summaryrefslogtreecommitdiff
path: root/lang/csharp/src/SecondaryRecnoDatabaseConfig.cs
blob: 63f8201e4893af67d5b16bcf9512ccf04ebeb885 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
/*-
 * See the file LICENSE for redistribution information.
 *
 * Copyright (c) 2009, 2015 Oracle and/or its affiliates.  All rights reserved.
 *
 */
using System;
using System.Collections.Generic;
using System.Text;

namespace BerkeleyDB {
    /// <summary>
    /// A class representing configuration parameters for
    /// <see cref="RecnoDatabase"/>
    /// </summary>
    public class SecondaryRecnoDatabaseConfig : SecondaryDatabaseConfig {
        /* Fields for DB->set_flags() */
        /// <summary>
        /// Cause the logical record numbers to be mutable, and change as
        /// records are added to and deleted from the database.
        /// </summary>
        /// <remarks>
        /// <para>
        /// For example, the deletion of record number 4 causes records numbered
        /// 5 and greater to be renumbered downward by one. If a cursor was
        /// positioned as record number 4 before the deletion, it refers to
        /// the new record number 4, if any such record exists, after the
        /// deletion. If a cursor was positioned after record number 4 before
        /// the deletion, it is shifted downward one logical record,
        /// continuing to refer to the same record as it did before.
        /// </para>
        /// <para>
        /// Using <see cref="Database.Put"/> or <see cref="Cursor.Put"/> to
        /// create new records causes the creation of multiple records if
        /// the record number is more than one greater than the largest record
        /// currently in the database. For example, creating record 28 when
        /// record 25 was previously the last record in the database
        /// creates records 26 and 27 as well as 28. Attempts to retrieve records
        /// that were created in this manner throw a
        /// <see cref="KeyEmptyException"/>.
        /// </para>
        /// <para>
        /// If a created record is not at the end of the database, all records
        /// following the new record are automatically renumbered upward by
        /// one. For example, the creation of a new record numbered 8 causes
        /// records numbered 8 and greater to be renumbered upward by one. If a
        /// cursor was positioned to record number 8 or greater before the
        /// insertion, it is shifted upward one logical record, continuing
        /// to refer to the same record as it did before.
        /// </para>
        /// <para>
        /// For these reasons, concurrent access to a
        /// <see cref="SecondaryRecnoDatabase"/> with this setting specified may
        /// be largely meaningless, although it is supported.
        /// </para>
        /// <para>
        /// If the database already exists, this setting must be the same as the
        /// existing database or an exception is thrown.
        /// </para>
        /// </remarks>
        public bool Renumber;
        /// <summary>
        /// If true, any <see cref="BackingFile"/> file is read in its
        /// entirety when <see cref="SecondaryRecnoDatabase.Open"/> is called.
        /// If false, <see cref="BackingFile"/> may be read lazily. 
        /// </summary>
        public bool Snapshot;
        internal new uint flags {
            get {
                uint ret = base.flags;
                ret |= Renumber ? Internal.DbConstants.DB_RENUMBER : 0;
                ret |= Snapshot ? Internal.DbConstants.DB_SNAPSHOT : 0;
                return ret;
            }
        }

        /// <summary>
        /// The policy for how to handle database creation.
        /// </summary>
        /// <remarks>
        /// If the database does not already exist and
        /// <see cref="CreatePolicy.NEVER"/> is set,
        /// <see cref="SecondaryRecnoDatabase.Open"/> fails.
        /// </remarks>
        public CreatePolicy Creation;
        internal new uint openFlags {
            get {
                uint flags = base.openFlags;
                flags |= (uint)Creation;
                return flags;
            }
        }


        internal bool delimiterIsSet;
        private int delim;
        /// <summary>
        /// The delimiting byte used to mark the end of a record in
        /// <see cref="BackingFile"/>.
        /// </summary>
        /// <remarks>
        /// <para>
        /// This byte is used for variable length records if
        /// <see cref="BackingFile"/> is set. If <see cref="BackingFile"/> is
        /// specified and no delimiting byte was specified, newline characters
        /// (ASCII 0x0a) are interpreted as end-of-record markers.
        /// </para>
        /// <para>
        /// If the database already exists, this setting is ignored.
        /// </para>
        /// </remarks>
        public int Delimiter {
            get { return delim; }
            set {
                delimiterIsSet = true;
                delim = value;
            }
        }

        internal bool lengthIsSet;
        private uint len;
        /// <summary>
        /// Specify that the records are fixed-length, not byte-delimited, and
        /// are of length Length. 
        /// </summary>
        /// <remarks>
        /// <para>
        /// Any records added to the database that are less than Length bytes
        /// long are automatically padded (see <see cref="PadByte"/> for more
        /// information).
        /// </para>
        /// <para>
        /// Any attempt to insert records into the database that are greater
        /// than Length bytes long cause the call to fail immediately and
        /// return an error. 
        /// </para>
        /// <para>
        /// If the database already exists, this setting is ignored.
        /// </para>
        /// </remarks>
        public uint Length {
            get { return len; }
            set {
                lengthIsSet = true;
                len = value;
            }
        }

        internal bool padIsSet;
        private int pad;
        /// <summary>
        /// The padding character for short, fixed-length records.
        /// </summary>
        /// <remarks>
        /// <para>
        /// If no pad character is specified, space characters (ASCII
        /// 0x20) are used for padding.
        /// </para>
        /// <para>
        /// If the database already exists, this setting is ignored.
        /// </para>
        /// </remarks>
        public int PadByte {
            get { return pad; }
            set {
                padIsSet = true;
                pad = value;
            }
        }

        /// <summary>
        /// The underlying source file for the Recno access method.
        /// </summary>
        /// <remarks>
        /// <para>
        /// The purpose of the source file is to provide fast access and
        /// modification to databases that are normally stored as flat text
        /// files.
        /// </para>
        /// <para>
        /// The source parameter specifies an underlying flat text database file
        /// that is read to initialize a transient record number index. In the
        /// case of variable length records, the records are separated, as
        /// specified by <see cref="Delimiter"/>. For example, standard UNIX
        /// byte stream files can be interpreted as a sequence of variable
        /// length records separated by newline characters.
        /// </para>
        /// <para>
        /// In addition, when cached data would normally be written back to the
        /// underlying database file (for example,
        /// <see cref="BaseDatabase.Close"/> or
        /// <see cref="BaseDatabase.Sync"/>), the in-memory copy of the
        /// database is written back to the source file.
        /// </para>
        /// <para>
        /// By default, the backing source file is read lazily; records
        /// are not read from the file until they are requested by the
        /// application. If multiple processes (not threads) are accessing a
        /// Recno database concurrently, and are either inserting or deleting
        /// records, the backing source file must be read in its entirety before
        /// more than a single process accesses the database, and only that
        /// process should specify the backing source file as part of the
        /// <see cref="SecondaryRecnoDatabase.Open"/> call. See
        /// <see cref="Snapshot"/> for more information.
        /// </para>
        /// <para>
        /// Reading and writing the backing source file specified by source
        /// cannot be transaction-protected because it involves filesystem
        /// operations that are not part of the Db transaction methodology. For
        /// this reason, if a temporary database is used to hold the records, it
        /// is possible to lose the contents of the source file, for example, if
        /// the system crashes at the right instant. If a file is used to hold
        /// the database, normal database recovery on that file can be used to
        /// prevent information loss, although it is still possible that the
        /// contents of source become lost if the system crashes.
        /// </para>
        /// <para>
        /// The source file must already exist (but may be zero-length) when 
        /// <see cref="SecondaryRecnoDatabase.Open"/> is called.
        /// </para>
        /// <para>
        /// It is not an error to specify a read-only source file when creating
        /// a database, nor is it an error to modify the resulting database.
        /// However, any attempt to write the changes to the backing source file
        /// using either the <see cref="BaseDatabase.Sync"/> or
        /// <see cref="BaseDatabase.Close"/> methods fail, of course.
        /// Use <see cref="BaseDatabase.Close(bool)"/> to stop it from
        /// attempting to write the changes to the backing file; instead, they
        /// are silently discarded.
        /// </para>
        /// <para>
        /// For all of the previous reasons, the source file is generally used
        /// to specify databases that are read-only for Berkeley DB
        /// applications; and that are either generated on the fly by software
        /// tools or modified using a different mechanism — for example, a text
        /// editor.
        /// </para>
        /// <para>
        /// If the database already exists, BackingFile must be the same as that
        /// historically used to create the database or corruption can occur.
        /// </para>
        /// </remarks>
        public string BackingFile;

        /// <summary>
        /// Instantiate a new SecondaryRecnoDatabaseConfig object
        /// </summary>
        public SecondaryRecnoDatabaseConfig(
            Database PrimaryDB, SecondaryKeyGenDelegate KeyGenFunc)
            : base(PrimaryDB, KeyGenFunc) {
            Renumber = false;
            Snapshot = false;
            delimiterIsSet = false;
            lengthIsSet = false;
            padIsSet = false;
            BackingFile = null;
            DbType = DatabaseType.RECNO;
        }
    }
}