1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2002, 2014 Oracle and/or its affiliates.  All rights reserved.
5  *
6  */
7 
8 package com.sleepycat.je;
9 
10 import com.sleepycat.je.dbi.EnvironmentImpl;
11 
12 /**
13  * Specifies the attributes of a database environment transaction.
14  */
15 public class TransactionConfig implements Cloneable {
16 
17     /**
18      * Default configuration used if null is passed to methods that create a
19      * transaction.
20      */
21     public static final TransactionConfig DEFAULT = new TransactionConfig();
22 
23     private boolean sync = false;
24     private boolean noSync = false;
25     private boolean writeNoSync = false;
26     private Durability durability = null;
27     private ReplicaConsistencyPolicy consistencyPolicy;
28     private boolean noWait = false;
29     private boolean readUncommitted = false;
30     private boolean readCommitted = false;
31     private boolean serializableIsolation = false;
32     private boolean readOnly = false;
33     private boolean localWrite = false;
34 
35     /**
36      * An instance created using the default constructor is initialized with
37      * the system's default settings.
38      */
TransactionConfig()39     public TransactionConfig() {
40     }
41 
42     /**
43      * @hidden
44      * For internal use only.
45      *
46      * Maps the existing sync settings to the equivalent durability settings.
47      * Figure out what we should do on commit. TransactionConfig could be
48      * set with conflicting values; take the most stringent ones first.
49      * All environment level defaults were applied by the caller.
50      *
51      * ConfigSync  ConfigWriteNoSync ConfigNoSync   default
52      *    0                 0             0         sync
53      *    0                 0             1         nosync
54      *    0                 1             0         write nosync
55      *    0                 1             1         write nosync
56      *    1                 0             0         sync
57      *    1                 0             1         sync
58      *    1                 1             0         sync
59      *    1                 1             1         sync
60      *
61      * @return the equivalent durability
62      */
getDurabilityFromSync(final EnvironmentImpl envImpl)63     public Durability getDurabilityFromSync(final EnvironmentImpl envImpl) {
64         if (sync) {
65             return Durability.COMMIT_SYNC;
66         } else if (writeNoSync) {
67             return Durability.COMMIT_WRITE_NO_SYNC;
68         } else if (noSync) {
69             return Durability.COMMIT_NO_SYNC;
70         }
71 
72         /*
73          * Replicated environments default to commitNoSync, while standalone
74          * default to commitSync.
75          */
76         if (envImpl.isReplicated()) {
77             return Durability.COMMIT_NO_SYNC;
78         } else {
79             return Durability.COMMIT_SYNC;
80         }
81     }
82 
83     /**
84      * Configures the transaction to write and synchronously flush the log it
85      * when commits.
86      *
87      * <p>This behavior may be set for a database environment using the
88      * Environment.setMutableConfig method. Any value specified to this method
89      * overrides that setting.</p>
90      *
91      * <p>The default is false for this class and true for the database
92      * environment.</p>
93      *
94      * <p>If true is passed to both setSync and setNoSync, setSync will take
95      * precedence.</p>
96      *
97      * @param sync If true, transactions exhibit all the ACID (atomicity,
98      * consistency, isolation, and durability) properties.
99      *
100      * @return this
101      */
setSync(final boolean sync)102     public TransactionConfig setSync(final boolean sync) {
103         setSyncVoid(sync);
104         return this;
105     }
106 
107     /**
108      * @hidden
109      * The void return setter for use by Bean editors.
110      */
setSyncVoid(final boolean sync)111     public void setSyncVoid(final boolean sync) {
112         checkMixedMode(sync, noSync, writeNoSync, durability);
113         this.sync = sync;
114     }
115 
116     /**
117      * Returns true if the transaction is configured to write and synchronously
118      * flush the log it when commits.
119      *
120      * @return true if the transaction is configured to write and synchronously
121      * flush the log it when commits.
122      */
getSync()123     public boolean getSync() {
124         return sync;
125     }
126 
127     /**
128      * Configures the transaction to not write or synchronously flush the log
129      * it when commits.
130      *
131      * <p>This behavior may be set for a database environment using the
132      * Environment.setMutableConfig method. Any value specified to this method
133      * overrides that setting.</p>
134      *
135      * <p>The default is false for this class and the database environment.</p>
136      *
137      * @param noSync If true, transactions exhibit the ACI (atomicity,
138      * consistency, and isolation) properties, but not D (durability); that is,
139      * database integrity will be maintained, but if the application or system
140      * fails, it is possible some number of the most recently committed
141      * transactions may be undone during recovery. The number of transactions
142      * at risk is governed by how many log updates can fit into the log buffer,
143      * how often the operating system flushes dirty buffers to disk, and how
144      * often the log is checkpointed.
145      *
146      * @deprecated replaced by {@link #setDurability}
147      *
148      * @return this
149      */
setNoSync(final boolean noSync)150     public TransactionConfig setNoSync(final boolean noSync) {
151         setNoSyncVoid(noSync);
152         return this;
153     }
154 
155     /**
156      * @hidden
157      * The void return setter for use by Bean editors.
158      */
setNoSyncVoid(final boolean noSync)159     public void setNoSyncVoid(final boolean noSync) {
160         checkMixedMode(sync, noSync, writeNoSync, durability);
161         this.noSync = noSync;
162     }
163 
164     /**
165      * Returns true if the transaction is configured to not write or
166      * synchronously flush the log it when commits.
167      *
168      * @return true if the transaction is configured to not write or
169      * synchronously flush the log it when commits.
170      *
171      * @deprecated replaced by {@link #getDurability}
172      */
getNoSync()173     public boolean getNoSync() {
174         return noSync;
175     }
176 
177     /**
178      * Configures the transaction to write but not synchronously flush the log
179      * it when commits.
180      *
181      * <p>This behavior may be set for a database environment using the
182      * Environment.setMutableConfig method. Any value specified to this method
183      * overrides that setting.</p>
184      *
185      * <p>The default is false for this class and the database environment.</p>
186      *
187      * @param writeNoSync If true, transactions exhibit the ACI (atomicity,
188      * consistency, and isolation) properties, but not D (durability); that is,
189      * database integrity will be maintained, but if the operating system
190      * fails, it is possible some number of the most recently committed
191      * transactions may be undone during recovery. The number of transactions
192      * at risk is governed by how often the operating system flushes dirty
193      * buffers to disk, and how often the log is checkpointed.
194      *
195      * @deprecated replaced by {@link #setDurability}
196      *
197      * @return this
198      */
setWriteNoSync(final boolean writeNoSync)199     public TransactionConfig setWriteNoSync(final boolean writeNoSync) {
200         setWriteNoSyncVoid(writeNoSync);
201         return this;
202     }
203 
204     /**
205      * @hidden
206      * The void return setter for use by Bean editors.
207      */
setWriteNoSyncVoid(final boolean writeNoSync)208     public void setWriteNoSyncVoid(final boolean writeNoSync) {
209         checkMixedMode(sync, noSync, writeNoSync, durability);
210         this.writeNoSync = writeNoSync;
211     }
212 
213     /**
214      * Returns true if the transaction is configured to write but not
215      * synchronously flush the log it when commits.
216      *
217      * @return true if the transaction is configured to not write or
218      * synchronously flush the log it when commits.
219      *
220      * @deprecated replaced by {@link #getDurability}
221      */
getWriteNoSync()222     public boolean getWriteNoSync() {
223         return writeNoSync;
224     }
225 
226     /**
227      * Configures the durability associated with a transaction when it commits.
228      * Changes to durability are not reflected back to the "sync" booleans --
229      * there isn't a one to one mapping.
230      *
231      * Note that you should not use both the durability and the XXXSync() apis
232      * on the same config object.
233      *
234      * @param durability the durability definition
235      *
236      * @return this
237      */
setDurability(final Durability durability)238     public TransactionConfig setDurability(final Durability durability) {
239         setDurabilityVoid(durability);
240         return this;
241     }
242 
243     /**
244      * @hidden
245      * The void return setter for use by Bean editors.
246      */
setDurabilityVoid(final Durability durability)247     public void setDurabilityVoid(final Durability durability) {
248         checkMixedMode(sync, noSync, writeNoSync, durability);
249         this.durability = durability;
250     }
251 
252     /**
253      * Returns the durability associated with the configuration.
254      *
255      * If {@link #setDurability} has not been called, this method returns null.
256      * When no durability settings have been specified using the
257      * {@code TransactionConfig}, the default durability is applied to the
258      * {@link Transaction} by {@link Environment#beginTransaction} using
259      * {@link EnvironmentConfig} settings.
260      *
261      * @return the durability setting currently associated with this config.
262      */
getDurability()263     public Durability getDurability() {
264         return durability;
265     }
266 
267     /**
268      * Used internally to configure Durability, modifying the existing
269      * Durability or explicit sync configuration.  This method is used to avoid
270      * a mixed mode exception, since the existing config may be in either mode.
271      */
overrideDurability(final Durability durability)272     void overrideDurability(final Durability durability) {
273         sync = false;
274         noSync = false;
275         writeNoSync = false;
276         this.durability = durability;
277     }
278 
279     /**
280      * Associates a consistency policy with this configuration.
281      *
282      * @param consistencyPolicy the consistency definition
283      *
284      * @return this
285      */
setConsistencyPolicy( final ReplicaConsistencyPolicy consistencyPolicy)286     public TransactionConfig setConsistencyPolicy(
287         final ReplicaConsistencyPolicy consistencyPolicy) {
288 
289         setConsistencyPolicyVoid(consistencyPolicy);
290         return this;
291     }
292 
293     /**
294      * @hidden
295      * The void return setter for use by Bean editors.
296      */
setConsistencyPolicyVoid( final ReplicaConsistencyPolicy consistencyPolicy)297     public void setConsistencyPolicyVoid(
298         final ReplicaConsistencyPolicy consistencyPolicy) {
299 
300         this.consistencyPolicy = consistencyPolicy;
301     }
302     /**
303      * Returns the consistency policy associated with the configuration.
304      *
305      * @return the consistency policy currently associated with this config.
306      */
getConsistencyPolicy()307     public ReplicaConsistencyPolicy getConsistencyPolicy() {
308         return consistencyPolicy;
309     }
310 
311     /**
312      * Configures the transaction to not wait if a lock request cannot be
313      * immediately granted.
314      *
315      * <p>The default is false for this class and the database environment.</p>
316      *
317      * @param noWait If true, transactions will not wait if a lock request
318      * cannot be immediately granted, instead {@link
319      * com.sleepycat.je.LockNotAvailableException LockNotAvailableException}
320      * will be thrown.
321      *
322      * @return this
323      */
setNoWait(final boolean noWait)324     public TransactionConfig setNoWait(final boolean noWait) {
325         setNoWaitVoid(noWait);
326         return this;
327     }
328 
329     /**
330      * @hidden
331      * The void return setter for use by Bean editors.
332      */
setNoWaitVoid(final boolean noWait)333     public void setNoWaitVoid(final boolean noWait) {
334         this.noWait = noWait;
335     }
336 
337     /**
338      * Returns true if the transaction is configured to not wait if a lock
339      * request cannot be immediately granted.
340      *
341      * @return true if the transaction is configured to not wait if a lock
342      * request cannot be immediately granted.
343      */
getNoWait()344     public boolean getNoWait() {
345         return noWait;
346     }
347 
348     /**
349      * Configures read operations performed by the transaction to return
350      * modified but not yet committed data.
351      *
352      * @param readUncommitted If true, configure read operations performed by
353      * the transaction to return modified but not yet committed data.
354      *
355      * @see LockMode#READ_UNCOMMITTED
356      *
357      * @return this
358      */
setReadUncommitted( final boolean readUncommitted)359     public TransactionConfig setReadUncommitted(
360         final boolean readUncommitted) {
361 
362         setReadUncommittedVoid(readUncommitted);
363         return this;
364     }
365 
366     /**
367      * @hidden
368      * The void return setter for use by Bean editors.
369      */
setReadUncommittedVoid(final boolean readUncommitted)370     public void setReadUncommittedVoid(final boolean readUncommitted) {
371         this.readUncommitted = readUncommitted;
372     }
373 
374     /**
375      * Returns true if read operations performed by the transaction are
376      * configured to return modified but not yet committed data.
377      *
378      * @return true if read operations performed by the transaction are
379      * configured to return modified but not yet committed data.
380      *
381      * @see LockMode#READ_UNCOMMITTED
382      */
getReadUncommitted()383     public boolean getReadUncommitted() {
384         return readUncommitted;
385     }
386 
387     /**
388      * Configures the transaction for read committed isolation.
389      *
390      * <p>This ensures the stability of the current data item read by the
391      * cursor but permits data read by this transaction to be modified or
392      * deleted prior to the commit of the transaction.</p>
393      *
394      * @param readCommitted If true, configure the transaction for read
395      * committed isolation.
396      *
397      * @see LockMode#READ_COMMITTED
398      *
399      * @return this
400      */
setReadCommitted(final boolean readCommitted)401     public TransactionConfig setReadCommitted(final boolean readCommitted) {
402         setReadCommittedVoid(readCommitted);
403         return this;
404     }
405 
406     /**
407      * @hidden
408      * The void return setter for use by Bean editors.
409      */
setReadCommittedVoid(final boolean readCommitted)410     public void setReadCommittedVoid(final boolean readCommitted) {
411         this.readCommitted = readCommitted;
412     }
413 
414     /**
415      * Returns true if the transaction is configured for read committed
416      * isolation.
417      *
418      * @return true if the transaction is configured for read committed
419      * isolation.
420      *
421      * @see LockMode#READ_COMMITTED
422      */
getReadCommitted()423     public boolean getReadCommitted() {
424         return readCommitted;
425     }
426 
427     /**
428      * Configures this transaction to have serializable (degree 3) isolation.
429      * By setting serializable isolation, phantoms will be prevented.
430      *
431      * <p>By default a transaction provides Repeatable Read isolation; {@link
432      * EnvironmentConfig#setTxnSerializableIsolation} may be called to override
433      * the default.  If the environment is configured for serializable
434      * isolation, all transactions will be serializable regardless of whether
435      * this method is called; calling {@link #setSerializableIsolation} with a
436      * false parameter will not disable serializable isolation.</p>
437      *
438      * The default is false for this class and the database environment.
439      *
440      * @see LockMode
441      *
442      * @return this
443      */
setSerializableIsolation( final boolean serializableIsolation)444     public TransactionConfig setSerializableIsolation(
445         final boolean serializableIsolation) {
446 
447         setSerializableIsolationVoid(serializableIsolation);
448         return this;
449     }
450 
451     /**
452      * @hidden
453      * The void return setter for use by Bean editors.
454      */
setSerializableIsolationVoid( final boolean serializableIsolation)455     public void setSerializableIsolationVoid(
456         final boolean serializableIsolation) {
457 
458         this.serializableIsolation = serializableIsolation;
459     }
460 
461     /**
462      * Returns true if the transaction has been explicitly configured to have
463      * serializable (degree 3) isolation.
464      *
465      * @return true if the transaction has been configured to have serializable
466      * isolation.
467      *
468      * @see LockMode
469      */
getSerializableIsolation()470     public boolean getSerializableIsolation() {
471         return serializableIsolation;
472     }
473 
474     /**
475      * Configures this transaction to disallow write operations, regardless of
476      * whether writes are allowed for the {@link Environment} or the
477      * {@link Database}s that are accessed.
478      *
479      * <p>If a write operation is attempted using a read-only transaction,
480      * an {@code UnsupportedOperationException} will be thrown.</p>
481      *
482      * <p>For a read-only transaction, the transaction's {@code Durability} is
483      * ignored, even when it is explicitly specified using {@link
484      * #setDurability(Durability)}.</p>
485      *
486      * <p>In a {@link com.sleepycat.je.rep.ReplicatedEnvironment}, a read-only
487      * transaction implicitly uses
488      * {@link com.sleepycat.je.Durability.ReplicaAckPolicy#NONE}.
489      * A read-only transaction on a Master will thus not be held up, or
490      * throw {@link com.sleepycat.je.rep.InsufficientReplicasException}, if the
491      * Master is not in contact with a sufficient number of Replicas at the
492      * time the transaction is initiated.</p>
493      *
494      * <p>The default setting is false (writes are allowed).</p>
495      *
496      * @return this
497      */
setReadOnly(final boolean readOnly)498     public TransactionConfig setReadOnly(final boolean readOnly) {
499         setReadOnlyVoid(readOnly);
500         return this;
501     }
502 
503     /**
504      * @hidden
505      * The void return setter for use by Bean editors.
506      */
setReadOnlyVoid(final boolean readOnly)507     public void setReadOnlyVoid(final boolean readOnly) {
508         if (localWrite && readOnly) {
509             throw new IllegalArgumentException(
510                 "localWrite and readOnly may not both be true");
511         }
512         this.readOnly = readOnly;
513     }
514 
515     /**
516      * Returns whether read-only is configured for this transaction.
517      */
getReadOnly()518     public boolean getReadOnly() {
519         return readOnly;
520     }
521 
522     /**
523      * Configures this transaction to allow writing to non-replicated
524      * {@link Database}s in a
525      * {@link com.sleepycat.je.rep.ReplicatedEnvironment}.
526      *
527      * <p>In a replicated environment, a given transaction may be used to
528      * write to either replicated databases or non-replicated databases, but
529      * not both. If a write operation to a replicated database is attempted
530      * when local-write is true, or to a non-replicated database when
531      * local-write is false, an {@code UnsupportedOperationException} will be
532      * thrown.</p>
533      *
534      * <p>Note that for auto-commit transactions (when the {@code Transaction}
535      * parameter is null), the local-write setting is automatically set to
536      * correspond to whether the database is replicated. With auto-commit,
537      * local-write is always true for a non-replicated database, and
538      * always false for a replicated database.</p>
539      *
540      * <p>In a replicated environment, a local-write transaction implicitly
541      * uses {@link com.sleepycat.je.Durability.ReplicaAckPolicy#NONE}.
542      * A local-write transaction on a Master will thus not be held up, or
543      * throw {@link com.sleepycat.je.rep.InsufficientReplicasException}, if the
544      * Master is not in contact with a sufficient number of Replicas at the
545      * time the transaction is initiated.</p>
546      *
547      * <p>By default the local-write setting is false, meaning that the
548      * transaction may only write to replicated Databases in a replicated
549      * environment.</p>
550      *
551      * <p>This configuration setting is ignored in a non-replicated Environment
552      * since no databases are replicated.</p>
553      *
554      * @return this
555      *
556      * @see <a href="rep/ReplicatedEnvironment.html#nonRepDbs>Non-replicated
557      * Databases in a Replicated Environment</a>
558      */
setLocalWrite(final boolean localWrite)559     public TransactionConfig setLocalWrite(final boolean localWrite) {
560         setLocalWriteVoid(localWrite);
561         return this;
562     }
563 
564     /**
565      * @hidden
566      * The void return setter for use by Bean editors.
567      */
setLocalWriteVoid(final boolean localWrite)568     public void setLocalWriteVoid(final boolean localWrite) {
569         if (localWrite && readOnly) {
570             throw new IllegalArgumentException(
571                 "localWrite and readOnly may not both be true");
572         }
573         this.localWrite = localWrite;
574     }
575 
576     /**
577      * Returns whether local-write is configured for this transaction.
578      */
getLocalWrite()579     public boolean getLocalWrite() {
580         return localWrite;
581     }
582 
583     /**
584      * Returns a copy of this configuration object.
585      */
586     @Override
clone()587     public TransactionConfig clone() {
588         try {
589             return (TransactionConfig) super.clone();
590         } catch (CloneNotSupportedException willNeverOccur) {
591             return null;
592         }
593     }
594 
595     /**
596      *
597      * Checks to catch mixing of deprecated and non-deprecated forms of the
598      * API. It's invoked before setting any of the config parameters. The
599      * arguments represent the new state of the durability configuration,
600      * before it has been changed.
601      *
602      * @throws IllegalArgumentException via TransactionConfig and
603      * EnvironmentMutableConfig setters
604      */
checkMixedMode(final boolean sync, final boolean noSync, final boolean writeNoSync, final Durability durability)605     static void checkMixedMode(final boolean sync,
606                                final boolean noSync,
607                                final boolean writeNoSync,
608                                final Durability durability)
609         throws IllegalArgumentException {
610 
611         if ((sync || noSync || writeNoSync) && (durability != null)) {
612             throw new IllegalArgumentException
613                 ("Mixed use of deprecated and current durability APIs is " +
614                  "not supported");
615         }
616 
617         if ((sync && noSync) ||
618             (sync && writeNoSync) ||
619             (noSync && writeNoSync)) {
620             throw new IllegalArgumentException
621                 ("Only one of TxnSync, TxnNoSync, and TxnWriteNoSync " +
622                  "can be set.");
623         }
624     }
625 
626     /**
627      * Returns the values for each configuration attribute.
628      *
629      * @return the values for each configuration attribute.
630      */
631     @Override
toString()632     public String toString() {
633         return "sync=" + sync +
634             "\nnoSync=" + noSync +
635             "\nwriteNoSync=" + writeNoSync +
636             "\ndurability=" + durability +
637             "\nconsistencyPolicy=" + consistencyPolicy +
638             "\nnoWait=" + noWait +
639             "\nreadUncommitted=" + readUncommitted +
640             "\nreadCommitted=" + readCommitted +
641             "\nSerializableIsolation=" + serializableIsolation +
642             "\n";
643     }
644 }
645