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 ) ; } }
Called when the IO thread has completed a successful request