if (contains(path, localBrokerPath[0])) { if (!isPermissableDestination(info.getDestination())) { if (isDuplicateSuppressionOff(info)) { addConsumerInfo(info); } else { synchronized (brokerService.getVmConnectorURI()) { addConsumerInfo(info); if (contains(destInfo.getBrokerPath(), localBrokerPath[0])) { LOG.debug("{} Ignoring destination {} already routed through this broker once", configuration.getBrokerName(), destInfo); return; destInfo.setBrokerPath(appendToBrokerPath(destInfo.getBrokerPath(), getRemoteBrokerPath())); LOG.trace("{} bridging {} destination on {} from {}, destination: {}", new Object[]{ configuration.getBrokerName(), (destInfo.isAddOperation() ? "add" : "remove"), localBroker, remoteBrokerName, destInfo removeDemandSubscription(id); boolean removed = ds.removeForcedDurableConsumer(id); if (removed) { cleanupDurableSub(ds, i); final RemoveSubscriptionInfo info = ((RemoveSubscriptionInfo) data); final SubscriptionInfo subscriptionInfo = new SubscriptionInfo(info.getClientId(), info.getSubscriptionName()); final boolean proxyBridgeSub = isProxyBridgeSubscription(subscriptionInfo.getClientId(), subscriptionInfo.getSubscriptionName()); for (Iterator<DemandSubscription> i = subscriptionMapByLocalId.values().iterator(); i.hasNext(); ) {
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); } } }
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; }
protected void addRemoteBrokerToBrokerPath(ConsumerInfo info) throws IOException { info.setBrokerPath(appendToBrokerPath(info.getBrokerPath(), getRemoteBrokerPath())); }
/** * Subscriptions for these destinations are always created */ protected void setupStaticDestinations() { ActiveMQDestination[] dests = staticallyIncludedDestinations; if (dests != null) { for (ActiveMQDestination dest : dests) { if (isPermissableDestination(dest)) { DemandSubscription sub = createDemandSubscription(dest, null); if (sub != null) { sub.setStaticallyIncluded(true); try { addSubscription(sub); } catch (IOException e) { LOG.error("Failed to add static destination {}", dest, e); } LOG.trace("{}, bridging messages for static destination: {}", configuration.getBrokerName(), dest); } else { LOG.info("{}, static destination excluded: {}, demand already exists", configuration.getBrokerName(), dest); } } else { LOG.info("{}, static destination excluded: {}", configuration.getBrokerName(), dest); } } } }
try { if (command.isMessageDispatch()) { safeWaitUntilStarted(); MessageDispatch md = (MessageDispatch) command; serviceRemoteConsumerAdvisory(md.getMessage().getDataStructure()); ackAdvisory(md.getMessage()); } else if (command.isBrokerInfo()) { futureRemoteBrokerInfo.set((BrokerInfo) command); serviceRemoteException(ce.getException()); } else { if (isDuplex()) { LOG.trace("{} duplex command type: {}", configuration.getBrokerName(), command.getDataStructureType()); if (command.isMessage()) { final ActiveMQMessage message = (ActiveMQMessage) command; if (NetworkBridgeFilter.isAdvisoryInterpretedByNetworkBridge(message)) { serviceRemoteConsumerAdvisory(message.getDataStructure()); ackAdvisory(message); } else { if (!isPermissableDestination(message.getDestination(), true)) { return; if (canDuplexDispatch(message)) { message.setProducerId(duplexInboundLocalProducerInfo.getProducerId()); if (message.isResponseRequired() || configuration.isAlwaysSyncSend()) { serviceInboundMessage(message); } else { if (message.isResponseRequired() || configuration.isAlwaysSyncSend()) {
try { if (command.isMessageDispatch()) { safeWaitUntilStarted(); networkBridgeStatistics.getEnqueues().increment(); final MessageDispatch md = (MessageDispatch) command; if (suppressMessageDispatch(md, sub)) { LOG.debug("{} message not forwarded to {} because message came from there or fails TTL, brokerPath: {}, message: {}", new Object[]{ configuration.getBrokerName(), remoteBrokerName, Arrays.toString(md.getMessage().getBrokerPath()), md.getMessage() Message message = configureMessage(md); LOG.debug("bridging ({} -> {}), consumer: {}, destination: {}, brokerPath: {}, message: {}", new Object[]{ configuration.getBrokerName(), remoteBrokerName, md.getConsumerId(), message.getDestination(), Arrays.toString(message.getBrokerPath()), (LOG.isTraceEnabled() ? message : message.getMessageId()) }); if (isDuplex() && NetworkBridgeFilter.isAdvisoryInterpretedByNetworkBridge(message)) { try { if (isPermissableDestination(md.getDestination())) { if (message.isPersistent() || configuration.isAlwaysSyncSend()) { serviceOutbound(message); } else if (command.isShutdownInfo()) { LOG.info("{} Shutting down {}", configuration.getBrokerName(), configuration.getName()); stop(); } else if (command.getClass() == ConnectionError.class) { ConnectionError ce = (ConnectionError) command; serviceLocalException(ce.getException()); } else {
protected boolean addConsumerInfo(final ConsumerInfo consumerInfo) throws IOException { boolean consumerAdded = false; ConsumerInfo info = consumerInfo.copy(); addRemoteBrokerToBrokerPath(info); DemandSubscription sub = createDemandSubscription(info); if (sub != null) { if (duplicateSuppressionIsRequired(sub)) { undoMapRegistration(sub); } else { addSubscription(sub); consumerAdded = true; } } return consumerAdded; }
if (contains(path, localBrokerPath[0])) { if (!isPermissableDestination(info.getDestination())) { if (addConsumerInfo(info)) { if (LOG.isDebugEnabled()) { LOG.debug(configuration.getBrokerName() + " bridging sub on " + localBroker + " from " + remoteBrokerName + " : " + info); if (contains(destInfo.getBrokerPath(), localBrokerPath[0])) { tempDest.setConnectionId(localSessionInfo.getSessionId().getConnectionId()); destInfo.setBrokerPath(appendToBrokerPath(destInfo.getBrokerPath(), getRemoteBrokerPath())); if (LOG.isTraceEnabled()) { LOG.trace("bridging destination control command: " + destInfo); } else if (data.getClass() == RemoveInfo.class) { ConsumerId id = (ConsumerId) ((RemoveInfo) data).getObjectId(); removeDemandSubscription(id);
try { if (command.isMessageDispatch()) { waitStarted(); MessageDispatch md = (MessageDispatch) command; serviceRemoteConsumerAdvisory(md.getMessage().getDataStructure()); demandConsumerDispatched++; if (demandConsumerDispatched > (demandConsumerInfo.getPrefetchSize() * .75)) { serviceRemoteBrokerInfo(command); } else if (command.getClass() == ConnectionError.class) { ConnectionError ce = (ConnectionError) command; serviceRemoteException(ce.getException()); } else { if (isDuplex()) { if (command.isMessage()) { ActiveMQMessage message = (ActiveMQMessage) command; if (AdvisorySupport.isConsumerAdvisoryTopic(message.getDestination()) || AdvisorySupport.isDestinationAdvisoryTopic(message.getDestination())) { serviceRemoteConsumerAdvisory(message.getDataStructure()); } else { if (!isPermissableDestination(message.getDestination(), true)) { return; localStartedLatch.await(); if (started.get()) { if (!addConsumerInfo((ConsumerInfo) command)) { if (LOG.isDebugEnabled()) { LOG.debug("Ignoring ConsumerInfo: " + command);
if (sub != null && md.getMessage() != null && sub.incrementOutstandingResponses()) { if (suppressMessageDispatch(md, sub)) { if (LOG.isDebugEnabled()) { LOG.debug(configuration.getBrokerName() + " message not forwarded to " + remoteBrokerName + " because message came from there or fails networkTTL, brokerPath: " + Arrays.toString(md.getMessage().getBrokerPath()) + ", message: " + md.getMessage()); Message message = configureMessage(md); if (LOG.isDebugEnabled()) { LOG.debug("bridging (" + configuration.getBrokerName() + " -> " + remoteBrokerName + ", consumer: " + md.getConsumerId() + ", destination " + message.getDestination() + ", brokerPath: " + Arrays.toString(message.getBrokerPath()) + ", message: " + message); serviceLocalBrokerInfo(command); } else if (command.isShutdownInfo()) { LOG.info(configuration.getBrokerName() + " Shutting down"); stop(); serviceLocalException(ce.getException()); } else { switch (command.getDataStructureType()) { serviceLocalException(e);
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())); } }
/** * Subscriptions for these destinations are always created */ protected void setupStaticDestinations() { ActiveMQDestination[] dests = staticallyIncludedDestinations; if (dests != null) { for (int i = 0; i < dests.length; i++) { ActiveMQDestination dest = dests[i]; DemandSubscription sub = createDemandSubscription(dest); try { addSubscription(sub); } catch (IOException e) { LOG.error("Failed to add static destination " + dest, e); } if (LOG.isTraceEnabled()) { LOG.trace("bridging messages for static destination: " + dest); } } } }
protected DemandSubscription createDemandSubscription(ConsumerInfo info) throws IOException { // add our original id to ourselves info.addNetworkConsumerId(info.getConsumerId()); return doCreateDemandSubscription(info); }
protected Message configureMessage(MessageDispatch md) throws IOException { Message message = md.getMessage().copy(); // Update the packet to show where it came from. message.setBrokerPath(appendToBrokerPath(message.getBrokerPath(), localBrokerPath)); message.setProducerId(producerInfo.getProducerId()); message.setDestination(md.getDestination()); message.setMemoryUsage(null); if (message.getOriginalTransactionId() == null) { message.setOriginalTransactionId(message.getTransactionId()); } message.setTransactionId(null); if (configuration.isUseCompression()) { message.compress(); } return message; }
final protected DemandSubscription createDemandSubscription(ActiveMQDestination destination, final String subscriptionName) { ConsumerInfo info = new ConsumerInfo(); info.setNetworkSubscription(true); info.setDestination(destination); if (subscriptionName != null) { info.setSubscriptionName(subscriptionName); } // Indicate that this subscription is being made on behalf of the remote broker. info.setBrokerPath(new BrokerId[]{remoteBrokerId}); // the remote info held by the DemandSubscription holds the original // consumerId, the local info get's overwritten info.setConsumerId(new ConsumerId(localSessionInfo.getSessionId(), consumerIdGenerator.getNextSequenceId())); DemandSubscription result = null; try { result = createDemandSubscription(info); } catch (IOException e) { LOG.error("Failed to create DemandSubscription ", e); } return result; }
private boolean suppressMessageDispatch(MessageDispatch md, DemandSubscription sub) throws Exception { // See if this consumer's brokerPath tells us it came from the broker at the other end // of the bridge. I think we should be making this decision based on the message's // broker bread crumbs and not the consumer's? However, the message's broker bread // crumbs are null, which is another matter. boolean suppress = false; Object consumerInfo = md.getMessage().getDataStructure(); if (consumerInfo != null && (consumerInfo instanceof ConsumerInfo)) { suppress = contains(((ConsumerInfo) consumerInfo).getBrokerPath(), remoteBrokerInfo.getBrokerId()); } // for durable subs, suppression via filter leaves dangling acks so we need to // check here and allow the ack irrespective if (!suppress && sub.getLocalInfo().isDurable()) { MessageEvaluationContext messageEvalContext = new MessageEvaluationContext(); messageEvalContext.setMessageReference(md.getMessage()); suppress = !createNetworkBridgeFilter(null).matches(messageEvalContext); } return suppress; }
protected void configureDemandSubscription(ConsumerInfo info, DemandSubscription sub) throws IOException { sub.getLocalInfo().setDispatchAsync(configuration.isDispatchAsync()); sub.getLocalInfo().setPrefetchSize(configuration.getPrefetchSize()); subscriptionMapByLocalId.put(sub.getLocalInfo().getConsumerId(), sub); subscriptionMapByRemoteId.put(sub.getRemoteInfo().getConsumerId(), sub); 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(createNetworkBridgeFilter(info)); } else { // need to ack this message if it is ignored as it is durable so // we check before we send. see: suppressMessageDispatch() } }
try { if (command.isMessageDispatch()) { safeWaitUntilStarted(); MessageDispatch md = (MessageDispatch) command; serviceRemoteConsumerAdvisory(md.getMessage().getDataStructure()); ackAdvisory(md.getMessage()); } else if (command.isBrokerInfo()) { futureRemoteBrokerInfo.set((BrokerInfo) command); serviceRemoteException(ce.getException()); } else { if (isDuplex()) { LOG.trace("{} duplex command type: {}", configuration.getBrokerName(), command.getDataStructureType()); if (command.isMessage()) { final ActiveMQMessage message = (ActiveMQMessage) command; if (NetworkBridgeFilter.isAdvisoryInterpretedByNetworkBridge(message)) { serviceRemoteConsumerAdvisory(message.getDataStructure()); ackAdvisory(message); } else { if (!isPermissableDestination(message.getDestination(), true)) { return; if (canDuplexDispatch(message)) { message.setProducerId(duplexInboundLocalProducerInfo.getProducerId()); if (message.isResponseRequired() || configuration.isAlwaysSyncSend()) { serviceInboundMessage(message); } else { if (message.isResponseRequired() || configuration.isAlwaysSyncSend()) {
try { if (command.isMessageDispatch()) { safeWaitUntilStarted(); networkBridgeStatistics.getEnqueues().increment(); final MessageDispatch md = (MessageDispatch) command; if (suppressMessageDispatch(md, sub)) { LOG.debug("{} message not forwarded to {} because message came from there or fails TTL, brokerPath: {}, message: {}", new Object[]{ configuration.getBrokerName(), remoteBrokerName, Arrays.toString(md.getMessage().getBrokerPath()), md.getMessage() Message message = configureMessage(md); LOG.debug("bridging ({} -> {}), consumer: {}, destination: {}, brokerPath: {}, message: {}", new Object[]{ configuration.getBrokerName(), remoteBrokerName, md.getConsumerId(), message.getDestination(), Arrays.toString(message.getBrokerPath()), (LOG.isTraceEnabled() ? message : message.getMessageId()) }); if (isDuplex() && NetworkBridgeFilter.isAdvisoryInterpretedByNetworkBridge(message)) { try { if (isPermissableDestination(md.getDestination())) { if (message.isPersistent() || configuration.isAlwaysSyncSend()) { serviceOutbound(message); } else if (command.isShutdownInfo()) { LOG.info("{} Shutting down {}", configuration.getBrokerName(), configuration.getName()); stop(); } else if (command.getClass() == ConnectionError.class) { ConnectionError ce = (ConnectionError) command; serviceLocalException(ce.getException()); } else {