Find 方法
public List Find()
{
var list = new List();
using (var cursor = _btree.OpenCursor(_txn, DbFileCursor.CreateFlags.None))
{
IPut item = null;
while (GetNextRecord(cursor, ref item))
list.Add(item);
}
return list;
}
GetNextRecord 核心邏輯
bool GetNextRecord(DbBTreeCursor cursor, ref IPut item)
{
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; // 跳過已刪除
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);
item = (IPut)_formatter.Deserialize(_dataStream);
return true;
default: return false;
}
} while (true);
}
關鍵點
DbEntry.Out 僅提供輸出緩衝區,BufferSmall 時需根據 Size 屬性擴容流並重新包裝。
KeyEmpty 表示槽位存在但已刪除,需 continue 跳過。
- 反序列化前必須
Position=0 並 SetLength(data.Size) 截取有效字節。
using 確保游標釋放。