@Override
 public void fail(Object msgId) {
   TransactionAttempt tx = (TransactionAttempt) msgId;
   TransactionStatus stored = _activeTx.remove(tx.getTransactionId());
   if (stored != null && tx.equals(stored.attempt)) {
     _activeTx.tailMap(tx.getTransactionId()).clear();
     sync();
   }
 }
 @Override
 public void ack(Object msgId) {
   TransactionAttempt tx = (TransactionAttempt) msgId;
   TransactionStatus status = _activeTx.get(tx.getTransactionId());
   if (status != null && tx.equals(status.attempt)) {
     if (status.status == AttemptStatus.PROCESSING) {
       status.status = AttemptStatus.PROCESSED;
     } else if (status.status == AttemptStatus.COMMITTING) {
       _activeTx.remove(tx.getTransactionId());
       _coordinatorState.cleanupBefore(tx.getTransactionId());
       _currTransaction = nextTransactionId(tx.getTransactionId());
       _state.setData(CURRENT_TX, _currTransaction);
     }
     sync();
   }
 }
 @Override
 public String toString() {
   return attempt.toString() + " <" + status.toString() + ">";
 }