Project

General

Profile

stat.diff

Igor Skornyakov, 04/08/2021 07:54 AM

Download (37.6 KB)

View differences:

src/com/goldencode/p2j/persist/ConnectionManager.java 2021-04-02 11:59:31 +0000
2 2
** Module   : ConnectionManager.java
3 3
** Abstract : Provides services for logical database connections and aliases
4 4
**
5
** Copyright (c) 2005-2019, Golden Code Development Corporation.
5
** Copyright (c) 2005-2021, Golden Code Development Corporation.
6 6
**
7 7
** -#- -I- --Date-- --JPRM-- ----------------------------Description-----------------------------
8 8
** 001 ECF 20051202   @23667 Created initial version. Provides services to
......
140 140
** 055 IAS 20200212          Rework CONNECT and DBPARAM
141 141
** 056 ECF 20200419          Removed Hibernate dependencies.
142 142
** 057 IAS 20200819          Added table CRUD ops statistics support
143
** 058 IAS 20210401          Fixed UserTableStatUpdater-related logic
143 144
*/
144 145

  
145 146
/*
......
205 206
import java.text.*;
206 207
import java.util.*;
207 208
import java.util.Map.*;
209
import java.util.concurrent.*;
208 210
import java.util.function.*;
209 211
import java.util.logging.*;
210 212
import java.util.stream.*;
......
382 384
      boolean inUse = MetadataManager.inUse(MetadataManager._CONNECT) ||
383 385
                      MetadataManager.inUse(MetadataManager._MYCONNECTION);
384 386
      metaListeners = inUse ? new HashMap<>() : null;
387
      if (MetadataManager.inUse(MetadataManager._USERTABLESTAT))
388
      {
389
         tableStatUpdaters = new ConcurrentHashMap<>();
390
      }
385 391
   
386 392
/* Temporary disable _UserTableStat support
387 393
      // determine whether we need to initialize a table statistics
......
2302 2308
   }
2303 2309
   
2304 2310
   /**
2311
    * Get <code>UserTableStatUpdater</code> object for the database
2312
    * @param id
2313
    *        database id
2314
    * @return <code>UserTableStatUpdater</code> object for the database
2315
    */
2316
   public static UserTableStatUpdater tableStatUpdater(String id)
2317
   {
2318
      return tableStatUpdaters == null ? null : tableStatUpdaters.get(id);
2319
   }
2320

  
2321
   /**
2305 2322
    * Initialize a metaschema database by initializing a connection listener and storing it for
2306 2323
    * later use.
2307 2324
    * <p>
src/com/goldencode/p2j/persist/PreselectQuery.java 2021-04-02 12:01:55 +0000
565 565
**                           _multiplex sort component matches the index direction.
566 566
**     OM  20201120          Adjusted error messages.
567 567
**     CA  20210310          A dynamic predicate must set the default lock to NONE, instead of SHARE.
568
**    IAS  29210401          Update _UserTableStat "read" counter
568 569
*/
569 570

  
570 571
/*
......
630 631
import com.goldencode.p2j.persist.dirty.*;
631 632
import com.goldencode.p2j.persist.event.*;
632 633
import com.goldencode.p2j.persist.lock.*;
634
import com.goldencode.p2j.persist.meta.*;
633 635
import com.goldencode.p2j.persist.orm.*;
634 636
import com.goldencode.p2j.util.*;
635 637
import com.goldencode.p2j.util.LogHelper;
......
5760 5762
                     try
5761 5763
                     {
5762 5764
                        dmo = p.load(buffer.getDMOImplementationClass(), id, lt, timeout, updateLock);
5763
                        
5765
                       
5764 5766
                        break;
5765 5767
                     }
5766 5768
                     catch (LockTimeoutException exc)
......
5813 5815
                  dmo = p.load(buffer.getDMOImplementationClass(), id, lt, 0L, updateLock);
5814 5816
               }
5815 5817
            }
5818
            if (dmo != null)
5819
            {
5820
               UserTableStatUpdater.retrieve(persistence.getDatabase(), buffer);
5821
            }
5816 5822
            
5817 5823
            if (LOG_FINE)
5818 5824
            {
src/com/goldencode/p2j/persist/RandomAccessQuery.java 2021-04-08 11:47:16 +0000
330 330
**     CA  20200924          Replaced Method.invoke with ReflectASM.
331 331
**     OM  20201120          Added javadoc note about a possible incorrect logged error.
332 332
**     CA  20210310          A dynamic predicate must set the default lock to NONE, instead of SHARE.
333
**    IAS  29210401          Update _UserTableStat "read" counter, flash it before access
334
**    IAS  29210402          Do not use <code>ffCache</code> for meta tables
333 335
*/
334 336

  
335 337
/*
......
395 397
import com.goldencode.p2j.persist.dirty.*;
396 398
import com.goldencode.p2j.persist.event.*;
397 399
import com.goldencode.p2j.persist.lock.*;
400
import com.goldencode.p2j.persist.meta.*;
401
import com.goldencode.p2j.persist.meta.MetadataManager.*;
398 402
import com.goldencode.p2j.persist.orm.*;
399 403
import com.goldencode.p2j.util.*;
400 404
import com.goldencode.p2j.util.LogHelper;
......
1262 1266
      buffer.initialize();
1263 1267
      
1264 1268
      DmoMeta dmoMeta = buffer.getDmoInfo();
1269
      if (dmoMeta.isVST(SystemTable._UserTableStat))
1270
      {
1271
         UserTableStatUpdater.persist(buffer.getDatabase().getId());
1272
      }
1265 1273
      int idxCount = dmoMeta.getIndexCount(true) + dmoMeta.getIndexCount(false);
1266 1274
      
1267 1275
      if (idxCount > 0)
......
1329 1337
      this.args = args;
1330 1338
      this.dfArgs = args;
1331 1339
      this.indexInfo = indexInfo;
1332
      if (index != 0)
1340
      if (!dmoMeta.isMeta() && index != 0)
1333 1341
      {
1334 1342
         this.ffCache = FastFindCache.getInstance(buffer.isTemporary());
1335 1343
      }
......
4003 4011
         ErrorManager.recordOrThrowError(exc);
4004 4012
      }
4005 4013
      
4014
      if (dmo != null)
4015
      {
4016
         UserTableStatUpdater.retrieve(buffer.getPersistence().getDatabase(), buffer);
4017
      }
4006 4018
      return dmo;
4007 4019
   }
4008 4020
   
......
4652 4664
            try
4653 4665
            {
4654 4666
               dmo = persistence.load(buffer.getDMOImplementationClass(), id, lockType, 0L, updateLock);
4667
               if (dmo != null)
4668
               {
4669
                  UserTableStatUpdater.retrieve(persistence.getDatabase(), buffer);
4670
               }
4655 4671
            }
4656 4672
            catch (MissingRecordException exc)
4657 4673
            {
src/com/goldencode/p2j/persist/dialect/H2Helper.java 2021-04-08 11:48:26 +0000
152 152
    *          Database name to be embedded in the connection URL.
153 153
    * @param   settings
154 154
    *          Object into which to store properties.
155
    * 
155
    * @param   avoidLogging 
156
    *          Flag indicating tables must be NO-UNDO
156 157
    * @return  The populated properties object (same object instance as {@code props}).
157 158
    */
158
   public static Settings setCommonInMemoryProperties(String database, Settings settings, boolean avoidLogging)
159
   public static Settings setCommonInMemoryProperties(String database, Settings settings, 
160
         boolean avoidLogging)
159 161
   {
160 162
      boolean inMem = "jdbc:h2:mem:".equals(JDBC_PREFIX);
161 163
      StringBuilder url = new StringBuilder();
src/com/goldencode/p2j/persist/meta/ConnectTableUpdater.java 2021-04-02 14:08:04 +0000
2 2
** Module   : ConnectTableUpdater.java
3 3
** Abstract : Manages metadata connect records for a particular, primary database
4 4
**
5
** Copyright (c) 2015-2020, Golden Code Development Corporation.
5
** Copyright (c) 2015-2021, Golden Code Development Corporation.
6 6
**
7 7
** -#- -I- --Date-- --------------------------------Description----------------------------------
8 8
** 001 ECF 20150111 Created initial version.
......
12 12
** 005 ECF 20200906 New ORM implementation.
13 13
** 006 IAS 20200819 Added support for additional _Connect table fields.
14 14
** 007 CA  20200924 Replaced Method.invoke with ReflectASM.
15
** 008 IAS 20210401 Do not update MyConnection on server startup.
15 16
*/
16 17

  
17 18
/*
......
221 222
    */
222 223
   public void databaseConnected(int64 connectID)
223 224
   {
224
      if (dmoMyconnClass == null || dmoConnectClass == null)
225
      if (dmoMyconnClass == null || dmoConnectClass == null || !Persistence.isActive())
225 226
      {
226 227
         return;
227 228
      }
src/com/goldencode/p2j/persist/meta/MetaTableWrapper.java 2021-04-02 12:07:49 +0000
2 2
** Module   : MetaTableWrapper.java
3 3
** Abstract : Wraps data for operations with meta table
4 4
**
5
** Copyright (c) 2013-2020, Golden Code Development Corporation.
5
** Copyright (c) 2013-2021, Golden Code Development Corporation.
6 6
**
7 7
** -#- -I- --Date-- --------------------------------Description----------------------------------
8 8
** 001 IAS 20200819 Created initial version.
9 9
** 002 CA  20200924 Replaced Method.invoke with ReflectASM.
10
**     IAS 29210401 Re-worked for new ORM
10 11
*/
11 12

  
12 13
/*
......
67 68
import java.lang.reflect.*;
68 69
import java.util.*;
69 70
import java.util.logging.*;
71

  
72
import com.goldencode.p2j.persist.*;
73
import com.goldencode.p2j.persist.meta.LockTableUpdater.*;
74
import com.goldencode.p2j.persist.meta.UserTableStatUpdater.*;
70 75
import com.goldencode.p2j.persist.orm.*;
71 76
import com.goldencode.p2j.util.*;
72 77
import com.goldencode.proxy.*;
......
81 86
   private static final Logger LOG = LogHelper.getLogger(MetaTableWrapper.class);
82 87

  
83 88
   /** DMO class */
84
   private final Class<?> dmoClass;
89
   private final Class<? extends Record> dmoClass;
85 90

  
86 91
   /** DMO methods map by name */
87 92
   private final Map<Method, Method> methodMap = new HashMap<>();
88 93

  
89
   /** Name of the DMO Impl class */
90
   private final String dmoEntity;
91

  
92 94
   /** DMO Impl object */
93 95
   private Object dmoImpl;
94 96
   
95 97
   /** Meta table DMO proxy */
96 98
   private final T metaTableProxy;
97 99
   
100
   /** Dummy empty class to be used as the super class for proxy. */
101
   public static class Empty {}
102

  
98 103
   /** DMO operations <code>InvocationHandler</code> */  
99 104
   private final InvocationHandler handler = new InvocationHandler() 
100 105
   {
......
125 130
    * 
126 131
    * @param facet
127 132
    *        DMO interface class
128
    * @param implName
133
    * @param ifName
129 134
    *        DMO interface class simple name 
130 135
    */
131
   public MetaTableWrapper(Class<T> facet, String implName)
136
   public MetaTableWrapper(Class<T> facet, String ifName)
132 137
   {
133
      this.dmoEntity = String.format("%s._meta.impl." + implName, DmoMetadataManager.getDmoBasePackage());
138
      String dmoName = String.format("%s._meta.%s", 
139
            DmoMetadataManager.getDmoBasePackage(), ifName);
140
      Class<? extends Record> implementingClass = null;
134 141
      try
135 142
      {
136
         this.dmoClass = Class.forName(dmoEntity);
137
         for (Method m : facet.getMethods())
143
         DmoMeta dmoInfo = DmoMetadataManager.getDmoInfo(Class.forName(dmoName));
144
         implementingClass = dmoInfo.getImplementationClass();
145
         this.metaTableProxy = ProxyFactory.getProxy(Empty.class, 
146
               new Class<?>[]{facet}, handler);
147
         for (Method ifcMeth : MinimalUsertablestat.class.getMethods())
138 148
         {
139
            Method dmoMethod = dmoClass.getMethod(m.getName(), m.getParameterTypes());
140
            methodMap.put(m, dmoMethod);
149
            Method dmoMeth = implementingClass.getMethod(ifcMeth.getName(), ifcMeth.getParameterTypes());
150
            methodMap.put(ifcMeth, dmoMeth);
141 151
         }
142
         this.metaTableProxy = ProxyFactory.getProxy(dmoClass, new Class<?>[]{facet}, handler);
143 152
      } 
144
      catch (ClassNotFoundException | NoSuchMethodException e)
153
      catch (ClassNotFoundException | IllegalArgumentException | NoSuchMethodException e)
145 154
      {
146
         throw new RuntimeException("Error preparing MetaLock implementation class", e);
155
         throw new RuntimeException("Error preparing MetaUsertablestat implementation class", e);
147 156
      }
148

  
157
      this.dmoClass = implementingClass;
149 158
   }
150 159

  
151 160
   /**
......
153 162
    * 
154 163
    * @return DMO interface class
155 164
    */
156
   public Class<?> getDmoClass()
165
   public Class<? extends Record> getDmoClass()
157 166
   {
158 167
      return dmoClass;
159 168
   }
......
168 177
   }
169 178

  
170 179
   /**
171
    * Get name of the DMO Impl class 
172
    * @return name of the DMO Impl class
173
    */
174
   public String getDmoEntity()
175
   {
176
      return dmoEntity;
177
   }
178
   
179
   /**
180 180
    * Get meta table DMO proxy 
181 181
    * @return meta table DMO proxy
182 182
    */
src/com/goldencode/p2j/persist/meta/UserTableStatUpdater.java 2021-04-08 10:24:53 +0000
1
/*
2
** Module   : UserTableStatUpdater.java
3
** Abstract : Manages _UserTableStat VST
4
**
5
** Copyright (c) 2020-2021, Golden Code Development Corporation.
6
**
7
** -#- -I- --Date-- --------------------------------Description----------------------------------
8
** 001 IAS 20200819 Created initial version.
9
** 002 IAS 20210401 Fixed bugs and added new helper methods
10
*/
11

  
12
/*
13
** This program is free software: you can redistribute it and/or modify
14
** it under the terms of the GNU Affero General Public License as
15
** published by the Free Software Foundation, either version 3 of the
16
** License, or (at your option) any later version.
17
**
18
** This program is distributed in the hope that it will be useful,
19
** but WITHOUT ANY WARRANTY; without even the implied warranty of
20
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
** GNU Affero General Public License for more details.
22
**
23
** You may find a copy of the GNU Affero GPL version 3 at the following
24
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
25
** 
26
** Additional terms under GNU Affero GPL version 3 section 7:
27
** 
28
**   Under Section 7 of the GNU Affero GPL version 3, the following additional
29
**   terms apply to the works covered under the License.  These additional terms
30
**   are non-permissive additional terms allowed under Section 7 of the GNU
31
**   Affero GPL version 3 and may not be removed by you.
32
** 
33
**   0. Attribution Requirement.
34
** 
35
**     You must preserve all legal notices or author attributions in the covered
36
**     work or Appropriate Legal Notices displayed by works containing the covered
37
**     work.  You may not remove from the covered work any author or developer
38
**     credit already included within the covered work.
39
** 
40
**   1. No License To Use Trademarks.
41
** 
42
**     This license does not grant any license or rights to use the trademarks
43
**     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
44
**     of Golden Code Development Corporation. You are not authorized to use the
45
**     name Golden Code, FWD, or the names of any author or contributor, for
46
**     publicity purposes without written authorization.
47
** 
48
**   2. No Misrepresentation of Affiliation.
49
** 
50
**     You may not represent yourself as Golden Code Development Corporation or FWD.
51
** 
52
**     You may not represent yourself for publicity purposes as associated with
53
**     Golden Code Development Corporation, FWD, or any author or contributor to
54
**     the covered work, without written authorization.
55
** 
56
**   3. No Misrepresentation of Source or Origin.
57
** 
58
**     You may not represent the covered work as solely your work.  All modified
59
**     versions of the covered work must be marked in a reasonable way to make it
60
**     clear that the modified work is not originating from Golden Code Development
61
**     Corporation or FWD.  All modified versions must contain the notices of
62
**     attribution required in this license.
63
*/
64

  
1 65
package com.goldencode.p2j.persist.meta;
2 66

  
3 67
import java.util.*;
......
5 69
import java.util.concurrent.atomic.*;
6 70
import java.util.logging.*;
7 71

  
72
import org.apache.commons.lang3.*;
73

  
8 74
import com.goldencode.p2j.persist.*;
9 75
import com.goldencode.p2j.persist.lock.*;
10 76
import com.goldencode.p2j.persist.meta.TableStats.*;
77
import com.goldencode.p2j.persist.orm.*;
78
import com.goldencode.p2j.security.SecurityManager;
11 79
import com.goldencode.p2j.util.*;
12 80

  
13 81
/**
14
 * Maintains the CRUD operations' statistics in the <code>_usertablestat</code> VST
82
 * Maintains the CRUD operations' statistics in the <code>_usertablestat</code>
83
 * VST
15 84
 */
16 85
public class UserTableStatUpdater
17 86
{
......
26 95

  
27 96
   /** MetaUsertablestatImpl DMO wrapper */
28 97
   private final MetaTableWrapper<MinimalUsertablestat> usertablestatWrapper = new MetaTableWrapper<>(
29
         MinimalUsertablestat.class, "MetaUsertablestatImpl");
98
         MinimalUsertablestat.class, "MetaUsertablestat");
30 99

  
31 100
   /** MetaUsertablestatImpl DMO proxy */
32 101
   private final MinimalUsertablestat usertablestat = usertablestatWrapper.getMetaTableProxy();
33 102

  
34
   /** Session Id holder */
35
   private final SessionIdHolder sessionIdHolder = new SessionIdHolder();
36

  
37 103
   /** meta database */
38 104
   private final Database metaDatabase;
39
   
40
   /** meta database Persistence */ 
105

  
106
   /** meta database Persistence */
41 107
   private final Persistence persistence;
42 108

  
109
   /** Security manager */
110
   private final SecurityManager securityManager;
111

  
43 112
   /** Tables' CRUD operations statistics per connection */
44
   private final ConcurrentMap<integer, ConcurrentMap<integer, TableStats>> tableStats = 
45
         new ConcurrentSkipListMap<>();
113
   private final ConcurrentMap<integer, ConcurrentMap<integer, TableStats>> tableStats = new ConcurrentSkipListMap<>();
46 114

  
47
   /**  Statistics statistics version */
115
   /** Statistics statistics version */
48 116
   private final AtomicLong databaseVersion = new AtomicLong(-1);
49 117

  
50 118
   /** In-memory statistics version */
......
54 122
   private final AtomicLong nextPrimaryKey = new AtomicLong(1);
55 123

  
56 124
   /**
125
    * Persist statistics in the meta database
126
    * 
127
    * @param dbId database id
128
    */
129
   public static void persist(String dbId)
130
   {
131
      UserTableStatUpdater userTableStatUpdater = ConnectionManager.tableStatUpdater(dbId);
132
      if (userTableStatUpdater != null)
133
      {
134
         try
135
         {
136
            userTableStatUpdater.persist();
137
         } catch (PersistenceException e)
138
         {
139
            LOG.log(Level.WARNING, "Failed to flush _UserTableStat", e);
140
         }
141
      }
142
   }
143

  
144
   /**
145
    * Register retrieve operation
146
    * @param db 
147
    *        database
148
    * @param buffer 
149
    *        target buffer
150
    */
151
   public static void retrieve(Database db, RecordBuffer buffer)
152
   {
153
      DmoMeta dmoMeta = buffer.getDmoInfo();
154
      if (dmoMeta.isMeta())
155
      {
156
         return;
157
      }
158
      Class<? extends Record> dmoClass = dmoMeta.getImplementationClass();
159
      integer filenum = MetadataManager.getFileNum(db, dmoClass);
160
      UserTableStatUpdater userTableStatUpdater = 
161
            ConnectionManager.tableStatUpdater(db.getId());
162
      if (userTableStatUpdater != null)
163
      {
164
         TableStats tableStats = userTableStatUpdater.getTableStats(
165
               new integer(userTableStatUpdater.getSecurityManager().getSessionId()), 
166
               filenum);
167
         if (tableStats != null)
168
         {
169
            tableStats.retrieve();
170
         }
171
      }
172

  
173
   }
174

  
175
   /**
176
    * Get the SecurityManager instance
177
    * @return SecurityManager instance
178
    */
179
   public SecurityManager getSecurityManager()
180
   {
181
      return securityManager;
182
   }
183

  
184
   /**
57 185
    * Constructor
58 186
    * 
59
    * @param metaDatabase
60
    *        meta database
187
    * @param metaDatabase meta database
61 188
    */
62 189
   public UserTableStatUpdater(Database metaDatabase)
63 190
   {
64 191
      this.metaDatabase = metaDatabase;
65 192
      this.persistence = PersistenceFactory.getInstance(metaDatabase);
193
      this.securityManager = SecurityManager.getInstance();
66 194
   }
67 195

  
68 196
   /**
69 197
    * Get table statistics holder for a give connection and table
70 198
    * 
71
    * @param connectId
72
    *        connection id
73
    * @param tableNo
74
    *        table number
199
    * @param connectId connection id
200
    * @param tableNo   table number
75 201
    * @return table statistics holder
76 202
    */
77 203
   public TableStats getTableStats(integer connectId, integer tableNo)
78 204
   {
79
      return tableStats.computeIfAbsent(connectId, k -> new ConcurrentSkipListMap<>()).
80
                        computeIfAbsent(tableNo, k -> new TableStats(statisticsVersion));
205
      return tableStats.computeIfAbsent(connectId, 
206
            k -> new ConcurrentSkipListMap<>()).computeIfAbsent(tableNo,
207
                                       k -> new TableStats(statisticsVersion));
81 208
   }
82
   
83
   /** 
209

  
210
   /**
84 211
    * Persist statistics in the meta database
85 212
    * 
86 213
    * @return <code>true</code> if success
87
    * @throws PersistenceException 
214
    * @throws PersistenceException
88 215
    */
89
   public boolean persist() 
90
   throws PersistenceException
216
   public boolean persist() throws PersistenceException
91 217
   {
92
      long statVersion = statisticsVersion.get(); 
93
      if (statVersion <= databaseVersion.get()) 
218
      long statVersion = statisticsVersion.get();
219
      if (statVersion <= databaseVersion.get())
94 220
      {
95 221
         return true;
96 222
      }
97
      try {
223
      try
224
      {
98 225
         boolean commit = persistence.beginTransaction();
99 226
         Map<integer, Map<integer, Long>> updates = new HashMap<>();
100 227
         new Worker().run(updates);
......
105 232
         }
106 233
         databaseVersion.set(statVersion);
107 234
         // update "persisted" value
108
         for (Map.Entry<integer, Map<integer, Long>> ce: updates.entrySet())
235
         for (Map.Entry<integer, Map<integer, Long>> ce : updates.entrySet())
109 236
         {
110 237
            ConcurrentMap<integer, TableStats> cs = tableStats.get(ce.getKey());
111 238
            if (ce == null)
112 239
            {
113 240
               continue;
114 241
            }
115
            for (Map.Entry<integer, Long> te: ce.getValue().entrySet())
242
            for (Map.Entry<integer, Long> te : ce.getValue().entrySet())
116 243
            {
117 244
               TableStats ts = cs.get(te.getKey());
118 245
               if (ts != null)
......
122 249
            }
123 250
         }
124 251
         return true;
125
     } 
126
     catch (PersistenceException e) {
252
      } catch (PersistenceException e)
253
      {
127 254
         persistence.rollback();
128 255
         return false;
129
     }
256
      }
130 257
   }
131
   
258

  
132 259
   /**
133 260
    * Drop data for the closed connection
134
    *  
135
    * @param connectId
136
    *        connection id
261
    * 
262
    * @param connectId connection id
137 263
    */
138 264
   public void disconnected(int64 connectId)
139 265
   {
......
142 268
      try
143 269
      {
144 270
         commit = persistence.beginTransaction();
145
         persistence.getSingleSQLResult(
146
               "DELETE FROM " + USERTABLESTAT_TABLE + " WHERE usertablestat_conn = ?1", 
147
               new Object[] {connectId.intValue()}
148
         );
271
         persistence.executeSQL("DELETE FROM " + USERTABLESTAT_TABLE + " WHERE usertablestat_conn = ?1",
272
               new Object[]
273
               { connectId.intValue() });
149 274
         persistence.flush();
150
         
275

  
151 276
         if (commit)
152 277
         {
153 278
            commit = false;
154 279
            persistence.commit();
155 280
         }
156
         
157
      }
158
      catch(Exception e)
281

  
282
      } catch (Exception e)
159 283
      {
160
         LOG.log(Level.WARNING, "Failed to cleanup statistics for the closed connection: " + 
161
                  connectId.intValue(), e);
284
         LOG.log(Level.WARNING, "Failed to cleanup statistics for the closed connection: " + connectId.intValue(), e);
162 285
         try
163 286
         {
164 287
            if (commit)
165 288
            {
166 289
               persistence.rollback();
167 290
            }
168
         }
169
         catch (PersistenceException pe)
291
         } catch (PersistenceException pe)
170 292
         {
171 293
            LOG.log(Level.WARNING, "Failed to rollback transaction", e);
172 294
         }
173 295
      }
174 296
   }
175
   
297

  
176 298
   /**
177
    * Implements incremental update of the _UserTableStat table  
299
    * Implements incremental update of the _UserTableStat table
178 300
    */
179 301
   private class Worker
180 302
   {
181 303
      /**
182 304
       * Perform incremental database update
183 305
       * 
184
       * @param updates
185
       *        version of the updated/inserted records
306
       * @param updates version of the updated/inserted records
186 307
       * @throws PersistenceException
187 308
       */
188
      public void run(Map<integer, Map<integer, Long>> updates) 
189
      throws PersistenceException
309
      public void run(Map<integer, Map<integer, Long>> updates) throws PersistenceException
190 310
      {
191
         for (Map.Entry<integer, ConcurrentMap<integer, TableStats>> ce: tableStats.entrySet())
311
         for (Map.Entry<integer, ConcurrentMap<integer, TableStats>> ce : tableStats.entrySet())
192 312
         {
193
            for (Map.Entry<integer, TableStats> te: ce.getValue().entrySet())
313
            integer connId = ce.getKey();
314
            for (Map.Entry<integer, TableStats> te : ce.getValue().entrySet())
194 315
            {
195 316
               Snapshot data = te.getValue().getStat();
196 317
               if (data.version <= data.persisted)
197 318
               {
198 319
                  continue;
199 320
               }
321
               integer tblId = te.getKey();
200 322
               Record dmo = data.persisted < 0 ? 
201
                     createRecord(ce.getKey(), te.getKey(), data) :
202
                     updateRecord(ce.getKey(), te.getKey(), data);
203
                     updates.computeIfAbsent(ce.getKey(), k -> new HashMap<>()).
204
                              put(te.getKey(), data.version);
323
                       createRecord(connId, tblId, data):
324
                       updateRecord(connId, tblId, data);
325
               updates.computeIfAbsent(connId, k -> new HashMap<>()).put(tblId, data.version);
205 326
               persistence.save(dmo, dmo.primaryKey());
206 327
            }
207 328
         }
......
209 330

  
210 331
      /**
211 332
       * Update _usertablestat record
212
       * @param connId
213
       *        connection id
214
       * @param tblId
215
       *        table id
216
       * @param data
217
       *        data snapshot
218
       * @return
219
       *        updated Record object 
333
       * 
334
       * @param connId connection id
335
       * @param tblId  table id
336
       * @param data   data snapshot
337
       * @return updated Record object
220 338
       * @throws PersistenceException
221 339
       */
222
      private Record updateRecord(integer connId, integer tblId, Snapshot data)
223
      throws PersistenceException
340
      private Record updateRecord(integer connId, integer tblId, Snapshot data) throws PersistenceException
224 341
      {
225
         Long id = (Long)persistence.getSingleSQLResult(
226
               "SELECT ID FROM " + USERTABLESTAT_TABLE + " WHERE " + 
227
                     "USERTABLESTAT_CONN = ?1 AND USERTABLESTAT_NUM = ?2",
228
                new Object[] {connId.longValue(), tblId.longValue()});
342
         Long id = (Long) persistence.getSingleSQLResult("SELECT ID FROM " + USERTABLESTAT_TABLE + " WHERE "
343
               + "USERTABLESTAT_CONN = ?1 AND USERTABLESTAT_NUM = ?2", new Object[]
344
         { connId.longValue(), tblId.longValue() });
229 345
         Record dmo = null;
230
         
346

  
231 347
         if (id != null)
232 348
         {
233
            RecordIdentifier<String> metaIdent =
234
               new RecordIdentifier<>(usertablestatWrapper.getDmoEntity(), id);
349
            RecordIdentifier<String> metaIdent = new RecordIdentifier<>(usertablestatWrapper.getDmoClass().getName(),
350
                  id);
235 351
            dmo = persistence.quickLoad(metaIdent);
236 352
         }
237 353
         if (dmo == null)
238 354
         {
239
            throw new PersistenceException(
240
                  String.format("No lock record found for connId = %s, tblId = %s",
241
                                connId.longValue(), tblId.longValue()
242
                  )
243
            );
355
            throw new PersistenceException(String.format("No lock record found for connId = %s, tblId = %s",
356
                  connId.longValue(), tblId.longValue()));
244 357
         }
245 358
         usertablestatWrapper.setDelegate(dmo);
246 359
         MinimalUsertablestat proxy = usertablestatWrapper.getMetaTableProxy();
......
250 363

  
251 364
      /**
252 365
       * Created _usertablestat record
253
       * @param connId
254
       *        connection id
255
       * @param tblId
256
       *        table id
257
       * @param data
258
       *        data snapshot
259
       * @return
260
       *        created new Record object 
366
       * 
367
       * @param connId connection id
368
       * @param tblId  table id
369
       * @param data   data snapshot
370
       * @return created new Record object
261 371
       * @throws PersistenceException
262 372
       */
263
      private Record createRecord(integer connId, integer tblId, Snapshot data)
264
      throws PersistenceException
373
      private Record createRecord(integer connId, integer tblId, Snapshot data) throws PersistenceException
265 374
      {
266 375
         Record dmo = null;
267
         try 
376
         try
268 377
         {
269
            dmo = (Record) usertablestatWrapper.getDmoClass().newInstance();
378
            dmo = usertablestatWrapper.getDmoClass().newInstance();
379
            dmo.initialize(null, true);
270 380
            long id = nextPrimaryKey.getAndIncrement();
271 381
            dmo.primaryKey(id);
272 382
            usertablestatWrapper.setDelegate(dmo);
......
275 385
            proxy.setUsertablestatConn(connId);
276 386
            proxy.setUsertablestatNum(tblId);
277 387
            populateStat(data, proxy);
278
         }
279
         catch (InstantiationException | IllegalAccessException e)
388
         } catch (InstantiationException | IllegalAccessException e)
280 389
         {
281 390
            throw new PersistenceException("Error creating meta usertablestat record", e);
282 391
         }
283 392
         return dmo;
284
     }
393
      }
285 394

  
286 395
      private void populateStat(Snapshot data, MinimalUsertablestat proxy)
287 396
      {
......
290 399
         proxy.setUsertablestatUpdate(new integer(data.update));
291 400
         proxy.setUsertablestatDelete(new integer(data.delete));
292 401
      }
293
      
402

  
294 403
   }
404

  
295 405
   /**
296 406
    * Interface which defines the minimally required methods of the
297 407
    * <code>MinimalUsertablestat</code> interface. This interface defines the proxy
......
305 415
      /**
306 416
       * Getter: UserTableStat-Id
307 417
       * 
308
       * @return  UserTableStat-Id
418
       * @return UserTableStat-Id
309 419
       */
310 420
      public int64 getUsertablestatId();
311 421

  
312 422
      /**
313 423
       * Setter: UserTableStat-Id
314 424
       * 
315
       * @param   usertablestatId
316
       *          UserTableStat-Id
425
       * @param usertablestatId UserTableStat-Id
317 426
       */
318 427
      public void setUsertablestatId(NumberType usertablestatId);
319 428

  
320 429
      /**
321 430
       * Getter: Connection
322 431
       * 
323
       * @return  Connection
432
       * @return Connection
324 433
       */
325 434
      public integer getUsertablestatConn();
326 435

  
327 436
      /**
328 437
       * Setter: Connection
329 438
       * 
330
       * @param   usertablestatConn
331
       *          Connection
439
       * @param usertablestatConn Connection
332 440
       */
333 441
      public void setUsertablestatConn(NumberType usertablestatConn);
334 442

  
335 443
      /**
336 444
       * Getter: Table #
337 445
       * 
338
       * @return  Table #
446
       * @return Table #
339 447
       */
340 448
      public integer getUsertablestatNum();
341 449

  
342 450
      /**
343 451
       * Setter: Table #
344 452
       * 
345
       * @param   usertablestatNum
346
       *          Table #
453
       * @param usertablestatNum Table #
347 454
       */
348 455
      public void setUsertablestatNum(NumberType usertablestatNum);
349 456

  
350 457
      /**
351 458
       * Getter: read
352 459
       * 
353
       * @return  read
460
       * @return read
354 461
       */
355 462
      public int64 getUsertablestatRead();
356 463

  
357 464
      /**
358 465
       * Setter: read
359 466
       * 
360
       * @param   usertablestatRead
361
       *          read
467
       * @param usertablestatRead read
362 468
       */
363 469
      public void setUsertablestatRead(NumberType usertablestatRead);
364 470

  
365 471
      /**
366 472
       * Getter: update
367 473
       * 
368
       * @return  update
474
       * @return update
369 475
       */
370 476
      public int64 getUsertablestatUpdate();
371 477

  
372 478
      /**
373 479
       * Setter: update
374 480
       * 
375
       * @param   usertablestatUpdate
376
       *          update
481
       * @param usertablestatUpdate update
377 482
       */
378 483
      public void setUsertablestatUpdate(NumberType usertablestatUpdate);
379 484

  
380 485
      /**
381 486
       * Getter: create
382 487
       * 
383
       * @return  create
488
       * @return create
384 489
       */
385 490
      public int64 getUsertablestatCreate();
386 491

  
387 492
      /**
388 493
       * Setter: create
389 494
       * 
390
       * @param   usertablestatCreate
391
       *          create
495
       * @param usertablestatCreate create
392 496
       */
393 497
      public void setUsertablestatCreate(NumberType usertablestatCreate);
394 498

  
395 499
      /**
396 500
       * Getter: delete
397 501
       * 
398
       * @return  delete
502
       * @return delete
399 503
       */
400 504
      public int64 getUsertablestatDelete();
401 505

  
402 506
      /**
403 507
       * Setter: delete
404 508
       * 
405
       * @param   usertablestatDelete
406
       *          delete
509
       * @param usertablestatDelete delete
407 510
       */
408 511
      public void setUsertablestatDelete(NumberType usertablestatDelete);
409 512

  
410 513
      /**
411 514
       * Getter: Partition Id
412 515
       * 
413
       * @return  Partition Id
516
       * @return Partition Id
414 517
       */
415 518
      public integer getUsertablestatPartitionid();
416 519

  
417 520
      /**
418 521
       * Setter: Partition Id
419 522
       * 
420
       * @param   usertablestatPartitionid
421
       *          Partition Id
523
       * @param usertablestatPartitionid Partition Id
422 524
       */
423 525
      public void setUsertablestatPartitionid(NumberType usertablestatPartitionid);
424 526

  
425 527
      /**
426 528
       * Getter: Tenant Id
427 529
       * 
428
       * @return  Tenant Id
530
       * @return Tenant Id
429 531
       */
430 532
      public integer getUsertablestatTenantid();
431 533

  
432 534
      /**
433 535
       * Setter: Tenant Id
434 536
       * 
435
       * @param   usertablestatTenantid
436
       *          Tenant Id
537
       * @param usertablestatTenantid Tenant Id
437 538
       */
438 539
      public void setUsertablestatTenantid(NumberType usertablestatTenantid);
439 540
   }
src/com/goldencode/p2j/persist/orm/DmoMeta.java 2021-04-08 10:42:19 +0000
23 23
**     OM  20201202 Added getPrimaryIndex() method.
24 24
**     IAS 20201210 Added support for word tables.
25 25
**     IAS 20210219 Word tables support for custom extents
26
**     IAS 29210401 Added 'isVST' and 'isMeta' methods
26 27
*/
27 28

  
28 29
/*
......
85 86
import com.goldencode.p2j.persist.annotation.*;
86 87
import com.goldencode.p2j.persist.annotation.Table;
87 88
import com.goldencode.p2j.persist.dirty.*;
89
import com.goldencode.p2j.persist.meta.MetadataManager.*;
88 90
import com.goldencode.p2j.util.*;
89 91
import com.google.common.collect.*;
92

  
93
import org.apache.commons.lang3.*;
90 94
import org.apache.commons.lang3.tuple.*;
91 95
import java.lang.reflect.*;
92 96
import java.util.*;
......
1395 1399
      }
1396 1400
      return sb.toString();
1397 1401
   }
1402
   
1403
   /**
1404
    * Check if DMO corresponds to a meta table.
1405
    * @return <code>true</code> if DMO corresponds to a meta table..
1406
    */
1407
   public boolean isMeta()
1408
   {
1409
      return !StringUtils.isEmpty(category);
1410
     
1411
   }
1412

  
1413
   /**
1414
    * Check if DMO corresponds to a specified VST.
1415
    * @param systemTable
1416
    *        VST to be checked
1417
    * @return <code>true</code> if DMO corresponds to a specified VST.
1418
    */
1419
   public boolean isVST(SystemTable systemTable)
1420
   {
1421
      return Category.VST.name().equals(category) && 
1422
            systemTable._file_name.equalsIgnoreCase(legacyTable);
1423
   }
1398 1424
   /**
1399 1425
    * Word index data. 
1400 1426
    */
src/com/goldencode/p2j/persist/orm/FqlToSqlConverter.java 2021-04-02 12:04:59 +0000
19 19
**     IAS 20210315 Use Database instead of schema in constructor, re-work implicit ordering
20 20
**     IAS 20210321 Re-worked implicit ordering for word tables. Added implicit sorting for
21 21
**                  _temp and 'dirty' databases.
22
**    IAS  29210401 Flash _UserTableStat before access
22 23
*/
23 24

  
24 25
/*
......
95 96
import com.goldencode.p2j.persist.orm.Query.*;
96 97
import com.goldencode.p2j.uast.*;
97 98
import com.goldencode.p2j.persist.meta.*;
99
import com.goldencode.p2j.persist.meta.MetadataManager.*;
98 100
import com.goldencode.p2j.util.*;
99 101
import com.goldencode.p2j.util.ErrorManager;
100 102
import com.goldencode.p2j.util.LogicalExpressionConverter.*;
......
2842 2844
            DmoMeta dmoInfo = DmoMetadataManager.getDmoInfo(dmoName, schema);
2843 2845
            if (dmoInfo != null)
2844 2846
            {
2847
               if (dmoInfo.isVST(SystemTable._UserTableStat))
2848
               {
2849
                  UserTableStatUpdater.persist(db.getId());
2850
               }
2845 2851
               if (alias == null || alias.getType() == ALIAS)
2846 2852
               {
2847 2853
                  String aliasName;
src/com/goldencode/p2j/persist/pl/Functions.java 2021-04-08 11:45:22 +0000
3 3
** Abstract : Dispatcher methods for Java language, server-side database
4 4
**            functions which replace Progress built-in functions
5 5
**
6
** Copyright (c) 2004-2020, Golden Code Development Corporation.
6
** Copyright (c) 2004-2021, Golden Code Development Corporation.
7 7
**
8 8
** -#- -I- --Date-- --JPRM-- ----------------------------Description-----------------------------
9 9
** 001 ECF 20060811   @28584 Created initial version. Backing methods for
......
92 92
** 040 ECF 20200504          Added missing alias for entryIn(Long, String).
93 93
** 041 OM  20200212          Unknown value fixes.
94 94
** 042 IAS 20201121          Added 'words' functions.
95
** 043 IAS 20210407          Added 'fwdSession' function.
95 96
*/
96 97

  
97 98
/*
......
152 153
import java.math.*;
153 154
import java.sql.*;
154 155
import com.goldencode.p2j.*;
156
import com.goldencode.p2j.net.*;
157
import com.goldencode.p2j.security.SecurityManager;
155 158
import com.goldencode.p2j.util.*;
156 159

  
157 160
/**
......
3577 3580
   }
3578 3581

  
3579 3582
   /**
3583
    * Helper function to return the FWD Session Id.
3584
    *
3585
    * @return  FWD Session Id.
3586
    */
3587
   @HQLFunction
3588
   public static int fwdSession()
3589
   {
3590
      return SecurityManager.getInstance().getSessionId().intValue();
3591
   }
3592
   /**
3580 3593
    * Rewraps an Integer value into a Long.
3581 3594
    * 
3582 3595
    * @param   i