Search in sources :

Example 1 with Declared

use of org.apache.qpid.proton.amqp.transaction.Declared in project activemq-artemis by apache.

the class ProtonTransactionHandler method onMessage.

@Override
public void onMessage(Delivery delivery) throws ActiveMQAMQPException {
    final Receiver receiver;
    try {
        receiver = ((Receiver) delivery.getLink());
        if (!delivery.isReadable()) {
            return;
        }
        ByteBuffer buffer;
        MessageImpl msg;
        connection.lock();
        try {
            // transaction declare and discahrge operations.
            if (receiver.getCredit() < amqpLowMark) {
                receiver.flow(amqpCredit);
            }
            // the incoming request is to big just use a scratch buffer.
            if (delivery.available() > DECODE_BUFFER.capacity()) {
                buffer = ByteBuffer.allocate(delivery.available());
            } else {
                buffer = (ByteBuffer) DECODE_BUFFER.clear();
            }
            // Update Buffer for the next incoming command.
            buffer.limit(receiver.recv(buffer.array(), buffer.arrayOffset(), buffer.capacity()));
            receiver.advance();
            msg = decodeMessage(buffer);
        } finally {
            connection.unlock();
        }
        Object action = ((AmqpValue) msg.getBody()).getValue();
        if (action instanceof Declare) {
            Binary txID = sessionSPI.newTransaction();
            Declared declared = new Declared();
            declared.setTxnId(txID);
            IOCallback ioAction = new IOCallback() {

                @Override
                public void done() {
                    connection.lock();
                    try {
                        delivery.settle();
                        delivery.disposition(declared);
                    } finally {
                        connection.unlock();
                        connection.flush();
                    }
                }

                @Override
                public void onError(int errorCode, String errorMessage) {
                }
            };
            sessionSPI.afterIO(ioAction);
        } else if (action instanceof Discharge) {
            Discharge discharge = (Discharge) action;
            Binary txID = discharge.getTxnId();
            ProtonTransactionImpl tx = (ProtonTransactionImpl) sessionSPI.getTransaction(txID, true);
            tx.discharge();
            IOCallback ioAction = new IOCallback() {

                @Override
                public void done() {
                    connection.lock();
                    try {
                        delivery.settle();
                        delivery.disposition(new Accepted());
                    } finally {
                        connection.unlock();
                        connection.flush();
                    }
                }

                @Override
                public void onError(int errorCode, String errorMessage) {
                }
            };
            if (discharge.getFail()) {
                sessionSPI.withinContext(() -> tx.rollback());
                sessionSPI.afterIO(ioAction);
            } else {
                sessionSPI.withinContext(() -> tx.commit());
                sessionSPI.afterIO(ioAction);
            }
        }
    } catch (ActiveMQAMQPException amqpE) {
        log.warn(amqpE.getMessage(), amqpE);
        connection.lock();
        try {
            delivery.settle();
            delivery.disposition(createRejected(amqpE.getAmqpError(), amqpE.getMessage()));
        } finally {
            connection.unlock();
        }
        connection.flush();
    } catch (Throwable e) {
        log.warn(e.getMessage(), e);
        connection.lock();
        try {
            delivery.settle();
            delivery.disposition(createRejected(Symbol.getSymbol("failed"), e.getMessage()));
        } finally {
            connection.unlock();
        }
        connection.flush();
    }
}
Also used : Receiver(org.apache.qpid.proton.engine.Receiver) Declare(org.apache.qpid.proton.amqp.transaction.Declare) ByteBuffer(java.nio.ByteBuffer) IOCallback(org.apache.activemq.artemis.core.io.IOCallback) AmqpValue(org.apache.qpid.proton.amqp.messaging.AmqpValue) Declared(org.apache.qpid.proton.amqp.transaction.Declared) Discharge(org.apache.qpid.proton.amqp.transaction.Discharge) Accepted(org.apache.qpid.proton.amqp.messaging.Accepted) ActiveMQAMQPException(org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPException) Binary(org.apache.qpid.proton.amqp.Binary) MessageImpl(org.apache.qpid.proton.message.impl.MessageImpl)

Example 2 with Declared

use of org.apache.qpid.proton.amqp.transaction.Declared in project activemq-artemis by apache.

the class AmqpTransactionCoordinator method processDeliveryUpdates.

@Override
public void processDeliveryUpdates(AmqpConnection connection, Delivery delivery) throws IOException {
    try {
        Iterator<Delivery> deliveries = pendingDeliveries.iterator();
        while (deliveries.hasNext()) {
            Delivery pendingDelivery = deliveries.next();
            if (!pendingDelivery.remotelySettled()) {
                continue;
            }
            DeliveryState state = pendingDelivery.getRemoteState();
            AmqpTransactionId txId = (AmqpTransactionId) pendingDelivery.getContext();
            AsyncResult pendingRequest = pendingRequests.get(txId);
            if (pendingRequest == null) {
                throw new IllegalStateException("Pending tx operation with no pending request");
            }
            if (state instanceof Declared) {
                LOG.debug("New TX started: {}", txId.getTxId());
                Declared declared = (Declared) state;
                txId.setRemoteTxId(declared.getTxnId());
                pendingRequest.onSuccess();
            } else if (state instanceof Rejected) {
                LOG.debug("Last TX request failed: {}", txId.getTxId());
                Rejected rejected = (Rejected) state;
                Exception cause = AmqpSupport.convertToException(rejected.getError());
                JMSException failureCause = null;
                if (txId.isCommit()) {
                    failureCause = new TransactionRolledBackException(cause.getMessage());
                } else {
                    failureCause = new JMSException(cause.getMessage());
                }
                pendingRequest.onFailure(failureCause);
            } else {
                LOG.debug("Last TX request succeeded: {}", txId.getTxId());
                pendingRequest.onSuccess();
            }
            // Clear state data
            pendingDelivery.settle();
            pendingRequests.remove(txId);
            deliveries.remove();
        }
        super.processDeliveryUpdates(connection, delivery);
    } catch (Exception e) {
        throw IOExceptionSupport.create(e);
    }
}
Also used : IllegalStateException(javax.jms.IllegalStateException) DeliveryState(org.apache.qpid.proton.amqp.transport.DeliveryState) JMSException(javax.jms.JMSException) TransactionRolledBackException(javax.jms.TransactionRolledBackException) Delivery(org.apache.qpid.proton.engine.Delivery) Rejected(org.apache.qpid.proton.amqp.messaging.Rejected) AsyncResult(org.apache.activemq.transport.amqp.client.util.AsyncResult) Declared(org.apache.qpid.proton.amqp.transaction.Declared) BufferOverflowException(java.nio.BufferOverflowException) IOException(java.io.IOException) IllegalStateException(javax.jms.IllegalStateException) JMSException(javax.jms.JMSException) TransactionRolledBackException(javax.jms.TransactionRolledBackException)

Aggregations

Declared (org.apache.qpid.proton.amqp.transaction.Declared)2 IOException (java.io.IOException)1 BufferOverflowException (java.nio.BufferOverflowException)1 ByteBuffer (java.nio.ByteBuffer)1 IllegalStateException (javax.jms.IllegalStateException)1 JMSException (javax.jms.JMSException)1 TransactionRolledBackException (javax.jms.TransactionRolledBackException)1 IOCallback (org.apache.activemq.artemis.core.io.IOCallback)1 ActiveMQAMQPException (org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPException)1 AsyncResult (org.apache.activemq.transport.amqp.client.util.AsyncResult)1 Binary (org.apache.qpid.proton.amqp.Binary)1 Accepted (org.apache.qpid.proton.amqp.messaging.Accepted)1 AmqpValue (org.apache.qpid.proton.amqp.messaging.AmqpValue)1 Rejected (org.apache.qpid.proton.amqp.messaging.Rejected)1 Declare (org.apache.qpid.proton.amqp.transaction.Declare)1 Discharge (org.apache.qpid.proton.amqp.transaction.Discharge)1 DeliveryState (org.apache.qpid.proton.amqp.transport.DeliveryState)1 Delivery (org.apache.qpid.proton.engine.Delivery)1 Receiver (org.apache.qpid.proton.engine.Receiver)1 MessageImpl (org.apache.qpid.proton.message.impl.MessageImpl)1