public boolean performWriteSkewCheck(DataContainer container, int segment, PersistenceManager persistenceManager,
                                        TxInvocationContext ctx, EntryVersion versionSeen,
                                        VersionGenerator versionGenerator, TimeService timeService) {
      if (versionSeen == null) {
         if (trace) {
            log.tracef("Perform write skew check for key %s but the key was not read. Skipping check!", toStr(key));
         }
         //version seen is null when the entry was not read. In this case, the write skew is not needed.
         return true;
      }
      EntryVersion prevVersion;
      if (ctx.isOriginLocal()) {
         prevVersion = getCurrentEntryVersion(container, segment, persistenceManager, ctx, versionGenerator, timeService);
      } else {
         // If this node is an owner and not originator, the entry has been loaded and wrapped under lock,
         // so the version in context should be up-to-date
         prevVersion = ctx.getCacheTransaction().getVersionsRead().get(key);
         if (prevVersion == null) {
            // If the command has IGNORE_RETURN_VALUE flags it's possible that the entry was not loaded
            // from cache loader - we have to force load
            prevVersion = getCurrentEntryVersion(container, segment, persistenceManager, ctx, versionGenerator, timeService);
         }
      }
      // If it is expired then it is possible the previous version doesn't exist - because entry didn't exist)
      if (isExpired() && prevVersion == versionGenerator.nonExistingVersion()) {
         return true;
      }
      // ISPN-7170: With total-order protocol, a command may skip loading the entry from persistence layer, and keep
      // the entry would have non-existing version. Then TotalOrderVersionedEntryWrappingInterceptor would
      // increase the version and store the entry during commit phase, potentially overwriting newer version.
      // Therefore we use the compulsory load during this check (in prepare phase) and update the entry version.
      if (prevVersion.compareTo(metadata.version()) != InequalVersionComparisonResult.EQUAL) {
         if (trace) {
            log.tracef("Updating version in metadata %s -> %s", metadata.version(), prevVersion);
         }
         metadata = metadata.builder().version(prevVersion).build();
      }

      //in this case, the transaction read some value and the data container has a value stored.
      //version seen and previous version are not null. Simple version comparation.
      InequalVersionComparisonResult result = prevVersion.compareTo(versionSeen);
      if (trace) {
         log.tracef("Comparing versions %s and %s for key %s: %s", prevVersion, versionSeen, key, result);
      }
      // TODO: there is a risk associated with versions that are not monotonous per entry - if an entry is removed
      // and then written several times, it can reach the previous version.
      return InequalVersionComparisonResult.EQUAL == result;
   }
public boolean performWriteSkewCheck ( DataContainer container , int segment , PersistenceManager persistenceManager , TxInvocationContext ctx , EntryVersion versionSeen , VersionGenerator versionGenerator , TimeService timeService ) { if ( versionSeen == null ) { if ( trace ) { log . tracef ( "Perform write skew check for key %s but the key was not read. Skipping check!" , toStr ( key ) ) ; } return true ; } EntryVersion prevVersion ; if ( ctx . isOriginLocal ( ) ) { prevVersion = getCurrentEntryVersion ( container , segment , persistenceManager , ctx , versionGenerator , timeService ) ; } else { prevVersion = ctx . getCacheTransaction ( ) . getVersionsRead ( ) . get ( key ) ; if ( prevVersion == null ) { prevVersion = getCurrentEntryVersion ( container , segment , persistenceManager , ctx , versionGenerator , timeService ) ; } } if ( isExpired ( ) && prevVersion == versionGenerator . nonExistingVersion ( ) ) { return true ; } if ( prevVersion . compareTo ( metadata . version ( ) ) != InequalVersionComparisonResult . EQUAL ) { if ( trace ) { log . tracef ( "Updating version in metadata %s -> %s" , metadata . version ( ) , prevVersion ) ; } metadata = metadata . builder ( ) . version ( prevVersion ) . build ( ) ; } InequalVersionComparisonResult result = prevVersion . compareTo ( versionSeen ) ; if ( trace ) { log . tracef ( "Comparing versions %s and %s for key %s: %s" , prevVersion , versionSeen , key , result ) ; } return InequalVersionComparisonResult . EQUAL == result ; }
@param container the data container to check the write skew against
@param segment the segment matching this entry
@param persistenceManager the persistence manager to possibly check write skew against
@param ctx the invocation context
@param versionSeen what version has been seen for this entry
@param versionGenerator generator to generate a new version if needed
@param timeService time service to check if entries are expired
@return whether a write skew occurred for this entry