/*- * 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 that provides an arbitrary number of persistent objects that /// return an increasing or decreasing sequence of integers. /// public class Sequence : IDisposable { private DB_SEQUENCE seq; private bool isOpen; /// /// Instantiate a new Sequence object. /// /// /// If is null and the operation occurs in a /// transactional database, the operation will be implicitly transaction /// protected. /// /// Configuration parameters for the Sequence public Sequence(SequenceConfig cfg) : this(cfg, null) { } /// /// Instantiate a new Sequence object. /// /// /// If is null and the operation occurs in a /// transactional database, the operation will be implicitly transaction /// protected. /// /// Configuration parameters for the Sequence /// /// 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. /// public Sequence(SequenceConfig cfg, Transaction txn) { seq = new DB_SEQUENCE(cfg.BackingDatabase.db, 0); if (cfg.initialValIsSet) seq.initial_value(cfg.InitialValue); seq.set_flags(cfg.flags); if (cfg.rangeIsSet) seq.set_range(cfg.Min, cfg.Max); if (cfg.cacheSzIsSet) seq.set_cachesize(cfg.CacheSize); seq.open(Transaction.getDB_TXN(txn), cfg.key, cfg.openFlags); isOpen = true; } /// /// Close the sequence handle. Any unused cached values are lost. /// public void Close() { isOpen = false; seq.close(0); } /// /// Return the next available element in the sequence and change the /// sequence value by . /// /// /// /// If there are enough cached values in the sequence handle then they /// will be returned. Otherwise the next value will be fetched from the /// database and incremented (decremented) by enough to cover the delta /// and the next batch of cached values. /// /// /// For maximum concurrency a non-zero cache size should be specified /// prior to opening the sequence handle and /// should be specified for each Get method call. /// /// /// By default, sequence ranges do not wrap; to cause the sequence to /// wrap around the beginning or end of its range, set /// to true. /// /// /// If was opened in a transaction, /// calling Get may result in changes to the sequence object; these /// changes will be automatically committed in a transaction internal to /// the Berkeley DB library. If the thread of control calling Get has an /// active transaction, which holds locks on the same database as the /// one in which the sequence object is stored, it is possible for a /// thread of control calling Get to self-deadlock because the active /// transaction's locks conflict with the internal transaction's locks. /// For this reason, it is often preferable for sequence objects to be /// stored in their own database. /// /// /// /// The amount by which to increment the sequence value. Must be /// greater than 0. /// /// The next available element in the sequence. public Int64 Get(int Delta) { return Get(Delta, false, null); } /// /// Return the next available element in the sequence and change the /// sequence value by . /// /// /// The amount by which to increment the sequence value. Must be /// greater than 0. /// /// /// If true, and if the operation is implicitly transaction protected, /// do not synchronously flush the log when the transaction commits. /// /// The next available element in the sequence. public Int64 Get(int Delta, bool NoSync) { return Get(Delta, NoSync, null); } /// /// Return the next available element in the sequence and change the /// sequence value by . /// /// /// The amount by which to increment the sequence value. Must be /// greater than 0. /// /// /// 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. /// Must be null if the sequence was opened with a non-zero cache size. /// /// The next available element in the sequence. public Int64 Get(int Delta, Transaction txn) { return Get(Delta, false, txn); } private Int64 Get(int Delta, bool NoSync, Transaction txn) { Int64 ret = DbConstants.DB_AUTO_COMMIT; uint flags = NoSync ? DbConstants.DB_TXN_NOSYNC : 0; seq.get(Transaction.getDB_TXN(txn), Delta, ref ret, flags); return ret; } /// /// The database used by the sequence. /// public Database BackingDatabase { get { return Database.fromDB(seq.get_db()); } } /// /// The key for the sequence. /// public DatabaseEntry Key { get { DatabaseEntry ret = new DatabaseEntry(); seq.get_key(ret); return ret; } } /// /// Print diagnostic information. /// public void PrintStats() { PrintStats(false); } /// /// Print diagnostic information. /// /// /// The diagnostic information is described by /// . /// /// /// If true, reset statistics after printing. /// public void PrintStats(bool ClearStats) { uint flags = 0; flags |= ClearStats ? DbConstants.DB_STAT_CLEAR : 0; seq.stat_print(flags); } /// /// Remove the sequence from the database. /// public void Remove() { Remove(false, null); } /// /// Remove the sequence from the database. /// /// /// If true, and if the operation is implicitly transaction protected, /// do not synchronously flush the log when the transaction commits. /// public void Remove(bool NoSync) { Remove(NoSync, null); } /// /// Remove the sequence from the database. /// /// /// 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. /// public void Remove(Transaction txn) { Remove(false, txn); } private void Remove(bool NoSync, Transaction txn) { uint flags = NoSync ? DbConstants.DB_TXN_NOSYNC : 0; isOpen = false; seq.remove(Transaction.getDB_TXN(txn), flags); } /// /// Return statistical information for this sequence. /// /// Statistical information for this sequence. public SequenceStats Stats() { return Stats(false); } /// /// Return statistical information for this sequence. /// /// /// /// In the presence of multiple threads or processes accessing an active /// sequence, the information returned by DB_SEQUENCE->stat() may be /// out-of-date. /// /// /// The DB_SEQUENCE->stat() method cannot be transaction-protected. For /// this reason, it should be called in a thread of control that has no /// open cursors or active transactions. /// /// /// If true, reset statistics. /// Statistical information for this sequence. public SequenceStats Stats(bool clear) { uint flags = 0; flags |= clear ? DbConstants.DB_STAT_CLEAR : 0; SequenceStatStruct st = seq.stat(flags); return new SequenceStats(st); } /// /// Release the resources held by this object, and close the sequence if /// it's still open. /// public void Dispose() { if (isOpen) seq.close(0); seq.Dispose(); GC.SuppressFinalize(this); } /// /// The current cache size. /// public int Cachesize { get { int ret = 0; seq.get_cachesize(ref ret); return ret; } } /// /// The minimum value in the sequence. /// public Int64 Min { get { Int64 ret = 0; Int64 tmp = 0; seq.get_range(ref ret, ref tmp); return ret; } } /// /// The maximum value in the sequence. /// public Int64 Max { get { Int64 ret = 0; Int64 tmp = 0; seq.get_range(ref tmp, ref ret); return ret; } } /// /// If true, the sequence should wrap around when it is incremented /// (decremented) past the specified maximum (minimum) value. /// public bool Wrap { get { uint flags = 0; seq.get_flags(ref flags); return (flags & DbConstants.DB_SEQ_WRAP) != 0; } } /// /// If true, the sequence will be incremented. This is the default. /// public bool Increment { get { uint flags = 0; seq.get_flags(ref flags); return (flags & DbConstants.DB_SEQ_INC) != 0; } } /// /// If true, the sequence will be decremented. /// public bool Decrement { get { uint flags = 0; seq.get_flags(ref flags); return (flags & DbConstants.DB_SEQ_DEC) != 0; } } } }