Skip to content

Commit

Permalink
ethdb/rocksdb: fixed iterator & added tests
Browse files Browse the repository at this point in the history
  • Loading branch information
sadoci committed Nov 19, 2021
1 parent b89baa7 commit 98bc33d
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 28 deletions.
73 changes: 45 additions & 28 deletions ethdb/rocksdb/rocksdb.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// rocksdb.go
//go:build rocksdb
// +build rocksdb

package rocksdb
Expand Down Expand Up @@ -35,6 +36,7 @@ type RDBDatabase struct {
type RDBIterator struct {
it *C.rocksdb_iterator_t
opts *C.rocksdb_readoptions_t
first bool
lowerBound []byte
upperBound []byte
}
Expand Down Expand Up @@ -163,28 +165,57 @@ func (db *RDBDatabase) NewIterator(prefix, start []byte) ethdb.Iterator {
begin = append(begin, start...)

opts := C.rocksdb_readoptions_create()
lowerBound := b2c(begin)
C.rocksdb_readoptions_set_iterate_lower_bound(opts, lowerBound, C.size_t(len(begin)))
upperBound := b2c(end)
C.rocksdb_readoptions_set_iterate_upper_bound(opts, upperBound, C.size_t(len(end)))
if len(begin) > 0 {
lowerBound := b2c(begin)
C.rocksdb_readoptions_set_iterate_lower_bound(opts, lowerBound, C.size_t(len(begin)))
upperBound := b2c(end)
C.rocksdb_readoptions_set_iterate_upper_bound(opts, upperBound, C.size_t(len(end)))
}
it := C.rocksdb_create_iterator(db.db, opts)
C.rocksdb_iter_seek_to_first(it)
rit := &RDBIterator{
it: it,
opts: opts,
first: true,
}
if len(begin) > 0 {
rit.lowerBound = begin
rit.upperBound = end
}
return rit
}

func (db *RDBDatabase) NewIteratorWithStart(start []byte) ethdb.Iterator {
opts := C.rocksdb_readoptions_create()
lowerBound := b2c(start)
C.rocksdb_readoptions_set_iterate_lower_bound(opts, lowerBound, C.size_t(len(start)))
it := C.rocksdb_create_iterator(db.db, opts)
C.rocksdb_iter_seek_to_first(it)
return &RDBIterator{
it: it,
opts: opts,
lowerBound: begin,
upperBound: end,
first: true,
lowerBound: start,
}
}

func (db *RDBDatabase) NewIteratorWithStart(start []byte) ethdb.Iterator {
func (db *RDBDatabase) NewIteratorWithPrefix(prefix []byte) ethdb.Iterator {
start := prefix
end := incrBytes(start)

opts := C.rocksdb_readoptions_create()
lowerBound := b2c(start)
C.rocksdb_readoptions_set_iterate_lower_bound(opts, lowerBound, C.size_t(len(start)))
upperBound := b2c(end)
C.rocksdb_readoptions_set_iterate_upper_bound(opts, upperBound, C.size_t(len(end)))
it := C.rocksdb_create_iterator(db.db, opts)
C.rocksdb_iter_seek_to_first(it)
return &RDBIterator{
it: it,
opts: opts,
first: true,
lowerBound: start,
upperBound: end,
}
}

Expand All @@ -205,34 +236,20 @@ func incrBytes(bz []byte) []byte {
return nil
}

func (db *RDBDatabase) NewIteratorWithPrefix(prefix []byte) ethdb.Iterator {
start := prefix
end := incrBytes(start)

opts := C.rocksdb_readoptions_create()
lowerBound := b2c(start)
C.rocksdb_readoptions_set_iterate_lower_bound(opts, lowerBound, C.size_t(len(start)))
upperBound := b2c(end)
C.rocksdb_readoptions_set_iterate_upper_bound(opts, upperBound, C.size_t(len(end)))
it := C.rocksdb_create_iterator(db.db, opts)
return &RDBIterator{
it: it,
opts: opts,
lowerBound: start,
upperBound: end,
}
}

func (it *RDBIterator) Next() bool {
if C.rocksdb_iter_valid(it.it) == 0 {
return false
if it.first {
it.first = false
} else {
C.rocksdb_iter_next(it.it)
}
C.rocksdb_iter_next(it.it)
return C.rocksdb_iter_valid(it.it) != 0
}

func (it *RDBIterator) Error() error {
var cerr *C.char
if it.it == nil {
return nil
}
C.rocksdb_iter_get_error(it.it, &cerr)
if cerr != nil {
err := errors.New(C.GoString(cerr))
Expand Down
111 changes: 111 additions & 0 deletions ethdb/rocksdb/rocksdb_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Copyright 2019 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
//go:build rocksdb
// +build rocksdb

package rocksdb

import (
"os"
"testing"

"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethdb/dbtest"
)

type EphemeralRDB struct {
rdb *RDBDatabase
file string
}

func newEphemeralRDB(file string, cache int, handles int, namespace string, readonly bool) (*EphemeralRDB, error) {
rdb, err := New(file, cache, handles, namespace, readonly)
if err != nil {
return nil, err
}
return &EphemeralRDB{
rdb: rdb,
file: file,
}, nil
}

func (db *EphemeralRDB) Path() string {
return db.rdb.Path()
}

func (db *EphemeralRDB) Put(key []byte, value []byte) error {
return db.rdb.Put(key, value)
}

func (db *EphemeralRDB) Has(key []byte) (bool, error) {
return db.rdb.Has(key)
}

func (db *EphemeralRDB) Get(key []byte) ([]byte, error) {
return db.rdb.Get(key)
}

func (db *EphemeralRDB) Delete(key []byte) error {
return db.rdb.Delete(key)
}

func (db *EphemeralRDB) NewIterator(prefix, start []byte) ethdb.Iterator {
return db.rdb.NewIterator(prefix, start)
}

func (db *EphemeralRDB) NewIteratorWithStart(start []byte) ethdb.Iterator {
return db.rdb.NewIteratorWithStart(start)
}

func (db *EphemeralRDB) NewIteratorWithPrefix(prefix []byte) ethdb.Iterator {
return db.rdb.NewIteratorWithPrefix(prefix)
}

func (db *EphemeralRDB) Close() error {
err := db.rdb.Close()
if len(db.file) > 0 {
os.RemoveAll(db.file)
}
return err
}

func (db *EphemeralRDB) Stat(property string) (string, error) {
return db.rdb.Stat(property)
}

func (db *EphemeralRDB) Compact(start []byte, limit []byte) error {
return db.rdb.Compact(start, limit)
}

func (db *EphemeralRDB) Meter(prefix string) {
return
}

func (db *EphemeralRDB) NewBatch() ethdb.Batch {
return db.rdb.NewBatch()
}

func TestRocksDB(t *testing.T) {
t.Run("DatabaseSuite", func(t *testing.T) {
dbtest.TestDatabaseSuite(t, func() ethdb.KeyValueStore {
db, err := newEphemeralRDB("test", 1024, 1024, "test", false)
if err != nil {
t.Fatal(err)
}
return db
})
})
}

0 comments on commit 98bc33d

Please sign in to comment.