public void updateInputChannel(InputChannelDeploymentDescriptor icdd)
      throws IOException, InterruptedException {
    synchronized (requestLock) {
      if (isReleased) {
        // There was a race with a task failure/cancel
        return;
      }

      final IntermediateResultPartitionID partitionId =
          icdd.getConsumedPartitionId().getPartitionId();

      InputChannel current = inputChannels.get(partitionId);

      if (current.getClass() == UnknownInputChannel.class) {

        UnknownInputChannel unknownChannel = (UnknownInputChannel) current;

        InputChannel newChannel;

        ResultPartitionLocation partitionLocation = icdd.getConsumedPartitionLocation();

        if (partitionLocation.isLocal()) {
          newChannel = unknownChannel.toLocalInputChannel();
        } else if (partitionLocation.isRemote()) {
          newChannel = unknownChannel.toRemoteInputChannel(partitionLocation.getConnectionId());
        } else {
          throw new IllegalStateException("Tried to update unknown channel with unknown channel.");
        }

        LOG.debug("Updated unknown input channel to {}.", newChannel);

        inputChannels.put(partitionId, newChannel);

        newChannel.requestSubpartition(consumedSubpartitionIndex);

        for (TaskEvent event : pendingEvents) {
          newChannel.sendTaskEvent(event);
        }

        if (--numberOfUninitializedChannels == 0) {
          pendingEvents.clear();
        }
      }
    }
  }
  /** Creates an input gate and all of its input channels. */
  public static SingleInputGate create(
      String owningTaskName,
      JobID jobId,
      ExecutionAttemptID executionId,
      InputGateDeploymentDescriptor igdd,
      NetworkEnvironment networkEnvironment) {

    final IntermediateDataSetID consumedResultId = checkNotNull(igdd.getConsumedResultId());

    final int consumedSubpartitionIndex = igdd.getConsumedSubpartitionIndex();
    checkArgument(consumedSubpartitionIndex >= 0);

    final InputChannelDeploymentDescriptor[] icdd =
        checkNotNull(igdd.getInputChannelDeploymentDescriptors());

    final SingleInputGate inputGate =
        new SingleInputGate(
            owningTaskName,
            jobId,
            executionId,
            consumedResultId,
            consumedSubpartitionIndex,
            icdd.length,
            networkEnvironment.getPartitionStateChecker());

    // Create the input channels. There is one input channel for each consumed partition.
    final InputChannel[] inputChannels = new InputChannel[icdd.length];

    for (int i = 0; i < inputChannels.length; i++) {

      final ResultPartitionID partitionId = icdd[i].getConsumedPartitionId();
      final ResultPartitionLocation partitionLocation = icdd[i].getConsumedPartitionLocation();

      if (partitionLocation.isLocal()) {
        inputChannels[i] =
            new LocalInputChannel(
                inputGate,
                i,
                partitionId,
                networkEnvironment.getPartitionManager(),
                networkEnvironment.getTaskEventDispatcher(),
                networkEnvironment.getPartitionRequestInitialAndMaxBackoff());
      } else if (partitionLocation.isRemote()) {
        inputChannels[i] =
            new RemoteInputChannel(
                inputGate,
                i,
                partitionId,
                partitionLocation.getConnectionId(),
                networkEnvironment.getConnectionManager(),
                networkEnvironment.getPartitionRequestInitialAndMaxBackoff());
      } else if (partitionLocation.isUnknown()) {
        inputChannels[i] =
            new UnknownInputChannel(
                inputGate,
                i,
                partitionId,
                networkEnvironment.getPartitionManager(),
                networkEnvironment.getTaskEventDispatcher(),
                networkEnvironment.getConnectionManager(),
                networkEnvironment.getPartitionRequestInitialAndMaxBackoff());
      } else {
        throw new IllegalStateException("Unexpected partition location.");
      }

      inputGate.setInputChannel(partitionId.getPartitionId(), inputChannels[i]);
    }

    LOG.debug("Created input channels {} from {}.", Arrays.toString(inputChannels), igdd);

    return inputGate;
  }