The core protocol of WoopChain
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
woop/internal/tikv/prefix/prefix_database.go

119 lines
3.4 KiB

3 years ago
package prefix
import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/harmony-one/harmony/internal/tikv/byte_alloc"
"github.com/harmony-one/harmony/internal/tikv/common"
)
// PrefixDatabase is a wrapper to split the storage with prefix
type PrefixDatabase struct {
prefix []byte
db common.TiKVStore
keysPool *byte_alloc.Allocator
}
func NewPrefixDatabase(prefix []byte, db common.TiKVStore) *PrefixDatabase {
return &PrefixDatabase{
prefix: prefix,
db: db,
keysPool: byte_alloc.NewAllocator(),
}
}
func (p *PrefixDatabase) AncientDatadir() (string, error) {
return "", nil
}
// NewBatchWithSize creates a write-only database batch with pre-allocated buffer.
func (p *PrefixDatabase) NewBatchWithSize(size int) ethdb.Batch {
return nil
}
3 years ago
// makeKey use to create a key with prefix, keysPool can reduce gc pressure
func (p *PrefixDatabase) makeKey(keys []byte) []byte {
prefixLen := len(p.prefix)
byt := p.keysPool.Get(len(keys) + prefixLen)
copy(byt, p.prefix)
copy(byt[prefixLen:], keys)
return byt
}
// Has retrieves if a key is present in the key-value data store.
func (p *PrefixDatabase) Has(key []byte) (bool, error) {
return p.db.Has(p.makeKey(key))
}
// Get retrieves the given key if it's present in the key-value data store.
func (p *PrefixDatabase) Get(key []byte) ([]byte, error) {
return p.db.Get(p.makeKey(key))
}
// Put inserts the given value into the key-value data store.
func (p *PrefixDatabase) Put(key []byte, value []byte) error {
return p.db.Put(p.makeKey(key), value)
}
// Delete removes the key from the key-value data store.
func (p *PrefixDatabase) Delete(key []byte) error {
return p.db.Delete(p.makeKey(key))
}
// NewBatch creates a write-only database that buffers changes to its host db
// until a final write is called.
func (p *PrefixDatabase) NewBatch() ethdb.Batch {
return newPrefixBatch(p.prefix, p.db.NewBatch())
}
// buildLimitUsePrefix build the limit byte from start byte, useful generating from prefix works
func (p *PrefixDatabase) buildLimitUsePrefix() []byte {
var limit []byte
for i := len(p.prefix) - 1; i >= 0; i-- {
c := p.prefix[i]
if c < 0xff {
limit = make([]byte, i+1)
copy(limit, p.prefix)
limit[i] = c + 1
break
}
}
return limit
}
// NewIterator creates a binary-alphabetical iterator over the start to end keyspace
// contained within the key-value database.
func (p *PrefixDatabase) NewIterator(start, end []byte) ethdb.Iterator {
start = append(p.prefix, start...)
if len(end) == 0 {
end = p.buildLimitUsePrefix()
} else {
end = append(p.prefix, end...)
}
return newPrefixIterator(p.prefix, p.db.NewIterator(start, end))
}
// Stat returns a particular internal stat of the database.
func (p *PrefixDatabase) Stat(property string) (string, error) {
return p.db.Stat(property)
}
// Compact flattens the underlying data store for the given key range. In essence,
// deleted and overwritten versions are discarded, and the data is rearranged to
// reduce the cost of operations needed to access them.
//
// A nil start is treated as a key before all keys in the data store; a nil limit
// is treated as a key after all keys in the data store. If both is nil then it
// will compact entire data store.
func (p *PrefixDatabase) Compact(start []byte, limit []byte) error {
return p.db.Compact(start, limit)
}
// Close the storage
func (p *PrefixDatabase) Close() error {
return p.db.Close()
}