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;
10using BerkeleyDB.Internal;
11
12namespace BerkeleyDB {
13    /// <summary>
14    /// A class representing a RecnoDatabase. The Recno format supports fixed-
15    /// or variable-length records, accessed sequentially or by logical record
16    /// number, and optionally backed by a flat text file.
17    /// </summary>
18    public class SecondaryRecnoDatabase : SecondaryDatabase {
19
20        #region Constructors
21        internal SecondaryRecnoDatabase(DatabaseEnvironment env, uint flags)
22            : base(env, flags) { }
23
24        private void Config(SecondaryRecnoDatabaseConfig cfg) {
25            base.Config((SecondaryDatabaseConfig)cfg);
26            db.set_flags(cfg.flags);
27
28            if (cfg.delimiterIsSet)
29                db.set_re_delim(cfg.Delimiter);
30            if (cfg.lengthIsSet)
31                db.set_re_len(cfg.Length);
32            if (cfg.padIsSet)
33                db.set_re_pad(cfg.PadByte);
34            if (cfg.BackingFile != null)
35                db.set_re_source(cfg.BackingFile);
36        }
37
38        /// <summary>
39        /// Instantiate a new SecondaryRecnoDatabase object, open the
40        /// database represented by <paramref name="Filename"/> and associate
41        /// the database with the
42        /// <see cref="SecondaryDatabaseConfig.Primary">primary index</see>.
43        /// </summary>
44        /// <remarks>
45        /// <para>
46        /// If <paramref name="Filename"/> is null, the database is strictly
47        /// temporary and cannot be opened by any other thread of control, thus
48        /// the database can only be accessed by sharing the single database
49        /// object that created it, in circumstances where doing so is safe.
50        /// </para>
51        /// <para>
52        /// If <see cref="DatabaseConfig.AutoCommit"/> is set, the operation
53        /// will be implicitly transaction protected. Note that transactionally
54        /// protected operations on a datbase object requires the object itself
55        /// be transactionally protected during its open.
56        /// </para>
57        /// </remarks>
58        /// <param name="Filename">
59        /// The name of an underlying file that will be used to back the
60        /// database. In-memory databases never intended to be preserved on disk
61        /// may be created by setting this parameter to null.
62        /// </param>
63        /// <param name="cfg">The database's configuration</param>
64        /// <returns>A new, open database object</returns>
65        public static SecondaryRecnoDatabase Open(
66            string Filename, SecondaryRecnoDatabaseConfig cfg) {
67            return Open(Filename, null, cfg, null);
68        }
69        /// <summary>
70        /// Instantiate a new SecondaryRecnoDatabase object, open the
71        /// database represented by <paramref name="Filename"/> and associate
72        /// the database with the
73        /// <see cref="SecondaryDatabaseConfig.Primary">primary index</see>.
74        /// </summary>
75        /// <remarks>
76        /// <para>
77        /// If both <paramref name="Filename"/> and
78        /// <paramref name="DatabaseName"/> are null, the database is strictly
79        /// temporary and cannot be opened by any other thread of control, thus
80        /// the database can only be accessed by sharing the single database
81        /// object that created it, in circumstances where doing so is safe. If
82        /// <paramref name="Filename"/> is null and
83        /// <paramref name="DatabaseName"/> is non-null, the database can be
84        /// opened by other threads of control and will be replicated to client
85        /// sites in any replication group.
86        /// </para>
87        /// <para>
88        /// If <see cref="DatabaseConfig.AutoCommit"/> is set, the operation
89        /// will be implicitly transaction protected. Note that transactionally
90        /// protected operations on a datbase object requires the object itself
91        /// be transactionally protected during its open.
92        /// </para>
93        /// </remarks>
94        /// <param name="Filename">
95        /// The name of an underlying file that will be used to back the
96        /// database. In-memory databases never intended to be preserved on disk
97        /// may be created by setting this parameter to null.
98        /// </param>
99        /// <param name="DatabaseName">
100        /// This parameter allows applications to have multiple databases in a
101        /// single file. Although no DatabaseName needs to be specified, it is
102        /// an error to attempt to open a second database in a file that was not
103        /// initially created using a database name.
104        /// </param>
105        /// <param name="cfg">The database's configuration</param>
106        /// <returns>A new, open database object</returns>
107        public static SecondaryRecnoDatabase Open(string Filename,
108            string DatabaseName, SecondaryRecnoDatabaseConfig cfg) {
109            return Open(Filename, DatabaseName, cfg, null);
110        }
111        /// <summary>
112        /// Instantiate a new SecondaryRecnoDatabase object, open the
113        /// database represented by <paramref name="Filename"/> and associate
114        /// the database with the
115        /// <see cref="SecondaryDatabaseConfig.Primary">primary index</see>.
116        /// </summary>
117        /// <remarks>
118        /// <para>
119        /// If <paramref name="Filename"/> is null, the database is strictly
120        /// temporary and cannot be opened by any other thread of control, thus
121        /// the database can only be accessed by sharing the single database
122        /// object that created it, in circumstances where doing so is safe.
123        /// </para>
124        /// <para>
125        /// If <paramref name="txn"/> is null, but
126        /// <see cref="DatabaseConfig.AutoCommit"/> is set, the operation will
127        /// be implicitly transaction protected. Note that transactionally
128        /// protected operations on a datbase object requires the object itself
129        /// be transactionally protected during its open. Also note that the
130        /// transaction must be committed before the object is closed.
131        /// </para>
132        /// </remarks>
133        /// <param name="Filename">
134        /// The name of an underlying file that will be used to back the
135        /// database. In-memory databases never intended to be preserved on disk
136        /// may be created by setting this parameter to null.
137        /// </param>
138        /// <param name="cfg">The database's configuration</param>
139        /// <param name="txn">
140        /// If the operation is part of an application-specified transaction,
141        /// <paramref name="txn"/> is a Transaction object returned from
142        /// <see cref="DatabaseEnvironment.BeginTransaction"/>; if
143        /// the operation is part of a Berkeley DB Concurrent Data Store group,
144        /// <paramref name="txn"/> is a handle returned from
145        /// <see cref="DatabaseEnvironment.BeginCDSGroup"/>; otherwise null.
146        /// </param>
147        /// <returns>A new, open database object</returns>
148        public static SecondaryRecnoDatabase Open(string Filename,
149            SecondaryRecnoDatabaseConfig cfg, Transaction txn) {
150            return Open(Filename, null, cfg, txn);
151        }
152        /// <summary>
153        /// Instantiate a new SecondaryRecnoDatabase object, open the
154        /// database represented by <paramref name="Filename"/> and associate
155        /// the database with the
156        /// <see cref="SecondaryDatabaseConfig.Primary">primary index</see>.
157        /// </summary>
158        /// <remarks>
159        /// <para>
160        /// If both <paramref name="Filename"/> and
161        /// <paramref name="DatabaseName"/> are null, the database is strictly
162        /// temporary and cannot be opened by any other thread of control, thus
163        /// the database can only be accessed by sharing the single database
164        /// object that created it, in circumstances where doing so is safe. If
165        /// <paramref name="Filename"/> is null and
166        /// <paramref name="DatabaseName"/> is non-null, the database can be
167        /// opened by other threads of control and will be replicated to client
168        /// sites in any replication group.
169        /// </para>
170        /// <para>
171        /// If <paramref name="txn"/> is null, but
172        /// <see cref="DatabaseConfig.AutoCommit"/> is set, the operation will
173        /// be implicitly transaction protected. Note that transactionally
174        /// protected operations on a datbase object requires the object itself
175        /// be transactionally protected during its open. Also note that the
176        /// transaction must be committed before the object is closed.
177        /// </para>
178        /// </remarks>
179        /// <param name="Filename">
180        /// The name of an underlying file that will be used to back the
181        /// database. In-memory databases never intended to be preserved on disk
182        /// may be created by setting this parameter to null.
183        /// </param>
184        /// <param name="DatabaseName">
185        /// This parameter allows applications to have multiple databases in a
186        /// single file. Although no DatabaseName needs to be specified, it is
187        /// an error to attempt to open a second database in a file that was not
188        /// initially created using a database name.
189        /// </param>
190        /// <param name="cfg">The database's configuration</param>
191        /// <param name="txn">
192        /// If the operation is part of an application-specified transaction,
193        /// <paramref name="txn"/> is a Transaction object returned from
194        /// <see cref="DatabaseEnvironment.BeginTransaction"/>; if
195        /// the operation is part of a Berkeley DB Concurrent Data Store group,
196        /// <paramref name="txn"/> is a handle returned from
197        /// <see cref="DatabaseEnvironment.BeginCDSGroup"/>; otherwise null.
198        /// </param>
199        /// <returns>A new, open database object</returns>
200        public static SecondaryRecnoDatabase Open(string Filename,
201            string DatabaseName,
202            SecondaryRecnoDatabaseConfig cfg, Transaction txn) {
203            SecondaryRecnoDatabase ret = new SecondaryRecnoDatabase(cfg.Env, 0);
204            ret.Config(cfg);
205            ret.db.open(Transaction.getDB_TXN(txn), Filename,
206                DatabaseName, cfg.DbType.getDBTYPE(), cfg.openFlags, 0);
207            ret.isOpen = true;
208            ret.doAssocRef =
209                new BDB_AssociateDelegate(SecondaryDatabase.doAssociate);
210            cfg.Primary.db.associate(Transaction.getDB_TXN(null),
211                ret.db, ret.doAssocRef, cfg.assocFlags);
212
213            if (cfg.ForeignKeyDatabase != null) {
214                if (cfg.OnForeignKeyDelete == ForeignKeyDeleteAction.NULLIFY)
215                    ret.doNullifyRef =
216                        new BDB_AssociateForeignDelegate(doNullify);
217                else
218                    ret.doNullifyRef = null;
219                cfg.ForeignKeyDatabase.db.associate_foreign(
220                    ret.db, ret.doNullifyRef, cfg.foreignFlags);
221            }
222            return ret;
223        }
224
225        #endregion Constructors
226
227        #region Properties
228        /// <summary>
229        /// If true, the logical record numbers are mutable, and change as
230        /// records are added to and deleted from the database.
231        /// </summary>
232        public bool Renumber {
233            get {
234                uint flags = 0;
235                db.get_flags(ref flags);
236                return (flags & DbConstants.DB_RENUMBER) != 0;
237            }
238        }
239        /// <summary>
240        /// If true, any <see cref="BackingFile"/> file will be read in its
241        /// entirety when <see cref="Open"/> is called. If false,
242        /// <see cref="BackingFile"/> may be read lazily.
243        /// </summary>
244        public bool Snapshot {
245            get {
246                uint flags = 0;
247                db.get_flags(ref flags);
248                return (flags & DbConstants.DB_SNAPSHOT) != 0;
249            }
250        }
251        /// <summary>
252        /// The delimiting byte used to mark the end of a record in
253        /// <see cref="BackingFile"/>.
254        /// </summary>
255        public int Delimiter {
256            get {
257                int ret = 0;
258                db.get_re_delim(ref ret);
259                return ret;
260            }
261        }
262        /// <summary>
263        /// If using fixed-length, not byte-delimited records, the length of the
264        /// records.
265        /// </summary>
266        public uint Length {
267            get {
268                uint ret = 0;
269                db.get_re_len(ref ret);
270                return ret;
271            }
272        }
273        /// <summary>
274        /// The padding character for short, fixed-length records.
275        /// </summary>
276        public int PadByte {
277            get {
278                int ret = 0;
279                db.get_re_pad(ref ret);
280                return ret;
281            }
282        }
283        /// <summary>
284        /// The underlying source file for the Recno access method.
285        /// </summary>
286        public string BackingFile {
287            get {
288                string ret = "";
289                db.get_re_source(ref ret);
290                return ret;
291            }
292        }
293        #endregion Properties
294
295    }
296}
297