/// <summary> /// Add a key/data pair to the database. /// </summary> /// <param name="key">The key.</param> /// <param name="data">The data.</param> public void Add(byte[] key, byte[] data) { if (_file == null) { throw new ObjectDisposedException(GetType().Name); } var bytes = new byte[8]; Cdb.PackInt32((UInt32)key.Length, bytes, 0); Cdb.PackInt32((UInt32)data.Length, bytes, 4); // Write the record: keylen, datalen, key, data. _file.Write(bytes, 0, bytes.Length); _file.Write(key, 0, key.Length); _file.Write(data, 0, data.Length); // Add hash and offset to the in-memory list: UInt32 hash = Cdb.Hash(key); _hashInfo.Add(new HashPos(hash, _pos)); _hashSize[hash & 255] += 1; // one more entry // Update the file position pointer: AdvancePos(8); // key and data length AdvancePos((UInt32)key.Length); AdvancePos((UInt32)data.Length); }
private void Finish() { // Find the start of each hash table var tableStart = new UInt32[256]; UInt32 start = 0; for (int i = 0; i < 256; i++) { start += _hashSize[i]; tableStart[i] = start; } // Create a new hash info table in order by hash table var table = new HashPos[_hashInfo.Count]; foreach (var hp in _hashInfo) { table[--tableStart[hp.Hash & 255]] = hp; } var eightBytes = new byte[8]; var fixedTable = new byte[2048]; // Append each of the hash tables to the end of the file. // Along the way, build the fixed table (to be written later). for (int i = 0; i < 256; i++) { UInt32 len = _hashSize[i] * 2; // len of i-th hash table // Remember pos and len of i-th hash table in fixed table: Cdb.PackInt32(_pos, fixedTable, i * 8); Cdb.PackInt32(len, fixedTable, i * 8 + 4); // Build the i-th hash table: UInt32 tableIndex = tableStart[i]; var hashTable = new HashPos[len]; for (uint u = 0; u < _hashSize[i]; u++) { HashPos hp = table[tableIndex++]; // Locate a free entry in the hash table: UInt32 where = (hp.Hash >> 8) % len; while (hashTable[where].Pos != 0) { if (++where == len) { where = 0; // wrap around } } hashTable[where] = hp; // and store the (hash,pos) pair } // Append to the end of the CDB file: for (uint u = 0; u < len; u++) { Cdb.PackInt32(hashTable[u].Hash, eightBytes, 0); Cdb.PackInt32(hashTable[u].Pos, eightBytes, 4); _file.Write(eightBytes, 0, 8); AdvancePos(8); } } // Rewind to the start of the file and write the fixed-size table: _file.Seek(0, SeekOrigin.Begin); _file.Write(fixedTable, 0, fixedTable.Length); }