@Override
  public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
    if (evt instanceof BufferCallEvent) {
      BufferCallEvent bcEvt = (BufferCallBeforeInitHandler.BufferCallEvent) evt;
      switch (bcEvt.action) {
        case FLUSH:
          for (Call call : id2Call.values()) {
            ctx.write(call);
          }
          ctx.flush();
          ctx.pipeline().remove(this);
          break;
        case FAIL:
          for (Call call : id2Call.values()) {
            call.setException(bcEvt.error);
          }
          // here we do not remove us from the pipeline, for receiving possible exceptions and log
          // it, especially the ssl exceptions, to prevent it reaching the tail of the pipeline and
          // generate a confusing netty WARN
          break;
      }
    } else if (evt instanceof CallEvent) {
      // just remove the call for now until we add other call event other than timeout and cancel.
      id2Call.remove(((CallEvent) evt).call.id);
    } else {
      ctx.fireUserEventTriggered(evt);
    }
  }
We will expose the connection to upper layer before initialized, so we need to buffer the calls
passed in and write them out once the connection is established.
hbase-client/src/main/java/org/apache/hadoop/hbase/ipc/BufferCallBeforeInitHandler.java