View Javadoc

1   package org.jscsi.target.connection;
2   
3   
4   import org.jscsi.parser.ProtocolDataUnit;
5   import org.jscsi.parser.login.ISID;
6   import org.jscsi.target.Target;
7   import org.jscsi.target.TargetServer;
8   import org.jscsi.target.settings.SessionSettingsNegotiator;
9   import org.jscsi.target.storage.IStorageModule;
10  import org.jscsi.target.util.SerialArithmeticNumber;
11  
12  
13  /**
14   * A class for objects representing an iSCSI session with all necessary variables.
15   * <p>
16   * Currently, a {@link TargetSession} can only have <b>one</b> {@link Connection}, i.e. <code>MaxConnections=1</code>.
17   * 
18   * @author Andreas Ergenzinger, University of Konstanz
19   */
20  public class TargetSession {
21  
22      /**
23       * Returns the value of the next {@link TargetSession} object's {@link #targetSessionIdentifyingHandle} variable.
24       * 
25       * @return the value of the next {@link TargetSession} object's {@link #targetSessionIdentifyingHandle} variable
26       */
27      private static short getNextTargetSessionIdentifyingHandle () {
28          short handle = nextTargetSessionIdentifyingHandle++;// no concurrency
29                                                              // necessary
30          if (handle == 0) {// is reserved
31              handle = nextTargetSessionIdentifyingHandle++;
32          }
33          return handle;
34      }
35  
36      /**
37       * The {@link TargetServer} that this session is associated with
38       */
39      private TargetServer targetServer;
40  
41      /**
42       * The {@link Target} that this session is associated with
43       */
44      private Target target;
45  
46      /**
47       * The {@link TargetConnection} used for exchanging messages and data with the session's initiator endpoint.
48       */
49      private Connection connection;
50  
51      /**
52       * The {@link ISID} used by the initiator for identifying this session.
53       */
54      private ISID initiatorSessionID;
55  
56      /**
57       * Keeps track of the value to expect in the <code>ExpCmdSN</code> field of the next received
58       * {@link ProtocolDataUnit}
59       */
60      private SerialArithmeticNumber expectedCommandSequenceNumber;
61  
62      /**
63       * Determines the number of iSCSI Command {@link ProtocolDataUnit}s the initiator may send without having the wait
64       * for confirmation from the target that the command has finished.
65       * <p>
66       * A value of <code>1</code> means that the initiator must wait for each command to finish before issuing the next
67       * one.
68       * 
69       * @see #getExpectedCommandSequenceNumber()
70       * @see #getMaximumCommandSequenceNumber()
71       */
72      private final int commandWindowSize = 1;
73  
74      /**
75       * The {@link SessionSettingsNegotiator} responsible managing connection parameters with session scope.
76       */
77      private SessionSettingsNegotiator sessionSettingsNegotiator;
78  
79      /**
80       * A value used by the target to identify this session.
81       */
82      private short targetSessionIdentifyingHandle;
83  
84      /**
85       * A counter for {@link #targetSessionIdentifyingHandle}s.
86       * 
87       * @see #getNextTargetSessionIdentifyingHandle()
88       */
89      private static short nextTargetSessionIdentifyingHandle = 1;
90  
91      /**
92       * This value determines if this {@link TargetSession} is a discovery session or a regular (operational) session.
93       */
94      private SessionType sessionType;
95  
96      /**
97       * Constructs a new {@link TargetSession}
98       * 
99       * @param connection the session's (first) {@link Connection}
100      * @param initiatorSessionID the {@link ISID} specified by the initiator
101      * @param expectedCommandSequenceNumber initialization value of {@link #expectedCommandSequenceNumber}
102      * @param statusSequenceNumber the value expected by the initiator in the next {@link ProtocolDataUnit}'s
103      *            <code>StatSN</code> field
104      */
105     public TargetSession (final TargetServer target, final Connection connection, final ISID initiatorSessionID, final int expectedCommandSequenceNumber, final int statusSequenceNumber) {
106         this.targetServer = target;
107         // set connection variables and parameters
108         connection.setSession(this);
109         this.connection = connection;
110         connection.setStatusSequenceNumber(statusSequenceNumber);
111 
112         // initialize ConnectionSettingsNegotiator (makes sure that settings are
113         // initialized)
114         sessionSettingsNegotiator = new SessionSettingsNegotiator();
115         connection.initializeConnectionSettingsNegotiator(sessionSettingsNegotiator);
116 
117         // set session variables
118         this.initiatorSessionID = initiatorSessionID;
119         targetSessionIdentifyingHandle = getNextTargetSessionIdentifyingHandle();
120         this.expectedCommandSequenceNumber = new SerialArithmeticNumber(expectedCommandSequenceNumber);
121     }
122 
123     /**
124      * Returns the session's {@link TargetServer}.
125      * 
126      * @return the session's {@link TargetServer}
127      */
128     public TargetServer getTargetServer () {
129         return targetServer;
130     }
131 
132     /**
133      * Returns the session's {@link Connection}.
134      * 
135      * @return the session's {@link Connection}
136      */
137     public Connection getConnection () {
138         return connection;
139     }
140 
141     /**
142      * Returns the session's {@link Target}
143      * 
144      * @return the session's {@link Target}
145      */
146     public Target getTarget () {
147         return target;
148     }
149 
150     /**
151      * Returns the session's {@link IStorageModule}.
152      * 
153      * @return the session's {@link IStorageModule}
154      */
155     public IStorageModule getStorageModule () {
156         return target.getStorageModule();
157     }
158 
159     /**
160      * Returns the {@link SerialArithmeticNumber} representing the next expected command sequence number.
161      * <p>
162      * This value will be used both during sending (<code>ExpCmdSN</code> field) and receiving ( <code>CmdSN</code>) of
163      * {@link ProtocolDataUnit}s.
164      * 
165      * @return the {@link SerialArithmeticNumber} representing the next expected command sequence number
166      * @see #expectedCommandSequenceNumber
167      */
168     SerialArithmeticNumber getExpectedCommandSequenceNumber () {
169         return expectedCommandSequenceNumber;
170     }
171 
172     /**
173      * Returns the {@link ISID} used by the initiator to identify this session.
174      * 
175      * @return the {@link ISID} used by the initiator to identify this session
176      */
177     public ISID getInitiatorSessionID () {
178         return initiatorSessionID;
179     }
180 
181     /**
182      * Returns a {@link SerialArithmeticNumber} representing the maximum command sequence number the target will accept.
183      * <p>
184      * This value will be used both during sending (<code>MaxCmdSN</code> field) and receiving (checking if PDU's
185      * <code>CmdSN</code> lies in the command sequence number window resulting from
186      * {@link #expectedCommandSequenceNumber} and {@link #commandWindowSize}) of {@link ProtocolDataUnit}s.
187      * 
188      * @return the {@link SerialArithmeticNumber} representing the next expected command sequence number
189      */
190     SerialArithmeticNumber getMaximumCommandSequenceNumber () {
191         return new SerialArithmeticNumber(expectedCommandSequenceNumber.getValue() + commandWindowSize - 1);
192     }
193 
194     /**
195      * Returns the value used by the jSCSI Target to identify this session.
196      * 
197      * @return the value used by the jSCSI Target to identify this session
198      */
199     public short getTargetSessionIdentifyingHandle () {
200         return targetSessionIdentifyingHandle;
201     }
202 
203     /**
204      * Returns <code>true</code> if this session is a regular (operational) session, and <code>false</code> if it is s
205      * discovery session.
206      * 
207      * @return <code>true</code> if and only if this is not a regular (operational) session
208      */
209     public boolean isNormalSession () {
210         return sessionType == SessionType.NORMAL;
211     }
212 
213     /**
214      * Removes a {@link TargetConnection} from the session's list of open connections. If this reduces the number of
215      * connections to zero, the session will be removed from the {@link TargetServer}'s list of active sessions.
216      * 
217      * @param connection the connection to be removed
218      */
219     void removeTargetConnection (Connection connection) {
220         // do this only if connection count == 0, currently it always is
221         targetServer.removeTargetSession(this);
222     }
223 
224     /**
225      * Sets the session's type (discovery or operational).
226      * <p>
227      * The type may and must be set just once. Repeated calls of this method will fail. <code>true</code> will be
228      * returned if the session type was set successfully, <code>false</code> if not.
229      * 
230      * @param sessionType the session type
231      * @return <code>true</code> if the session type was set successfully, <code>false</code> if not
232      */
233     boolean setSessionType (SessionType sessionType) {
234         // allow just once, accept only non-null parameter
235         if (sessionType == null || this.sessionType != null) return false;
236         this.sessionType = sessionType;
237         return true;
238     }
239 
240     /**
241      * Sets the target name and retrieves the target (if it exists) from the TargetServer
242      * 
243      * @param targetName
244      */
245     public void setTargetName (String targetName) {
246         if (targetName == null) target = null;
247         target = targetServer.getTarget(targetName);
248     }
249 
250     public String getTargetName () {
251         if (target != null) return target.getTargetName();
252         return null;
253     }
254 }