public DefaultChannelPipeline(Channel channel) {
    if (channel == null) {
      throw new NullPointerException("channel");
    }
    this.channel = channel;

    tail = new DefaultChannelHandlerContext(this, null, generateName(TAIL_HANDLER), TAIL_HANDLER);

    HeadHandler headHandler;
    switch (channel.metadata().bufferType()) {
      case BYTE:
        headHandler = new ByteHeadHandler();
        break;
      case MESSAGE:
        headHandler = new MessageHeadHandler();
        break;
      default:
        throw new Error("unknown buffer type: " + channel.metadata().bufferType());
    }

    head =
        new DefaultChannelHandlerContext(this, null, generateName(headHandler), headHandler, true);

    head.next = tail;
    tail.prev = head;

    unsafe = channel.unsafe();
  }
  @Override
  public void fireChannelActive() {
    firedChannelActive = true;
    head.fireChannelActive();

    if (channel.config().isAutoRead()) {
      channel.read();
    }

    if (fireInboundBufferUpdatedOnActivation) {
      fireInboundBufferUpdatedOnActivation = false;
      head.fireInboundBufferUpdated();
    }
  }
 @Override
 public void fireInboundBufferSuspended() {
   head.fireInboundBufferSuspended();
   if (channel.config().isAutoRead()) {
     read();
   }
 }
  @Override
  public void fireChannelUnregistered() {
    head.fireChannelUnregistered();

    // Free all buffers if channel is closed and unregistered.
    if (!channel.isOpen()) {
      head.invokeFreeInboundBuffer();
    }
  }
  private void callAfterRemove(final DefaultChannelHandlerContext ctx, boolean forward) {
    final ChannelHandler handler = ctx.handler();

    // Notify the complete removal.
    try {
      handler.afterRemove(ctx);
    } catch (Throwable t) {
      throw new ChannelPipelineException(
          ctx.handler().getClass().getName() + ".afterRemove() has thrown an exception.", t);
    }

    if (forward) {
      ctx.forwardBufferContent();
    } else {
      ctx.clearBuffer();
    }

    ctx.removed = true;

    // Free all buffers before completing removal.
    if (!channel.isRegistered()) {
      ctx.freeHandlerBuffersAfterRemoval();
    }
  }