docs: public void error(NetworkConnection vc,
                       IOReadRequestContext rrc,
                       IOException t)               // F176003, F184828, D194678
     {
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.entry(this, tc, "error", new Object[] {vc, rrc, t});  // F184828
        if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled() && (t != null)) SibTr.exception(this, tc, t);
        if (thisConnection.isLoggingIOEvents()) thisConnection.getConnectionEventRecorder().logDebug("error method invoked on read context "+System.identityHashCode(rrc)+" with exception "+t);
  
        try
        {
           synchronized(this)
           {
              // begin F174772
              if (receivePhysicalCloseRequest)
              {
                 // Ignore any errors when we are physically closing they could be
                 // because of a race condidition between write operations and the
                 // close of the socket.
                 if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "ignoring as in process of close");
              }
              // end F174772
              // begin F175658
              else if (t instanceof SocketTimeoutException)
              {
                 if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "error is as a result of a timeout");
  
                 // We should only enter this arm of the if statement
                 // if we have timed out on a previous request.  This
                 // must be heartbeat realted.
                 if (awaitingHeartbeatResponse.isSet())
                 {
                    if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "timed out waiting for heartbeat response");  // F177053
                    thisConnection.getConnectionEventRecorder().logDebug("timed out waiting for heartbeat response");
  
                    // At this point issue a message to the console
                    String remoteHostAddress = "<Unknown>";
                    String remoteHostPort = "<Unknown>";
                    String chainName = thisConnection.chainName;
  
                    if (tcpCtx != null)
                    {
                       InetAddress addr = tcpCtx.getRemoteAddress();
                       if (addr != null)
                       {
                          remoteHostAddress = addr.getHostAddress();
                       }
                       remoteHostPort = ""+tcpCtx.getRemotePort();
                    }
  
                    if (thisConnection.isInbound())
                    {
                       if (conversation.getConversationType() == Conversation.ME)
                       {
                          SibTr.error(tc, SibTr.Suppressor.ALL_FOR_A_WHILE_SIMILAR_INSERTS,
                                      "ME_NOT_RESPONDING_SICJ0041",
                                      new Object[] { remoteHostAddress, chainName, ""+currentHeartbeatTimeout });
                       }
                       else if (conversation.getConversationType() == Conversation.CLIENT)
                       {
                          SibTr.error(tc, SibTr.Suppressor.ALL_FOR_A_WHILE_SIMILAR_INSERTS,
                                      "CLIENT_NOT_RESPONDING_SICJ0042",
                                      new Object[] { remoteHostAddress, chainName, ""+currentHeartbeatTimeout });
                       }
                    }
                    else  // we are Outbound
                    {
                       if (conversation.getConversationType() == Conversation.ME)
                       {
                          SibTr.error(tc, SibTr.Suppressor.ALL_FOR_A_WHILE_SIMILAR_INSERTS,
                                      "ME_NOT_RESPONDING_OUTBOUND_SICJ0070",
                                      new Object[] { remoteHostAddress, remoteHostPort, chainName, ""+currentHeartbeatTimeout });
                       }
                       else if (conversation.getConversationType() == Conversation.CLIENT)
                       {
                          SibTr.error(tc, SibTr.Suppressor.ALL_FOR_A_WHILE_SIMILAR_INSERTS,
                                      "CLIENT_NOT_RESPONDING_OUTBOUND_SICJ0071",
                                      new Object[] { remoteHostAddress, remoteHostPort, chainName, ""+currentHeartbeatTimeout });
                       }
                    }
  
                    // Close the underlying connection.  This takes out all
                    // the conversations it shares, wakes up exchanges and
                    // delivers exceptions to the conversation receive listeners.
                    // begin F176003
                    JFapHeartbeatTimeoutException exception =
                       new JFapHeartbeatTimeoutException("Connection dropped after heartbeat request went unacknowledged");
                    exception.initCause(t);
                    FFDCFilter.processException
                    (exception, "com.ibm.ws.sib.jfapchannel.impl.ConnectionReadCompletedCallback", JFapChannelConstants.CONNREADCOMPCALLBACK_ERROR_03, thisConnection.getDiagnostics(true));
                    thisConnection.invalidate(false, exception, "heartbeat request was not acknowledged");
  
                    // end F176003
  
                    
                 }
                 // being F177053
                 else if (thisConnection.getHeartbeatInterval() == 0)
                 {
                    // Oh dear.  This is a bit of a irratating situation we find
                    // ourselves in.  It looks like someone has turned off heartbeating
                    // yet - whilst it was switched on we asked to be notified of a
                    // timeout.  We should probably just ignore this.
                    if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "timed out but heartbeating now switched off");
  
                    // begin D183461
                    NetworkConnection rvc = null;
                    synchronized(connectionClosingLock)
                    {
                       if (!connectionClosing)
                       {
                          if (thisConnection.isLoggingIOEvents()) thisConnection.getConnectionEventRecorder().logDebug("invoking readCtx.read() on context "+System.identityHashCode(readCtx)+" with no timeout");
                          rvc = readCtx.read(1, this, false, IOReadRequestContext.NO_TIMEOUT);      // F184828
                       }
                    }
                    // end D183461
                    if (rvc != null)
                       complete(rvc, readCtx);
                   
                 }
                 // end F177053
                 else
                 {
                    if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "sending heartbeat request");  // F177053, D224570
  
                    // We timed out and we weren't awaiting a heartbeat
                    // response.  This must mean that we timedout on the
                    // heartbeat interval.  Issue a heartbeat request to
                    // our peer.
  
                    // Remember state about the fact that we are about to
                    // issue a heartbeat request.
                    awaitingHeartbeatResponse.set();
                    currentHeartbeatTimeout = thisConnection.getHeartbeatTimeout();
  
                    thisConnection.getConnectionEventRecorder().logDebug("sending heartbeat request and waiting up to "+currentHeartbeatTimeout+" seconds for a response");
  
                    // Send a heartbeat request to our peer.
                    // begin D221868
                    SIException sendException = null;
                    try
                    {
                       thisConnection.sendHeartbeat();
                    }
                    catch(SIConnectionLostException e)
                    {
                       // No FFDC code needed
                       if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "Exception received when heartbeating peer ("+e.toString()+").  Dropping connection");
                       sendException = e;
                    }
                    catch(SIConnectionDroppedException e)
                    {
                       // No FFDC code needed
                       if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "Exception received when heartbeating peer ("+e.toString()+").  Dropping connection");
                       sendException = e;
                    }
  
                    if (sendException == null)
                    {
                       // Resume our outstanding read request - but this time,
                       // set the timeout to our heartbeat timeout time.  This is
                       // because we are waiting for the response.
                       int timeout = currentHeartbeatTimeout*1000;
                       if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "setting heartbeat timeout to: "+timeout+" milliseconds");   // F177053
  
                       // begin F177053, D183461
                       NetworkConnection rvc = null;
                       synchronized(connectionClosingLock)
                       {
                          if (!connectionClosing)
                          {
                             if (thisConnection.isLoggingIOEvents()) thisConnection.getConnectionEventRecorder().logDebug("invoking readCtx.read() on context "+System.identityHashCode(readCtx)+" with a timeout of "+timeout);
                             rvc = readCtx.read(1, this, false, timeout);    // F184828
                          }
                       }
                       if (rvc != null)
                          complete(rvc, readCtx);
                       // end F177053, D183461
                    }
                    else
                    {
                       // We failed to send a heartbeat request to our peer.
                       thisConnection.invalidate(false, sendException, "exception caught while attempting to send heartbeat");  // D224570
  
                    
                    }
                    // end D221868
                 }
              }
              // end F175658
              else                                                                    // F174772
              {                                                                       // F174772
                 // begin F176003
                 // We used to set the first parameter to true here meaning that we
                 // need to notify the peer that we are having a bit of trouble.
                 // However, I believe that to be incorrect as I think that if this
                 // method is called then the socket is already dead - hence trying
                 // to notify the peer would mean that we would hang.
                 thisConnection.invalidate(false, t, "IOException received for connection - "+t.getMessage());   // D179618, D224570
                 // end F176003
               
                 //Note that this also deals with the buffer returned by getBuffer.
           		final IOReadRequestContext req = readCtx;
                 final WsByteBuffer[] buffers = req.getBuffers();
           		if (buffers != null)
           		{
           		   for(final WsByteBuffer buffer: buffers)
                    {
                       //Try and release the buffer.
                       //Absorb any exceptions if it gets released by another thread (for example by Connection.nonThreadSafePhysicalClose).
                       try
                       {
                          buffer.release();
                       }
                       catch(RuntimeException e)
                       {
                          //No FFDC code needed
                          if(TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "Caught exception on releasing buffer.", e);
                       }
                    }
                    
                    req.setBuffers(null);
           		}
           		else
           		{
           			if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "Request has no buffers: "+req);
           		}
              }
           }
        }
        catch(Error error)
        {
           FFDCFilter.processException
           (error, "com.ibm.ws.sib.jfapchannel.impl.ConnectionReadCompletedCallback", JFapChannelConstants.CONNREADCOMPCALLBACK_ERROR_05, thisConnection.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)
  
           thisConnection.invalidate(false, error, "Error caught in ConnectionReadCompletedCallback.error()");
  
           // 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.ConnectionReadCompletedCallback", JFapChannelConstants.CONNREADCOMPCALLBACK_ERROR_06, thisConnection.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.
           thisConnection.invalidate(false, runtimeException, "RuntimeException caught in ConnectionReadCompletedCallback.error()");
  
           // 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, "error");
     }