Project

General

Profile

change_broker_lazy_update.patch

Alexandru Lungu, 03/09/2023 07:44 AM

Download (13.4 KB)

View differences:

src/com/goldencode/p2j/persist/AdaptiveQuery.java 2023-03-09 12:31:10 +0000
349 349
**                           set is created, ProgressiveResults can no longer be the type returned.
350 350
**     RAA 20230221          If the query will be executed lazy, then it is no longer registered as a 
351 351
**                           listener.
352
**     RAA 20230302          Added a condition that checks if the buffer is active before seeing if the query
353
**                           supports lazy mode. This is part of the registration as a listener process.
352 354
*/
353 355

  
354 356
/*
......
531 533
   /** Determines if this will be unregistered from ChangeBroker on cleanup. */
532 534
   private boolean unregisterOnCleanup = false;
533 535
   
536
   /** Flag to check the ability to fetch the records in a lazy manner, without server-side invalidation */
537
   private Boolean lazyMode = null;
538
   
534 539
   /**
535 540
    * Default constructor. Initialization is deferred until <code>initialize()</code> is
536 541
    * called.
......
559 564
      
560 565
      adapter = new ResultsAdapter(new ResultsSource());
561 566
      
562
      ChangeBroker.get().addListener(this);
567
      registerRecordChangeListeners(null);
563 568
      
564 569
      TransactionManager.registerOffEndQuery(this);
565 570
      
......
592 597
      
593 598
      adapter = new ResultsAdapter(new ResultsSource());
594 599
      
595
      ChangeBroker.get().addListener(this);
600
      registerRecordChangeListeners(null);
596 601
      
597 602
      TransactionManager.registerOffEndQuery(this);
598 603
      
......
665 670
         addWhereExpression(whereExpr);
666 671
      }
667 672
      
668
      ChangeBroker.get().addListener(this);
669
//      buffer persistence may not be active yet - what do we do? what about scrolling?
670
//      if (buffer == null || !buffer.getPersistence().supportsLazyQueryResultsMode())
671
//      {
672
//         ChangeBroker.get().addListener(this);
673
//      }
673
      registerRecordChangeListeners(null);
674 674
      
675 675
      return this;
676 676
   }
......
1110 1110
   {
1111 1111
      closed = false;
1112 1112
      
1113
      int scope = BufferManager.get().findNearestExternal();
1114
      RecordBuffer[] buffers = getRecordBuffers();
1115
      
1116
      for (RecordBuffer buffer : buffers)
1117
      {
1118
         scope = ((scope == -1)
1119
                  ? buffer.getScopeOpenDepth()
1120
                  : Math.min(scope, buffer.getScopeOpenDepth()));
1121
      }
1122
      
1123
      if (scope != -1)
1124
      {
1125
         registerRecordChangeListeners(scope);
1113
      // rule out the scope computation and registering if this is a lazy query anyway
1114
      // lazy queries don't require server-side invalidation as it supports it at the database level
1115
      if (shouldRegisterRecordChangeListeners())
1116
      {
1117
         int scope = BufferManager.get().findNearestExternal();
1118
         RecordBuffer[] buffers = getRecordBuffers();
1119
         
1120
         for (RecordBuffer buffer : buffers)
1121
         {
1122
            scope = ((scope == -1)
1123
                     ? buffer.getScopeOpenDepth()
1124
                     : Math.min(scope, buffer.getScopeOpenDepth()));
1125
         }
1126
         
1127
         if (scope != -1)
1128
         {
1129
            registerRecordChangeListeners(Integer.valueOf(scope));
1130
         }
1126 1131
      }
1127 1132

  
1128 1133
      if (cursor != null)
......
1137 1142
   }
1138 1143
   
1139 1144
   /**
1145
    * Check if this type of query should register record change listeners. Use this 
1146
    * to avoid computing any scope for registration and end up with a no registration
1147
    * behavior. 
1148
    * 
1149
    * @return   {@code true} if we should invest time into computing the scope in order
1150
    *           to call {@link #registerRecordChangeListeners} or {@code false} if we
1151
    *           can skip doing any work to honor {@link #registerRecordChangeListeners}.
1152
    */
1153
   @Override
1154
   public boolean shouldRegisterRecordChangeListeners()
1155
   {
1156
      return !isLazyMode();
1157
   }
1158
   
1159
   /**
1140 1160
    * Register all <code>RecordChangeListener</code>s associated with this
1141 1161
    * query (if any), with the context-local <code>ChangeBroker</code> at the
1142 1162
    * indicated scope.
1143 1163
    * 
1144 1164
    * @param   scope
1145 1165
    *          Scope at which listeners should be registered with the change
1146
    *          broker.
1166
    *          broker. {@code null} means register at the closest scope.
1147 1167
    */
1148
   public void registerRecordChangeListeners(int scope)
1168
   @Override
1169
   public void registerRecordChangeListeners(Integer scope)
1149 1170
   {
1171
      // Queries over temporary tables have their invalidation dealt with by the
1172
      // lazy mechanism, so there is no need to register them as listeners.
1173
      if (isLazyMode())
1174
      {
1175
         return;
1176
      }
1177
      
1178
      if (scope == null)
1179
      {
1180
         ChangeBroker.get().addListener(this);
1181
         return;
1182
      }
1183
      
1150 1184
      ChangeBroker.get().addListener(this, scope);
1151 1185
      
1152 1186
      // if these were added as global listeners in ChangeBroker remember to remove them
......
2237 2271
   throws PersistenceException
2238 2272
   {      
2239 2273
      ArrayList<QueryComponent> components = components();
2240
      // rather check persistence if supports this
2241
      if (components.size() == 1 && components.get(0).getBuffer().isTemporary() && !isScrolling())
2242
      {
2243
         return;
2244
      }
2274

  
2245 2275
      boolean preselect = isPreselect();
2246 2276
      boolean invalidate = true;
2247 2277
      boolean cacheAll = false;
......
3005 3035
   throws PersistenceException
3006 3036
   {
3007 3037
      Results results = null;
3008
      boolean lazyMode = persistence.supportsLazyQueryResultsMode();
3009
      if (lazyMode && !isScrolling())
3038
      if (isLazyMode())
3010 3039
      {
3011 3040
         Long templateRowid = getTemplateQueryRowid(args);
3012 3041
         if (templateRowid != null)
......
3015 3044
            return results;
3016 3045
         }
3017 3046
         
3018
         return new ScrollingResults(persistence, executeScroll(persistence, fql, args, lazyMode));
3047
         return new ScrollingResults(persistence, executeScroll(persistence, fql, args, true));
3019 3048
      }
3020 3049
      
3021 3050
      if (cacheOnReval || probablyRequiresResort())
......
3457 3486
   }
3458 3487
   
3459 3488
   /**
3489
    * Helper method to understand if this query is going to use lazy query results mode.
3490
    * Such mode automatically solves invalidation at the database side, so there is no
3491
    * need to invalidate in the server-side.
3492
    *  
3493
    * @return  {@code true} if this is a lazy mode query with implicit invalidation handling
3494
    */
3495
   private boolean isLazyMode()
3496
   {
3497
      if (lazyMode == null)
3498
      {
3499
         ArrayList<QueryComponent> components = components();
3500
         if (components == null || components.size() != 1)
3501
         {
3502
            return false;
3503
         }
3504
         RecordBuffer buffer = components.get(0).getBuffer();
3505
         lazyMode = buffer != null    &&
3506
                    buffer.isActive() &&
3507
                    buffer.getPersistence().supportsLazyQueryResultsMode();
3508
      }
3509
      
3510
      return lazyMode;
3511
   }
3512
   
3513
   /**
3460 3514
    * Indicate whether the query results as initially fetched are likely to require a re-sort before they
3461 3515
    * are returned. This decision is based on whether the sort phrase exists and does not match any legacy
3462 3516
    * index of the first query component table.
src/com/goldencode/p2j/persist/CompoundQuery.java 2023-03-09 12:35:59 +0000
239 239
**     SVL 20230113          More performance improvements by replacing some "for-each" loops with indexed
240 240
**                           "for" loops.
241 241
** 082 CA  20230221          Javadoc fixes.
242
** 083 AL2 20230309          Optimized record change listener registration to avoid computing scope for queries
243
*                            which dont require registration.
242 244
*/
243 245

  
244 246
/*
......
2445 2447
      {
2446 2448
         CompoundComponent comp = compoundComponents.get(i);
2447 2449
         Joinable query = comp.getQuery();
2450
         if (!query.shouldRegisterRecordChangeListeners())
2451
         {
2452
            continue;
2453
         }
2454
         
2448 2455
         int scope = externalScope;
2449 2456
         RecordBuffer[] buffers = query.getRecordBuffers();
2450 2457
         
......
2458 2465
         
2459 2466
         if (scope != -1)
2460 2467
         {
2461
            query.registerRecordChangeListeners(scope);
2468
            query.registerRecordChangeListeners(Integer.valueOf(scope));
2462 2469
         }
2463 2470
      }
2464 2471
      
src/com/goldencode/p2j/persist/Joinable.java 2023-03-09 12:13:48 +0000
48 48
**                           are not the same), to be aware of the external buffers (i.e. added for CAN-FIND
49 49
**                           sub-select clauses).  The translate will be performed before the query is being
50 50
**                           executed.
51
** 020 AL2 20230309          Allow registering change listeners at latest scope using null.
51 52
*/
52 53

  
53 54
/*
......
251 252
   public Object[] peekLast();
252 253
   
253 254
   /**
255
    * Check if this type of query should register record change listeners. Use this 
256
    * to avoid computing any scope for registration and end up with a no registration
257
    * behavior. 
258
    * 
259
    * @return   {@code true} if we should invest time into computing the scope in order
260
    *           to call {@link #registerRecordChangeListeners} or {@code false} if we
261
    *           can skip doing any work to honor {@link #registerRecordChangeListeners}.
262
    */
263
   public default boolean shouldRegisterRecordChangeListeners()
264
   {
265
      return true;
266
   }
267
   
268
   /**
254 269
    * Register all <code>RecordChangeListener</code>s associated with this
255 270
    * query (if any), with the context-local <code>ChangeBroker</code> at the
256 271
    * indicated scope.
257 272
    * 
258 273
    * @param   scope
259 274
    *          Scope at which listeners should be registered with the change
260
    *          broker.
275
    *          broker. {@code null} means register at the closest scope.
261 276
    */
262
   public void registerRecordChangeListeners(int scope);
277
   public void registerRecordChangeListeners(Integer scope);
263 278
   
264 279
   /**
265 280
    * Create an adaptive query component based on the information in this query (which is
src/com/goldencode/p2j/persist/PreselectQuery.java 2023-03-09 12:27:04 +0000
2211 2211
      return super.getExternalBuffers();
2212 2212
   }
2213 2213
   
2214

  
2215
   /**
2216
    * Check if this type of query should register record change listeners. Use this 
2217
    * to avoid computing any scope for registration and end up with a no registration
2218
    * behavior. 
2219
    * 
2220
    * @return   {@code true} if we should invest time into computing the scope in order
2221
    *           to call {@link #registerRecordChangeListeners} or {@code false} if we
2222
    *           can skip doing any work to honor {@link #registerRecordChangeListeners}.
2223
    */
2224
   @Override
2225
   public boolean shouldRegisterRecordChangeListeners()
2226
   {
2227
      return false;
2228
   }
2229
   
2214 2230
   /**
2215 2231
    * Register all <code>RecordChangeListener</code>s associated with this
2216 2232
    * query (if any), with the context-local <code>ChangeBroker</code> at the
......
2220 2236
    * 
2221 2237
    * @param   scope
2222 2238
    *          Scope at which listeners should be registered with the change
2223
    *          broker.
2239
    *          broker. {@code null} means register at the closest scope.
2224 2240
    */
2225
   public void registerRecordChangeListeners(int scope)
2241
   @Override
2242
   public void registerRecordChangeListeners(Integer scope)
2226 2243
   {
2227 2244
   }
2228 2245
   
src/com/goldencode/p2j/persist/RandomAccessQuery.java 2023-03-09 11:47:41 +0000
352 352
** 116 AL2 20230210          Allow direct access for recid/unique index look-ups.
353 353
**         20230227          Added locking if query is find-by-row-id and record is found in cache.
354 354
**         20230307          Honor record nursery before direct access.
355
**         20230309          Allow register of record change listeners at latest scope using null.
355 356
*/
356 357

  
357 358
/*
......
2922 2923
    * 
2923 2924
    * @param   scope
2924 2925
    *          Scope at which listeners should be registered with the change broker.
2926
    *          {@code null} means register at the closest scope.
2925 2927
    */
2926
   public void registerRecordChangeListeners(int scope)
2928
   @Override
2929
   public void registerRecordChangeListeners(Integer scope)
2927 2930
   {
2928 2931
      ChangeBroker broker = ChangeBroker.get();
2929
      broker.addListener(this, scope);
2932
      if (scope == null)
2933
      {
2934
         broker.addListener(this);
2935
      }
2936
      else
2937
      {
2938
         broker.addListener(this, scope);
2939
      }
2940
      
2930 2941
      if (placeholderCleaner != null)
2931 2942
      {
2932
         broker.addListener(placeholderCleaner, scope);
2943
         if (scope == null)
2944
         {
2945
            broker.addListener(placeholderCleaner);
2946
         }
2947
         else
2948
         {
2949
            broker.addListener(this, scope);
2950
         }
2933 2951
      }
2934 2952
      
2935 2953
      // if these were added as global listeners in ChangeBroker remember to remove them
2936 2954
      // when the query is destroyed. Otherwise, the ChangeBroker will drop them automatically
2937 2955
      // when the respective scope is finished.
2938
      if (scope == 0)
2956
      if (scope != null && scope == 0)
2939 2957
      {
2940 2958
         unregisterOnCleanup = true;
2941 2959
      }