private boolean decodeMsg(Object msg) throws Throwable {
    final Class<?> msgClazz = msg.getClass();

    // ---- Buffer --------------------------------------------------------
    if (msgClazz == NettyMessage.BufferResponse.class) {
      NettyMessage.BufferResponse bufferOrEvent = (NettyMessage.BufferResponse) msg;

      RemoteInputChannel inputChannel = inputChannels.get(bufferOrEvent.receiverId);
      if (inputChannel == null) {
        bufferOrEvent.releaseBuffer();

        cancelRequestFor(bufferOrEvent.receiverId);

        return true;
      }

      return decodeBufferOrEvent(inputChannel, bufferOrEvent);
    }
    // ---- Error ---------------------------------------------------------
    else if (msgClazz == NettyMessage.ErrorResponse.class) {
      NettyMessage.ErrorResponse error = (NettyMessage.ErrorResponse) msg;

      SocketAddress remoteAddr = ctx.channel().remoteAddress();

      if (error.isFatalError()) {
        notifyAllChannelsOfErrorAndClose(
            new RemoteTransportException(
                "Fatal error at remote task manager '" + remoteAddr + "'.",
                remoteAddr,
                error.cause));
      } else {
        RemoteInputChannel inputChannel = inputChannels.get(error.receiverId);

        if (inputChannel != null) {
          if (error.cause.getClass() == PartitionNotFoundException.class) {
            inputChannel.onFailedPartitionRequest();
          } else {
            inputChannel.onError(
                new RemoteTransportException(
                    "Error at remote task manager '" + remoteAddr + "'.", remoteAddr, error.cause));
          }
        }
      }
    } else {
      throw new IllegalStateException("Received unknown message from producer: " + msg.getClass());
    }

    return true;
  }
  private void notifyAllChannelsOfErrorAndClose(Throwable cause) {
    if (channelError.compareAndSet(false, true)) {
      try {
        for (RemoteInputChannel inputChannel : inputChannels.values()) {
          inputChannel.onError(cause);
        }
      } catch (Throwable t) {
        // We can only swallow the Exception at this point. :(
        LOG.warn(
            "An Exception was thrown during error notification of a " + "remote input channel.", t);
      } finally {
        inputChannels.clear();

        if (ctx != null) {
          ctx.close();
        }
      }
    }
  }