public InternalCacheEntry retrieveFromRemoteSource(Object key, InvocationContext ctx) throws Exception { ClusteredGetCommand get = cf.buildClusteredGetCommand(key, ctx.getFlags()); List<Address> targets = locate(key); targets.remove(getSelf()); ResponseFilter filter = new ClusteredGetResponseValidityFilter(targets); Map<Address, Response> responses = rpcManager.invokeRemotely( targets, get, ResponseMode.SYNCHRONOUS, configuration.getSyncReplTimeout(), false, filter); if (!responses.isEmpty()) { for (Response r : responses.values()) { if (r instanceof SuccessfulResponse) { InternalCacheValue cacheValue = (InternalCacheValue) ((SuccessfulResponse) r).getResponseValue(); return cacheValue.toInternalCacheEntry(key); } } } return null; }
@SuppressWarnings("unchecked") final V get(Object key, EnumSet<Flag> explicitFlags, ClassLoader explicitClassLoader) { assertKeyNotNull(key); InvocationContext ctx = getInvocationContextForRead(null, explicitFlags, explicitClassLoader); GetKeyValueCommand command = commandsFactory.buildGetKeyValueCommand(key, ctx.getFlags()); return (V) invoker.invoke(ctx, command); }
/** * Simply check if there is an ongoing tx. * * <ul> * <li>If there is one, this is a no-op and just passes the call up the chain. * <li>If there isn't one and there is a batch in progress, resume the batch's tx, pass up, and * finally suspend the batch's tx. * <li>If there is no batch in progress, just pass the call up the chain. * </ul> */ @Override protected Object handleDefault(InvocationContext ctx, VisitableCommand command) throws Throwable { Transaction tx; if (!ctx.isOriginLocal()) return invokeNextInterceptor(ctx, command); // if in a batch, attach tx if (transactionManager.getTransaction() == null && (tx = batchContainer.getBatchTransaction()) != null) { try { transactionManager.resume(tx); // If there's no ongoing tx then BatchingInterceptor creates one and then invokes next // interceptor, // so that all interceptors in the stack will be executed in a transactional context. // This is where a new context (TxInvocationContext) is created, as the existing context is // not transactional: NonTxInvocationContext. InvocationContext txContext = icc.createInvocationContext(true, -1); txContext.setFlags(ctx.getFlags()); return invokeNextInterceptor(txContext, command); } finally { if (transactionManager.getTransaction() != null && batchContainer.isSuspendTxAfterInvocation()) transactionManager.suspend(); } } else { return invokeNextInterceptor(ctx, command); } }
final boolean remove( Object key, Object value, EnumSet<Flag> explicitFlags, ClassLoader explicitClassLoader) { assertKeyNotNull(key); InvocationContext ctx = getInvocationContextWithImplicitTransaction(explicitFlags, explicitClassLoader); RemoveCommand command = commandsFactory.buildRemoveCommand(key, value, ctx.getFlags()); return (Boolean) executeCommandAndCommitIfNeeded(ctx, command); }
@SuppressWarnings("unchecked") final V remove(Object key, EnumSet<Flag> explicitFlags, ClassLoader explicitClassLoader) { assertKeyNotNull(key); InvocationContext ctx = getInvocationContextWithImplicitTransaction(explicitFlags, explicitClassLoader); RemoveCommand command = commandsFactory.buildRemoveCommand(key, null, ctx.getFlags()); return (V) executeCommandAndCommitIfNeeded(ctx, command); }
final boolean containsKey( Object key, EnumSet<Flag> explicitFlags, ClassLoader explicitClassLoader) { assertKeyNotNull(key); InvocationContext ctx = getInvocationContextForRead(null, explicitFlags, explicitClassLoader); GetKeyValueCommand command = commandsFactory.buildGetKeyValueCommand(key, ctx.getFlags()); Object response = invoker.invoke(ctx, command); return response != null; }
final NotifyingFuture<Void> clearAsync( EnumSet<Flag> explicitFlags, ClassLoader explicitClassLoader) { InvocationContext ctx = getInvocationContextWithImplicitTransaction(explicitFlags, explicitClassLoader); ctx.setUseFutureReturnType(true); ClearCommand command = commandsFactory.buildClearCommand(ctx.getFlags()); return wrapInFuture(executeCommandAndCommitIfNeeded(ctx, command)); }
final NotifyingFuture<Boolean> removeAsync( Object key, Object value, EnumSet<Flag> explicitFlags, ClassLoader explicitClassLoader) { assertKeyNotNull(key); InvocationContext ctx = getInvocationContextWithImplicitTransaction(explicitFlags, explicitClassLoader); ctx.setUseFutureReturnType(true); RemoveCommand command = commandsFactory.buildRemoveCommand(key, value, ctx.getFlags()); return wrapInFuture(executeCommandAndCommitIfNeeded(ctx, command)); }
boolean lock( Collection<? extends K> keys, EnumSet<Flag> explicitFlags, ClassLoader explicitClassLoader) { if (keys == null || keys.isEmpty()) { throw new IllegalArgumentException("Cannot lock empty list of keys"); } InvocationContext ctx = getInvocationContextForWrite(explicitFlags, explicitClassLoader); LockControlCommand command = commandsFactory.buildLockControlCommand(keys, false, ctx.getFlags()); return (Boolean) invoker.invoke(ctx, command); }
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; }
final NotifyingFuture<Void> putAllAsync( Map<? extends K, ? extends V> data, long lifespan, TimeUnit lifespanUnit, long maxIdle, TimeUnit maxIdleUnit, EnumSet<Flag> explicitFlags, ClassLoader explicitClassLoader) { assertKeysNotNull(data); InvocationContext ctx = getInvocationContextWithImplicitTransaction(explicitFlags, explicitClassLoader); ctx.setUseFutureReturnType(true); PutMapCommand command = commandsFactory.buildPutMapCommand( data, lifespanUnit.toMillis(lifespan), maxIdleUnit.toMillis(maxIdle), ctx.getFlags()); return wrapInFuture(executeCommandAndCommitIfNeeded(ctx, command)); }
final void putAll( Map<? extends K, ? extends V> map, long lifespan, TimeUnit lifespanUnit, long maxIdleTime, TimeUnit idleTimeUnit, EnumSet<Flag> explicitFlags, ClassLoader explicitClassLoader) { assertKeysNotNull(map); InvocationContext ctx = getInvocationContextWithImplicitTransaction(explicitFlags, explicitClassLoader); PutMapCommand command = commandsFactory.buildPutMapCommand( map, lifespanUnit.toMillis(lifespan), idleTimeUnit.toMillis(maxIdleTime), ctx.getFlags()); executeCommandAndCommitIfNeeded(ctx, command); }
@SuppressWarnings("unchecked") final V put( K key, V value, long lifespan, TimeUnit lifespanUnit, long maxIdleTime, TimeUnit idleTimeUnit, EnumSet<Flag> explicitFlags, ClassLoader explicitClassLoader) { assertKeyNotNull(key); InvocationContext ctx = getInvocationContextWithImplicitTransaction(explicitFlags, explicitClassLoader); PutKeyValueCommand command = commandsFactory.buildPutKeyValueCommand( key, value, lifespanUnit.toMillis(lifespan), idleTimeUnit.toMillis(maxIdleTime), ctx.getFlags()); return (V) executeCommandAndCommitIfNeeded(ctx, command); }
final NotifyingFuture<V> replaceAsync( K key, V value, long lifespan, TimeUnit lifespanUnit, long maxIdle, TimeUnit maxIdleUnit, EnumSet<Flag> explicitFlags, ClassLoader explicitClassLoader) { assertKeyNotNull(key); InvocationContext ctx = getInvocationContextWithImplicitTransaction(explicitFlags, explicitClassLoader); ctx.setUseFutureReturnType(true); ReplaceCommand command = commandsFactory.buildReplaceCommand( key, null, value, lifespanUnit.toMillis(lifespan), maxIdleUnit.toMillis(maxIdle), ctx.getFlags()); return wrapInFuture(executeCommandAndCommitIfNeeded(ctx, command)); }
final boolean replace( K key, V oldValue, V value, long lifespan, TimeUnit lifespanUnit, long maxIdleTime, TimeUnit idleTimeUnit, EnumSet<Flag> explicitFlags, ClassLoader explicitClassLoader) { assertKeyNotNull(key); InvocationContext ctx = getInvocationContextWithImplicitTransaction(explicitFlags, explicitClassLoader); ReplaceCommand command = commandsFactory.buildReplaceCommand( key, oldValue, value, lifespanUnit.toMillis(lifespan), idleTimeUnit.toMillis(maxIdleTime), ctx.getFlags()); return (Boolean) executeCommandAndCommitIfNeeded(ctx, command); }
private Map<Object, InternalCacheValue> applyStateMap( Map<Object, InternalCacheValue> state, boolean withRetry) { Map<Object, InternalCacheValue> retry = withRetry ? new HashMap<Object, InternalCacheValue>() : null; for (Map.Entry<Object, InternalCacheValue> e : state.entrySet()) { InternalCacheValue v = e.getValue(); InvocationContext ctx = icc.createInvocationContext(); // locking not necessary in the case of a join since the node isn't doing anything else // TODO what if the node is already running? ctx.setFlags( CACHE_MODE_LOCAL, SKIP_CACHE_LOAD, SKIP_REMOTE_LOOKUP, SKIP_SHARED_CACHE_STORE, SKIP_LOCKING, SKIP_OWNERSHIP_CHECK); try { PutKeyValueCommand put = cf.buildPutKeyValueCommand( e.getKey(), v.getValue(), v.getLifespan(), v.getMaxIdle(), ctx.getFlags()); interceptorChain.invoke(ctx, put); } catch (Exception ee) { if (withRetry) { if (trace) log.tracef( "Problem %s encountered when applying state for key %s. Adding entry to retry queue.", ee.getMessage(), e.getKey()); retry.put(e.getKey(), e.getValue()); } else { log.problemApplyingStateForKey(ee.getMessage(), e.getKey()); } } } return retry; }
final void clear(EnumSet<Flag> explicitFlags, ClassLoader explicitClassLoader) { InvocationContext ctx = getInvocationContextWithImplicitTransaction(explicitFlags, explicitClassLoader); ClearCommand command = commandsFactory.buildClearCommand(ctx.getFlags()); executeCommandAndCommitIfNeeded(ctx, command); }