/**
*
* Copyright 2004 Protique Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
**/
package org.activemq.broker.impl;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.security.auth.Subject;
import javax.transaction.xa.XAException;
import org.activemq.broker.BrokerAdmin;
import org.activemq.broker.BrokerClient;
import org.activemq.broker.BrokerConnector;
import org.activemq.io.util.SpooledBoundedActiveMQMessageQueue;
import org.activemq.message.ActiveMQMessage;
import org.activemq.message.ActiveMQXid;
import org.activemq.message.BrokerAdminCommand;
import org.activemq.message.BrokerInfo;
import org.activemq.message.CapacityInfo;
import org.activemq.message.CleanupConnectionInfo;
import org.activemq.message.ConnectionInfo;
import org.activemq.message.ConsumerInfo;
import org.activemq.message.DurableUnsubscribe;
import org.activemq.message.IntResponseReceipt;
import org.activemq.message.KeepAlive;
import org.activemq.message.MessageAck;
import org.activemq.message.Packet;
import org.activemq.message.PacketListener;
import org.activemq.message.ProducerInfo;
import org.activemq.message.Receipt;
import org.activemq.message.ResponseReceipt;
import org.activemq.message.SessionInfo;
import org.activemq.message.TransactionInfo;
import org.activemq.message.XATransactionInfo;
import org.activemq.transport.NetworkChannel;
import org.activemq.transport.NetworkConnector;
import org.activemq.transport.TransportChannel;
import org.activemq.util.IdGenerator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArrayList;
import EDU.oswego.cs.dl.util.concurrent.SynchronizedBoolean;
import EDU.oswego.cs.dl.util.concurrent.ThreadedExecutor;
/**
* A Broker client side proxy representing a JMS Connnection
*
* @version $Revision: 1.1.1.1 $
*/
public class BrokerClientImpl implements BrokerClient, ExceptionListener, PacketListener {
private static final Log log = LogFactory.getLog(BrokerClientImpl.class);
private static final Log commandLog = LogFactory.getLog("org.activemq.broker.CommandTrace");
private BrokerConnector brokerConnector;
private TransportChannel channel;
private ConnectionInfo connectionInfo;
private IdGenerator packetIdGenerator;
private SynchronizedBoolean closed;
private Set activeConsumers;
private CopyOnWriteArrayList consumers;
private CopyOnWriteArrayList producers;
private CopyOnWriteArrayList transactions;
private CopyOnWriteArrayList sessions;
private SynchronizedBoolean started;
private boolean brokerConnection;
private boolean clusteredConnection;
private String remoteBrokerName;
private int capacity = 100;
private SpooledBoundedActiveMQMessageQueue spoolQueue;
private boolean cleanedUp;
private boolean registered;
private ArrayList dispatchQueue = new ArrayList();
private Subject subject;
private boolean remoteNetworkConnector;
/**
* Default Constructor of BrokerClientImpl
*/
public BrokerClientImpl() {
this.packetIdGenerator = new IdGenerator();
this.closed = new SynchronizedBoolean(false);
this.started = new SynchronizedBoolean(false);
this.activeConsumers = new HashSet();
this.consumers = new CopyOnWriteArrayList();
this.producers = new CopyOnWriteArrayList();
this.transactions = new CopyOnWriteArrayList();
this.sessions = new CopyOnWriteArrayList();
}
/**
* Initialize the BrokerClient
*
* @param brokerConnector
* @param channel
*/
public void initialize(BrokerConnector brokerConnector, TransportChannel channel) {
this.brokerConnector = brokerConnector;
this.channel = channel;
this.channel.setPacketListener(this);
this.channel.setExceptionListener(this);
log.trace("brokerConnectorConnector client initialized");
}
/**
* @return the BrokerConnector this client is associated with
*/
public BrokerConnector getBrokerConnector() {
return this.brokerConnector;
}
/**
* @return the connection information for this client
*/
public ConnectionInfo getConnectionInfo() {
return connectionInfo;
}
/**
* @see javax.jms.ExceptionListener#onException(javax.jms.JMSException)
*/
public void onException(JMSException jmsEx) {
log.info("Client disconnected: " + this);
log.debug("Disconnect cuase: ", jmsEx);
close();
}
/**
* @return pretty print for this brokerConnector-client
*/
public String toString() {
String str = "brokerConnector-client:(" + hashCode() + ") ";
str += connectionInfo == null ? "" : connectionInfo.getClientId();
str += ": " + channel;
return str;
}
/**
* Dispatch an ActiveMQMessage to the end client
*
* @param message
*/
public void dispatch(ActiveMQMessage message) {
if (!isSlowConsumer()) {
dispatchToClient(message);
}
else {
if (spoolQueue == null) {
log.warn("Connection: " + connectionInfo.getClientId() + " is a slow consumer");
String spoolName = brokerConnector.getBrokerInfo().getBrokerName() + "_" + connectionInfo.getClientId();
try {
spoolQueue = new SpooledBoundedActiveMQMessageQueue(brokerConnector.getBrokerContainer().getBroker()
.getTempDir(), spoolName);
final SpooledBoundedActiveMQMessageQueue bpq = spoolQueue;
ThreadedExecutor exec = new ThreadedExecutor();
exec.execute(new Runnable() {
public void run() {
while (!closed.get()) {
try {
Packet packet = bpq.dequeue();
if (packet != null) {
dispatchToClient(packet);
}
}
catch (InterruptedException e) {
log.warn("async dispatch got an interupt", e);
}
catch (JMSException e) {
log.error("async dispatch got an problem", e);
}
}
}
});
}
catch (IOException e) {
log.error("Could not create SpooledBoundedQueue for this slow consumer", e);
close();
}
catch (InterruptedException e) {
log.error("Could not create SpooledBoundedQueue for this slow consumer", e);
close();
}
}
if (spoolQueue != null) {
try {
spoolQueue.enqueue(message);
}
catch (JMSException e) {
log.error(
"Could not enqueue message " + message + " to SpooledBoundedQueue for this slow consumer",
e);
close();
}
}
}
}
private void dispatchToClient(Packet message) {
if (started.get()) {
send(message);
}
else {
boolean msgSent = false;
if (message.isJMSMessage()) {
ActiveMQMessage jmsMsg = (ActiveMQMessage) message;
if (jmsMsg.getJMSActiveMQDestination().isAdvisory()) {
send(message);
msgSent = true;
}
}
if (!msgSent) {
// If the connection is stopped.. we have to hold the message till it is started.
synchronized (started) {
dispatchQueue.add(message);
}
}
}
}
/**
* @return true if the peer for this Client is itself another Broker
*/
public boolean isBrokerConnection() {
return brokerConnection;
}
/**
* @return true id this client is part of a cluster
*/
public boolean isClusteredConnection() {
return clusteredConnection;
}
/**
* Get the Capacity for in-progress messages at the peer (probably a JMSConnection) Legimate values between 0-100. 0
* capacity representing that the peer cannot process any more messages at the current time
*
* @return
*/
public int getCapacity() {
return capacity;
}
/**
* @return the client id of the remote connection
*/
public String getClientID() {
if (connectionInfo != null) {
return connectionInfo.getClientId();
}
return null;
}
/**
* @return the channel used
*/
public TransportChannel getChannel() {
return channel;
}
/**
* Get an indication if the peer should be considered as a slow consumer
*
* @return true id the peer should be considered as a slow consumer
*/
public boolean isSlowConsumer() {
return capacity <= 20; //don't want to fill the peer completely - as this may effect it's processing!
}
/**
* Consume a Packet from the underlying TransportChannel for processing
*
* @param packet
*/
public void consume(Packet packet) {
if (packet != null) {
if( commandLog.isDebugEnabled() )
commandLog.debug("broker for "+getClientID()+" received: "+packet);
Throwable requestEx = null;
boolean failed = false;
boolean receiptRequired = packet.isReceiptRequired();
short correlationId = packet.getId();
String brokerName = brokerConnector.getBrokerInfo().getBrokerName();
String clusterName = brokerConnector.getBrokerInfo().getClusterName();
try {
if (brokerConnection) {
if (remoteBrokerName != null && remoteBrokerName.length() > 0) {
packet.addBrokerVisited(remoteBrokerName); //got from the remote broker
}
packet.addBrokerVisited(brokerName);
}
if (packet.isJMSMessage()) {
ActiveMQMessage message = (ActiveMQMessage) packet;
if (!brokerConnection) {
message.setEntryBrokerName(brokerName);
message.setEntryClusterName(clusterName);
}
consumeActiveMQMessage(message);
}
else {
switch (packet.getPacketType()) {
case Packet.ACTIVEMQ_MSG_ACK : {
MessageAck ack = (MessageAck) packet;
consumeMessageAck(ack);
break;
}
case Packet.XA_TRANSACTION_INFO : {
XATransactionInfo info = (XATransactionInfo) packet;
consumeXATransactionInfo(info);
receiptRequired=info.isReceiptRequired();
break;
}
case Packet.TRANSACTION_INFO : {
TransactionInfo info = (TransactionInfo) packet;
consumeTransactionInfo(info);
break;
}
case Packet.CONSUMER_INFO : {
ConsumerInfo info = (ConsumerInfo) packet;
consumeConsumerInfo(info);
break;
}
case Packet.PRODUCER_INFO : {
ProducerInfo info = (ProducerInfo) packet;
consumeProducerInfo(info);
break;
}
case Packet.SESSION_INFO : {
SessionInfo info = (SessionInfo) packet;
consumeSessionInfo(info);
break;
}
case Packet.ACTIVEMQ_CONNECTION_INFO : {
ConnectionInfo info = (ConnectionInfo) packet;
consumeConnectionInfo(info);
break;
}
case Packet.DURABLE_UNSUBSCRIBE : {
DurableUnsubscribe ds = (DurableUnsubscribe) packet;
brokerConnector.durableUnsubscribe(this, ds);
break;
}
case Packet.CAPACITY_INFO : {
CapacityInfo info = (CapacityInfo) packet;
consumeCapacityInfo(info);
break;
}
case Packet.CAPACITY_INFO_REQUEST : {
updateCapacityInfo(packet.getId());
break;
}
case Packet.ACTIVEMQ_BROKER_INFO : {
consumeBrokerInfo((BrokerInfo) packet);
break;
}
case Packet.KEEP_ALIVE : {
// Ignore as the packet contains no additional information to consume
break;
}
case Packet.BROKER_ADMIN_COMMAND : {
consumeBrokerAdminCommand((BrokerAdminCommand) packet);
break;
}
case Packet.CLEANUP_CONNECTION_INFO : {
consumeCleanupConnectionInfo((CleanupConnectionInfo) packet);
break;
}
default : {
log.warn("Unknown Packet received: " + packet);
break;
}
}
}
}
catch (Throwable e) {
requestEx = e;
log.warn("caught exception consuming packet: " + packet, e);
failed = true;
}
if (receiptRequired){
sendReceipt(correlationId, requestEx, failed);
}
}
}
/**
* @param cleanupInfo
* @throws JMSException
*/
private void consumeCleanupConnectionInfo(CleanupConnectionInfo cleanupInfo) throws JMSException {
try {
for (Iterator i = consumers.iterator(); i.hasNext();) {
ConsumerInfo info = (ConsumerInfo) i.next();
info.setStarted(false);
this.brokerConnector.deregisterMessageConsumer(this, info);
}
for (Iterator i = producers.iterator(); i.hasNext();) {
ProducerInfo info = (ProducerInfo) i.next();
info.setStarted(false);
this.brokerConnector.deregisterMessageProducer(this, info);
}
for (Iterator i = sessions.iterator(); i.hasNext();) {
SessionInfo info = (SessionInfo) i.next();
info.setStarted(false);
this.brokerConnector.deregisterSession(this, info);
}
for (Iterator i = transactions.iterator(); i.hasNext();) {
this.brokerConnector.rollbackTransaction(this, i.next().toString());
}
this.brokerConnector.deregisterClient(this, connectionInfo);
registered = false;
} finally {
// whatever happens, lets make sure we unregister & clean things
// down
if (log.isDebugEnabled()) {
log.debug(this + " has stopped");
}
this.consumers.clear();
this.producers.clear();
this.transactions.clear();
this.sessions.clear();
}
}
/**
* @param command
* @throws JMSException
*/
private void consumeBrokerAdminCommand(BrokerAdminCommand command) throws JMSException {
BrokerAdmin brokerAdmin = brokerConnector.getBrokerContainer().getBroker().getBrokerAdmin();
if (BrokerAdminCommand.CREATE_DESTINATION.equals(command.getCommand())) {
brokerAdmin.createMessageContainer(command.getDestination());
}
else if (BrokerAdminCommand.DESTROY_DESTINATION.equals(command.getCommand())) {
brokerAdmin.destoryMessageContainer(command.getDestination());
}
else if (BrokerAdminCommand.EMPTY_DESTINATION.equals(command.getCommand())) {
brokerAdmin.getMessageContainerAdmin(command.getDestination()).empty();
}
else if (BrokerAdminCommand.SHUTDOWN_SERVER_VM.equals(command.getCommand())) {
if (Boolean.getBoolean("enable.vm.shutdown")) {
log.info("processing command=" + BrokerAdminCommand.SHUTDOWN_SERVER_VM);
System.exit(1);
} else
{
log.warn("ignoring command=" + BrokerAdminCommand.SHUTDOWN_SERVER_VM + ", enable.vm.shutdown=false");
}
}
else {
throw new JMSException("Broker Admin Command type: " + command.getCommand() + " not recognized.");
}
}
/**
* Register/deregister MessageConsumer with the Broker
*
* @param info
* @throws JMSException
*/
public void consumeConsumerInfo(ConsumerInfo info) throws JMSException {
String localBrokerName = brokerConnector.getBrokerInfo().getBrokerName();
if (info.isStarted()) {
consumers.add(info);
if (this.activeConsumers.add(info)) {
this.brokerConnector.registerMessageConsumer(this, info);
}
}
else {
consumers.remove(info);
if (activeConsumers.remove(info)) {
this.brokerConnector.deregisterMessageConsumer(this, info);
}
}
}
/**
* Update the peer Connection about the Broker's capacity for messages
*
* @param capacity
*/
public void updateBrokerCapacity(int capacity) {
CapacityInfo info = new CapacityInfo();
info.setResourceName(this.brokerConnector.getBrokerInfo().getBrokerName());
info.setCapacity(capacity);
info.setFlowControlTimeout(getFlowControlTimeout(capacity));
send(info);
}
/**
* register with the Broker
*
* @param info
* @throws JMSException
*/
public void consumeConnectionInfo(ConnectionInfo info) throws JMSException {
this.connectionInfo = info;
if (info.isClosed()) {
try {
cleanUp();
if (info.isReceiptRequired()){
sendReceipt(info.getId(), null, false);
}
info.setReceiptRequired(false);
try {
Thread.sleep(500);
}
catch (Throwable e) {
}
}
finally {
close();
}
}
else {
if (!registered) {
this.brokerConnector.registerClient(this, info);
registered = true;
}
synchronized (started) {
//set transport hint
if (info.getProperties() != null && info.getProperties().getProperty(ConnectionInfo.NO_DELAY_PROPERTY) != null){
boolean noDelay = new Boolean(info.getProperties().getProperty(ConnectionInfo.NO_DELAY_PROPERTY)).booleanValue();
channel.setNoDelay(noDelay);
}
if (!started.get() && info.isStarted()) {
started.set(true);
// Dispatch any queued
log.debug(this + " has started running client version " + info.getClientVersion()
+ " , wire format = " + info.getWireFormatVersion());
//go through consumers, producers, and sessions - setting their clientId (which might not have been set)
for (Iterator i = consumers.iterator();i.hasNext();) {
ConsumerInfo ci = (ConsumerInfo) i.next();
ci.setClientId(info.getClientId());
}
for (Iterator i = producers.iterator();i.hasNext();) {
ProducerInfo pi = (ProducerInfo) i.next();
pi.setClientId(info.getClientId());
}
for (Iterator i = sessions.iterator();i.hasNext();) {
SessionInfo si = (SessionInfo) i.next();
si.setClientId(info.getClientId());
}
for (int i = 0;i < dispatchQueue.size();i++) {
ActiveMQMessage msg = (ActiveMQMessage) dispatchQueue.get(i);
dispatch(msg);
}
dispatchQueue.clear();
}
if (started.get() && !info.isStarted()) {
started.set(false);
log.debug(this + " has stopped");
}
}
}
}
/**
* start consuming messages
*
* @throws JMSException
*/
public void start() throws JMSException {
channel.start();
}
/**
* stop consuming messages
*
* @throws JMSException
*/
public void stop() throws JMSException {
log.trace("Stopping channel: " + channel);
channel.stop();
}
/**
* cleanup
*/
public synchronized void cleanUp() {
// we could be called here from 2 different code paths
// based on if we get a transport failure or we do a clean shutdown
// so lets only run this stuff once
if (!cleanedUp) {
cleanedUp = true;
try {
try {
for (Iterator i = consumers.iterator();i.hasNext();) {
ConsumerInfo info = (ConsumerInfo) i.next();
info.setStarted(false);
this.brokerConnector.deregisterMessageConsumer(this, info);
}
for (Iterator i = producers.iterator();i.hasNext();) {
ProducerInfo info = (ProducerInfo) i.next();
info.setStarted(false);
this.brokerConnector.deregisterMessageProducer(this, info);
}
for (Iterator i = sessions.iterator();i.hasNext();) {
SessionInfo info = (SessionInfo) i.next();
info.setStarted(false);
this.brokerConnector.deregisterSession(this, info);
}
for (Iterator i = transactions.iterator();i.hasNext();) {
this.brokerConnector.rollbackTransaction(this, i.next().toString());
}
}
finally {
// whatever happens, lets make sure we unregister & clean things down
if (log.isDebugEnabled()) {
log.debug(this + " has stopped");
}
this.consumers.clear();
this.producers.clear();
this.transactions.clear();
this.sessions.clear();
this.brokerConnector.deregisterClient(this, connectionInfo);
registered = false;
}
}
catch (JMSException e) {
log.warn("failed to de-register Broker client: " + e, e);
}
}
else {
log.debug("We are ignoring a duplicate cleanup() method called for: " + this);
}
}
// Implementation methods
//-------------------------------------------------------------------------
protected void send(Packet packet) {
if (!closed.get()) {
try {
if (brokerConnection) {
String brokerName = brokerConnector.getBrokerContainer().getBroker().getBrokerName();
packet.addBrokerVisited(brokerName);
if (packet.hasVisited(remoteBrokerName)) {
if (log.isDebugEnabled()) {
log.debug("Not Forwarding: " + remoteBrokerName + " has already been visited by packet: "
+ packet);
}
return;
}
}
packet.setId(this.packetIdGenerator.getNextShortSequence());
if( commandLog.isDebugEnabled() )
commandLog.debug("broker for "+getClientID()+" sending: "+packet);
this.channel.asyncSend(packet);
}
catch (JMSException e) {
log.warn(this + " caught exception ", e);
close();
}
}
}
/**
* validate the connection
* @param timeout
* @throws JMSException
*/
public void validateConnection(int timeout) throws JMSException {
KeepAlive packet = new KeepAlive();
packet.setReceiptRequired(true);
packet.setId(this.packetIdGenerator.getNextShortSequence());
// In most cases, if the transport is dead due to network errors
// the network error will be recognised immediately and an exception
// thrown. If the duplicate client ids are due to misconfiguration,
// we make sure that we do not terminate the "right" connection
// prematurely by using a long timeout here. If the existing client
// is working heavily and/or over a slow link, it might take some time
// for it to respond. In such a case, the new client is misconfigured
// and can wait for a while before being kicked out.
Receipt r = getChannel().send(packet, timeout);
if (r == null) throw new JMSException("Client did not respond in time");
}
protected void close() {
if (closed.commit(false, true)) {
this.channel.stop();
log.debug(this + " has closed");
}
}
/**
* Send message to Broker
*
* @param message
* @throws JMSException
*/
private void consumeActiveMQMessage(ActiveMQMessage message) throws JMSException {
this.brokerConnector.sendMessage(this, message);
}
/**
* Send Message acknowledge to the Broker
*
* @param ack
* @throws JMSException
*/
private void consumeMessageAck(MessageAck ack) throws JMSException {
this.brokerConnector.acknowledgeMessage(this, ack);
}
/**
* Handle transaction start/commit/rollback
*
* @param info
* @throws JMSException
*/
private void consumeTransactionInfo(TransactionInfo info) throws JMSException {
if (info.getType() == TransactionInfo.START) {
transactions.add(info.getTransactionId());
this.brokerConnector.startTransaction(this, info.getTransactionId());
}
else {
if (info.getType() == TransactionInfo.ROLLBACK) {
this.brokerConnector.rollbackTransaction(this, info.getTransactionId());
}
else if (info.getType() == TransactionInfo.COMMIT) {
this.brokerConnector.commitTransaction(this, info.getTransactionId());
}
transactions.remove(info.getTransactionId());
}
}
/**
* Handle XA transaction start/prepare/commit/rollback
*
* @param info
* @throws JMSException
* @throws XAException
*/
private void consumeXATransactionInfo(XATransactionInfo info) throws JMSException, XAException {
if (info.getType() == XATransactionInfo.START) {
this.brokerConnector.startTransaction(this, info.getXid());
}
else if (info.getType() == XATransactionInfo.XA_RECOVER) {
ActiveMQXid rc[] = this.brokerConnector.getPreparedTransactions(this);
if( info.isReceiptRequired()) {
// We will be sending our own receipt..
info.setReceiptRequired(false);
// Send the receipt..
ResponseReceipt receipt = new ResponseReceipt();
receipt.setCorrelationId(info.getId());
receipt.setResult(rc);
send(receipt);
}
}
else if (info.getType() == XATransactionInfo.GET_RM_ID) {
String rc = this.brokerConnector.getResourceManagerId(this);
if( info.isReceiptRequired()) {
// We will be sending our own receipt..
info.setReceiptRequired(false);
// Send the receipt..
ResponseReceipt receipt = new ResponseReceipt();
receipt.setId(this.packetIdGenerator.getNextShortSequence());
receipt.setCorrelationId(info.getId());
receipt.setResult(rc);
send(receipt);
}
}
else if (info.getType() == XATransactionInfo.END) {
// we don't do anything..
}
else {
if (info.getType() == XATransactionInfo.PRE_COMMIT) {
int rc = this.brokerConnector.prepareTransaction(this, info.getXid());
// We will be sending our own receipt..
if( info.isReceiptRequired()) {
info.setReceiptRequired(false);
// Send the receipt..
IntResponseReceipt receipt = new IntResponseReceipt();
receipt.setId(this.packetIdGenerator.getNextShortSequence());
receipt.setCorrelationId(info.getId());
receipt.setResult(rc);
send(receipt);
}
}
else if (info.getType() == XATransactionInfo.ROLLBACK) {
this.brokerConnector.rollbackTransaction(this, info.getXid());
}
else if (info.getType() == XATransactionInfo.COMMIT_ONE_PHASE) {
this.brokerConnector.commitTransaction(this, info.getXid(), true);
}
else if (info.getType() == XATransactionInfo.COMMIT) {
this.brokerConnector.commitTransaction(this, info.getXid(), false);
}
else {
throw new JMSException("Packet type: " + info.getType() + " not recognized.");
}
}
}
/**
* register/deregister MessageProducer in the Broker
*
* @param info
* @throws JMSException
*/
private void consumeProducerInfo(ProducerInfo info) throws JMSException {
if (info.isStarted()) {
producers.add(info);
this.brokerConnector.registerMessageProducer(this, info);
}
else {
producers.remove(info);
this.brokerConnector.deregisterMessageProducer(this, info);
}
}
/**
* register/deregister Session in a Broker
*
* @param info
* @throws JMSException
*/
private void consumeSessionInfo(SessionInfo info) throws JMSException {
if (info.isStarted()) {
sessions.add(info);
this.brokerConnector.registerSession(this, info);
}
else {
sessions.remove(info);
this.brokerConnector.deregisterSession(this, info);
}
}
/**
* Update capacity for the peer
*
* @param info
*/
private void consumeCapacityInfo(CapacityInfo info) {
this.capacity = info.getCapacity();
}
private void updateCapacityInfo(short correlationId) {
CapacityInfo info = new CapacityInfo();
info.setResourceName(this.brokerConnector.getBrokerInfo().getBrokerName());
info.setCorrelationId(correlationId);
info.setCapacity(this.brokerConnector.getBrokerCapacity());
info.setFlowControlTimeout(getFlowControlTimeout(info.getCapacity()));
send(info);
}
private long getFlowControlTimeout(int capacity) {
long result = -1;
if (capacity <= 0) {
result = 10000;
}
else if (capacity <= 10) {
result = 1000;
}
else if (capacity <= 20) {
result = 10;
}
return result;
}
private void consumeBrokerInfo(final BrokerInfo info) {
brokerConnection = true;
started.set(true);
remoteBrokerName = info.getBrokerName();
if (remoteBrokerName == null || remoteBrokerName.length() == 0) {
log.warn("No remote broker name available!");
}
else {
if (log.isDebugEnabled()) {
log.debug("Received broker info from: " + remoteBrokerName + " on client: " + channel);
}
}
String clusterName = getBrokerConnector().getBrokerContainer().getBroker().getBrokerClusterName();
if (clusterName.equals(info.getClusterName())) {
clusteredConnection = true;
}
if (!remoteNetworkConnector && info.isRemote()) {
try {
final NetworkConnector networkConnector = new NetworkConnector(brokerConnector.getBrokerContainer());
networkConnector.getThreadPool().execute(new Runnable() {
public void run() {
try {
NetworkChannel networkChannel = new NetworkChannel(networkConnector, brokerConnector
.getBrokerContainer(), channel, info.getBrokerName(), info.getClusterName());
networkConnector.addNetworkChannel(networkChannel);
brokerConnector.getBrokerContainer().addNetworkConnector(networkConnector);
networkConnector.start();
}
catch (JMSException e) {
log.error("Failed to create reverse remote channel", e);
}
}
});
log.info("Started reverse remote channel to " + remoteBrokerName);
remoteNetworkConnector = true;
}
catch (InterruptedException e) {
log.error("Failed to create reverse remote channel", e);
}
}
}
private void sendReceipt(short correlationId, Throwable requestEx, boolean failed) {
Receipt receipt = new Receipt();
receipt.setCorrelationId(correlationId);
receipt.setBrokerName(brokerConnector.getBrokerInfo().getBrokerName());
receipt.setClusterName(brokerConnector.getBrokerInfo().getClusterName());
receipt.setException(requestEx);
receipt.setFailed(failed);
send(receipt);
}
/**
* @param subject
*/
public void setSubject(Subject subject) {
this.subject = subject;
}
/**
* @return the subject
*/
public Subject getSubject() {
return subject;
}
}