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