git-svn-id: https://svn.apache.org/repos/asf/activemq/trunk@560696 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Robert Davies 2007-07-29 08:57:31 +00:00
parent 50c6d9ccc8
commit 35ba427ec9
2 changed files with 274 additions and 229 deletions

View File

@ -15,6 +15,7 @@
package org.apache.activemq.broker; package org.apache.activemq.broker;
import java.io.IOException; import java.io.IOException;
import java.net.URI;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@ -29,7 +30,6 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import org.apache.activemq.Service; import org.apache.activemq.Service;
import org.apache.activemq.broker.ft.MasterBroker; import org.apache.activemq.broker.ft.MasterBroker;
import org.apache.activemq.broker.region.ConnectionStatistics; import org.apache.activemq.broker.region.ConnectionStatistics;
@ -80,11 +80,13 @@ import org.apache.activemq.thread.Task;
import org.apache.activemq.thread.TaskRunner; import org.apache.activemq.thread.TaskRunner;
import org.apache.activemq.thread.TaskRunnerFactory; import org.apache.activemq.thread.TaskRunnerFactory;
import org.apache.activemq.transport.DefaultTransportListener; import org.apache.activemq.transport.DefaultTransportListener;
import org.apache.activemq.transport.ResponseCorrelator;
import org.apache.activemq.transport.Transport; import org.apache.activemq.transport.Transport;
import org.apache.activemq.transport.TransportFactory; import org.apache.activemq.transport.TransportFactory;
import org.apache.activemq.util.IntrospectionSupport; import org.apache.activemq.util.IntrospectionSupport;
import org.apache.activemq.util.MarshallingSupport; import org.apache.activemq.util.MarshallingSupport;
import org.apache.activemq.util.ServiceSupport; import org.apache.activemq.util.ServiceSupport;
import org.apache.activemq.util.URISupport;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@ -834,7 +836,7 @@ public class TransportConnection implements Service,Connection,Task,CommandVisit
public synchronized void start() throws Exception{ public synchronized void start() throws Exception{
starting=true; starting=true;
try{ try{
transport.start(); transport.start();
if (taskRunnerFactory != null) { if (taskRunnerFactory != null) {
taskRunner = taskRunnerFactory.createTaskRunner(this, "ActiveMQ Connection Dispatcher: " + getRemoteAddress()); taskRunner = taskRunnerFactory.createTaskRunner(this, "ActiveMQ Connection Dispatcher: " + getRemoteAddress());
@ -1090,12 +1092,21 @@ public class TransportConnection implements Service,Connection,Task,CommandVisit
NetworkBridgeConfiguration config = new NetworkBridgeConfiguration(); NetworkBridgeConfiguration config = new NetworkBridgeConfiguration();
IntrospectionSupport.setProperties(config,props,""); IntrospectionSupport.setProperties(config,props,"");
config.setBrokerName(broker.getBrokerName()); config.setBrokerName(broker.getBrokerName());
Transport localTransport = TransportFactory.connect(broker.getVmConnectorURI()); URI uri = broker.getVmConnectorURI();
duplexBridge = NetworkBridgeFactory.createBridge(config,localTransport,transport); HashMap map = new HashMap(URISupport.parseParamters(uri));
map.put("network", "true");
map.put("async","false");
uri = URISupport.createURIWithQuery(uri, URISupport.createQueryString(map));
Transport localTransport = TransportFactory.connect(uri);
Transport remoteBridgeTransport = new ResponseCorrelator(transport);
duplexBridge = NetworkBridgeFactory.createBridge(config,localTransport,remoteBridgeTransport);
//now turn duplex off this side //now turn duplex off this side
info.setDuplexConnection(false);
duplexBridge.setCreatedByDuplex(true); duplexBridge.setCreatedByDuplex(true);
duplexBridge.start(); duplexBridge.duplexStart(brokerInfo,info);
log.info("Created Duplex Bridge back to " + info.getBrokerName()); log.info("Created Duplex Bridge back to " + info.getBrokerName());
return null;
}catch(Exception e){ }catch(Exception e){
log.error("Creating duplex network bridge",e); log.error("Creating duplex network bridge",e);
} }
@ -1103,7 +1114,6 @@ public class TransportConnection implements Service,Connection,Task,CommandVisit
// We only expect to get one broker info command per connection // We only expect to get one broker info command per connection
if(this.brokerInfo!=null){ if(this.brokerInfo!=null){
log.warn("Unexpected extra broker info command received: "+info); log.warn("Unexpected extra broker info command received: "+info);
Thread.dumpStack();
} }
this.brokerInfo=info; this.brokerInfo=info;
broker.addBroker(this,info); broker.addBroker(this,info);

View File

@ -27,6 +27,7 @@ import java.util.concurrent.atomic.AtomicLong;
import org.apache.activemq.advisory.AdvisorySupport; import org.apache.activemq.advisory.AdvisorySupport;
import org.apache.activemq.command.ActiveMQDestination; import org.apache.activemq.command.ActiveMQDestination;
import org.apache.activemq.command.ActiveMQMessage;
import org.apache.activemq.command.ActiveMQTempDestination; import org.apache.activemq.command.ActiveMQTempDestination;
import org.apache.activemq.command.ActiveMQTopic; import org.apache.activemq.command.ActiveMQTopic;
import org.apache.activemq.command.BrokerId; import org.apache.activemq.command.BrokerId;
@ -110,103 +111,107 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge {
final AtomicLong enqueueCounter = new AtomicLong(); final AtomicLong enqueueCounter = new AtomicLong();
final AtomicLong dequeueCounter = new AtomicLong(); final AtomicLong dequeueCounter = new AtomicLong();
private AtomicBoolean started = new AtomicBoolean();
public DemandForwardingBridgeSupport(NetworkBridgeConfiguration configuration, Transport localBroker, Transport remoteBroker) { public DemandForwardingBridgeSupport(NetworkBridgeConfiguration configuration, Transport localBroker, Transport remoteBroker) {
this.configuration=configuration; this.configuration=configuration;
this.localBroker = localBroker; this.localBroker = localBroker;
this.remoteBroker = remoteBroker; this.remoteBroker = remoteBroker;
} }
public void start() throws Exception {
localBroker.setTransportListener(new DefaultTransportListener(){
public void onCommand(Object o){
Command command = (Command) o;
serviceLocalCommand(command);
}
public void onException(IOException error){ public void duplexStart(BrokerInfo localBrokerInfo,BrokerInfo remoteBrokerInfo) throws Exception{
serviceLocalException(error); this.localBrokerInfo=localBrokerInfo;
} this.remoteBrokerInfo=remoteBrokerInfo;
}); start();
remoteBroker.setTransportListener(new TransportListener(){ serviceRemoteCommand(remoteBrokerInfo);
public void onCommand(Object o){
Command command = (Command) o;
serviceRemoteCommand(command);
}
public void onException(IOException error){
serviceRemoteException(error);
}
public void transportInterupted(){
//clear any subscriptions - to try and prevent the bridge from stalling the broker
if( remoteInterupted.compareAndSet(false, true) ) {
log.info("Outbound transport to " + remoteBrokerName + " interrupted.");
if( localBridgeStarted.get() ) {
clearDownSubscriptions();
synchronized( DemandForwardingBridgeSupport.this ) {
try{
localBroker.oneway(localConnectionInfo.createRemoveCommand());
}catch(TransportDisposedIOException td){
log.debug("local broker is now disposed",td);
}
catch(IOException e){
log.warn("Caught exception from local start",e);
}
}
}
localBridgeStarted.set(false);
remoteBridgeStarted.set(false);
startedLatch = new CountDownLatch(2);
}
}
public void transportResumed(){
if( remoteInterupted.compareAndSet(true, false) ) {
// We want to slow down false connects so that we don't get in a busy loop.
// False connects can occurr if you using SSH tunnels.
if( !lastConnectSucceeded.get() ) {
try {
log.debug("Previous connection was never fully established. Sleeping for second to avoid busy loop.");
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
lastConnectSucceeded.set(false);
try {
startLocalBridge();
remoteBridgeStarted.set(true);
startedLatch.countDown();
log.info("Outbound transport to " + remoteBrokerName + " resumed");
}catch(Exception e) {
log.error("Caught exception from local start in resume transport",e );
}
}
}
});
localBroker.start();
remoteBroker.start();
try{
triggerRemoteStartBridge();
}catch(IOException e){
log.warn("Caught exception from remote start",e);
}
NetworkBridgeListener l = this.networkBridgeListener;
if (l!=null) {
l.onStart(this);
}
} }
public void start() throws Exception{
if(started.compareAndSet(false,true)){
localBroker.setTransportListener(new DefaultTransportListener(){
public void onCommand(Object o){
Command command=(Command)o;
serviceLocalCommand(command);
}
public void onException(IOException error){
serviceLocalException(error);
}
});
remoteBroker.setTransportListener(new TransportListener(){
public void onCommand(Object o){
Command command=(Command)o;
serviceRemoteCommand(command);
}
public void onException(IOException error){
serviceRemoteException(error);
}
public void transportInterupted(){
// clear any subscriptions - to try and prevent the bridge from stalling the broker
if(remoteInterupted.compareAndSet(false,true)){
log.info("Outbound transport to "+remoteBrokerName+" interrupted.");
if(localBridgeStarted.get()){
clearDownSubscriptions();
synchronized(DemandForwardingBridgeSupport.this){
try{
localBroker.oneway(localConnectionInfo.createRemoveCommand());
}catch(TransportDisposedIOException td){
log.debug("local broker is now disposed",td);
}catch(IOException e){
log.warn("Caught exception from local start",e);
}
}
}
localBridgeStarted.set(false);
remoteBridgeStarted.set(false);
startedLatch=new CountDownLatch(2);
}
}
public void transportResumed(){
if(remoteInterupted.compareAndSet(true,false)){
// We want to slow down false connects so that we don't get in a busy loop.
// False connects can occurr if you using SSH tunnels.
if(!lastConnectSucceeded.get()){
try{
log
.debug("Previous connection was never fully established. Sleeping for second to avoid busy loop.");
Thread.sleep(1000);
}catch(InterruptedException e){
Thread.currentThread().interrupt();
}
}
lastConnectSucceeded.set(false);
try{
startLocalBridge();
remoteBridgeStarted.set(true);
startedLatch.countDown();
log.info("Outbound transport to "+remoteBrokerName+" resumed");
}catch(Exception e){
log.error("Caught exception from local start in resume transport",e);
}
}
}
});
localBroker.start();
remoteBroker.start();
try{
triggerRemoteStartBridge();
}catch(IOException e){
log.warn("Caught exception from remote start",e);
}
NetworkBridgeListener l=this.networkBridgeListener;
if(l!=null){
l.onStart(this);
}
}
}
protected void triggerLocalStartBridge() throws IOException { protected void triggerLocalStartBridge() throws IOException {
Thread thead=new Thread(){ Thread thead=new Thread(){
public void run(){ public void run(){
@ -259,95 +264,88 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge {
} }
} }
protected void startRemoteBridge() throws Exception { protected void startRemoteBridge() throws Exception{
if(remoteBridgeStarted.compareAndSet(false,true)) { if(remoteBridgeStarted.compareAndSet(false,true)){
synchronized(this){
synchronized (this) { if(isCreatedByDuplex()==false){
BrokerInfo brokerInfo=new BrokerInfo();
if( remoteConnectionInfo!=null ) { brokerInfo.setBrokerName(configuration.getBrokerName());
remoteBroker.oneway(remoteConnectionInfo.createRemoveCommand()); brokerInfo.setNetworkConnection(true);
} brokerInfo.setDuplexConnection(configuration.isDuplex());
// set our properties
Properties props=new Properties();
IntrospectionSupport.getProperties(this,props,null);
String str=MarshallingSupport.propertiesToString(props);
brokerInfo.setNetworkProperties(str);
remoteBroker.oneway(brokerInfo);
}
if(remoteConnectionInfo!=null){
remoteBroker.oneway(remoteConnectionInfo.createRemoveCommand());
}
remoteConnectionInfo=new ConnectionInfo(); remoteConnectionInfo=new ConnectionInfo();
remoteConnectionInfo.setConnectionId(new ConnectionId(idGenerator.generateId())); remoteConnectionInfo.setConnectionId(new ConnectionId(idGenerator.generateId()));
remoteConnectionInfo.setClientId("NC_"+configuration.getBrokerName()+"_outbound"); remoteConnectionInfo.setClientId("NC_"+configuration.getBrokerName()+"_outbound");
remoteConnectionInfo.setUserName(configuration.getUserName()); remoteConnectionInfo.setUserName(configuration.getUserName());
remoteConnectionInfo.setPassword(configuration.getPassword()); remoteConnectionInfo.setPassword(configuration.getPassword());
remoteBroker.oneway(remoteConnectionInfo); remoteBroker.oneway(remoteConnectionInfo);
if (isCreatedByDuplex()==false) {
BrokerInfo brokerInfo=new BrokerInfo();
brokerInfo.setBrokerName(configuration.getBrokerName());
brokerInfo.setNetworkConnection(true);
brokerInfo.setDuplexConnection(configuration.isDuplex());
//set our properties
Properties props = new Properties();
IntrospectionSupport.getProperties(this,props,null);
String str = MarshallingSupport.propertiesToString(props);
brokerInfo.setNetworkProperties(str);
remoteBroker.oneway(brokerInfo);
}
SessionInfo remoteSessionInfo=new SessionInfo(remoteConnectionInfo,1); SessionInfo remoteSessionInfo=new SessionInfo(remoteConnectionInfo,1);
remoteBroker.oneway(remoteSessionInfo); remoteBroker.oneway(remoteSessionInfo);
producerInfo=new ProducerInfo(remoteSessionInfo,1); producerInfo=new ProducerInfo(remoteSessionInfo,1);
producerInfo.setResponseRequired(false); producerInfo.setResponseRequired(false);
remoteBroker.oneway(producerInfo); remoteBroker.oneway(producerInfo);
// Listen to consumer advisory messages on the remote broker to determine demand. // Listen to consumer advisory messages on the remote broker to determine demand.
demandConsumerInfo=new ConsumerInfo(remoteSessionInfo,1); demandConsumerInfo=new ConsumerInfo(remoteSessionInfo,1);
demandConsumerInfo.setDispatchAsync(configuration.isDispatchAsync()); demandConsumerInfo.setDispatchAsync(configuration.isDispatchAsync());
String advisoryTopic = AdvisorySupport.CONSUMER_ADVISORY_TOPIC_PREFIX+configuration.getDestinationFilter(); String advisoryTopic=AdvisorySupport.CONSUMER_ADVISORY_TOPIC_PREFIX
if( configuration.isBridgeTempDestinations() ) { +configuration.getDestinationFilter();
advisoryTopic += ","+AdvisorySupport.TEMP_DESTINATION_COMPOSITE_ADVISORY_TOPIC; if(configuration.isBridgeTempDestinations()){
advisoryTopic+=","+AdvisorySupport.TEMP_DESTINATION_COMPOSITE_ADVISORY_TOPIC;
} }
demandConsumerInfo.setDestination(new ActiveMQTopic(advisoryTopic)); demandConsumerInfo.setDestination(new ActiveMQTopic(advisoryTopic));
demandConsumerInfo.setPrefetchSize(configuration.getPrefetchSize()); demandConsumerInfo.setPrefetchSize(configuration.getPrefetchSize());
remoteBroker.oneway(demandConsumerInfo); remoteBroker.oneway(demandConsumerInfo);
startedLatch.countDown(); startedLatch.countDown();
if(!disposed){
if (!disposed){
triggerLocalStartBridge(); triggerLocalStartBridge();
} }
}
}
} }
} }
public void stop() throws Exception{ public void stop() throws Exception{
log.debug(" stopping "+configuration.getBrokerName()+" bridge to "+remoteBrokerName+" is disposed already ? "+disposed); if(started.compareAndSet(true,false)){
boolean wasDisposedAlready=disposed; log.debug(" stopping "+configuration.getBrokerName()+" bridge to "+remoteBrokerName
if(!disposed){ +" is disposed already ? "+disposed);
NetworkBridgeListener l = this.networkBridgeListener; boolean wasDisposedAlready=disposed;
if (l!=null) { if(!disposed){
l.onStop(this); NetworkBridgeListener l=this.networkBridgeListener;
if(l!=null){
l.onStop(this);
}
try{
disposed=true;
remoteBridgeStarted.set(false);
localBroker.oneway(new ShutdownInfo());
remoteBroker.oneway(new ShutdownInfo());
}catch(IOException e){
log.debug("Caught exception stopping",e);
}finally{
ServiceStopper ss=new ServiceStopper();
ss.stop(localBroker);
ss.stop(remoteBroker);
// Release the started Latch since another thread could be stuck waiting for it to start up.
startedLatch.countDown();
startedLatch.countDown();
ss.throwFirstException();
}
} }
if(wasDisposedAlready){
try{ log.debug(configuration.getBrokerName()+" bridge to "+remoteBrokerName+" stopped");
disposed=true; }else{
remoteBridgeStarted.set(false); log.info(configuration.getBrokerName()+" bridge to "+remoteBrokerName+" stopped");
localBroker.oneway(new ShutdownInfo());
remoteBroker.oneway(new ShutdownInfo());
}catch(IOException e){
log.debug("Caught exception stopping",e);
}finally{
ServiceStopper ss=new ServiceStopper();
ss.stop(localBroker);
ss.stop(remoteBroker);
// Release the started Latch since another thread could be stuck waiting for it to start up.
startedLatch.countDown();
startedLatch.countDown();
ss.throwFirstException();
} }
} }
if(wasDisposedAlready){
log.debug(configuration.getBrokerName()+" bridge to "+remoteBrokerName+" stopped");
}else{
log.info(configuration.getBrokerName()+" bridge to "+remoteBrokerName+" stopped");
}
} }
public void serviceRemoteException(Throwable error){ public void serviceRemoteException(Throwable error){
@ -370,12 +368,12 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge {
} }
} }
protected void serviceRemoteCommand(Command command) { protected void serviceRemoteCommand(Command command){
if(!disposed){ if(!disposed){
try{ try{
if(command.isMessageDispatch()){ if(command.isMessageDispatch()){
waitStarted(); waitStarted();
MessageDispatch md=(MessageDispatch) command; MessageDispatch md=(MessageDispatch)command;
serviceRemoteConsumerAdvisory(md.getMessage().getDataStructure()); serviceRemoteConsumerAdvisory(md.getMessage().getDataStructure());
demandConsumerDispatched++; demandConsumerDispatched++;
if(demandConsumerDispatched>(demandConsumerInfo.getPrefetchSize()*.75)){ if(demandConsumerDispatched>(demandConsumerInfo.getPrefetchSize()*.75)){
@ -383,117 +381,137 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge {
demandConsumerDispatched=0; demandConsumerDispatched=0;
} }
}else if(command.isBrokerInfo()){ }else if(command.isBrokerInfo()){
lastConnectSucceeded.set(true);
lastConnectSucceeded.set(true); remoteBrokerInfo=((BrokerInfo)command);
remoteBrokerInfo = ((BrokerInfo)command); serviceRemoteBrokerInfo(command);
// Let the local broker know the remote broker's ID.
serviceRemoteBrokerInfo(command); localBroker.oneway(command);
// Let the local broker know the remote broker's ID. }else if(command.getClass()==ConnectionError.class){
localBroker.oneway(command); ConnectionError ce=(ConnectionError)command;
serviceRemoteException(ce.getException());
}else if(command.getClass() == ConnectionError.class ) {
ConnectionError ce = (ConnectionError) command;
serviceRemoteException(ce.getException());
}else{ }else{
switch(command.getDataStructureType()){ if(configuration.isDuplex()||createdByDuplex){
case KeepAliveInfo.DATA_STRUCTURE_TYPE: if(command.isMessage()){
case WireFormatInfo.DATA_STRUCTURE_TYPE: ActiveMQMessage message=(ActiveMQMessage)command;
case ShutdownInfo.DATA_STRUCTURE_TYPE: if(AdvisorySupport.isConsumerAdvisoryTopic(message.getDestination())){
break; serviceRemoteConsumerAdvisory(message.getDataStructure());
default: }else{
log.warn("Unexpected remote command: "+command); localBroker.oneway(message);
}
}else{
switch(command.getDataStructureType()){
case ConnectionInfo.DATA_STRUCTURE_TYPE:
case SessionInfo.DATA_STRUCTURE_TYPE:
case ProducerInfo.DATA_STRUCTURE_TYPE:
localBroker.oneway(command);
break;
case ConsumerInfo.DATA_STRUCTURE_TYPE:
if(!addConsumerInfo((ConsumerInfo)command)){
if(log.isDebugEnabled())
log.debug("Ignoring ConsumerInfo: "+command);
}
break;
default:
if(log.isDebugEnabled())
log.debug("Ignoring remote command: "+command);
}
}
}else{
switch(command.getDataStructureType()){
case KeepAliveInfo.DATA_STRUCTURE_TYPE:
case WireFormatInfo.DATA_STRUCTURE_TYPE:
case ShutdownInfo.DATA_STRUCTURE_TYPE:
break;
default:
log.warn("Unexpected remote command: "+command);
}
} }
} }
}catch(Exception e){ }catch(Throwable e){
serviceRemoteException(e); serviceRemoteException(e);
} }
} }
} }
private void serviceRemoteConsumerAdvisory(DataStructure data) throws IOException { private void serviceRemoteConsumerAdvisory(DataStructure data) throws IOException{
final int networkTTL=configuration.getNetworkTTL();
final int networkTTL = configuration.getNetworkTTL();
if(data.getClass()==ConsumerInfo.class){ if(data.getClass()==ConsumerInfo.class){
// Create a new local subscription // Create a new local subscription
ConsumerInfo info=(ConsumerInfo) data; ConsumerInfo info=(ConsumerInfo)data;
BrokerId[] path=info.getBrokerPath(); BrokerId[] path=info.getBrokerPath();
if((path!=null&&path.length>= networkTTL)){ if((path!=null&&path.length>=networkTTL)){
if(log.isDebugEnabled()) if(log.isDebugEnabled())
log.debug(configuration.getBrokerName() + " Ignoring Subscription " + info + " restricted to " + networkTTL + " network hops only"); log.debug(configuration.getBrokerName()+" Ignoring Subscription "+info+" restricted to "+networkTTL
+" network hops only");
return; return;
} }
if(contains(info.getBrokerPath(),localBrokerPath[0])){ if(contains(info.getBrokerPath(),localBrokerPath[0])){
// Ignore this consumer as it's a consumer we locally sent to the broker. // Ignore this consumer as it's a consumer we locally sent to the broker.
if(log.isDebugEnabled()) if(log.isDebugEnabled())
log.debug(configuration.getBrokerName() + " Ignoring sub " + info + " already routed through this broker once"); log.debug(configuration.getBrokerName()+" Ignoring sub "+info
+" already routed through this broker once");
return; return;
} }
if (!isPermissableDestination(info.getDestination())){ if(!isPermissableDestination(info.getDestination())){
//ignore if not in the permited or in the excluded list // ignore if not in the permited or in the excluded list
if(log.isDebugEnabled()) if(log.isDebugEnabled())
log.debug(configuration.getBrokerName() + " Ignoring sub " + info + " destination " + info.getDestination() + " is not permiited"); log.debug(configuration.getBrokerName()+" Ignoring sub "+info+" destination "+info.getDestination()
+" is not permiited");
return; return;
} }
// Update the packet to show where it came from. if(addConsumerInfo(info)){
info=info.copy();
addRemoteBrokerToBrokerPath(info);
DemandSubscription sub=createDemandSubscription(info);
if (sub != null){
addSubscription(sub);
if(log.isDebugEnabled()) if(log.isDebugEnabled())
log.debug(configuration.getBrokerName() + " Forwarding sub on "+localBroker+" from "+remoteBrokerName+" : "+info); log.debug(configuration.getBrokerName()+" Forwarding sub on "+localBroker+" from "+remoteBrokerName
}else { +" : "+info);
}else{
if(log.isDebugEnabled()) if(log.isDebugEnabled())
log.debug(configuration.getBrokerName() + " Ignoring sub " + info + " already subscribed to matching destination"); log.debug(configuration.getBrokerName()+" Ignoring sub "+info
+" already subscribed to matching destination");
} }
} }else if(data.getClass()==DestinationInfo.class){
else if (data.getClass()==DestinationInfo.class){ // It's a destination info - we want to pass up
// It's a destination info - we want to pass up // infomation about temporary destinations
//infomation about temporary destinations DestinationInfo destInfo=(DestinationInfo)data;
DestinationInfo destInfo = (DestinationInfo) data;
BrokerId[] path=destInfo.getBrokerPath(); BrokerId[] path=destInfo.getBrokerPath();
if((path!=null&&path.length>= networkTTL)){ if((path!=null&&path.length>=networkTTL)){
if(log.isDebugEnabled()) if(log.isDebugEnabled())
log.debug("Ignoring Subscription " + destInfo + " restricted to " + networkTTL + " network hops only"); log.debug("Ignoring Subscription "+destInfo+" restricted to "+networkTTL+" network hops only");
return; return;
} }
if(contains(destInfo.getBrokerPath(),localBrokerPath[0])){ if(contains(destInfo.getBrokerPath(),localBrokerPath[0])){
// Ignore this consumer as it's a consumer we locally sent to the broker. // Ignore this consumer as it's a consumer we locally sent to the broker.
if(log.isDebugEnabled()) if(log.isDebugEnabled())
log.debug("Ignoring sub " + destInfo + " already routed through this broker once"); log.debug("Ignoring sub "+destInfo+" already routed through this broker once");
return; return;
} }
destInfo.setConnectionId(localConnectionInfo.getConnectionId()); destInfo.setConnectionId(localConnectionInfo.getConnectionId());
if (destInfo.getDestination() instanceof ActiveMQTempDestination){ if(destInfo.getDestination() instanceof ActiveMQTempDestination){
//re-set connection id so comes from here // re-set connection id so comes from here
ActiveMQTempDestination tempDest = (ActiveMQTempDestination) destInfo.getDestination(); ActiveMQTempDestination tempDest=(ActiveMQTempDestination)destInfo.getDestination();
tempDest.setConnectionId(localSessionInfo.getSessionId().getConnectionId()); tempDest.setConnectionId(localSessionInfo.getSessionId().getConnectionId());
} }
destInfo.setBrokerPath(appendToBrokerPath(destInfo.getBrokerPath(),getRemoteBrokerPath())); destInfo.setBrokerPath(appendToBrokerPath(destInfo.getBrokerPath(),getRemoteBrokerPath()));
log.debug("Replying destination control command: "+destInfo);
log.debug("Replying destination control command: "+destInfo);
localBroker.oneway(destInfo); localBroker.oneway(destInfo);
}else if(data.getClass()==RemoveInfo.class){
} ConsumerId id=(ConsumerId)((RemoveInfo)data).getObjectId();
else if(data.getClass()==RemoveInfo.class){
ConsumerId id=(ConsumerId) ((RemoveInfo) data).getObjectId();
removeDemandSubscription(id); removeDemandSubscription(id);
} }
} }
public void serviceLocalException(Throwable error) { public void serviceLocalException(Throwable error){
if( !disposed ) { if(!disposed){
log.info("Network connection between "+localBroker+" and "+remoteBroker+" shutdown due to a local error: "+error); log.info("Network connection between "+localBroker+" and "+remoteBroker+" shutdown due to a local error: "
log.debug("The local Exception was:"+error,error); +error);
new Thread() { log.debug("The local Exception was:"+error,error);
public void run() { new Thread(){
ServiceSupport.dispose(DemandForwardingBridgeSupport.this);
} public void run(){
}.start(); ServiceSupport.dispose(DemandForwardingBridgeSupport.this);
}
}.start();
fireBridgeFailed(); fireBridgeFailed();
} }
} }
protected void addSubscription(DemandSubscription sub) throws IOException { protected void addSubscription(DemandSubscription sub) throws IOException {
@ -741,8 +759,7 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge {
} }
} }
return false; return false;
} }
return true; return true;
} }
@ -766,6 +783,18 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge {
} }
} }
} }
protected boolean addConsumerInfo(final ConsumerInfo consumerInfo) throws IOException {
boolean result = false;
ConsumerInfo info=consumerInfo.copy();
addRemoteBrokerToBrokerPath(info);
DemandSubscription sub=createDemandSubscription(info);
if (sub != null){
addSubscription(sub);
result = true;
}
return result;
}
protected DemandSubscription createDemandSubscription(ConsumerInfo info) throws IOException { protected DemandSubscription createDemandSubscription(ConsumerInfo info) throws IOException {
return doCreateDemandSubscription(info); return doCreateDemandSubscription(info);
@ -775,7 +804,13 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge {
DemandSubscription result=new DemandSubscription(info); DemandSubscription result=new DemandSubscription(info);
result.getLocalInfo().setConsumerId(new ConsumerId(localSessionInfo.getSessionId(),consumerIdGenerator result.getLocalInfo().setConsumerId(new ConsumerId(localSessionInfo.getSessionId(),consumerIdGenerator
.getNextSequenceId())); .getNextSequenceId()));
if (info.getDestination().isTemporary()) {
//reset the local connection Id
ActiveMQTempDestination dest = (ActiveMQTempDestination)result.getLocalInfo().getDestination();
dest.setConnectionId(localConnectionInfo.getConnectionId().toString());
}
if( configuration.isDecreaseNetworkConsumerPriority() ) { if( configuration.isDecreaseNetworkConsumerPriority() ) {
byte priority=ConsumerInfo.NETWORK_CONSUMER_PRIORITY; byte priority=ConsumerInfo.NETWORK_CONSUMER_PRIORITY;
if(priority>Byte.MIN_VALUE&&info.getBrokerPath()!=null&&info.getBrokerPath().length>1){ if(priority>Byte.MIN_VALUE&&info.getBrokerPath()!=null&&info.getBrokerPath().length>1){
@ -828,7 +863,7 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge {
subscriptionMapByLocalId.clear(); subscriptionMapByLocalId.clear();
subscriptionMapByRemoteId.clear(); subscriptionMapByRemoteId.clear();
} }
protected abstract NetworkBridgeFilter createNetworkBridgeFilter(ConsumerInfo info) throws IOException; protected abstract NetworkBridgeFilter createNetworkBridgeFilter(ConsumerInfo info) throws IOException;
protected abstract void serviceLocalBrokerInfo(Command command) throws InterruptedException; protected abstract void serviceLocalBrokerInfo(Command command) throws InterruptedException;