Пример #1
0
  @Override
  public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command)
      throws Throwable {

    // This method will get the put() calls on the cache and then send them into Lucene once it's
    // successful.
    // do the actual put first.
    Object toReturn = invokeNextInterceptor(ctx, command);

    if (shouldModifyIndexes(ctx)) {
      // First making a check to see if the key is already in the cache or not. If it isn't we can
      // add the key no problem,
      // otherwise we need to be updating the indexes as opposed to simply adding to the indexes.
      getLog().debug("Infinispan Query indexing is triggered");
      Object key = command.getKey();
      Object value = extractValue(command.getValue());

      if (updateKnownTypesIfNeeded(value)) {
        // This means that the entry is just modified so we need to update the indexes and not add
        // to them.
        updateIndexes(value, extractValue(key));
      } else {
        if (updateKnownTypesIfNeeded(toReturn)) {
          removeFromIndexes(toReturn, extractValue(command.getKey()));
        }
      }
    }
    return toReturn;
  }
Пример #2
0
 /**
  * Indexing management of a PutKeyValueCommand
  *
  * @param command the visited PutKeyValueCommand
  * @param ctx the InvocationContext of the PutKeyValueCommand
  * @param previousValue the value being replaced by the put operation
  * @param transactionContext Optional for lazy initialization, or reuse an existing context.
  */
 private void processPutKeyValueCommand(
     final PutKeyValueCommand command,
     final InvocationContext ctx,
     final Object previousValue,
     TransactionContext transactionContext) {
   final boolean usingSkipIndexCleanupFlag = usingSkipIndexCleanup(command);
   // whatever the new type, we might still need to cleanup for the previous value (and schedule
   // removal first!)
   Object value = extractValue(command.getValue());
   if (!usingSkipIndexCleanupFlag
       && updateKnownTypesIfNeeded(previousValue)
       && shouldRemove(value, previousValue)) {
     if (shouldModifyIndexes(command, ctx)) {
       transactionContext =
           transactionContext == null ? makeTransactionalEventContext() : transactionContext;
       removeFromIndexes(previousValue, extractValue(command.getKey()), transactionContext);
     }
   }
   if (updateKnownTypesIfNeeded(value)) {
     if (shouldModifyIndexes(command, ctx)) {
       // This means that the entry is just modified so we need to update the indexes and not add
       // to them.
       transactionContext =
           transactionContext == null ? makeTransactionalEventContext() : transactionContext;
       updateIndexes(
           usingSkipIndexCleanupFlag, value, extractValue(command.getKey()), transactionContext);
     }
   }
 }
 @Override
 public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command)
     throws Throwable {
   if (isStoreAsBinary() || isClusterInvocation(ctx) || isStoreInvocation(ctx))
     checkMarshallable(command.getKey(), command.getValue());
   return super.visitPutKeyValueCommand(ctx, command);
 }
 @Override
 public BasicInvocationStage visitPutKeyValueCommand(
     InvocationContext ctx, PutKeyValueCommand command) throws Throwable {
   if (streamSummaryContainer.isEnabled() && ctx.isOriginLocal()) {
     streamSummaryContainer.addPut(command.getKey(), isRemote(command.getKey()));
   }
   return invokeNext(ctx, command).handle(writeSkewReturnHandler);
 }
 @Override
 public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command)
     throws Throwable {
   if (cdl.localNodeIsOwner(command.getKey())) {
     entryFactory.wrapEntryForWriting(
         ctx, command.getKey(), EntryFactory.Wrap.WRAP_ALL, false, false);
     ctx.forkInvocationSync(command);
   }
   return null;
 }
 @Override
 public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command)
     throws Throwable {
   if (ctx.isOriginLocal()) {
     Entity entity = extractEntity(command.getValue());
     EntryVersion entryVersion = getEntryVersion(ctx, command.getKey());
     applyVersion(entity, entryVersion);
   }
   return invokeNextInterceptor(ctx, command);
 }
 @Override
 public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command)
     throws Throwable {
   processCommand(command);
   containsPutForExternalRead =
       containsPutForExternalRead
           || (command.getFlags() != null
               && command.getFlags().contains(Flag.PUT_FOR_EXTERNAL_READ));
   result.add(command.getKey());
   return null;
 }
 @Override
 public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command)
     throws Throwable {
   Object returnValue = invokeNextInterceptor(ctx, command);
   Object key = command.getKey();
   if (skip(ctx, key, command) || ctx.isInTxScope() || !command.isSuccessful()) return returnValue;
   InternalCacheEntry se = getStoredEntry(key, ctx);
   store.store(se);
   log.tracef("Stored entry %s under key %s", se, key);
   if (getStatisticsEnabled()) cacheStores.incrementAndGet();
   return returnValue;
 }
  @Override
  public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command)
      throws Throwable {
    SingleKeyRecipientGenerator skrg = new SingleKeyRecipientGenerator(command.getKey());
    Object returnValue = handleWriteCommand(ctx, command, skrg, false, false);
    // If this was a remote put record that which sent it
    if (isL1CacheEnabled
        && !ctx.isOriginLocal()
        && !skrg.generateRecipients().contains(ctx.getOrigin()))
      l1Manager.addRequestor(command.getKey(), ctx.getOrigin());

    return returnValue;
  }
 @Override
 public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command)
     throws Throwable {
   if (!isPutForExternalRead(ctx)) {
     return handleInvalidate(ctx, command, command.getKey());
   }
   return invokeNextInterceptor(ctx, command);
 }
Пример #11
0
  private void applyStateInNonTransaction(XSiteState[] chunk) {
    SingleKeyNonTxInvocationContext ctx =
        (SingleKeyNonTxInvocationContext)
            invocationContextFactory.createSingleKeyNonTxInvocationContext();

    for (XSiteState siteState : chunk) {
      PutKeyValueCommand command = createPut(siteState);
      ctx.setLockOwner(command.getLockOwner());
      interceptorChain.invoke(ctx, command);
      ctx.resetState(); // re-use same context. Old context is not longer needed
      if (trace) {
        log.tracef("Successfully applied key'%s'", siteState);
      }
    }
    if (debug) {
      log.debugf("Successfully applied state. %s keys inserted", chunk.length);
    }
  }
Пример #12
0
 @Override
 public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command)
     throws Throwable {
   Object result = super.visitPutKeyValueCommand(ctx, command);
   if (!ctx.isInTxScope() && !command.hasFlag(Flag.PUT_FOR_STATE_TRANSFER)) {
     doBlock(ctx, command);
   }
   return result;
 }
 @Override
 public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command)
     throws Throwable {
   log.tracef("Processing a remote put %s", command);
   if (command.isConditional()) {
     return backupCache.putIfAbsent(command.getKey(), command.getValue(), command.getMetadata());
   }
   return backupCache.put(command.getKey(), command.getValue(), command.getMetadata());
 }
Пример #14
0
 final NotifyingFuture<V> putIfAbsentAsync(
     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);
   PutKeyValueCommand command =
       commandsFactory.buildPutKeyValueCommand(
           key,
           value,
           lifespanUnit.toMillis(lifespan),
           maxIdleUnit.toMillis(maxIdle),
           ctx.getFlags());
   command.setPutIfAbsent(true);
   return wrapInFuture(executeCommandAndCommitIfNeeded(ctx, command));
 }
Пример #15
0
 @SuppressWarnings("unchecked")
 final V putIfAbsent(
     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());
   command.setPutIfAbsent(true);
   return (V) executeCommandAndCommitIfNeeded(ctx, command);
 }
Пример #16
0
  /** @param isRemote true if the command is deserialized and is executed remote. */
  @Override
  public void initializeReplicableCommand(ReplicableCommand c, boolean isRemote) {
    if (c == null) return;
    switch (c.getCommandId()) {
      case PutKeyValueCommand.COMMAND_ID:
        ((PutKeyValueCommand) c).init(notifier, configuration);
        break;
      case ReplaceCommand.COMMAND_ID:
        ((ReplaceCommand) c).init(notifier, configuration);
        break;
      case PutMapCommand.COMMAND_ID:
        ((PutMapCommand) c).init(notifier);
        break;
      case RemoveCommand.COMMAND_ID:
        ((RemoveCommand) c).init(notifier, configuration);
        break;
      case MultipleRpcCommand.COMMAND_ID:
        MultipleRpcCommand rc = (MultipleRpcCommand) c;
        rc.init(interceptorChain, icf);
        if (rc.getCommands() != null)
          for (ReplicableCommand nested : rc.getCommands()) {
            initializeReplicableCommand(nested, false);
          }
        break;
      case SingleRpcCommand.COMMAND_ID:
        SingleRpcCommand src = (SingleRpcCommand) c;
        src.init(interceptorChain, icf);
        if (src.getCommand() != null) initializeReplicableCommand(src.getCommand(), false);

        break;
      case InvalidateCommand.COMMAND_ID:
        InvalidateCommand ic = (InvalidateCommand) c;
        ic.init(notifier, configuration);
        break;
      case InvalidateL1Command.COMMAND_ID:
        InvalidateL1Command ilc = (InvalidateL1Command) c;
        ilc.init(configuration, distributionManager, notifier, dataContainer);
        break;
      case PrepareCommand.COMMAND_ID:
      case VersionedPrepareCommand.COMMAND_ID:
      case TotalOrderNonVersionedPrepareCommand.COMMAND_ID:
      case TotalOrderVersionedPrepareCommand.COMMAND_ID:
        PrepareCommand pc = (PrepareCommand) c;
        pc.init(interceptorChain, icf, txTable);
        pc.initialize(notifier, recoveryManager);
        if (pc.getModifications() != null)
          for (ReplicableCommand nested : pc.getModifications()) {
            initializeReplicableCommand(nested, false);
          }
        pc.markTransactionAsRemote(isRemote);
        if (configuration.deadlockDetection().enabled() && isRemote) {
          DldGlobalTransaction transaction = (DldGlobalTransaction) pc.getGlobalTransaction();
          transaction.setLocksHeldAtOrigin(pc.getAffectedKeys());
        }
        break;
      case CommitCommand.COMMAND_ID:
      case VersionedCommitCommand.COMMAND_ID:
      case TotalOrderCommitCommand.COMMAND_ID:
      case TotalOrderVersionedCommitCommand.COMMAND_ID:
        CommitCommand commitCommand = (CommitCommand) c;
        commitCommand.init(interceptorChain, icf, txTable);
        commitCommand.markTransactionAsRemote(isRemote);
        break;
      case RollbackCommand.COMMAND_ID:
      case TotalOrderRollbackCommand.COMMAND_ID:
        RollbackCommand rollbackCommand = (RollbackCommand) c;
        rollbackCommand.init(interceptorChain, icf, txTable);
        rollbackCommand.markTransactionAsRemote(isRemote);
        break;
      case ClearCommand.COMMAND_ID:
        ClearCommand cc = (ClearCommand) c;
        cc.init(notifier, dataContainer);
        break;
      case ClusteredGetCommand.COMMAND_ID:
        ClusteredGetCommand clusteredGetCommand = (ClusteredGetCommand) c;
        clusteredGetCommand.initialize(
            icf,
            this,
            entryFactory,
            interceptorChain,
            distributionManager,
            txTable,
            configuration.dataContainer().keyEquivalence());
        break;
      case LockControlCommand.COMMAND_ID:
        LockControlCommand lcc = (LockControlCommand) c;
        lcc.init(interceptorChain, icf, txTable);
        lcc.markTransactionAsRemote(isRemote);
        if (configuration.deadlockDetection().enabled() && isRemote) {
          DldGlobalTransaction gtx = (DldGlobalTransaction) lcc.getGlobalTransaction();
          RemoteTransaction transaction = txTable.getRemoteTransaction(gtx);
          if (transaction != null) {
            if (!configuration.clustering().cacheMode().isDistributed()) {
              Set<Object> keys = txTable.getLockedKeysForRemoteTransaction(gtx);
              GlobalTransaction gtx2 = transaction.getGlobalTransaction();
              ((DldGlobalTransaction) gtx2).setLocksHeldAtOrigin(keys);
              gtx.setLocksHeldAtOrigin(keys);
            } else {
              GlobalTransaction gtx2 = transaction.getGlobalTransaction();
              ((DldGlobalTransaction) gtx2).setLocksHeldAtOrigin(gtx.getLocksHeldAtOrigin());
            }
          }
        }
        break;
      case StateRequestCommand.COMMAND_ID:
        ((StateRequestCommand) c).init(stateProvider);
        break;
      case StateResponseCommand.COMMAND_ID:
        ((StateResponseCommand) c).init(stateConsumer);
        break;
      case GetInDoubtTransactionsCommand.COMMAND_ID:
        GetInDoubtTransactionsCommand gptx = (GetInDoubtTransactionsCommand) c;
        gptx.init(recoveryManager);
        break;
      case TxCompletionNotificationCommand.COMMAND_ID:
        TxCompletionNotificationCommand ftx = (TxCompletionNotificationCommand) c;
        ftx.init(txTable, lockManager, recoveryManager, stateTransferManager);
        break;
      case MapCombineCommand.COMMAND_ID:
        MapCombineCommand mrc = (MapCombineCommand) c;
        mrc.init(mapReduceManager);
        break;
      case ReduceCommand.COMMAND_ID:
        ReduceCommand reduceCommand = (ReduceCommand) c;
        reduceCommand.init(mapReduceManager);
        break;
      case DistributedExecuteCommand.COMMAND_ID:
        DistributedExecuteCommand dec = (DistributedExecuteCommand) c;
        dec.init(cache);
        break;
      case GetInDoubtTxInfoCommand.COMMAND_ID:
        GetInDoubtTxInfoCommand gidTxInfoCommand = (GetInDoubtTxInfoCommand) c;
        gidTxInfoCommand.init(recoveryManager);
        break;
      case CompleteTransactionCommand.COMMAND_ID:
        CompleteTransactionCommand ccc = (CompleteTransactionCommand) c;
        ccc.init(recoveryManager);
        break;
      case ApplyDeltaCommand.COMMAND_ID:
        break;
      case CreateCacheCommand.COMMAND_ID:
        CreateCacheCommand createCacheCommand = (CreateCacheCommand) c;
        createCacheCommand.init(cache.getCacheManager());
        break;
      case XSiteAdminCommand.COMMAND_ID:
        XSiteAdminCommand xSiteAdminCommand = (XSiteAdminCommand) c;
        xSiteAdminCommand.init(backupSender);
        break;
      case CancelCommand.COMMAND_ID:
        CancelCommand cancelCommand = (CancelCommand) c;
        cancelCommand.init(cancellationService);
        break;
      case XSiteStateTransferControlCommand.COMMAND_ID:
        XSiteStateTransferControlCommand xSiteStateTransferControlCommand =
            (XSiteStateTransferControlCommand) c;
        xSiteStateTransferControlCommand.initialize(
            xSiteStateProvider, xSiteStateConsumer, xSiteStateTransferManager);
        break;
      case XSiteStatePushCommand.COMMAND_ID:
        XSiteStatePushCommand xSiteStatePushCommand = (XSiteStatePushCommand) c;
        xSiteStatePushCommand.initialize(xSiteStateConsumer);
        break;
      case EntryRequestCommand.COMMAND_ID:
        EntryRequestCommand entryRequestCommand = (EntryRequestCommand) c;
        entryRequestCommand.init(entryRetriever);
        break;
      case EntryResponseCommand.COMMAND_ID:
        EntryResponseCommand entryResponseCommand = (EntryResponseCommand) c;
        entryResponseCommand.init(entryRetriever);
        break;
      case GetKeysInGroupCommand.COMMAND_ID:
        GetKeysInGroupCommand getKeysInGroupCommand = (GetKeysInGroupCommand) c;
        getKeysInGroupCommand.setGroupManager(groupManager);
        break;
      case ClusteredGetAllCommand.COMMAND_ID:
        ClusteredGetAllCommand clusteredGetAllCommand = (ClusteredGetAllCommand) c;
        clusteredGetAllCommand.init(
            icf,
            this,
            entryFactory,
            interceptorChain,
            txTable,
            configuration.dataContainer().keyEquivalence());
        break;
      case StreamRequestCommand.COMMAND_ID:
        StreamRequestCommand streamRequestCommand = (StreamRequestCommand) c;
        streamRequestCommand.inject(localStreamManager);
        break;
      case StreamResponseCommand.COMMAND_ID:
        StreamResponseCommand streamResponseCommand = (StreamResponseCommand) c;
        streamResponseCommand.inject(clusterStreamManager);
        break;
      case StreamSegmentResponseCommand.COMMAND_ID:
        StreamSegmentResponseCommand streamSegmentResponseCommand =
            (StreamSegmentResponseCommand) c;
        streamSegmentResponseCommand.inject(clusterStreamManager);
        break;
      case RemoveExpiredCommand.COMMAND_ID:
        RemoveExpiredCommand removeExpiredCommand = (RemoveExpiredCommand) c;
        removeExpiredCommand.init(notifier, configuration);
        break;
      default:
        ModuleCommandInitializer mci = moduleCommandInitializers.get(c.getCommandId());
        if (mci != null) {
          mci.initializeReplicableCommand(c, isRemote);
        } else {
          if (trace) log.tracef("Nothing to initialize for command: %s", c);
        }
    }
  }
  /** @param isRemote true if the command is deserialized and is executed remote. */
  public void initializeReplicableCommand(ReplicableCommand c, boolean isRemote) {
    if (c == null) return;
    switch (c.getCommandId()) {
      case PutKeyValueCommand.COMMAND_ID:
        ((PutKeyValueCommand) c).init(notifier);
        break;
      case PutMapCommand.COMMAND_ID:
        ((PutMapCommand) c).init(notifier);
        break;
      case RemoveCommand.COMMAND_ID:
        ((RemoveCommand) c).init(notifier);
        break;
      case MultipleRpcCommand.COMMAND_ID:
        MultipleRpcCommand rc = (MultipleRpcCommand) c;
        rc.init(interceptorChain, icc);
        if (rc.getCommands() != null)
          for (ReplicableCommand nested : rc.getCommands()) {
            initializeReplicableCommand(nested, false);
          }
        break;
      case SingleRpcCommand.COMMAND_ID:
        SingleRpcCommand src = (SingleRpcCommand) c;
        src.init(interceptorChain, icc);
        if (src.getCommand() != null) initializeReplicableCommand(src.getCommand(), false);

        break;
      case InvalidateCommand.COMMAND_ID:
        InvalidateCommand ic = (InvalidateCommand) c;
        ic.init(notifier);
        break;
      case InvalidateL1Command.COMMAND_ID:
        InvalidateL1Command ilc = (InvalidateL1Command) c;
        ilc.init(configuration, distributionManager, notifier, dataContainer);
        break;
      case PrepareCommand.COMMAND_ID:
        PrepareCommand pc = (PrepareCommand) c;
        pc.init(interceptorChain, icc, txTable);
        pc.initialize(notifier, recoveryManager);
        if (pc.getModifications() != null)
          for (ReplicableCommand nested : pc.getModifications()) {
            initializeReplicableCommand(nested, false);
          }
        pc.markTransactionAsRemote(isRemote);
        if (configuration.isEnableDeadlockDetection() && isRemote) {
          DldGlobalTransaction transaction = (DldGlobalTransaction) pc.getGlobalTransaction();
          transaction.setLocksHeldAtOrigin(pc.getAffectedKeys());
        }
        break;
      case CommitCommand.COMMAND_ID:
        CommitCommand commitCommand = (CommitCommand) c;
        commitCommand.init(interceptorChain, icc, txTable);
        commitCommand.markTransactionAsRemote(isRemote);
        break;
      case RollbackCommand.COMMAND_ID:
        RollbackCommand rollbackCommand = (RollbackCommand) c;
        rollbackCommand.init(interceptorChain, icc, txTable);
        rollbackCommand.markTransactionAsRemote(isRemote);
        break;
      case ClearCommand.COMMAND_ID:
        ClearCommand cc = (ClearCommand) c;
        cc.init(notifier);
        break;
      case ClusteredGetCommand.COMMAND_ID:
        ClusteredGetCommand clusteredGetCommand = (ClusteredGetCommand) c;
        clusteredGetCommand.initialize(icc, this, interceptorChain, distributionManager);
        break;
      case LockControlCommand.COMMAND_ID:
        LockControlCommand lcc = (LockControlCommand) c;
        lcc.init(interceptorChain, icc, txTable);
        lcc.markTransactionAsRemote(isRemote);
        if (configuration.isEnableDeadlockDetection() && isRemote) {
          DldGlobalTransaction gtx = (DldGlobalTransaction) lcc.getGlobalTransaction();
          RemoteTransaction transaction = txTable.getRemoteTransaction(gtx);
          if (transaction != null) {
            if (!configuration.getCacheMode().isDistributed()) {
              Set<Object> keys = txTable.getLockedKeysForRemoteTransaction(gtx);
              GlobalTransaction gtx2 = transaction.getGlobalTransaction();
              ((DldGlobalTransaction) gtx2).setLocksHeldAtOrigin(keys);
              gtx.setLocksHeldAtOrigin(keys);
            } else {
              GlobalTransaction gtx2 = transaction.getGlobalTransaction();
              ((DldGlobalTransaction) gtx2).setLocksHeldAtOrigin(gtx.getLocksHeldAtOrigin());
            }
          }
        }
        break;
      case RehashControlCommand.COMMAND_ID:
        RehashControlCommand rcc = (RehashControlCommand) c;
        rcc.init(distributionManager, configuration, dataContainer, this);
        break;
      case GetInDoubtTransactionsCommand.COMMAND_ID:
        GetInDoubtTransactionsCommand gptx = (GetInDoubtTransactionsCommand) c;
        gptx.init(recoveryManager);
        break;
      case RemoveRecoveryInfoCommand.COMMAND_ID:
        RemoveRecoveryInfoCommand ftx = (RemoveRecoveryInfoCommand) c;
        ftx.init(recoveryManager);
        break;
      case MapReduceCommand.COMMAND_ID:
        MapReduceCommand mrc = (MapReduceCommand) c;
        mrc.init(
            this,
            interceptorChain,
            icc,
            distributionManager,
            cache.getAdvancedCache().getRpcManager().getAddress());
        break;
      case DistributedExecuteCommand.COMMAND_ID:
        DistributedExecuteCommand dec = (DistributedExecuteCommand) c;
        dec.init(cache);
        break;
      case GetInDoubtTxInfoCommand.COMMAND_ID:
        GetInDoubtTxInfoCommand gidTxInfoCommand = (GetInDoubtTxInfoCommand) c;
        gidTxInfoCommand.init(recoveryManager);
        break;
      case CompleteTransactionCommand.COMMAND_ID:
        CompleteTransactionCommand ccc = (CompleteTransactionCommand) c;
        ccc.init(recoveryManager);
        break;
      default:
        ModuleCommandInitializer mci = moduleCommandInitializers.get(c.getCommandId());
        if (mci != null) {
          mci.initializeReplicableCommand(c, isRemote);
        } else {
          if (trace) log.tracef("Nothing to initialize for command: %s", c);
        }
    }
  }
 @Override
 public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command)
     throws Throwable {
   SingleKeyRecipientGenerator skrg = new SingleKeyRecipientGenerator(command.getKey());
   return handleWriteCommand(ctx, command, skrg, false, false);
 }
 @Override
 public CompletableFuture<Void> visitPutKeyValueCommand(
     InvocationContext ctx, PutKeyValueCommand command) throws Throwable {
   return visitWriteCommand(ctx, command, command.getKey());
 }
 @Override
 public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command)
     throws Throwable {
   result.add(command.getKey());
   return null;
 }
 @Override
 public final CompletableFuture<Void> visitPutKeyValueCommand(
     InvocationContext ctx, PutKeyValueCommand command) throws Throwable {
   wrapEntryForPutIfNeeded(ctx, command);
   return setSkipRemoteGetsAndInvokeNextForDataCommand(ctx, command, command.getMetadata());
 }