use of org.apache.qpid.server.protocol.v1_0.type.messaging.Source in project qpid-broker-j by apache.
the class SendingLinkEndpoint method reattachLink.
@Override
protected void reattachLink(final Attach attach) throws AmqpErrorException {
if (getSource() == null) {
throw new IllegalStateException("Terminus should be set when resuming a Link.");
}
if (attach.getSource() == null) {
throw new IllegalStateException("Attach.getSource should not be null when resuming a Link. That would be recovering the Link.");
}
Source newSource = (Source) attach.getSource();
Source oldSource = getSource();
final SendingDestination destination = getSession().getSendingDestination(getLink(), oldSource);
prepareConsumerOptionsAndFilters(destination);
if (getDestination() instanceof ExchangeSendingDestination && !Boolean.TRUE.equals(newSource.getDynamic())) {
final SendingDestination newDestination = getSession().getSendingDestination(getLink(), newSource);
if (getSession().updateSourceForSubscription(this, newSource, newDestination)) {
setDestination(newDestination);
}
}
attachReceived(attach);
}
use of org.apache.qpid.server.protocol.v1_0.type.messaging.Source in project qpid-broker-j by apache.
the class SendingLinkEndpoint method recoverLink.
@Override
protected void recoverLink(final Attach attach) throws AmqpErrorException {
Source source = getSource();
if (source == null && attach.getDesiredCapabilities() != null) {
List<Symbol> capabilities = Arrays.asList(attach.getDesiredCapabilities());
if (capabilities.contains(Session_1_0.GLOBAL_CAPABILITY) && capabilities.contains(Session_1_0.SHARED_CAPABILITY) && getLinkName().endsWith("|global")) {
NamedAddressSpace namedAddressSpace = getSession().getConnection().getAddressSpace();
Collection<Link_1_0<? extends BaseSource, ? extends BaseTarget>> links = namedAddressSpace.findSendingLinks(ANY_CONTAINER_ID, Pattern.compile("^" + Pattern.quote(getLinkName()) + "$"));
for (Link_1_0<? extends BaseSource, ? extends BaseTarget> link : links) {
BaseSource baseSource = link.getSource();
if (baseSource instanceof Source) {
Source linkSource = (Source) baseSource;
source = new Source(linkSource);
getLink().setSource(source);
break;
}
}
}
}
if (source == null) {
throw new AmqpErrorException(new Error(AmqpError.NOT_FOUND, ""));
}
attach.setSource(source);
receiveAttach(attach);
}
use of org.apache.qpid.server.protocol.v1_0.type.messaging.Source 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.protocol.v1_0.type.messaging.Source in project qpid-broker-j by apache.
the class SendingLinkEndpoint method detach.
@Override
protected void detach(Error error, final boolean close) {
if (_consumerTarget != null) {
_consumerTarget.close();
}
Source source = getSource();
TerminusExpiryPolicy expiryPolicy = source.getExpiryPolicy();
NamedAddressSpace addressSpace = getSession().getConnection().getAddressSpace();
List<Symbol> sourceCapabilities = source.getCapabilities() == null ? Collections.emptyList() : Arrays.asList(source.getCapabilities());
if (close || TerminusExpiryPolicy.LINK_DETACH.equals(expiryPolicy) || ((expiryPolicy == null || TerminusExpiryPolicy.SESSION_END.equals(expiryPolicy)) && getSession().isClosing()) || (TerminusExpiryPolicy.CONNECTION_CLOSE.equals(expiryPolicy) && getSession().getConnection().isClosing())) {
Error closingError = null;
if (getDestination() instanceof ExchangeSendingDestination && addressSpace instanceof QueueManagingVirtualHost) {
cleanUpUnsettledDeliveries();
try {
((QueueManagingVirtualHost) addressSpace).removeSubscriptionQueue(((ExchangeSendingDestination) getDestination()).getQueue().getName());
TerminusDurability sourceDurability = source.getDurable();
if (sourceDurability != null && !TerminusDurability.NONE.equals(sourceDurability) && sourceCapabilities.contains(Session_1_0.SHARED_CAPABILITY) && sourceCapabilities.contains(ExchangeSendingDestination.TOPIC_CAPABILITY)) {
Pattern containerIdPattern = sourceCapabilities.contains(Session_1_0.GLOBAL_CAPABILITY) ? ANY_CONTAINER_ID : Pattern.compile("^" + Pattern.quote(getSession().getConnection().getRemoteContainerId()) + "$");
Pattern linkNamePattern = Pattern.compile("^" + Pattern.quote(getLinkName()) + "\\|?\\d*$");
final Collection<LinkModel> links = addressSpace.findSendingLinks(containerIdPattern, linkNamePattern);
for (LinkModel link : links) {
if (link instanceof Link_1_0) {
((Link_1_0) link).linkClosed();
}
}
}
} catch (AccessControlException e) {
LOGGER.error("Error unregistering subscription", e);
closingError = new Error(AmqpError.NOT_ALLOWED, "Error unregistering subscription");
} catch (IllegalStateException e) {
String message;
if (sourceCapabilities.contains(Session_1_0.SHARED_CAPABILITY) && sourceCapabilities.contains(ExchangeSendingDestination.TOPIC_CAPABILITY)) {
String subscriptionName = getLinkName();
int separator = subscriptionName.indexOf("|");
if (separator > 0) {
subscriptionName = subscriptionName.substring(0, separator);
}
message = "There are active consumers on the shared subscription '" + subscriptionName + "'";
} else {
message = e.getMessage();
}
closingError = new Error(AmqpError.RESOURCE_LOCKED, message);
} catch (NotFoundException e) {
closingError = new Error(AmqpError.NOT_FOUND, e.getMessage());
}
}
if (error == null) {
error = closingError;
} else {
LOGGER.warn("Unexpected error on detaching endpoint {}: {}", getLinkName(), error);
}
} else if (addressSpace instanceof QueueManagingVirtualHost && ((QueueManagingVirtualHost) addressSpace).isDiscardGlobalSharedSubscriptionLinksOnDetach() && sourceCapabilities.contains(Session_1_0.SHARED_CAPABILITY) && sourceCapabilities.contains(Session_1_0.GLOBAL_CAPABILITY) && sourceCapabilities.contains(ExchangeSendingDestination.TOPIC_CAPABILITY)) {
// However, we keep one link (ending with "|global") to perform a null-source lookup upon un-subscription.
if (!getLinkName().endsWith("|global")) {
getLink().linkClosed();
} else {
Pattern linkNamePattern = Pattern.compile("^" + Pattern.quote(getLinkName()) + "$");
final Collection<LinkModel> links = addressSpace.findSendingLinks(ANY_CONTAINER_ID, linkNamePattern);
if (links.size() > 1) {
getLink().linkClosed();
}
}
}
super.detach(error, close);
}
use of org.apache.qpid.server.protocol.v1_0.type.messaging.Source in project qpid-broker-j by apache.
the class Session_1_0 method updateSourceForSubscription.
public boolean updateSourceForSubscription(final SendingLinkEndpoint linkEndpoint, final Source newSource, final SendingDestination newDestination) {
SendingDestination oldDestination = linkEndpoint.getDestination();
if (oldDestination instanceof ExchangeSendingDestination) {
ExchangeSendingDestination oldExchangeDestination = (ExchangeSendingDestination) oldDestination;
String newAddress = newSource.getAddress();
if (newDestination instanceof ExchangeSendingDestination) {
ExchangeSendingDestination newExchangeDestination = (ExchangeSendingDestination) newDestination;
if (oldExchangeDestination.getQueue() != newExchangeDestination.getQueue()) {
Source oldSource = linkEndpoint.getSource();
oldSource.setAddress(newAddress);
oldSource.setFilter(newSource.getFilter());
return true;
}
}
}
return false;
}
Aggregations