use of org.apache.qpid.server.protocol.v1_0.type.transaction.Discharge in project qpid-broker-j by apache.
the class TxnCoordinatorReceivingLinkEndpoint method receiveDelivery.
@Override
protected Error receiveDelivery(Delivery delivery) {
// Only interested in the amqp-value section that holds the message to the coordinator
try (QpidByteBuffer payload = delivery.getPayload()) {
List<EncodingRetainingSection<?>> sections = getSectionDecoder().parseAll(payload);
boolean amqpValueSectionFound = false;
for (EncodingRetainingSection section : sections) {
try {
if (section instanceof AmqpValueSection) {
if (amqpValueSectionFound) {
throw new ConnectionScopedRuntimeException("Received more than one AmqpValue sections");
}
amqpValueSectionFound = true;
Object command = section.getValue();
Session_1_0 session = getSession();
AMQPConnection_1_0<?> connection = session.getConnection();
connection.receivedComplete();
if (command instanceof Declare) {
final IdentifiedTransaction txn = connection.createIdentifiedTransaction();
_createdTransactions.put(txn.getId(), txn.getServerTransaction());
long notificationRepeatPeriod = getSession().getContextValue(Long.class, Session.TRANSACTION_TIMEOUT_NOTIFICATION_REPEAT_PERIOD);
connection.registerTransactionTickers(txn.getServerTransaction(), this::doTimeoutAction, notificationRepeatPeriod);
Declared state = new Declared();
state.setTxnId(Session_1_0.integerToTransactionId(txn.getId()));
updateDisposition(delivery.getDeliveryTag(), state, true);
} else if (command instanceof Discharge) {
Discharge discharge = (Discharge) command;
Error error = discharge(discharge.getTxnId(), Boolean.TRUE.equals(discharge.getFail()));
final DeliveryState outcome;
if (error == null) {
outcome = new Accepted();
} else if (Arrays.asList(getSource().getOutcomes()).contains(Rejected.REJECTED_SYMBOL)) {
final Rejected rejected = new Rejected();
rejected.setError(error);
outcome = rejected;
error = null;
} else {
outcome = null;
}
if (error == null) {
updateDisposition(delivery.getDeliveryTag(), outcome, true);
}
return error;
} else {
throw new ConnectionScopedRuntimeException(String.format("Received unknown command '%s'", command.getClass().getSimpleName()));
}
}
} finally {
section.dispose();
}
}
if (!amqpValueSectionFound) {
throw new ConnectionScopedRuntimeException("Received no AmqpValue section");
}
} catch (AmqpErrorException e) {
return e.getError();
}
return null;
}
use of org.apache.qpid.server.protocol.v1_0.type.transaction.Discharge in project qpid-broker-j by apache.
the class DischargeTest method dischargeUnsettledAfterSenderClose.
@Test
@SpecificationTest(section = "4.4.4.1", description = "Transactional Posting [...]" + " Delivery Sent Unsettled By Controller; Resource Does Not Settle [...]" + " After a successful discharge, the state of unsettled deliveries at the resource MUST" + " reflect the outcome that was applied.")
public void dischargeUnsettledAfterSenderClose() throws Exception {
try (FrameTransport transport = new FrameTransport(getBrokerAdmin()).connect()) {
final Interaction interaction = transport.newInteraction();
interaction.negotiateOpen().begin().consumeResponse(Begin.class).txnAttachCoordinatorLink(UnsignedInteger.ZERO, this::coordinatorAttachExpected).txnDeclare().attachRole(Role.SENDER).attachHandle(UnsignedInteger.ONE).attachTargetAddress(BrokerAdmin.TEST_QUEUE_NAME).attachRcvSettleMode(ReceiverSettleMode.SECOND).attach().consumeResponse(Attach.class).assertLatestResponse(Attach.class, attach -> assumeThat(attach.getRcvSettleMode(), is(equalTo(ReceiverSettleMode.SECOND)))).consumeResponse(Flow.class).transferDeliveryId().transferTransactionalStateFromCurrentTransaction().transferPayloadData(getTestName()).transferHandle(UnsignedInteger.ONE).transfer().consumeResponse(Disposition.class).detachHandle(UnsignedInteger.ONE).detachClose(true).detach().consumeResponse(Detach.class);
interaction.txnDischarge(false);
assertThat(interaction.getCoordinatorLatestDeliveryState(), is(instanceOf(Accepted.class)));
}
final Object receivedMessage = Utils.receiveMessage(getBrokerAdmin(), BrokerAdmin.TEST_QUEUE_NAME);
assertThat(receivedMessage, is(equalTo(getTestName())));
}
use of org.apache.qpid.server.protocol.v1_0.type.transaction.Discharge in project qpid-broker-j by apache.
the class DischargeTest method dischargeSettledAfterSenderDetach.
@Test
@SpecificationTest(section = "4.4.4.1", description = "Transactional Posting [...]" + " Delivery Sent Unsettled By Controller; Resource Settles [...]" + " The resource MUST determine the outcome of the delivery before committing the" + " transaction, and this MUST be communicated to the controller before the acceptance" + " of a successful discharge. The outcome communicated by the resource MUST be associated" + " with the same transaction with which the transfer from controller to resource" + " was associated.")
public void dischargeSettledAfterSenderDetach() throws Exception {
try (FrameTransport transport = new FrameTransport(getBrokerAdmin()).connect()) {
final Interaction interaction = transport.newInteraction();
interaction.negotiateOpen().begin().consumeResponse(Begin.class).txnAttachCoordinatorLink(UnsignedInteger.ZERO, this::coordinatorAttachExpected).txnDeclare().attachRole(Role.SENDER).attachHandle(UnsignedInteger.ONE).attachTargetAddress(BrokerAdmin.TEST_QUEUE_NAME).attach().consumeResponse(Attach.class).consumeResponse(Flow.class).transferDeliveryId().transferTransactionalStateFromCurrentTransaction().transferPayloadData(getTestName()).transferHandle(UnsignedInteger.ONE).transfer().consume(Disposition.class, Flow.class);
interaction.detachHandle(UnsignedInteger.ONE).detach().consumeResponse(Detach.class).txnDischarge(false);
assertThat(interaction.getCoordinatorLatestDeliveryState(), is(instanceOf(Accepted.class)));
}
final Object receivedMessage = Utils.receiveMessage(getBrokerAdmin(), BrokerAdmin.TEST_QUEUE_NAME);
assertThat(receivedMessage, is(equalTo(getTestName())));
}
use of org.apache.qpid.server.protocol.v1_0.type.transaction.Discharge in project qpid-broker-j by apache.
the class DischargeTest method dischargeSettledAfterReceiverDetach.
@Test
@SpecificationTest(section = "4.4.2", description = "Transactional Retirement [...]" + " To associate an outcome with a transaction the controller sends a disposition" + " performative which sets the state of the delivery to a transactional-state with the" + " desired transaction identifier and the outcome to be applied upon a successful discharge.")
public void dischargeSettledAfterReceiverDetach() throws Exception {
try (FrameTransport transport = new FrameTransport(getBrokerAdmin()).connect()) {
final Interaction interaction = transport.newInteraction();
interaction.negotiateOpen().begin().consumeResponse(Begin.class).txnAttachCoordinatorLink(UnsignedInteger.ZERO, this::coordinatorAttachExpected).txnDeclare().attachRole(Role.RECEIVER).attachHandle(UnsignedInteger.ONE).attachSourceAddress(BrokerAdmin.TEST_QUEUE_NAME).attachRcvSettleMode(ReceiverSettleMode.FIRST).attach().consumeResponse(Attach.class).flowNextIncomingIdFromPeerLatestSessionBeginAndDeliveryCount().flowNextOutgoingId(UnsignedInteger.ZERO).flowOutgoingWindow(UnsignedInteger.ZERO).flowIncomingWindow(UnsignedInteger.ONE).flowLinkCredit(UnsignedInteger.ONE).flowHandleFromLinkHandle().flow();
Utils.putMessageOnQueue(getBrokerAdmin(), BrokerAdmin.TEST_QUEUE_NAME, getTestName());
List<Transfer> transfers = interaction.receiveDelivery().getLatestDelivery();
assertThat(transfers, is(notNullValue()));
assertThat(transfers, is(not(empty())));
final UnsignedInteger deliveryId = transfers.get(0).getDeliveryId();
interaction.detach().consumeResponse(Detach.class).dispositionFirst(deliveryId).dispositionTransactionalStateFromCurrentTransaction(new Accepted()).dispositionRole(Role.RECEIVER).disposition().txnDischarge(false);
assertThat(interaction.getCoordinatorLatestDeliveryState(), is(instanceOf(Accepted.class)));
interaction.doCloseConnection();
}
String secondMessage = getTestName() + "_2";
Utils.putMessageOnQueue(getBrokerAdmin(), BrokerAdmin.TEST_QUEUE_NAME, secondMessage);
Object receivedMessage = Utils.receiveMessage(getBrokerAdmin(), BrokerAdmin.TEST_QUEUE_NAME);
assertThat(receivedMessage, is(equalTo(secondMessage)));
}
use of org.apache.qpid.server.protocol.v1_0.type.transaction.Discharge in project qpid-broker-j by apache.
the class TransactionalTransferTest method receiveTransactionalRetirementDispositionFailsDueToUnknownTransactionId.
@Test
@SpecificationTest(section = "4.4.2", description = "Transactional Retirement[...]" + " To associate an outcome with a transaction the controller" + " sends a disposition performative which sets the state" + " of the delivery to a transactional-state with the desired" + " transaction identifier and the outcome to be applied" + " upon a successful discharge.")
public void receiveTransactionalRetirementDispositionFailsDueToUnknownTransactionId() throws Exception {
Utils.putMessageOnQueue(getBrokerAdmin(), BrokerAdmin.TEST_QUEUE_NAME, getTestName());
try (FrameTransport transport = new FrameTransport(getBrokerAdmin()).connect()) {
final Interaction interaction = transport.newInteraction();
List<Transfer> transfers = interaction.negotiateOpen().begin().consumeResponse(Begin.class).txnAttachCoordinatorLink(UnsignedInteger.ZERO, this::coordinatorAttachExpected).txnDeclare().attachRole(Role.RECEIVER).attachHandle(UnsignedInteger.ONE).attachSourceAddress(BrokerAdmin.TEST_QUEUE_NAME).attachRcvSettleMode(ReceiverSettleMode.FIRST).attach().consumeResponse(Attach.class).flowIncomingWindow(UnsignedInteger.ONE).flowNextIncomingIdFromPeerLatestSessionBeginAndDeliveryCount().flowOutgoingWindow(UnsignedInteger.ZERO).flowNextOutgoingId(UnsignedInteger.ZERO).flowLinkCredit(UnsignedInteger.ONE).flowHandleFromLinkHandle().flow().receiveDelivery().getLatestDelivery();
UnsignedInteger deliveryId = transfers.get(0).getDeliveryId();
assertThat(deliveryId, is(notNullValue()));
Object data = interaction.decodeLatestDelivery().getDecodedLatestDelivery();
assertThat(data, is(equalTo(getTestName())));
ErrorCarryingFrameBody response = interaction.dispositionSettled(true).dispositionRole(Role.RECEIVER).dispositionTransactionalState(integerToBinary(Integer.MAX_VALUE), new Accepted()).dispositionFirst(deliveryId).disposition().consume(ErrorCarryingFrameBody.class, Flow.class);
final Error error = response.getError();
assertThat(error, is(notNullValue()));
assertThat(error.getCondition(), equalTo(TransactionError.UNKNOWN_ID));
} finally {
assertThat(Utils.receiveMessage(getBrokerAdmin(), BrokerAdmin.TEST_QUEUE_NAME), is(equalTo(getTestName())));
}
}
Aggregations