use of org.apache.qpid.server.message.MessageInstanceConsumer in project qpid-broker-j by apache.
the class ConsumerTarget_1_0Test method testTTLAdjustedOnSend.
public void testTTLAdjustedOnSend() throws Exception {
final MessageInstanceConsumer comsumer = mock(MessageInstanceConsumer.class);
long ttl = 2000L;
long arrivalTime = System.currentTimeMillis() - 1000L;
final Header header = new Header();
header.setTtl(UnsignedInteger.valueOf(ttl));
final Message_1_0 message = createTestMessage(header, arrivalTime);
final MessageInstance messageInstance = mock(MessageInstance.class);
when(messageInstance.getMessage()).thenReturn(message);
AtomicReference<QpidByteBuffer> payloadRef = new AtomicReference<>();
doAnswer(invocation -> {
final Object[] args = invocation.getArguments();
Transfer transfer = (Transfer) args[0];
QpidByteBuffer transferPayload = transfer.getPayload();
QpidByteBuffer payloadCopy = transferPayload.duplicate();
payloadRef.set(payloadCopy);
return null;
}).when(_sendingLinkEndpoint).transfer(any(Transfer.class), anyBoolean());
_consumerTarget.doSend(comsumer, messageInstance, false);
verify(_sendingLinkEndpoint, times(1)).transfer(any(Transfer.class), anyBoolean());
final List<EncodingRetainingSection<?>> sections;
try (QpidByteBuffer payload = payloadRef.get()) {
sections = new SectionDecoderImpl(_describedTypeRegistry.getSectionDecoderRegistry()).parseAll(payload);
}
Header sentHeader = null;
for (EncodingRetainingSection<?> section : sections) {
if (section instanceof HeaderSection) {
sentHeader = ((HeaderSection) section).getValue();
}
}
assertNotNull("Header is not found", sentHeader);
assertNotNull("Ttl is not set", sentHeader.getTtl());
assertTrue("Unexpected ttl", sentHeader.getTtl().longValue() <= 1000);
}
use of org.apache.qpid.server.message.MessageInstanceConsumer in project qpid-broker-j by apache.
the class AMQChannel method resend.
/**
* Called to resend all outstanding unacknowledged messages to this same channel.
*/
private void resend() {
final Map<Long, MessageConsumerAssociation> msgToRequeue = new LinkedHashMap<>();
final Map<Long, MessageConsumerAssociation> msgToResend = new LinkedHashMap<>();
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Unacknowledged messages: {}", _unacknowledgedMessageMap.size());
}
_unacknowledgedMessageMap.visit(new Visitor() {
@Override
public boolean callback(final long deliveryTag, final MessageConsumerAssociation association) {
if (association.getConsumer().isClosed()) {
// consumer has gone
msgToRequeue.put(deliveryTag, association);
} else {
// Consumer still exists
msgToResend.put(deliveryTag, association);
}
return false;
}
@Override
public void visitComplete() {
}
});
for (Map.Entry<Long, MessageConsumerAssociation> entry : msgToResend.entrySet()) {
long deliveryTag = entry.getKey();
MessageInstance message = entry.getValue().getMessageInstance();
MessageInstanceConsumer consumer = entry.getValue().getConsumer();
// Without any details from the client about what has been processed we have to mark
// all messages in the unacked map as redelivered.
message.setRedelivered();
if (message.makeAcquisitionUnstealable(consumer)) {
message.decrementDeliveryCount();
consumer.getTarget().send(consumer, message, false);
// remove from unacked map - don't want to restore credit though(!)
_unacknowledgedMessageMap.remove(deliveryTag, false);
} else {
msgToRequeue.put(deliveryTag, entry.getValue());
}
}
// Process Messages to Requeue at the front of the queue
for (Map.Entry<Long, MessageConsumerAssociation> entry : msgToRequeue.entrySet()) {
long deliveryTag = entry.getKey();
MessageInstance message = entry.getValue().getMessageInstance();
MessageInstanceConsumer consumer = entry.getValue().getConsumer();
// Amend the delivery counter as the client hasn't seen these messages yet.
message.decrementDeliveryCount();
// here we do wish to restore credit
_unacknowledgedMessageMap.remove(deliveryTag, true);
message.setRedelivered();
message.release(consumer);
}
}
use of org.apache.qpid.server.message.MessageInstanceConsumer in project qpid-broker-j by apache.
the class SendingLinkEndpoint method attachReceived.
@Override
public void attachReceived(final Attach attach) throws AmqpErrorException {
super.attachReceived(attach);
Target target = (Target) attach.getTarget();
Source source = getSource();
if (source == null) {
source = new Source();
Source attachSource = (Source) attach.getSource();
final Modified defaultOutcome = new Modified();
defaultOutcome.setDeliveryFailed(true);
source.setDefaultOutcome(defaultOutcome);
source.setOutcomes(Accepted.ACCEPTED_SYMBOL, Released.RELEASED_SYMBOL, Rejected.REJECTED_SYMBOL);
source.setAddress(attachSource.getAddress());
source.setDynamic(attachSource.getDynamic());
if (Boolean.TRUE.equals(attachSource.getDynamic()) && attachSource.getDynamicNodeProperties() != null) {
Map<Symbol, Object> dynamicNodeProperties = new HashMap<>();
if (attachSource.getDynamicNodeProperties().containsKey(Session_1_0.LIFETIME_POLICY)) {
dynamicNodeProperties.put(Session_1_0.LIFETIME_POLICY, attachSource.getDynamicNodeProperties().get(Session_1_0.LIFETIME_POLICY));
}
source.setDynamicNodeProperties(dynamicNodeProperties);
}
source.setDurable(TerminusDurability.min(attachSource.getDurable(), getLink().getHighestSupportedTerminusDurability()));
source.setExpiryPolicy(attachSource.getExpiryPolicy());
source.setDistributionMode(attachSource.getDistributionMode());
source.setFilter(attachSource.getFilter());
source.setCapabilities(attachSource.getCapabilities());
final SendingDestination destination = getSession().getSendingDestination(getLink(), source);
source.setCapabilities(destination.getCapabilities());
getLink().setSource(source);
prepareConsumerOptionsAndFilters(destination);
}
getLink().setTarget(target);
final MessageInstanceConsumer oldConsumer = getConsumer();
createConsumerTarget();
_resumeAcceptedTransfers.clear();
_resumeFullTransfers.clear();
final NamedAddressSpace addressSpace = getSession().getConnection().getAddressSpace();
// TODO: QPID-7845 : Resuming links is unsupported at the moment. Thus, cleaning up unsettled deliveries unconditionally.
cleanUpUnsettledDeliveries();
getSession().addDeleteTask(_cleanUpUnsettledDeliveryTask);
Map<Binary, OutgoingDelivery> unsettledCopy = new HashMap<>(_unsettled);
Map<Binary, DeliveryState> remoteUnsettled = attach.getUnsettled() == null ? Collections.emptyMap() : new HashMap<>(attach.getUnsettled());
final boolean isUnsettledComplete = !Boolean.TRUE.equals(attach.getIncompleteUnsettled());
for (Map.Entry<Binary, OutgoingDelivery> entry : unsettledCopy.entrySet()) {
Binary deliveryTag = entry.getKey();
final MessageInstance queueEntry = entry.getValue().getMessageInstance();
if (!remoteUnsettled.containsKey(deliveryTag) && isUnsettledComplete) {
queueEntry.setRedelivered();
queueEntry.release(oldConsumer);
_unsettled.remove(deliveryTag);
} else if (remoteUnsettled.get(deliveryTag) instanceof Outcome) {
Outcome outcome = (Outcome) remoteUnsettled.get(deliveryTag);
if (outcome instanceof Accepted) {
if (oldConsumer.acquires()) {
AutoCommitTransaction txn = new AutoCommitTransaction(addressSpace.getMessageStore());
if (queueEntry.acquire() || queueEntry.isAcquired()) {
txn.dequeue(Collections.singleton(queueEntry), new ServerTransaction.Action() {
@Override
public void postCommit() {
queueEntry.delete();
}
@Override
public void onRollback() {
}
});
}
}
} else if (outcome instanceof Released) {
if (oldConsumer.acquires()) {
AutoCommitTransaction txn = new AutoCommitTransaction(addressSpace.getMessageStore());
txn.dequeue(Collections.singleton(queueEntry), new ServerTransaction.Action() {
@Override
public void postCommit() {
queueEntry.release(oldConsumer);
}
@Override
public void onRollback() {
}
});
}
}
// TODO: QPID-7845: Handle rejected and modified outcome
remoteUnsettled.remove(deliveryTag);
_resumeAcceptedTransfers.add(deliveryTag);
} else {
_resumeFullTransfers.add(queueEntry);
// TODO:QPID-7845: exists in receivers map, but not yet got an outcome ... should resend with resume = true
}
}
getConsumerTarget().updateNotifyWorkDesired();
}
use of org.apache.qpid.server.message.MessageInstanceConsumer in project qpid-broker-j by apache.
the class AbstractConsumerTarget method sendNextMessage.
@Override
public boolean sendNextMessage() {
MessageContainer messageContainer = null;
MessageInstanceConsumer consumer = null;
boolean iteratedCompleteList = false;
while (messageContainer == null) {
if (_pullIterator == null || !_pullIterator.hasNext()) {
if (iteratedCompleteList) {
break;
}
iteratedCompleteList = true;
_pullIterator = getConsumers().iterator();
}
if (_pullIterator.hasNext()) {
consumer = _pullIterator.next();
messageContainer = consumer.pullMessage();
}
}
if (messageContainer != null) {
MessageInstance entry = messageContainer.getMessageInstance();
try {
send(consumer, entry, false);
} catch (MessageConversionException mce) {
restoreCredit(entry.getMessage());
final TransactionLogResource owningResource = entry.getOwningResource();
if (owningResource instanceof MessageSource) {
final MessageSource.MessageConversionExceptionHandlingPolicy handlingPolicy = ((MessageSource) owningResource).getMessageConversionExceptionHandlingPolicy();
switch(handlingPolicy) {
case CLOSE:
entry.release(consumer);
throw new ConnectionScopedRuntimeException(String.format("Unable to convert message %s for this consumer", entry.getMessage()), mce);
case ROUTE_TO_ALTERNATE:
if (consumer.acquires()) {
int enqueues = entry.routeToAlternate(null, null);
if (enqueues == 0) {
LOGGER.info("Failed to convert message {} for this consumer because '{}'." + " Message discarded.", entry.getMessage(), mce.getMessage());
} else {
LOGGER.info("Failed to convert message {} for this consumer because '{}'." + " Message routed to alternate.", entry.getMessage(), mce.getMessage());
}
} else {
LOGGER.info("Failed to convert message {} for this browser because '{}'." + " Message skipped.", entry.getMessage(), mce.getMessage());
}
break;
case REJECT:
entry.reject(consumer);
entry.release(consumer);
LOGGER.info("Failed to convert message {} for this consumer because '{}'." + " Message skipped.", entry.getMessage(), mce.getMessage());
break;
default:
throw new ServerScopedRuntimeException("Unrecognised policy " + handlingPolicy);
}
} else {
throw new ConnectionScopedRuntimeException(String.format("Unable to convert message %s for this consumer", entry.getMessage()), mce);
}
} finally {
if (messageContainer.getMessageReference() != null) {
messageContainer.getMessageReference().release();
}
}
return true;
} else {
return false;
}
}
use of org.apache.qpid.server.message.MessageInstanceConsumer in project qpid-broker-j by apache.
the class VirtualHostPropertiesNodeTest method testAddConsumer.
public void testAddConsumer() throws Exception {
final EnumSet<ConsumerOption> options = EnumSet.noneOf(ConsumerOption.class);
final ConsumerTarget target = mock(ConsumerTarget.class);
when(target.allocateCredit(any(ServerMessage.class))).thenReturn(true);
MessageInstanceConsumer consumer = _virtualHostPropertiesNode.addConsumer(target, null, ServerMessage.class, getTestName(), options, 0);
final MessageContainer messageContainer = consumer.pullMessage();
assertNotNull("Could not pull message from VirtualHostPropertyNode", messageContainer);
if (messageContainer.getMessageReference() != null) {
messageContainer.getMessageReference().release();
}
}
Aggregations