github.com/eris-ltd/erisdb@v0.25.0/storage/kvstore.go (about) 1 package storage 2 3 import ( 4 "bytes" 5 6 dbm "github.com/tendermint/tendermint/libs/db" 7 ) 8 9 type KVIterator = dbm.Iterator 10 11 // This is partially extrated from Cosmos SDK for alignment but is more minimal, we should suggest this becomes an 12 // embedded interface 13 type KVIterable interface { 14 // Iterator over a domain of keys in ascending order. high is exclusive. 15 // low must be less than high, or the Iterator is invalid. 16 // Iterator must be closed by caller. 17 // To iterate over entire domain, use store.Iterator(nil, nil) 18 // CONTRACT: No writes may happen within a domain while an iterator exists over it. 19 Iterator(low, high []byte) KVIterator 20 21 // Iterator over a domain of keys in descending order. high is exclusive. 22 // must be less than high, or the Iterator is invalid. 23 // Iterator must be closed by caller. 24 // CONTRACT: No writes may happen within a domain while an iterator exists over it. 25 ReverseIterator(low, high []byte) KVIterator 26 } 27 28 // Provides the native iteration for IAVLTree 29 type KVCallbackIterable interface { 30 // low must be lexicographically less than high. high is exclusive unless it is nil in which case it is inclusive. 31 // ascending == false reverses order. 32 Iterate(low, high []byte, ascending bool, fn func(key []byte, value []byte) error) error 33 } 34 35 func KVCallbackIterator(rit KVCallbackIterable, ascending bool, low, high []byte) dbm.Iterator { 36 ch := make(chan KVPair) 37 go func() { 38 defer close(ch) 39 rit.Iterate(low, high, ascending, func(key, value []byte) (err error) { 40 ch <- KVPair{key, value} 41 return 42 }) 43 }() 44 return NewChannelIterator(ch, low, high) 45 } 46 47 type KVReader interface { 48 // Get returns nil iff key doesn't exist. Panics on nil key. 49 Get(key []byte) []byte 50 // Has checks if a key exists. Panics on nil key. 51 Has(key []byte) bool 52 } 53 54 type KVWriter interface { 55 // Set sets the key. Panics on nil key. 56 Set(key, value []byte) 57 // Delete deletes the key. Panics on nil key. 58 Delete(key []byte) 59 } 60 61 type KVIterableReader interface { 62 KVReader 63 KVIterable 64 } 65 66 type KVCallbackIterableReader interface { 67 KVReader 68 KVCallbackIterable 69 } 70 71 // KVStore is a simple interface to get/set data 72 type KVReaderWriter interface { 73 KVReader 74 KVWriter 75 } 76 77 type KVStore interface { 78 KVReaderWriter 79 KVIterable 80 } 81 82 // NormaliseDomain encodes the assumption that when nil is used as a lower bound is interpreted as low rather than high 83 func NormaliseDomain(low, high []byte) ([]byte, []byte) { 84 if len(low) == 0 { 85 low = []byte{} 86 } 87 return low, high 88 } 89 90 // KeyOrder maps []byte{} -> -1, []byte(nil) -> 1, and everything else to 0. This encodes the assumptions of the 91 // KVIterator domain endpoints 92 func KeyOrder(key []byte) int { 93 if key == nil { 94 // Sup 95 return 1 96 } 97 if len(key) == 0 { 98 // Inf 99 return -1 100 } 101 // Normal key 102 return 0 103 } 104 105 // Sorts the keys as if they were compared lexicographically with their KeyOrder prepended 106 func CompareKeys(k1, k2 []byte) int { 107 ko1 := KeyOrder(k1) 108 ko2 := KeyOrder(k2) 109 if ko1 < ko2 { 110 return -1 111 } 112 if ko1 > ko2 { 113 return 1 114 } 115 return bytes.Compare(k1, k2) 116 }