cosmos-sdk/store/prefix/store.go

208 lines
4.4 KiB
Go
Raw Normal View History

2019-02-01 17:03:09 -08:00
package prefix
import (
2018-09-05 21:48:32 -07:00
"bytes"
"errors"
"io"
2019-02-01 17:03:09 -08:00
"github.com/cosmos/cosmos-sdk/store/cachekv"
"github.com/cosmos/cosmos-sdk/store/tracekv"
"github.com/cosmos/cosmos-sdk/store/types"
)
2019-02-01 17:03:09 -08:00
var _ types.KVStore = Store{}
2018-07-26 18:24:18 -07:00
2019-02-01 17:03:09 -08:00
// Store is similar with tendermint/tendermint/libs/db/prefix_db
2018-10-08 12:43:55 -07:00
// both gives access only to the limited subset of the store
// for convinience or safety
2019-02-01 17:03:09 -08:00
type Store struct {
parent types.KVStore
prefix []byte
}
2019-02-01 17:03:09 -08:00
func NewStore(parent types.KVStore, prefix []byte) Store {
return Store{
parent: parent,
prefix: prefix,
}
}
2018-09-10 23:59:58 -07:00
func cloneAppend(bz []byte, tail []byte) (res []byte) {
res = make([]byte, len(bz)+len(tail))
copy(res, bz)
2018-10-08 11:06:16 -07:00
copy(res[len(bz):], tail)
return
}
2019-02-01 17:03:09 -08:00
func (s Store) key(key []byte) (res []byte) {
2018-09-28 12:53:12 -07:00
if key == nil {
2019-02-01 17:03:09 -08:00
panic("nil key on Store")
2018-09-28 12:53:12 -07:00
}
2018-09-27 11:12:52 -07:00
res = cloneAppend(s.prefix, key)
return
}
// Implements Store
2019-02-01 17:03:09 -08:00
func (s Store) GetStoreType() types.StoreType {
2018-07-26 18:24:18 -07:00
return s.parent.GetStoreType()
}
// Implements CacheWrap
2019-02-01 17:03:09 -08:00
func (s Store) CacheWrap() types.CacheWrap {
return cachekv.NewStore(s)
}
// CacheWrapWithTrace implements the KVStore interface.
2019-02-01 17:03:09 -08:00
func (s Store) CacheWrapWithTrace(w io.Writer, tc types.TraceContext) types.CacheWrap {
return cachekv.NewStore(tracekv.NewStore(s, w, tc))
}
// Implements KVStore
2019-02-01 17:03:09 -08:00
func (s Store) Get(key []byte) []byte {
res := s.parent.Get(s.key(key))
return res
}
// Implements KVStore
2019-02-01 17:03:09 -08:00
func (s Store) Has(key []byte) bool {
return s.parent.Has(s.key(key))
}
// Implements KVStore
2019-02-01 17:03:09 -08:00
func (s Store) Set(key, value []byte) {
types.AssertValidKey(key)
types.AssertValidValue(value)
s.parent.Set(s.key(key), value)
}
// Implements KVStore
2019-02-01 17:03:09 -08:00
func (s Store) Delete(key []byte) {
s.parent.Delete(s.key(key))
}
// Implements KVStore
2018-09-05 21:48:32 -07:00
// Check https://github.com/tendermint/tendermint/blob/master/libs/db/prefix_db.go#L106
2019-02-01 17:03:09 -08:00
func (s Store) Iterator(start, end []byte) types.Iterator {
2018-09-27 11:12:52 -07:00
newstart := cloneAppend(s.prefix, start)
var newend []byte
if end == nil {
2018-09-05 21:48:32 -07:00
newend = cpIncr(s.prefix)
} else {
2018-09-27 11:12:52 -07:00
newend = cloneAppend(s.prefix, end)
}
2018-10-08 12:43:55 -07:00
iter := s.parent.Iterator(newstart, newend)
2018-09-05 21:48:32 -07:00
2018-10-08 12:43:55 -07:00
return newPrefixIterator(s.prefix, start, end, iter)
}
// ReverseIterator implements KVStore
2018-09-05 21:48:32 -07:00
// Check https://github.com/tendermint/tendermint/blob/master/libs/db/prefix_db.go#L129
2019-02-01 17:03:09 -08:00
func (s Store) ReverseIterator(start, end []byte) types.Iterator {
newstart := cloneAppend(s.prefix, start)
2018-09-05 21:48:32 -07:00
var newend []byte
if end == nil {
newend = cpIncr(s.prefix)
} else {
2018-09-10 23:59:58 -07:00
newend = cloneAppend(s.prefix, end)
}
2018-09-05 21:48:32 -07:00
iter := s.parent.ReverseIterator(newstart, newend)
2018-10-08 12:43:55 -07:00
return newPrefixIterator(s.prefix, start, end, iter)
}
2019-02-01 17:03:09 -08:00
var _ types.Iterator = (*prefixIterator)(nil)
type prefixIterator struct {
prefix []byte
start []byte
end []byte
iter types.Iterator
valid bool
}
2019-02-01 17:03:09 -08:00
func newPrefixIterator(prefix, start, end []byte, parent types.Iterator) *prefixIterator {
2018-10-08 13:37:18 -07:00
return &prefixIterator{
2018-10-08 12:43:55 -07:00
prefix: prefix,
start: start,
end: end,
iter: parent,
valid: parent.Valid() && bytes.HasPrefix(parent.Key(), prefix),
}
}
// Implements Iterator
func (pi *prefixIterator) Domain() ([]byte, []byte) {
return pi.start, pi.end
}
// Implements Iterator
func (pi *prefixIterator) Valid() bool {
return pi.valid && pi.iter.Valid()
}
// Implements Iterator
func (pi *prefixIterator) Next() {
if !pi.valid {
2018-09-05 21:48:32 -07:00
panic("prefixIterator invalid, cannot call Next()")
}
if pi.iter.Next(); !pi.iter.Valid() || !bytes.HasPrefix(pi.iter.Key(), pi.prefix) {
// TODO: shouldn't pi be set to nil instead?
pi.valid = false
2018-09-05 21:48:32 -07:00
}
}
// Implements Iterator
func (pi *prefixIterator) Key() (key []byte) {
if !pi.valid {
2018-10-08 13:06:40 -07:00
panic("prefixIterator invalid, cannot call Key()")
}
key = pi.iter.Key()
key = stripPrefix(key, pi.prefix)
return
}
// Implements Iterator
func (pi *prefixIterator) Value() []byte {
if !pi.valid {
2018-10-08 13:06:40 -07:00
panic("prefixIterator invalid, cannot call Value()")
}
return pi.iter.Value()
}
// Implements Iterator
func (pi *prefixIterator) Close() error {
return pi.iter.Close()
}
2018-09-05 21:48:32 -07:00
// Error returns an error if the prefixIterator is invalid defined by the Valid
// method.
func (pi *prefixIterator) Error() error {
if !pi.Valid() {
return errors.New("invalid prefixIterator")
}
return nil
}
2018-09-05 21:48:32 -07:00
// copied from github.com/tendermint/tendermint/libs/db/prefix_db.go
func stripPrefix(key []byte, prefix []byte) []byte {
if len(key) < len(prefix) || !bytes.Equal(key[:len(prefix)], prefix) {
panic("should not happen")
}
2018-09-05 21:48:32 -07:00
return key[len(prefix):]
}
2019-02-01 17:03:09 -08:00
// wrapping types.PrefixEndBytes
2018-09-05 21:48:32 -07:00
func cpIncr(bz []byte) []byte {
2019-02-01 17:03:09 -08:00
return types.PrefixEndBytes(bz)
2018-09-05 21:48:32 -07:00
}