public void send(Request request, List<Response.ResponseListener> listeners) { if (!scheme.equals(request.getScheme())) throw new IllegalArgumentException( "Invalid request scheme " + request.getScheme() + " for destination " + this); if (!getHost().equals(request.getHost())) throw new IllegalArgumentException( "Invalid request host " + request.getHost() + " for destination " + this); int port = request.getPort(); if (port >= 0 && getPort() != port) throw new IllegalArgumentException( "Invalid request port " + port + " for destination " + this); HttpConversation conversation = client.getConversation(request.getConversationID(), true); HttpExchange exchange = new HttpExchange(conversation, this, request, listeners); if (client.isRunning()) { if (exchanges.offer(exchange)) { if (!client.isRunning() && exchanges.remove(exchange)) { throw new RejectedExecutionException(client + " is stopping"); } else { LOG.debug("Queued {}", request); requestNotifier.notifyQueued(request); Connection connection = acquire(); if (connection != null) process(connection, false); } } else { throw new RejectedExecutionException( "Max requests per destination " + client.getMaxRequestsQueuedPerDestination() + " exceeded"); } } else { throw new RejectedExecutionException(client + " is stopped"); } }
/** * 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); } } }
protected void send(HttpRequest request, List<Response.ResponseListener> listeners) { if (!getScheme().equals(request.getScheme())) throw new IllegalArgumentException( "Invalid request scheme " + request.getScheme() + " for destination " + this); if (!getHost().equals(request.getHost())) throw new IllegalArgumentException( "Invalid request host " + request.getHost() + " for destination " + this); int port = request.getPort(); if (port >= 0 && getPort() != port) throw new IllegalArgumentException( "Invalid request port " + port + " for destination " + this); HttpExchange exchange = new HttpExchange(this, request, listeners); if (client.isRunning()) { if (enqueue(exchanges, exchange)) { if (!client.isRunning() && exchanges.remove(exchange)) { request.abort(new RejectedExecutionException(client + " is stopping")); } else { if (LOG.isDebugEnabled()) LOG.debug("Queued {} for {}", request, this); requestNotifier.notifyQueued(request); send(); } } else { if (LOG.isDebugEnabled()) LOG.debug( "Max queue size {} exceeded by {} for {}", client.getMaxRequestsQueuedPerDestination(), request, this); request.abort( new RejectedExecutionException( "Max requests per destination " + client.getMaxRequestsQueuedPerDestination() + " exceeded for " + this)); } } else { request.abort(new RejectedExecutionException(client + " is stopped")); } }
public void release(Connection connection) { LOG.debug("{} released", connection); if (client.isRunning()) { boolean removed = activeConnections.remove(connection); if (removed) process(connection, false); else LOG.debug("{} explicit", connection); } else { LOG.debug("{} is stopped", client); remove(connection); connection.close(); } }
@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(); } }
/** * 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 * @param dispatch whether to dispatch the processing to another thread */ protected void process(Connection connection, boolean dispatch) { // Ugly cast, but lack of generic reification forces it final HttpConnection httpConnection = (HttpConnection) connection; final HttpExchange exchange = exchanges.poll(); if (exchange == null) { LOG.debug("{} idle", httpConnection); if (!idleConnections.offer(httpConnection)) { LOG.debug("{} idle overflow"); httpConnection.close(); } if (!client.isRunning()) { LOG.debug("{} is stopping", client); remove(httpConnection); httpConnection.close(); } } else { final Request request = exchange.getRequest(); Throwable cause = request.getAbortCause(); if (cause != null) { abort(exchange, cause); LOG.debug("Aborted before processing {}: {}", exchange, cause); } else { LOG.debug("{} active", httpConnection); if (!activeConnections.offer(httpConnection)) { LOG.warn("{} active overflow"); } if (dispatch) { client .getExecutor() .execute( new Runnable() { @Override public void run() { httpConnection.send(exchange); } }); } else { httpConnection.send(exchange); } } } }