@Override
  public synchronized void stop() {
    if (!live) {
      return;
    }
    live = false;
    logger.finest("Stopping ConnectionManager");

    if (acceptorThread != null) {
      acceptorThread.shutdown();
    }

    for (SocketChannelWrapper socketChannel : acceptedSockets) {
      closeResource(socketChannel);
    }
    for (Connection conn : connectionsMap.values()) {
      destroySilently(conn);
    }
    for (TcpIpConnection conn : activeConnections) {
      destroySilently(conn);
    }
    ioThreadingModel.shutdown();
    acceptedSockets.clear();
    connectionsInProgress.clear();
    connectionsMap.clear();
    monitors.clear();
    activeConnections.clear();
  }
  @Override
  public void destroyConnection(final Connection connection) {
    if (connection == null) {
      return;
    }
    if (logger.isFinestEnabled()) {
      logger.finest("Destroying " + connection);
    }

    if (activeConnections.remove(connection)) {
      // this should not be needed; but some tests are using DroppingConnection which is not a
      // TcpIpConnection.
      if (connection instanceof TcpIpConnection) {
        ioThreadingModel.onConnectionRemoved((TcpIpConnection) connection);
      }
    }
    final Address endPoint = connection.getEndPoint();
    if (endPoint != null) {
      connectionsInProgress.remove(endPoint);
      connectionsMap.remove(endPoint, connection);
      fireConnectionRemovedEvent(connection, endPoint);
    }
    if (connection.isAlive()) {
      connection.close();
      closedCount.inc();
    }
  }
  @Override
  public synchronized void start() {
    if (live) {
      return;
    }
    if (!serverSocketChannel.isOpen()) {
      throw new IllegalStateException("ConnectionManager is already shutdown. Cannot start!");
    }

    live = true;
    logger.finest("Starting ConnectionManager and IO selectors.");

    ioThreadingModel.start();
    startAcceptorThread();
  }
  TcpIpConnection newConnection(SocketChannelWrapper channel, Address endpoint) {
    TcpIpConnection connection =
        new TcpIpConnection(this, connectionIdGen.incrementAndGet(), channel, ioThreadingModel);

    connection.setEndPoint(endpoint);
    activeConnections.add(connection);
    acceptedSockets.remove(channel);

    connection.start();
    ioThreadingModel.onConnectionAdded(connection);

    logger.info(
        "Established socket connection between "
            + channel.socket().getLocalSocketAddress()
            + " and "
            + channel.socket().getRemoteSocketAddress());
    openedCount.inc();

    return connection;
  }