Coverage Report - org.jscsi.target.settings.SessionSettingsNegotiator
 
Classes in this File Line Coverage Branch Coverage Complexity
SessionSettingsNegotiator
0%
0/36
0%
0/2
1.444
 
 1  
 package org.jscsi.target.settings;
 2  
 
 3  
 
 4  
 import java.util.concurrent.atomic.AtomicLong;
 5  
 import java.util.concurrent.locks.Lock;
 6  
 
 7  
 import javax.naming.OperationNotSupportedException;
 8  
 
 9  
 import org.jscsi.target.connection.TargetSession;
 10  
 import org.jscsi.target.settings.entry.BooleanEntry;
 11  
 import org.jscsi.target.settings.entry.Entry;
 12  
 import org.jscsi.target.settings.entry.NumericalEntry;
 13  
 import org.jscsi.target.settings.entry.StringEntry;
 14  
 import org.jscsi.target.settings.entry.Use;
 15  
 import org.jscsi.target.util.BinaryLock;
 16  
 
 17  
 
 18  
 /**
 19  
  * A class for managing {@link Entry} objects responsible for negotiating session-wide parameters.
 20  
  * <p>
 21  
  * Each instance of this class belongs to one {@link TargetSession} object.
 22  
  * 
 23  
  * @see SettingsNegotiator
 24  
  * @author Andreas Ergenzinger
 25  
  */
 26  
 public final class SessionSettingsNegotiator extends SettingsNegotiator {
 27  
 
 28  
     /**
 29  
      * Prevents concurrent negotiations over multiple connections of the same session.
 30  
      * 
 31  
      * @see #lock()
 32  
      * @see #unlock()
 33  
      */
 34  0
     private final BinaryLock lock = new BinaryLock();
 35  
 
 36  
     /**
 37  
      * A counter that provides a unique, ordered identifying value for {@link Settings} objects.
 38  
      */
 39  0
     private final AtomicLong currentSettingsId = new AtomicLong();
 40  
 
 41  
     /**
 42  
      * A current snapshot of all session-wide parameters.
 43  
      */
 44  
     private SessionSettingsBuilderComponent sessionSettingBuilderComponent;
 45  
 
 46  
     /**
 47  
      * The {@link SessionSettingsNegotiator} constructor.
 48  
      */
 49  
     public SessionSettingsNegotiator () {
 50  0
         super();// initializes entries
 51  0
         updateSettingsBuilderComponent();
 52  0
     }
 53  
 
 54  
     /**
 55  
      * Blocks until the {@link #lock()} has been acquired and returns <code>true</code> or returns <code>false</code> if
 56  
      * the method returned prematurely due to an interrupt.
 57  
      * <p>
 58  
      * The usual safeguards with using {@link Lock} objects should be applied, namely using
 59  
      * <code>try ...  catch ... finally ...</code> blocks to make sure the lock is always released.
 60  
      * 
 61  
      * @return <code>true</code>if and only if the lock has been acquired
 62  
      */
 63  
     boolean lock () {
 64  0
         return lock.lock();
 65  
     }
 66  
 
 67  
     /**
 68  
      * Releases the {@link #lock} if called by the locking {@link Thread}.
 69  
      * 
 70  
      * @see #lock()
 71  
      */
 72  
     void unlock () {
 73  0
         lock.unlock();
 74  0
     }
 75  
 
 76  
     /**
 77  
      * Returns the {@link Entry} responsible for negotiating the specified <i>key</i> identifying a session-wide
 78  
      * parameter, or <code>null</code> if no such {@link Entry} can be found.
 79  
      * 
 80  
      * @param key identifies an {@link Entry} responsible for a session-wide parameter
 81  
      * @return the requested {@link Entry} or <code>null</code>
 82  
      */
 83  
     Entry getEntry (final String key) {
 84  0
         return getEntry(key, entries);
 85  
     }
 86  
 
 87  
     long getCurrentSettingsId () {
 88  0
         return currentSettingsId.get();
 89  
     }
 90  
 
 91  
     @Override
 92  
     protected void initializeEntries () {
 93  
 
 94  
         /*
 95  
          * No indicates that the data PDUs within a sequence can be in any order. Yes indicates that the data PDUs
 96  
          * within a sequence have to be at continuously increasing addresses and that overlays are forbidden.
 97  
          */
 98  0
         entries.add(new BooleanEntry(new KeySet(TextKeyword.DATA_PDU_IN_ORDER),// keySet
 99  
         Use.LEADING_LOPNS,// use
 100  
         NegotiationStatus.DEFAULT,// negotiationStatus
 101  
         true,// negotiationValue
 102  
         BooleanResultFunction.OR,// resultFunction
 103  
         true));// defaultValue
 104  
 
 105  
         /*
 106  
          * If set to No, the data PDU sequence may be transferred in any order. If set to Yes, the sequence must be
 107  
          * transferred using continuously increasing offsets except for error recovery.
 108  
          */
 109  0
         entries.add(new BooleanEntry(new KeySet(TextKeyword.DATA_SEQUENCE_IN_ORDER),// keySet
 110  
         Use.LEADING_LOPNS,// use
 111  
         NegotiationStatus.DEFAULT,// negotiationStatus
 112  
         true,// negotiationValue
 113  
         BooleanResultFunction.OR,// resultFunction
 114  
         true));// defaultValue
 115  
 
 116  
         /*
 117  
          * Max seconds that connection and task allegiance reinstatement is still possible following a connection
 118  
          * termination or reset. A value of zero means that no reinstatement is possible.
 119  
          */
 120  0
         entries.add(new NumericalEntry(new KeySet(TextKeyword.DEFAULT_TIME_2_RETAIN, TextKeyword.TIME_2_RETAIN),// keySet
 121  
         NegotiationType.NEGOTIATED,// negotiationType
 122  
         Use.LEADING_LOPNS,// use
 123  
         NegotiationStatus.DEFAULT,// negotiationStatus
 124  
         0,// negotiationValue
 125  
         NumericalValueRange.create(0, 3600),// protocolValueRange
 126  
         NumericalResultFunction.MIN,// resultFunction
 127  
         20,// defaultValue
 128  
         false));// zeroMeansDontCare
 129  
 
 130  
         /*
 131  
          * Min seconds to wait before attempting connection and task allegiance reinstatement after a connection
 132  
          * termination or a connection reset. A value of zero means that task reassignment can be done immediately.
 133  
          */
 134  0
         entries.add(new NumericalEntry(new KeySet(TextKeyword.DEFAULT_TIME_2_WAIT, TextKeyword.TIME_2_WAIT),// keySet
 135  
         NegotiationType.NEGOTIATED,// negotiationType
 136  
         Use.LEADING_LOPNS,// use
 137  
         NegotiationStatus.DEFAULT,// negotiationStatus
 138  
         2,// negotiationValue
 139  
         NumericalValueRange.create(0, 3600),// protocolValueRange
 140  
         NumericalResultFunction.MAX,// resultFunction
 141  
         2,// defaultValue
 142  
         false));// zeroMeansDontCare
 143  
 
 144  
         /*
 145  
          * Recovery levels represent a combination of recovery capabilities. Each level includes all the capabilities of
 146  
          * the lower recovery level.
 147  
          */
 148  0
         entries.add(new NumericalEntry(new KeySet(TextKeyword.ERROR_RECOVERY_LEVEL),// keySet
 149  
         NegotiationType.NEGOTIATED,// negotiationType
 150  
         Use.LEADING_LOPNS,// use
 151  
         NegotiationStatus.DEFAULT,// negotiationStatus
 152  
         0,// negotiationValue
 153  
         NumericalValueRange.create(0, 2),// protocolValueRange
 154  
         NumericalResultFunction.MIN,// resultFunction
 155  
         0,// defaultValue
 156  
         false));// zeroMeansDontCare
 157  
 
 158  
         /*
 159  
          * Maximum SCSI payload, in bytes, of unsolicited data an initiator may send to the target. Includes immediate
 160  
          * data and a sequence of unsolicited Data-Out PDUs. Zero (don't care) can be used. Must be <= MaxBurstLength.
 161  
          */
 162  0
         entries.add(new NumericalEntry(new KeySet(TextKeyword.FIRST_BURST_LENGTH),// keySet
 163  
         NegotiationType.NEGOTIATED,// negotiationType
 164  
         Use.LEADING_LOPNS,// use
 165  
         NegotiationStatus.DEFAULT,// negotiationStatus
 166  
         65536,// negotiationValue (default value)
 167  
         NumericalValueRange.create(512, 16777215),// protocolValueRange
 168  
         // 512 to 2^24 - 1
 169  
         NumericalResultFunction.MIN,// resultFunction
 170  
         65536,// defaultValue, 64K
 171  
         true));// zeroMeansDontCare
 172  
 
 173  
         /*
 174  
          * Either the initiator or target can turn off ImmediateData.
 175  
          */
 176  0
         entries.add(new BooleanEntry(new KeySet(TextKeyword.IMMEDIATE_DATA),// keySet
 177  
         Use.LEADING_LOPNS,// use
 178  
         NegotiationStatus.DEFAULT,// negotiationStatus
 179  
         true,// negotiationValue
 180  
         BooleanResultFunction.AND,// resultFunction
 181  
         true));// defaultValue
 182  
 
 183  
         /*
 184  
          * Turns off the default use of R2T; allows an initiator to start sending data to a target as if it had received
 185  
          * an initial R2T.
 186  
          */
 187  0
         entries.add(new BooleanEntry(new KeySet(TextKeyword.INITIAL_R_2_T),// keySet
 188  
         Use.LEADING_LOPNS,// use
 189  
         NegotiationStatus.DEFAULT,// negotiationStatus
 190  
         true,// negotiationValue
 191  
         BooleanResultFunction.OR,// resultFunction
 192  
         true));// defaultValue
 193  
 
 194  
         /*
 195  
          * Sent to the target in the login PDU.
 196  
          */
 197  0
         entries.add(new StringEntry(new KeySet(TextKeyword.INITIATOR_ALIAS),// keySet
 198  
         NegotiationType.DECLARED,// negotiationType
 199  
         Use.INITIAL_AND_FFP,// use
 200  
         NegotiationStatus.NOT_NEGOTIATED,// negotiationStatus
 201  
         null,// supportedValues, anything goes
 202  
         null));// defaultValue
 203  
 
 204  
         /*
 205  
          * Must be sent on first login request per connection.
 206  
          */
 207  0
         entries.add(new StringEntry(new KeySet(TextKeyword.INITIATOR_NAME),// keySet
 208  
         NegotiationType.DECLARED,// negotiationType
 209  
         Use.INITIAL,// use
 210  
         NegotiationStatus.NOT_NEGOTIATED,// negotiationStatus
 211  
         null,// supportedValues, anything goes
 212  
         null));// defaultValue
 213  
 
 214  
         /*
 215  
          * Maximum SCSI data payload in bytes for data-in or for a solicited data-out sequence. Zero (don't care) can be
 216  
          * used.
 217  
          */
 218  0
         entries.add(new NumericalEntry(new KeySet(TextKeyword.MAX_BURST_LENGTH),// keySet
 219  
         NegotiationType.NEGOTIATED,// negotiationType
 220  
         Use.LEADING_LOPNS,// use
 221  
         NegotiationStatus.DEFAULT,// negotiationStatus
 222  
         262144,// negotiationValue (default value)
 223  
         NumericalValueRange.create(512, 16777215),// protocolValueRange
 224  
         // 512 to 2^24 - 1
 225  
         NumericalResultFunction.MIN,// resultFunction
 226  
         262144,// defaultValue, 256K
 227  
         true));// zeroMeansDontCare
 228  
 
 229  
         /*
 230  
          * The initiator and target negotiate the maximum number of connections that can be requested or are acceptable.
 231  
          */
 232  0
         entries.add(new NumericalEntry(new KeySet(TextKeyword.MAX_CONNECTIONS),// keySet
 233  
         NegotiationType.NEGOTIATED,// negotiationType
 234  
         Use.LEADING_LOPNS,// use
 235  
         NegotiationStatus.DEFAULT,// negotiationStatus
 236  
         1,// negotiationValue (default value)
 237  
         NumericalValueRange.create(1, 65535),// protocolValueRange
 238  
         NumericalResultFunction.MIN,// resultFunction
 239  
         1,// defaultValue
 240  
         false));// zeroMeansDontCare
 241  
 
 242  
         /*
 243  
          * The maximum number of outstanding R2Ts.
 244  
          */
 245  0
         entries.add(new NumericalEntry(new KeySet(TextKeyword.MAX_OUTSTANDING_R_2_T),// keySet
 246  
         NegotiationType.NEGOTIATED,// negotiationType
 247  
         Use.LEADING_LOPNS,// use
 248  
         NegotiationStatus.DEFAULT,// negotiationStatus
 249  
         1,// negotiationValue (default value)
 250  
         NumericalValueRange.create(1, 65535),// protocolValueRange
 251  
         NumericalResultFunction.MIN,// resultFunction
 252  
         1,// defaultValue
 253  
         false));// zeroMeansDontCare
 254  
 
 255  
         /*
 256  
          * The session type (Normal or Discovery).
 257  
          */
 258  0
         entries.add(new StringEntry(new KeySet(TextKeyword.SESSION_TYPE),// keySet
 259  
         NegotiationType.DECLARED,// negotiationType
 260  
         Use.INITIAL,// use
 261  
         NegotiationStatus.DEFAULT,// negotiationStatus
 262  
         null,// supportedValues, no checking
 263  
         TextKeyword.NORMAL));// defaultValue
 264  0
     }
 265  
 
 266  
     /**
 267  
      * Updates {@link #sessionSettingBuilderComponent} with the currently valid parameters retrieved from the elements
 268  
      * of {@link SettingsNegotiator#entries}.
 269  
      */
 270  
     protected void updateSettingsBuilderComponent () {
 271  
 
 272  0
         sessionSettingBuilderComponent = new SessionSettingsBuilderComponent(currentSettingsId.getAndIncrement() + 1,// settingsId
 273  
         entries);// entries with current/new values
 274  0
     }
 275  
 
 276  
     SessionSettingsBuilderComponent getSessionSettingsBuilderComponent () {
 277  0
         return sessionSettingBuilderComponent;
 278  
     }
 279  
 
 280  
     @Override
 281  
     public boolean checkConstraints () {
 282  
         try {
 283  
             // ensure FirstBurstLength <= MaxBurstLength
 284  0
             final int firstBurstLength = getEntry(TextKeyword.FIRST_BURST_LENGTH).getIntegerValue();
 285  0
             final int maxBurstLength = getEntry(TextKeyword.MAX_BURST_LENGTH).getIntegerValue();
 286  0
             if (maxBurstLength > firstBurstLength) return false;
 287  0
         } catch (OperationNotSupportedException e) {
 288  
             // programmer error, requested wrong data type
 289  0
             e.printStackTrace();
 290  0
             return false;
 291  0
         }
 292  0
         return true;
 293  
     }
 294  
 }