@Override
 public void rollbackTransaction(ConnectionContext context, TransactionId xid) throws Exception {
   if (isLogAll() || isLogTransactionEvents()) {
     LOG.info("Rolling back Transaction: {}", xid.getTransactionKey());
   }
   super.rollbackTransaction(context, xid);
 }
 @Override
 public void beginTransaction(ConnectionContext context, TransactionId xid) throws Exception {
   if (isLogAll() || isLogTransactionEvents()) {
     LOG.info("Beginning transaction: {}", xid.getTransactionKey());
   }
   super.beginTransaction(context, xid);
 }
 @Override
 public int prepareTransaction(ConnectionContext context, TransactionId xid) throws Exception {
   if (isLogAll() || isLogTransactionEvents()) {
     LOG.info("Preparing transaction: {}", xid.getTransactionKey());
   }
   return super.prepareTransaction(context, xid);
 }
  @Override
  public TransactionId[] getPreparedTransactions(ConnectionContext context) throws Exception {

    TransactionId[] result = super.getPreparedTransactions(context);
    if ((isLogAll() || isLogTransactionEvents()) && result != null) {
      StringBuffer tids = new StringBuffer();
      for (TransactionId tid : result) {
        if (tids.length() > 0) {
          tids.append(", ");
        }
        tids.append(tid.getTransactionKey());
      }
      LOG.info("Prepared transactions: {}", tids);
    }
    return result;
  }
 @Override
 public void forgetTransaction(ConnectionContext context, TransactionId transactionId)
     throws Exception {
   if (isLogAll() || isLogTransactionEvents()) {
     LOG.info("Forgetting transaction: {}", transactionId.getTransactionKey());
   }
   super.forgetTransaction(context, transactionId);
 }
 @Override
 public void commitTransaction(ConnectionContext context, TransactionId xid, boolean onePhase)
     throws Exception {
   if (isLogAll() || isLogTransactionEvents()) {
     LOG.info("Committing transaction: {}", xid.getTransactionKey());
   }
   super.commitTransaction(context, xid, onePhase);
 }
 /**
  * @throws IOException
  * @see org.apache.activemq.store.TransactionStore#rollback(TransactionId)
  */
 public void rollback(TransactionId txid) throws IOException {
   if (txid.isXATransaction() || theStore.isConcurrentStoreAndDispatchTransactions() == false) {
     KahaTransactionInfo info = getTransactionInfo(txid);
     theStore.store(new KahaRollbackCommand().setTransactionInfo(info), false, null, null);
     forgetRecoveredAcks(txid);
   } else {
     inflightTransactions.remove(txid);
   }
 }
 /**
  * @throws IOException
  * @see org.apache.activemq.store.TransactionStore#prepare(TransactionId)
  */
 public void prepare(TransactionId txid) throws IOException {
   KahaTransactionInfo info = getTransactionInfo(txid);
   if (txid.isXATransaction() || theStore.isConcurrentStoreAndDispatchTransactions() == false) {
     theStore.store(new KahaPrepareCommand().setTransactionInfo(info), true, null, null);
   } else {
     Tx tx = inflightTransactions.remove(txid);
     if (tx != null) {
       theStore.store(new KahaPrepareCommand().setTransactionInfo(info), true, null, null);
     }
   }
 }
  public void commit(
      TransactionId txid, boolean wasPrepared, Runnable preCommit, Runnable postCommit)
      throws IOException {
    if (txid != null) {
      if (!txid.isXATransaction() && theStore.isConcurrentStoreAndDispatchTransactions()) {
        if (preCommit != null) {
          preCommit.run();
        }
        Tx tx = inflightTransactions.remove(txid);
        if (tx != null) {
          List<Future<Object>> results = tx.commit();
          boolean doneSomething = false;
          for (Future<Object> result : results) {
            try {
              result.get();
            } catch (InterruptedException e) {
              theStore.brokerService.handleIOException(new IOException(e.getMessage()));
            } catch (ExecutionException e) {
              theStore.brokerService.handleIOException(new IOException(e.getMessage()));
            } catch (CancellationException e) {
            }
            if (!result.isCancelled()) {
              doneSomething = true;
            }
          }
          if (postCommit != null) {
            postCommit.run();
          }
          if (doneSomething) {
            KahaTransactionInfo info = getTransactionInfo(txid);
            theStore.store(new KahaCommitCommand().setTransactionInfo(info), true, null, null);
          }
        } else {
          // The Tx will be null for failed over clients - lets run their post commits
          if (postCommit != null) {
            postCommit.run();
          }
        }

      } else {
        KahaTransactionInfo info = getTransactionInfo(txid);
        theStore.store(
            new KahaCommitCommand().setTransactionInfo(info), true, preCommit, postCommit);
        forgetRecoveredAcks(txid);
      }
    } else {
      LOG.error("Null transaction passed on commit");
    }
  }
  public boolean isInXATransaction() {
    if (transactionId != null && transactionId.isXATransaction()) {
      return true;
    } else {
      synchronized (ENDED_XA_TRANSACTION_CONTEXTS) {
        for (List<TransactionContext> transactions : ENDED_XA_TRANSACTION_CONTEXTS.values()) {
          if (transactions.contains(this)) {
            return true;
          }
        }
      }
    }

    return false;
  }
  public KahaTransactionInfo createTransactionInfo(TransactionId txid) {
    if (txid == null) {
      return null;
    }
    KahaTransactionInfo rc = new KahaTransactionInfo();

    if (txid.isLocalTransaction()) {
      LocalTransactionId t = (LocalTransactionId) txid;
      KahaLocalTransactionId kahaTxId = new KahaLocalTransactionId();
      kahaTxId.setConnectionId(t.getConnectionId().getValue());
      kahaTxId.setTransactionId(t.getValue());
      rc.setLocalTransactionId(kahaTxId);
    } else {
      XATransactionId t = (XATransactionId) txid;
      KahaXATransactionId kahaTxId = new KahaXATransactionId();
      kahaTxId.setBranchQualifier(new Buffer(t.getBranchQualifier()));
      kahaTxId.setGlobalTransactionId(new Buffer(t.getGlobalTransactionId()));
      kahaTxId.setFormatId(t.getFormatId());
      rc.setXaTransactionId(kahaTxId);
    }
    return rc;
  }
 protected void forgetRecoveredAcks(TransactionId txid) throws IOException {
   if (txid.isXATransaction()) {
     XATransactionId xaTid = ((XATransactionId) txid);
     theStore.forgetRecoveredAcks(xaTid.getPreparedAcks());
   }
 }
  public void acknowledge(MessageAck ack) throws Exception {
    MessageId first = ack.getFirstMessageId();
    MessageId lastm = ack.getLastMessageId();
    TransactionId tid = ack.getTransactionId();
    boolean isLocalTx = (tid != null) && tid.isLocalTransaction();
    boolean single = lastm.equals(first);

    MessageInfo mi = null;
    int n = 0;

    if (ack.isIndividualAck()) {
      Iterator<MessageInfo> iter = deliveringRefs.iterator();
      while (iter.hasNext()) {
        mi = iter.next();
        if (mi.amqId.equals(lastm)) {
          n++;
          iter.remove();
          session.getCoreSession().individualAcknowledge(nativeId, mi.nativeId);
          session.getCoreSession().commit();
          break;
        }
      }
    } else if (ack.isRedeliveredAck()) {
      // client tells that this message is for redlivery.
      // do nothing until poisoned.
      n = 1;
    } else if (ack.isPoisonAck()) {
      // send to dlq
      Iterator<MessageInfo> iter = deliveringRefs.iterator();
      boolean firstFound = false;
      while (iter.hasNext()) {
        mi = iter.next();
        if (mi.amqId.equals(first)) {
          n++;
          iter.remove();
          session
              .getCoreSession()
              .moveToDeadLetterAddress(nativeId, mi.nativeId, ack.getPoisonCause());
          session.getCoreSession().commit();
          if (single) {
            break;
          }
          firstFound = true;
        } else if (firstFound || first == null) {
          n++;
          iter.remove();
          session
              .getCoreSession()
              .moveToDeadLetterAddress(nativeId, mi.nativeId, ack.getPoisonCause());
          session.getCoreSession().commit();
          if (mi.amqId.equals(lastm)) {
            break;
          }
        }
      }
    } else if (ack.isDeliveredAck() || ack.isExpiredAck()) {
      // ToDo: implement with tests
      n = 1;
    } else {
      Iterator<MessageInfo> iter = deliveringRefs.iterator();
      boolean firstFound = false;
      while (iter.hasNext()) {
        MessageInfo ami = iter.next();
        if (ami.amqId.equals(first)) {
          n++;
          if (!isLocalTx) {
            iter.remove();
          } else {
            ami.setLocalAcked(true);
          }
          if (single) {
            mi = ami;
            break;
          }
          firstFound = true;
        } else if (firstFound || first == null) {
          n++;
          if (!isLocalTx) {
            iter.remove();
          } else {
            ami.setLocalAcked(true);
          }
          if (ami.amqId.equals(lastm)) {
            mi = ami;
            break;
          }
        }
      }
      if (mi != null && !isLocalTx) {
        session.getCoreSession().acknowledge(nativeId, mi.nativeId);
      }
    }

    acquireCredit(n);
  }
 public boolean isInLocalTransaction() {
   return transactionId != null && transactionId.isLocalTransaction();
 }