final void acknowledge(
      ConnectionContext context,
      final TopicMessageStore destination,
      final String clientId,
      final String subscriptionName,
      final MessageId messageId,
      final MessageAck ack)
      throws IOException {

    if (ack.isInTransaction()) {
      if (ack.getTransactionId().isXATransaction()
          || theStore.isConcurrentStoreAndDispatchTransactions() == false) {
        destination.acknowledge(context, clientId, subscriptionName, messageId, ack);
      } else {
        Tx tx = getTx(ack.getTransactionId());
        tx.add(
            new RemoveMessageCommand(context) {
              public MessageAck getMessageAck() {
                return ack;
              }

              public Future<Object> run(ConnectionContext ctx) throws IOException {
                destination.acknowledge(ctx, clientId, subscriptionName, messageId, ack);
                return AbstractMessageStore.FUTURE;
              }
            });
      }
    } else {
      destination.acknowledge(context, clientId, subscriptionName, messageId, ack);
    }
  }
  final void removeAsyncMessage(
      ConnectionContext context, final MessageStore destination, final MessageAck ack)
      throws IOException {

    if (ack.isInTransaction()) {
      if (ack.getTransactionId().isXATransaction()
          || theStore.isConcurrentStoreAndDispatchTransactions() == false) {
        destination.removeAsyncMessage(context, ack);
      } else {
        Tx tx = getTx(ack.getTransactionId());
        tx.add(
            new RemoveMessageCommand(context) {
              @Override
              public MessageAck getMessageAck() {
                return ack;
              }

              @Override
              public Future<Object> run(ConnectionContext ctx) throws IOException {
                destination.removeMessage(ctx, ack);
                return AbstractMessageStore.FUTURE;
              }
            });
      }
    } else {
      destination.removeAsyncMessage(context, ack);
    }
  }