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 java.util.Arrays;
11 import java.util.Comparator;
12 import java.util.HashSet;
13 import java.util.LinkedList;
14 import java.util.List;
15 import java.util.Set;
16 
17 import com.sleepycat.je.dbi.DatabaseImpl;
18 import com.sleepycat.je.trigger.ReplicatedDatabaseTrigger;
19 import com.sleepycat.je.trigger.PersistentTrigger;
20 import com.sleepycat.je.trigger.Trigger;
21 
22 /**
23  * <p>Specifies the attributes of a database.</p>
24  *
25  * <p>There are two groups of database attributes: per-database handle
26  * attributes, and database-wide attributes. An attribute may be
27  * persistent/transient or mutable/immutable:</p>
28  *
29  * <table border="true">
30  * <tr>
31  *     <td>Scope</td>
32  *     <td>Mutable</td>
33  *     <td>Persistent</td>
34  *     <td>Attribute</td>
35  * </tr>
36  * <tr>
37  *     <td rowspan="4">Database-wide attribute</td>
38  *     <td>True</td>
39  *     <td>True</td>
40  *     <td>{@link DatabaseConfig#getBtreeComparator() btree comparator}<br>
41  *         {@link DatabaseConfig#getDuplicateComparator() duplicate comparator}<br>
42  *         {@link DatabaseConfig#getKeyPrefixing() key prefixing}<br>
43  *         {@link DatabaseConfig#getNodeMaxEntries() nodeMaxEntries}<br>
44  *         <!--
45  *         {@link DatabaseConfig#getTriggers() triggers}<br></td>
46  *         -->
47  * </tr>
48  * <tr>
49  *     <td>True</td>
50  *     <td>False</td>
51  *     <td>{@link DatabaseConfig#getDeferredWrite() deferred write}<br>
52  *         {@link DatabaseConfig#getTransactional() transactional}<br></td>
53  * </tr>
54  * <tr>
55  *     <td>False</td>
56  *     <td>True</td>
57  *     <td>
58  *         {@link DatabaseConfig#getSortedDuplicates() sorted duplicates}<br>
59  *     </td>
60  * </tr>
61  * <tr>
62  *     <td>False</td>
63  *     <td>False</td>
64  *     <td>{@link DatabaseConfig#getTemporary() temporary}</td>
65  * </tr>
66  * <tr>
67  *     <td>Per-database handle attributes</td>
68  *     <td>False</td>
69  *     <td>False</td>
70  *     <td>{@link DatabaseConfig#getAllowCreate() allow create}<br>
71  *         {@link DatabaseConfig#getExclusiveCreate() exclusive create}<br>
72  *         {@link DatabaseConfig#getReadOnly() read only}<br>
73  *         {@link DatabaseConfig#getUseExistingConfig() use existing config}<br>
74  *     </td>
75  * </tr>
76  * </table>
77  * </p>
78  *
79  * <p>Persistent attributes will be saved in the log and remain in effect
80  * every time the environment is reopened. Transient attributes only remain
81  * in effect until:</p>
82  *
83  * <ul>
84  * <li>the database configuration is updated</li>
85  * <li>the database handle(per-database handle attributes) is closed, or all
86  * handles for this database (database-wide attributes) are closed.</li>
87  * </ul>
88  */
89 public class DatabaseConfig implements Cloneable {
90 
91     /**
92      * An instance created using the default constructor is initialized with
93      * the system's default settings.
94      */
95     public static final DatabaseConfig DEFAULT = new DatabaseConfig();
96 
97     private boolean allowCreate = false;
98     private boolean exclusiveCreate = false;
99     private boolean transactional = false;
100     private boolean readOnly = false;
101     private boolean sortedDuplicates = false;
102     private boolean deferredWrite = false;
103     private boolean temporary = false;
104     private boolean keyPrefixing = false;
105     private boolean replicated = true;
106 
107     private int nodeMaxEntries;
108     private Comparator<byte[]> btreeComparator = null;
109     private Comparator<byte[]> duplicateComparator = null;
110     private boolean btreeComparatorByClassName = false;
111     private boolean duplicateComparatorByClassName = false;
112     private boolean overrideBtreeComparator = false;
113     private boolean overrideDuplicateComparator = false;
114     private boolean useExistingConfig = false;
115     private CacheMode cacheMode = null;
116     private CacheModeStrategy cacheModeStrategy = null;
117     private SecondaryAssociation secAssociation = null;
118 
119     /* User defined triggers associated with this database. */
120     private List<Trigger> triggers = new LinkedList<Trigger>();
121     private boolean overrideTriggers;
122 
123     /**
124      * An instance created using the default constructor is initialized with
125      * the system's default settings.
126      */
DatabaseConfig()127     public DatabaseConfig() {
128     }
129 
130     /**
131      * Configures the {@link com.sleepycat.je.Environment#openDatabase
132      * Environment.openDatabase} method to create the database if it does not
133      * already exist.
134      *
135      * @param allowCreate If true, configure the {@link
136      * com.sleepycat.je.Environment#openDatabase Environment.openDatabase}
137      * method to create the database if it does not already exist.
138      *
139      * @return this
140      */
setAllowCreate(boolean allowCreate)141     public DatabaseConfig setAllowCreate(boolean allowCreate) {
142         setAllowCreateVoid(allowCreate);
143         return this;
144     }
145 
146     /**
147      * @hidden
148      * The void return setter for use by Bean editors.
149      */
setAllowCreateVoid(boolean allowCreate)150     public void setAllowCreateVoid(boolean allowCreate) {
151         this.allowCreate = allowCreate;
152     }
153 
154     /**
155      * Returns true if the {@link com.sleepycat.je.Environment#openDatabase
156      * Environment.openDatabase} method is configured to create the database
157      * if it does not already exist.
158      *
159      * <p>This method may be called at any time during the life of the
160      * application.</p>
161      *
162      * @return true if the {@link com.sleepycat.je.Environment#openDatabase
163      * Environment.openDatabase} method is configured to create the database
164      * if it does not already exist.
165      */
getAllowCreate()166     public boolean getAllowCreate() {
167         return allowCreate;
168     }
169 
170     /**
171      * Configure the {@link com.sleepycat.je.Environment#openDatabase
172      * Environment.openDatabase} method to fail if the database already exists.
173      *
174      * <p>The exclusiveCreate mode is only meaningful if specified with the
175      * allowCreate mode.</p>
176      *
177      * @param exclusiveCreate If true, configure the {@link
178      * com.sleepycat.je.Environment#openDatabase Environment.openDatabase}
179      * method to fail if the database already exists.
180      *
181      * @return this
182      */
setExclusiveCreate(boolean exclusiveCreate)183     public DatabaseConfig setExclusiveCreate(boolean exclusiveCreate) {
184         setExclusiveCreateVoid(exclusiveCreate);
185         return this;
186     }
187 
188     /**
189      * @hidden
190      * The void return setter for use by Bean editors.
191      */
setExclusiveCreateVoid(boolean exclusiveCreate)192     public void setExclusiveCreateVoid(boolean exclusiveCreate) {
193         this.exclusiveCreate = exclusiveCreate;
194     }
195 
196     /**
197      * Returns true if the {@link com.sleepycat.je.Environment#openDatabase
198      * Environment.openDatabase} method is configured to fail if the database
199      * already exists.
200      *
201      * <p>This method may be called at any time during the life of the
202      * application.</p>
203      *
204      * @return true if the {@link com.sleepycat.je.Environment#openDatabase
205      * Environment.openDatabase} method is configured to fail if the database
206      * already exists.
207      */
getExclusiveCreate()208     public boolean getExclusiveCreate() {
209         return exclusiveCreate;
210     }
211 
212     /**
213      * Configures the database to support records with duplicate keys.
214      *
215      * <p>When duplicate keys are configured for a database, key prefixing is
216      * also implicitly configured.  Without key prefixing, databases with
217      * duplicates would store keys inefficiently. Key prefixing is therefore
218      * mandatory for databases with duplicates.</p>
219      *
220      * <p>Although two records may have the same key, they may not also have
221      * the same data item.  Two identical records, that have the same key and
222      * data, may not be stored in a database.</p>
223      *
224      * <p>The ordering of duplicates in the database is determined by the
225      * duplicate comparison function.  See {@link #setDuplicateComparator}.  If
226      * the application does not specify a duplicate comparison function, a
227      * default lexical comparison will be used.</p>
228      *
229      * <p>If a primary database is to be associated with one or more secondary
230      * databases, it may not be configured for duplicates.</p>
231      *
232      * <p>Calling this method affects the database, including all threads of
233      * control accessing the database.</p>
234      *
235      * <p>If the database already exists when the database is opened, any
236      * database configuration specified by this method must be the same as the
237      * existing database or an error will be returned.</p>
238      *
239      * @param sortedDuplicates If true, configure the database to support
240      * duplicate data items. A value of false is illegal to this method, that
241      * is, once set, the configuration cannot be cleared.
242      *
243      * @return this
244      */
setSortedDuplicates(boolean sortedDuplicates)245     public DatabaseConfig setSortedDuplicates(boolean sortedDuplicates) {
246         setSortedDuplicatesVoid(sortedDuplicates);
247         return this;
248     }
249 
250     /**
251      * @hidden
252      * The void return setter for use by Bean editors.
253      */
setSortedDuplicatesVoid(boolean sortedDuplicates)254     public void setSortedDuplicatesVoid(boolean sortedDuplicates) {
255         this.sortedDuplicates = sortedDuplicates;
256         if (sortedDuplicates) {
257             setKeyPrefixingVoid(true);
258         }
259     }
260 
261     /**
262      * Returns true if the database is configured to support records with
263      * duplicate keys.
264      *
265      * <p>This method may be called at any time during the life of the
266      * application.</p>
267      *
268      * @return true if the database is configured to support records with
269      * duplicate keys.
270      */
getSortedDuplicates()271     public boolean getSortedDuplicates() {
272         return sortedDuplicates;
273     }
274 
275     /**
276      * Returns the key prefixing configuration.  Note that key prefixing is
277      * always enabled for a database with duplicates configured.
278      *
279      * @return true if key prefixing has been enabled in this database.
280      */
getKeyPrefixing()281     public boolean getKeyPrefixing() {
282         return keyPrefixing;
283     }
284 
285     /**
286      * Configure the database to support key prefixing. Key prefixing causes
287      * the representation of keys in the b-tree internal nodes to be split
288      * between the common prefix of all keys and the suffixes.  Using this
289      * may result in a more space-efficient representation in both the
290      * in-memory and on-disk formats, but at some possible performance cost.
291      *
292      * <p>When duplicate keys are configured for a database, key prefixing is
293      * also implicitly configured.  Without key prefixing, databases with
294      * duplicates would store keys inefficiently. Key prefixing is therefore
295      * mandatory for databases with duplicates.</p>
296      *
297      * @param keyPrefixing If true, enables keyPrefixing for the
298      * database.
299      *
300      * @return this
301      *
302      * @throws IllegalStateException if the keyPrefixing argument is false and
303      * {@link #setSortedDuplicates} has been called to configure duplicates.
304      * Key prefixing is therefore mandatory for databases with duplicates.
305      *
306      */
setKeyPrefixing(boolean keyPrefixing)307     public DatabaseConfig setKeyPrefixing(boolean keyPrefixing) {
308         setKeyPrefixingVoid(keyPrefixing);
309         return this;
310     }
311 
312     /**
313      * @hidden
314      * The void return setter for use by Bean editors.
315      */
setKeyPrefixingVoid(boolean keyPrefixing)316     public void setKeyPrefixingVoid(boolean keyPrefixing) {
317         if (!keyPrefixing && sortedDuplicates) {
318             throw new IllegalStateException
319                 ("Key prefixing is mandatory for databases with duplicates");
320         }
321         this.keyPrefixing = keyPrefixing;
322     }
323 
324     /**
325      * Encloses the database open within a transaction.
326      *
327      * <p>If the call succeeds, the open operation will be recoverable.  If the
328      * call fails, no database will have been created.</p>
329      *
330      * <p>All future operations on this database, which are not explicitly
331      * enclosed in a transaction by the application, will be enclosed in in a
332      * transaction within the library.</p>
333      *
334      * @param transactional If true, enclose the database open within a
335      * transaction.
336      *
337      * @return this
338      */
setTransactional(boolean transactional)339     public DatabaseConfig setTransactional(boolean transactional) {
340         setTransactionalVoid(transactional);
341         return this;
342     }
343 
344     /**
345      * @hidden
346      * The void return setter for use by Bean editors.
347      */
setTransactionalVoid(boolean transactional)348     public void setTransactionalVoid(boolean transactional) {
349         this.transactional = transactional;
350     }
351 
352     /**
353      * Returns true if the database open is enclosed within a transaction.
354      *
355      * <p>This method may be called at any time during the life of the
356      * application.</p>
357      *
358      * @return true if the database open is enclosed within a transaction.
359      */
getTransactional()360     public boolean getTransactional() {
361         return transactional;
362     }
363 
364     /**
365      * Configures the database in read-only mode.
366      *
367      * <p>Any attempt to modify items in the database will fail, regardless of
368      * the actual permissions of any underlying files.</p>
369      *
370      * @param readOnly If true, configure the database in read-only mode.
371      *
372      * @return this
373      */
setReadOnly(boolean readOnly)374     public DatabaseConfig setReadOnly(boolean readOnly) {
375         setReadOnlyVoid(readOnly);
376         return this;
377     }
378 
379     /**
380      * @hidden
381      * The void return setter for use by Bean editors.
382      */
setReadOnlyVoid(boolean readOnly)383     public void setReadOnlyVoid(boolean readOnly) {
384         this.readOnly = readOnly;
385     }
386 
387     /**
388      * Returns true if the database is configured in read-only mode.
389      *
390      * <p>This method may be called at any time during the life of the
391      * application.</p>
392      *
393      * @return true if the database is configured in read-only mode.
394      */
getReadOnly()395     public boolean getReadOnly() {
396         return readOnly;
397     }
398 
399     /**
400      * Configures the {@link com.sleepycat.je.Environment#openDatabase
401      * Environment.openDatabase} method to have a B+Tree fanout of
402      * nodeMaxEntries.
403      *
404      * <p>The nodeMaxEntries parameter is only meaningful if specified with the
405      * allowCreate mode. See {@link EnvironmentConfig#NODE_MAX_ENTRIES} for the
406      * valid value range, and the default value. </p>
407      *
408      * @param nodeMaxEntries The maximum children per B+Tree node.
409      *
410      * @return this
411      */
setNodeMaxEntries(int nodeMaxEntries)412     public DatabaseConfig setNodeMaxEntries(int nodeMaxEntries) {
413         setNodeMaxEntriesVoid(nodeMaxEntries);
414         return this;
415     }
416 
417     /**
418      * @hidden
419      * The void return setter for use by Bean editors.
420      */
setNodeMaxEntriesVoid(int nodeMaxEntries)421     public void setNodeMaxEntriesVoid(int nodeMaxEntries) {
422         this.nodeMaxEntries = nodeMaxEntries;
423     }
424 
425     /**
426      * @deprecated this property no longer has any effect; {@link
427      * #setNodeMaxEntries} should be used instead.
428      */
setNodeMaxDupTreeEntries(int nodeMaxDupTreeEntries)429     public DatabaseConfig setNodeMaxDupTreeEntries(int nodeMaxDupTreeEntries) {
430         return this;
431     }
432 
433     /**
434      * @hidden
435      * The void return setter for use by Bean editors.
436      */
setNodeMaxDupTreeEntriesVoid(int nodeMaxDupTreeEntries)437     public void setNodeMaxDupTreeEntriesVoid(int nodeMaxDupTreeEntries) {
438     }
439 
440     /**
441      * Returns the maximum number of children a B+Tree node can have.
442      *
443      * <p>This method may be called at any time during the life of the
444      * application.</p>
445      *
446      * @return The maximum number of children a B+Tree node can have.
447      */
getNodeMaxEntries()448     public int getNodeMaxEntries() {
449         return nodeMaxEntries;
450     }
451 
452     /**
453      * @deprecated this property no longer has any effect and zero is always
454      * returned; {@link #getNodeMaxEntries} should be used instead.
455      */
getNodeMaxDupTreeEntries()456     public int getNodeMaxDupTreeEntries() {
457         return 0;
458     }
459 
460     /**
461      * By default, a byte by byte lexicographic comparison is used for btree
462      * keys. To customize the comparison, supply a different Comparator.
463      *
464      * <p>Note that there are two ways to set the comparator: by specifying the
465      * class or by specifying a serializable object.  This method is used to
466      * specify a serializable object.  The comparator class must implement
467      * java.util.Comparator and must be serializable.  JE will serialize the
468      * Comparator and deserialize it when subsequently opening the
469      * database.</p>
470      *
471      * <p>If a comparator needs to be initialized before it is used or needs
472      * access to the environment's ClassLoader property, it may implement the
473      * {@link DatabaseComparator} interface.</p>
474      *
475      * <p>The Comparator.compare() method is passed the byte arrays that are
476      * stored in the database. If you know how your data is organized in the
477      * byte array, then you can write a comparison routine that directly
478      * examines the contents of the arrays. Otherwise, you have to reconstruct
479      * your original objects, and then perform the comparison.  See the <a
480      * href="{@docRoot}/../GettingStartedGuide/comparator.html"
481      * target="_top">Getting Started Guide</a> for examples.</p>
482      *
483      * <p><em>WARNING:</em> There are several special considerations that must
484      * be taken into account when implementing a comparator.<p>
485      * <ul>
486      *   <li>Comparator instances are shared by multiple threads and comparator
487      *   methods are called without any special synchronization. Therefore,
488      *   comparators must be thread safe.  In general no shared state should be
489      *   used and any caching of computed values must be done with proper
490      *   synchronization.</li>
491      *
492      *   <li>Because records are stored in the order determined by the
493      *   Comparator, the Comparator's behavior must not change over time and
494      *   therefore should not be dependent on any state that may change over
495      *   time.  In addition, although it is possible to change the comparator
496      *   for an existing database, care must be taken that the new comparator
497      *   provides compatible results with the previous comparator, or database
498      *   corruption will occur.</li>
499      *
500      *   <li>JE uses comparators internally in a wide variety of circumstances,
501      *   so custom comparators must be sure to return valid values for any two
502      *   arbitrary keys.  The user must not make any assumptions about the
503      *   range of key values that might be compared. For example, it's possible
504      *   for the comparator may be used against previously deleted values.</li>
505      * </ul>
506      *
507      * <p>A special type of comparator is a <em>partial comparator</em>, which
508      * compares a proper subset (not all bytes) of the key.  A partial
509      * comparator allows uniquely identifying a record by a partial key value.
510      * For example, the key could contain multiple fields but could uniquely
511      * identify the record with a single field.  The partial comparator could
512      * then compare only the single identifying field.  A query ({@link
513      * Cursor#getSearchKey Cursor.getSearchKey}, for example) could then be
514      * performed by passing a partial key that contains only the identifying
515      * field.</p>
516      *
517      * <p><strong>WARNING:</strong> All partial comparators must implement
518      * the {@link PartialComparator} tag interface.  See "Upgrading from JE 5.0
519      * or earlier" in the change log and the {@link PartialComparator} javadoc
520      * for more information.</p>
521      * <p>
522      * Another special type of comparator is a <em>binary equality</em>
523      * comparator, which considers two keys to be equal if and only if they
524      * have the same length and they are equal byte-per-byte. All binary
525      * equality comparators must implement the {@link BinaryEqualityComparator}
526      * interface. The significance of binary equality comparators is that they
527      * make possible certain internal optimizations, like the "blind puts"
528      * optimization, described in
529      * {@link BinaryEqualityComparator}
530      * <p>
531      * The comparator for an existing database will not be overridden unless
532      * setOverrideBtreeComparator() is set to true.
533      *
534      * @return this
535      */
setBtreeComparator( Comparator<byte[]> btreeComparator)536     public DatabaseConfig setBtreeComparator(
537         Comparator<byte[]> btreeComparator) {
538 
539         setBtreeComparatorVoid(btreeComparator);
540         return this;
541     }
542 
543     /**
544      * @hidden
545      * The void return setter for use by Bean editors.
546      */
setBtreeComparatorVoid(Comparator<byte[]> btreeComparator)547     public void setBtreeComparatorVoid(Comparator<byte[]> btreeComparator) {
548 
549         /* Note: comparator may be null */
550         this.btreeComparator = validateComparator(btreeComparator, "Btree");
551         this.btreeComparatorByClassName = false;
552     }
553 
554     /**
555      * By default, a byte by byte lexicographic comparison is used for btree
556      * keys. To customize the comparison, supply a different Comparator.
557      *
558      * <p>Note that there are two ways to set the comparator: by specifying the
559      * class or by specifying a serializable object.  This method is used to
560      * specify a Comparator class.  The comparator class must implement
561      * java.util.Comparator and must have a public zero-parameter constructor.
562      * JE will store the class name and instantiate the Comparator by class
563      * name (using <code>Class.forName</code> and <code>newInstance</code>)
564      * when subsequently opening the database.  Because the Comparator is
565      * instantiated using its default constructor, it should not be dependent
566      * on other constructor parameters.</p>
567      *
568      * <p>The Comparator.compare() method is passed the byte arrays that are
569      * stored in the database. If you know how your data is organized in the
570      * byte array, then you can write a comparison routine that directly
571      * examines the contents of the arrays. Otherwise, you have to reconstruct
572      * your original objects, and then perform the comparison.  See the <a
573      * href="{@docRoot}/../GettingStartedGuide/comparator.html"
574      * target="_top">Getting Started Guide</a> for examples.</p>
575      *
576      * <p>If a comparator needs to be initialized before it is used or needs
577      * access to the environment's ClassLoader property, it may implement the
578      * {@link DatabaseComparator} interface.</p>
579      *
580      * <p><em>WARNING:</em> There are several special considerations that must
581      * be taken into account when implementing a comparator.<p>
582      * <ul>
583      *   <li>Comparator instances are shared by multiple threads and comparator
584      *   methods are called without any special synchronization. Therefore,
585      *   comparators must be thread safe.  In general no shared state should be
586      *   used and any caching of computed values must be done with proper
587      *   synchronization.</li>
588      *
589      *   <li>Because records are stored in the order determined by the
590      *   Comparator, the Comparator's behavior must not change over time and
591      *   therefore should not be dependent on any state that may change over
592      *   time.  In addition, although it is possible to change the comparator
593      *   for an existing database, care must be taken that the new comparator
594      *   provides compatible results with the previous comparator, or database
595      *   corruption will occur.</li>
596      *
597      *   <li>JE uses comparators internally in a wide variety of circumstances,
598      *   so custom comparators must be sure to return valid values for any two
599      *   arbitrary keys.  The user must not make any assumptions about the
600      *   range of key values that might be compared. For example, it's possible
601      *   for the comparator may be used against previously deleted values.</li>
602      * </ul>
603      *
604      * <p>A special type of comparator is a <em>partial comparator</em>, which
605      * compares a proper subset (not all bytes) of the key.  A partial
606      * comparator allows uniquely identifying a record by a partial key value.
607      * For example, the key could contain multiple fields but could uniquely
608      * identify the record with a single field.  The partial comparator could
609      * then compare only the single identifying field.  A query ({@link
610      * Cursor#getSearchKey Cursor.getSearchKey}, for example) could then be
611      * performed by passing a partial key that contains only the identifying
612      * field.</p>
613      *
614      * <p><strong>WARNING:</strong> All partial comparators must implement
615      * the {@link PartialComparator} tag interface.  See "Upgrading from JE 5.0
616      * or earlier" in the change log and the {@link PartialComparator} javadoc
617      * for more information.</p>
618      * <p>
619      * Another special type of comparator is a <em>binary equality</em>
620      * comparator, which considers two keys to be equal if and only if they
621      * have the same length and they are equal byte-per-byte. All binary
622      * equality comparators must implement the {@link BinaryEqualityComparator}
623      * interface. The significance of binary equality comparators is that they
624      * make possible certain internal optimizations, like the "blind puts"
625      * optimization, described in
626      * {@link BinaryEqualityComparator}
627      * <p>
628      * The comparator for an existing database will not be overridden unless
629      * setOverrideBtreeComparator() is set to true.
630      *
631      * @return this
632      */
setBtreeComparator( Class<? extends Comparator<byte[]>> btreeComparatorClass)633     public DatabaseConfig setBtreeComparator(
634         Class<? extends Comparator<byte[]>>
635         btreeComparatorClass) {
636 
637         setBtreeComparatorVoid(btreeComparatorClass);
638         return this;
639     }
640 
641     /**
642      * @hidden
643      * The void return setter for use by Bean editors.
644      */
setBtreeComparatorVoid(Class<? extends Comparator<byte[]>> btreeComparatorClass)645     public void setBtreeComparatorVoid(Class<? extends Comparator<byte[]>>
646                                        btreeComparatorClass) {
647 
648         /* Note: comparator may be null */
649         this.btreeComparator = validateComparator(btreeComparatorClass,
650                                                   "Btree");
651         this.btreeComparatorByClassName = true;
652     }
653 
654     /**
655      * Returns the Comparator used for key comparison on this database.
656      */
getBtreeComparator()657     public Comparator<byte[]> getBtreeComparator() {
658         return btreeComparator;
659     }
660 
661     /**
662      * Returns true if the btree comparator is set by class name, not by
663      * serializable Comparator object
664      * @return true if the comparator is set by class name, not by serializable
665      * Comparator object.
666      */
getBtreeComparatorByClassName()667     public boolean getBtreeComparatorByClassName() {
668         return btreeComparatorByClassName;
669     }
670 
671     /**
672      * Sets to true if the database exists and the btree comparator specified
673      * in this configuration object should override the current comparator.
674      *
675      * @param override Set to true to override the existing comparator.
676      *
677      * @return this
678      */
setOverrideBtreeComparator(boolean override)679     public DatabaseConfig setOverrideBtreeComparator(boolean override) {
680         setOverrideBtreeComparatorVoid(override);
681         return this;
682     }
683 
684     /**
685      * @hidden
686      * The void return setter for use by Bean editors.
687      */
setOverrideBtreeComparatorVoid(boolean override)688     public void setOverrideBtreeComparatorVoid(boolean override) {
689         overrideBtreeComparator = override;
690     }
691 
692     /**
693      * Returns the override setting for the btree comparator.
694      */
getOverrideBtreeComparator()695     public boolean getOverrideBtreeComparator() {
696         return overrideBtreeComparator;
697     }
698 
699     /**
700      * By default, a byte by byte lexicographic comparison is used for
701      * duplicate data items in a duplicate set.  To customize the comparison,
702      * supply a different Comparator.
703      *
704      * <p>Note that there are two ways to set the comparator: by specifying the
705      * class or by specifying a serializable object.  This method is used to
706      * specify a serializable object.  The comparator class must implement
707      * java.util.Comparator and must be serializable.  JE will serialize the
708      * Comparator and deserialize it when subsequently opening the
709      * database.</p>
710      *
711      * <p>The Comparator.compare() method is passed the byte arrays that are
712      * stored in the database. If you know how your data is organized in the
713      * byte array, then you can write a comparison routine that directly
714      * examines the contents of the arrays. Otherwise, you have to reconstruct
715      * your original objects, and then perform the comparison.  See the <a
716      * href="{@docRoot}/../GettingStartedGuide/comparator.html"
717      * target="_top">Getting Started Guide</a> for examples.</p>
718      *
719      * <p>If a comparator needs to be initialized before it is used or needs
720      * access to the environment's ClassLoader property, it may implement the
721      * {@link DatabaseComparator} interface.</p>
722      *
723      * <p><em>WARNING:</em> There are several special considerations that must
724      * be taken into account when implementing a comparator.<p>
725      * <ul>
726      *   <li>Comparator instances are shared by multiple threads and comparator
727      *   methods are called without any special synchronization. Therefore,
728      *   comparators must be thread safe.  In general no shared state should be
729      *   used and any caching of computed values must be done with proper
730      *   synchronization.</li>
731      *
732      *   <li>Because records are stored in the order determined by the
733      *   Comparator, the Comparator's behavior must not change over time and
734      *   therefore should not be dependent on any state that may change over
735      *   time.  In addition, although it is possible to change the comparator
736      *   for an existing database, care must be taken that the new comparator
737      *   provides compatible results with the previous comparator, or database
738      *   corruption will occur.</li>
739      *
740      *   <li>JE uses comparators internally in a wide variety of circumstances,
741      *   so custom comparators must be sure to return valid values for any two
742      *   arbitrary keys.  The user must not make any assumptions about the
743      *   range of key values that might be compared. For example, it's possible
744      *   for the comparator may be used against previously deleted values.</li>
745      * </ul>
746      *
747      * <p>A special type of comparator is a <em>partial comparator</em>, which
748      * is a comparator that compares a proper subset (not all bytes) of the
749      * data.  A partial comparator allows uniquely identifying a record within
750      * a duplicate set by a partial data value.  For example, the data could
751      * contain multiple fields but could uniquely identify the record with a
752      * single field.  The partial comparator could then compare only the single
753      * identifying field.  A query ({@link Cursor#getSearchBoth
754      * Cursor.getSearchBoth}, for example) could then be performed by passing a
755      * partial data value that contains only the identifying field.</p>
756      *
757      * <p>When using a partial comparator, it is possible to update the data
758      * for a duplicate record, as long as only the non-identifying fields in
759      * the data are changed.  See {@link Cursor#putCurrent Cursor.putCurrent}
760      * for more information.</p>
761      *
762      * <p><strong>WARNING:</strong> All partial comparators must implement
763      * the {@link PartialComparator} tag interface.  See "Upgrading from JE 5.0
764      * or earlier" in the change log and the {@link PartialComparator} javadoc
765      * for more information.</p>
766      * <p>
767      * Another special type of comparator is a <em>binary equality</em>
768      * comparator, which considers two keys to be equal if and only if they
769      * have the same length and they are equal byte-per-byte. All binary
770      * equality comparators must implement the {@link BinaryEqualityComparator}
771      * interface. The significance of binary equality comparators is that they
772      * make possible certain internal optimizations, like the "blind puts"
773      * optimization, described in
774      * {@link BinaryEqualityComparator}
775      * <p>
776      * The comparator for an existing database will not be overridden unless
777      * setOverrideDuplicateComparator() is set to true.
778      */
setDuplicateComparator( Comparator<byte[]> duplicateComparator)779     public DatabaseConfig setDuplicateComparator(
780         Comparator<byte[]> duplicateComparator) {
781 
782         /* Note: comparator may be null */
783         setDuplicateComparatorVoid(duplicateComparator);
784         return this;
785     }
786 
787     /**
788      * @hidden
789      * The void return setter for use by Bean editors.
790      */
setDuplicateComparatorVoid( Comparator<byte[]> duplicateComparator)791     public void setDuplicateComparatorVoid(
792         Comparator<byte[]>
793         duplicateComparator) {
794 
795         /* Note: comparator may be null */
796         this.duplicateComparator =
797             validateComparator(duplicateComparator, "Duplicate");
798         this.duplicateComparatorByClassName = false;
799     }
800 
801     /**
802      * By default, a byte by byte lexicographic comparison is used for
803      * duplicate data items in a duplicate set.  To customize the comparison,
804      * supply a different Comparator.
805      *
806      * <p>Note that there are two ways to set the comparator: by specifying the
807      * class or by specifying a serializable object.  This method is used to
808      * specify a Comparator class.  The comparator class must implement
809      * java.util.Comparator and must have a public zero-parameter constructor.
810      * JE will store the class name and instantiate the Comparator by class
811      * name (using <code>Class.forName</code> and <code>newInstance</code>)
812      * when subsequently opening the database.  Because the Comparator is
813      * instantiated using its default constructor, it should not be dependent
814      * on other constructor parameters.</p>
815      *
816      * <p>The Comparator.compare() method is passed the byte arrays that are
817      * stored in the database. If you know how your data is organized in the
818      * byte array, then you can write a comparison routine that directly
819      * examines the contents of the arrays. Otherwise, you have to reconstruct
820      * your original objects, and then perform the comparison.  See the <a
821      * href="{@docRoot}/../GettingStartedGuide/comparator.html"
822      * target="_top">Getting Started Guide</a> for examples.</p>
823      *
824      * <p>If a comparator needs to be initialized before it is used or needs
825      * access to the environment's ClassLoader property, it may implement the
826      * {@link DatabaseComparator} interface.</p>
827      *
828      * <p><em>WARNING:</em> There are several special considerations that must
829      * be taken into account when implementing a comparator.<p>
830      * <ul>
831      *   <li>Comparator instances are shared by multiple threads and comparator
832      *   methods are called without any special synchronization. Therefore,
833      *   comparators must be thread safe.  In general no shared state should be
834      *   used and any caching of computed values must be done with proper
835      *   synchronization.</li>
836      *
837      *   <li>Because records are stored in the order determined by the
838      *   Comparator, the Comparator's behavior must not change over time and
839      *   therefore should not be dependent on any state that may change over
840      *   time.  In addition, although it is possible to change the comparator
841      *   for an existing database, care must be taken that the new comparator
842      *   provides compatible results with the previous comparator, or database
843      *   corruption will occur.</li>
844      *
845      *   <li>JE uses comparators internally in a wide variety of circumstances,
846      *   so custom comparators must be sure to return valid values for any two
847      *   arbitrary keys.  The user must not make any assumptions about the
848      *   range of key values that might be compared. For example, it's possible
849      *   for the comparator may be used against previously deleted values.</li>
850      * </ul>
851      *
852      * <p>A special type of comparator is a <em>partial comparator</em>, which
853      * is a comparator that compares a proper subset (not all bytes) of the
854      * data.  A partial comparator allows uniquely identifying a record within
855      * a duplicate set by a partial data value.  For example, the data could
856      * contain multiple fields but could uniquely identify the record with a
857      * single field.  The partial comparator could then compare only the single
858      * identifying field.  A query ({@link Cursor#getSearchBoth
859      * Cursor.getSearchBoth}, for example) could then be performed by passing a
860      * partial data value that contains only the identifying field.</p>
861      *
862      * <p>When using a partial comparator, it is possible to update the data
863      * for a duplicate record, as long as only the non-identifying fields in
864      * the data are changed.  See {@link Cursor#putCurrent Cursor.putCurrent}
865      * for more information.</p>
866      *
867      * <p><strong>WARNING:</strong> All partial comparators must implement
868      * the {@link PartialComparator} tag interface.  See "Upgrading from JE 5.0
869      * or earlier" in the change log and the {@link PartialComparator} javadoc
870      * for more information.</p>
871      * <p>
872      * Another special type of comparator is a <em>binary equality</em>
873      * comparator, which considers two keys to be equal if and only if they
874      * have the same length and they are equal byte-per-byte. All binary
875      * equality comparators must implement the {@link BinaryEqualityComparator}
876      * interface. The significance of binary equality comparators is that they
877      * make possible certain internal optimizations, like the "blind puts"
878      * optimization, described in
879      * {@link BinaryEqualityComparator}
880      * <p>
881      * The comparator for an existing database will not be overridden unless
882      * setOverrideDuplicateComparator() is set to true.
883      *
884      * @return this
885      */
setDuplicateComparator( Class<? extends Comparator<byte[]>> duplicateComparatorClass)886     public DatabaseConfig setDuplicateComparator(
887         Class<? extends Comparator<byte[]>>
888         duplicateComparatorClass) {
889 
890         setDuplicateComparatorVoid(duplicateComparatorClass);
891         return this;
892     }
893 
894     /**
895      * @hidden
896      * The void return setter for use by Bean editors.
897      */
setDuplicateComparatorVoid( Class<? extends Comparator<byte[]>> duplicateComparatorClass)898     public void setDuplicateComparatorVoid(
899         Class<? extends Comparator<byte[]>>
900         duplicateComparatorClass) {
901 
902         /* Note: comparator may be null */
903         this.duplicateComparator =
904             validateComparator(duplicateComparatorClass, "Duplicate");
905         this.duplicateComparatorByClassName = true;
906     }
907 
908     /**
909      * Returns the Comparator used for duplicate record comparison on this
910      * database.
911      */
getDuplicateComparator()912     public Comparator<byte[]> getDuplicateComparator() {
913         return duplicateComparator;
914     }
915 
916     /**
917      * Returns true if the duplicate comparator is set by class name, not by
918      * serializable Comparator object.
919      *
920      * @return true if the duplicate comparator is set by class name, not by
921      * serializable Comparator object.
922      */
getDuplicateComparatorByClassName()923     public boolean getDuplicateComparatorByClassName() {
924         return duplicateComparatorByClassName;
925     }
926 
927     /**
928      * Sets to true if the database exists and the duplicate comparator
929      * specified in this configuration object should override the current
930      * comparator.
931      *
932      * @param override Set to true to override the existing comparator.
933      *
934      * @return this
935      */
setOverrideDuplicateComparator(boolean override)936     public DatabaseConfig setOverrideDuplicateComparator(boolean override) {
937         setOverrideDuplicateComparatorVoid(override);
938         return this;
939     }
940 
941     /**
942      * @hidden
943      * The void return setter for use by Bean editors.
944      */
setOverrideDuplicateComparatorVoid(boolean override)945     public void setOverrideDuplicateComparatorVoid(boolean override) {
946         overrideDuplicateComparator = override;
947     }
948 
949     /**
950      * Returns the override setting for the duplicate comparator.
951      */
getOverrideDuplicateComparator()952     public boolean getOverrideDuplicateComparator() {
953         return overrideDuplicateComparator;
954     }
955 
956     /**
957      * @hidden
958      * For internal use only.
959      *
960      * Specifies the list of triggers associated with the database; triggers
961      * are executed in the order specified by this list.
962      * <p>
963      * This configuration parameter is only meaningful when configuring a
964      * <code>Primary</code> database.
965      * <p>
966      * The type of the trigger specified in the list must match the type of
967      * database being configured. For example, the trigger object must
968      * implement the <code>ReplicatedDatabaseTrigger</code> interface if it's
969      * used to configure a replicated database.
970      * <p>
971      * Some of the incorrect uses of this parameter are detected during calls
972      * to {@link Environment#openDatabase Environment.openDatabase} or
973      * {@link Environment#openSecondaryDatabase
974      * Environment.openSecondaryDatabase} and will result in an
975      * <code>IllegalArgumentException</code>.
976      *
977      * @param triggers the list of database triggers to be associated with the
978      * environment.
979      *
980      * @throws IllegalArgumentException If the triggers in the list do not have
981      * unique names, have conflicting types (e.g. only a subset implement
982      * {@link ReplicatedDatabaseTrigger ReplicatedDatabaseTrigger}), or do not
983      * implement {@link ReplicatedDatabaseTrigger ReplicatedDatabaseTrigger}
984      * for a replicated database.
985      *
986      * @return this
987      */
setTriggers(List<Trigger> triggers)988     public DatabaseConfig setTriggers(List<Trigger> triggers) {
989         setTriggersVoid(triggers);
990         return this;
991     }
992 
993     /**
994      * @hidden
995      * The void return setter for use by Bean editors.
996      */
setTriggersVoid(List<Trigger> triggers)997     public void setTriggersVoid(List<Trigger> triggers) {
998         this.triggers = triggers;
999 
1000         if ((triggers == null) || (triggers.size() == 0)) {
1001             return;
1002         }
1003 
1004         checkTriggers(triggers);
1005     }
1006 
1007     /**
1008      * @hidden
1009      * For internal use only.
1010      *
1011      * Returns the list of configured database triggers.
1012      */
getTriggers()1013     public List<Trigger> getTriggers() {
1014         return triggers;
1015     }
1016 
1017     /**
1018      * @hidden
1019      * For internal use only.
1020      *
1021      * Set to true if the database exists and the {@link PersistentTrigger}s in
1022      * the trigger list specified in this configuration object should override
1023      * those in the current list of triggers.  Note that any transient triggers
1024      * that are specified are always configured, because they do not override
1025      * existing triggers.
1026      *
1027      * @param override Set to true to override the existing comparator.
1028      *
1029      * @return this
1030      */
setOverrideTriggers(boolean override)1031     public DatabaseConfig setOverrideTriggers(boolean override) {
1032         setOverrideTriggersVoid(override);
1033         return this;
1034     }
1035 
1036     /**
1037      * @hidden
1038      * The void return setter for use by Bean editors.
1039      */
setOverrideTriggersVoid(boolean override)1040     public void setOverrideTriggersVoid(boolean override) {
1041         overrideTriggers = override;
1042     }
1043 
1044     /**
1045      * @hidden
1046      * For internal use only.
1047      *
1048      * Returns the override setting for triggers.
1049      */
getOverrideTriggers()1050     public boolean getOverrideTriggers() {
1051         return overrideTriggers;
1052     }
1053 
1054     /**
1055      * Sets the temporary database option.
1056      *
1057      * <p> Temporary databases operate internally in deferred-write mode to
1058      * provide reduced disk I/O and increased concurrency.  But unlike an
1059      * ordinary deferred-write database, the information in a temporary
1060      * database is not durable or persistent.
1061      *
1062      * <p> A temporary database is not flushed to disk when the database is
1063      * closed or when a checkpoint is performed, and the Database.sync method
1064      * may not be called.  When all handles for a temporary database are
1065      * closed, the database is automatically removed.  If a crash occurs before
1066      * closing a temporary database, the database will be automatically removed
1067      * when the environment is re-opened.
1068      *
1069      * <p> Note that although temporary databases can page to disk if the cache
1070      * is not large enough to hold the databases, they are much more efficient
1071      * if the database remains in memory. See the JE FAQ on the Oracle
1072      * Technology Network site for information on how to estimate the cache
1073      * size needed by a given database.
1074      *
1075      * <p>
1076      * See the {@link <a
1077      * href="{@docRoot}/../GettingStartedGuide/DB.html#tempdbje">Getting
1078      * Started Guide, Database chapter</a>} for a full description of temporary
1079      * databases.
1080      * <p>
1081      * @param temporary if true, the database will be opened as a temporary
1082      * database.
1083      *
1084      * @return this
1085      */
setTemporary(boolean temporary)1086     public DatabaseConfig setTemporary(boolean temporary) {
1087         setTemporaryVoid(temporary);
1088         return this;
1089     }
1090 
1091     /**
1092      * @hidden
1093      * The void return setter for use by Bean editors.
1094      */
setTemporaryVoid(boolean temporary)1095     public void setTemporaryVoid(boolean temporary) {
1096         this.temporary = temporary;
1097     }
1098 
1099     /**
1100      * Returns the temporary database option.
1101      * @return boolean if true, the database is temporary.
1102      */
getTemporary()1103     public boolean getTemporary() {
1104         return temporary;
1105     }
1106 
1107     /**
1108      * Sets the deferred-write option.
1109      *
1110      * <p> Deferred-write databases have reduced disk I/O and improved
1111      * concurrency.  Disk I/O is reduced when data records are frequently
1112      * modified or deleted.  The information in a deferred-write database is
1113      * not guaranteed to be durable or persistent until {@link Database#close}
1114      * or {@link Database#sync} is called, or a checkpoint is performed. Since
1115      * the usual write ahead logging system is relaxed in order to improve
1116      * performance, if the environment crashes before a {@link Database#sync}
1117      * or {@link Database#close}, none, all, or a unpredictable set of the
1118      * operations previously done may be persistent.
1119      *
1120      * <p> After a deferred-write database is closed it may be re-opened as an
1121      * ordinary transactional or non-transactional database.  For example, this
1122      * can be used to initially load a large data set in deferred-write mode
1123      * and then switch to transactional mode for subsequent operations.
1124      *
1125      * <p> Note that although deferred-write databases can page to disk if the
1126      * cache is not large enough to hold the databases, they are much more
1127      * efficient if the database remains in memory. See the JE FAQ on the
1128      * Oracle Technology Network site for information on how to estimate the
1129      * cache size needed by a given database.
1130      *
1131      * <p>
1132      * See the {@link <a
1133      * href="{@docRoot}/../GettingStartedGuide/DB.html#dwdatabase">Getting
1134      * Started Guide, Database chapter</a>} for a full description
1135      * of deferred-write databases.
1136      *
1137      * <p>
1138      * @param deferredWrite if true, the database will be opened as a
1139      * deferred-write database.
1140      *
1141      * @return this
1142      */
setDeferredWrite(boolean deferredWrite)1143     public DatabaseConfig setDeferredWrite(boolean deferredWrite) {
1144         setDeferredWriteVoid(deferredWrite);
1145         return this;
1146     }
1147 
1148     /**
1149      * @hidden
1150      * The void return setter for use by Bean editors.
1151      */
setDeferredWriteVoid(boolean deferredWrite)1152     public void setDeferredWriteVoid(boolean deferredWrite) {
1153         this.deferredWrite = deferredWrite;
1154     }
1155 
1156     /**
1157      * Returns the deferred-write option.
1158      *
1159      * @return boolean if true, deferred-write is enabled.
1160      */
getDeferredWrite()1161     public boolean getDeferredWrite() {
1162         return deferredWrite;
1163     }
1164 
1165     /**
1166      * Used to set the comparator when filling in a configuration from an
1167      * existing database.
1168      */
setBtreeComparatorInternal(Comparator<byte[]> comparator, boolean byClassName)1169     void setBtreeComparatorInternal(Comparator<byte[]> comparator,
1170                                     boolean byClassName) {
1171         btreeComparator = comparator;
1172         btreeComparatorByClassName = byClassName;
1173     }
1174 
1175     /**
1176      * Used to set the comparator when filling in a configuration from an
1177      * existing database.
1178      */
setDuplicateComparatorInternal(Comparator<byte[]> comparator, boolean byClassName)1179     void setDuplicateComparatorInternal(Comparator<byte[]> comparator,
1180                                         boolean byClassName) {
1181         duplicateComparator = comparator;
1182         duplicateComparatorByClassName = byClassName;
1183     }
1184 
1185     /**
1186      * Setting useExistingConfig to true allows a program to open a database
1187      * without knowing a prior what its configuration is.  For example, if you
1188      * want to open a database without knowing whether it contains sorted
1189      * duplicates or not, you can set this property to true.  In general, this
1190      * is used by the JE utilities, to avoid having to know the configuration
1191      * of a database.  The databases should be opened readOnly when this
1192      * property is set to true.
1193      *
1194      * @param useExistingConfig true if this Database should be opened using
1195      * the existing configuration.
1196      *
1197      * @return this
1198      */
setUseExistingConfig(boolean useExistingConfig)1199     public DatabaseConfig setUseExistingConfig(boolean useExistingConfig) {
1200         setUseExistingConfigVoid(useExistingConfig);
1201         return this;
1202     }
1203 
1204     /**
1205      * @hidden
1206      * The void return setter for use by Bean editors.
1207      */
setUseExistingConfigVoid(boolean useExistingConfig)1208     public void setUseExistingConfigVoid(boolean useExistingConfig) {
1209         this.useExistingConfig = useExistingConfig;
1210     }
1211 
1212     /**
1213      * Return the value of the useExistingConfig property.
1214      *
1215      * @return the value of the useExistingConfig property.
1216      */
getUseExistingConfig()1217     public boolean getUseExistingConfig() {
1218         return useExistingConfig;
1219     }
1220 
1221     /**
1222      * Sets the default {@code CacheMode} used for operations performed on this
1223      * database.  If this property is non-null, it overrides the default
1224      * specified using {@link EnvironmentConfig#setCacheMode} for operations on
1225      * this database.  The default cache mode may be overridden on a per-record
1226      * or per-operation basis using {@link Cursor#setCacheMode}.
1227      *
1228      * @param cacheMode is the default {@code CacheMode} used for operations
1229      * performed on this database.  If {@code null} is specified, the
1230      * environment default will be used.
1231      *
1232      * @see CacheMode for further details.
1233      *
1234      * @since 4.0.97
1235      */
setCacheMode(final CacheMode cacheMode)1236     public DatabaseConfig setCacheMode(final CacheMode cacheMode) {
1237         setCacheModeVoid(cacheMode);
1238         return this;
1239     }
1240 
1241     /**
1242      * @hidden
1243      * The void return setter for use by Bean editors.
1244      */
setCacheModeVoid(final CacheMode cacheMode)1245     public void setCacheModeVoid(final CacheMode cacheMode) {
1246         this.cacheMode = cacheMode;
1247     }
1248 
1249     /**
1250      * Returns the default {@code CacheMode} used for operations performed on
1251      * this database, or null if the environment default is used.
1252      *
1253      * @return the default {@code CacheMode} used for operations performed on
1254      * this database, or null if the environment default is used.
1255      *
1256      * @see #setCacheMode
1257      *
1258      * @since 4.0.97
1259      */
getCacheMode()1260     public CacheMode getCacheMode() {
1261         return cacheMode;
1262     }
1263 
1264     /**
1265      * @hidden
1266      * For internal use only.
1267      *
1268      * Sets the {@code CacheModeStrategy} used for operations performed on this
1269      * database.  If this property is non-null, it overrides the default
1270      * specified using {@link EnvironmentConfig#setCacheModeStrategy} for
1271      * operations on this database.
1272      *
1273      * @param strategy is the {@code CacheModeStrategy} used for operations
1274      * performed on this database.  If {@code null} is specified, the
1275      * environment default will be used.
1276      *
1277      * @see CacheModeStrategy for further details.
1278      *
1279      * @since 4.0.97
1280      */
setCacheModeStrategy( final CacheModeStrategy strategy)1281     public DatabaseConfig setCacheModeStrategy(
1282         final CacheModeStrategy strategy) {
1283         cacheModeStrategy = strategy;
1284         return this;
1285     }
1286 
1287     /**
1288      * @hidden
1289      * The void return setter for use by Bean editors.
1290      */
setCacheModeStrategyVoid(final CacheModeStrategy strategy)1291     public void setCacheModeStrategyVoid(final CacheModeStrategy strategy) {
1292         cacheModeStrategy = strategy;
1293     }
1294 
1295     /**
1296      * @hidden
1297      * For internal use only.
1298      *
1299      * Returns the {@code CacheModeStrategy} used for operations performed on
1300      * this database, or null if the environment default is used.
1301      *
1302      * @return the default {@code CacheModeStrategy} used for operations
1303      * performed on this database, or null if the environment default is used.
1304      *
1305      * @see #setCacheModeStrategy
1306      *
1307      * @since 4.0.97
1308      */
getCacheModeStrategy()1309     public CacheModeStrategy getCacheModeStrategy() {
1310         return cacheModeStrategy;
1311     }
1312 
1313     /**
1314      * Configures a database to be replicated or non-replicated, in a
1315      * replicated Environment.  By default this property is true, meaning that
1316      * by default a database is replicated in a replicated Environment.
1317      * <p>
1318      * In a non-replicated Environment, this property is ignored.  All
1319      * databases are non-replicated in a non-replicated Environment.
1320      *
1321      * @see
1322      * <a href="rep/ReplicatedEnvironment.html#nonRepDbs">Non-replicated
1323      * Databases in a Replicated Environment</a>
1324      */
setReplicated(boolean replicated)1325     public DatabaseConfig setReplicated(boolean replicated) {
1326         setReplicatedVoid(replicated);
1327         return this;
1328     }
1329 
1330     /**
1331      * @hidden
1332      * The void return setter for use by Bean editors.
1333      */
setReplicatedVoid(boolean replicated)1334     public void setReplicatedVoid(boolean replicated) {
1335         this.replicated = replicated;
1336     }
1337 
1338     /**
1339      * Returns the replicated property for the database.
1340      * <p>
1341      * This method returns true by default.  However, in a non-replicated
1342      * Environment, this property is ignored.  All databases are non-replicated
1343      * in a non-replicated Environment.
1344      *
1345      * @see #setReplicated
1346      */
getReplicated()1347     public boolean getReplicated() {
1348         return replicated;
1349     }
1350 
1351     /**
1352      * @hidden
1353      * For internal use only.
1354      *
1355      * Configures a SecondaryAssociation that is used to define
1356      * primary-secondary associations for a group of primary and secondary
1357      * databases.  The same SecondaryAssociation instance must be configured on
1358      * the primary and secondary databases.
1359      *
1360      * @see SecondaryAssociation
1361      */
1362     public DatabaseConfig
setSecondaryAssociation(SecondaryAssociation association)1363         setSecondaryAssociation(SecondaryAssociation association) {
1364         setSecondaryAssociationVoid(association);
1365         return this;
1366     }
1367 
1368     /**
1369      * @hidden
1370      * The void return setter for use by Bean editors.
1371      */
setSecondaryAssociationVoid(SecondaryAssociation association)1372     public void setSecondaryAssociationVoid(SecondaryAssociation association) {
1373         secAssociation = association;
1374     }
1375 
1376     /**
1377      * @hidden
1378      * For internal use only.
1379      *
1380      * Returns the configured SecondaryAssociation.
1381      *
1382      * @see #setSecondaryAssociation
1383      * @see SecondaryAssociation
1384      */
getSecondaryAssociation()1385     public SecondaryAssociation getSecondaryAssociation() {
1386         return secAssociation;
1387     }
1388 
1389     /**
1390      * Returns a copy of this configuration object.
1391      *
1392      * @deprecated As of JE 4.0.13, replaced by {@link
1393      * DatabaseConfig#clone()}.</p>
1394      */
cloneConfig()1395     public DatabaseConfig cloneConfig() {
1396         return clone();
1397     }
1398 
1399     /**
1400      * Returns a copy of this configuration object.
1401      */
1402     @Override
clone()1403     public DatabaseConfig clone() {
1404         try {
1405             return (DatabaseConfig) super.clone();
1406         } catch (CloneNotSupportedException willNeverOccur) {
1407             return null;
1408         }
1409     }
1410 
1411     /**
1412      * For JCA Database handle caching.
1413      *
1414      * @throws IllegalArgumentException via JEConnection.openDatabase.
1415      */
validate(DatabaseConfig config)1416     void validate(DatabaseConfig config)
1417         throws DatabaseException {
1418 
1419         if (config == null) {
1420             config = DatabaseConfig.DEFAULT;
1421         }
1422 
1423         boolean txnMatch = (config.transactional == transactional);
1424         boolean roMatch = (config.readOnly == readOnly);
1425         boolean sdMatch = (config.sortedDuplicates == sortedDuplicates);
1426         boolean dwMatch = (config.getDeferredWrite() == deferredWrite);
1427         boolean btCmpMatch = true;
1428         if (config.overrideBtreeComparator) {
1429             if (btreeComparator == null) {
1430                 btCmpMatch = (config.btreeComparator == null);
1431             } else if (config.btreeComparatorByClassName !=
1432                        btreeComparatorByClassName) {
1433                 btCmpMatch = false;
1434             } else if (btreeComparatorByClassName) {
1435                 btCmpMatch = btreeComparator.getClass() ==
1436                              config.btreeComparator.getClass();
1437             } else {
1438                 btCmpMatch = Arrays.equals
1439                     (DatabaseImpl.objectToBytes
1440                         (btreeComparator, "Btree"),
1441                      DatabaseImpl.objectToBytes
1442                         (config.btreeComparator, "Btree"));
1443             }
1444         }
1445         boolean dtCmpMatch = true;
1446         if (config.overrideDuplicateComparator) {
1447             if (duplicateComparator == null) {
1448                 dtCmpMatch = (config.duplicateComparator == null);
1449             } else if (config.duplicateComparatorByClassName !=
1450                        duplicateComparatorByClassName) {
1451                 dtCmpMatch = false;
1452             } else if (duplicateComparatorByClassName) {
1453                 dtCmpMatch = duplicateComparator.getClass() ==
1454                              config.duplicateComparator.getClass();
1455             } else {
1456                 dtCmpMatch = Arrays.equals
1457                     (DatabaseImpl.objectToBytes
1458                         (duplicateComparator, "Duplicate"),
1459                      DatabaseImpl.objectToBytes
1460                         (config.duplicateComparator, "Duplicate"));
1461             }
1462         }
1463 
1464         if (txnMatch &&
1465             roMatch &&
1466             sdMatch &&
1467             dwMatch &&
1468             btCmpMatch &&
1469             dtCmpMatch) {
1470             return;
1471         }
1472         String message = genDatabaseConfigMismatchMessage
1473             (txnMatch, roMatch, sdMatch, dwMatch,
1474              btCmpMatch, dtCmpMatch);
1475         throw new IllegalArgumentException(message);
1476     }
1477 
genDatabaseConfigMismatchMessage(boolean txnMatch, boolean roMatch, boolean sdMatch, boolean dwMatch, boolean btCmpMatch, boolean dtCmpMatch)1478     private String genDatabaseConfigMismatchMessage(boolean txnMatch,
1479                                                     boolean roMatch,
1480                                                     boolean sdMatch,
1481                                                     boolean dwMatch,
1482                                                     boolean btCmpMatch,
1483                                                     boolean dtCmpMatch) {
1484         StringBuilder ret = new StringBuilder
1485             ("The following DatabaseConfig parameters for the\n" +
1486              "cached Database do not match the parameters for the\n" +
1487              "requested Database:\n");
1488         if (!txnMatch) {
1489             ret.append(" Transactional\n");
1490         }
1491 
1492         if (!roMatch) {
1493             ret.append(" Read-Only\n");
1494         }
1495 
1496         if (!sdMatch) {
1497             ret.append(" Sorted Duplicates\n");
1498         }
1499 
1500         if (!dwMatch) {
1501             ret.append(" Deferred Write");
1502         }
1503 
1504         if (!btCmpMatch) {
1505             ret.append(" Btree Comparator\n");
1506         }
1507 
1508         if (!dtCmpMatch) {
1509             ret.append(" Duplicate Comparator\n");
1510         }
1511 
1512         return ret.toString();
1513     }
1514 
1515     /**
1516      * Checks that this comparator can be serialized by JE.
1517      *
1518      * @throws IllegalArgumentException via setBtreeComparator and
1519      * setDuplicateComparator
1520      */
validateComparator( Comparator<byte[]> comparator, String type)1521     private Comparator<byte[]> validateComparator(
1522         Comparator<byte[]> comparator,
1523         String type)
1524         throws IllegalArgumentException {
1525 
1526         if (comparator == null) {
1527             return null;
1528         }
1529 
1530         try {
1531             DatabaseImpl.comparatorToBytes(comparator, false /*byClassName*/,
1532                                            type);
1533             return comparator;
1534         } catch (DatabaseException e) {
1535             throw new IllegalArgumentException
1536                 (type + " comparator is not valid.", e);
1537         }
1538     }
1539 
1540     /**
1541      * Checks that this comparator class can be instantiated by JE.
1542      *
1543      * @throws IllegalArgumentException via setBtreeComparator and
1544      * setDuplicateComparator
1545      */
validateComparator( Class<? extends Comparator<byte[]>> comparatorClass, String type)1546     private Comparator<byte[]> validateComparator(
1547         Class<? extends Comparator<byte[]>> comparatorClass,
1548         String type)
1549         throws IllegalArgumentException {
1550 
1551         if (comparatorClass == null) {
1552             return null;
1553         }
1554 
1555         if (!Comparator.class.isAssignableFrom(comparatorClass)) {
1556             throw new IllegalArgumentException
1557                 (comparatorClass.getName() +
1558                  " is is not valid as a " + type +
1559                  " comparator because it does not " +
1560                  " implement java.util.Comparator.");
1561         }
1562 
1563         try {
1564             return DatabaseImpl.instantiateComparator(comparatorClass, type);
1565         } catch (DatabaseException e) {
1566             throw new IllegalArgumentException
1567                 (type + " comparator is not valid. " +
1568                  "Perhaps you have not implemented a zero-parameter " +
1569                  "constructor for the comparator or the comparator class " +
1570                  "cannot be found.",
1571                  e);
1572         }
1573     }
1574 
1575     /**
1576      * Checks that this database configuration is valid for a new, non-existant
1577      * database.
1578      *
1579      * @throws IllegalArgumentException via Environment.openDatabase and
1580      * openSecondaryDatabase
1581      */
validateForNewDb()1582     void validateForNewDb()
1583         throws DatabaseException {
1584 
1585         if (readOnly) {
1586             throw new IllegalArgumentException
1587                 ("DatabaseConfig.setReadOnly() must be set to false " +
1588                  "when creating a Database");
1589         }
1590 
1591         if (transactional && deferredWrite) {
1592             throw new IllegalArgumentException
1593                 ("deferredWrite mode is not supported for transactional " +
1594                  "databases");
1595         }
1596     }
1597 
1598     /**
1599      * For unit tests, checks that the database configuration attributes that
1600      * are saved persistently are equal.
1601      */
persistentEquals(DatabaseConfig other)1602     boolean persistentEquals(DatabaseConfig other) {
1603         if (sortedDuplicates != other.sortedDuplicates) {
1604             return false;
1605         }
1606 
1607         if (temporary != other.temporary) {
1608             return false;
1609         }
1610 
1611         if (replicated != other.replicated) {
1612             return false;
1613         }
1614 
1615         if (nodeMaxEntries != other.nodeMaxEntries) {
1616             return false;
1617         }
1618 
1619         if (((btreeComparator == null) && (other.btreeComparator != null)) ||
1620             ((btreeComparator != null) && (other.btreeComparator == null))) {
1621             return false;
1622         }
1623 
1624         if (btreeComparator != null) {
1625             if (btreeComparator.getClass() !=
1626                 other.btreeComparator.getClass()) {
1627             return false;
1628         }
1629         }
1630 
1631         if (((duplicateComparator == null) &&
1632              (other.duplicateComparator != null)) ||
1633             ((duplicateComparator != null) &&
1634              (other.duplicateComparator == null))) {
1635             return false;
1636         }
1637 
1638         if ((duplicateComparator != null)) {
1639             if (duplicateComparator.getClass() !=
1640                 other.duplicateComparator.getClass()) {
1641                 return false;
1642         }
1643         }
1644 
1645         return true;
1646     }
1647 
1648     /**
1649      * Perform validations at database open time on the completed DbConfig
1650      * object. Inter-attribute checks are done here.
1651      */
validateOnDbOpen(String databaseName, boolean dbIsReplicated)1652     void validateOnDbOpen(String databaseName,
1653                           boolean dbIsReplicated) {
1654 
1655         if ((getDeferredWrite() && getTemporary()) ||
1656             (getDeferredWrite() && getTransactional()) ||
1657             (getTemporary() && getTransactional())) {
1658             throw new IllegalArgumentException
1659                 ("Attempted to open Database " + databaseName +
1660                  " and two ore more of the following exclusive properties" +
1661                  " are true: deferredWrite, temporary, transactional");
1662         }
1663 
1664         if ((triggers != null) && (triggers.size() > 0)) {
1665 
1666             final boolean replicatedTriggers = checkTriggers(triggers);
1667             if (dbIsReplicated && !replicatedTriggers) {
1668                 throw new IllegalArgumentException
1669                     ("For a replicated Database, triggers must implement " +
1670                      ReplicatedDatabaseTrigger.class.getName());
1671             }
1672         }
1673     }
1674 
1675     /**
1676      * Checks that the triggers in the list have consistent definitions.
1677      *
1678      * @param triggerList the list of triggers to be checked
1679      *
1680      * @return true if the list consists of just replicated triggers, false if
1681      * it consists entirely of non-replicated triggers.
1682      *
1683      * @throws IllegalArgumentException if the list had triggers with duplicate
1684      * names or the types were not consistent.
1685      */
checkTriggers(List<Trigger> triggerList)1686     boolean checkTriggers(List<Trigger> triggerList) {
1687 
1688         final boolean replicatedTrigger =
1689             triggerList.get(0) instanceof ReplicatedDatabaseTrigger;
1690 
1691         final Set<String> triggerNames = new HashSet<String>();
1692 
1693         for (Trigger trigger : triggerList) {
1694 
1695             /*
1696              * Note that we do not disallow the unsupported PersistentTrigger
1697              * or ReplicatedDatabaseTrigger intefaces here, to enable the
1698              * continued testing of these partially implemented features.
1699              *
1700             if (trigger instanceof PersistentTrigger) {
1701                 throw new IllegalArgumentException
1702                     ("PeristentTrigger not supported: " + trigger.getName());
1703             }
1704             */
1705 
1706             if (!triggerNames.add(trigger.getName())) {
1707                 throw new IllegalArgumentException
1708                     ("Duplicate trigger name:" + trigger.getName());
1709             }
1710             if (replicatedTrigger !=
1711                 (trigger instanceof ReplicatedDatabaseTrigger)) {
1712                 throw new IllegalArgumentException
1713                     ("Conflicting trigger types in list:" + triggerList);
1714             }
1715         }
1716         return replicatedTrigger;
1717     }
1718 
1719     /**
1720      * Combine the per-Database handle and Database-wide properties for a
1721      * database handle.
1722      *
1723      * @param dbImpl the underlying DatabaseImpl for a database handle, which
1724      * provides the Database-wide properties
1725      *
1726      * @param dbHandleConfig DatabaseConfig field for the same database handle,
1727      * which provides the per-Database properties.
1728      *
1729      * @return a DatabaseConfig which includes the correct Database-wide and
1730      * per-Database handle properties.
1731      */
combineConfig(DatabaseImpl dbImpl, DatabaseConfig dbHandleConfig)1732     static DatabaseConfig combineConfig(DatabaseImpl dbImpl,
1733                                         DatabaseConfig dbHandleConfig) {
1734 
1735         DatabaseConfig showConfig = dbHandleConfig.cloneConfig();
1736 
1737         /*
1738          * Set the Database-wide properties from the DatabaseImpl, since they
1739          * might have changed from other database handles.
1740          *
1741          * Note: sorted duplicates, temporary and replicated attributes are not
1742          * mutable and were checked at handle creation to make sure these
1743          * properties in dbHandleConfig are consistent with
1744          * DatabaseImpl. They're still set here in case the useExistingConfig
1745          * property is set, and those field were not initialized.
1746          */
1747         if (dbImpl != null) {
1748             /* mutable, persistent, database wide attributes. */
1749             showConfig.setBtreeComparatorInternal
1750                 (dbImpl.getBtreeComparator(),
1751                  dbImpl.getBtreeComparatorByClass());
1752             showConfig.setDuplicateComparatorInternal
1753                 (dbImpl.getDuplicateComparator(),
1754                  dbImpl.getDuplicateComparatorByClass());
1755             showConfig.setKeyPrefixing(dbImpl.getKeyPrefixing());
1756             showConfig.setNodeMaxEntries(dbImpl.getNodeMaxTreeEntries());
1757             showConfig.setTriggers(dbImpl.getTriggers());
1758 
1759             /* mutable, but non-persistent attributes. */
1760             showConfig.setTransactional(dbImpl.isTransactional());
1761             showConfig.setDeferredWrite(dbImpl.isDurableDeferredWrite());
1762 
1763             /* not mutable, but initialized in the showConfig. */
1764             showConfig.setReplicated(dbImpl.isReplicated());
1765             showConfig.setSortedDuplicates(dbImpl.getSortedDuplicates());
1766             showConfig.setTemporary(dbImpl.isTemporary());
1767         }
1768 
1769         return showConfig;
1770     }
1771 
1772     /**
1773      * Returns the values for each configuration attribute.
1774      *
1775      * @return the values for each configuration attribute.
1776      */
1777     @Override
toString()1778     public String toString() {
1779         return "allowCreate=" + allowCreate +
1780             "\nexclusiveCreate=" + exclusiveCreate +
1781             "\ntransactional=" + transactional +
1782             "\nreadOnly=" + readOnly +
1783             "\nsortedDuplicates=" + sortedDuplicates +
1784             "\ndeferredWrite=" + deferredWrite +
1785             "\ntemporary=" + temporary +
1786             "\nkeyPrefixing=" + keyPrefixing +
1787             "\n";
1788     }
1789 }
1790