use of org.apache.qpid.server.protocol.v1_0.type.messaging.Data in project qpid-broker-j by apache.
the class TransactionalTransferTest method receiveTransactionalAcquisitionDischargeFail.
@Test
@SpecificationTest(section = "4.4.3", description = "Transactional Acquisition[...]In the case of the flow frame," + " the transactional work is not necessarily directly" + " initiated or entirely determined when the flow frame" + " arrives at the resource, but can in fact occur at some " + " later point and in ways not necessarily" + " anticipated by the controller.")
public void receiveTransactionalAcquisitionDischargeFail() throws Exception {
getBrokerAdmin().putMessageOnQueue(BrokerAdmin.TEST_QUEUE_NAME, TEST_MESSAGE_CONTENT);
try (FrameTransport transport = new FrameTransport(_brokerAddress).connect()) {
final Interaction interaction = transport.newInteraction();
final InteractionTransactionalState txnState = interaction.createTransactionalState(UnsignedInteger.ZERO);
interaction.negotiateProtocol().consumeResponse().open().consumeResponse(Open.class).begin().consumeResponse(Begin.class).txnAttachCoordinatorLink(txnState).txnDeclare(txnState).attachRole(Role.RECEIVER).attachHandle(UnsignedInteger.ONE).attachSourceAddress(BrokerAdmin.TEST_QUEUE_NAME).attachRcvSettleMode(ReceiverSettleMode.FIRST).attach().consumeResponse(Attach.class).flowIncomingWindow(UnsignedInteger.ONE).flowNextIncomingId(UnsignedInteger.ZERO).flowOutgoingWindow(UnsignedInteger.ZERO).flowNextOutgoingId(UnsignedInteger.ZERO).flowLinkCredit(UnsignedInteger.ONE).flowHandleFromLinkHandle().flowProperties(Collections.singletonMap(Symbol.valueOf("txn-id"), txnState.getCurrentTransactionId())).flow().receiveDelivery();
List<Transfer> transfers = interaction.getLatestDelivery();
assertThat(transfers.size(), is(equalTo(1)));
Transfer transfer = transfers.get(0);
assertThat(transfer.getState(), is(instanceOf(TransactionalState.class)));
assertThat(((TransactionalState) transfer.getState()).getTxnId(), is(equalTo(txnState.getCurrentTransactionId())));
Object data = interaction.decodeLatestDelivery().getDecodedLatestDelivery();
assertThat(data, is(equalTo(TEST_MESSAGE_CONTENT)));
interaction.dispositionSettled(true).dispositionRole(Role.RECEIVER).dispositionTransactionalState(txnState.getCurrentTransactionId(), new Accepted()).disposition().txnDischarge(txnState, true);
assumeThat(getBrokerAdmin().isQueueDepthSupported(), is(true));
assertThat(getBrokerAdmin().getQueueDepthMessages(BrokerAdmin.TEST_QUEUE_NAME), is(equalTo(1)));
}
}
use of org.apache.qpid.server.protocol.v1_0.type.messaging.Data 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 {
getBrokerAdmin().putMessageOnQueue(BrokerAdmin.TEST_QUEUE_NAME, TEST_MESSAGE_CONTENT);
try (FrameTransport transport = new FrameTransport(_brokerAddress).connect()) {
final Interaction interaction = transport.newInteraction();
final InteractionTransactionalState txnState = interaction.createTransactionalState(UnsignedInteger.ZERO);
List<Transfer> transfers = interaction.negotiateProtocol().consumeResponse().open().consumeResponse(Open.class).begin().consumeResponse(Begin.class).txnAttachCoordinatorLink(txnState).txnDeclare(txnState).attachRole(Role.RECEIVER).attachHandle(UnsignedInteger.ONE).attachSourceAddress(BrokerAdmin.TEST_QUEUE_NAME).attachRcvSettleMode(ReceiverSettleMode.FIRST).attach().consumeResponse(Attach.class).flowIncomingWindow(UnsignedInteger.ONE).flowNextIncomingId(UnsignedInteger.ZERO).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(TEST_MESSAGE_CONTENT)));
Response<?> response = interaction.dispositionSettled(true).dispositionRole(Role.RECEIVER).dispositionTransactionalState(integerToBinary(Integer.MAX_VALUE), new Accepted()).dispositionFirst(deliveryId).disposition().consumeResponse().getLatestResponse();
assertUnknownTransactionIdError(response);
}
}
use of org.apache.qpid.server.protocol.v1_0.type.messaging.Data in project qpid-broker-j by apache.
the class ConsumerTarget_1_0 method doSend.
@Override
public void doSend(final MessageInstanceConsumer consumer, final MessageInstance entry, boolean batch) {
ServerMessage serverMessage = entry.getMessage();
Message_1_0 message;
final MessageConverter<? super ServerMessage, Message_1_0> converter;
if (serverMessage instanceof Message_1_0) {
converter = null;
message = (Message_1_0) serverMessage;
} else {
converter = (MessageConverter<? super ServerMessage, Message_1_0>) MessageConverterRegistry.getConverter(serverMessage.getClass(), Message_1_0.class);
if (converter == null) {
throw new ServerScopedRuntimeException(String.format("Could not find message converter from '%s' to '%s'." + " This is unexpected since we should not try to send if the converter is not present.", serverMessage.getClass(), Message_1_0.class));
}
message = converter.convert(serverMessage, _linkEndpoint.getAddressSpace());
}
Transfer transfer = new Transfer();
try {
QpidByteBuffer bodyContent = message.getContent();
HeaderSection headerSection = message.getHeaderSection();
UnsignedInteger ttl = headerSection == null ? null : headerSection.getValue().getTtl();
if (entry.getDeliveryCount() != 0 || ttl != null) {
Header header = new Header();
if (headerSection != null) {
final Header oldHeader = headerSection.getValue();
header.setDurable(oldHeader.getDurable());
header.setPriority(oldHeader.getPriority());
if (ttl != null) {
long timeSpentOnBroker = System.currentTimeMillis() - message.getArrivalTime();
final long adjustedTtl = Math.max(0L, ttl.longValue() - timeSpentOnBroker);
header.setTtl(UnsignedInteger.valueOf(adjustedTtl));
}
headerSection.dispose();
}
if (entry.getDeliveryCount() != 0) {
header.setDeliveryCount(UnsignedInteger.valueOf(entry.getDeliveryCount()));
}
headerSection = header.createEncodingRetainingSection();
}
List<QpidByteBuffer> payload = new ArrayList<>();
if (headerSection != null) {
payload.add(headerSection.getEncodedForm());
headerSection.dispose();
}
EncodingRetainingSection<?> section;
if ((section = message.getDeliveryAnnotationsSection()) != null) {
payload.add(section.getEncodedForm());
section.dispose();
}
if ((section = message.getMessageAnnotationsSection()) != null) {
payload.add(section.getEncodedForm());
section.dispose();
}
if ((section = message.getPropertiesSection()) != null) {
payload.add(section.getEncodedForm());
section.dispose();
}
if ((section = message.getApplicationPropertiesSection()) != null) {
payload.add(section.getEncodedForm());
section.dispose();
}
payload.add(bodyContent);
if ((section = message.getFooterSection()) != null) {
payload.add(section.getEncodedForm());
section.dispose();
}
try (QpidByteBuffer combined = QpidByteBuffer.concatenate(payload)) {
transfer.setPayload(combined);
}
payload.forEach(QpidByteBuffer::dispose);
byte[] data = new byte[8];
ByteBuffer.wrap(data).putLong(_deliveryTag++);
final Binary tag = new Binary(data);
transfer.setDeliveryTag(tag);
if (_linkEndpoint.isAttached()) {
if (SenderSettleMode.SETTLED.equals(getEndpoint().getSendingSettlementMode())) {
transfer.setSettled(true);
} else {
final UnsettledAction action;
if (_acquires) {
action = new DispositionAction(tag, entry, consumer);
addUnacknowledgedMessage(entry);
} else {
action = new DoNothingAction();
}
_linkEndpoint.addUnsettled(tag, action, entry);
}
if (_transactionId != null) {
TransactionalState state = new TransactionalState();
state.setTxnId(_transactionId);
transfer.setState(state);
}
if (_acquires && _transactionId != null) {
try {
ServerTransaction txn = _linkEndpoint.getTransaction(_transactionId);
txn.addPostTransactionAction(new ServerTransaction.Action() {
@Override
public void postCommit() {
}
@Override
public void onRollback() {
entry.release(consumer);
_linkEndpoint.updateDisposition(tag, null, true);
}
});
} catch (UnknownTransactionException e) {
entry.release(consumer);
getEndpoint().close(new Error(TransactionError.UNKNOWN_ID, e.getMessage()));
return;
}
}
getSession().getAMQPConnection().registerMessageDelivered(message.getSize());
getEndpoint().transfer(transfer, false);
} else {
entry.release(consumer);
}
} finally {
transfer.dispose();
if (converter != null) {
converter.dispose(message);
}
}
}
use of org.apache.qpid.server.protocol.v1_0.type.messaging.Data in project qpid-broker-j by apache.
the class ArrayTypeConstructor method construct.
@Override
public Object[] construct(final QpidByteBuffer in, final ValueHandler handler) throws AmqpErrorException {
int size = read(in);
long remaining = in.remaining();
if (remaining < (long) size) {
throw new AmqpErrorException(AmqpError.DECODE_ERROR, "Insufficient data to decode array - requires %d octects, only %d remaining.", size, remaining);
}
List<Object> rval;
int count = read(in);
TypeConstructor t = handler.readConstructor(in);
rval = new ArrayList<>(count);
for (int i = 0; i < count; i++) {
rval.add(t.construct(in, handler));
}
long expectedRemaining = remaining - size;
long unconsumedBytes = in.remaining() - expectedRemaining;
if (unconsumedBytes > 0) {
final String msg = String.format("Array incorrectly encoded, %d bytes remaining after decoding %d elements", unconsumedBytes, count);
throw new AmqpErrorException(AmqpError.DECODE_ERROR, msg);
} else if (unconsumedBytes < 0) {
final String msg = String.format("Array incorrectly encoded, %d bytes beyond provided size consumed after decoding %d elements", -unconsumedBytes, count);
throw new AmqpErrorException(AmqpError.DECODE_ERROR, msg);
}
if (rval.size() == 0) {
return null;
} else {
return rval.toArray((Object[]) Array.newInstance(rval.get(0).getClass(), rval.size()));
}
}
use of org.apache.qpid.server.protocol.v1_0.type.messaging.Data in project qpid-broker-j by apache.
the class FrameHandler method parse.
@Override
public ProtocolHandler parse(QpidByteBuffer in) {
try {
LOGGER.debug("RECV {} bytes", in.remaining());
Error frameParsingError = null;
int size;
int remaining;
List<ChannelFrameBody> channelFrameBodies = new ArrayList<>();
while ((remaining = in.remaining()) >= 8 && frameParsingError == null) {
size = in.getInt();
if (size < 8) {
frameParsingError = createFramingError("specified frame size %d smaller than minimum frame header size %d", size, 8);
break;
}
if (size > _connectionHandler.getMaxFrameSize()) {
frameParsingError = createFramingError("specified frame size %d larger than maximum frame header size %d", size, _connectionHandler.getMaxFrameSize());
break;
}
if (remaining < size) {
in.position(in.position() - 4);
break;
}
int dataOffset = (in.get() << 2) & 0x3FF;
if (dataOffset < 8) {
frameParsingError = createFramingError("specified frame data offset %d smaller than minimum frame header size %d", dataOffset, 8);
break;
}
if (dataOffset > size) {
frameParsingError = createFramingError("specified frame data offset %d larger than the frame size %d", dataOffset, size);
break;
}
byte type = in.get();
switch(type) {
case 0:
if (_isSasl) {
frameParsingError = createFramingError("received an AMQP frame type when expecting an SASL frame");
}
break;
case 1:
if (!_isSasl) {
frameParsingError = createFramingError("received a SASL frame type when expecting an AMQP frame");
}
break;
default:
frameParsingError = createFramingError("unknown frame type: %d", type);
}
if (frameParsingError != null) {
break;
}
int channel = in.getUnsignedShort();
if (dataOffset != 8) {
in.position(in.position() + dataOffset - 8);
}
try (QpidByteBuffer dup = in.slice()) {
dup.limit(size - dataOffset);
in.position(in.position() + size - dataOffset);
final boolean hasFrameBody = dup.hasRemaining();
Object frameBody;
if (hasFrameBody) {
frameBody = _valueHandler.parse(dup);
if (dup.hasRemaining()) {
if (frameBody instanceof Transfer) {
try (QpidByteBuffer payload = dup.slice()) {
((Transfer) frameBody).setPayload(payload);
}
} else {
frameParsingError = createFramingError("Frame length %d larger than contained frame body %s.", size, frameBody);
break;
}
}
} else {
frameBody = null;
if (_isSasl) {
frameParsingError = createFramingError("Empty (heartbeat) frames are not permitted during SASL negotiation");
break;
}
}
channelFrameBodies.add(new ChannelFrameBody() {
@Override
public int getChannel() {
return channel;
}
@Override
public Object getFrameBody() {
return frameBody;
}
});
if (_isSasl) {
break;
}
} catch (AmqpErrorException ex) {
frameParsingError = ex.getError();
}
}
if (frameParsingError != null) {
_connectionHandler.handleError(frameParsingError);
_errored = true;
} else {
_connectionHandler.receive(channelFrameBodies);
}
} catch (RuntimeException e) {
if (e instanceof ServerScopedRuntimeException) {
throw e;
}
LOGGER.warn("Unexpected exception handling frame", e);
// This exception is unexpected. The up layer should handle error condition gracefully
_connectionHandler.handleError(this.createError(AmqpError.INTERNAL_ERROR, e.toString()));
}
return this;
}
Aggregations