Called by the channel below us when a write has finished.

@param vc
@param wsc
438352
@Override
    public void complete(VirtualConnection vc, TCPWriteRequestContext wsc) {

        if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
            Tr.debug(tc, "complete() called: vc=" + vc);
        }
        HttpInboundServiceContextImpl mySC = (HttpInboundServiceContextImpl) vc.getStateMap().get(CallbackIDs.CALLBACK_HTTPISC);
        if (null != wsc) {
            wsc.setBuffers(null);
        }

        // access logging if the finishResponse API was used
        if (mySC.isMessageSent()) {
            mySC.logFinalResponse(mySC.getNumBytesWritten());
            HttpInvalidMessageException inv = mySC.checkResponseValidity();
            if (null != inv) {
                // response was invalid in some way... error scenario
                mySC.setPersistent(false);
                if (null != mySC.getAppWriteCallback()) {
                    mySC.getAppWriteCallback().error(vc, inv);
                }
                return;
            }
        }

        // if a callback exists above, pass along the complete. But if the
        // app channel didn't give us a callback (it doesn't care) then we
        // can't pass anything along and we stop further work here
        if (null != mySC.getAppWriteCallback()) {
            if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                Tr.debug(tc, "Calling write complete callback of app channel.");
            }
            if (mySC.getResponseImpl().isTemporaryStatusCode()) {
                // allow other responses to follow a temporary one
                if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                    Tr.debug(tc, "Temp response sent, resetting send flags");
                }
                mySC.resetWrite();
            }
            mySC.getAppWriteCallback().complete(vc);
        } else {
            // this is dangerous since we're not notifying the channel above
            // of the complete work, but they don't care since they didn't
            // give us a callback to use... hopefully they will continue this
            // connection properly.
            if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                Tr.debug(tc, "No available app channel callback");
            }
        }
    }
842155
@Override
    public void error(VirtualConnection vc, Throwable t) {

        if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())    
            Tr.debug(tc, "error callback called , WriteListener enabled: " + this._wl); 

        // reset the reqState
        WebContainerRequestState reqState = WebContainerRequestState.getInstance(true);                         
        reqState.init();  

        synchronized(_hout._writeReadyLockObj){
            // Make sure the ready is set to true before calling onError
            _hout.set_internalReady(true);            
            _hout.setWriteReady(true);   
            reqState.setAttribute("com.ibm.ws.webcontainer.AllowWriteFromE", true); 
            reqState.setAttribute("com.ibm.ws.webcontainer.WriteAllowedonThisThread", true);
        }
        
        SRTServletRequestThreadData.getInstance().init(_requestDataAsyncWriteCallbackThread);
        
        //Push the original thread's context onto the current thread, also save off the current thread's context
        tcm.pushContextData();

        if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()){  
            Tr.debug(tc, "WriteListener enabled: " + this._wl +" , calling user's onError : " + vc );            
        }       
        try{  
            synchronized(_hout) {
                //An error occurred. Issue the onError call on the user's WriteListener
                _wl.onError(t);
            }
            
            if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()){  
                Tr.debug(tc, "WriteListener enabled: " + this._wl +" , returned from user's onError : " + vc );            
            }  
        } catch (Exception e) {
             
            Tr.error(tc, "writeListener.onError.failed", new Object[] {this._wl, e.toString()});
            
        }
        finally{

            tcm.popContextData();//Revert back to the thread's current context

            reqState.removeAttribute("com.ibm.ws.webcontainer.AllowWriteFromE");
        }
    }
825576
@Override
  public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise)
      throws Exception {
    if (msg instanceof SendGrpcFrameCommand) {
      sendGrpcFrame(ctx, (SendGrpcFrameCommand) msg, promise);
    } else if (msg instanceof SendResponseHeadersCommand) {
      sendResponseHeaders(ctx, (SendResponseHeadersCommand) msg, promise);
    } else if (msg instanceof CancelServerStreamCommand) {
      cancelStream(ctx, (CancelServerStreamCommand) msg, promise);
    } else if (msg instanceof ForcefulCloseCommand) {
      forcefulClose(ctx, (ForcefulCloseCommand) msg, promise);
    } else {
      AssertionError e =
          new AssertionError("Write called for unexpected type: " + msg.getClass().getName());
      ReferenceCountUtil.release(msg);
      promise.setFailure(e);
      throw e;
    }
  }
31828
@Override
    public void writeFragmentTo(MwsWriter w) {
        w.write("Status", status);
        w.write("Timestamp", timestamp);
        w.write("MessageId", messageId);
        w.writeList("Messages", "Message", messages);
    }
1201790
private void invokeOnComplete() {
        for (; ; ) {
            if (pooledBuffers != null) {
                for (PooledByteBuffer buffer : pooledBuffers) {
                    buffer.close();
                }
                pooledBuffers = null;
            }
            IoCallback callback = this.callback;
            this.buffer = null;
            this.fileChannel = null;
            this.callback = null;
            inCallback = true;
            try {
                callback.onComplete(exchange, this);
            } finally {
                inCallback = false;
            }

            StreamSinkChannel channel = this.channel;
            if (this.buffer != null) {
                long t = Buffers.remaining(buffer);
                final long total = t;
                long written = 0;

                try {
                    do {
                        long res = channel.write(buffer);
                        written += res;
                        if (res == 0) {
                            if(writeListener == null) {
                                initWriteListener();
                            }
                            channel.getWriteSetter().set(writeListener);
                            channel.resumeWrites();
                            return;
                        }
                    } while (written < total);
                    //we loop and invoke onComplete again
                } catch (IOException e) {
                    invokeOnException(callback, e);
                }
            } else if (this.fileChannel != null) {
                if(transferTask == null) {
                    transferTask = new TransferTask();
                }
                if (!transferTask.run(false)) {
                    return;
                }
            } else {
                return;
            }

        }
    }
149989
@Override
    public void writeFragmentTo(MwsWriter w) {
        w.write("NextToken", nextToken);
        w.write("CreatedBefore", createdBefore);
        w.write("LastUpdatedBefore", lastUpdatedBefore);
        w.writeList("Orders", "Order", orders);
    }
713303
void writeFinished(Object error) {
        checkThread();
        writingBuffer = null;
        Promise wp = this.writePromise;
        writePromise = null;
        if ( ! wp.isSettled() ) {
            if ( error != null )
                wp.reject(error);
            else
                wp.resolve();
        }
    }
85753
public void write(BitOutputStream os, boolean isLast) throws IOException {

        os.writeRawUInt(isLast, STREAM_METADATA_IS_LAST_LEN);
        os.writeRawUInt(METADATA_TYPE_STREAMINFO, STREAM_METADATA_TYPE_LEN);
        os.writeRawUInt(calcLength(), STREAM_METADATA_LENGTH_LEN);

        os.writeRawUInt(minBlockSize, STREAMINFO_MIN_BLOCK_SIZE_LEN);
        os.writeRawUInt(maxBlockSize, STREAMINFO_MAX_BLOCK_SIZE_LEN);
        os.writeRawUInt(minFrameSize, STREAMINFO_MIN_FRAME_SIZE_LEN);
        os.writeRawUInt(maxFrameSize, STREAMINFO_MAX_FRAME_SIZE_LEN);
        os.writeRawUInt(sampleRate, STREAMINFO_SAMPLE_RATE_LEN);
        os.writeRawUInt(channels - 1, STREAMINFO_CHANNELS_LEN);
        os.writeRawULong(bitsPerSample - 1, STREAMINFO_BITS_PER_SAMPLE_LEN);
        os.writeRawULong(totalSamples, STREAMINFO_TOTAL_SAMPLES_LEN);
        os.writeByteBlock(md5sum, md5sum.length);
        os.flushByteAligned();
    }
303815
@Override
    public void close(VirtualConnection inVC, Exception e) {
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
            Tr.entry(tc, "close, vc=" + getVCHash());
        }

        // Set closed flag so that ready can't be called again in an error condition.
        // This is a protective measure.
        closed = true;

        // Clean up the read and write interfaces as well as the SSL engine.

        // cleanup has logic to avoid writing if stop(0) has been called
        cleanup();

        //If the channel has already processed the close signal, it is too late to try and clean up the individual connection links here.
        //This race condition should not happen if channels above us are well behaved, so not using synchronize logic here, so as not to
        //impact mainline performance.
        if (this.sslChannel.getstop0Called() != true) {
            if (getDeviceLink() != null) {
                getDeviceLink().close(inVC, e);
            }
        }

        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
            Tr.exit(tc, "close");
        }
    }
694704
public static final long write(WritableByteChannel channel, ByteBuffer[] srcs) throws IOException
    {
        return write(channel, srcs, 0, srcs.length);
    }
339275
public void complete(VirtualConnection vc, TCPReadRequestContext req) {

        if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
            Tr.debug(tc, "complete() called: vc=" + vc);
        }
        HttpOutboundServiceContextImpl mySC = (HttpOutboundServiceContextImpl) vc.getStateMap().get(CallbackIDs.CALLBACK_HTTPOSC);
        // keep reading and handling new data until either we're done
        // parsing headers or until we're waiting on a read to finish
        VirtualConnection readVC = null;
        try {
            do {
                if (mySC.parseMessage()) {
                    // start processing the new parsed message
                    mySC.handleParsedMessage();
                    return;
                }
                // not done parsing, read for more data
                if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                    Tr.debug(tc, "Reading for more data");
                }
                // configure the buffers for reading
                mySC.setupReadBuffers(mySC.getHttpConfig().getIncomingHdrBufferSize(), false);
                readVC = req.read(1, this, false, mySC.getReadTimeout());
            } while (null != readVC);
        } catch (Exception e) {
            FFDCFilter.processException(e, getClass().getName() + ".complete", "112", this);
            if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                Tr.debug(tc, "Caught exception: " + e.getMessage());
            }
            mySC.setPersistent(false);
            mySC.getAppWriteCallback().error(vc, e);
        }
    }
694547
public void complete(NetworkConnection vc, IOWriteRequestContext wctx) {
      if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.entry(this, tc, "complete", new Object[] {vc, wctx});
      if (connection.isLoggingIOEvents()) connection.getConnectionEventRecorder().logDebug("complete method invoked on write context "+System.identityHashCode(wctx));

      try {
         doWork(true);
      } catch(SIConnectionDroppedException connectionDroppedException) {
         // No FFDC code needed

         // This has been thrown because the priority queue was purged (most likely on another thread).
         // The exception is thrown to prevent threads in this method looping forever or hanging if the
         // conneciton is invalidate on another thread.  Therefore we simply swallow this exception and
         // allow the thread to exit this method.

         if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
            SibTr.debug(this, tc, "Caught SIConnectionDroppedException, Priority Queue has been purged");
      } catch(Error error) {
         FFDCFilter.processException
         (error, "com.ibm.ws.sib.jfapchannel.impl.ConnectionWriteCompletedCallback", JFapChannelConstants.CONNWRITECOMPCALLBACK_COMPLETE_03, connection.getDiagnostics(true));
         if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled()) SibTr.exception(this, tc, error);

         // It might appear slightly odd for this code to catch Error (especially since the JDK docs say
         // that Error means that something has gone so badly wrong that you should abandon all hope).
         // This code makes one final stab at putting out some diagnostics about what happened (if we
         // propagate the Error up to the TCP Channel, it is sometimes lost) and closing down the
         // connection.  I figured that we might as well try to do something - as we can hardly make
         // things worse... (famous last words)

         connection.invalidate(false, error, "Error caught in ConnectionWriteCompletedCallback.complete()");

         // Re-throw the error to ensure that it causes the maximum devastation.
         // The JVM is probably very ill if an Error is thrown so attempt no recovery.
         throw error;
      } catch(RuntimeException runtimeException) {
         FFDCFilter.processException
         (runtimeException, "com.ibm.ws.sib.jfapchannel.impl.ConnectionWriteCompletedCallback", JFapChannelConstants.CONNWRITECOMPCALLBACK_COMPLETE_04, connection.getDiagnostics(true));
         if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled()) SibTr.exception(this, tc, runtimeException);

         // We can reasonably try to recover from a runtime exception by invalidating the associated
         // connection.  This should drive the underlying TCP/IP socket to be closed.
         connection.invalidate(false, runtimeException, "RuntimeException caught in ConnectionWriteCompletedCallback.complete()");

         // Don't throw the RuntimeException on as we risk blowing away part of the TCP channel.
      }

      if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(this, tc, "complete");
   }
421388
@Override
    public void afterCompletion(int status) {

        if (tc.isEntryEnabled()) {
            Tr.entry(this, tc, "afterCompletion");
        }

        if (tc.isDebugEnabled()) {
            Tr.debug(
                     tc,
                     "Using transaction wrapper@" + Integer.toHexString(this.hashCode()));
        }

        if (mcWrapper.isMCAborted()) {
            Tr.exit(tc, "Connection was aborted. Exiting afterCompletion.");
            return;
        }

        // When afterCompletionCode is called we need to reset the registeredForSync flag.
        registeredForSync = false;
        this.hasRollbackOccured = false;
        /*
         * Mark the transaction complete in the wrapper
         */
        // Do NOT catch runtime exections here.  Let them flow out of the component.
        mcWrapper.transactionComplete();

        if (tc.isDebugEnabled()) {
            if (mcWrapper.getHandleCount() != 0) {
                // Issue warning that Connections have not been closed by the end of the current UOW
                //  scope and will be closed by the CM.
                //            Tr.warning(this, tc,"HANDLE_NOT_CLOSED_J2CA0055");
                Tr.debug(this, tc, "Information:  handle not closed at end of UOW. Connection from pool " + mcWrapper.gConfigProps.getXpathId());
            }
        }

        // Do NOT catch the runtime exception which getConnectionManager might throw.
        // If this is thrown it is an internal bug and needs to be fixed.
        // Allow the rte to flow up to the container.
        boolean shareable = mcWrapper.getConnectionManager().shareable();

        //  - Simplified the following if/else construct taking advantage of the
        //             new releaseToPoolManger call on mcWrapper.
        //
        // If the connection is shareable, or it is non-shareable and the handleCount is
        // zero, then release it back to the poolManger, otherwise simply reset the
        // transaction related variables.
        //
        // Note: shareable connections are released at the end of transactions regardless of
        //  outstanding handles because we don't supports handled being associated to an active
        //  managedConnection outside of a sharing boundary.
        //
        //  if the MCWrapper is stale we will release the connection to the pool.
        //
        if ((shareable) || (!shareable && mcWrapper.getHandleCount() == 0) || mcWrapper.isStale()) {

            if (tc.isDebugEnabled()) {
                Tr.debug(this, tc,
                         "Releasing the connection to the pool. shareable = " + shareable + "  handleCount = " + mcWrapper.getHandleCount() + "  isStale = " + mcWrapper.isStale());
            }

            try {
                mcWrapper.releaseToPoolManager();
            } catch (Exception e) {
                // No need to rethrow this exception since nothing can be done about it,
                //  and the application has successfully finished its use of the connection.
                com.ibm.ws.ffdc.FFDCFilter.processException(
                                                            e,
                                                            "com.ibm.ejs.j2c.LocalTransactionWrapper.afterCompletion",
                                                            "711",
                                                            this);
                if (tc.isDebugEnabled()) {
                    Tr.debug(this, tc, "afterCompletionCode for datasource " + mcWrapper.gConfigProps.cfName + ":  caught Exception", e);
                }
            }

        } // end ((shareable) || (!shareable && mcWrapper.getHandleCount() == 0))
        else {
            /*
             * The cleanup of the coordinator enlisted flag should only be done for non sharable connections, in
             * other cases, the coord is set to null in mcWrapper.releaseToPoolManager(). We only need to worry about this
             * if the handleCount is greater than 0 (in which case the cleanup will be done by the poolManager). Same
             * thing for the tranFailed flag in the MCWrapper.
             */
            mcWrapper.setUOWCoordinator(null);
            // Reset the serialReuseCount since it is only valid for the duration of
            // the LTC. Note that the release path above will also reset it via mcWrapper.cleanup().
            enlisted = false;
        }

        if (tc.isEntryEnabled()) {
            Tr.exit(this, tc, "afterCompletion");
        }
    }
1038864
public void writeUncommitted(SIMPMessage m) throws SIResourceException
  {

    if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
      SibTr.entry(this, tc, "writeUncommitted", new Object[] { m });

    TickRange tr = null;

    JsMessage jsMsg = m.getMessage();
   
    long stamp = jsMsg.getGuaranteedValueValueTick();
    long starts = jsMsg.getGuaranteedValueStartTick();
    long ends = jsMsg.getGuaranteedValueEndTick();

    if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
    {
      SibTr.debug(tc, "writeUncommitted at: " + stamp + " on Stream " +  stream);
    }

    synchronized (this)
    {      
      if (m.getStreamIsGuess())
      {
        newGuessInStream(stamp);
      }
      msgAdded(stamp);

      // write into stream
      tr = TickRange.newUncommittedTick(stamp);
      tr.startstamp = starts;
      tr.endstamp = ends;
    
      // Save message in the stream while it is Uncommitted
      // It will be replaced by its index in the ItemStream once it becomes a Value
      tr.value = m;

      oststream.writeCombinedRange(tr);
 
      // Now update our lastMsgAdded with the tick of the
      // message we have just added
      lastMsgAdded = stamp;
      
      // SIB0105
      // If this is the first uncommitted messages to be added to the stream, start off the 
      // blocked message health state timer. This will check back in the future to see if the
      // message successfully sent.
      if (blockedStreamAlarm==null)
      {
        blockedStreamAlarm = new BlockedStreamAlarm(getCompletedPrefix());
        am.create(mp.getCustomProperties().getBlockedStreamHealthCheckInterval(), blockedStreamAlarm);
      }

    } // end synchronized

    if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
      SibTr.exit(tc, "writeUncommitted");
  }
688554
public void write(int b) throws IOException
	{
		//PK89810, If WCCustomProperties.FINISH_RESPONSE_ON_CLOSE is set and stream is already obtained and closed. 
		// User will not be allowed to write more data if the above case is met, outputstreamClosed will be true and default is false.
		if (!(WCCustomProperties.FINISH_RESPONSE_ON_CLOSE) || !outputstreamClosed ) //PK89810
		{
		if (com.ibm.ejs.ras.TraceComponent.isAnyTracingEnabled()&&logger.isLoggable (Level.FINE)) {  //306998.15
			logger.logp(Level.FINE, CLASS_NAME,"write", "write --> "+b);
        }
		if (!_hasWritten && obs != null)
		{
			_hasWritten = true;
			if (obsList!=null){
				for (int i=0;i<obsList.size();i++){
					obsList.get(i).alertFirstWrite();
				}
			}
			else {
			obs.alertFirstWrite();
		}
		}
		if (limit > -1)
		{
			if (total >= limit)
			{
				throw new WriteBeyondContentLengthException();
			}
		}
		if (count == buf.length)
		{
			response.setFlushMode(false);
			flushBytes();
			response.setFlushMode(true);
		}
		buf[count++] = (byte) b;
		total++;
	}
		else
		{//PK89810 start
			if (com.ibm.ejs.ras.TraceComponent.isAnyTracingEnabled()&&logger.isLoggable (Level.FINE))
				logger.logp(Level.FINE, CLASS_NAME,"write", " write not allowed, outputstreamClosed value -->" + outputstreamClosed);
			
		}//PK89810 End
	}
1150480
public static final long write(WritableByteChannel channel, ByteBuffer[] srcs, int offset, int length) throws IOException
    {
        long res = 0;
        for  (int ii=0;ii<length;ii++)
        {
            ByteBuffer bb = srcs[ii+offset];
            if (bb.hasRemaining())
            {
                res += channel.write(bb);
                if (bb.hasRemaining())
                {
                    break;
                }
            }
        }
        return res;
    }
90819
private void write(int c) throws IOException {
		if (!firstCharacterWritten) {
			if (c != '\n') {
				out.write(c);
				firstCharacterWritten = true;
			}
		} else {
			out.write(c);
		}
	}