protected DemandSubscription doCreateDemandSubscription(ConsumerInfo info) throws IOException { DemandSubscription result = new DemandSubscription(info); result.getLocalInfo().setConsumerId(new ConsumerId(localSessionInfo.getSessionId(), consumerIdGenerator.getNextSequenceId())); if (info.getDestination().isTemporary()) { // reset the local connection Id ActiveMQTempDestination dest = (ActiveMQTempDestination) result.getLocalInfo().getDestination(); dest.setConnectionId(localConnectionInfo.getConnectionId().toString()); } if (configuration.isDecreaseNetworkConsumerPriority()) { byte priority = (byte) configuration.getConsumerPriorityBase(); if (info.getBrokerPath() != null && info.getBrokerPath().length > 1) { // The longer the path to the consumer, the less it's consumer priority. priority -= info.getBrokerPath().length + 1; } result.getLocalInfo().setPriority(priority); LOG.debug("{} using priority: {} for subscription: {}", new Object[]{configuration.getBrokerName(), priority, info}); } configureDemandSubscription(info, result); return result; }
DestinationFilter filter = DestinationFilter.parseFilter(ds.getLocalInfo().getDestination()); if (canConduit(ds) && filter.matches(info.getDestination())) { LOG.debug("{} {} with ids {} matched (add interest) {}", new Object[]{ ds.add(info.getConsumerId()); if (isForcedDurable) { forcedDurableRemoteId.add(info.getConsumerId()); ds.addForcedDurableConsumer(info.getConsumerId()); addProxyNetworkSubscriptionClientId(ds, info.getClientId(), info.getSubscriptionName()); } else { ds.getDurableRemoteSubs().add(new SubscriptionInfo(info.getClientId(), info.getSubscriptionName()));
final MessageDispatch md = (MessageDispatch) command; final DemandSubscription sub = subscriptionMapByLocalId.get(md.getConsumerId()); if (sub != null && md.getMessage() != null && sub.incrementOutstandingResponses()) { localBroker.oneway(new MessageAck(md, MessageAck.INDIVIDUAL_ACK_TYPE, 1)); } finally { sub.decrementOutstandingResponses(); sub.decrementOutstandingResponses(); networkBridgeStatistics.getDequeues().increment(); } finally { sub.decrementOutstandingResponses();
@Override public void run() { sub.waitForCompletion(); try { localBroker.oneway(sub.getLocalInfo().createRemoveCommand()); } catch (IOException e) { LOG.warn("failed to deliver remove command for local subscription, for remote {}", sub.getRemoteInfo().getConsumerId(), e); } } });
private void undoMapRegistration(DemandSubscription sub) { subscriptionMapByLocalId.remove(sub.getLocalInfo().getConsumerId()); subscriptionMapByRemoteId.remove(sub.getRemoteInfo().getConsumerId()); }
private boolean canConduit(DemandSubscription ds) { return ds.isStaticallyIncluded() || ds.getRemoteInfo().getDestination().isTopic() || !ds.getRemoteInfo().isNetworkSubscription() || (ds.getRemoteInfo().getDestination().isQueue() && configuration.isConduitNetworkQueueSubscriptions()); }
protected void configureDemandSubscription(ConsumerInfo info, DemandSubscription sub) throws IOException { if (AdvisorySupport.isConsumerAdvisoryTopic(info.getDestination()) || AdvisorySupport.isVirtualDestinationConsumerAdvisoryTopic(info.getDestination())) { sub.getLocalInfo().setDispatchAsync(true); } else { sub.getLocalInfo().setDispatchAsync(configuration.isDispatchAsync()); } configureConsumerPrefetch(sub.getLocalInfo()); subscriptionMapByLocalId.put(sub.getLocalInfo().getConsumerId(), sub); subscriptionMapByRemoteId.put(sub.getRemoteInfo().getConsumerId(), sub); sub.setNetworkBridgeFilter(createNetworkBridgeFilter(info)); if (!info.isDurable()) { // This works for now since we use a VM connection to the local broker. // may need to change if we ever subscribe to a remote broker. sub.getLocalInfo().setAdditionalPredicate(sub.getNetworkBridgeFilter()); } else { sub.setLocalDurableSubscriber(new SubscriptionInfo(info.getClientId(), info.getSubscriptionName())); } }
private void cleanupDurableSub(final DemandSubscription ds, Iterator<DemandSubscription> i) throws IOException { if (ds != null && ds.getLocalDurableSubscriber() != null && ds.getDurableRemoteSubs().isEmpty() && ds.getForcedDurableConsumersSize() == 0) { // deactivate subscriber RemoveInfo removeInfo = new RemoveInfo(ds.getLocalInfo().getConsumerId()); localBroker.oneway(removeInfo); // remove subscriber RemoveSubscriptionInfo sending = new RemoveSubscriptionInfo(); sending.setClientId(localClientId); sending.setSubscriptionName(ds.getLocalDurableSubscriber().getSubscriptionName()); sending.setConnectionId(this.localConnectionInfo.getConnectionId()); localBroker.oneway(sending); //remove subscriber from map i.remove(); } }
@Override protected void removeDemandSubscription(ConsumerId id) throws IOException { List<DemandSubscription> tmpList = new ArrayList<DemandSubscription>(); for (DemandSubscription ds : subscriptionMapByLocalId.values()) { if (ds.remove(id)) { LOG.debug("{} on {} from {} removed interest for: {} from {}", new Object[]{ configuration.getBrokerName(), localBroker, remoteBrokerName, id, ds }); } if (ds.isEmpty()) { tmpList.add(ds); } } for (DemandSubscription ds : tmpList) { removeSubscription(ds); LOG.debug("{} on {} from {} removed {}", new Object[]{ configuration.getBrokerName(), localBroker, remoteBrokerName, ds }); } } }
protected void addSubscription(DemandSubscription sub) throws IOException { if (sub != null) { localBroker.oneway(sub.getLocalInfo()); } }
private boolean suppressMessageDispatch(MessageDispatch md, DemandSubscription sub) throws Exception { boolean suppress = false; // for durable subs, suppression via filter leaves dangling acks so we // need to check here and allow the ack irrespective if (sub.getLocalInfo().isDurable()) { NonCachedMessageEvaluationContext messageEvalContext = new NonCachedMessageEvaluationContext(); messageEvalContext.setMessageReference(md.getMessage()); messageEvalContext.setDestination(md.getDestination()); suppress = !sub.getNetworkBridgeFilter().matches(messageEvalContext); } return suppress; }
protected void addConsumerInfo(final ConsumerInfo consumerInfo) throws IOException { ConsumerInfo info = consumerInfo.copy(); addRemoteBrokerToBrokerPath(info); DemandSubscription sub = createDemandSubscription(info); if (sub != null) { if (duplicateSuppressionIsRequired(sub)) { undoMapRegistration(sub); } else { if (consumerInfo.isDurable()) { //Handle the demand generated by proxy network subscriptions //The broker path is case is normal if (isProxyNSConsumerBrokerPath(sub.getRemoteInfo()) && info.getSubscriptionName() != null && info.getSubscriptionName().startsWith(DURABLE_SUB_PREFIX)) { final BrokerId[] path = info.getBrokerPath(); addProxyNetworkSubscriptionBrokerPath(sub, path, consumerInfo.getSubscriptionName()); //This is the durable sync case on broker restart } else if (isProxyNSConsumerClientId(sub.getRemoteInfo().getClientId()) && isProxyBridgeSubscription(info.getClientId(), info.getSubscriptionName())) { addProxyNetworkSubscriptionClientId(sub, sub.getRemoteInfo().getClientId(), consumerInfo.getSubscriptionName()); } else { sub.getDurableRemoteSubs().add(new SubscriptionInfo(sub.getRemoteInfo().getClientId(), consumerInfo.getSubscriptionName())); } } addSubscription(sub); LOG.debug("{} new demand subscription: {}", configuration.getBrokerName(), sub); } } }
public boolean incrementOutstandingResponses() { dispatched.incrementAndGet(); if (activeWaiter.get()) { decrementOutstandingResponses(); return false; } return true; }
protected boolean removeDemandSubscriptionByLocalId(ConsumerId consumerId) { boolean removeDone = false; DemandSubscription sub = subscriptionMapByLocalId.get(consumerId); if (sub != null) { try { removeDemandSubscription(sub.getRemoteInfo().getConsumerId()); removeDone = true; } catch (IOException e) { LOG.debug("removeDemandSubscriptionByLocalId failed for localId: {}", consumerId, e); } } return removeDone; }
@Override protected void removeDemandSubscription(ConsumerId id) throws IOException { List<DemandSubscription> tmpList = new ArrayList<DemandSubscription>(); for (Iterator i = subscriptionMapByLocalId.values().iterator(); i.hasNext();) { DemandSubscription ds = (DemandSubscription)i.next(); if (ds.remove(id)) { if (LOG.isDebugEnabled()) { LOG.debug(configuration.getBrokerName() + " removing interest in sub on " + localBroker + " from " + remoteBrokerName + " : sub: " + id + " existing matched sub: " + ds.getRemoteInfo()); } } if (ds.isEmpty()) { tmpList.add(ds); } } for (Iterator<DemandSubscription> i = tmpList.iterator(); i.hasNext();) { DemandSubscription ds = i.next(); removeSubscription(ds); if (LOG.isDebugEnabled()) { LOG.debug(configuration.getBrokerName() + " removing sub on " + localBroker + " from " + remoteBrokerName + " : " + ds.getRemoteInfo()); } } }
protected boolean addToAlreadyInterestedConsumers(ConsumerInfo info) { // search through existing subscriptions and see if we have a match boolean matched = false; for (Iterator i = subscriptionMapByLocalId.values().iterator(); i.hasNext();) { DemandSubscription ds = (DemandSubscription)i.next(); DestinationFilter filter = DestinationFilter.parseFilter(ds.getLocalInfo().getDestination()); if (filter.matches(info.getDestination())) { if (LOG.isDebugEnabled()) { LOG.debug(configuration.getBrokerName() + " matched (add interest) to exsting sub for: " + ds.getRemoteInfo() + " with sub: " + info.getConsumerId()); } // add the interest in the subscription // ds.add(ds.getRemoteInfo().getConsumerId()); if (checkPaths(info.getBrokerPath(), ds.getRemoteInfo().getBrokerPath())) { ds.add(info.getConsumerId()); } matched = true; // continue - we want interest to any existing // DemandSubscriptions } } return matched; }
DemandSubscription sub = createDemandSubscription(dest, subName); if (sub != null) { sub.getLocalInfo().setSubscriptionName(getSubscriberName(dest)); sub.setStaticallyIncluded(true); addSubscription(sub); break;
@Override protected DemandSubscription createDemandSubscription(ConsumerInfo info) throws IOException { boolean isForcedDurable = NetworkBridgeUtils.isForcedDurable(info, dynamicallyIncludedDestinations, staticallyIncludedDestinations); if (addToAlreadyInterestedConsumers(info, isForcedDurable)) { return null; // don't want this subscription added } //add our original id to ourselves info.addNetworkConsumerId(info.getConsumerId()); ConsumerId forcedDurableId = isForcedDurable ? info.getConsumerId() : null; if(info.isDurable() || isForcedDurable) { // set the subscriber name to something reproducible info.setSubscriptionName(getSubscriberName(info.getDestination())); // and override the consumerId with something unique so that it won't // be removed if the durable subscriber (at the other end) goes away info.setConsumerId(new ConsumerId(localSessionInfo.getSessionId(), consumerIdGenerator.getNextSequenceId())); } info.setSelector(null); DemandSubscription demandSubscription = doCreateDemandSubscription(info); if (forcedDurableId != null) { demandSubscription.addForcedDurableConsumer(forcedDurableId); forcedDurableRemoteId.add(forcedDurableId); } return demandSubscription; }
protected void configureDemandSubscription(ConsumerInfo info, DemandSubscription sub) throws IOException { if (AdvisorySupport.isConsumerAdvisoryTopic(info.getDestination()) || AdvisorySupport.isVirtualDestinationConsumerAdvisoryTopic(info.getDestination())) { sub.getLocalInfo().setDispatchAsync(true); } else { sub.getLocalInfo().setDispatchAsync(configuration.isDispatchAsync()); } configureConsumerPrefetch(sub.getLocalInfo()); subscriptionMapByLocalId.put(sub.getLocalInfo().getConsumerId(), sub); subscriptionMapByRemoteId.put(sub.getRemoteInfo().getConsumerId(), sub); sub.setNetworkBridgeFilter(createNetworkBridgeFilter(info)); if (!info.isDurable()) { // This works for now since we use a VM connection to the local broker. // may need to change if we ever subscribe to a remote broker. sub.getLocalInfo().setAdditionalPredicate(sub.getNetworkBridgeFilter()); } else { sub.setLocalDurableSubscriber(new SubscriptionInfo(info.getClientId(), info.getSubscriptionName())); } }
protected void removeSubscription(final DemandSubscription sub) throws IOException { if (sub != null) { LOG.trace("{} remove local subscription: {} for remote {}", new Object[]{configuration.getBrokerName(), sub.getLocalInfo().getConsumerId(), sub.getRemoteInfo().getConsumerId()}); // ensure not available for conduit subs pending removal subscriptionMapByLocalId.remove(sub.getLocalInfo().getConsumerId()); subscriptionMapByRemoteId.remove(sub.getRemoteInfo().getConsumerId()); // continue removal in separate thread to free up tshis thread for outstanding responses // Serialize with removeDestination operations so that removeSubs are serialized with // removeDestinations such that all removeSub advisories are generated serialExecutor.execute(new Runnable() { @Override public void run() { sub.waitForCompletion(); try { localBroker.oneway(sub.getLocalInfo().createRemoveCommand()); } catch (IOException e) { LOG.warn("failed to deliver remove command for local subscription, for remote {}", sub.getRemoteInfo().getConsumerId(), e); } } }); } }