1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 2009 Oracle.  All rights reserved.
5 *
6 */
7using System;
8using System.Collections.Generic;
9using System.Text;
10
11using BerkeleyDB.Internal;
12
13namespace BerkeleyDB {
14    /// <summary>
15    /// A class representing configuration parameters for
16    /// <see cref="BTreeDatabase"/>
17    /// </summary>
18    public class BTreeDatabaseConfig : DatabaseConfig {
19        /* Fields for DB->set_flags() */
20        /// <summary>
21        /// Policy for duplicate data items in the database; that is, insertion
22        /// when the key of the key/data pair being inserted already exists in
23        /// the database will be successful.
24        /// </summary>
25        /// <remarks>
26        /// <para>The ordering of duplicates in the database for
27        /// <see cref="DuplicatesPolicy.UNSORTED"/> is determined by the order
28        /// of insertion, unless the ordering is otherwise specified by use of a
29        /// cursor operation or a duplicate sort function. The ordering of
30        /// duplicates in the database for
31        /// <see cref="DuplicatesPolicy.SORTED"/> is determined by the
32        /// duplicate comparison function. If the application does not specify a
33        /// comparison function using
34        /// <see cref="DuplicateCompare"/>, a default lexical
35        /// comparison will be used.
36        /// </para>
37        /// <para>
38        /// <see cref="DuplicatesPolicy.SORTED"/> is preferred to
39        /// <see cref="DuplicatesPolicy.UNSORTED"/> for performance reasons.
40        /// <see cref="DuplicatesPolicy.UNSORTED"/> should only be used by
41        /// applications wanting to order duplicate data items manually.
42        /// </para>
43        /// <para>
44        /// If the database already exists, the value of Duplicates must be the
45        /// same as the existing database or an error will be returned.
46        /// </para>
47        /// <para>
48        /// It is an error to specify <see cref="UseRecordNumbers"/> and
49        /// anything other than <see cref="DuplicatesPolicy.NONE"/>.
50        /// </para>
51        /// </remarks>
52        public DuplicatesPolicy Duplicates;
53        /// <summary>
54        /// Turn reverse splitting in the Btree on or off.
55        /// </summary>
56        /// <remarks>
57        /// As pages are emptied in a database, the Berkeley DB Btree
58        /// implementation attempts to coalesce empty pages into higher-level
59        /// pages in order to keep the database as small as possible and
60        /// minimize search time. This can hurt performance in applications with
61        /// cyclical data demands; that is, applications where the database
62        /// grows and shrinks repeatedly. For example, because Berkeley DB does
63        /// page-level locking, the maximum level of concurrency in a database
64        /// of two pages is far smaller than that in a database of 100 pages, so
65        /// a database that has shrunk to a minimal size can cause severe
66        /// deadlocking when a new cycle of data insertion begins.
67        /// </remarks>
68        public bool NoReverseSplitting;
69        /// <summary>
70        /// If true, support retrieval from the Btree using record numbers.
71        /// </summary>
72        /// <remarks>
73        /// <para>
74        /// Logical record numbers in Btree databases are mutable in the face of
75        /// record insertion or deletion. See
76        /// <see cref="RecnoDatabaseConfig.Renumber"/> for further discussion.
77        /// </para>
78		/// <para>
79        /// Maintaining record counts within a Btree introduces a serious point
80        /// of contention, namely the page locations where the record counts are
81        /// stored. In addition, the entire database must be locked during both
82        /// insertions and deletions, effectively single-threading the database
83        /// for those operations. Specifying UseRecordNumbers can result in
84        /// serious performance degradation for some applications and data sets.
85        /// </para>
86		/// <para>
87        /// It is an error to specify <see cref="UseRecordNumbers"/> and
88        /// anything other than <see cref="DuplicatesPolicy.NONE"/>.
89        /// </para>
90		/// <para>
91        /// If the database already exists, the value of UseRecordNumbers must
92        /// be the same as the existing database or an error will be returned.
93        /// </para>
94        /// </remarks>
95        public bool UseRecordNumbers;
96        internal new uint flags {
97            get {
98                uint ret = base.flags;
99                ret |= (uint)Duplicates;
100                ret |= NoReverseSplitting ?
101                    Internal.DbConstants.DB_REVSPLITOFF : 0;
102                ret |= UseRecordNumbers ? Internal.DbConstants.DB_RECNUM : 0;
103                return ret;
104            }
105        }
106
107        /// <summary>
108        /// The policy for how to handle database creation.
109        /// </summary>
110        /// <remarks>
111        /// If the database does not already exist and
112        /// <see cref="CreatePolicy.NEVER"/> is set,
113        /// <see cref="BTreeDatabase.Open"/> will fail.
114        /// </remarks>
115        public CreatePolicy Creation;
116        internal new uint openFlags {
117            get {
118                uint flags = base.openFlags;
119                flags |= (uint)Creation;
120                return flags;
121            }
122        }
123
124        /// <summary>
125        /// The Btree key comparison function.
126        /// </summary>
127        /// <remarks>
128        /// <para>
129        /// The comparison function is called whenever it is necessary to
130        /// compare a key specified by the application with a key currently
131        /// stored in the tree.
132        /// </para>
133		/// <para>
134        /// If no comparison function is specified, the keys are compared
135        /// lexically, with shorter keys collating before longer keys.
136        /// </para>
137		/// <para>
138        /// If the database already exists, the comparison function must be the
139        /// same as that historically used to create the database or corruption
140        /// can occur.
141        /// </para>
142        /// </remarks>
143        public EntryComparisonDelegate BTreeCompare;
144        /// <summary>
145        /// The Btree prefix function.
146        /// </summary>
147        /// <remarks>
148        /// <para>
149        /// The prefix function is used to determine the amount by which keys
150        /// stored on the Btree internal pages can be safely truncated without
151        /// losing their uniqueness. See the Btree prefix comparison section of
152        /// the Berkeley DB Reference Guide for more details about how this
153        /// works. The usefulness of this is data-dependent, but can produce
154        /// significantly reduced tree sizes and search times in some data sets.
155        /// </para>
156		/// <para>
157        /// If no prefix function or key comparison function is specified by the
158        /// application, a default lexical comparison function is used as the
159        /// prefix function. If no prefix function is specified and
160        /// <see cref="BTreeCompare"/> is specified, no prefix function is
161        /// used. It is an error to specify a prefix function without also
162        /// specifying <see cref="BTreeCompare"/>.
163        /// </para>
164		/// <para>
165        /// If the database already exists, the prefix function must be the
166        /// same as that historically used to create the database or corruption
167        /// can occur.
168        /// </para>
169        /// </remarks>
170        public EntryComparisonDelegate BTreePrefixCompare;
171        /// <summary>
172        /// The duplicate data item comparison function.
173        /// </summary>
174        /// <remarks>
175        /// <para>
176        /// The comparison function is called whenever it is necessary to
177        /// compare a data item specified by the application with a data item
178        /// currently stored in the database. Setting DuplicateCompare implies
179        /// setting <see cref="Duplicates"/> to
180        /// <see cref="DuplicatesPolicy.SORTED"/>.
181        /// </para>
182		/// <para>
183        /// If no comparison function is specified, the data items are compared
184        /// lexically, with shorter data items collating before longer data
185        /// items.
186        /// </para>
187		/// <para>
188        /// If the database already exists when
189        /// <see cref="BTreeDatabase.Open"/> is called, the
190        /// delegate must be the same as that historically used to create the
191        /// database or corruption can occur.
192        /// </para>
193        /// </remarks>
194        public EntryComparisonDelegate DuplicateCompare;
195
196	internal bool compressionIsSet;
197        private BTreeCompressDelegate compressFunc;
198        /// <summary>
199        /// The compression function used to store key/data pairs in the
200        /// database.
201        /// </summary>
202        public BTreeCompressDelegate Compress { get { return compressFunc; } }
203        private BTreeDecompressDelegate decompressFunc;
204        /// <summary>
205        /// The decompression function used to retrieve key/data pairs from the
206        /// database.
207        /// </summary>
208        public BTreeDecompressDelegate Decompress {
209            get { return decompressFunc; }
210        }
211        /// <summary>
212        /// Enable compression of the key/data pairs stored in the database,
213        /// using the default compression and decompression functions.
214        /// </summary>
215        /// <remarks>
216        /// The default functions perform prefix compression on keys, and prefix
217        /// compression on data items for duplicate keys.
218        /// </remarks>
219        public void SetCompression() {
220            compressionIsSet = true;
221            compressFunc = null;
222            decompressFunc = null;
223        }
224        /// <summary>
225        /// Enable compression of the key/data pairs stored in the database,
226        /// using the specified compression and decompression functions.
227        /// </summary>
228        /// <param name="compression">The compression function</param>
229        /// <param name="decompression">The decompression function</param>
230        public void SetCompression(BTreeCompressDelegate compression,
231            BTreeDecompressDelegate decompression) {
232            compressionIsSet = true;
233            compressFunc = compression;
234            decompressFunc = decompression;
235        }
236
237        internal bool minkeysIsSet;
238        private uint minKeys;
239        /// <summary>
240        /// The minimum number of key/data pairs intended to be stored on any
241        /// single Btree leaf page.
242        /// </summary>
243        /// <remarks>
244        /// <para>
245        /// This value is used to determine if key or data items will be stored
246        /// on overflow pages instead of Btree leaf pages. For more information
247        /// on the specific algorithm used, see the Berkeley DB Reference Guide.
248        /// The value specified must be at least 2; if not explicitly set, a
249        /// value of 2 is used.
250        /// </para>
251		/// <para>
252        /// If the database already exists, MinKeysPerPage will be ignored.
253        /// </para>
254        /// </remarks>
255        public uint MinKeysPerPage {
256            get { return minKeys; }
257            set {
258                minkeysIsSet = true;
259                minKeys = value;
260            }
261        }
262
263        /// <summary>
264        /// Create a new BTreeDatabaseConfig object
265        /// </summary>
266        public BTreeDatabaseConfig() {
267            Duplicates = DuplicatesPolicy.NONE;
268            NoReverseSplitting = false;
269            UseRecordNumbers = false;
270
271            BTreeCompare = null;
272            BTreePrefixCompare = null;
273
274            minkeysIsSet = false;
275
276            Creation = CreatePolicy.NEVER;
277        }
278    }
279}
280