/** {@inheritDoc} */
  public final void execute() throws InternetSCSIException {

    final ProtocolDataUnit protocolDataUnit =
        protocolDataUnitFactory.create(
            false,
            true,
            OperationCode.SCSI_COMMAND,
            connection.getSetting(OperationalTextKey.HEADER_DIGEST),
            connection.getSetting(OperationalTextKey.DATA_DIGEST));
    final SCSICommandParser scsi =
        (SCSICommandParser) protocolDataUnit.getBasicHeaderSegment().getParser();

    scsi.setReadExpectedFlag(false);
    scsi.setWriteExpectedFlag(true);
    scsi.setTaskAttributes(taskAttributes);

    scsi.setExpectedDataTransferLength(expectedDataTransferLength);

    final int maxRecvDataSegmentLength =
        connection.getSettingAsInt(OperationalTextKey.MAX_RECV_DATA_SEGMENT_LENGTH);
    scsi.setCommandDescriptorBlock(
        SCSICommandDescriptorBlockParser.createWriteMessage(logicalBlockAddress, transferLength));

    final IDataSegment dataSegment =
        DataSegmentFactory.create(
            buffer,
            bufferPosition,
            expectedDataTransferLength,
            DataSegmentFormat.BINARY,
            maxRecvDataSegmentLength);
    final IDataSegmentIterator iterator = dataSegment.iterator();
    int bufferOffset = 0;

    if (connection.getSettingAsBoolean(OperationalTextKey.IMMEDIATE_DATA)) {
      final int min =
          Math.min(
              maxRecvDataSegmentLength,
              connection.getSettingAsInt(OperationalTextKey.FIRST_BURST_LENGTH));
      protocolDataUnit.setDataSegment(iterator.next(min));
      bufferOffset += min;
    }

    connection.send(protocolDataUnit);

    if (!connection.getSettingAsBoolean(OperationalTextKey.INITIAL_R2T) && iterator.hasNext()) {
      connection.nextState(
          new WriteFirstBurstState(connection, iterator, 0xFFFFFFFF, 0, bufferOffset));
    } else {
      connection.nextState(new WriteSecondResponseState(connection, iterator, 0, bufferOffset));
    }
    super.stateFollowing = true;
    // return true;
  }