protected void updateStateOnNodesLeaving(Collection<Address> leavers) {
    Set<GlobalTransaction> toKill = new HashSet<GlobalTransaction>();
    for (GlobalTransaction gt : remoteTransactions.keySet()) {
      if (leavers.contains(gt.getAddress())) toKill.add(gt);
    }

    if (toKill.isEmpty())
      log.tracef(
          "No global transactions pertain to originator(s) %s who have left the cluster.", leavers);
    else
      log.tracef(
          "%s global transactions pertain to leavers list %s and need to be killed",
          toKill.size(), leavers);

    for (GlobalTransaction gtx : toKill) {
      log.tracef("Killing remote transaction originating on leaver %s", gtx);
      RollbackCommand rc = new RollbackCommand(cacheName, gtx);
      rc.init(invoker, icc, TransactionTable.this);
      try {
        rc.perform(null);
        log.tracef("Rollback of transaction %s complete.", gtx);
      } catch (Throwable e) {
        log.unableToRollbackGlobalTx(gtx, e);
      }
    }

    log.trace("Completed cleaning transactions originating on leavers");
  }
 private void killTransaction(GlobalTransaction gtx) {
   RollbackCommand rc = new RollbackCommand(cacheName, gtx);
   rc.init(invoker, icf, TransactionTable.this);
   try {
     rc.perform(null);
     if (trace) log.tracef("Rollback of transaction %s complete.", gtx);
   } catch (Throwable e) {
     log.unableToRollbackGlobalTx(gtx, e);
   }
 }
    @Override
    public Object visitRollbackCommand(TxInvocationContext ctx, RollbackCommand command)
        throws Throwable {

      if (!isTransactional()) {
        log.cannotRespondToRollback(command.getGlobalTransaction(), backupCache.getName());
      } else {
        log.tracef("Rolling back remote transaction %s", command.getGlobalTransaction());
        completeTransaction(command.getGlobalTransaction(), false);
      }
      return null;
    }
  public void cleanupStaleTransactions(CacheTopology cacheTopology) {
    int topologyId = cacheTopology.getTopologyId();
    List<Address> members = cacheTopology.getMembers();

    // We only care about transactions originated before this topology update
    if (getMinTopologyId() >= topologyId) return;

    log.tracef(
        "Checking for transactions originated on leavers. Current members are %s, remote transactions: %d",
        members, remoteTransactions.size());
    Set<GlobalTransaction> toKill = new HashSet<GlobalTransaction>();
    for (Map.Entry<GlobalTransaction, RemoteTransaction> e : remoteTransactions.entrySet()) {
      GlobalTransaction gt = e.getKey();
      RemoteTransaction remoteTx = e.getValue();
      log.tracef("Checking transaction %s", gt);
      // The topology id check is needed for joiners
      if (remoteTx.getTopologyId() < topologyId && !members.contains(gt.getAddress())) {
        toKill.add(gt);
      }
    }

    if (toKill.isEmpty()) {
      log.tracef("No global transactions pertain to originator(s) who have left the cluster.");
    } else {
      log.tracef("%s global transactions pertain to leavers and need to be killed", toKill.size());
    }

    for (GlobalTransaction gtx : toKill) {
      log.tracef("Killing remote transaction originating on leaver %s", gtx);
      RollbackCommand rc = new RollbackCommand(cacheName, gtx);
      rc.init(invoker, icc, TransactionTable.this);
      try {
        rc.perform(null);
        log.tracef("Rollback of transaction %s complete.", gtx);
      } catch (Throwable e) {
        log.unableToRollbackGlobalTx(gtx, e);
      }
    }

    log.tracef(
        "Completed cleaning transactions originating on leavers. Remote transactions remaining: %d",
        remoteTransactions.size());
  }
  /** @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);
        }
    }
  }
 public RollbackCommand buildRollbackCommand(GlobalTransaction gtx) {
   RollbackCommand rollbackCommand = new RollbackCommand(gtx);
   rollbackCommand.setCacheName(cacheName);
   return rollbackCommand;
 }