代码:BerkeleyDB操作封装
public interface IPut
{
string Key { get; }
}
public class BDBManager : IDisposable
{
/// <summary>
/// 数据库目录
/// </summary>
private string directory;
/// <summary>
/// 数据库文件名
/// </summary>
private string dbName;
private DbBTree btree;
private Txn txn;
private Db db;
private Env env;
/// <summary>
/// 二进制序列化
/// </summary>
private BinaryFormatter formatter;
/// <summary>
/// 键内存流
/// </summary>
private MemoryStream keyStream;
/// <summary>
/// 内容内存流
/// </summary>
private MemoryStream dataStream;
public BDBManager(string directory, string dbName)
{
this.directory = directory;
this.dbName = dbName;
Init();
StreamInit();
}
public bool Set(IPut put)
{
Reset();
keyStream.Position = 0;
formatter.Serialize(keyStream, put.Key);
DbEntry key = DbEntry.InOut(keyStream.GetBuffer(), 0, (int)keyStream.Position);
dataStream.Position = 0;
formatter.Serialize(dataStream, put);
DbEntry data = DbEntry.InOut(dataStream.GetBuffer(), 0, (int)dataStream.Position);
WriteStatus status = btree.Put(txn, ref key, ref data);
switch (status)
{
case WriteStatus.Success:
return true;
case WriteStatus.NotFound:
case WriteStatus.KeyExist:
default:
return false;
}
}
private bool iscomit = false;
public void Commit()
{
txn.Commit(Txn.CommitMode.None);
iscomit = true;
}
public List<IPut> Find()
{
List<IPut> custList = new List<IPut>();
using (DbBTreeCursor cursor = btree.OpenCursor(txn, DbFileCursor.CreateFlags.None))
{
IPut cust = null;
while (GetNextRecord(cursor, ref cust))
custList.Add(cust);
}
return custList;
}
public bool Get(ref IPut put)
{
keyStream.Position = 0;
formatter.Serialize(keyStream, put.Key);
DbEntry key = DbEntry.InOut(keyStream.GetBuffer(), 0, (int)keyStream.Position);
dataStream.SetLength(dataStream.Capacity);
DbEntry data = DbEntry.Out(dataStream.GetBuffer());
while (true)
{
ReadStatus status = btree.Get(txn, ref key, ref data, DbFile.ReadFlags.None);
switch (status)
{
case ReadStatus.Success:
dataStream.Position = 0;
dataStream.SetLength(data.Size);
put = (IPut)formatter.Deserialize(dataStream);
return true;
case ReadStatus.BufferSmall: //扩容
if (key.Buffer.Length < key.Size)
{
keyStream.SetLength(key.Size);
key = DbEntry.Out(keyStream.GetBuffer());
}
if (data.Buffer.Length < data.Size)
{
dataStream.SetLength(data.Size);
data = DbEntry.Out(dataStream.GetBuffer());
}
continue;
case ReadStatus.NotFound:
case ReadStatus.KeyEmpty:
default:
return false;
}
}
}
public bool Remove(IPut put)
{
Reset();
keyStream.Position = 0;
formatter.Serialize(keyStream, put.Key);
DbEntry key = DbEntry.InOut(keyStream.GetBuffer(), 0, (int)keyStream.Position);
DeleteStatus status = btree.Delete(txn, ref key);
switch (status)
{
case DeleteStatus.NotFound:
case DeleteStatus.Success:
return true;
case DeleteStatus.KeyEmpty:
default:
return false;
}
}
public void Dispose()
{
if (!iscomit)
Commit();
db.Close();
db.Close();
}
private void Reset()
{
iscomit = false;
}
private void Init()
{
env = new Env(EnvCreateFlags.None);
Env.OpenFlags envFlags =
Env.OpenFlags.Create |
Env.OpenFlags.InitLock |
Env.OpenFlags.InitLog |
Env.OpenFlags.InitMPool |
Env.OpenFlags.InitTxn |
Env.OpenFlags.Recover;
env.Open(directory, envFlags, 0);
txn = env.TxnBegin(null, Txn.BeginFlags.None);
db = env.CreateDatabase(DbCreateFlags.None);
btree = (DbBTree)db.Open(txn, dbName, null, DbType.BTree, Db.OpenFlags.Create, 0);
}
private void StreamInit()
{
formatter = new BinaryFormatter();
keyStream = new MemoryStream();
dataStream = new MemoryStream();
}
private bool GetNextRecord(DbBTreeCursor cursor, ref IPut cust)
{
ReadStatus status;
keyStream.SetLength(keyStream.Capacity);
dataStream.SetLength(dataStream.Capacity);
DbEntry key = DbEntry.Out(keyStream.GetBuffer());
DbEntry data = DbEntry.Out(dataStream.GetBuffer());
do
{
status = cursor.Get(ref key, ref data, DbFileCursor.GetMode.Next, DbFileCursor.ReadFlags.None);
switch (status)
{
case ReadStatus.NotFound: return false;
case ReadStatus.KeyEmpty: continue; // skip deleted records
case ReadStatus.BufferSmall:
if (key.Buffer.Length < key.Size)
{
keyStream.SetLength(key.Size);
key = DbEntry.Out(keyStream.GetBuffer());
}
if (data.Buffer.Length < data.Size)
{
dataStream.SetLength(data.Size);
data = DbEntry.Out(dataStream.GetBuffer());
}
continue;
case ReadStatus.Success:
dataStream.Position = 0;
dataStream.SetLength(data.Size);
cust = (IPut)formatter.Deserialize(dataStream);
return true;
default:
return false;
}
} while (true);
}
}