Eric Shu created GEODE-1491:
-------------------------------

             Summary: A rollback command could fail with IllegalStateException 
if the client failed over and the transaction has been rolled back.
                 Key: GEODE-1491
                 URL: https://issues.apache.org/jira/browse/GEODE-1491
             Project: Geode
          Issue Type: Bug
          Components: transactions
            Reporter: Eric Shu


{noformat}
The TXManagerImpl rollback() method executes the followings.
    setTXState(null);
    tx.rollback();
    saveTXStateForClientFailover(tx);
    cleanup(tx.getTransactionId());
    noteRollbackSuccess(opStart, lifeTime, tx);

In saveTXStateForClientFailover(), the txid is put into failovermap for 
failover operation. However as it is a rollback, tx.getCommitMessage() returns 
null.
  private void saveTXStateForClientFailover(TXStateProxy tx) {
    if (tx.isOnBehalfOfClient() && tx.isRealDealLocal()) {
      failoverMap.put(tx.getTxId(), tx.getCommitMessage());
      if (logger.isDebugEnabled()) {
        logger.debug("TX: storing client initiated transaction:{}; now there 
are {} entries in the failoverMap",
            tx.getTxId(), failoverMap.size());
      }
    }
  }

If the proxyserver send the rollback message to the host server, but the client 
then failover to another proxy. The retry of rollback checks to see if the 
transaction is completed, before retries the rollback operation.
  @Override
  protected boolean operateOnTx(TXId txId,DistributionManager dm) {
    GemFireCacheImpl cache = GemFireCacheImpl.getInstance();
    if (cache == null) {
      throw new 
CacheClosedException(LocalizedStrings.CacheFactory_A_CACHE_HAS_NOT_YET_BEEN_CREATED.toLocalizedString());
    }
    TXManagerImpl txMgr = cache.getTXMgr();
    if (logger.isDebugEnabled()) {
      logger.debug("TX: Rolling back :{}", txId);
    }
    try {
      if (!txMgr.isHostedTxRecentlyCompleted(txId)) {
        txMgr.rollback();
      }
    } finally {
      txMgr.removeHostedTXState(txId);
    }
    return true;
  }

The isHostedTxRecentlyCompleted() only checks if the transaction completed with 
a commit message.
  public boolean isHostedTxRecentlyCompleted(TXId txId) {
    TXCommitMessage msg = failoverMap.remove(txId);
    if (msg != null) {
      failoverMap.put(txId, msg);
      return true;
    }
    return false;
}
This could leads to a rollback command from a client failed with 
IllegalStateException: Thread does not have an active transaction 
{noformat}



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to