private Object handleInvalidate(InvocationContext ctx, WriteCommand command, Object... keys) throws Throwable { Object retval = invokeNextInterceptor(ctx, command); if (command.isSuccessful() && !ctx.isInTxScope()) { if (keys != null && keys.length != 0) { return invalidateAcrossCluster( isSynchronous(ctx), ctx, keys, ctx.isUseFutureReturnType(), retval); } } return retval; }
/** * If we are within one transaction we won't do any replication as replication would only be * performed at commit time. If the operation didn't originate locally we won't do any replication * either. */ private Object handleWriteCommand( InvocationContext ctx, WriteCommand command, RecipientGenerator recipientGenerator, boolean skipRemoteGet, boolean skipL1Invalidation) throws Throwable { // see if we need to load values from remote srcs first if (ctx.isOriginLocal() && !skipRemoteGet) remoteGetBeforeWrite(ctx, command.isConditional(), recipientGenerator); boolean sync = isSynchronous(ctx); // if this is local mode then skip distributing if (isLocalModeForced(ctx)) { return invokeNextInterceptor(ctx, command); } // FIRST pass this call up the chain. Only if it succeeds (no exceptions) locally do we attempt // to distribute. Object returnValue = invokeNextInterceptor(ctx, command); if (command.isSuccessful()) { if (!ctx.isInTxScope()) { NotifyingNotifiableFuture<Object> futureToReturn = null; Future<?> invalidationFuture = null; if (ctx.isOriginLocal()) { int newCacheViewId = -1; stateTransferLock.waitForStateTransferToEnd(ctx, command, newCacheViewId); List<Address> rec = recipientGenerator.generateRecipients(); int numCallRecipients = rec == null ? 0 : rec.size(); if (trace) log.tracef("Invoking command %s on hosts %s", command, rec); boolean useFuture = ctx.isUseFutureReturnType(); if (isL1CacheEnabled && !skipL1Invalidation) // Handle the case where the put is local. If in unicast mode and this is not a data // owner, nothing happens. If in multicast mode, we this node will send the multicast if (rpcManager.getTransport().getMembers().size() > numCallRecipients) { // Command was successful, we have a number of receipients and L1 should be flushed, // so request any L1 invalidations from this node if (trace) log.tracef( "Put occuring on node, requesting L1 cache invalidation for keys %s. Other data owners are %s", command.getAffectedKeys(), dm.getAffectedNodes(command.getAffectedKeys())); if (useFuture) { futureToReturn = l1Manager.flushCache( recipientGenerator.getKeys(), returnValue, ctx.getOrigin(), !(command instanceof RemoveCommand)); } else { invalidationFuture = l1Manager.flushCacheWithSimpleFuture( recipientGenerator.getKeys(), returnValue, ctx.getOrigin(), !(command instanceof RemoveCommand)); } } else { if (trace) log.tracef("Not performing invalidation! numCallRecipients=%s", numCallRecipients); } if (!isSingleOwnerAndLocal(recipientGenerator)) { if (useFuture) { if (futureToReturn == null) futureToReturn = new NotifyingFutureImpl(returnValue); rpcManager.invokeRemotelyInFuture(rec, command, futureToReturn); return futureToReturn; } else { rpcManager.invokeRemotely(rec, command, sync); } } else if (useFuture && futureToReturn != null) { return futureToReturn; } if (invalidationFuture != null && sync) { invalidationFuture.get(); // wait for the inval command to complete if (trace) log.tracef("Finished invalidating keys %s ", recipientGenerator.getKeys()); } } else { // Piggyback remote puts and cause L1 invalidations if (isL1CacheEnabled && !skipL1Invalidation) { // Command was successful and L1 should be flushed, so request any L1 invalidations from // this node if (trace) log.tracef( "Put occuring on node, requesting cache invalidation for keys %s. Origin of command is remote", command.getAffectedKeys()); // If this is a remove command, then don't pass in the origin - since the entru would be // removed from the origin's L1 cache. invalidationFuture = l1Manager.flushCacheWithSimpleFuture( recipientGenerator.getKeys(), returnValue, ctx.getOrigin(), !(command instanceof RemoveCommand)); if (sync) { invalidationFuture.get(); // wait for the inval command to complete if (trace) log.tracef("Finished invalidating keys %s ", recipientGenerator.getKeys()); } } } } } return returnValue; }