final void flushComplete ( ) throws IOException { synchronized ( lock ) { try { bufferFull = false ; int remaining = header . getRemainingInBuffer ( ) ; boolean finalFrame = finalFrameQueued ; boolean channelClosed = finalFrame && remaining == 0 && ! header . isAnotherFrameRequired ( ) ; if ( remaining > 0 ) { body . getBuffer ( ) . limit ( body . getBuffer ( ) . limit ( ) + remaining ) ; if ( finalFrame ) { //we clear the final frame flag, as it could not actually be written out //note that we don't attempt to requeue, as whatever stopped it from being written will likely still //be an issue this . finalFrameQueued = false ; } } else if ( header . isAnotherFrameRequired ( ) ) { this . finalFrameQueued = false ; if ( body != null ) { body . close ( ) ; body = null ; state &= ~ STATE_PRE_WRITE_CALLED ; } } else if ( body != null ) { body . close ( ) ; body = null ; state &= ~ STATE_PRE_WRITE_CALLED ; } if ( channelClosed ) { fullyFlushed = true ; if ( body != null ) { body . close ( ) ; body = null ; state &= ~ STATE_PRE_WRITE_CALLED ; } } else if ( body != null ) { // We still have a body, but since we just flushed, we transfer it to the write buffer. // This works as long as you call write() again //TODO: this code may not work if the channel has frame level compression and flow control //we don't have an implementation that needs this yet so it is ok for now body . getBuffer ( ) . compact ( ) ; writeBuffer = body ; body = null ; state &= ~ STATE_PRE_WRITE_CALLED ; } if ( header . getByteBuffer ( ) != null ) { header . getByteBuffer ( ) . close ( ) ; } header = null ; readyForFlush = false ; if ( isWriteResumed ( ) && ! channelClosed ) { wakeupWrites ( ) ; } else if ( isWriteResumed ( ) ) { //we need to execute the write listener one last time //we need to dispatch it back to the IO thread, so we don't invoke it recursivly ChannelListeners . invokeChannelListener ( getIoThread ( ) , ( S ) this , getWriteListener ( ) ) ; } final ChannelListener < ? super S > closeListener = this . closeSetter . get ( ) ; if ( channelClosed && closeListener != null ) { ChannelListeners . invokeChannelListener ( getIoThread ( ) , ( S ) AbstractFramedStreamSinkChannel . this , closeListener ) ; } handleFlushComplete ( channelClosed ) ; } finally { wakeupWaiters ( ) ; } } }
Method that is invoked when a frame has been fully flushed . This method is only invoked by the IO thread