/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2009 Oracle. All rights reserved.
*
*/
using System;
using System.Collections.Generic;
using System.Text;
using BerkeleyDB.Internal;
namespace BerkeleyDB {
///
/// A class representing a SecondaryBTreeDatabase. The Btree format is a
/// representation of a sorted, balanced tree structure.
///
public class SecondaryBTreeDatabase : SecondaryDatabase {
private EntryComparisonDelegate compareHandler;
private EntryComparisonDelegate prefixCompareHandler;
private EntryComparisonDelegate dupCompareHandler;
private BDB_CompareDelegate doCompareRef;
private BDB_CompareDelegate doPrefixCompareRef;
private BDB_CompareDelegate doDupCompareRef;
#region Constructors
internal SecondaryBTreeDatabase(DatabaseEnvironment env, uint flags)
: base(env, flags) { }
private void Config(SecondaryBTreeDatabaseConfig cfg) {
base.Config((SecondaryDatabaseConfig)cfg);
db.set_flags(cfg.flags);
if (cfg.Compare != null)
Compare = cfg.Compare;
if (cfg.PrefixCompare != null)
PrefixCompare = cfg.PrefixCompare;
if (cfg.DuplicateCompare != null)
DupCompare = cfg.DuplicateCompare;
if (cfg.minkeysIsSet)
db.set_bt_minkey(cfg.MinKeysPerPage);
}
///
/// Instantiate a new SecondaryBTreeDatabase object, open the
/// database represented by and associate
/// the database with the
/// primary index.
///
///
///
/// If is null, the database is strictly
/// temporary and cannot be opened by any other thread of control, thus
/// the database can only be accessed by sharing the single database
/// object that created it, in circumstances where doing so is safe.
///
///
/// If is set, the operation
/// will be implicitly transaction protected. Note that transactionally
/// protected operations on a datbase object requires the object itself
/// be transactionally protected during its open.
///
///
///
/// The name of an underlying file that will be used to back the
/// database. In-memory databases never intended to be preserved on disk
/// may be created by setting this parameter to null.
///
/// The database's configuration
/// A new, open database object
public static SecondaryBTreeDatabase Open(
string Filename, SecondaryBTreeDatabaseConfig cfg) {
return Open(Filename, null, cfg, null);
}
///
/// Instantiate a new SecondaryBTreeDatabase object, open the
/// database represented by and associate
/// the database with the
/// primary index.
///
///
///
/// If both and
/// are null, the database is strictly
/// temporary and cannot be opened by any other thread of control, thus
/// the database can only be accessed by sharing the single database
/// object that created it, in circumstances where doing so is safe. If
/// is null and
/// is non-null, the database can be
/// opened by other threads of control and will be replicated to client
/// sites in any replication group.
///
///
/// If is set, the operation
/// will be implicitly transaction protected. Note that transactionally
/// protected operations on a datbase object requires the object itself
/// be transactionally protected during its open.
///
///
///
/// The name of an underlying file that will be used to back the
/// database. In-memory databases never intended to be preserved on disk
/// may be created by setting this parameter to null.
///
///
/// This parameter allows applications to have multiple databases in a
/// single file. Although no DatabaseName needs to be specified, it is
/// an error to attempt to open a second database in a file that was not
/// initially created using a database name.
///
/// The database's configuration
/// A new, open database object
public static SecondaryBTreeDatabase Open(string Filename,
string DatabaseName, SecondaryBTreeDatabaseConfig cfg) {
return Open(Filename, DatabaseName, cfg, null);
}
///
/// Instantiate a new SecondaryBTreeDatabase object, open the
/// database represented by and associate
/// the database with the
/// primary index.
///
///
///
/// If is null, the database is strictly
/// temporary and cannot be opened by any other thread of control, thus
/// the database can only be accessed by sharing the single database
/// object that created it, in circumstances where doing so is safe.
///
///
/// If is null, but
/// is set, the operation will
/// be implicitly transaction protected. Note that transactionally
/// protected operations on a datbase object requires the object itself
/// be transactionally protected during its open. Also note that the
/// transaction must be committed before the object is closed.
///
///
///
/// The name of an underlying file that will be used to back the
/// database. In-memory databases never intended to be preserved on disk
/// may be created by setting this parameter to null.
///
/// The database's configuration
///
/// If the operation is part of an application-specified transaction,
/// is a Transaction object returned from
/// ; if
/// the operation is part of a Berkeley DB Concurrent Data Store group,
/// is a handle returned from
/// ; otherwise null.
///
/// A new, open database object
public static SecondaryBTreeDatabase Open(string Filename,
SecondaryBTreeDatabaseConfig cfg, Transaction txn) {
return Open(Filename, null, cfg, txn);
}
///
/// Instantiate a new SecondaryBTreeDatabase object, open the
/// database represented by and associate
/// the database with the
/// primary index.
///
///
///
/// If both and
/// are null, the database is strictly
/// temporary and cannot be opened by any other thread of control, thus
/// the database can only be accessed by sharing the single database
/// object that created it, in circumstances where doing so is safe. If
/// is null and
/// is non-null, the database can be
/// opened by other threads of control and will be replicated to client
/// sites in any replication group.
///
///
/// If is null, but
/// is set, the operation will
/// be implicitly transaction protected. Note that transactionally
/// protected operations on a datbase object requires the object itself
/// be transactionally protected during its open. Also note that the
/// transaction must be committed before the object is closed.
///
///
///
/// The name of an underlying file that will be used to back the
/// database. In-memory databases never intended to be preserved on disk
/// may be created by setting this parameter to null.
///
///
/// This parameter allows applications to have multiple databases in a
/// single file. Although no DatabaseName needs to be specified, it is
/// an error to attempt to open a second database in a file that was not
/// initially created using a database name.
///
/// The database's configuration
///
/// If the operation is part of an application-specified transaction,
/// is a Transaction object returned from
/// ; if
/// the operation is part of a Berkeley DB Concurrent Data Store group,
/// is a handle returned from
/// ; otherwise null.
///
/// A new, open database object
public static SecondaryBTreeDatabase Open(
string Filename, string DatabaseName,
SecondaryBTreeDatabaseConfig cfg, Transaction txn) {
SecondaryBTreeDatabase ret = new SecondaryBTreeDatabase(cfg.Env, 0);
ret.Config(cfg);
ret.db.open(Transaction.getDB_TXN(txn), Filename,
DatabaseName, cfg.DbType.getDBTYPE(), cfg.openFlags, 0);
ret.isOpen = true;
ret.doAssocRef = new BDB_AssociateDelegate(
SecondaryDatabase.doAssociate);
cfg.Primary.db.associate(Transaction.getDB_TXN(null),
ret.db, ret.doAssocRef, cfg.assocFlags);
if (cfg.ForeignKeyDatabase != null) {
if (cfg.OnForeignKeyDelete == ForeignKeyDeleteAction.NULLIFY)
ret.doNullifyRef =
new BDB_AssociateForeignDelegate(doNullify);
else
ret.doNullifyRef = null;
cfg.ForeignKeyDatabase.db.associate_foreign(
ret.db, ret.doNullifyRef, cfg.foreignFlags);
}
return ret;
}
#endregion Constructors
#region Callbacks
private static int doDupCompare(
IntPtr dbp, IntPtr dbt1p, IntPtr dbt2p) {
DB db = new DB(dbp, false);
DBT dbt1 = new DBT(dbt1p, false);
DBT dbt2 = new DBT(dbt2p, false);
return ((SecondaryBTreeDatabase)(db.api_internal)).DupCompare(
DatabaseEntry.fromDBT(dbt1), DatabaseEntry.fromDBT(dbt2));
}
private static int doCompare(IntPtr dbp, IntPtr dbtp1, IntPtr dbtp2) {
DB db = new DB(dbp, false);
DBT dbt1 = new DBT(dbtp1, false);
DBT dbt2 = new DBT(dbtp2, false);
SecondaryBTreeDatabase tmp =
(SecondaryBTreeDatabase)db.api_internal;
return tmp.compareHandler(
DatabaseEntry.fromDBT(dbt1), DatabaseEntry.fromDBT(dbt2));
}
private static int doPrefixCompare(
IntPtr dbp, IntPtr dbtp1, IntPtr dbtp2) {
DB db = new DB(dbp, false);
DBT dbt1 = new DBT(dbtp1, false);
DBT dbt2 = new DBT(dbtp2, false);
SecondaryBTreeDatabase tmp =
(SecondaryBTreeDatabase)db.api_internal;
return tmp.prefixCompareHandler(
DatabaseEntry.fromDBT(dbt1), DatabaseEntry.fromDBT(dbt2));
}
#endregion Callbacks
#region Properties
// Sorted alpha by property name
///
/// The Btree key comparison function. The comparison function is called
/// whenever it is necessary to compare a key specified by the
/// application with a key currently stored in the tree.
///
public EntryComparisonDelegate Compare {
get { return compareHandler; }
private set {
if (value == null)
db.set_bt_compare(null);
else if (compareHandler == null) {
if (doCompareRef == null)
doCompareRef = new BDB_CompareDelegate(doCompare);
db.set_bt_compare(doCompare);
}
compareHandler = value;
}
}
///
/// The duplicate data item comparison function.
///
public EntryComparisonDelegate DupCompare {
get { return dupCompareHandler; }
private set {
/* Cannot be called after open. */
if (value == null)
db.set_dup_compare(null);
else if (dupCompareHandler == null) {
if (doDupCompareRef == null)
doDupCompareRef = new BDB_CompareDelegate(doDupCompare);
db.set_dup_compare(doDupCompareRef);
}
dupCompareHandler = value;
}
}
///
/// Whether the insertion of duplicate data items in the database is
/// permitted, and whether duplicates items are sorted.
///
public DuplicatesPolicy Duplicates {
get {
uint flags = 0;
db.get_flags(ref flags);
if ((flags & DbConstants.DB_DUPSORT) != 0)
return DuplicatesPolicy.SORTED;
else if ((flags & DbConstants.DB_DUP) != 0)
return DuplicatesPolicy.UNSORTED;
else
return DuplicatesPolicy.NONE;
}
}
///
/// The minimum number of key/data pairs intended to be stored on any
/// single Btree leaf page.
///
public uint MinKeysPerPage {
get {
uint ret = 0;
db.get_bt_minkey(ref ret);
return ret;
}
}
///
/// If false, empty pages will not be coalesced into higher-level pages.
///
public bool ReverseSplit {
get {
uint flags = 0;
db.get_flags(ref flags);
return (flags & DbConstants.DB_REVSPLITOFF) == 0;
}
}
///
/// The Btree prefix function. The prefix function is used to determine
/// the amount by which keys stored on the Btree internal pages can be
/// safely truncated without losing their uniqueness.
///
public EntryComparisonDelegate PrefixCompare {
get { return prefixCompareHandler; }
private set {
if (value == null)
db.set_bt_prefix(null);
else if (prefixCompareHandler == null) {
if (doPrefixCompareRef == null)
doPrefixCompareRef =
new BDB_CompareDelegate(doPrefixCompare);
db.set_bt_prefix(doPrefixCompareRef);
}
prefixCompareHandler = value;
}
}
///
/// If true, this object supports retrieval from the Btree using record
/// numbers.
///
public bool RecordNumbers {
get {
uint flags = 0;
db.get_flags(ref flags);
return (flags & DbConstants.DB_RECNUM) != 0;
}
}
#endregion Properties
}
}