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 org.jscsi.exception.InternetSCSIException;
23  import org.jscsi.exception.OperationalTextKeyException;
24  import org.jscsi.initiator.connection.Connection;
25  import org.jscsi.parser.ProtocolDataUnit;
26  import org.jscsi.parser.datasegment.IDataSegmentIterator;
27  import org.jscsi.parser.datasegment.OperationalTextKey;
28  import org.jscsi.parser.r2t.Ready2TransferParser;
29  import org.jscsi.parser.scsi.SCSIResponseParser;
30  import org.jscsi.parser.scsi.SCSIStatus;
31  
32  
33  /**
34   * <h1>WriteSecondResponseState</h1>
35   * <p/>
36   * This state handles the response(s) after the second and following data sequences was/were sent.
37   * 
38   * @author Volker Wildi
39   */
40  public final class WriteSecondResponseState extends AbstractState {
41  
42      // --------------------------------------------------------------------------
43      // --------------------------------------------------------------------------
44  
45      /** The chunk of the data segment to send as next. */
46      private final IDataSegmentIterator iterator;
47  
48      /** The sequence number of this data package unit. */
49      private final int dataSequenceNumber;
50  
51      /** The start offset of the data to send. */
52      private final int bufferOffset;
53  
54      // --------------------------------------------------------------------------
55      // --------------------------------------------------------------------------
56  
57      /**
58       * Constructor to create a <code>WriteSecondResponseState</code> instance, which handles the response of the iSCSI
59       * Target.
60       * 
61       * @param initConnection This is the connection, which is used for the network transmission.
62       * @param initIterator The next chunk of data to send as next with the next write data sequence.
63       * @param initDataSequenceNumber The Data Sequence Number to use as next.
64       * @param initBufferOffset The start offset of the data to send.
65       */
66      public WriteSecondResponseState (final Connection initConnection, final IDataSegmentIterator initIterator, final int initDataSequenceNumber, final int initBufferOffset) {
67  
68          super(initConnection);
69          iterator = initIterator;
70          dataSequenceNumber = initDataSequenceNumber;
71          bufferOffset = initBufferOffset;
72      }
73  
74      // --------------------------------------------------------------------------
75      // --------------------------------------------------------------------------
76  
77      /** {@inheritDoc} */
78      public final void execute () throws InternetSCSIException {
79  
80          final ProtocolDataUnit protocolDataUnit = connection.receive();
81          LOGGER.trace("1" + protocolDataUnit);
82          if (protocolDataUnit.getBasicHeaderSegment().getParser() instanceof Ready2TransferParser) {
83              LOGGER.trace("2");
84              final Ready2TransferParser parser = (Ready2TransferParser) protocolDataUnit.getBasicHeaderSegment().getParser();
85  
86              final int targetTransferTag = parser.getTargetTransferTag();
87              if (LOGGER.isDebugEnabled()) {
88                  LOGGER.debug("R2T has TTT set to " + targetTransferTag);
89              }
90  
91              final int desiredDataTransferLength = parser.getDesiredDataTransferLength();
92              if (desiredDataTransferLength > connection.getSettingAsInt(OperationalTextKey.MAX_BURST_LENGTH)) {
93                  if (LOGGER.isErrorEnabled()) {
94                      LOGGER.error("MaxBurstLength limit is exceed.");
95                  }
96                  throw new InternetSCSIException("MaxBurstLength limit is exceed.");
97              }
98  
99              connection.nextState(new WriteSecondBurstState(connection, iterator, targetTransferTag, desiredDataTransferLength, dataSequenceNumber, bufferOffset));
100             super.stateFollowing = true;
101             // return true;
102             return;
103         } else if (protocolDataUnit.getBasicHeaderSegment().getParser() instanceof SCSIResponseParser) {
104             final SCSIResponseParser parser = (SCSIResponseParser) protocolDataUnit.getBasicHeaderSegment().getParser();
105 
106             if (!iterator.hasNext() && parser.getStatus() == SCSIStatus.GOOD) {
107                 connection.getSession().incrementInitiatorTaskTag();
108                 // return false;
109                 super.stateFollowing = false;
110                 return;
111             }
112         }
113 
114         throw new RuntimeException(protocolDataUnit.getBasicHeaderSegment().getParser().toString());
115     }
116 
117     // --------------------------------------------------------------------------
118     // --------------------------------------------------------------------------
119 
120     /** {@inheritDoc} */
121     @Override
122     public final Exception isCorrect (final ProtocolDataUnit protocolDataUnit) {
123 
124         // FIXME: Implement
125         try {
126             if (!connection.getSettingAsBoolean(OperationalTextKey.DATA_PDU_IN_ORDER) && !connection.getSettingAsBoolean(OperationalTextKey.DATA_SEQUENCE_IN_ORDER)) {
127                 return new UnsupportedOperationException(new StringBuilder(OperationalTextKey.DATA_PDU_IN_ORDER.toString()).append(" is yet not supported.").toString());
128             } else {
129                 return null;
130             }
131         } catch (OperationalTextKeyException e) {
132             return e;
133         }
134 
135     }
136 
137     // --------------------------------------------------------------------------
138     // --------------------------------------------------------------------------
139     // --------------------------------------------------------------------------
140     // --------------------------------------------------------------------------
141 
142 }