cosmos-sdk/store/prefixstore.go

212 lines
4.2 KiB
Go
Raw Normal View History

package store
import (
2018-09-05 21:48:32 -07:00
"bytes"
"io"
sdk "github.com/cosmos/cosmos-sdk/types"
)
2018-07-26 18:24:18 -07:00
var _ KVStore = prefixStore{}
type prefixStore struct {
2018-07-26 18:24:18 -07:00
parent KVStore
prefix []byte
}
2018-09-10 23:59:58 -07:00
func cloneAppend(bz []byte, tail []byte) (res []byte) {
res = make([]byte, len(bz)+len(tail))
2018-09-05 21:48:32 -07:00
copy(res, bz)
2018-09-10 23:59:58 -07:00
res = append(res, bz...)
2018-09-05 21:48:32 -07:00
return
}
func (s prefixStore) key(key []byte) (res []byte) {
2018-09-10 23:59:58 -07:00
res = cloneAppend(s.prefix, key)
2018-09-05 21:48:32 -07:00
return
}
// Implements Store
func (s prefixStore) GetStoreType() StoreType {
2018-07-26 18:24:18 -07:00
return s.parent.GetStoreType()
}
// Implements CacheWrap
func (s prefixStore) CacheWrap() CacheWrap {
return NewCacheKVStore(s)
}
// CacheWrapWithTrace implements the KVStore interface.
func (s prefixStore) CacheWrapWithTrace(w io.Writer, tc TraceContext) CacheWrap {
return NewCacheKVStore(NewTraceKVStore(s, w, tc))
}
// Implements KVStore
func (s prefixStore) Get(key []byte) []byte {
2018-09-05 21:48:32 -07:00
res := s.parent.Get(s.key(key))
return res
}
// Implements KVStore
func (s prefixStore) Has(key []byte) bool {
2018-09-05 21:48:32 -07:00
return s.parent.Has(s.key(key))
}
// Implements KVStore
func (s prefixStore) Set(key, value []byte) {
2018-09-05 21:48:32 -07:00
s.parent.Set(s.key(key), value)
}
// Implements KVStore
func (s prefixStore) Delete(key []byte) {
2018-09-05 21:48:32 -07:00
s.parent.Delete(s.key(key))
}
// Implements KVStore
func (s prefixStore) Prefix(prefix []byte) KVStore {
return prefixStore{s, prefix}
}
2018-07-26 18:24:18 -07:00
// Implements KVStore
func (s prefixStore) Gas(meter GasMeter, config GasConfig) KVStore {
return NewGasKVStore(meter, config, s)
}
// Implements KVStore
2018-09-05 21:48:32 -07:00
// Check https://github.com/tendermint/tendermint/blob/master/libs/db/prefix_db.go#L106
func (s prefixStore) Iterator(start, end []byte) Iterator {
2018-09-10 23:59:58 -07:00
newstart := cloneAppend(s.prefix, start)
2018-09-05 21:48:32 -07:00
var newend []byte
if end == nil {
2018-09-05 21:48:32 -07:00
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
return prefixIterator{
prefix: s.prefix,
2018-09-10 23:59:58 -07:00
start: start,
end: end,
2018-09-05 21:48:32 -07:00
iter: s.parent.Iterator(newstart, newend),
}
2018-09-05 21:48:32 -07:00
}
// Implements KVStore
2018-09-05 21:48:32 -07:00
// Check https://github.com/tendermint/tendermint/blob/master/libs/db/prefix_db.go#L129
func (s prefixStore) ReverseIterator(start, end []byte) Iterator {
2018-09-05 21:48:32 -07:00
var newstart []byte
if start == nil {
newstart = cpIncr(s.prefix)
} else {
2018-09-10 23:59:58 -07:00
newstart = cloneAppend(s.prefix, start)
2018-09-05 21:48:32 -07:00
}
var newend []byte
if end == nil {
2018-09-10 23:59:58 -07:00
newend = cpDecr(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)
if start == nil {
skipOne(iter, cpIncr(s.prefix))
}
return prefixIterator{
prefix: s.prefix,
2018-09-10 23:59:58 -07:00
start: start,
end: end,
2018-09-05 21:48:32 -07:00
iter: iter,
}
}
type prefixIterator struct {
2018-09-05 21:48:32 -07:00
prefix []byte
start, end []byte
iter Iterator
valid bool
}
// Implements Iterator
2018-09-05 21:48:32 -07:00
func (iter prefixIterator) Domain() ([]byte, []byte) {
return iter.start, iter.end
}
// Implements Iterator
func (iter prefixIterator) Valid() bool {
2018-09-05 21:48:32 -07:00
return iter.valid && iter.iter.Valid()
}
// Implements Iterator
func (iter prefixIterator) Next() {
2018-09-05 21:48:32 -07:00
if !iter.valid {
panic("prefixIterator invalid, cannot call Next()")
}
iter.iter.Next()
2018-09-05 21:48:32 -07:00
if !iter.iter.Valid() || !bytes.HasPrefix(iter.iter.Key(), iter.prefix) {
iter.iter.Close()
iter.valid = false
}
}
// Implements Iterator
func (iter prefixIterator) Key() (key []byte) {
key = iter.iter.Key()
key = key[len(iter.prefix):]
return
}
// Implements Iterator
func (iter prefixIterator) Value() []byte {
return iter.iter.Value()
}
// Implements Iterator
func (iter prefixIterator) Close() {
iter.iter.Close()
}
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")
}
return key[len(prefix):]
}
// wrapping sdk.PrefixEndBytes
func cpIncr(bz []byte) []byte {
return sdk.PrefixEndBytes(bz)
}
// copied from github.com/tendermint/tendermint/libs/db/util.go
func cpDecr(bz []byte) (ret []byte) {
if len(bz) == 0 {
panic("cpDecr expects non-zero bz length")
}
2018-09-10 23:59:58 -07:00
ret = make([]byte, len(bz))
copy(ret, bz)
2018-09-05 21:48:32 -07:00
for i := len(bz) - 1; i >= 0; i-- {
if ret[i] > byte(0x00) {
ret[i]--
return
}
ret[i] = byte(0xFF)
if i == 0 {
return nil
}
}
return nil
}
func skipOne(iter Iterator, skipKey []byte) {
if iter.Valid() {
if bytes.Equal(iter.Key(), skipKey) {
iter.Next()
}
}
}