Example #1
0
        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);
            }
        }
Example #2
0
        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);
            }
        }
Example #3
0
        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);
        }
Example #4
0
        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;
        }