/** * Processes a new connection making it idle or active depending on whether requests are waiting * to be sent. * * <p>A new connection is created when a request needs to be executed; it is possible that the * request that triggered the request creation is executed by another connection that was just * released, so the new connection may become idle. * * <p>If a request is waiting to be executed, it will be dequeued and executed by the new * connection. * * @param connection the new connection */ public void process(final C connection) { HttpClient client = getHttpClient(); final HttpExchange exchange = getHttpExchanges().poll(); if (LOG.isDebugEnabled()) LOG.debug("Processing exchange {} on {} of {}", exchange, connection, this); if (exchange == null) { if (!connectionPool.release(connection)) connection.close(); if (!client.isRunning()) { if (LOG.isDebugEnabled()) LOG.debug("{} is stopping", client); connection.close(); } } else { final Request request = exchange.getRequest(); Throwable cause = request.getAbortCause(); if (cause != null) { if (LOG.isDebugEnabled()) LOG.debug("Aborted before processing {}: {}", exchange, cause); // It may happen that the request is aborted before the exchange // is created. Aborting the exchange a second time will result in // a no-operation, so we just abort here to cover that edge case. exchange.abort(cause); } else { send(connection, exchange); } } }
@Override public void release(Connection c) { @SuppressWarnings("unchecked") C connection = (C) c; if (LOG.isDebugEnabled()) LOG.debug("Released {}", connection); HttpClient client = getHttpClient(); if (client.isRunning()) { if (connectionPool.isActive(connection)) { if (connectionPool.release(connection)) send(); else connection.close(); } else { if (LOG.isDebugEnabled()) LOG.debug("Released explicit {}", connection); } } else { if (LOG.isDebugEnabled()) LOG.debug("{} is stopped", client); connection.close(); } }
@Override public void close() throws IOException { closed = true; service.shutdown(); try { service.awaitTermination(1, TimeUnit.SECONDS); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } chronicle.close(); }
/** * Stop routine will close the closeable -if not null - and set the reference to null afterwards * This operation does raise any exception on the close, though it does record it */ @Override protected void serviceStop() { C target = getCloseable(); if (target != null) { try { target.close(); } catch (IOException ioe) { noteFailure(ioe); } setCloseable(null); } }
@Override public void operationComplete(ChannelFuture future) throws Exception { String msg; if (local != null) { msg = String.format("Channel closed %s <--> %s.", local, remote); } else { msg = String.format( "Channel closed %s <--> %s.", future.channel().localAddress(), future.channel().remoteAddress()); } if (RpcBus.this.isClient()) { if (local != null) { logger.info(String.format(msg)); } } else { queue.channelClosed(new ChannelClosedException(msg)); } clientConnection.close(); }