protected void processDispatch(Command command) throws IOException { MessageDispatch messageDispatch = (MessageDispatch) (command.isMessageDispatch() ? command : null); try { if (!stopping.get()) { if (messageDispatch != null) { protocolManager.preProcessDispatch(messageDispatch); } dispatch(command); } } catch (IOException e) { if (messageDispatch != null) { TransmitCallback sub = messageDispatch.getTransmitCallback(); protocolManager.postProcessDispatch(messageDispatch); if (sub != null) { sub.onFailure(); } messageDispatch = null; throw e; } } finally { if (messageDispatch != null) { TransmitCallback sub = messageDispatch.getTransmitCallback(); protocolManager.postProcessDispatch(messageDispatch); if (sub != null) { sub.onSuccess(); } } } }
private AMQProducerBrokerExchange getProducerBrokerExchange(ProducerId id) throws IOException { AMQProducerBrokerExchange result = producerExchanges.get(id); if (result == null) { synchronized (producerExchanges) { result = new AMQProducerBrokerExchange(); result.setConnectionContext(context); // todo implement reconnect https://issues.apache.org/jira/browse/ARTEMIS-194 if (context.isReconnect() || (context.isNetworkConnection() && this.acceptorUsed.isAuditNetworkProducers())) { if (protocolManager.getPersistenceAdapter() != null) { result.setLastStoredSequenceId( protocolManager.getPersistenceAdapter().getLastProducerSequenceId(id)); } } SessionState ss = state.getSessionState(id.getParentId()); if (ss != null) { result.setProducerState(ss.getProducerState(id)); ProducerState producerState = ss.getProducerState(id); if (producerState != null && producerState.getInfo() != null) { ProducerInfo info = producerState.getInfo(); result.setMutable(info.getDestination() == null || info.getDestination().isComposite()); } } producerExchanges.put(id, result); } } return result; }
@Override public Response processAddSession(SessionInfo info) throws Exception { // Avoid replaying dup commands if (!state.getSessionIds().contains(info.getSessionId())) { protocolManager.addSession(this, info); try { state.addSession(info); } catch (IllegalStateException e) { e.printStackTrace(); protocolManager.removeSession(context, info); } } return null; }
protected void doStop() throws Exception { this.acceptorUsed.onStopped(this); /* * What's a duplex bridge? try { synchronized (this) { if (duplexBridge != * null) { duplexBridge.stop(); } } } catch (Exception ignore) { * LOG.trace("Exception caught stopping. This exception is ignored.", * ignore); } */ try { getTransportConnection().close(); } catch (Exception e) { // log } if (taskRunner != null) { taskRunner.shutdown(1); taskRunner = null; } active = false; // Run the MessageDispatch callbacks so that message references get // cleaned up. synchronized (dispatchQueue) { for (Iterator<Command> iter = dispatchQueue.iterator(); iter.hasNext(); ) { Command command = iter.next(); if (command.isMessageDispatch()) { MessageDispatch md = (MessageDispatch) command; TransmitCallback sub = md.getTransmitCallback(); protocolManager.postProcessDispatch(md); if (sub != null) { sub.onFailure(); } } } dispatchQueue.clear(); } // // Remove all logical connection associated with this connection // from the broker. if (!protocolManager.isStopped()) { context.getStopping().set(true); try { processRemoveConnection(state.getInfo().getConnectionId(), 0L); } catch (Throwable ignore) { ignore.printStackTrace(); } } }
@Override public Response processRollbackTransaction(TransactionInfo info) throws Exception { protocolManager.rollbackTransaction(info); TransactionId txId = info.getTransactionId(); txMap.remove(txId); return null; }
public void dispatchAsync(Command message) { if (!stopping.get()) { if (taskRunner == null) { dispatchSync(message); } else { synchronized (dispatchQueue) { dispatchQueue.add(message); } try { taskRunner.wakeup(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } else { if (message.isMessageDispatch()) { MessageDispatch md = (MessageDispatch) message; TransmitCallback sub = md.getTransmitCallback(); protocolManager.postProcessDispatch(md); if (sub != null) { sub.onFailure(); } } } }
@Override public Response processRemoveSession(SessionId id, long lastDeliveredSequenceId) throws Exception { SessionState session = state.getSessionState(id); if (session == null) { throw new IllegalStateException("Cannot remove session that had not been registered: " + id); } // Don't let new consumers or producers get added while we are closing // this down. session.shutdown(); // Cascade the connection stop to the consumers and producers. for (ConsumerId consumerId : session.getConsumerIds()) { try { processRemoveConsumer(consumerId, lastDeliveredSequenceId); } catch (Throwable e) { // LOG.warn("Failed to remove consumer: {}", consumerId, e); } } for (ProducerId producerId : session.getProducerIds()) { try { processRemoveProducer(producerId); } catch (Throwable e) { // LOG.warn("Failed to remove producer: {}", producerId, e); } } state.removeSession(id); protocolManager.removeSession(context, session.getInfo()); return null; }
private void deleteTempQueues() throws Exception { Iterator<String> queueNames = tempQueues.iterator(); while (queueNames.hasNext()) { String q = queueNames.next(); protocolManager.deleteQueue(q); } }
@Override public Response processCommitTransactionTwoPhase(TransactionInfo info) throws Exception { protocolManager.commitTransactionTwoPhase(info); TransactionId txId = info.getTransactionId(); txMap.remove(txId); return null; }
@Override public Response processForgetTransaction(TransactionInfo info) throws Exception { TransactionId txId = info.getTransactionId(); txMap.remove(txId); protocolManager.forgetTransaction(info.getTransactionId()); return null; }
public void deliverMessage(MessageDispatch dispatch) { Message m = dispatch.getMessage(); if (m != null) { long endTime = System.currentTimeMillis(); m.setBrokerOutTime(endTime); } protocolManager.send(this, dispatch); }
@Override public Response processRemoveDestination(DestinationInfo info) throws Exception { ActiveMQDestination dest = info.getDestination(); if (dest.isQueue()) { String qName = "jms.queue." + dest.getPhysicalName(); protocolManager.deleteQueue(qName); } return null; }
@Override public Response processEndTransaction(TransactionInfo info) throws Exception { protocolManager.endTransaction(info); TransactionId txId = info.getTransactionId(); if (!txMap.containsKey(txId)) { txMap.put(txId, info); } return null; }
@Override public Response processMessage(Message messageSend) { Response resp = null; try { ProducerId producerId = messageSend.getProducerId(); AMQProducerBrokerExchange producerExchange = getProducerBrokerExchange(producerId); final AMQConnectionContext pcontext = producerExchange.getConnectionContext(); final ProducerInfo producerInfo = producerExchange.getProducerState().getInfo(); boolean sendProducerAck = !messageSend.isResponseRequired() && producerInfo.getWindowSize() > 0 && !pcontext.isInRecoveryMode(); AMQSession session = protocolManager.getSession(producerId.getParentId()); if (producerExchange.canDispatch(messageSend)) { SendingResult result = session.send(producerExchange, messageSend, sendProducerAck); if (result.isBlockNextSend()) { if (!context.isNetworkConnection() && result.isSendFailIfNoSpace()) { throw new ResourceAllocationException( "Usage Manager Memory Limit reached. Stopping producer (" + producerId + ") to prevent flooding " + result.getBlockingAddress() + "." + " See http://activemq.apache.org/producer-flow-control.html for more info"); } if (producerInfo.getWindowSize() > 0 || messageSend.isResponseRequired()) { // in that case don't send the response // this will force the client to wait until // the response is got. context.setDontSendReponse(true); } else { // hang the connection until the space is available session.blockingWaitForSpace(producerExchange, result); } } else if (sendProducerAck) { ProducerAck ack = new ProducerAck(producerInfo.getProducerId(), messageSend.getSize()); this.dispatchAsync(ack); } } } catch (Throwable e) { if (e instanceof ActiveMQSecurityException) { resp = new ExceptionResponse(new JMSSecurityException(e.getMessage())); } else { resp = new ExceptionResponse(e); } } return resp; }
@Override public Response processAddDestination(DestinationInfo dest) throws Exception { Response resp = null; try { protocolManager.addDestination(this, dest); } catch (Exception e) { if (e instanceof ActiveMQSecurityException) { resp = new ExceptionResponse(new JMSSecurityException(e.getMessage())); } else { resp = new ExceptionResponse(e); } } return resp; }
@Override public Response processAddConsumer(ConsumerInfo info) { Response resp = null; try { protocolManager.addConsumer(this, info); } catch (Exception e) { if (e instanceof ActiveMQSecurityException) { resp = new ExceptionResponse(new JMSSecurityException(e.getMessage())); } else { resp = new ExceptionResponse(e); } } return resp; }
@Override public Response processAddProducer(ProducerInfo info) throws Exception { Response resp = null; try { protocolManager.addProducer(this, info); } catch (Exception e) { if (e instanceof ActiveMQSecurityException) { resp = new ExceptionResponse(new JMSSecurityException(e.getMessage())); } else if (e instanceof ActiveMQNonExistentQueueException) { resp = new ExceptionResponse(new InvalidDestinationException(e.getMessage())); } else { resp = new ExceptionResponse(e); } } return resp; }
@Override public Response processRemoveConnection(ConnectionId id, long lastDeliveredSequenceId) throws Exception { // Don't allow things to be added to the connection state while we // are shutting down. state.shutdown(); // Cascade the connection stop to the sessions. for (SessionId sessionId : state.getSessionIds()) { try { processRemoveSession(sessionId, lastDeliveredSequenceId); } catch (Throwable e) { // LOG } } try { protocolManager.removeConnection(context, state.getInfo(), null); } catch (Throwable e) { // log } return null; }
private void negotiate(WireFormatInfo command) throws IOException { this.wireFormat.renegotiateWireFormat(command); // throw back a brokerInfo here protocolManager.sendBrokerInfo(this); }
@Override public Response processPrepareTransaction(TransactionInfo info) throws Exception { protocolManager.prepareTransaction(info); return null; }
@Override public Response processRecoverTransactions(TransactionInfo info) throws Exception { Set<SessionId> sIds = state.getSessionIds(); TransactionId[] recovered = protocolManager.recoverTransactions(sIds); return new DataArrayResponse(recovered); }
@Override public Response processRemoveProducer(ProducerId id) throws Exception { protocolManager.removeProducer(id); return null; }
@Override public Response processRemoveSubscription(RemoveSubscriptionInfo subInfo) throws Exception { protocolManager.removeSubscription(subInfo); return null; }
@Override public Response processAddConnection(ConnectionInfo info) throws Exception { WireFormatInfo wireFormatInfo = wireFormat.getPreferedWireFormatInfo(); // Older clients should have been defaulting this field to true.. but // they were not. if (wireFormatInfo != null && wireFormatInfo.getVersion() <= 2) { info.setClientMaster(true); } state = new ConnectionState(info); context = new AMQConnectionContext(); state.reset(info); this.faultTolerantConnection = info.isFaultTolerant(); // Setup the context. String clientId = info.getClientId(); context.setBroker(protocolManager); context.setClientId(clientId); context.setClientMaster(info.isClientMaster()); context.setConnection(this); context.setConnectionId(info.getConnectionId()); // for now we pass the manager as the connector and see what happens // it should be related to activemq's Acceptor context.setConnector(this.acceptorUsed); context.setMessageAuthorizationPolicy(getMessageAuthorizationPolicy()); context.setNetworkConnection(networkConnection); context.setFaultTolerant(faultTolerantConnection); context.setTransactions(new ConcurrentHashMap<TransactionId, AMQTransaction>()); context.setUserName(info.getUserName()); context.setWireFormatInfo(wireFormatInfo); context.setReconnect(info.isFailoverReconnect()); this.manageable = info.isManageable(); context.setConnectionState(state); if (info.getClientIp() == null) { info.setClientIp(getRemoteAddress()); } try { protocolManager.addConnection(context, info); } catch (Exception e) { if (e instanceof SecurityException) { // close this down - in case the peer of this transport doesn't play // nice delayedStop(2000, "Failed with SecurityException: " + e.getLocalizedMessage(), e); } Response resp = new ExceptionResponse(e); return resp; } if (info.isManageable()) { // send ConnectionCommand ConnectionControl command = this.acceptorUsed.getConnectionControl(); command.setFaultTolerant(protocolManager.isFaultTolerantConfiguration()); if (info.isFailoverReconnect()) { command.setRebalanceConnection(false); } dispatchAsync(command); } return null; }
// throw a WireFormatInfo to the peer public void init() { WireFormatInfo info = wireFormat.getPreferedWireFormatInfo(); protocolManager.send(this, info); }
@Override public void bufferReceived(Object connectionID, ActiveMQBuffer buffer) { try { dataReceived = true; Command command = (Command) wireFormat.unmarshal(buffer); boolean responseRequired = command.isResponseRequired(); int commandId = command.getCommandId(); // the connection handles pings, negotiations directly. // and delegate all other commands to manager. if (command.getClass() == KeepAliveInfo.class) { KeepAliveInfo info = (KeepAliveInfo) command; info.setResponseRequired(false); // if we don't respond to KeepAlive commands then the client will think the server is dead // and timeout // for some reason KeepAliveInfo.isResponseRequired() is always false protocolManager.sendReply(this, info); } else if (command.getClass() == WireFormatInfo.class) { // amq here starts a read/write monitor thread (detect ttl?) negotiate((WireFormatInfo) command); } else if (command.getClass() == ConnectionInfo.class || command.getClass() == ConsumerInfo.class || command.getClass() == RemoveInfo.class || command.getClass() == SessionInfo.class || command.getClass() == ProducerInfo.class || ActiveMQMessage.class.isAssignableFrom(command.getClass()) || command.getClass() == MessageAck.class || command.getClass() == TransactionInfo.class || command.getClass() == DestinationInfo.class || command.getClass() == ShutdownInfo.class || command.getClass() == RemoveSubscriptionInfo.class) { Response response = null; if (pendingStop) { response = new ExceptionResponse(this.stopError); } else { response = ((Command) command).visit(this); if (response instanceof ExceptionResponse) { if (!responseRequired) { Throwable cause = ((ExceptionResponse) response).getException(); serviceException(cause); response = null; } } } if (responseRequired) { if (response == null) { response = new Response(); } } // The context may have been flagged so that the response is not // sent. if (context != null) { if (context.isDontSendReponse()) { context.setDontSendReponse(false); response = null; } } if (response != null && !protocolManager.isStopping()) { response.setCorrelationId(commandId); dispatchSync(response); } } else { // note!!! wait for negotiation (e.g. use a countdown latch) // before handling any other commands this.protocolManager.handleCommand(this, command); } } catch (IOException e) { ActiveMQServerLogger.LOGGER.error("error decoding", e); } catch (Throwable t) { ActiveMQServerLogger.LOGGER.error("error decoding", t); } }