public void Put(QdbmKey key, byte[] value) { if (key == null || key.KeyBytes.Length == 0) { throw new ArgumentException("key must be specified", nameof(key)); } if (value == null || value.Length == 0) { throw new ArgumentException("value must be specified", nameof(value)); } _databaseStream.Seek(Constants.OffsetHeaderRecordCount, SeekOrigin.Begin); var existingRecordHeader = GetRecordHeader(key); var keySize = key.KeyBytes.Length; var valueSize = value.Length; var recordHeader = new QdbmRecordHeader { KeySize = keySize, ValueSize = valueSize }; var record = new QdbmRecord(key, recordHeader, value); if (existingRecordHeader?.Size >= recordHeader.Size) { record.Header.Offset = existingRecordHeader.Offset; WriteRecordToDbStream(record); } else { AppendRecordToDbStream(record); } var recordOffset = record.Header.Offset; var bucketOffset = CalculateBucketOffset(record.Key, out var bucketId); _databaseStream.Seek(bucketOffset, SeekOrigin.Begin); var existingRecordOffset = _databaseBinaryReader.ReadInt32(); if (existingRecordOffset == 0) { _databaseStream.Seek(bucketOffset, SeekOrigin.Begin); _databaseBinaryWriter.Write(recordOffset); _buckets[bucketId] = bucketOffset; } else { SetChildOffset(record.Key.SecondaryHashCode, existingRecordOffset, recordOffset); } }
private QdbmRecordHeader ReadRecordHeader(int recordOffset) { _databaseStream.Seek(recordOffset, SeekOrigin.Begin); var header = new QdbmRecordHeader { Offset = recordOffset, Flags = _databaseBinaryReader.ReadInt32(), SecondHashValue = _databaseBinaryReader.ReadInt32(), KeySize = _databaseBinaryReader.ReadInt32(), ValueSize = _databaseBinaryReader.ReadInt32(), PaddingSize = _databaseBinaryReader.ReadInt32(), LeftChildOffset = _databaseBinaryReader.ReadInt32(), RightChildOffset = _databaseBinaryReader.ReadInt32() }; return(header); }
private QdbmRecord ReadRecord(QdbmRecordHeader recordHeader) { _databaseStream.Seek(recordHeader.Offset + Constants.OffsetRecordKeyOffset, SeekOrigin.Begin); var key = _databaseBinaryReader.ReadBytes(recordHeader.KeySize); var value = _databaseBinaryReader.ReadBytes(recordHeader.ValueSize); var qdbmKey = new QdbmKey(key); if (qdbmKey.SecondaryHashCode != recordHeader.SecondHashValue) { throw new InvalidOperationException("Database is corrupt."); } var qdbmRecord = new QdbmRecord(qdbmKey, recordHeader, value); return(qdbmRecord); }
public QdbmRecord(QdbmKey key, QdbmRecordHeader header, byte[] value) { Key = key; Header = header; Value = value; }