View Javadoc

1   /**
2    * Copyright (c) 2012, University of Konstanz, Distributed Systems Group All rights reserved.
3    * 
4    * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
5    * following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of
6    * conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice,
7    * this list of conditions and the following disclaimer in the documentation and/or other materials provided with the
8    * distribution. * Neither the name of the University of Konstanz nor the names of its contributors may be used to
9    * endorse or promote products derived from this software without specific prior written permission.
10   * 
11   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
12   * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
13   * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
14   * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
15   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
16   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
17   * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
18   */
19  package org.jscsi.initiator.connection.state;
20  
21  
22  import java.util.LinkedList;
23  import java.util.Queue;
24  
25  import org.jscsi.exception.InternetSCSIException;
26  import org.jscsi.initiator.connection.Connection;
27  import org.jscsi.parser.OperationCode;
28  import org.jscsi.parser.ProtocolDataUnit;
29  import org.jscsi.parser.data.DataOutParser;
30  import org.jscsi.parser.datasegment.IDataSegmentIterator;
31  import org.jscsi.parser.datasegment.IDataSegmentIterator.IDataSegmentChunk;
32  import org.jscsi.parser.datasegment.OperationalTextKey;
33  
34  
35  /**
36   * <h1>WriteFirstBurstState</h1>
37   * <p/>
38   * This state handles a first Write Sending State, which sends at most <code>FirstBurstLength</code> bytes in the first
39   * sequence.
40   * 
41   * @author Volker Wildi
42   */
43  public final class WriteFirstBurstState extends AbstractState {
44  
45      // --------------------------------------------------------------------------
46      // --------------------------------------------------------------------------
47  
48      /** The iterator of this data segment to send as next. */
49      private IDataSegmentIterator iterator;
50  
51      /**
52       * The Target Transfer Tag, which is sent by the iSCSI Target within a Ready2Transfer PDU.
53       */
54      private final int targetTransferTag;
55  
56      /** The sequence number of this data package unit. */
57      private int dataSequenceNumber;
58  
59      /** The start offset of the data to send. */
60      private int bufferOffset;
61  
62      // --------------------------------------------------------------------------
63      // --------------------------------------------------------------------------
64  
65      /**
66       * Constructor to create a <code>WriteFirstBurstState</code> instance, which sends the first data sequence.
67       * 
68       * @param initConnection This is the connection, which is used for the network transmission.
69       * @param initIterator The next chunk of the data to send.
70       * @param initTargetTransferTag The Target Transfer Tag to use as next.
71       * @param initDataSequenceNumber The Data Sequence Number to use as next.
72       * @param initBufferOffset The start offset of the data to send.
73       */
74      public WriteFirstBurstState (final Connection initConnection, final IDataSegmentIterator initIterator, final int initTargetTransferTag, final int initDataSequenceNumber, final int initBufferOffset) {
75  
76          super(initConnection);
77          iterator = initIterator;
78          targetTransferTag = initTargetTransferTag;
79          dataSequenceNumber = initDataSequenceNumber;
80          bufferOffset = initBufferOffset;
81      }
82  
83      // --------------------------------------------------------------------------
84      // --------------------------------------------------------------------------
85  
86      /** {@inheritDoc} */
87      public final void execute () throws InternetSCSIException {
88  
89          final Queue<ProtocolDataUnit> protocolDataUnits = new LinkedList<ProtocolDataUnit>();
90  
91          ProtocolDataUnit protocolDataUnit;
92          DataOutParser dataOut;
93          IDataSegmentChunk dataSegmentChunk;
94          boolean finalFlag = false;
95          final int maxRecvDataSegmentLength = connection.getSettingAsInt(OperationalTextKey.MAX_RECV_DATA_SEGMENT_LENGTH);
96          // the remaining bytes to send (do not forget the immediately send
97          // data!)
98          int bytes2Transfer = connection.getSettingAsInt(OperationalTextKey.FIRST_BURST_LENGTH) - bufferOffset;
99  
100         while (bytes2Transfer > 0 && iterator.hasNext()) {
101             if (bytes2Transfer <= maxRecvDataSegmentLength) {
102                 dataSegmentChunk = iterator.next(bytes2Transfer);
103                 finalFlag = true;
104             } else {
105                 dataSegmentChunk = iterator.next(maxRecvDataSegmentLength);
106                 finalFlag = false;
107             }
108 
109             protocolDataUnit = protocolDataUnitFactory.create(false, finalFlag, OperationCode.SCSI_DATA_OUT, connection.getSetting(OperationalTextKey.HEADER_DIGEST), connection.getSetting(OperationalTextKey.DATA_DIGEST));
110             protocolDataUnit.getBasicHeaderSegment().setInitiatorTaskTag(connection.getSession().getInitiatorTaskTag());
111 
112             dataOut = (DataOutParser) protocolDataUnit.getBasicHeaderSegment().getParser();
113 
114             dataOut.setTargetTransferTag(targetTransferTag);
115             dataOut.setDataSequenceNumber(dataSequenceNumber++);
116             dataOut.setBufferOffset(bufferOffset);
117             bufferOffset += maxRecvDataSegmentLength;
118 
119             protocolDataUnit.setDataSegment(dataSegmentChunk);
120 
121             protocolDataUnits.offer(protocolDataUnit);
122             bytes2Transfer -= maxRecvDataSegmentLength;
123         }
124 
125         connection.send(protocolDataUnits);
126 
127         connection.nextState(new WriteSecondResponseState(connection, iterator, dataSequenceNumber, bufferOffset));
128         super.stateFollowing = true;
129         // return true;
130     }
131 
132     // --------------------------------------------------------------------------
133     // --------------------------------------------------------------------------
134     // --------------------------------------------------------------------------
135     // --------------------------------------------------------------------------
136 
137 }