2019-02-01 17:03:09 -08:00
|
|
|
package types
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
|
2020-01-16 13:46:51 -08:00
|
|
|
tmkv "github.com/tendermint/tendermint/libs/kv"
|
2019-02-01 17:03:09 -08:00
|
|
|
)
|
|
|
|
|
|
|
|
// Iterator over all the keys with a certain prefix in ascending order
|
|
|
|
func KVStorePrefixIterator(kvs KVStore, prefix []byte) Iterator {
|
|
|
|
return kvs.Iterator(prefix, PrefixEndBytes(prefix))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Iterator over all the keys with a certain prefix in descending order.
|
|
|
|
func KVStoreReversePrefixIterator(kvs KVStore, prefix []byte) Iterator {
|
|
|
|
return kvs.ReverseIterator(prefix, PrefixEndBytes(prefix))
|
|
|
|
}
|
|
|
|
|
2019-07-19 07:05:37 -07:00
|
|
|
// DiffKVStores compares two KVstores and returns all the key/value pairs
|
2020-03-01 16:27:03 -08:00
|
|
|
// that differ from one another. It also skips value comparison for a set of provided prefixes.
|
2020-01-16 13:46:51 -08:00
|
|
|
func DiffKVStores(a KVStore, b KVStore, prefixesToSkip [][]byte) (kvAs, kvBs []tmkv.Pair) {
|
2019-02-01 17:03:09 -08:00
|
|
|
iterA := a.Iterator(nil, nil)
|
2020-03-01 16:27:03 -08:00
|
|
|
defer iterA.Close()
|
2019-02-01 17:03:09 -08:00
|
|
|
iterB := b.Iterator(nil, nil)
|
2020-03-01 16:27:03 -08:00
|
|
|
defer iterB.Close()
|
2019-07-19 07:05:37 -07:00
|
|
|
|
2019-02-01 17:03:09 -08:00
|
|
|
for {
|
|
|
|
if !iterA.Valid() && !iterB.Valid() {
|
2020-03-01 16:27:03 -08:00
|
|
|
return kvAs, kvBs
|
2019-02-01 17:03:09 -08:00
|
|
|
}
|
2020-03-01 16:27:03 -08:00
|
|
|
|
2020-01-16 13:46:51 -08:00
|
|
|
var kvA, kvB tmkv.Pair
|
2019-02-01 17:03:09 -08:00
|
|
|
if iterA.Valid() {
|
2020-01-16 13:46:51 -08:00
|
|
|
kvA = tmkv.Pair{Key: iterA.Key(), Value: iterA.Value()}
|
2019-02-01 17:03:09 -08:00
|
|
|
iterA.Next()
|
|
|
|
}
|
|
|
|
if iterB.Valid() {
|
2020-01-16 13:46:51 -08:00
|
|
|
kvB = tmkv.Pair{Key: iterB.Key(), Value: iterB.Value()}
|
2019-02-01 17:03:09 -08:00
|
|
|
iterB.Next()
|
|
|
|
}
|
2020-03-01 16:27:03 -08:00
|
|
|
|
2019-02-01 17:03:09 -08:00
|
|
|
compareValue := true
|
|
|
|
for _, prefix := range prefixesToSkip {
|
|
|
|
// Skip value comparison if we matched a prefix
|
2020-04-07 15:33:30 -07:00
|
|
|
if bytes.HasPrefix(kvA.Key, prefix) || bytes.HasPrefix(kvB.Key, prefix) {
|
2019-02-01 17:03:09 -08:00
|
|
|
compareValue = false
|
2020-04-07 15:33:30 -07:00
|
|
|
break
|
2019-02-01 17:03:09 -08:00
|
|
|
}
|
|
|
|
}
|
2020-04-07 15:33:30 -07:00
|
|
|
|
|
|
|
if compareValue && (!bytes.Equal(kvA.Key, kvB.Key) || !bytes.Equal(kvA.Value, kvB.Value)) {
|
2019-08-13 15:16:03 -07:00
|
|
|
kvAs = append(kvAs, kvA)
|
|
|
|
kvBs = append(kvBs, kvB)
|
2019-02-01 17:03:09 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// PrefixEndBytes returns the []byte that would end a
|
|
|
|
// range query for all []byte with a certain prefix
|
|
|
|
// Deals with last byte of prefix being FF without overflowing
|
|
|
|
func PrefixEndBytes(prefix []byte) []byte {
|
2019-02-26 05:54:47 -08:00
|
|
|
if len(prefix) == 0 {
|
2019-02-01 17:03:09 -08:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
end := make([]byte, len(prefix))
|
|
|
|
copy(end, prefix)
|
|
|
|
|
|
|
|
for {
|
|
|
|
if end[len(end)-1] != byte(255) {
|
|
|
|
end[len(end)-1]++
|
|
|
|
break
|
|
|
|
}
|
2020-03-01 16:27:03 -08:00
|
|
|
end = end[:len(end)-1]
|
|
|
|
if len(end) == 0 {
|
|
|
|
end = nil
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
2019-02-01 17:03:09 -08:00
|
|
|
}
|
|
|
|
return end
|
|
|
|
}
|
|
|
|
|
|
|
|
// InclusiveEndBytes returns the []byte that would end a
|
|
|
|
// range query such that the input would be included
|
2019-08-19 09:06:27 -07:00
|
|
|
func InclusiveEndBytes(inclusiveBytes []byte) []byte {
|
|
|
|
return append(inclusiveBytes, byte(0x00))
|
2019-02-01 17:03:09 -08:00
|
|
|
}
|