2 * See the file LICENSE for redistribution information.
4 * Copyright (c) 2009, 2012 Oracle and/or its affiliates. All rights reserved.
8 using System.Collections.Generic;
10 using BerkeleyDB.Internal;
12 namespace BerkeleyDB {
14 /// The base class from which all database classes inherit
16 public class BaseDatabase : IDisposable {
19 /// The environment that the database lies in.
21 protected internal DatabaseEnvironment env;
23 /// Whether the database is opened.
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;
34 /// Protected constructor
36 /// <param name="envp">
37 /// The environment in which to create this database
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;
44 env = new DatabaseEnvironment(db.env());
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.
54 /// <param name="clone">Database to clone</param>
55 protected BaseDatabase(BaseDatabase clone) {
58 db.api_internal = this;
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)
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;
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);
92 /// Protected factory method to create and open a new database object.
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
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);
105 ret.db.open(Transaction.getDB_TXN(txn),
106 Filename, DatabaseName, DBTYPE.DB_UNKNOWN, cfg.openFlags, 0);
109 #endregion Constructor
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);
119 // Sorted alpha by property name
121 /// If true, all database modification operations based on this object
122 /// will be transactionally protected.
124 public bool AutoCommit {
127 db.get_open_flags(ref flags);
128 return (flags & DbConstants.DB_AUTO_COMMIT) != 0;
132 /// The size of the shared memory buffer pool -- that is, the cache.
134 public CacheInfo CacheSize {
139 db.get_cachesize(ref gb, ref b, ref n);
140 return new CacheInfo(gb, b, n);
144 /// The CreatePolicy with which this database was opened.
146 public CreatePolicy Creation {
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;
155 return CreatePolicy.NEVER;
159 /// The name of this database, if it has one.
161 public string DatabaseName {
165 db.get_dbname(out tmp, out ret);
170 /// If true, do checksum verification of pages read into the cache from
171 /// the backing filestore.
174 /// Berkeley DB uses the SHA1 Secure Hash Algorithm if encryption is
175 /// configured and a general hash algorithm if it is not.
177 public bool DoChecksum {
180 db.get_flags(ref flags);
181 return (flags & DbConstants.DB_CHKSUM) != 0;
186 /// The algorithm used by the Berkeley DB library to perform encryption
189 public EncryptionAlgorithm EncryptAlgorithm {
192 db.get_encrypt_flags(ref flags);
193 return (EncryptionAlgorithm)Enum.ToObject(
194 typeof(EncryptionAlgorithm), flags);
198 /// If true, encrypt all data stored in the database.
200 public bool Encrypted {
203 db.get_flags(ref flags);
204 return (flags & DbConstants.DB_ENCRYPT) != 0;
208 /// The database byte order.
210 public ByteOrder Endianness {
213 db.get_lorder(ref lorder);
214 return ByteOrder.FromConst(lorder);
218 /// The mechanism for reporting detailed error messages to the
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.
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.
235 /// Setting ErrorFeedback to NULL unconfigures the callback interface.
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.
243 /// For databases opened inside of a DatabaseEnvironment, setting
244 /// ErrorFeedback affects the entire environment and is equivalent to
245 /// setting DatabaseEnvironment.ErrorFeedback.
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.
253 public ErrorFeedbackDelegate ErrorFeedback {
254 get { return env.ErrorFeedback; }
255 set { env.ErrorFeedback = value; }
258 /// The prefix string that appears before error messages issued by
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"/>.
268 /// Setting ErrorPrefix configures operations performed using the
269 /// specified object, not all operations performed on the underlying
273 public string ErrorPrefix {
274 get { return env.ErrorPrefix; }
275 set { env.ErrorPrefix = value; }
278 /// Monitor progress within long running operations.
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.
289 /// It is up to the delegate to display this information in an
290 /// appropriate manner.
293 public DatabaseFeedbackDelegate Feedback {
294 get { return feedbackHandler; }
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);
303 feedbackHandler = value;
307 /// The filename of this database, if it has one.
309 public string FileName {
313 db.get_dbname(out ret, out tmp);
318 /// If true, the object is free-threaded; that is, concurrently usable
319 /// by multiple threads in the address space.
321 public bool FreeThreaded {
324 db.get_open_flags(ref flags);
325 return (flags & DbConstants.DB_THREAD) != 0;
329 /// If true, the object references a physical file supporting multiple
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.
338 public bool HasMultiple { get { return (db.get_multiple() != 0); } }
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.
345 public bool InHostOrder {
348 db.get_byteswapped(ref isswapped);
349 return (isswapped == 0);
354 /// If true, this database is not mapped into process memory.
357 /// See <see cref="DatabaseEnvironment.MMapSize"/> for further
364 db.get_open_flags(ref flags);
365 return (flags & DbConstants.DB_NOMMAP) == 0;
369 /// If true, Berkeley DB will not write log records for this database.
371 public bool NonDurableTxns {
374 db.get_flags(ref flags);
375 return (flags & DbConstants.DB_TXN_NOT_DURABLE) != 0;
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.
388 public bool? NoWaitDbExclusiveLock {
393 db.get_lk_exclusive(ref onoff, ref nowait);
395 if (nowait > 0) result = true;
402 /// The database's current page size.
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.
408 public uint Pagesize {
411 db.get_pagesize(ref pgsz);
416 /// The cache priority for pages referenced by this object.
418 public CachePriority Priority {
421 db.get_priority(ref pri);
422 return CachePriority.fromUInt(pri);
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.
430 public bool ReadOnly {
433 db.get_open_flags(ref flags);
434 return (flags & DbConstants.DB_RDONLY) != 0;
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.
442 public bool ReadUncommitted {
445 db.get_open_flags(ref flags);
446 return (flags & DbConstants.DB_READ_UNCOMMITTED) != 0;
450 /// If true, this database has been opened in a transactional mode.
452 public bool Transactional {
453 get { return (db.get_transactional() != 0); }
456 /// If true, the underlying file was physically truncated upon open,
457 /// discarding all previous databases it might have held.
459 public bool Truncated {
462 db.get_open_flags(ref flags);
463 return (flags & DbConstants.DB_TRUNCATE) != 0;
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"/>.
471 public DatabaseType Type {
473 DBTYPE mytype = DBTYPE.DB_UNKNOWN;
474 db.get_type(ref mytype);
476 case DBTYPE.DB_BTREE:
477 return DatabaseType.BTREE;
479 return DatabaseType.HASH;
481 return DatabaseType.HEAP;
482 case DBTYPE.DB_QUEUE:
483 return DatabaseType.QUEUE;
484 case DBTYPE.DB_RECNO:
485 return DatabaseType.RECNO;
487 return DatabaseType.UNKNOWN;
492 /// If true, the database was opened with support for multiversion
493 /// concurrency control.
495 public bool UseMVCC {
498 db.get_open_flags(ref flags);
499 return (flags & DbConstants.DB_MULTIVERSION) != 0;
502 #endregion Properties
505 //Sorted alpha by method name
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.
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.
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.
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.
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.
538 /// When multiple threads are using the object concurrently, only a
539 /// single thread may call the Close method.
542 /// The object may not be accessed again after Close is called,
543 /// regardless of its outcome.
546 public void Close() {
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.
554 /// <param name="sync">
555 /// If false, do not flush cached information to disk.
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.
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.
577 /// Note that this parameter only works when the database has been
578 /// opened using an environment.
581 public void Close(bool sync) {
582 db.close(sync ? 0 : DbConstants.DB_NOSYNC);
587 /// Create a database cursor.
589 /// <returns>A newly created cursor</returns>
590 public Cursor Cursor() { return Cursor(new CursorConfig(), null); }
592 /// Create a database cursor with the given configuration.
594 /// <param name="cfg">
595 /// The configuration properties for the cursor.
597 /// <returns>A newly created cursor</returns>
598 public Cursor Cursor(CursorConfig cfg) { return Cursor(cfg, null); }
600 /// Create a transactionally protected database cursor.
602 /// <param name="txn">
603 /// The transaction context in which the cursor may be used.
605 /// <returns>A newly created cursor</returns>
606 public Cursor Cursor(Transaction txn) {
607 return Cursor(new CursorConfig(), txn);
610 /// Create a transactionally protected database cursor with the given
613 /// <param name="cfg">
614 /// The configuration properties for the cursor.
616 /// <param name="txn">
617 /// The transaction context in which the cursor may be used.
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);
625 return new Cursor(db.cursor(Transaction.getDB_TXN(txn),
626 cfg.flags), Type, Pagesize, cfg.Priority);
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.
643 /// When called on a secondary database, remove the key/data pair from
644 /// the primary database and all secondary indices.
647 /// If the operation occurs in a transactional database, the operation
648 /// will be implicitly transaction protected.
651 /// <param name="key">
652 /// Discard the key/data pair associated with <paramref name="key"/>.
654 /// <exception cref="NotFoundException">
655 /// A NotFoundException is thrown if <paramref name="key"/> is not in
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.
664 public void Delete(DatabaseEntry key) {
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.
681 /// When called on a secondary database, remove the key/data pairs from
682 /// the primary database and all secondary indices.
685 /// If <paramref name="txn"/> is null and the operation occurs in a
686 /// transactional database, the operation will be implicitly transaction
690 /// <param name="key">
691 /// Discard the key/data pairs associated with <paramref name="key"/>.
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.
701 /// <exception cref="NotFoundException">
702 /// A NotFoundException is thrown if <paramref name="key"/> is not in
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.
711 public void Delete(DatabaseEntry key, Transaction txn) {
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);
722 /// Check whether <paramref name="key"/> appears in the database.
725 /// If the operation occurs in a transactional database, the operation
726 /// will be implicitly transaction protected.
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
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.
740 /// True if <paramref name="key"/> appears in the database, false
743 public bool Exists(DatabaseEntry key) {
744 return Exists(key, null, null);
747 /// Check whether <paramref name="key"/> appears in the database.
750 /// If <paramref name="txn"/> is null and the operation occurs in a
751 /// transactional database, the operation will be implicitly transaction
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.
763 /// <exception cref="NotFoundException">
764 /// A NotFoundException is thrown if <paramref name="key"/> is not in
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.
774 /// True if <paramref name="key"/> appears in the database, false
777 public bool Exists(DatabaseEntry key, Transaction txn) {
778 return Exists(key, txn, null);
781 /// Check whether <paramref name="key"/> appears in the database.
784 /// If <paramref name="txn"/> is null and the operation occurs in a
785 /// transactional database, the operation will be implicitly transaction
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.
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
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.
809 /// True if <paramref name="key"/> appears in the database, false
813 DatabaseEntry key, Transaction txn, LockingInfo info) {
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
821 db.exists(Transaction.getDB_TXN(txn),
822 key, (info == null) ? 0 : info.flags);
824 } catch (NotFoundException) {
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"/>.
835 /// If the operation occurs in a transactional database, the operation
836 /// will be implicitly transaction protected.
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
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.
850 /// A <see cref="KeyValuePair{T,T}"/> whose Key
851 /// parameter is <paramref name="key"/> and whose Value parameter is the
855 KeyValuePair<DatabaseEntry, DatabaseEntry> Get(DatabaseEntry key) {
856 return Get(key, (Transaction)null, (LockingInfo)null);
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"/>.
864 /// If <paramref name="txn"/> is null and the operation occurs in a
865 /// transactional database, the operation will be implicitly transaction
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.
876 /// <exception cref="NotFoundException">
877 /// A NotFoundException is thrown if <paramref name="key"/> is not in
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.
887 /// A <see cref="KeyValuePair{T,T}"/> whose Key
888 /// parameter is <paramref name="key"/> and whose Value parameter is the
891 public KeyValuePair<DatabaseEntry, DatabaseEntry> Get(
892 DatabaseEntry key, Transaction txn) {
893 return Get(key, txn, null);
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"/>.
901 /// If <paramref name="txn"/> is null and the operation occurs in a
902 /// transactional database, the operation will be implicitly transaction
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.
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
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.
925 /// A <see cref="KeyValuePair{T,T}"/> whose Key
926 /// parameter is <paramref name="key"/> and whose Value parameter is the
929 public KeyValuePair<DatabaseEntry, DatabaseEntry> Get(
930 DatabaseEntry key, Transaction txn, LockingInfo info) {
931 return Get(key, null, txn, info, 0);
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.
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
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.
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.
961 public KeyValuePair<DatabaseEntry, DatabaseEntry> Get(
962 DatabaseEntry key, DatabaseEntry data) {
963 return Get(key, data, null, null);
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.
977 /// If <paramref name="txn"/> is null and the operation occurs in
978 /// a transactional database, the operation will be implicitly
979 /// transaction protected.
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.
990 /// <exception cref="NotFoundException">
991 /// A NotFoundException is thrown if <paramref name="key"/> is not in
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.
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.
1005 public KeyValuePair<DatabaseEntry, DatabaseEntry> Get(
1006 DatabaseEntry key, DatabaseEntry data, Transaction txn) {
1007 return Get(key, data, txn, null);
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.
1021 /// If <paramref name="txn"/> is null and the operation occurs in
1022 /// a transactional database, the operation will be implicitly
1023 /// transaction protected.
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.
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
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.
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.
1050 public KeyValuePair<DatabaseEntry, DatabaseEntry> Get(
1051 DatabaseEntry key, DatabaseEntry data, Transaction txn,
1053 return Get(key, data, txn, info, 0);
1056 /// Protected method to retrieve data from the underlying DB handle.
1058 /// <param name="key">
1059 /// The key to search for. If null a new DatabaseEntry is created.
1061 /// <param name="data">
1062 /// The data to search for. If null a new DatabaseEntry is created.
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().
1071 /// A <see cref="KeyValuePair{T,T}"/> whose Key
1072 /// parameter is <paramref name="key"/> and whose Value parameter is the
1075 protected KeyValuePair<DatabaseEntry, DatabaseEntry> Get(
1077 DatabaseEntry data, Transaction txn, LockingInfo info, uint flags) {
1079 key = new DatabaseEntry();
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);
1088 /// Retrieve a key/data pair from the database which matches
1089 /// <paramref name="key"/> and <paramref name="data"/>.
1092 /// If the operation occurs in a transactional database, the operation
1093 /// will be implicitly transaction protected.
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.
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.
1108 /// A <see cref="KeyValuePair{T,T}"/> whose Key
1109 /// parameter is <paramref name="key"/> and whose Value parameter is
1110 /// <paramref name="data"/>.
1112 public KeyValuePair<DatabaseEntry, DatabaseEntry> GetBoth(
1113 DatabaseEntry key, DatabaseEntry data) {
1114 return GetBoth(key, data, null, null);
1117 /// Retrieve a key/data pair from the database which matches
1118 /// <paramref name="key"/> and <paramref name="data"/>.
1121 /// If <paramref name="txn"/> is null and the operation occurs in a
1122 /// transactional database, the operation will be implicitly transaction
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.
1134 /// <exception cref="NotFoundException">
1135 /// A NotFoundException is thrown if <paramref name="key"/> and
1136 /// <paramref name="data"/> are not in the database.
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.
1145 /// A <see cref="KeyValuePair{T,T}"/> whose Key
1146 /// parameter is <paramref name="key"/> and whose Value parameter is
1147 /// <paramref name="data"/>.
1149 public KeyValuePair<DatabaseEntry, DatabaseEntry> GetBoth(
1150 DatabaseEntry key, DatabaseEntry data, Transaction txn) {
1151 return GetBoth(key, data, txn, null);
1154 /// Retrieve a key/data pair from the database which matches
1155 /// <paramref name="key"/> and <paramref name="data"/>.
1158 /// If <paramref name="txn"/> is null and the operation occurs in a
1159 /// transactional database, the operation will be implicitly transaction
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.
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.
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.
1183 /// A <see cref="KeyValuePair{T,T}"/> whose Key
1184 /// parameter is <paramref name="key"/> and whose Value parameter is
1185 /// <paramref name="data"/>.
1187 public KeyValuePair<DatabaseEntry, DatabaseEntry> GetBoth(
1189 DatabaseEntry data, Transaction txn, LockingInfo info) {
1190 return Get(key, data, txn, info, DbConstants.DB_GET_BOTH);
1194 /// Display the database statistical information which does not require
1195 /// traversal of the database.
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.
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.
1208 public void PrintFastStats() {
1209 PrintStats(false, true);
1212 /// Display the database statistical information which does not require
1213 /// traversal of the database.
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.
1220 /// <param name="PrintAll">
1221 /// If true, display all available information.
1223 public void PrintFastStats(bool PrintAll) {
1224 PrintStats(PrintAll, true);
1227 /// Display the database statistical information.
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.
1235 public void PrintStats() {
1236 PrintStats(false, false);
1239 /// Display the database statistical information.
1241 /// <param name="PrintAll">
1242 /// If true, display all available information.
1244 public void PrintStats(bool PrintAll) {
1245 PrintStats(PrintAll, false);
1247 private void PrintStats(bool all, bool fast) {
1249 flags |= all ? DbConstants.DB_STAT_ALL : 0;
1250 flags |= fast ? DbConstants.DB_FAST_STAT : 0;
1251 db.stat_print(flags);
1255 /// Remove the underlying file represented by
1256 /// <paramref name="Filename"/>, incidentally removing all of the
1257 /// databases it contained.
1259 /// <param name="Filename">The file to remove</param>
1260 public static void Remove(string Filename) {
1261 Remove(Filename, null, null);
1264 /// Remove the underlying file represented by
1265 /// <paramref name="Filename"/>, incidentally removing all of the
1266 /// databases it contained.
1268 /// <param name="Filename">The file to remove</param>
1269 /// <param name="DbEnv">
1270 /// The DatabaseEnvironment the database belongs to
1272 public static void Remove(string Filename, DatabaseEnvironment DbEnv) {
1273 Remove(Filename, null, DbEnv);
1276 /// Remove the database specified by <paramref name="Filename"/> and
1277 /// <paramref name="DatabaseName"/>.
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);
1285 /// Remove the database specified by <paramref name="Filename"/> and
1286 /// <paramref name="DatabaseName"/>.
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.
1298 /// Remove should not be called if the remove is intended to be
1299 /// transactionally safe;
1300 /// <see cref="DatabaseEnvironment.RemoveDB"/> should be
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
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);
1316 /// Rename the underlying file represented by
1317 /// <paramref name="Filename"/>, incidentally renaming all of the
1318 /// databases it contained.
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);
1326 /// Rename the underlying file represented by
1327 /// <paramref name="Filename"/>, incidentally renaming all of the
1328 /// databases it contained.
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
1335 public static void Rename(
1336 string Filename, string NewName, DatabaseEnvironment DbEnv) {
1337 Rename(Filename, null, NewName, DbEnv);
1340 /// Rename the database specified by <paramref name="Filename"/> and
1341 /// <paramref name="DatabaseName"/>.
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);
1351 /// Rename the database specified by <paramref name="Filename"/> and
1352 /// <paramref name="DatabaseName"/>.
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.
1365 /// Rename should not be called if the rename is intended to be
1366 /// transactionally safe;
1367 /// <see cref="DatabaseEnvironment.RenameDB"/> should be
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
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);
1384 /// Flush any cached information to disk.
1388 /// If the database is in memory only, Sync has no effect and will
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.
1404 public void Sync() {
1409 /// Empty the database, discarding all records it contains.
1412 /// If the operation occurs in a transactional database, the operation
1413 /// will be implicitly transaction protected.
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
1422 /// The number of records discarded from the database.
1424 public uint Truncate() {
1425 return Truncate(null);
1428 /// Empty the database, discarding all records it contains.
1431 /// If <paramref name="txn"/> is null and the operation occurs in a
1432 /// transactional database, the operation will be implicitly transaction
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.
1443 /// The number of records discarded from the database.
1445 public uint Truncate(Transaction txn) {
1447 db.truncate(Transaction.getDB_TXN(txn), ref countp, 0);
1454 /// Release the resources held by this object, and close the database if
1455 /// it's still open.
1457 public void Dispose() {
1463 GC.SuppressFinalize(this);