예제 #1
0
 /**
  * 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();
   }
 }
예제 #2
0
 public void stop() {
   StoppableExecutor executor;
   lock.lock();
   try {
     executor = this.executor;
   } finally {
     lock.unlock();
   }
   if (executor != null) {
     executor.stop();
   }
 }
예제 #3
0
 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();
   }
 }
예제 #4
0
  /**
   * 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();
    }
  }
예제 #5
0
 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();
   }
 }
예제 #6
0
 /**
  * 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();
     }
   }
 }
예제 #7
0
  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);
            }
          }
        });
  }