Skip to content

Commit

Permalink
Add support for backing CDB with a bytes buffer as an alternative to …
Browse files Browse the repository at this point in the history
…a reader.
  • Loading branch information
cipriancraciun committed Dec 25, 2021
1 parent 45c2f51 commit 6c948e5
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 13 deletions.
31 changes: 24 additions & 7 deletions cdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type index [256]table
// create a database, use Writer.
type CDB struct {
reader io.ReaderAt
readerBytes []byte
hash func([]byte) uint32
index index
}
Expand Down Expand Up @@ -48,11 +49,25 @@ func Open(path string) (*CDB, error) {
// was created with a particular hash function, that same hash function must be
// passed to New, or the database will return incorrect results.
func New(reader io.ReaderAt, hash func([]byte) uint32) (*CDB, error) {
return NewFromReaderWithHasher(reader, hash)
}

func NewFromReaderWithHasher(reader io.ReaderAt, hash func ([]byte) uint32) (*CDB, error) {
cdb := &CDB{reader: reader}
return cdb.initialize(hash)
}

func NewFromBufferWithHasher(buffer []byte, hash func ([]byte) uint32) (*CDB, error) {
cdb := &CDB{readerBytes: buffer}
return cdb.initialize(hash)
}

func (cdb *CDB) initialize (hash func ([]byte) uint32) (*CDB, error) {
if hash == nil {
hash = CDBHash
}

cdb := &CDB{reader: reader, hash: hash}
cdb.hash = hash
err := cdb.readIndex()
if err != nil {
return nil, err
Expand Down Expand Up @@ -80,7 +95,7 @@ func (cdb *CDB) GetWithHash(key []byte, hash uint32) ([]byte, error) {

for {
slotOffset := table.offset + (8 * slot)
slotHash, offset, err := readTuple(cdb.reader, slotOffset)
slotHash, offset, err := cdb.readTuple(slotOffset)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -108,6 +123,9 @@ func (cdb *CDB) GetWithHash(key []byte, hash uint32) ([]byte, error) {

// Close closes the database to further reads.
func (cdb *CDB) Close() error {
if cdb.reader == nil {
return nil
}
if closer, ok := cdb.reader.(io.Closer); ok {
return closer.Close()
} else {
Expand All @@ -116,8 +134,7 @@ func (cdb *CDB) Close() error {
}

func (cdb *CDB) readIndex() error {
buf := make([]byte, indexSize)
_, err := cdb.reader.ReadAt(buf, 0)
buf, err := cdb.readAt(0, indexSize)
if err != nil {
return err
}
Expand All @@ -134,7 +151,7 @@ func (cdb *CDB) readIndex() error {
}

func (cdb *CDB) getValueAt(offset uint32, expectedKey []byte) ([]byte, error) {
keyLength, valueLength, err := readTuple(cdb.reader, offset)
keyLength, valueLength, err := cdb.readTuple(offset)
if err != nil {
return nil, err
}
Expand All @@ -144,8 +161,8 @@ func (cdb *CDB) getValueAt(offset uint32, expectedKey []byte) ([]byte, error) {
return nil, nil
}

buf := make([]byte, keyLength+valueLength)
_, err = cdb.reader.ReadAt(buf, int64(offset+8))
var buf []byte
buf, err = cdb.readAt(offset+8, keyLength+valueLength)
if err != nil {
return nil, err
}
Expand Down
6 changes: 3 additions & 3 deletions iterator.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ func (iter *Iterator) Next() bool {
return false
}

keyLength, valueLength, err := readTuple(iter.db.reader, iter.pos)
keyLength, valueLength, err := iter.db.readTuple(iter.pos)
if err != nil {
iter.err = err
return false
}

buf := make([]byte, keyLength+valueLength)
_, err = iter.db.reader.ReadAt(buf, int64(iter.pos+8))
var buf []byte
buf, err = iter.db.readAt(iter.pos+8, keyLength+valueLength)
if err != nil {
iter.err = err
return false
Expand Down
19 changes: 16 additions & 3 deletions util.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,22 @@ import (
"io"
)

func readTuple(r io.ReaderAt, offset uint32) (uint32, uint32, error) {
tuple := make([]byte, 8)
_, err := r.ReadAt(tuple, int64(offset))
func (cdb *CDB) readAt(offset uint32, size uint32) ([]byte, error) {
var buf []byte
if cdb.readerBytes != nil {
buf = cdb.readerBytes[offset : offset + size]
} else {
buf = make([]byte, size)
_, err := cdb.reader.ReadAt(buf, int64 (offset))
if err != nil {
return nil, err
}
}
return buf, nil
}

func (cdb *CDB) readTuple(offset uint32) (uint32, uint32, error) {
tuple, err := cdb.readAt(offset, 8)
if err != nil {
return 0, 0, err
}
Expand Down

0 comments on commit 6c948e5

Please sign in to comment.