private void returnConnection(final ConnectionHolder connectionHolder) {

        ClientStatistics stats = connectionHolder.clientConnection.getStatistics();
        this.requestCount.incrementAndGet();
        if(stats != null) {
            //we update the stats when the connection is closed
            this.read.addAndGet(stats.getRead());
            this.written.addAndGet(stats.getWritten());
            stats.reset();
        }

        HostThreadData hostData = getData();
        if (closed) {
            //the host has been closed
            IoUtils.safeClose(connectionHolder.clientConnection);
            ConnectionHolder con = hostData.availableConnections.poll();
            while (con != null) {
                IoUtils.safeClose(con.clientConnection);
                con = hostData.availableConnections.poll();
            }
            redistributeQueued(hostData);
            return;
        }

        //only do something if the connection is open. If it is closed then
        //the close setter will handle creating a new connection and decrementing
        //the connection count
        final ClientConnection connection = connectionHolder.clientConnection;
        if (connection.isOpen() && !connection.isUpgraded()) {
            CallbackHolder callback = hostData.awaitingConnections.poll();
            while (callback != null && callback.isCancelled()) {
                callback = hostData.awaitingConnections.poll();
            }
            if (callback != null) {
                if (callback.getTimeoutKey() != null) {
                    callback.getTimeoutKey().remove();
                }
                // Anything waiting for a connection is not expecting exclusivity.
                connectionReady(connectionHolder, callback.getCallback(), callback.getExchange(), false);
            } else {
                final int cachedConnectionCount = hostData.availableConnections.size();
                if (cachedConnectionCount >= maxCachedConnections) {
                    // Close the longest idle connection instead of the current one
                    final ConnectionHolder holder = hostData.availableConnections.poll();
                    if (holder != null) {
                        IoUtils.safeClose(holder.clientConnection);
                    }
                }
                hostData.availableConnections.add(connectionHolder);
                // If the soft max and ttl are configured
                if (timeToLive > 0) {
                    //we only start the timeout process once we have hit the core pool size
                    //otherwise connections could start timing out immediately once the core pool size is hit
                    //and if we never hit the core pool size then it does not make sense to start timers which are never
                    //used (as timers are expensive)
                    final long currentTime = System.currentTimeMillis();
                    connectionHolder.timeout = currentTime + timeToLive;
                    if(hostData.availableConnections.size() > coreCachedConnections) {
                        if (hostData.nextTimeout <= 0) {
                            hostData.timeoutKey = WorkerUtils.executeAfter(connection.getIoThread(), hostData.timeoutTask, timeToLive, TimeUnit.MILLISECONDS);
                            hostData.nextTimeout = connectionHolder.timeout;
                        }
                    }
                }
            }
        } else if (connection.isOpen() && connection.isUpgraded()) {
            //we treat upgraded connections as closed
            //as we do not want the connection pool filled with upgraded connections
            //if the connection is actually closed the close setter will handle it
            connection.getCloseSetter().set(null);
            handleClosedConnection(hostData, connectionHolder);
        }
    }
private void returnConnection ( final ConnectionHolder connectionHolder ) { ClientStatistics stats = connectionHolder . clientConnection . getStatistics ( ) ; this . requestCount . incrementAndGet ( ) ; if ( stats != null ) { this . read . addAndGet ( stats . getRead ( ) ) ; this . written . addAndGet ( stats . getWritten ( ) ) ; stats . reset ( ) ; } HostThreadData hostData = getData ( ) ; if ( closed ) { IoUtils . safeClose ( connectionHolder . clientConnection ) ; ConnectionHolder con = hostData . availableConnections . poll ( ) ; while ( con != null ) { IoUtils . safeClose ( con . clientConnection ) ; con = hostData . availableConnections . poll ( ) ; } redistributeQueued ( hostData ) ; return ; } final ClientConnection connection = connectionHolder . clientConnection ; if ( connection . isOpen ( ) && ! connection . isUpgraded ( ) ) { CallbackHolder callback = hostData . awaitingConnections . poll ( ) ; while ( callback != null && callback . isCancelled ( ) ) { callback = hostData . awaitingConnections . poll ( ) ; } if ( callback != null ) { if ( callback . getTimeoutKey ( ) != null ) { callback . getTimeoutKey ( ) . remove ( ) ; } connectionReady ( connectionHolder , callback . getCallback ( ) , callback . getExchange ( ) , false ) ; } else { final int cachedConnectionCount = hostData . availableConnections . size ( ) ; if ( cachedConnectionCount >= maxCachedConnections ) { final ConnectionHolder holder = hostData . availableConnections . poll ( ) ; if ( holder != null ) { IoUtils . safeClose ( holder . clientConnection ) ; } } hostData . availableConnections . add ( connectionHolder ) ; if ( timeToLive > 0 ) { final long currentTime = System . currentTimeMillis ( ) ; connectionHolder . timeout = currentTime + timeToLive ; if ( hostData . availableConnections . size ( ) > coreCachedConnections ) { if ( hostData . nextTimeout <= 0 ) { hostData . timeoutKey = WorkerUtils . executeAfter ( connection . getIoThread ( ) , hostData . timeoutTask , timeToLive , TimeUnit . MILLISECONDS ) ; hostData . nextTimeout = connectionHolder . timeout ; } } } } } else if ( connection . isOpen ( ) && connection . isUpgraded ( ) ) { connection . getCloseSetter ( ) . set ( null ) ; handleClosedConnection ( hostData , connectionHolder ) ; } }
Called when the IO thread has completed a successful request

@param connectionHolder The client connection holder