001    /*
002     * Copyright 2014-2015 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2015 UnboundID Corp.
007     *
008     * This program is free software; you can redistribute it and/or modify
009     * it under the terms of the GNU General Public License (GPLv2 only)
010     * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011     * as published by the Free Software Foundation.
012     *
013     * This program is distributed in the hope that it will be useful,
014     * but WITHOUT ANY WARRANTY; without even the implied warranty of
015     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016     * GNU General Public License for more details.
017     *
018     * You should have received a copy of the GNU General Public License
019     * along with this program; if not, see <http://www.gnu.org/licenses>.
020     */
021    package com.unboundid.ldap.sdk.unboundidds.controls;
022    
023    
024    
025    import java.util.ArrayList;
026    
027    import com.unboundid.asn1.ASN1Boolean;
028    import com.unboundid.asn1.ASN1Element;
029    import com.unboundid.asn1.ASN1Enumerated;
030    import com.unboundid.asn1.ASN1Integer;
031    import com.unboundid.asn1.ASN1Long;
032    import com.unboundid.asn1.ASN1OctetString;
033    import com.unboundid.asn1.ASN1Sequence;
034    import com.unboundid.ldap.sdk.Control;
035    import com.unboundid.ldap.sdk.LDAPException;
036    import com.unboundid.ldap.sdk.ResultCode;
037    import com.unboundid.util.Debug;
038    import com.unboundid.util.NotMutable;
039    import com.unboundid.util.StaticUtils;
040    import com.unboundid.util.ThreadSafety;
041    import com.unboundid.util.ThreadSafetyLevel;
042    import com.unboundid.util.Validator;
043    
044    import static com.unboundid.ldap.sdk.unboundidds.controls.ControlMessages.*;
045    
046    
047    
048    /**
049     * <BLOCKQUOTE>
050     *   <B>NOTE:</B>  This class is part of the Commercial Edition of the UnboundID
051     *   LDAP SDK for Java.  It is not available for use in applications that
052     *   include only the Standard Edition of the LDAP SDK, and is not supported for
053     *   use in conjunction with non-UnboundID products.
054     * </BLOCKQUOTE>
055     * This class provides a request control that can be used to specify a number of
056     * settings used for any database transaction that may be associated with the
057     * associated request.  It may be included in an end transaction extended
058     * request or an atomic multi-update extended request (it is not supported for
059     * use in non-atomic multi-update requests).
060     * <BR><BR>
061     * This control has an OID of 1.3.6.1.4.1.30221.2.5.38.  It may have a
062     * criticality of either {@code true} (in which case the server will reject the
063     * associated operation if this control is not recognized) or {@code false} (in
064     * which case the server will ignore this control if it is not recognized).  It
065     * must have a value with the following encoding:
066     * <PRE>
067     *   TransactionSettingsRequestValue ::= SEQUENCE {
068     *        transactionName              [0] OCTET STRING OPTIONAL,
069     *        commitDurability             [1] ENUMERATED {
070     *             nonSynchronous           (0),
071     *             partiallySynchronous     (1),
072     *             fullySynchronous         (2),
073     *             ... } OPTIONAL,
074     *        backendLockBehavior          [2] ENUMERATED {
075     *             doNotAcquire                    (0),
076     *             acquireAfterRetries             (1),
077     *             acquireBeforeRetries            (2),
078     *             acquireBeforeInitialAttempt     (3),
079     *             ... } OPTIONAL,
080     *        backendLockTimeoutMillis     [3] INTEGER OPTIONAL,
081     *        retryAttempts                [4] INTEGER OPTIONAL,
082     *        txnLockTimeout               [5] SEQUENCE {
083     *             minTimeoutMillis     INTEGER,
084     *             maxTimeoutMillis     INTEGER,
085     *             ... } OPTIONAL,
086     *        returnResponseControl        [6] BOOLEAN DEFAULT FALSE,
087     *        ... }
088     * </PRE>
089     */
090    @NotMutable()
091    @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
092    public final class TransactionSettingsRequestControl
093           extends Control
094    {
095      /**
096       * The OID (1.3.6.1.4.1.30221.2.5.38) for the undelete request control.
097       */
098      public static final String TRANSACTION_SETTINGS_REQUEST_OID =
099           "1.3.6.1.4.1.30221.2.5.38";
100    
101    
102    
103      /**
104       * The BER type for the value sequence element that specifies the name to use
105       * for the transaction.
106       */
107      private static final byte TYPE_TXN_NAME = (byte) 0x80;
108    
109    
110    
111      /**
112       * The BER type for the value sequence element that specifies the commit
113       * durability to use.
114       */
115      private static final byte TYPE_COMMIT_DURABILITY = (byte) 0x81;
116    
117    
118    
119      /**
120       * The BER type for the value sequence element that specifies the behavior
121       * to use with regard to acquiring the exclusive backend lock.
122       */
123      private static final byte TYPE_BACKEND_LOCK_BEHAVIOR = (byte) 0x82;
124    
125    
126    
127      /**
128       * The BER type for the value sequence element that specifies the exclusive
129       * backend lock timeout.
130       */
131      private static final byte TYPE_BACKEND_LOCK_TIMEOUT = (byte) 0x83;
132    
133    
134    
135      /**
136       * The BER type for the value sequence element that specifies the number of
137       * retry attempts.
138       */
139      private static final byte TYPE_RETRY_ATTEMPTS = (byte) 0x84;
140    
141    
142    
143      /**
144       * The BER type for the value sequence element that specifies the minimum and
145       * maximum database lock timeout values.
146       */
147      private static final byte TYPE_TXN_LOCK_TIMEOUT = (byte) 0xA5;
148    
149    
150    
151      /**
152       * The BER type for the value sequence element that indicates whether to
153       * return a response control with transaction-related information about the
154       * processing of the associated operation.
155       */
156      private static final byte TYPE_RETURN_RESPONSE_CONTROL = (byte) 0x86;
157    
158    
159    
160      /**
161       * The serial version UID for this serializable class.
162       */
163      private static final long serialVersionUID = -4749344077745581287L;
164    
165    
166    
167      // Indicates whether to return a response control.
168      private final boolean returnResponseControl;
169    
170      // The number of times to retry if a lock conflict exception is encountered.
171      private final Integer retryAttempts;
172    
173      // The backend lock timeout, in milliseconds.
174      private final Long backendLockTimeoutMillis;
175    
176      // The maximum transaction lock timeout, in milliseconds.
177      private final Long maxTxnLockTimeoutMillis;
178    
179      // The minimum transaction lock timeout, in milliseconds.
180      private final Long minTxnLockTimeoutMillis;
181    
182      // The requested transaction name.
183      private final String transactionName;
184    
185      // The requested commit durability setting.
186      private final TransactionSettingsBackendLockBehavior backendLockBehavior;
187    
188      // The requested commit durability setting.
189      private final TransactionSettingsCommitDurability commitDurability;
190    
191    
192    
193      /**
194       * Creates a new transaction settings request control with the provided
195       * information.
196       *
197       * @param  isCritical                Indicates whether the control should be
198       *                                   considered critical.
199       * @param  transactionName           The name to use for the transaction.  It
200       *                                   may be {@code null} if no
201       *                                   client-specified transaction name is
202       *                                   needed.  If a transaction name is
203       *                                   provided, it will be used purely for
204       *                                   informational and/or troubleshooting
205       *                                   purposes.
206       * @param  commitDurability          The durability level that should be used
207       *                                   when committing the associated
208       *                                   transaction.  It may be {@code null} if
209       *                                   the server-default durability level
210       *                                   should be used.
211       * @param  backendLockBehavior       The behavior that should be used with
212       *                                   regard to acquiring an exclusive lock for
213       *                                   processing in the target backend.  It may
214       *                                   be {@code null} if the server-default
215       *                                   backend lock behavior should be used.
216       * @param  backendLockTimeoutMillis  The maximum length of time in
217       *                                   milliseconds to spend attempting to
218       *                                   acquire an exclusive backend lock if it
219       *                                   is needed during any part of the
220       *                                   processing.  A value that of zero
221       *                                   indicates that no timeout should be
222       *                                   enforced.  It may be {@code null} if the
223       *                                   server will determine the backend lock
224       *                                   timeout that should be used.
225       * @param  retryAttempts             The number of times to retry the
226       *                                   associated operations in a new
227       *                                   transaction if the initial attempt fails.
228       *                                   If this is {@code null}, then the server
229       *                                   will determine the number of retry
230       *                                   attempts to make.  Note that depending on
231       *                                   the backend lock behavior, the server may
232       *                                   make one additional retry attempt if
233       *                                   necessary after acquiring an exclusive
234       *                                   backend lock.
235       * @param  minTxnLockTimeoutMillis   The minimum database lock timeout that
236       *                                   should be used for the associated
237       *                                   transaction.  If this is specified, then
238       *                                   the first attempt will use this lock
239       *                                   timeout, and subsequent attempts will use
240       *                                   a timeout value between this and the
241       *                                   maximum database lock timeout (which must
242       *                                   also be specified).  If this is
243       *                                   {@code null}, then the server will
244       *                                   determine the database lock timeout
245       *                                   settings to use.
246       * @param  maxTxnLockTimeoutMillis   The maximum database lock timeout that
247       *                                   should be used for the associated
248       *                                   transaction.  If this is specified, then
249       *                                   the minimum database lock timeout must
250       *                                   also be specified, and this value must be
251       *                                   greater than or equal to the minimum lock
252       *                                   timeout.  If this is {@code null}, then
253       *                                   the server will determine the database
254       *                                   lock timeout settings to use.
255       */
256      public TransactionSettingsRequestControl(final boolean isCritical,
257                  final String transactionName,
258                  final TransactionSettingsCommitDurability commitDurability,
259                  final TransactionSettingsBackendLockBehavior backendLockBehavior,
260                  final Long backendLockTimeoutMillis, final Integer retryAttempts,
261                  final Long minTxnLockTimeoutMillis,
262                  final Long maxTxnLockTimeoutMillis)
263      {
264        this(isCritical, transactionName, commitDurability, backendLockBehavior,
265             backendLockTimeoutMillis, retryAttempts, minTxnLockTimeoutMillis,
266             maxTxnLockTimeoutMillis, false);
267      }
268    
269    
270    
271      /**
272       * Creates a new transaction settings request control with the provided
273       * information.
274       *
275       * @param  isCritical                Indicates whether the control should be
276       *                                   considered critical.
277       * @param  transactionName           The name to use for the transaction.  It
278       *                                   may be {@code null} if no
279       *                                   client-specified transaction name is
280       *                                   needed.  If a transaction name is
281       *                                   provided, it will be used purely for
282       *                                   informational and/or troubleshooting
283       *                                   purposes.
284       * @param  commitDurability          The durability level that should be used
285       *                                   when committing the associated
286       *                                   transaction.  It may be {@code null} if
287       *                                   the server-default durability level
288       *                                   should be used.
289       * @param  backendLockBehavior       The behavior that should be used with
290       *                                   regard to acquiring an exclusive lock for
291       *                                   processing in the target backend.  It may
292       *                                   be {@code null} if the server-default
293       *                                   backend lock behavior should be used.
294       * @param  backendLockTimeoutMillis  The maximum length of time in
295       *                                   milliseconds to spend attempting to
296       *                                   acquire an exclusive backend lock if it
297       *                                   is needed during any part of the
298       *                                   processing.  A value that of zero
299       *                                   indicates that no timeout should be
300       *                                   enforced.  It may be {@code null} if the
301       *                                   server will determine the backend lock
302       *                                   timeout that should be used.
303       * @param  retryAttempts             The number of times to retry the
304       *                                   associated operations in a new
305       *                                   transaction if the initial attempt fails.
306       *                                   If this is {@code null}, then the server
307       *                                   will determine the number of retry
308       *                                   attempts to make.  Note that depending on
309       *                                   the backend lock behavior, the server may
310       *                                   make one additional retry attempt if
311       *                                   necessary after acquiring an exclusive
312       *                                   backend lock.
313       * @param  minTxnLockTimeoutMillis   The minimum database lock timeout that
314       *                                   should be used for the associated
315       *                                   transaction.  If this is specified, then
316       *                                   the first attempt will use this lock
317       *                                   timeout, and subsequent attempts will use
318       *                                   a timeout value between this and the
319       *                                   maximum database lock timeout (which must
320       *                                   also be specified).  If this is
321       *                                   {@code null}, then the server will
322       *                                   determine the database lock timeout
323       *                                   settings to use.
324       * @param  maxTxnLockTimeoutMillis   The maximum database lock timeout that
325       *                                   should be used for the associated
326       *                                   transaction.  If this is specified, then
327       *                                   the minimum database lock timeout must
328       *                                   also be specified, and this value must be
329       *                                   greater than or equal to the minimum lock
330       *                                   timeout.  If this is {@code null}, then
331       *                                   the server will determine the database
332       *                                   lock timeout settings to use.
333       * @param  returnResponseControl     Indicates whether to return a response
334       *                                   control with transaction-related
335       *                                   information collected over the course of
336       *                                   processing the associated operation.
337       */
338      public TransactionSettingsRequestControl(final boolean isCritical,
339                  final String transactionName,
340                  final TransactionSettingsCommitDurability commitDurability,
341                  final TransactionSettingsBackendLockBehavior backendLockBehavior,
342                  final Long backendLockTimeoutMillis, final Integer retryAttempts,
343                  final Long minTxnLockTimeoutMillis,
344                  final Long maxTxnLockTimeoutMillis,
345                  final boolean returnResponseControl)
346      {
347        super(TRANSACTION_SETTINGS_REQUEST_OID, isCritical,
348             encodeValue(transactionName, commitDurability, backendLockBehavior,
349                  backendLockTimeoutMillis, retryAttempts, minTxnLockTimeoutMillis,
350                  maxTxnLockTimeoutMillis, returnResponseControl));
351    
352        this.transactionName          = transactionName;
353        this.commitDurability         = commitDurability;
354        this.backendLockBehavior      = backendLockBehavior;
355        this.backendLockTimeoutMillis = backendLockTimeoutMillis;
356        this.minTxnLockTimeoutMillis  = minTxnLockTimeoutMillis;
357        this.maxTxnLockTimeoutMillis  = maxTxnLockTimeoutMillis;
358        this.retryAttempts            = retryAttempts;
359        this.returnResponseControl    = returnResponseControl;
360      }
361    
362    
363    
364      /**
365       * Creates a new transaction settings request control that is decoded from the
366       * provided generic control.
367       *
368       * @param  c  The generic control to decode as a transaction settings request
369       *            control.
370       *
371       * @throws  LDAPException  If a problem is encountered while attempting to
372       *                         decode the provided control as a transaction
373       *                         settings request control.
374       */
375      public TransactionSettingsRequestControl(final Control c)
376             throws LDAPException
377      {
378        super(c);
379    
380        final ASN1OctetString value = c.getValue();
381        if (value == null)
382        {
383          throw new LDAPException(ResultCode.DECODING_ERROR,
384               ERR_TXN_SETTINGS_REQUEST_MISSING_VALUE.get());
385        }
386    
387        try
388        {
389          boolean                                responseControl   = false;
390          Integer                                numRetries        = null;
391          Long                                   backendTimeout    = null;
392          Long                                   maxTxnLockTimeout = null;
393          Long                                   minTxnLockTimeout = null;
394          String                                 txnName           = null;
395          TransactionSettingsCommitDurability    durability        = null;
396          TransactionSettingsBackendLockBehavior lockBehavior      = null;
397    
398          for (final ASN1Element e :
399               ASN1Sequence.decodeAsSequence(value.getValue()).elements())
400          {
401            switch (e.getType())
402            {
403              case TYPE_TXN_NAME:
404                txnName = ASN1OctetString.decodeAsOctetString(e).stringValue();
405                break;
406    
407              case TYPE_COMMIT_DURABILITY:
408                durability = TransactionSettingsCommitDurability.valueOf(
409                     ASN1Enumerated.decodeAsEnumerated(e).intValue());
410                if (durability == null)
411                {
412                  throw new LDAPException(ResultCode.DECODING_ERROR,
413                       ERR_TXN_SETTINGS_REQUEST_UNKNOWN_DURABILITY.get(
414                            ASN1Enumerated.decodeAsEnumerated(e).intValue()));
415                }
416                break;
417    
418              case TYPE_BACKEND_LOCK_BEHAVIOR:
419                lockBehavior = TransactionSettingsBackendLockBehavior.valueOf(
420                     ASN1Enumerated.decodeAsEnumerated(e).intValue());
421                if (lockBehavior == null)
422                {
423                  throw new LDAPException(ResultCode.DECODING_ERROR,
424                       ERR_TXN_SETTINGS_REQUEST_UNKNOWN_LOCK_BEHAVIOR.get(
425                            ASN1Enumerated.decodeAsEnumerated(e).intValue()));
426                }
427                break;
428    
429              case TYPE_BACKEND_LOCK_TIMEOUT:
430                backendTimeout = ASN1Long.decodeAsLong(e).longValue();
431                if (backendTimeout < 0L)
432                {
433                  throw new LDAPException(ResultCode.DECODING_ERROR,
434                       ERR_TXN_SETTINGS_REQUEST_INVALID_BACKEND_LOCK_TIMEOUT.get(
435                            backendTimeout));
436                }
437                break;
438    
439              case TYPE_RETRY_ATTEMPTS:
440                numRetries = ASN1Integer.decodeAsInteger(e).intValue();
441                if (numRetries < 0)
442                {
443                  throw new LDAPException(ResultCode.DECODING_ERROR,
444                       ERR_TXN_SETTINGS_REQUEST_INVALID_RETRY_ATTEMPTS.get(
445                            numRetries));
446                }
447                break;
448    
449              case TYPE_TXN_LOCK_TIMEOUT:
450                final ASN1Element[] timeoutElements =
451                     ASN1Sequence.decodeAsSequence(e).elements();
452                minTxnLockTimeout =
453                     ASN1Long.decodeAsLong(timeoutElements[0]).longValue();
454                maxTxnLockTimeout =
455                     ASN1Long.decodeAsLong(timeoutElements[1]).longValue();
456                if (minTxnLockTimeout < 0)
457                {
458                  throw new LDAPException(ResultCode.DECODING_ERROR,
459                       ERR_TXN_SETTINGS_REQUEST_INVALID_MIN_TXN_LOCK_TIMEOUT.get(
460                            minTxnLockTimeout));
461                }
462                if (maxTxnLockTimeout < minTxnLockTimeout)
463                {
464                  throw new LDAPException(ResultCode.DECODING_ERROR,
465                       ERR_TXN_SETTINGS_REQUEST_INVALID_MAX_TXN_LOCK_TIMEOUT.get(
466                            maxTxnLockTimeout, minTxnLockTimeout));
467                }
468                break;
469    
470              case TYPE_RETURN_RESPONSE_CONTROL:
471                responseControl = ASN1Boolean.decodeAsBoolean(e).booleanValue();
472                break;
473    
474              default:
475                throw new LDAPException(ResultCode.DECODING_ERROR,
476                     ERR_TXN_SETTINGS_REQUEST_UNRECOGNIZED_ELEMENT_TYPE.get(
477                          StaticUtils.toHex(e.getType())));
478            }
479          }
480    
481          transactionName          = txnName;
482          commitDurability         = durability;
483          backendLockBehavior      = lockBehavior;
484          backendLockTimeoutMillis = backendTimeout;
485          minTxnLockTimeoutMillis  = minTxnLockTimeout;
486          maxTxnLockTimeoutMillis  = maxTxnLockTimeout;
487          retryAttempts            = numRetries;
488          returnResponseControl    = responseControl;
489        }
490        catch (final LDAPException le)
491        {
492          Debug.debugException(le);
493          throw le;
494        }
495        catch (final Exception e)
496        {
497          Debug.debugException(e);
498          throw new LDAPException(ResultCode.DECODING_ERROR,
499               ERR_TXN_SETTINGS_REQUEST_ERROR_DECODING_VALUE.get(
500                    StaticUtils.getExceptionMessage(e)),
501               e);
502        }
503      }
504    
505    
506    
507      /**
508       * Encodes the provided information into a form suitable for use as the value
509       * of this ASN.1 element.
510       *
511       * @param  transactionName           The name to use for the transaction.  It
512       *                                   may be {@code null} if no
513       *                                   client-specified transaction name is
514       *                                   needed.  If a transaction name is
515       *                                   provided, it will be used purely for
516       *                                   informational and/or troubleshooting
517       *                                   purposes.
518       * @param  commitDurability          The durability level that should be used
519       *                                   when committing the associated
520       *                                   transaction.  It may be {@code null} if
521       *                                   the server-default durability level
522       *                                   should be used.
523       * @param  backendLockBehavior       The behavior that should be used with
524       *                                   regard to acquiring an exclusive lock for
525       *                                   processing in the target backend.  It may
526       *                                   be {@code null} if the server-default
527       *                                   backend lock behavior should be used.
528       * @param  backendLockTimeoutMillis  The maximum length of time in
529       *                                   milliseconds to spend attempting to
530       *                                   acquire an exclusive backend lock if it
531       *                                   is needed during any part of the
532       *                                   processing.  A value that of zero
533       *                                   indicates that no timeout should be
534       *                                   enforced.  It may be {@code null} if the
535       *                                   server will determine the backend lock
536       *                                   timeout that should be used.
537       * @param  retryAttempts             The number of times to retry the
538       *                                   associated operations in a new
539       *                                   transaction if the initial attempt fails.
540       *                                   If this is {@code null}, then the server
541       *                                   will determine the number of retry
542       *                                   attempts to make.  Note that depending on
543       *                                   the backend lock behavior, the server may
544       *                                   make one additional retry attempt if
545       *                                   necessary after acquiring an exclusive
546       *                                   backend lock.
547       * @param  minTxnLockTimeoutMillis   The minimum database lock timeout that
548       *                                   should be used for the associated
549       *                                   transaction.  If this is specified, then
550       *                                   the first attempt will use this lock
551       *                                   timeout, and subsequent attempts will use
552       *                                   a timeout value between this and the
553       *                                   maximum database lock timeout (which must
554       *                                   also be specified).  If this is
555       *                                   {@code null}, then the server will
556       *                                   determine the database lock timeout
557       *                                   settings to use.
558       * @param  maxTxnLockTimeoutMillis   The maximum database lock timeout that
559       *                                   should be used for the associated
560       *                                   transaction.  If this is specified, then
561       *                                   the minimum database lock timeout must
562       *                                   also be specified, and this value must be
563       *                                   greater than or equal to the minimum lock
564       *                                   timeout.  If this is {@code null}, then
565       *                                   the server will determine the database
566       *                                   lock timeout settings to use.
567       * @param  returnResponseControl     Indicates whether to return a response
568       *                                   control with transaction-related
569       *                                   information collected over the course of
570       *                                   processing the associated operation.
571       *
572       * @return  The encoded value to use for the control.
573       */
574      private static ASN1OctetString encodeValue(
575                   final String transactionName,
576                   final TransactionSettingsCommitDurability commitDurability,
577                   final TransactionSettingsBackendLockBehavior backendLockBehavior,
578                   final Long backendLockTimeoutMillis, final Integer retryAttempts,
579                   final Long minTxnLockTimeoutMillis,
580                   final Long maxTxnLockTimeoutMillis,
581                   final boolean returnResponseControl)
582      {
583        final ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(7);
584    
585        if (transactionName != null)
586        {
587          elements.add(new ASN1OctetString(TYPE_TXN_NAME, transactionName));
588        }
589    
590        if (commitDurability != null)
591        {
592          elements.add(new ASN1Enumerated(TYPE_COMMIT_DURABILITY,
593               commitDurability.intValue()));
594        }
595    
596        if (backendLockBehavior != null)
597        {
598          elements.add(new ASN1Enumerated(TYPE_BACKEND_LOCK_BEHAVIOR,
599               backendLockBehavior.intValue()));
600        }
601    
602        if (backendLockTimeoutMillis != null)
603        {
604          Validator.ensureTrue((backendLockTimeoutMillis >= 0L),
605               "If a backend lock timeout is specified, then it must be greater " +
606                    "than or equal to zero.");
607          elements.add(new ASN1Long(TYPE_BACKEND_LOCK_TIMEOUT,
608               backendLockTimeoutMillis));
609        }
610    
611        if (retryAttempts != null)
612        {
613          Validator.ensureTrue((retryAttempts >= 0),
614               "If specified, the number of retry attempts must be greater than " +
615                    "or equal to zero.");
616    
617          elements.add(new ASN1Integer(TYPE_RETRY_ATTEMPTS, retryAttempts));
618        }
619    
620        if (minTxnLockTimeoutMillis != null)
621        {
622          Validator.ensureTrue((maxTxnLockTimeoutMillis != null),
623               "If a minimum transaction lock timeout is specified, then a " +
624                    "maximum transaction lock timeout must also be specified.");
625          Validator.ensureTrue((minTxnLockTimeoutMillis > 0),
626               "If a minimum transaction lock timeout is specified, then it must " +
627                    "be greater than zero.");
628          Validator.ensureTrue((maxTxnLockTimeoutMillis >= minTxnLockTimeoutMillis),
629               "If a minimum transaction lock timeout is specified, then it must " +
630                    "be less than or equal to the minimum transaction lock " +
631                    "timeout.");
632          elements.add(new ASN1Sequence(TYPE_TXN_LOCK_TIMEOUT,
633               new ASN1Long(minTxnLockTimeoutMillis),
634               new ASN1Long(maxTxnLockTimeoutMillis)));
635        }
636        else
637        {
638          Validator.ensureTrue((maxTxnLockTimeoutMillis == null),
639               "If a maximum transaction lock timeout is specified, then a " +
640                    "minimum transaction lock timeout must also be specified.");
641        }
642    
643        if (returnResponseControl)
644        {
645          elements.add(new ASN1Boolean(TYPE_RETURN_RESPONSE_CONTROL, true));
646        }
647    
648        return new ASN1OctetString(new ASN1Sequence(elements).encode());
649      }
650    
651    
652    
653      /**
654       * Retrieves the name to assign to the associated transaction, if specified.
655       *
656       * @return  The name to assign to the associated transaction, or {@code null}
657       *          if none has been specified.
658       */
659      public String getTransactionName()
660      {
661        return transactionName;
662      }
663    
664    
665    
666      /**
667       * Retrieves the commit durability that should be used for the associated
668       * transaction, if specified.
669       *
670       * @return  The commit durability that should be used for the associated
671       *          transaction, or {@code null} if none has been specified and the
672       *          server should determine the commit durability.
673       */
674      public TransactionSettingsCommitDurability getCommitDurability()
675      {
676        return commitDurability;
677      }
678    
679    
680    
681      /**
682       * Retrieves the backend lock behavior that should be used for the associated
683       * transaction, if specified.
684       *
685       * @return  The backend lock behavior that should be used for the associated
686       *          transaction, or {@code null} if none has been specified and the
687       *          server should determine the backend lock behavior.
688       */
689      public TransactionSettingsBackendLockBehavior getBackendLockBehavior()
690      {
691        return backendLockBehavior;
692      }
693    
694    
695    
696      /**
697       * Retrieves the backend lock timeout (in milliseconds) that should be used
698       * for the associated transaction, if specified.
699       *
700       * @return  The backend lock timeout (in milliseconds) that should be used for
701       *          the associated transaction, or {@code null} if none has been
702       *          specified and the server should determine the backend lock
703       *          timeout.
704       */
705      public Long getBackendLockTimeoutMillis()
706      {
707        return backendLockTimeoutMillis;
708      }
709    
710    
711    
712      /**
713       * Retrieves the maximum number of times that the transaction may be retried
714       * if the initial attempt fails due to a lock conflict, if specified.
715       *
716       * @return  The maximum number of times that the transaction may be retried if
717       *          the initial attempt fails due to a lock conflict, or {@code null}
718       *          if none has been specified and the server should determine the
719       *          number of retry attempts.
720       */
721      public Integer getRetryAttempts()
722      {
723        return retryAttempts;
724      }
725    
726    
727    
728      /**
729       * Retrieves the minimum transaction lock timeout (in milliseconds) that
730       * should be used for the associated transaction, if specified.  This is the
731       * timeout value that will be used for the first attempt.  Any subsequent
732       * attempts will have a lock timeout that is between the minimum and maximum
733       * timeout value.
734       *
735       * @return  The minimum lock timeout (in milliseconds) that should
736       *          be used for the associated transaction, or {@code null} if none
737       *          has been specified and the server should determine the minimum
738       *          transaction lock timeout.
739       */
740      public Long getMinTxnLockTimeoutMillis()
741      {
742        return minTxnLockTimeoutMillis;
743      }
744    
745    
746    
747      /**
748       * Retrieves the maximum transaction lock timeout (in milliseconds) that
749       * should be used for the associated transaction, if specified.  The timeout
750       * to be used for any retries will be between the minimum and maximum lock
751       * timeout values.
752       *
753       * @return  The maximum lock timeout (in milliseconds) that should
754       *          be used for the associated transaction, or {@code null} if none
755       *          has been specified and the server should determine the maximum
756       *          transaction lock timeout.
757       */
758      public Long getMaxTxnLockTimeoutMillis()
759      {
760        return maxTxnLockTimeoutMillis;
761      }
762    
763    
764    
765      /**
766       * Indicates whether to return a response control with transaction-related
767       * information collected over the course of processing the associated
768       * operation.
769       *
770       * @return  {@code true} if the server should return a response control with
771       *          transaction-related information, or {@code false} if not.
772       */
773      public boolean returnResponseControl()
774      {
775        return returnResponseControl;
776      }
777    
778    
779    
780      /**
781       * {@inheritDoc}
782       */
783      @Override()
784      public String getControlName()
785      {
786        return INFO_CONTROL_NAME_TXN_SETTINGS_REQUEST.get();
787      }
788    
789    
790    
791      /**
792       * {@inheritDoc}
793       */
794      @Override()
795      public void toString(final StringBuilder buffer)
796      {
797        buffer.append("TransactionSettingsRequestControl(isCritical=");
798        buffer.append(isCritical());
799    
800        if (transactionName != null)
801        {
802          buffer.append(", transactionName='");
803          buffer.append(transactionName);
804          buffer.append('\'');
805        }
806    
807        if (commitDurability != null)
808        {
809          buffer.append(", commitDurability='");
810          buffer.append(commitDurability.name());
811          buffer.append('\'');
812        }
813    
814        if (backendLockBehavior != null)
815        {
816          buffer.append(", backendLockBehavior='");
817          buffer.append(backendLockBehavior.name());
818          buffer.append('\'');
819        }
820    
821        if (backendLockTimeoutMillis != null)
822        {
823          buffer.append(", backendLockTimeoutMillis=");
824          buffer.append(backendLockTimeoutMillis);
825        }
826    
827        if (retryAttempts != null)
828        {
829          buffer.append(", retryAttempts=");
830          buffer.append(retryAttempts);
831        }
832    
833        if (minTxnLockTimeoutMillis != null)
834        {
835          buffer.append(", minTxnLockTimeoutMillis=");
836          buffer.append(minTxnLockTimeoutMillis);
837        }
838    
839        if (maxTxnLockTimeoutMillis != null)
840        {
841          buffer.append(", maxTxnLockTimeoutMillis=");
842          buffer.append(maxTxnLockTimeoutMillis);
843        }
844    
845        buffer.append(", returnResponseControl=");
846        buffer.append(returnResponseControl);
847    
848        buffer.append(')');
849      }
850    }