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