private boolean needsRemoteGet(InvocationContext ctx, Object key, boolean retvalCheck) { final CacheEntry entry; return retvalCheck && !ctx.hasFlag(Flag.CACHE_MODE_LOCAL) && !ctx.hasFlag(Flag.SKIP_REMOTE_LOOKUP) && ((entry = ctx.lookupEntry(key)) == null || entry.isNull() || entry.isLockPlaceholder()); }
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; }
@Override public Object perform(InvocationContext ctx) throws Throwable { CacheEntry entry = ctx.lookupEntry(key); if (entry == null || entry.isNull()) { return null; } if (entry.isRemoved()) { return null; } return entryFactory.copy(entry); }
@Override public final MVCCEntry wrapEntryForPut( InvocationContext ctx, Object key, InternalCacheEntry icEntry, boolean undeleteIfNeeded) throws InterruptedException { CacheEntry cacheEntry = getFromContext(ctx, key); MVCCEntry mvccEntry; if (cacheEntry != null && cacheEntry.isNull()) cacheEntry = null; if (cacheEntry != null) { mvccEntry = wrapMvccEntryForPut(ctx, key, cacheEntry); mvccEntry.undelete(undeleteIfNeeded); } else { InternalCacheEntry ice = (icEntry == null ? getFromContainer(key) : icEntry); // A putForExternalRead is putIfAbsent, so if key present, do nothing if (ice != null && ctx.hasFlag(Flag.PUT_FOR_EXTERNAL_READ)) return null; mvccEntry = ice != null ? wrapInternalCacheEntryForPut(ctx, key, ice) : newMvccEntryForPut(ctx, key); } mvccEntry.copyForUpdate(container, localModeWriteSkewCheck); return mvccEntry; }