@Override
  public final CacheEntry wrapEntryForReading(InvocationContext ctx, Object key)
      throws InterruptedException {
    CacheEntry cacheEntry = getFromContext(ctx, key);
    if (cacheEntry == null) {
      cacheEntry = getFromContainer(key);

      // do not bother wrapping though if this is not in a tx.  repeatable read etc are all
      // meaningless unless there is a tx.
      if (useRepeatableRead) {
        MVCCEntry mvccEntry =
            cacheEntry == null
                ? createWrappedEntry(key, null, null, false, false, -1)
                : createWrappedEntry(
                    key,
                    cacheEntry.getValue(),
                    cacheEntry.getVersion(),
                    false,
                    false,
                    cacheEntry.getLifespan());
        if (mvccEntry != null) ctx.putLookedUpEntry(key, mvccEntry);
        return mvccEntry;
      } else if (cacheEntry
          != null) { // if not in transaction and repeatable read, or simply read committed
                     // (regardless of whether in TX or not), do not wrap
        ctx.putLookedUpEntry(key, cacheEntry);
      }
      return cacheEntry;
    }
    return cacheEntry;
  }
 @Override
 public final MVCCEntry wrapEntryForRemove(InvocationContext ctx, Object key)
     throws InterruptedException {
   CacheEntry cacheEntry = getFromContext(ctx, key);
   MVCCEntry mvccEntry = null;
   if (cacheEntry != null) {
     if (cacheEntry instanceof MVCCEntry && !(cacheEntry instanceof NullMarkerEntry)) {
       mvccEntry = (MVCCEntry) cacheEntry;
     } else {
       mvccEntry = wrapMvccEntryForRemove(ctx, key, cacheEntry);
     }
   } else {
     InternalCacheEntry ice = getFromContainer(key);
     if (ice != null) {
       mvccEntry = wrapInternalCacheEntryForPut(ctx, key, ice);
     }
   }
   if (mvccEntry == null) {
     // make sure we record this! Null value since this is a forced lock on the key
     ctx.putLookedUpEntry(key, null);
   } else {
     mvccEntry.copyForUpdate(container, localModeWriteSkewCheck);
   }
   return mvccEntry;
 }
 private MVCCEntry newMvccEntryForPut(InvocationContext ctx, Object key) {
   MVCCEntry mvccEntry;
   if (trace) log.trace("Creating new entry.");
   notifier.notifyCacheEntryCreated(key, true, ctx);
   mvccEntry = createWrappedEntry(key, null, null, true, false, -1);
   mvccEntry.setCreated(true);
   ctx.putLookedUpEntry(key, mvccEntry);
   notifier.notifyCacheEntryCreated(key, false, ctx);
   return mvccEntry;
 }
 @Override
 public final MVCCEntry wrapEntryForReplace(InvocationContext ctx, Object key)
     throws InterruptedException {
   MVCCEntry mvccEntry = wrapEntry(ctx, key);
   if (mvccEntry == null) {
     // make sure we record this! Null value since this is a forced lock on the key
     ctx.putLookedUpEntry(key, null);
   }
   return mvccEntry;
 }
  private Object realRemoteGet(
      InvocationContext ctx, Object key, boolean storeInL1, boolean isWrite) throws Throwable {
    if (trace) log.tracef("Doing a remote get for key %s", key);

    boolean acquireRemoteLock = false;
    if (ctx.isInTxScope()) {
      TxInvocationContext txContext = (TxInvocationContext) ctx;
      acquireRemoteLock =
          isWrite && isPessimisticCache && !txContext.getAffectedKeys().contains(key);
    }
    // attempt a remote lookup
    InternalCacheEntry ice = dm.retrieveFromRemoteSource(key, ctx, acquireRemoteLock);

    if (acquireRemoteLock) {
      ((TxInvocationContext) ctx).addAffectedKey(key);
    }

    if (ice != null) {
      if (storeInL1) {
        if (isL1CacheEnabled) {
          if (trace) log.tracef("Caching remotely retrieved entry for key %s in L1", key);
          // This should be fail-safe
          try {
            long lifespan =
                ice.getLifespan() < 0
                    ? configuration.getL1Lifespan()
                    : Math.min(ice.getLifespan(), configuration.getL1Lifespan());
            PutKeyValueCommand put =
                cf.buildPutKeyValueCommand(
                    ice.getKey(), ice.getValue(), lifespan, -1, ctx.getFlags());
            lockAndWrap(ctx, key, ice);
            invokeNextInterceptor(ctx, put);
          } catch (Exception e) {
            // Couldn't store in L1 for some reason.  But don't fail the transaction!
            log.infof("Unable to store entry %s in L1 cache", key);
            log.debug("Inability to store in L1 caused by", e);
          }
        } else {
          CacheEntry ce = ctx.lookupEntry(key);
          if (ce == null || ce.isNull() || ce.isLockPlaceholder() || ce.getValue() == null) {
            if (ce != null && ce.isChanged()) {
              ce.setValue(ice.getValue());
            } else {
              if (isWrite) lockAndWrap(ctx, key, ice);
              else ctx.putLookedUpEntry(key, ice);
            }
          }
        }
      } else {
        if (trace) log.tracef("Not caching remotely retrieved entry for key %s in L1", key);
      }
      return ice.getValue();
    }
    return null;
  }
 private DeltaAwareCacheEntry wrapInternalCacheEntryForDelta(
     InvocationContext ctx, Object key, CacheEntry cacheEntry) {
   DeltaAwareCacheEntry e;
   if (cacheEntry instanceof MVCCEntry) {
     e = createWrappedDeltaEntry(key, (DeltaAware) cacheEntry.getValue(), cacheEntry);
   } else {
     e = createWrappedDeltaEntry(key, (DeltaAware) cacheEntry.getValue(), null);
   }
   ctx.putLookedUpEntry(key, e);
   return e;
 }
 private MVCCEntry wrapMvccEntryForRemove(
     InvocationContext ctx, Object key, CacheEntry cacheEntry) {
   MVCCEntry mvccEntry =
       createWrappedEntry(
           key,
           cacheEntry.getValue(),
           cacheEntry.getVersion(),
           false,
           true,
           cacheEntry.getLifespan());
   ctx.putLookedUpEntry(key, mvccEntry);
   return mvccEntry;
 }
 private DeltaAwareCacheEntry newDeltaAwareCacheEntry(
     InvocationContext ctx, Object key, DeltaAware deltaAware) {
   DeltaAwareCacheEntry deltaEntry = createWrappedDeltaEntry(key, deltaAware, null);
   ctx.putLookedUpEntry(key, deltaEntry);
   return deltaEntry;
 }