neoneo-go/pkg/core/storage/leveldb_store.go
Roman Khimov bc31ab3d2c storage: add bloom filter to leveldb
We're constantly checking for transactions there and most of the time this
check is not successful (meaning that the transaction in question is
new). Bloom filter easily reduces the need to search over the DB in 99% of
these cases and gives some 13% increase in single-node TPS.
2020-09-09 20:46:31 +03:00

82 lines
2.1 KiB
Go

package storage
import (
"github.com/syndtr/goleveldb/leveldb"
"github.com/syndtr/goleveldb/leveldb/filter"
"github.com/syndtr/goleveldb/leveldb/opt"
"github.com/syndtr/goleveldb/leveldb/util"
)
// LevelDBOptions configuration for LevelDB.
type LevelDBOptions struct {
DataDirectoryPath string `yaml:"DataDirectoryPath"`
}
// LevelDBStore is the official storage implementation for storing and retrieving
// blockchain data.
type LevelDBStore struct {
db *leveldb.DB
path string
}
// NewLevelDBStore returns a new LevelDBStore object that will
// initialize the database found at the given path.
func NewLevelDBStore(cfg LevelDBOptions) (*LevelDBStore, error) {
var opts = new(opt.Options) // should be exposed via LevelDBOptions if anything needed
opts.Filter = filter.NewBloomFilter(10)
db, err := leveldb.OpenFile(cfg.DataDirectoryPath, opts)
if err != nil {
return nil, err
}
return &LevelDBStore{
path: cfg.DataDirectoryPath,
db: db,
}, nil
}
// Put implements the Store interface.
func (s *LevelDBStore) Put(key, value []byte) error {
return s.db.Put(key, value, nil)
}
// Get implements the Store interface.
func (s *LevelDBStore) Get(key []byte) ([]byte, error) {
value, err := s.db.Get(key, nil)
if err == leveldb.ErrNotFound {
err = ErrKeyNotFound
}
return value, err
}
// Delete implements the Store interface.
func (s *LevelDBStore) Delete(key []byte) error {
return s.db.Delete(key, nil)
}
// PutBatch implements the Store interface.
func (s *LevelDBStore) PutBatch(batch Batch) error {
lvldbBatch := batch.(*leveldb.Batch)
return s.db.Write(lvldbBatch, nil)
}
// Seek implements the Store interface.
func (s *LevelDBStore) Seek(key []byte, f func(k, v []byte)) {
iter := s.db.NewIterator(util.BytesPrefix(key), nil)
for iter.Next() {
f(iter.Key(), iter.Value())
}
iter.Release()
}
// Batch implements the Batch interface and returns a leveldb
// compatible Batch.
func (s *LevelDBStore) Batch() Batch {
return new(leveldb.Batch)
}
// Close implements the Store interface.
func (s *LevelDBStore) Close() error {
return s.db.Close()
}