DBT.cs :  » Database » Berkeley-DB » BerkeleyDb » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Database » Berkeley DB 
Berkeley DB » BerkeleyDb » DBT.cs
/*
 * This software is licensed according to the "Modified BSD License",
 * where the following substitutions are made in the license template:
 * <OWNER> = Karl Waclawek
 * <ORGANIZATION> = Karl Waclawek
 * <YEAR> = 2005, 2006
 * It can be obtained from http://opensource.org/licenses/bsd-license.html.
 */

using System;
using System.Collections.Generic;
using System.Security;
using System.Runtime.InteropServices;

namespace BerkeleyDb{
  /* Key/data structure -- a Data-Base Thang. */
  [StructLayout(LayoutKind.Sequential, Pack = Compile.PackSize), CLSCompliant(false)]
  public unsafe struct DBT
  {
    /*
     * data/size must be fields 1 and 2 for DB 1.85 compatibility.
     */
    public void* data;       /* Key/data */
    public UInt32 size;      /* key/data length */

    public UInt32 ulen;      /* RO: length of user buffer. */
    public UInt32 dlen;      /* RO: get/put record length. */
    public UInt32 doff;      /* RO: get/put record offset. */

#if BDB_4_5_20
    public IntPtr app_data;
#endif

    public const UInt32 DB_DBT_APPMALLOC = 0x001;   /* Callback allocated memory. */
    public const UInt32 DB_DBT_ISSET = 0x002;       /* Lower level calls set value. */
    public const UInt32 DB_DBT_MALLOC = 0x004;      /* Return in malloc'd memory. */
    public const UInt32 DB_DBT_PARTIAL = 0x008;     /* Partial put/get. */
    public const UInt32 DB_DBT_REALLOC = 0x010;     /* Return in realloc'd memory. */
#if BDB_4_3_29
    public const UInt32 DB_DBT_USERMEM = 0x020;     /* Return in user's memory. */
    public const UInt32 DB_DBT_DUPOK = 0x040;       /* Insert if duplicate. */
#endif
#if BDB_4_5_20
    public const UInt32 DB_DBT_USERCOPY = 0x020;    /* Use the user-supplied callback. */
    public const UInt32 DB_DBT_USERMEM = 0x040;     /* Return in user's memory. */
    public const UInt32 DB_DBT_DUPOK = 0x080;       /* Insert if duplicate. */
#endif
    public UInt32 flags;

    // for CLSCompliant initialization
    public DBT(int size, int ulen) {
      data = null;
      this.size = unchecked((UInt32)size);
      this.ulen = unchecked((UInt32)ulen);
      dlen = 0;
      doff = 0;
#if BDB_4_5_20
      app_data = IntPtr.Zero;
#endif
      flags = DB_DBT_USERMEM;  // we usually manage memory ourselves
    }

    // for CLSCompliant initialization
    public DBT(int size, int ulen, int dlen, int doff) {
      data = null;
      this.size = unchecked((UInt32)size);
      this.ulen = unchecked((UInt32)ulen);
      this.dlen = unchecked((UInt32)dlen);
      this.doff = unchecked((UInt32)doff);
#if BDB_4_5_20
      app_data = IntPtr.Zero;
#endif
      flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
    }
  }

  /// <summary>Wrapper for the <see cref="DBT">Key/Data Structure.</see></summary>
  [StructLayout(LayoutKind.Sequential)]
  public struct DbEntry:
    IEnumerable<DbEntry.DataItem>,
    IEnumerable<DbEntry.KeyDataItem>,
    IEnumerable<DbEntry.RecNoDataItem>
  {
    internal DBT dbt;
    internal ReturnType retType;
    byte[] buffer;
    int start;

    #region Static Construction

    /// <summary>Returns a <c>DbEntry</c> instance configured for output of a partial record.</summary>
    /// <param name="buffer">Byte buffer to fill. Must be unsigned integer aligned
    /// (rightmost 2 bits of address must be 0). For bulk retrieval, buffer size must
    /// be multiple of 1024 and larger than page size.</param>
    /// <param name="chunkLength">Length of partial record.</param>
    /// <param name="chunkOffset">Offset where partial record starts.</param>
    /// <returns><c>DbEntry</c> instance configured for receiving a partial record.</returns>
    public static DbEntry Out(byte[] buffer, int chunkLength, int chunkOffset) {
      if (buffer == null)
        throw new ArgumentNullException("buffer");
      DbEntry result;
      result.dbt = new DBT(0, buffer.Length, chunkLength, chunkOffset);
      result.buffer = buffer;
      result.start = 0;
      result.retType = ReturnType.Single;
      return result;
    }

    /// <summary>Returns a <c>DbEntry</c> instance configured for output.</summary>
    /// <param name="buffer">Byte buffer to fill. Must be unsigned integer aligned
    /// (rightmost 2 bits of address must be 0). For bulk retrieval, buffer size must
    /// be multiple of 1024 and larger than page size.</param>
    /// <returns><c>DbEntry</c> instance configured for receiving a data record.</returns>
    public static DbEntry Out(byte[] buffer) {
      if (buffer == null)
        throw new ArgumentNullException("buffer");
      DbEntry result;
      result.dbt = new DBT(0, buffer.Length);
      result.buffer = buffer;
      result.start = 0;
      result.retType = ReturnType.Single;
      return result;
    }

    /// <summary>Returns a <c>DbEntry</c> instance configured for input and output of a partial record.</summary>
    /// <param name="buffer">Byte buffer to fill. Must be unsigned integer aligned
    /// (rightmost 2 bits of address must be 0). For bulk retrieval, buffer size must
    /// be multiple of 1024 and larger than page size.</param>
    /// <param name="start">Start index of input data in buffer.</param>
    /// <param name="size">Size of input data in buffer.</param>
    /// <param name="chunkLength">Length of partial record.</param>
    /// <param name="chunkOffset">Offset where partial record starts.</param>
    /// <returns><c>DbEntry</c> instance configured with input data, for receiving a partial record.</returns>
    public static DbEntry InOut(
      byte[] buffer,
      int start,
      int size,
      int chunkLength,
      int chunkOffset) 
    {
      if (buffer == null)
        throw new ArgumentNullException("buffer");
      if (size < 0 || start < 0 || start + size > buffer.Length)
        throw new ArgumentException("Out of bounds.", "start, size");
      DbEntry result;
      result.dbt = new DBT(size, buffer.Length, chunkLength, chunkOffset);
      result.buffer = buffer;
      result.start = start;
      result.retType = ReturnType.Single;
      return result;
    }

    /// <summary>Returns a <c>DbEntry</c> instance configured for input and output.</summary>
    /// <param name="buffer">Byte buffer to fill. Must be unsigned integer aligned
    /// (rightmost 2 bits of address must be 0). For bulk retrieval, buffer size must
    /// be multiple of 1024 and larger than page size.</param>
    /// <param name="start">Start index of input data in buffer.</param>
    /// <param name="size">Size of input data in buffer.</param>
    /// <returns><c>DbEntry</c> instance configured with input data, for receiving a data record.</returns>
    public static DbEntry InOut(byte[] buffer, int start, int size) {
      if (buffer == null)
        throw new ArgumentNullException("buffer");
      if (size < 0 || start < 0 || start + size > buffer.Length)
        throw new ArgumentException("Out of bounds.", "start, size");
      DbEntry result;
      result.dbt = new DBT(size, buffer.Length);
      result.buffer = buffer;
      result.start = start;
      result.retType = ReturnType.Single;
      return result;
    }

    /// <summary>Returns a <c>DbEntry</c> instance configured for input and output.</summary>
    /// <param name="buffer">Byte buffer to fill. Must be unsigned integer aligned
    /// (rightmost 2 bits of address must be 0). For bulk retrieval, buffer size must
    /// be multiple of 1024 and larger than page size.</param>
    /// <returns><c>DbEntry</c> instance configured with input data, for receiving a data record.</returns>
    public static DbEntry InOut(byte[] buffer) {
      if (buffer == null)
        throw new ArgumentNullException("buffer");
      DbEntry result;
      result.dbt = new DBT(buffer.Length, buffer.Length);
      result.buffer = buffer;
      result.start = 0;
      result.retType = ReturnType.Single;
      return result;
    }

    /// <summary>Returns a <c>DbEntry</c> instance configured for the case when
    /// no data are to be retrieved.</summary>
    /// <remarks>Used for checking if a record exists, without actually retrieving it.</remarks>
    /// <returns>An empty <c>DbEntry</c> instance.</returns>
    public static DbEntry EmptyOut() {
      DbEntry result = new DbEntry();        // initializes all fields to 0
      result.dbt.flags = DBT.DB_DBT_PARTIAL;  // required to return no data
      // result.retType = ReturnType.Single;
      return result;
    }

    #endregion

    #region Helpers

    /// <summary>Sets return type based on access method and BDB bulk retrieval flags.</summary>
    /// <param name="dbType">Access method, e.g. DbType.BTree.</param>
    /// <param name="flags">Bulk retrieval flags, e.g. DB_MULTIPLE, DB_MULTIPLE_KEY.</param>
    [CLSCompliant(false)]
    public void SetReturnType(DbType dbType, uint flags) {
      retType = ReturnType.Single;
      if ((DbConst.DB_MULTIPLE & flags) != 0)
        retType = ReturnType.Multiple;
      else if ((DbConst.DB_MULTIPLE_KEY & flags) != 0) {
        switch (dbType) {
          case DbType.Recno:
            goto case DbType.Queue;
          case DbType.Queue:
            retType = ReturnType.MultipleRecNo;
            break;
          case DbType.BTree:
            goto case DbType.Hash;
          case DbType.Hash:
            retType = ReturnType.MultipleKey;
            break;
        }
      }
    }

    #endregion

    #region Public Operations & Properties

    /// <summary>Resizes buffer, preserving existing data.</summary>
    /// <param name="newLength">New buffer length, must not cause truncation of existing data.</param>
    public void ResizeBuffer(int newLength) {
      if (newLength < (start + Size))
        throw new ArgumentException("Must not truncate data in buffer.", "newLength");
      Array.Resize<byte>(ref buffer, newLength);
      dbt.ulen = unchecked((UInt32)newLength);
    }

    /// <summary>Byte buffer holding input and output data.</summary>
    public byte[] Buffer {
      get { return buffer; }
    }

    /// <summary>Start index of data in buffer.</summary>
    public int Start {
      get { return start; }
    }

    /// <summary>Size of input or output data.</summary>
    public int Size {
      get { return unchecked((int)dbt.size); }
    }

    /// <summary>Length of partial database record to update or retrieve.</summary>
    public int ChunkLength {
      get { return unchecked((int)dbt.dlen); }
    }

    /// <summary>Offset of partial database record to update or retrieve.</summary>
    public int ChunkOffset {
      get { return unchecked((int)dbt.doff); }
    }

    /// <summary>Indicates how records were retrieved (single or bulk).</summary>
    public ReturnType RetType {
      get { return retType; }
    }

    /// <summary>Bulk retrieval interface to iterate over multiple data records.</summary>
    public IEnumerable<DataItem> DataItems {
      get { return this; }
    }

    /// <summary>Bulk retrieval interface to iterate over multiple key/data pairs.</summary>
    public IEnumerable<KeyDataItem> KeyDataItems {
      get { return this; }
    }

    /// <summary>Bulk retrieval interface to iterate over multiple record number/data pairs.</summary>
    public IEnumerable<RecNoDataItem> RecNoDataItems {
      get { return this; }
    }

    #endregion

    #region IEnumerable, IEnumerable<T> Members

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
      switch (retType) {
        case ReturnType.Single: return new SingleEnumerator(Size);
        case ReturnType.Multiple: return new DataEnumerator(buffer, buffer.Length);
        case ReturnType.MultipleKey: return new KeyDataEnumerator(buffer, buffer.Length);
        case ReturnType.MultipleRecNo: return new RecNoDataEnumerator(buffer, buffer.Length);
        default: return null;
      }
    }

    IEnumerator<DataItem> IEnumerable<DataItem>.GetEnumerator() {
      if (retType == ReturnType.Single)
          return new SingleEnumerator(Size);
      else if (retType == ReturnType.Multiple)
        return new DataEnumerator(buffer, buffer.Length);
      else
        throw new BdbException("No DataItems available.");
    }

    IEnumerator<KeyDataItem> IEnumerable<KeyDataItem>.GetEnumerator() {
      if (retType == ReturnType.MultipleKey)
        return new KeyDataEnumerator(buffer, buffer.Length);
      else
        throw new BdbException("No KeyDataItems available.");
    }

    IEnumerator<RecNoDataItem> IEnumerable<RecNoDataItem>.GetEnumerator() {
      if (retType == ReturnType.MultipleRecNo)
         return new RecNoDataEnumerator(buffer, buffer.Length);
      else
         throw new BdbException("No RecNoDataItems available.");
     }

    #endregion

    #region Nested Types

    /// <summary>Indicates if data were retrieved as single records or in bulk.</summary>
    public enum ReturnType
    {
      Single = 0,
      Multiple,
      MultipleKey,
      MultipleRecNo
    }

    /// <summary>Represents data record for bulk retrieval.</summary>
    public struct DataItem
    {
      internal int start;
      internal int size;
      internal bool deleted;

      public int Start {
        get { return start; }
      }

      public int Size {
        get { return size; }
      }

      public bool Deleted {
        get { return deleted; }
      }
    }

    /// <summary>Represents key/data pair for bulk retrieval.</summary>
    public struct KeyDataItem
    {
      internal int keyStart;
      internal int keySize;
      internal int dataStart;
      internal int dataSize;

       public int KeyStart {
        get { return keyStart; }
      }

      public int KeySize {
        get { return keySize; }
      }
      
      public int DataStart {
        get { return dataStart; }
      }

      public int DataSize {
        get { return dataSize; }
      }
    }

    /// <summary>Represents record number/data pair for bulk retrieval.</summary>
    public struct RecNoDataItem
    {
      internal int recNo;
      internal int start;
      internal int size;

      public int RecNo {
        get { return recNo; }
      }

      public int Start {
        get { return start; }
      }

      public int Size {
        get { return size; }
      }
    }

    private abstract class BaseEnumerator: IDisposable
    {
      #region IDisposable Members

      public void Dispose() { }

      #endregion
    }

    private class SingleEnumerator: BaseEnumerator, IEnumerator<DataItem>
    {
      DataItem current = new DataItem();
      bool valid = false;
      bool done = false;

      public SingleEnumerator(int size) {
        current.size = size;
      }

      #region IEnumerator<DataItem> Members

      public DataItem Current {
        get {
          if (valid)
            return current;
          else
            throw new InvalidOperationException("Enumerator position invalid.");
        }
      }

      public bool MoveNext() {
        if (done) {
          valid = false;
          return false;
        }
        else {
          done = true;
          valid = true;
          return true;
        }
      }

      #endregion

      #region IEnumerator Members

      object System.Collections.IEnumerator.Current {
        get { return Current; }
      }

      public void Reset() {
        valid = false;
        done = false;
      }

      #endregion
    }

    private abstract class MultipleEnumerator: BaseEnumerator
    {
      protected byte[] buffer;
      protected int iterIndex;
      protected bool valid = false;
      int dataLen;

      // buffer must be multiple of 1024, larger than page size and unsigned integer aligned
      public MultipleEnumerator(byte[] buffer, int dataLen) {
        this.buffer = buffer;
        this.dataLen = dataLen;
        iterIndex = dataLen - sizeof(Int32);
      }

      #region IEnumerator Members

      public void Reset() {
        valid = false;
        iterIndex = dataLen - sizeof(Int32);
      }

      #endregion
    }

    private class DataEnumerator: MultipleEnumerator, IEnumerator<DataItem>
    {
      DataItem current = new DataItem();

      public DataEnumerator(byte[] buffer, int len) : base(buffer, len) { }

      #region IEnumerator<DataItem> Members

      public DataItem Current {
        get {
          if (valid)
            return current;
          else
            throw new InvalidOperationException("Enumerator position invalid.");
        }
      }

      public bool MoveNext() {
        Int32 start = BitConverter.ToInt32(buffer, iterIndex);
        iterIndex -= sizeof(Int32);
        if (start == -1) {
          valid = false;
          return false;
        }
        Int32 size = BitConverter.ToInt32(buffer, iterIndex);
        iterIndex -= sizeof(Int32);
        current.deleted = size == 0 && start == 0;
        current.start = start;
        current.size = size;
        valid = true;
        return true;
      }

      #endregion

      #region IEnumerator Members

      object System.Collections.IEnumerator.Current {
        get { return Current; }
      }

      #endregion
}

    private class KeyDataEnumerator: MultipleEnumerator, IEnumerator<KeyDataItem>
    {
      KeyDataItem current = new KeyDataItem();

      public KeyDataEnumerator(byte[] buffer, int len) : base(buffer, len) { }

      #region IEnumerator<KeyDataItem> Members

      public KeyDataItem Current {
        get {
          if (valid)
            return current;
          else
            throw new InvalidOperationException("Enumerator position invalid.");
        }
      }

      public bool MoveNext() {
        Int32 start = BitConverter.ToInt32(buffer, iterIndex);
        iterIndex -= sizeof(Int32);
        if (start == -1) {
          valid = false;
          return false;
        }
        current.keyStart = start;
        current.keySize = BitConverter.ToInt32(buffer, iterIndex);
        iterIndex -= sizeof(Int32);
        current.dataStart = BitConverter.ToInt32(buffer, iterIndex);
        iterIndex -= sizeof(Int32);
        current.dataSize = BitConverter.ToInt32(buffer, iterIndex);
        iterIndex -= sizeof(Int32);
        valid = true;
        return true;
      }

      #endregion

      #region IEnumerator Members

      object System.Collections.IEnumerator.Current {
        get { return Current; }
      }

      #endregion
    }

    private class RecNoDataEnumerator: MultipleEnumerator, IEnumerator<RecNoDataItem>
    {
      RecNoDataItem current = new RecNoDataItem();

      public RecNoDataEnumerator(byte[] buffer, int len) : base(buffer, len) { }

      #region IEnumerator<RecNoDataItem> Members

      public RecNoDataItem Current {
        get {
          if (valid)
            return current;
          else
            throw new InvalidOperationException("Enumerator position invalid.");
        }
      }

      public unsafe bool MoveNext() {
        Int32 recno = BitConverter.ToInt32(buffer, iterIndex);
        iterIndex -= sizeof(Int32);
        if (recno == 0) {
          valid = false;
          return false;
        }
        current.recNo = recno;
        Int32 start = BitConverter.ToInt32(buffer, iterIndex);
        iterIndex -= sizeof(Int32);
        Int32 size = BitConverter.ToInt32(buffer, iterIndex);
        iterIndex -= sizeof(Int32);
        current.start = start;
        current.size = size;
        valid = true;
        return true;
      }

      #endregion

      #region IEnumerator Members

      object System.Collections.IEnumerator.Current {
        get { return Current; }
      }

      #endregion
    }

    #endregion
  }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.