kvdb/table/table.go
package table
import (
"github.com/ethereum/go-ethereum/ethdb"
)
// Table wraps the underling DB, so all the table's data is stored with a prefix in underling DB
type Table struct {
db ethdb.KeyValueStore
prefix []byte
}
var (
// NOTE: key collisions are possible
separator = []byte{}
)
// prefixed key (prefix + separator + key)
func prefixed(key, prefix []byte) []byte {
prefixedKey := make([]byte, 0, len(prefix)+len(separator)+len(key))
prefixedKey = append(prefixedKey, prefix...)
prefixedKey = append(prefixedKey, separator...)
prefixedKey = append(prefixedKey, key...)
return prefixedKey
}
func noPrefix(key, prefix []byte) []byte {
if len(key) < len(prefix)+len(separator) {
return key
}
return key[len(prefix)+len(separator):]
}
/*
* Database
*/
func New(db ethdb.KeyValueStore, prefix []byte) *Table {
return &Table{db, prefix}
}
func (t *Table) NewTable(prefix []byte) *Table {
return New(t, prefix)
}
func (t *Table) Close() error {
return nil
}
// Drop the whole database.
func (t *Table) Drop() {}
func (t *Table) Has(key []byte) (bool, error) {
return t.db.Has(prefixed(key, t.prefix))
}
func (t *Table) Get(key []byte) ([]byte, error) {
return t.db.Get(prefixed(key, t.prefix))
}
func (t *Table) Put(key []byte, value []byte) error {
return t.db.Put(prefixed(key, t.prefix), value)
}
func (t *Table) Delete(key []byte) error {
return t.db.Delete(prefixed(key, t.prefix))
}
func (t *Table) NewBatch() ethdb.Batch {
return &batch{t.db.NewBatch(), t.prefix}
}
func (t *Table) Stat(property string) (string, error) {
return t.db.Stat(property)
}
func (t *Table) Compact(start []byte, limit []byte) error {
return t.db.Compact(start, limit)
}
/*
* Iterator
*/
type iterator struct {
it ethdb.Iterator
prefix []byte
}
func (it *iterator) Next() bool {
return it.it.Next()
}
func (it *iterator) Error() error {
return it.it.Error()
}
func (it *iterator) Key() []byte {
return noPrefix(it.it.Key(), it.prefix)
}
func (it *iterator) Value() []byte {
return it.it.Value()
}
func (it *iterator) Release() {
it.it.Release()
*it = iterator{}
}
func (t *Table) NewIterator(itPrefix []byte, start []byte) ethdb.Iterator {
return &iterator{t.db.NewIterator(prefixed(itPrefix, t.prefix), start), t.prefix}
}
/*
* Batch
*/
type batch struct {
batch ethdb.Batch
prefix []byte
}
func (b *batch) Put(key, value []byte) error {
return b.batch.Put(prefixed(key, b.prefix), value)
}
func (b *batch) Delete(key []byte) error {
return b.batch.Delete(prefixed(key, b.prefix))
}
func (b *batch) ValueSize() int {
return b.batch.ValueSize()
}
func (b *batch) Write() error {
return b.batch.Write()
}
func (b *batch) Reset() {
b.batch.Reset()
}
func (b *batch) Replay(w ethdb.KeyValueWriter) error {
return b.batch.Replay(&replayer{w, b.prefix})
}
/*
* Replayer
*/
type replayer struct {
writer ethdb.KeyValueWriter
prefix []byte
}
func (r *replayer) Put(key, value []byte) error {
return r.writer.Put(noPrefix(key, r.prefix), value)
}
func (r *replayer) Delete(key []byte) error {
return r.writer.Delete(noPrefix(key, r.prefix))
}