1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.jscsi.initiator.connection.state;
20
21
22 import java.nio.ByteBuffer;
23
24 import org.jscsi.exception.InternetSCSIException;
25 import org.jscsi.initiator.connection.Connection;
26 import org.jscsi.parser.OperationCode;
27 import org.jscsi.parser.ProtocolDataUnit;
28 import org.jscsi.parser.datasegment.DataSegmentFactory;
29 import org.jscsi.parser.datasegment.DataSegmentFactory.DataSegmentFormat;
30 import org.jscsi.parser.datasegment.IDataSegment;
31 import org.jscsi.parser.datasegment.IDataSegmentIterator;
32 import org.jscsi.parser.datasegment.OperationalTextKey;
33 import org.jscsi.parser.scsi.SCSICommandDescriptorBlockParser;
34 import org.jscsi.parser.scsi.SCSICommandParser;
35 import org.jscsi.parser.scsi.SCSICommandParser.TaskAttributes;
36
37
38
39
40
41
42
43
44
45 public final class WriteRequestState extends AbstractState {
46
47
48
49
50
51 private final ByteBuffer buffer;
52
53
54 private final TaskAttributes taskAttributes;
55
56
57 private final int expectedDataTransferLength;
58
59
60 private final int logicalBlockAddress;
61
62
63 private final int bufferPosition;
64
65
66
67
68 private final short transferLength;
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84 public WriteRequestState (final Connection initConnection, final ByteBuffer initBuffer, final int initBufferPosition, final TaskAttributes initTaskAttributes, final int initExpectedDataTransferLength, final int initLogicalBlockAddress, final short initTransferLength) {
85
86 super(initConnection);
87 buffer = initBuffer;
88 bufferPosition = initBufferPosition;
89 taskAttributes = initTaskAttributes;
90 expectedDataTransferLength = initExpectedDataTransferLength;
91 logicalBlockAddress = initLogicalBlockAddress;
92 transferLength = initTransferLength;
93 }
94
95
96
97
98
99 public final void execute () throws InternetSCSIException {
100
101 final ProtocolDataUnit protocolDataUnit = protocolDataUnitFactory.create(false, true, OperationCode.SCSI_COMMAND, connection.getSetting(OperationalTextKey.HEADER_DIGEST), connection.getSetting(OperationalTextKey.DATA_DIGEST));
102 final SCSICommandParser scsi = (SCSICommandParser) protocolDataUnit.getBasicHeaderSegment().getParser();
103
104 scsi.setReadExpectedFlag(false);
105 scsi.setWriteExpectedFlag(true);
106 scsi.setTaskAttributes(taskAttributes);
107
108 scsi.setExpectedDataTransferLength(expectedDataTransferLength);
109
110 final int maxRecvDataSegmentLength = connection.getSettingAsInt(OperationalTextKey.MAX_RECV_DATA_SEGMENT_LENGTH);
111 scsi.setCommandDescriptorBlock(SCSICommandDescriptorBlockParser.createWriteMessage(logicalBlockAddress, transferLength));
112
113 final IDataSegment dataSegment = DataSegmentFactory.create(buffer, bufferPosition, expectedDataTransferLength, DataSegmentFormat.BINARY, maxRecvDataSegmentLength);
114 final IDataSegmentIterator iterator = dataSegment.iterator();
115 int bufferOffset = 0;
116
117 if (connection.getSettingAsBoolean(OperationalTextKey.IMMEDIATE_DATA)) {
118 final int min = Math.min(maxRecvDataSegmentLength, connection.getSettingAsInt(OperationalTextKey.FIRST_BURST_LENGTH));
119 protocolDataUnit.setDataSegment(iterator.next(min));
120 bufferOffset += min;
121 }
122
123 connection.send(protocolDataUnit);
124
125 if (!connection.getSettingAsBoolean(OperationalTextKey.INITIAL_R2T) && iterator.hasNext()) {
126 connection.nextState(new WriteFirstBurstState(connection, iterator, 0xFFFFFFFF, 0, bufferOffset));
127 } else {
128 connection.nextState(new WriteSecondResponseState(connection, iterator, 0, bufferOffset));
129 }
130 super.stateFollowing = true;
131
132 }
133
134
135
136
137
138 }