private void WriteRecordToDbStream(QdbmRecord rec) { _databaseStream.Seek(rec.Header.Offset, SeekOrigin.Begin); _databaseBinaryWriter.Write(rec.Header.Flags); _databaseBinaryWriter.Write(rec.Key.SecondaryHashCode); _databaseBinaryWriter.Write(rec.Header.KeySize); _databaseBinaryWriter.Write(rec.Header.ValueSize); _databaseBinaryWriter.Write(rec.Header.PaddingSize); _databaseBinaryWriter.Write(0); _databaseBinaryWriter.Write(0); if (rec.Key.KeyBytes.Length > 0) { _databaseBinaryWriter.Write(rec.Key.KeyBytes); } if (rec.Value.Length > 0) { _databaseBinaryWriter.Write(rec.Value); } if (rec.PaddingData?.Length > 0) { _databaseBinaryWriter.Write(rec.PaddingData); } }
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 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); }
private void AppendRecordToDbStream(QdbmRecord rec) { var paddingSize = CalculatePaddingSize(rec.Header.KeySize, rec.Header.ValueSize); rec.PaddingData = new byte[paddingSize]; _databaseStream.Seek(0, SeekOrigin.End); var recordOffset = (int)_databaseStream.Position; rec.Header.Offset = recordOffset; WriteRecordToDbStream(rec); _databaseStream.Seek(Constants.OffsetHeaderRecordCount, SeekOrigin.Begin); _databaseBinaryWriter.Write(Header.RecordCount++); _databaseBinaryWriter.Seek(Constants.OffsetHeaderFileSize, SeekOrigin.Begin); _databaseBinaryWriter.Write(_databaseStream.Length); Header.FileSize = _databaseStream.Length; }