Exemple #1
0
        /// <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);
        }
Exemple #2
0
        /// <summary>
        /// Find the next record stored under the given <paramref name="key"/>.
        /// </summary>
        /// <returns>The next record stored under the given key,
        /// or <c>null</c> if no more records can be found.</returns>
        public byte[] FindNext(byte[] key)
        {
            // We change object state in here, so nobody must intervene!
            lock (_syncLock)
            {
                if (_cdbFile == null)
                {
                    throw new ObjectDisposedException(GetType().Name);
                }

                // Initialize: locate hash table and entry in it:
                if (_loop == 0)
                {
                    UInt32 u = Cdb.Hash(key);

                    // Get hash table len&pos for this key:
                    UInt32 slot = u & 255;
                    _hslots = _heads[(slot << 1) + 1];
                    if (_hslots == 0)
                    {
                        return(null);
                    }
                    _hpos = _heads[slot << 1];

                    // Remember this key's hash:
                    _khash = u;

                    // Locate the slot in the table at _hpos:
                    u   >>= 8;
                    u    %= _hslots;
                    u   <<= 3;
                    _kpos = _hpos + u;
                }

                // Search: iterate all hash slots for the given key:
                var bytes = new byte[8];
                while (_loop < _hslots)
                {
                    // Read the entry for this key from the hash slot
                    CdbRead(bytes, 8, _kpos);
                    UInt32 h   = Cdb.UnpackInt32(bytes, 0);
                    UInt32 pos = Cdb.UnpackInt32(bytes, 4);
                    if (pos == 0)
                    {
                        break;
                    }

                    // Advance loop counter and key position.
                    // Wrap key position if at end of hash table.
                    _loop += 1;
                    _kpos += 8;
                    if (_kpos == (_hpos + (_hslots << 3)))
                    {
                        _kpos = _hpos;
                    }

                    // Different hash? Probe next slot...
                    if (h != _khash)
                    {
                        continue;
                    }

                    // Jump to the record and see if key matches:
                    CdbRead(bytes, 8, pos);
                    UInt32 klen = Cdb.UnpackInt32(bytes, 0);
                    if (klen != key.Length)
                    {
                        continue;
                    }
                    if (!CdbMatch(key))
                    {
                        continue;
                    }
                    UInt32 dlen = Cdb.UnpackInt32(bytes, 4);

                    // Keys match: fetch the data
                    var data = new byte[dlen];
                    CdbRead(data, data.Length);
                    return(data);
                }

                return(null);                // No such key
            }
        }