Imported Upstream version 5.3.21
[platform/upstream/libdb.git] / lang / csharp / src / BaseDatabase.cs
1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2009, 2012 Oracle and/or its affiliates.  All rights reserved.
5  *
6  */
7 using System;
8 using System.Collections.Generic;
9 using System.Text;
10 using BerkeleyDB.Internal;
11
12 namespace BerkeleyDB {
13     /// <summary>
14     /// The base class from which all database classes inherit
15     /// </summary>
16     public class BaseDatabase : IDisposable {
17         internal DB db;
18         /// <summary>
19         /// The environment that the database lies in.
20         /// </summary>
21         protected internal DatabaseEnvironment env;
22         /// <summary>
23         /// Whether the database is opened.
24         /// </summary>
25         protected internal bool isOpen;
26         private DBTCopyDelegate CopyDelegate;
27         private EntryComparisonDelegate dupCompareHandler;
28         private DatabaseFeedbackDelegate feedbackHandler;
29         private BDB_CompareDelegate doDupCompareRef;
30         private BDB_DbFeedbackDelegate doFeedbackRef;
31
32         #region Constructors
33         /// <summary>
34         /// Protected constructor
35         /// </summary>
36         /// <param name="envp">
37         /// The environment in which to create this database
38         /// </param>
39         /// <param name="flags">Flags to pass to the DB->create() method</param>
40         protected BaseDatabase(DatabaseEnvironment envp, uint flags) {
41             db = new DB(envp == null ? null : envp.dbenv, flags);
42             db.api_internal = this;
43             if (envp == null) {
44                 env = new DatabaseEnvironment(db.env());
45             } else
46                 env = envp;
47         }
48
49         /// <summary>
50         /// Create a new database object with the same underlying DB handle as
51         /// <paramref name="clone"/>.  Used during Database.Open to get an
52         /// object of the correct DBTYPE.
53         /// </summary>
54         /// <param name="clone">Database to clone</param>
55         protected BaseDatabase(BaseDatabase clone) {
56             db = clone.db;
57             clone.db = null;
58             db.api_internal = this;
59             env = clone.env;
60             clone.env = null;
61         }
62
63         internal void Config(DatabaseConfig cfg) {
64             // The cache size cannot change.
65             if (cfg.CacheSize != null)
66                 db.set_cachesize(cfg.CacheSize.Gigabytes,
67                     cfg.CacheSize.Bytes, cfg.CacheSize.NCaches);
68             if (cfg.encryptionIsSet)
69                 db.set_encrypt(
70                     cfg.EncryptionPassword, (uint)cfg.EncryptAlgorithm);
71             if (cfg.ErrorPrefix != null)
72                 ErrorPrefix = cfg.ErrorPrefix;
73             if (cfg.ErrorFeedback != null)
74                 ErrorFeedback = cfg.ErrorFeedback;
75             if (cfg.Feedback != null)
76                 Feedback = cfg.Feedback;
77
78             db.set_flags(cfg.flags);
79             if (cfg.ByteOrder != ByteOrder.MACHINE)
80                 db.set_lorder(cfg.ByteOrder.lorder);
81             if (cfg.NoWaitDbExclusiveLock == true)
82                 db.set_lk_exclusive(1);
83             else if (cfg.NoWaitDbExclusiveLock == false)
84                 db.set_lk_exclusive(0);
85             if (cfg.pagesizeIsSet)
86                 db.set_pagesize(cfg.PageSize);
87             if (cfg.Priority != CachePriority.DEFAULT)
88                 db.set_priority(cfg.Priority.priority);
89         }
90
91         /// <summary>
92         /// Protected factory method to create and open a new database object.
93         /// </summary>
94         /// <param name="Filename">The database's filename</param>
95         /// <param name="DatabaseName">The subdatabase's name</param>
96         /// <param name="cfg">The database's configuration</param>
97         /// <param name="txn">
98         /// The transaction in which to open the database
99         /// </param>
100         /// <returns>A new, open database object</returns>
101         protected static BaseDatabase Open(string Filename,
102             string DatabaseName, DatabaseConfig cfg, Transaction txn) {
103             BaseDatabase ret = new BaseDatabase(cfg.Env, 0);
104             ret.Config(cfg);
105             ret.db.open(Transaction.getDB_TXN(txn),
106                 Filename, DatabaseName, DBTYPE.DB_UNKNOWN, cfg.openFlags, 0);
107             return ret;
108         }
109         #endregion Constructor
110
111         #region Callbacks
112         private static void doFeedback(IntPtr dbp, int opcode, int percent) {
113             DB db = new DB(dbp, false);
114             db.api_internal.Feedback((DatabaseFeedbackEvent)opcode, percent);
115         }
116         #endregion Callbacks
117
118         #region Properties
119         // Sorted alpha by property name
120         /// <summary>
121         /// If true, all database modification operations based on this object
122         /// will be transactionally protected.
123         /// </summary>
124         public bool AutoCommit {
125             get {
126                 uint flags = 0;
127                 db.get_open_flags(ref flags);
128                 return (flags & DbConstants.DB_AUTO_COMMIT) != 0;
129             }
130         }
131         /// <summary>
132         /// The size of the shared memory buffer pool -- that is, the cache.
133         /// </summary>
134         public CacheInfo CacheSize {
135             get {
136                 uint gb = 0;
137                 uint b = 0;
138                 int n = 0;
139                 db.get_cachesize(ref gb, ref b, ref n);
140                 return new CacheInfo(gb, b, n);
141             }
142         }
143         /// <summary>
144         /// The CreatePolicy with which this database was opened.
145         /// </summary>
146         public CreatePolicy Creation {
147             get {
148                 uint flags = 0;
149                 db.get_open_flags(ref flags);
150                 if ((flags & DbConstants.DB_EXCL) != 0)
151                     return CreatePolicy.ALWAYS;
152                 else if ((flags & DbConstants.DB_CREATE) != 0)
153                     return CreatePolicy.IF_NEEDED;
154                 else
155                     return CreatePolicy.NEVER;
156             }
157         }
158         /// <summary>
159         /// The name of this database, if it has one.
160         /// </summary>
161         public string DatabaseName {
162             get {
163                 string tmp = null;
164                 string ret = null;
165                 db.get_dbname(out tmp, out ret);                
166                 return ret;
167             }
168         }
169         /// <summary>
170         /// If true, do checksum verification of pages read into the cache from
171         /// the backing filestore.
172         /// </summary>
173         /// <remarks>
174         /// Berkeley DB uses the SHA1 Secure Hash Algorithm if encryption is
175         /// configured and a general hash algorithm if it is not.
176         /// </remarks>
177         public bool DoChecksum {
178             get {
179                 uint flags = 0;
180                 db.get_flags(ref flags);
181                 return (flags & DbConstants.DB_CHKSUM) != 0;
182             }
183         }
184
185         /// <summary>
186         /// The algorithm used by the Berkeley DB library to perform encryption
187         /// and decryption. 
188         /// </summary>
189         public EncryptionAlgorithm EncryptAlgorithm {
190             get {
191                 uint flags = 0;
192                 db.get_encrypt_flags(ref flags);
193                 return (EncryptionAlgorithm)Enum.ToObject(
194                     typeof(EncryptionAlgorithm), flags);
195             }
196         }
197         /// <summary>
198         /// If true, encrypt all data stored in the database.
199         /// </summary>
200         public bool Encrypted {
201             get {
202                 uint flags = 0;
203                 db.get_flags(ref flags);
204                 return (flags & DbConstants.DB_ENCRYPT) != 0;
205             }
206         }
207         /// <summary>
208         /// The database byte order.
209         /// </summary>
210         public ByteOrder Endianness {
211             get {
212                 int lorder = 0;
213                 db.get_lorder(ref lorder);
214                 return ByteOrder.FromConst(lorder);
215             }
216         }
217         /// <summary>
218         /// The mechanism for reporting detailed error messages to the
219         /// application.
220         /// </summary>
221         /// <remarks>
222         /// <para>
223         /// When an error occurs in the Berkeley DB library, a
224         /// <see cref="DatabaseException"/>, or subclass of DatabaseException,
225         /// is thrown. In some cases, however, the exception may be insufficient
226         /// to completely describe the cause of the error, especially during
227         /// initial application debugging.
228         /// </para>
229         /// <para>
230         /// In some cases, when an error occurs, Berkeley DB will call the given
231         /// delegate with additional error information. It is up to the delegate
232         /// to display the error message in an appropriate manner.
233         /// </para>
234         /// <para>
235         /// Setting ErrorFeedback to NULL unconfigures the callback interface.
236         /// </para>
237         /// <para>
238         /// This error-logging enhancement does not slow performance or
239         /// significantly increase application size, and may be run during
240         /// normal operation as well as during application debugging.
241         /// </para>
242         /// <para>
243         /// For databases opened inside of a DatabaseEnvironment, setting
244         /// ErrorFeedback affects the entire environment and is equivalent to
245         /// setting DatabaseEnvironment.ErrorFeedback.
246         /// </para>
247         /// <para>
248         /// For databases not opened in an environment, setting ErrorFeedback
249         /// configures operations performed using the specified object, not all
250         /// operations performed on the underlying database. 
251         /// </para>
252         /// </remarks>
253         public ErrorFeedbackDelegate ErrorFeedback {
254             get { return env.ErrorFeedback; }
255             set { env.ErrorFeedback = value; }
256         }
257         /// <summary>
258         /// The prefix string that appears before error messages issued by
259         /// Berkeley DB.
260         /// </summary>
261         /// <remarks>
262         /// <para>
263         /// For databases opened inside of a DatabaseEnvironment, setting
264         /// ErrorPrefix affects the entire environment and is equivalent to
265         /// setting <see cref="DatabaseEnvironment.ErrorPrefix"/>.
266         /// </para>
267         /// <para>
268         /// Setting ErrorPrefix configures operations performed using the
269         /// specified object, not all operations performed on the underlying
270         /// database. 
271         /// </para>
272         /// </remarks>
273         public string ErrorPrefix {
274             get { return env.ErrorPrefix; }
275             set { env.ErrorPrefix = value; }
276         }
277         /// <summary>
278         /// Monitor progress within long running operations.
279         /// </summary>
280         /// <remarks>
281         /// <para>
282         /// Some operations performed by the Berkeley DB library can take
283         /// non-trivial amounts of time. The Feedback delegate can be used by
284         /// applications to monitor progress within these operations. When an
285         /// operation is likely to take a long time, Berkeley DB will call the
286         /// specified delegate with progress information.
287         /// </para>
288         /// <para>
289         /// It is up to the delegate to display this information in an
290         /// appropriate manner. 
291         /// </para>
292         /// </remarks>
293         public DatabaseFeedbackDelegate Feedback {
294             get { return feedbackHandler; }
295             set {
296                 if (value == null)
297                     db.set_feedback(null);
298                 else if (feedbackHandler == null) {
299                     if (doFeedbackRef == null)
300                         doFeedbackRef = new BDB_DbFeedbackDelegate(doFeedback);
301                     db.set_feedback(doFeedbackRef);
302                 }
303                 feedbackHandler = value;
304             }
305         }
306         /// <summary>
307         /// The filename of this database, if it has one.
308         /// </summary>
309         public string FileName {
310             get {
311                 string ret = "";
312                 string tmp = "";
313                 db.get_dbname(out ret, out tmp);
314                 return ret;
315             }
316         }
317         /// <summary>
318         /// If true, the object is free-threaded; that is, concurrently usable
319         /// by multiple threads in the address space. 
320         /// </summary>
321         public bool FreeThreaded {
322             get {
323                 uint flags = 0;
324                 db.get_open_flags(ref flags);
325                 return (flags & DbConstants.DB_THREAD) != 0;
326             }
327         }
328         /// <summary>
329         /// If true, the object references a physical file supporting multiple
330         /// databases.
331         /// </summary>
332         /// <remarks>
333         /// If true, the object is a handle on a database whose key values are
334         /// the names of the databases stored in the physical file and whose
335         /// data values are opaque objects. No keys or data values may be
336         /// modified or stored using the database handle. 
337         /// </remarks>
338         public bool HasMultiple { get { return (db.get_multiple() != 0); } }
339         /// <summary>
340         /// If true, the underlying database files were created on an
341         /// architecture of the same byte order as the current one.  This
342         /// information may be used to determine whether application data needs
343         /// to be adjusted for this architecture or not. 
344         /// </summary>
345         public bool InHostOrder {
346             get {
347                 int isswapped = 0;
348                 db.get_byteswapped(ref isswapped);
349                 return (isswapped == 0);
350             }
351         }
352         /// <summary>
353         /// <para>
354         /// If true, this database is not mapped into process memory.
355         /// </para>
356         /// <para>
357         /// See <see cref="DatabaseEnvironment.MMapSize"/> for further
358         /// information. 
359         /// </para>
360         /// </summary>
361         public bool NoMMap {
362             get {
363                 uint flags = 0;
364                 db.get_open_flags(ref flags);
365                 return (flags & DbConstants.DB_NOMMAP) == 0;
366             }
367         }
368         /// <summary>
369         /// If true, Berkeley DB will not write log records for this database.
370         /// </summary>
371         public bool NonDurableTxns {
372             get {
373                 uint flags = 0;
374                 db.get_flags(ref flags);
375                 return (flags & DbConstants.DB_TXN_NOT_DURABLE) != 0;
376             }
377         }
378         /// <summary>
379         /// If true, configure the database handle to obtain a write lock on the
380         /// entire database. When the database is opened it will immediately
381         /// throw <see cref="LockNotGrantedException"/> if it cannot obtain the
382         /// exclusive lock immediately. If False, configure the database handle
383         /// to obtain a write lock on the entire database. When the database is
384         /// opened, it will block until it can obtain the exclusive lock. If
385         /// null, do not configure the database handle to obtain a write lock on
386         /// the entire database.
387         /// </summary>
388         public bool? NoWaitDbExclusiveLock {
389             get {
390                 int onoff = 0;
391                 int nowait = 0;
392                 bool? result = null;
393                 db.get_lk_exclusive(ref onoff, ref nowait);
394                 if (onoff > 0) {
395                     if (nowait > 0) result = true;
396                     else result = false;
397                 }
398                 return result;
399             }
400         }
401         /// <summary>
402         /// The database's current page size.
403         /// </summary>
404         /// <remarks>  If <see cref="DatabaseConfig.PageSize"/> was not set by
405         /// your application, then the default pagesize is selected based on the
406         /// underlying filesystem I/O block size.
407         /// </remarks>
408         public uint Pagesize {
409             get {
410                 uint pgsz = 0;
411                 db.get_pagesize(ref pgsz);
412                 return pgsz;
413             }
414         }
415         /// <summary>
416         /// The cache priority for pages referenced by this object.
417         /// </summary>
418         public CachePriority Priority {
419             get {
420                 uint pri = 0;
421                 db.get_priority(ref pri);
422                 return CachePriority.fromUInt(pri);
423             }
424         }
425         /// <summary>
426         /// If true, this database has been opened for reading only. Any attempt
427         /// to modify items in the database will fail, regardless of the actual
428         /// permissions of any underlying files. 
429         /// </summary>
430         public bool ReadOnly {
431             get {
432                 uint flags = 0;
433                 db.get_open_flags(ref flags);
434                 return (flags & DbConstants.DB_RDONLY) != 0;
435             }
436         }
437         /// <summary>
438         /// If true, this database supports transactional read operations with
439         /// degree 1 isolation. Read operations on the database may request the
440         /// return of modified but not yet committed data.
441         /// </summary>
442         public bool ReadUncommitted {
443             get {
444                 uint flags = 0;
445                 db.get_open_flags(ref flags);
446                 return (flags & DbConstants.DB_READ_UNCOMMITTED) != 0;
447             }
448         }
449         /// <summary>
450         /// If true, this database has been opened in a transactional mode.
451         /// </summary>
452         public bool Transactional {
453             get { return (db.get_transactional() != 0); }
454         }
455         /// <summary>
456         /// If true, the underlying file was physically truncated upon open,
457         /// discarding all previous databases it might have held.
458         /// </summary>
459         public bool Truncated {
460             get {
461                 uint flags = 0;
462                 db.get_open_flags(ref flags);
463                 return (flags & DbConstants.DB_TRUNCATE) != 0;
464             }
465         }
466         /// <summary>
467         /// The type of the underlying access method (and file format). This
468         /// value may be used to determine the type of the database after an
469         /// <see cref="Database.Open"/>. 
470         /// </summary>
471         public DatabaseType Type {
472             get {
473                 DBTYPE mytype = DBTYPE.DB_UNKNOWN;
474                 db.get_type(ref mytype);
475                 switch (mytype) {
476                     case DBTYPE.DB_BTREE:
477                         return DatabaseType.BTREE;
478                     case DBTYPE.DB_HASH:
479                         return DatabaseType.HASH;
480                     case DBTYPE.DB_HEAP:
481                         return DatabaseType.HEAP;
482                     case DBTYPE.DB_QUEUE:
483                         return DatabaseType.QUEUE;
484                     case DBTYPE.DB_RECNO:
485                         return DatabaseType.RECNO;
486                     default:
487                         return DatabaseType.UNKNOWN;
488                 }
489             }
490         }
491         /// <summary>
492         /// If true, the database was opened with support for multiversion
493         /// concurrency control.
494         /// </summary>
495         public bool UseMVCC {
496             get {
497                 uint flags = 0;
498                 db.get_open_flags(ref flags);
499                 return (flags & DbConstants.DB_MULTIVERSION) != 0;
500             }
501         }
502         #endregion Properties
503
504         #region Methods
505         //Sorted alpha by method name
506         /// <summary>
507         /// Flush any cached database information to disk, close any open
508         /// <see cref="Cursor"/> objects, free any
509         /// allocated resources, and close any underlying files.
510         /// </summary>
511         /// <overloads>
512         /// <para>
513         /// Although closing a database will close any open cursors, it is
514         /// recommended that applications explicitly close all their Cursor
515         /// objects before closing the database. The reason why is that when the
516         /// cursor is explicitly closed, the memory allocated for it is
517         /// reclaimed; however, this will not happen if you close a database
518         /// while cursors are still opened.
519         /// </para>
520         /// <para>
521         /// The same rule, for the same reasons, hold true for
522         /// <see cref="Transaction"/> objects. Simply make sure you resolve
523         /// all your transaction objects before closing your database handle.
524         /// </para>
525         /// <para>
526         /// Because key/data pairs are cached in memory, applications should
527         /// make a point to always either close database handles or sync their
528         /// data to disk (using <see cref="Sync"/> before exiting, to
529         /// ensure that any data cached in main memory are reflected in the
530         /// underlying file system.
531         /// </para>
532         /// <para>
533         /// When called on a database that is the primary database for a
534         /// secondary index, the primary database should be closed only after
535         /// all secondary indices referencing it have been closed.
536         /// </para>
537         /// <para>
538         /// When multiple threads are using the object concurrently, only a
539         /// single thread may call the Close method.
540         /// </para>
541         /// <para>
542         /// The object may not be accessed again after Close is called,
543         /// regardless of its outcome.
544         /// </para>
545         /// </overloads>
546         public void Close() {
547             Close(true);
548         }
549         /// <summary>
550         /// Optionally flush any cached database information to disk, close any
551         /// open <see cref="BaseDatabase.Cursor"/> objects, free
552         /// any allocated resources, and close any underlying files.
553         /// </summary>
554         /// <param name="sync">
555         /// If false, do not flush cached information to disk.
556         /// </param>
557         /// <remarks>
558         /// <para>
559         /// The sync parameter is a dangerous option. It should be set to false 
560         /// only if the application is doing logging (with transactions) so that
561         /// the database is recoverable after a system or application crash, or
562         /// if the database is always generated from scratch after any system or
563         /// application crash.
564         /// </para>
565         /// <para>
566         /// It is important to understand that flushing cached information to
567         /// disk only minimizes the window of opportunity for corrupted data.
568         /// Although unlikely, it is possible for database corruption to happen
569         /// if a system or application crash occurs while writing data to the
570         /// database. To ensure that database corruption never occurs,
571         /// applications must either use transactions and logging with automatic
572         /// recovery or edit a copy of the database, and once all applications
573         /// using the database have successfully called Close, atomically
574         /// replace the original database with the updated copy.
575         /// </para>
576         /// <para>
577         /// Note that this parameter only works when the database has been
578         /// opened using an environment. 
579         /// </para>
580         /// </remarks>
581         public void Close(bool sync) {
582             db.close(sync ? 0 : DbConstants.DB_NOSYNC);
583             isOpen = false;
584         }
585
586         /// <summary>
587         /// Create a database cursor.
588         /// </summary>
589         /// <returns>A newly created cursor</returns>
590         public Cursor Cursor() { return Cursor(new CursorConfig(), null); }
591         /// <summary>
592         /// Create a database cursor with the given configuration.
593         /// </summary>
594         /// <param name="cfg">
595         /// The configuration properties for the cursor.
596         /// </param>
597         /// <returns>A newly created cursor</returns>
598         public Cursor Cursor(CursorConfig cfg) { return Cursor(cfg, null); }
599         /// <summary>
600         /// Create a transactionally protected database cursor.
601         /// </summary>
602         /// <param name="txn">
603         /// The transaction context in which the cursor may be used.
604         /// </param>
605         /// <returns>A newly created cursor</returns>
606         public Cursor Cursor(Transaction txn) {
607             return Cursor(new CursorConfig(), txn);
608         }
609         /// <summary>
610         /// Create a transactionally protected database cursor with the given
611         /// configuration.
612         /// </summary>
613         /// <param name="cfg">
614         /// The configuration properties for the cursor.
615         /// </param>
616         /// <param name="txn">
617         /// The transaction context in which the cursor may be used.
618         /// </param>
619         /// <returns>A newly created cursor</returns>
620         public Cursor Cursor(CursorConfig cfg, Transaction txn) {
621             if (cfg.Priority == CachePriority.DEFAULT)
622                 return new Cursor(db.cursor(
623                     Transaction.getDB_TXN(txn), cfg.flags), Type, Pagesize);
624             else
625                 return new Cursor(db.cursor(Transaction.getDB_TXN(txn),
626                     cfg.flags), Type, Pagesize, cfg.Priority);
627         }
628
629         /// <summary>
630         /// Remove key/data pairs from the database. If <paramref name="key"/>
631         /// is DatabaseEntry, the key/data pair associated with 
632         /// <paramref name="key"/> is discarded from the database. In the
633         /// presence of duplicate key values, all records associated with the
634         /// designated key will be discarded. If <paramref name="key"/> is 
635         /// MultipleDatabaseEntry, delete multiple data items using keys from
636         /// the buffer to which the key parameter refers. If 
637         /// <paramref name="key"/> is MultipleKeyDatabaseEntry, delete multiple
638         /// data items using keys and data from the buffer to which the key 
639         /// parameter refers. 
640         /// </summary>
641         /// <remarks>
642         /// <para>
643         /// When called on a secondary database, remove the key/data pair from
644         /// the primary database and all secondary indices.
645         /// </para>
646         /// <para>
647         /// If the operation occurs in a transactional database, the operation
648         /// will be implicitly transaction protected.
649         /// </para>
650         /// </remarks>
651         /// <param name="key">
652         /// Discard the key/data pair associated with <paramref name="key"/>.
653         /// </param>
654         /// <exception cref="NotFoundException">
655         /// A NotFoundException is thrown if <paramref name="key"/> is not in
656         /// the database. 
657         /// </exception>
658         /// <exception cref="KeyEmptyException">
659         /// A KeyEmptyException is thrown if the database is a
660         /// <see cref="QueueDatabase"/> or <see cref="RecnoDatabase"/> 
661         /// database and <paramref name="key"/> exists, but was never explicitly
662         /// created by the application or was later deleted.
663         /// </exception>
664         public void Delete(DatabaseEntry key) {
665             Delete(key, null);
666         }
667         /// <summary>
668         /// Remove key/data pairs from the database. If <paramref name="key"/>
669         /// is DatabaseEntry, the key/data pair associated with 
670         /// <paramref name="key"/> is discarded from the database. In the
671         /// presence of duplicate key values, all records associated with the
672         /// designated key will be discarded. If <paramref name="key"/> is 
673         /// MultipleDatabaseEntry, delete multiple data items using keys from
674         /// the buffer to which the key parameter refers. If 
675         /// <paramref name="key"/> is MultipleKeyDatabaseEntry, delete multiple
676         /// data items using keys and data from the buffer to which the key 
677         /// parameter refers.
678         /// </summary>
679         /// <remarks>
680         /// <para>
681         /// When called on a secondary database, remove the key/data pairs from
682         /// the primary database and all secondary indices.
683         /// </para>
684         /// <para>
685         /// If <paramref name="txn"/> is null and the operation occurs in a
686         /// transactional database, the operation will be implicitly transaction
687         /// protected.
688         /// </para>
689         /// </remarks>
690         /// <param name="key">
691         /// Discard the key/data pairs associated with <paramref name="key"/>.
692         /// </param>
693         /// <param name="txn">
694         /// If the operation is part of an application-specified transaction,
695         /// <paramref name="txn"/> is a Transaction object returned from
696         /// <see cref="DatabaseEnvironment.BeginTransaction"/>; if
697         /// the operation is part of a Berkeley DB Concurrent Data Store group,
698         /// <paramref name="txn"/> is a handle returned from
699         /// <see cref="DatabaseEnvironment.BeginCDSGroup"/>; otherwise null.
700         /// </param>
701         /// <exception cref="NotFoundException">
702         /// A NotFoundException is thrown if <paramref name="key"/> is not in
703         /// the database. 
704         /// </exception>
705         /// <exception cref="KeyEmptyException">
706         /// A KeyEmptyException is thrown if the database is a
707         /// <see cref="QueueDatabase"/> or <see cref="RecnoDatabase"/> 
708         /// database and <paramref name="key"/> exists, but was never explicitly
709         /// created by the application or was later deleted.
710         /// </exception>
711         public void Delete(DatabaseEntry key, Transaction txn) {
712             uint flags = 0;
713             System.Type type = key.GetType();
714             if (type == typeof(MultipleDatabaseEntry))
715                 flags |= DbConstants.DB_MULTIPLE;
716             else if (type == typeof(MultipleKeyDatabaseEntry))
717                 flags |= DbConstants.DB_MULTIPLE_KEY;
718             db.del(Transaction.getDB_TXN(txn), key, flags);
719         }
720
721         /// <summary>
722         /// Check whether <paramref name="key"/> appears in the database.
723         /// </summary>
724         /// <remarks>
725         /// If the operation occurs in a transactional database, the operation
726         /// will be implicitly transaction protected.
727         /// </remarks>
728         /// <param name="key">The key to search for.</param>
729         /// <exception cref="NotFoundException">
730         /// A NotFoundException is thrown if <paramref name="key"/> is not in
731         /// the database. 
732         /// </exception>
733         /// <exception cref="KeyEmptyException">
734         /// A KeyEmptyException is thrown if the database is a
735         /// <see cref="QueueDatabase"/> or <see cref="RecnoDatabase"/> 
736         /// database and <paramref name="key"/> exists, but was never explicitly
737         /// created by the application or was later deleted.
738         /// </exception>
739         /// <returns>
740         /// True if <paramref name="key"/> appears in the database, false
741         /// otherwise.
742         /// </returns>
743         public bool Exists(DatabaseEntry key) {
744             return Exists(key, null, null);
745         }
746         /// <summary>
747         /// Check whether <paramref name="key"/> appears in the database.
748         /// </summary>
749         /// <remarks>
750         /// If <paramref name="txn"/> is null and the operation occurs in a
751         /// transactional database, the operation will be implicitly transaction
752         /// protected.
753         /// </remarks>
754         /// <param name="key">The key to search for.</param>
755         /// <param name="txn">
756         /// If the operation is part of an application-specified transaction,
757         /// <paramref name="txn"/> is a Transaction object returned from
758         /// <see cref="DatabaseEnvironment.BeginTransaction"/>; if
759         /// the operation is part of a Berkeley DB Concurrent Data Store group,
760         /// <paramref name="txn"/> is a handle returned from
761         /// <see cref="DatabaseEnvironment.BeginCDSGroup"/>; otherwise null.
762         /// </param>
763         /// <exception cref="NotFoundException">
764         /// A NotFoundException is thrown if <paramref name="key"/> is not in
765         /// the database. 
766         /// </exception>
767         /// <exception cref="KeyEmptyException">
768         /// A KeyEmptyException is thrown if the database is a
769         /// <see cref="QueueDatabase"/> or <see cref="RecnoDatabase"/> 
770         /// database and <paramref name="key"/> exists, but was never explicitly
771         /// created by the application or was later deleted.
772         /// </exception>
773         /// <returns>
774         /// True if <paramref name="key"/> appears in the database, false
775         /// otherwise.
776         /// </returns>
777         public bool Exists(DatabaseEntry key, Transaction txn) {
778             return Exists(key, txn, null);
779         }
780         /// <summary>
781         /// Check whether <paramref name="key"/> appears in the database.
782         /// </summary>
783         /// <remarks>
784         /// If <paramref name="txn"/> is null and the operation occurs in a
785         /// transactional database, the operation will be implicitly transaction
786         /// protected.
787         /// </remarks>
788         /// <param name="key">The key to search for.</param>
789         /// <param name="txn">
790         /// If the operation is part of an application-specified transaction,
791         /// <paramref name="txn"/> is a Transaction object returned from
792         /// <see cref="DatabaseEnvironment.BeginTransaction"/>; if
793         /// the operation is part of a Berkeley DB Concurrent Data Store group,
794         /// <paramref name="txn"/> is a handle returned from
795         /// <see cref="DatabaseEnvironment.BeginCDSGroup"/>; otherwise null.
796         /// </param>
797         /// <param name="info">The locking behavior to use.</param>
798         /// <exception cref="NotFoundException">
799         /// A NotFoundException is thrown if <paramref name="key"/> is not in
800         /// the database. 
801         /// </exception>
802         /// <exception cref="KeyEmptyException">
803         /// A KeyEmptyException is thrown if the database is a
804         /// <see cref="QueueDatabase"/> or <see cref="RecnoDatabase"/> 
805         /// database and <paramref name="key"/> exists, but was never explicitly
806         /// created by the application or was later deleted.
807         /// </exception>
808         /// <returns>
809         /// True if <paramref name="key"/> appears in the database, false
810         /// otherwise.
811         /// </returns>
812         public bool Exists(
813             DatabaseEntry key, Transaction txn, LockingInfo info) {
814             /* 
815              * If the library call does not throw an exception the key exists.
816              * If the exception is NotFound the key does not exist and we
817              * should return false.  Any other exception should get passed
818              * along.
819              */
820             try {
821                 db.exists(Transaction.getDB_TXN(txn),
822                     key, (info == null) ? 0 : info.flags);
823                 return true;
824             } catch (NotFoundException) {
825                 return false;
826             }
827         }
828
829         /// <summary>
830         /// Retrieve a key/data pair from the database.  In the presence of
831         /// duplicate key values, Get will return the first data item for 
832         /// <paramref name="key"/>.
833         /// </summary>
834         /// <remarks>
835         /// If the operation occurs in a transactional database, the operation
836         /// will be implicitly transaction protected.
837         /// </remarks>
838         /// <param name="key">The key to search for</param>
839         /// <exception cref="NotFoundException">
840         /// A NotFoundException is thrown if <paramref name="key"/> is not in
841         /// the database. 
842         /// </exception>
843         /// <exception cref="KeyEmptyException">
844         /// A KeyEmptyException is thrown if the database is a
845         /// <see cref="QueueDatabase"/> or <see cref="RecnoDatabase"/> 
846         /// database and <paramref name="key"/> exists, but was never explicitly
847         /// created by the application or was later deleted.
848         /// </exception>
849         /// <returns>
850         /// A <see cref="KeyValuePair{T,T}"/> whose Key
851         /// parameter is <paramref name="key"/> and whose Value parameter is the
852         /// retrieved data.
853         /// </returns>
854         public
855             KeyValuePair<DatabaseEntry, DatabaseEntry> Get(DatabaseEntry key) {
856             return Get(key, (Transaction)null, (LockingInfo)null);
857         }
858         /// <summary>
859         /// Retrieve a key/data pair from the database.  In the presence of
860         /// duplicate key values, Get will return the first data item for 
861         /// <paramref name="key"/>.
862         /// </summary>
863         /// <remarks>
864         /// If <paramref name="txn"/> is null and the operation occurs in a
865         /// transactional database, the operation will be implicitly transaction
866         /// protected.
867         /// </remarks>
868         /// <param name="key">The key to search for</param>
869         /// <param name="txn">
870         /// <paramref name="txn"/> is a Transaction object returned from
871         /// <see cref="DatabaseEnvironment.BeginTransaction"/>; if
872         /// the operation is part of a Berkeley DB Concurrent Data Store group,
873         /// <paramref name="txn"/> is a handle returned from
874         /// <see cref="DatabaseEnvironment.BeginCDSGroup"/>; otherwise null.
875         /// </param>
876         /// <exception cref="NotFoundException">
877         /// A NotFoundException is thrown if <paramref name="key"/> is not in
878         /// the database. 
879         /// </exception>
880         /// <exception cref="KeyEmptyException">
881         /// A KeyEmptyException is thrown if the database is a
882         /// <see cref="QueueDatabase"/> or <see cref="RecnoDatabase"/> 
883         /// database and <paramref name="key"/> exists, but was never explicitly
884         /// created by the application or was later deleted.
885         /// </exception>
886         /// <returns>
887         /// A <see cref="KeyValuePair{T,T}"/> whose Key
888         /// parameter is <paramref name="key"/> and whose Value parameter is the
889         /// retrieved data.
890         /// </returns>
891         public KeyValuePair<DatabaseEntry, DatabaseEntry> Get(
892             DatabaseEntry key, Transaction txn) {
893             return Get(key, txn, null);
894         }
895         /// <summary>
896         /// Retrieve a key/data pair from the database.  In the presence of
897         /// duplicate key values, Get will return the first data item for 
898         /// <paramref name="key"/>.
899         /// </summary>
900         /// <remarks>
901         /// If <paramref name="txn"/> is null and the operation occurs in a
902         /// transactional database, the operation will be implicitly transaction
903         /// protected.
904         /// </remarks>
905         /// <param name="key">The key to search for</param>
906         /// <param name="txn">
907         /// <paramref name="txn"/> is a Transaction object returned from
908         /// <see cref="DatabaseEnvironment.BeginTransaction"/>; if
909         /// the operation is part of a Berkeley DB Concurrent Data Store group,
910         /// <paramref name="txn"/> is a handle returned from
911         /// <see cref="DatabaseEnvironment.BeginCDSGroup"/>; otherwise null.
912         /// </param>
913         /// <param name="info">The locking behavior to use.</param>
914         /// <exception cref="NotFoundException">
915         /// A NotFoundException is thrown if <paramref name="key"/> is not in
916         /// the database. 
917         /// </exception>
918         /// <exception cref="KeyEmptyException">
919         /// A KeyEmptyException is thrown if the database is a
920         /// <see cref="QueueDatabase"/> or <see cref="RecnoDatabase"/> 
921         /// database and <paramref name="key"/> exists, but was never explicitly
922         /// created by the application or was later deleted.
923         /// </exception>
924         /// <returns>
925         /// A <see cref="KeyValuePair{T,T}"/> whose Key
926         /// parameter is <paramref name="key"/> and whose Value parameter is the
927         /// retrieved data.
928         /// </returns>
929         public KeyValuePair<DatabaseEntry, DatabaseEntry> Get(
930             DatabaseEntry key, Transaction txn, LockingInfo info) {
931             return Get(key, null, txn, info, 0);
932         }
933         /// <summary>
934         /// Retrieve a key/data pair from the database.  In the presence of
935         /// duplicate key values, Get will return the first data item for
936         /// <paramref name="key"/>. If the data is a partial
937         /// <see cref="DatabaseEntry"/>, <see cref="DatabaseEntry.PartialLen"/>
938         /// bytes starting <see cref="DatabaseEntry.PartialOffset"/> bytes
939         /// from the beginning of the retrieved data record are returned as
940         /// if they comprise the entire record. If any or all of the specified
941         /// bytes do not exist in the record, Get is successful, and any 
942         /// existing bytes are returned.
943         /// </summary>
944         /// <param name="key">The key to search for</param>
945         /// <param name="data">The retrieved data</param>
946         /// <exception cref="NotFoundException">
947         /// A NotFoundException is thrown if <paramref name="key"/> is not in
948         /// the database. 
949         /// </exception>
950         /// <exception cref="KeyEmptyException">
951         /// A KeyEmptyException is thrown if the database is a
952         /// <see cref="QueueDatabase"/> or <see cref="RecnoDatabase"/> 
953         /// database and <paramref name="key"/> exists, but was never 
954         /// explicitly created by the application or was later deleted.
955         /// </exception>
956         /// <returns>
957         /// A <see cref="KeyValuePair{T,T}"/> whose Key
958         /// parameter is <paramref name="key"/> and whose Value parameter is
959         /// the partially retrieved bytes in the data.
960         /// </returns>
961         public KeyValuePair<DatabaseEntry, DatabaseEntry> Get(
962             DatabaseEntry key, DatabaseEntry data) {
963             return Get(key, data, null, null);
964         }
965         /// <summary>
966         /// Retrieve a key/data pair from the database. In the presence of
967         /// duplicate key values, Get will return the first data item for
968         /// <paramref name="key"/>. If the data is a partial
969         /// <see cref="DatabaseEntry"/>, <see cref="DatabaseEntry.PartialLen"/>
970         /// bytes starting <see cref="DatabaseEntry.PartialOffset"/> bytes
971         /// from the beginning of the retrieved data record are returned as
972         /// if they comprise the entire record. If any or all of the specified
973         /// bytes do not exist in the record, Get is successful, and any 
974         /// existing bytes are returned.
975         /// </summary>
976         /// <remarks>
977         /// If <paramref name="txn"/> is null and the operation occurs in
978         /// a transactional database, the operation will be implicitly 
979         /// transaction protected.
980         /// </remarks>
981         /// <param name="key">The key to search for</param>
982         /// <param name="data">The retrieved data</param>
983         /// <param name="txn">
984         /// <paramref name="txn"/> is a Transaction object returned from
985         /// <see cref="DatabaseEnvironment.BeginTransaction"/>; if
986         /// the operation is part of a Berkeley DB Concurrent Data Store
987         /// group, <paramref name="txn"/> is a handle returned from
988         /// <see cref="DatabaseEnvironment.BeginCDSGroup"/>; otherwise null.
989         /// </param>
990         /// <exception cref="NotFoundException">
991         /// A NotFoundException is thrown if <paramref name="key"/> is not in
992         /// the database. 
993         /// </exception>
994         /// <exception cref="KeyEmptyException">
995         /// A KeyEmptyException is thrown if the database is a
996         /// <see cref="QueueDatabase"/> or <see cref="RecnoDatabase"/> 
997         /// database and <paramref name="key"/> exists, but was never 
998         /// explicitly created by the application or was later deleted.
999         /// </exception>
1000         /// <returns>
1001         /// A <see cref="KeyValuePair{T,T}"/> whose Key
1002         /// parameter is <paramref name="key"/> and whose Value parameter is
1003         /// the partially retrieved bytes in the data.
1004         /// </returns>
1005         public KeyValuePair<DatabaseEntry, DatabaseEntry> Get(
1006             DatabaseEntry key, DatabaseEntry data, Transaction txn) {
1007             return Get(key, data, txn, null);
1008         }
1009         /// <summary>
1010         /// Retrieve a key/data pair from the database.  In the presence of
1011         /// duplicate key values, Get will return the first data item for
1012         /// <paramref name="key"/>. If the data is a partial
1013         /// <see cref="DatabaseEntry"/>, <see cref="DatabaseEntry.PartialLen"/>
1014         /// bytes starting <see cref="DatabaseEntry.PartialOffset"/> bytes
1015         /// from the beginning of the retrieved data record are returned as
1016         /// if they comprise the entire record. If any or all of the specified
1017         /// bytes do not exist in the record, Get is successful, and any 
1018         /// existing bytes are returned.
1019         /// </summary>
1020         /// <remarks>
1021         /// If <paramref name="txn"/> is null and the operation occurs in
1022         /// a transactional database, the operation will be implicitly 
1023         /// transaction protected.
1024         /// </remarks>
1025         /// <param name="key">The key to search for</param>
1026         /// <param name="data">The retrieved data</param>
1027         /// <param name="txn">
1028         /// <paramref name="txn"/> is a Transaction object returned from
1029         /// <see cref="DatabaseEnvironment.BeginTransaction"/>; if
1030         /// the operation is part of a Berkeley DB Concurrent Data Store
1031         /// group, <paramref name="txn"/> is a handle returned from
1032         /// <see cref="DatabaseEnvironment.BeginCDSGroup"/>; otherwise null.
1033         /// </param>
1034         /// <param name="info">The locking behavior to use.</param>
1035         /// <exception cref="NotFoundException">
1036         /// A NotFoundException is thrown if <paramref name="key"/> is not in
1037         /// the database. 
1038         /// </exception>
1039         /// <exception cref="KeyEmptyException">
1040         /// A KeyEmptyException is thrown if the database is a
1041         /// <see cref="QueueDatabase"/> or <see cref="RecnoDatabase"/> 
1042         /// database and <paramref name="key"/> exists, but was never 
1043         /// explicitly created by the application or was later deleted.
1044         /// </exception>
1045         /// <returns>
1046         /// A <see cref="KeyValuePair{T,T}"/> whose Key
1047         /// parameter is <paramref name="key"/> and whose Value parameter is
1048         /// the partially retrieved bytes in the data.
1049         /// </returns>
1050         public KeyValuePair<DatabaseEntry, DatabaseEntry> Get(
1051             DatabaseEntry key, DatabaseEntry data, Transaction txn,
1052             LockingInfo info) {
1053             return Get(key, data, txn, info, 0);
1054         }
1055         /// <summary>
1056         /// Protected method to retrieve data from the underlying DB handle.
1057         /// </summary>
1058         /// <param name="key">
1059         /// The key to search for.  If null a new DatabaseEntry is created.
1060         /// </param>
1061         /// <param name="data">
1062         /// The data to search for.  If null a new DatabaseEntry is created.
1063         /// </param>
1064         /// <param name="txn">The txn for this operation.</param>
1065         /// <param name="info">Locking info for this operation.</param>
1066         /// <param name="flags">
1067         /// Flags value specifying which type of get to perform.  Passed
1068         /// directly to DB->get().
1069         /// </param>
1070         /// <returns>
1071         /// A <see cref="KeyValuePair{T,T}"/> whose Key
1072         /// parameter is <paramref name="key"/> and whose Value parameter is the
1073         /// retrieved data.
1074         /// </returns>
1075         protected KeyValuePair<DatabaseEntry, DatabaseEntry> Get(
1076             DatabaseEntry key,
1077             DatabaseEntry data, Transaction txn, LockingInfo info, uint flags) {
1078             if (key == null)
1079                 key = new DatabaseEntry();
1080             if (data == null)
1081                 data = new DatabaseEntry();
1082             flags |= info == null ? 0 : info.flags;
1083             db.get(Transaction.getDB_TXN(txn), key, data, flags);
1084             return new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data);
1085         }
1086
1087         /// <summary>
1088         /// Retrieve a key/data pair from the database which matches
1089         /// <paramref name="key"/> and <paramref name="data"/>.
1090         /// </summary>
1091         /// <remarks>
1092         /// If the operation occurs in a transactional database, the operation
1093         /// will be implicitly transaction protected.
1094         /// </remarks>
1095         /// <param name="key">The key to search for</param>
1096         /// <param name="data">The data to search for</param>
1097         /// <exception cref="NotFoundException">
1098         /// A NotFoundException is thrown if <paramref name="key"/> and
1099         /// <paramref name="data"/> are not in the database. 
1100         /// </exception>
1101         /// <exception cref="KeyEmptyException">
1102         /// A KeyEmptyException is thrown if the database is a
1103         /// <see cref="QueueDatabase"/> or <see cref="RecnoDatabase"/> 
1104         /// database and <paramref name="key"/> exists, but was never explicitly
1105         /// created by the application or was later deleted.
1106         /// </exception>
1107         /// <returns>
1108         /// A <see cref="KeyValuePair{T,T}"/> whose Key
1109         /// parameter is <paramref name="key"/> and whose Value parameter is
1110         /// <paramref name="data"/>.
1111         /// </returns>
1112         public KeyValuePair<DatabaseEntry, DatabaseEntry> GetBoth(
1113             DatabaseEntry key, DatabaseEntry data) {
1114             return GetBoth(key, data, null, null);
1115         }
1116         /// <summary>
1117         /// Retrieve a key/data pair from the database which matches
1118         /// <paramref name="key"/> and <paramref name="data"/>.
1119         /// </summary>
1120         /// <remarks>
1121         /// If <paramref name="txn"/> is null and the operation occurs in a
1122         /// transactional database, the operation will be implicitly transaction
1123         /// protected.
1124         /// </remarks>
1125         /// <param name="key">The key to search for</param>
1126         /// <param name="data">The data to search for</param>
1127         /// <param name="txn">
1128         /// <paramref name="txn"/> is a Transaction object returned from
1129         /// <see cref="DatabaseEnvironment.BeginTransaction"/>; if
1130         /// the operation is part of a Berkeley DB Concurrent Data Store group,
1131         /// <paramref name="txn"/> is a handle returned from
1132         /// <see cref="DatabaseEnvironment.BeginCDSGroup"/>; otherwise null.
1133         /// </param>
1134         /// <exception cref="NotFoundException">
1135         /// A NotFoundException is thrown if <paramref name="key"/> and
1136         /// <paramref name="data"/> are not in the database. 
1137         /// </exception>
1138         /// <exception cref="KeyEmptyException">
1139         /// A KeyEmptyException is thrown if the database is a
1140         /// <see cref="QueueDatabase"/> or <see cref="RecnoDatabase"/> 
1141         /// database and <paramref name="key"/> exists, but was never explicitly
1142         /// created by the application or was later deleted.
1143         /// </exception>
1144         /// <returns>
1145         /// A <see cref="KeyValuePair{T,T}"/> whose Key
1146         /// parameter is <paramref name="key"/> and whose Value parameter is
1147         /// <paramref name="data"/>.
1148         /// </returns>
1149         public KeyValuePair<DatabaseEntry, DatabaseEntry> GetBoth(
1150             DatabaseEntry key, DatabaseEntry data, Transaction txn) {
1151             return GetBoth(key, data, txn, null);
1152         }
1153         /// <summary>
1154         /// Retrieve a key/data pair from the database which matches
1155         /// <paramref name="key"/> and <paramref name="data"/>.
1156         /// </summary>
1157         /// <remarks>
1158         /// If <paramref name="txn"/> is null and the operation occurs in a
1159         /// transactional database, the operation will be implicitly transaction
1160         /// protected.
1161         /// </remarks>
1162         /// <param name="key">The key to search for</param>
1163         /// <param name="data">The data to search for</param>
1164         /// <param name="txn">
1165         /// <paramref name="txn"/> is a Transaction object returned from
1166         /// <see cref="DatabaseEnvironment.BeginTransaction"/>; if
1167         /// the operation is part of a Berkeley DB Concurrent Data Store group,
1168         /// <paramref name="txn"/> is a handle returned from
1169         /// <see cref="DatabaseEnvironment.BeginCDSGroup"/>; otherwise null.
1170         /// </param>
1171         /// <param name="info">The locking behavior to use.</param>
1172         /// <exception cref="NotFoundException">
1173         /// A NotFoundException is thrown if <paramref name="key"/> and
1174         /// <paramref name="data"/> are not in the database. 
1175         /// </exception>
1176         /// <exception cref="KeyEmptyException">
1177         /// A KeyEmptyException is thrown if the database is a
1178         /// <see cref="QueueDatabase"/> or <see cref="RecnoDatabase"/> 
1179         /// database and <paramref name="key"/> exists, but was never explicitly
1180         /// created by the application or was later deleted.
1181         /// </exception>
1182         /// <returns>
1183         /// A <see cref="KeyValuePair{T,T}"/> whose Key
1184         /// parameter is <paramref name="key"/> and whose Value parameter is
1185         /// <paramref name="data"/>.
1186         /// </returns>
1187         public KeyValuePair<DatabaseEntry, DatabaseEntry> GetBoth(
1188             DatabaseEntry key,
1189             DatabaseEntry data, Transaction txn, LockingInfo info) {
1190             return Get(key, data, txn, info, DbConstants.DB_GET_BOTH);
1191         }
1192
1193         /// <summary>
1194         /// Display the database statistical information which does not require
1195         /// traversal of the database. 
1196         /// </summary>
1197         /// <remarks>
1198         /// Among other things, this method makes it possible for applications
1199         /// to request key and record counts without incurring the performance
1200         /// penalty of traversing the entire database. 
1201         /// </remarks>
1202         /// <overloads>
1203         /// The statistical information is described by the
1204         /// <see cref="BTreeStats"/>, <see cref="HashStats"/>, 
1205         /// <see cref="HeapStats"/>, <see cref="QueueStats"/>, and
1206         /// <see cref="RecnoStats"/> classes. 
1207         /// </overloads>
1208         public void PrintFastStats() {
1209             PrintStats(false, true);
1210         }
1211         /// <summary>
1212         /// Display the database statistical information which does not require
1213         /// traversal of the database. 
1214         /// </summary>
1215         /// <remarks>
1216         /// Among other things, this method makes it possible for applications
1217         /// to request key and record counts without incurring the performance
1218         /// penalty of traversing the entire database. 
1219         /// </remarks>
1220         /// <param name="PrintAll">
1221         /// If true, display all available information.
1222         /// </param>
1223         public void PrintFastStats(bool PrintAll) {
1224             PrintStats(PrintAll, true);
1225         }
1226         /// <summary>
1227         /// Display the database statistical information.
1228         /// </summary>
1229         /// <overloads>
1230         /// The statistical information is described by the
1231         /// <see cref="BTreeStats"/>, <see cref="HashStats"/>, 
1232         /// <see cref="HeapStats"/>, <see cref="QueueStats"/>, and
1233         /// <see cref="RecnoStats"/> classes. 
1234         /// </overloads>
1235         public void PrintStats() {
1236             PrintStats(false, false);
1237         }
1238         /// <summary>
1239         /// Display the database statistical information.
1240         /// </summary>
1241         /// <param name="PrintAll">
1242         /// If true, display all available information.
1243         /// </param>
1244         public void PrintStats(bool PrintAll) {
1245             PrintStats(PrintAll, false);
1246         }
1247         private void PrintStats(bool all, bool fast) {
1248             uint flags = 0;
1249             flags |= all ? DbConstants.DB_STAT_ALL : 0;
1250             flags |= fast ? DbConstants.DB_FAST_STAT : 0;
1251             db.stat_print(flags);
1252         }
1253
1254         /// <summary>
1255         /// Remove the underlying file represented by
1256         /// <paramref name="Filename"/>, incidentally removing all of the
1257         /// databases it contained.
1258         /// </summary>
1259         /// <param name="Filename">The file to remove</param>
1260         public static void Remove(string Filename) {
1261             Remove(Filename, null, null);
1262         }
1263         /// <summary>
1264         /// Remove the underlying file represented by
1265         /// <paramref name="Filename"/>, incidentally removing all of the
1266         /// databases it contained.
1267         /// </summary>
1268         /// <param name="Filename">The file to remove</param>
1269         /// <param name="DbEnv">
1270         /// The DatabaseEnvironment the database belongs to
1271         /// </param>
1272         public static void Remove(string Filename, DatabaseEnvironment DbEnv) {
1273             Remove(Filename, null, DbEnv);
1274         }
1275         /// <summary>
1276         /// Remove the database specified by <paramref name="Filename"/> and
1277         /// <paramref name="DatabaseName"/>.
1278         /// </summary>
1279         /// <param name="Filename">The file to remove</param>
1280         /// <param name="DatabaseName">The database to remove</param>
1281         public static void Remove(string Filename, string DatabaseName) {
1282             Remove(Filename, DatabaseName, null);
1283         }
1284         /// <summary>
1285         /// Remove the database specified by <paramref name="Filename"/> and
1286         /// <paramref name="DatabaseName"/>.
1287         /// </summary>
1288         /// <overloads>
1289         /// <para>
1290         /// Applications should never remove databases with open DB handles, or
1291         /// in the case of removing a file, when any database in the file has an
1292         /// open handle. For example, some architectures do not permit the
1293         /// removal of files with open system handles. On these architectures,
1294         /// attempts to remove databases currently in use by any thread of
1295         /// control in the system may fail.
1296         /// </para>
1297         /// <para>
1298         /// Remove should not be called if the remove is intended to be
1299         /// transactionally safe;
1300         /// <see cref="DatabaseEnvironment.RemoveDB"/> should be
1301         /// used instead. 
1302         /// </para>
1303         /// </overloads>
1304         /// <param name="Filename">The file to remove</param>
1305         /// <param name="DatabaseName">The database to remove</param>
1306         /// <param name="DbEnv">
1307         /// The DatabaseEnvironment the database belongs to
1308         /// </param>
1309         public static void Remove(
1310             string Filename, string DatabaseName, DatabaseEnvironment DbEnv) {
1311             BaseDatabase db = new BaseDatabase(DbEnv, 0);
1312             db.db.remove(Filename, DatabaseName, 0);
1313         }
1314
1315         /// <summary>
1316         /// Rename the underlying file represented by
1317         /// <paramref name="Filename"/>, incidentally renaming all of the
1318         /// databases it contained.
1319         /// </summary>
1320         /// <param name="Filename">The file to rename</param>
1321         /// <param name="NewName">The new filename</param>
1322         public static void Rename(string Filename, string NewName) {
1323             Rename(Filename, null, NewName, null);
1324         }
1325         /// <summary>
1326         /// Rename the underlying file represented by
1327         /// <paramref name="Filename"/>, incidentally renaming all of the
1328         /// databases it contained.
1329         /// </summary>
1330         /// <param name="Filename">The file to rename</param>
1331         /// <param name="NewName">The new filename</param>
1332         /// <param name="DbEnv">
1333         /// The DatabaseEnvironment the database belongs to
1334         /// </param>
1335         public static void Rename(
1336             string Filename, string NewName, DatabaseEnvironment DbEnv) {
1337             Rename(Filename, null, NewName, DbEnv);
1338         }
1339         /// <summary>
1340         /// Rename the database specified by <paramref name="Filename"/> and
1341         /// <paramref name="DatabaseName"/>.
1342         /// </summary>
1343         /// <param name="Filename">The file to rename</param>
1344         /// <param name="DatabaseName">The database to rename</param>
1345         /// <param name="NewName">The new database name</param>
1346         public static void Rename(
1347             string Filename, string DatabaseName, string NewName) {
1348             Rename(Filename, DatabaseName, NewName, null);
1349         }
1350         /// <summary>
1351         /// Rename the database specified by <paramref name="Filename"/> and
1352         /// <paramref name="DatabaseName"/>.
1353         /// </summary>
1354         /// <overloads>
1355         /// <para>
1356         /// Applications should not rename databases that are currently in use.
1357         /// If an underlying file is being renamed and logging is currently
1358         /// enabled in the database environment, no database in the file may be
1359         /// open when Rename is called. In particular, some architectures do not
1360         /// permit renaming files with open handles. On these architectures,
1361         /// attempts to rename databases that are currently in use by any thread
1362         /// of control in the system may fail. 
1363         /// </para>
1364         /// <para>
1365         /// Rename should not be called if the rename is intended to be
1366         /// transactionally safe;
1367         /// <see cref="DatabaseEnvironment.RenameDB"/> should be
1368         /// used instead. 
1369         /// </para>
1370         /// </overloads>
1371         /// <param name="Filename">The file to rename</param>
1372         /// <param name="DatabaseName">The database to rename</param>
1373         /// <param name="NewName">The new database name</param>
1374         /// <param name="DbEnv">
1375         /// The DatabaseEnvironment the database belongs to
1376         /// </param>
1377         public static void Rename(string Filename,
1378             string DatabaseName, string NewName, DatabaseEnvironment DbEnv) {
1379             BaseDatabase db = new BaseDatabase(DbEnv, 0);
1380             db.db.rename(Filename, DatabaseName, NewName, 0);
1381         }
1382
1383         /// <summary>
1384         /// Flush any cached information to disk.
1385         /// </summary>
1386         /// <remarks>
1387         /// <para>
1388         /// If the database is in memory only, Sync has no effect and will
1389         /// always succeed.
1390         /// </para>
1391         /// <para>
1392         /// It is important to understand that flushing cached information to
1393         /// disk only minimizes the window of opportunity for corrupted data.
1394         /// Although unlikely, it is possible for database corruption to happen
1395         /// if a system or application crash occurs while writing data to the
1396         /// database. To ensure that database corruption never occurs, 
1397         /// applications must either: use transactions and logging with
1398         /// automatic recovery or edit a copy of the database, and once all
1399         /// applications using the database have successfully called
1400         /// <see cref="BaseDatabase.Close"/>, atomically replace
1401         /// the original database with the updated copy.
1402         /// </para>
1403         /// </remarks>
1404         public void Sync() {
1405             db.sync(0);
1406         }
1407
1408         /// <summary>
1409         /// Empty the database, discarding all records it contains.
1410         /// </summary>
1411         /// <remarks>
1412         /// If the operation occurs in a transactional database, the operation
1413         /// will be implicitly transaction protected.
1414         /// </remarks>
1415         /// <overloads>
1416         /// When called on a database configured with secondary indices, 
1417         /// Truncate will truncate the primary database and all secondary
1418         /// indices. A count of the records discarded from the primary database
1419         /// is returned. 
1420         /// </overloads>
1421         /// <returns>
1422         /// The number of records discarded from the database.
1423         ///</returns>
1424         public uint Truncate() {
1425             return Truncate(null);
1426         }
1427         /// <summary>
1428         /// Empty the database, discarding all records it contains.
1429         /// </summary>
1430         /// <remarks>
1431         /// If <paramref name="txn"/> is null and the operation occurs in a
1432         /// transactional database, the operation will be implicitly transaction
1433         /// protected.
1434         /// </remarks>
1435         /// <param name="txn">
1436         /// <paramref name="txn"/> is a Transaction object returned from
1437         /// <see cref="DatabaseEnvironment.BeginTransaction"/>; if
1438         /// the operation is part of a Berkeley DB Concurrent Data Store group,
1439         /// <paramref name="txn"/> is a handle returned from
1440         /// <see cref="DatabaseEnvironment.BeginCDSGroup"/>; otherwise null.
1441         /// </param>
1442         /// <returns>
1443         /// The number of records discarded from the database.
1444         ///</returns>
1445         public uint Truncate(Transaction txn) {
1446             uint countp = 0;
1447             db.truncate(Transaction.getDB_TXN(txn), ref countp, 0);
1448             return countp;
1449         }
1450
1451         #endregion Methods
1452
1453         /// <summary>
1454         /// Release the resources held by this object, and close the database if
1455         /// it's still open.
1456         /// </summary>
1457         public void Dispose() {
1458             if (isOpen)
1459                 this.Close();
1460             if (db != null)
1461                 this.db.Dispose();
1462
1463             GC.SuppressFinalize(this);
1464         }
1465     }
1466 }