<T extends InputStream & DataInput> void readResponse(T in, Map<Integer, Call> id2Call,
    Call preambleCall, Consumer<RemoteException> fatalConnectionErrorConsumer) throws IOException {
    int totalSize = in.readInt();
    ResponseHeader responseHeader = ResponseHeader.parseDelimitedFrom(in);
    int id = responseHeader.getCallId();
    if (LOG.isTraceEnabled()) {
      LOG.trace("got response header " + TextFormat.shortDebugString(responseHeader)
        + ", totalSize: " + totalSize + " bytes");
    }
    RemoteException remoteExc;
    if (responseHeader.hasException()) {
      ExceptionResponse exceptionResponse = responseHeader.getException();
      remoteExc = IPCUtil.createRemoteException(exceptionResponse);
      if (IPCUtil.isFatalConnectionException(exceptionResponse)) {
        // Here we will cleanup all calls so do not need to fall back, just return.
        fatalConnectionErrorConsumer.accept(remoteExc);
        if (preambleCall != null) {
          preambleCall.setException(remoteExc);
        }
        return;
      }
    } else {
      remoteExc = null;
    }
    if (id < 0) {
      LOG.debug("process preamble call response with response type {}",
        preambleCall != null
          ? preambleCall.responseDefaultType.getDescriptorForType().getName()
          : "null");
      if (preambleCall == null) {
        // fall through so later we will skip this response
        LOG.warn("Got a negative call id {} but there is no preamble call", id);
      } else {
        if (remoteExc != null) {
          preambleCall.setException(remoteExc);
        } else {
          finishCall(responseHeader, in, preambleCall);
        }
        return;
      }
    }
    Call call = id2Call.remove(id);
    if (call == null) {
      // So we got a response for which we have no corresponding 'call' here on the client-side.
      // We probably timed out waiting, cleaned up all references, and now the server decides
      // to return a response. There is nothing we can do w/ the response at this stage. Clean
      // out the wire of the response so its out of the way and we can get other responses on
      // this connection.
      if (LOG.isDebugEnabled()) {
        int readSoFar = IPCUtil.getTotalSizeWhenWrittenDelimited(responseHeader);
        int whatIsLeftToRead = totalSize - readSoFar;
        LOG.debug("Unknown callId: " + id + ", skipping over this response of " + whatIsLeftToRead
          + " bytes");
      }
      return;
    }
    call.callStats.setResponseSizeBytes(totalSize);
    if (remoteExc != null) {
      call.setException(remoteExc);
      return;
    }
    try {
      finishCall(responseHeader, in, call);
    } catch (IOException e) {
      // As the call has been removed from id2Call map, if we hit an exception here, the
      // exceptionCaught method can not help us finish the call, so here we need to catch the
      // exception and finish it
      call.setException(e);
      // throw the exception out, the upper layer should determine whether this is a critical
      // problem
      throw e;
    }
  }
Does the clean up work after the connection is removed from the connection pool
hbase-client/src/main/java/org/apache/hadoop/hbase/ipc/RpcConnection.java