/** * Adds a connection to some other message hub. Outgoing messages are forwarded to this * connection, and incoming messages are received from it. * * <p>Does not cleanup connections on stop or disconnect. It is the caller's responsibility to * manage the connection lifecycle. */ public void addConnection(RemoteConnection<InterHubMessage> connection) { lock.lock(); try { assertRunning("add connection"); ConnectionState connectionState = connections.add(connection); workers.execute(new ConnectionDispatch(connectionState)); workers.execute(new ConnectionReceive(connectionState)); } finally { lock.unlock(); } }
public void stop() { StoppableExecutor executor; lock.lock(); try { executor = this.executor; } finally { lock.unlock(); } if (executor != null) { executor.stop(); } }
private void stopConsuming() { StoppableExecutor executor; lock.lock(); try { stdin.clear(); removed = true; condition.signalAll(); executor = this.executor; } finally { lock.unlock(); } if (executor != null) { executor.stop(); } }
/** * Adds a handler for messages on the given channel. The handler may implement any of the * following: * * <ul> * <li>{@link Dispatch} to handle incoming messages received from any connections attached to * this hub. Each incoming message is passed to exactly one handler associated to the given * channel. * <li>{@link RejectedMessageListener} to receive notifications of outgoing messages that cannot * be sent on the given channel. * <li>{@link BoundedDispatch} to receive notifications of the end of incoming messages. * </ul> * * <p>The given handler does not need to be thread-safe, and is notified by at most one thread at * a time. Multiple handlers can be added for a given channel. * * <p>NOTE: If any method of the handler fails with an exception, the handler is discarded and * will receive no further notifications. */ public void addHandler(String channelName, Object handler) { lock.lock(); try { assertRunning("add handler"); RejectedMessageListener rejectedMessageListener; if (handler instanceof RejectedMessageListener) { rejectedMessageListener = (RejectedMessageListener) handler; } else { rejectedMessageListener = DISCARD; } Dispatch<Object> dispatch; if (handler instanceof Dispatch) { dispatch = (Dispatch) handler; } else { dispatch = DISCARD; } BoundedDispatch<Object> boundedDispatch; if (dispatch instanceof BoundedDispatch) { boundedDispatch = (BoundedDispatch) dispatch; } else { boundedDispatch = DISCARD; } ChannelIdentifier identifier = new ChannelIdentifier(channelName); EndPointQueue queue = incomingQueue.getChannel(identifier).newEndpoint(); workers.execute(new Handler(queue, dispatch, boundedDispatch, rejectedMessageListener)); } finally { lock.unlock(); } }
private void startConsuming(final StdinHandler handler) { lock.lock(); try { if (executor != null) { throw new UnsupportedOperationException("Multiple stdin handlers not supported."); } executor = executorFactory.create("Stdin handler"); executor.execute( new Runnable() { public void run() { while (true) { IoCommand command; lock.lock(); try { while (!removed && stdin.isEmpty()) { try { condition.await(); } catch (InterruptedException e) { throw UncheckedException.throwAsUncheckedException(e); } } if (removed) { return; } command = stdin.removeFirst(); } finally { lock.unlock(); } try { if (command instanceof CloseInput) { handler.onEndOfInput(); return; } else { handler.onInput((ForwardInput) command); } } catch (Exception e) { LOGGER.warn("Could not forward client stdin.", e); return; } } } }); } finally { lock.unlock(); } }
/** * Requests that this message hub stop. First requests stop as per {@link #requestStop()}, then * blocks until stop has completed. This means that: * * <ul> * <li>All calls to {@link Dispatch#dispatch(Object)} for outgoing messages have returned. * <li>All dispatches to handlers have completed. * <li>All internal threads have completed. * </ul> */ public void stop() { try { lock.lock(); try { requestStop(); } finally { lock.unlock(); } workers.stop(); } finally { lock.lock(); try { state = State.Stopped; } finally { lock.unlock(); } } }
public DefaultDaemonConnection( final Connection<Object> connection, ExecutorFactory executorFactory) { this.connection = connection; stdinQueue = new StdinQueue(executorFactory); disconnectQueue = new DisconnectQueue(); receiveQueue = new ReceiveQueue(); executor = executorFactory.create("Handler for " + connection.toString()); executor.execute( new Runnable() { public void run() { Throwable failure = null; try { while (true) { Object message; try { message = connection.receive(); } catch (Exception e) { LOGGER.debug("Could not receive message from client.", e); failure = e; return; } if (message == null) { LOGGER.debug("Received end-of-input from client."); return; } if (!(message instanceof IoCommand)) { LOGGER.debug("Received non-IO message from client: {}", message); receiveQueue.add(message); } else { LOGGER.debug("Received IO message from client: {}", message); stdinQueue.add((IoCommand) message); } } } finally { stdinQueue.disconnect(); disconnectQueue.disconnect(); receiveQueue.disconnect(failure); } } }); }