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