github.com/Finschia/finschia-sdk@v0.48.1/store/cachekv/mergeiterator.go (about) 1 package cachekv 2 3 import ( 4 "bytes" 5 "errors" 6 7 "github.com/Finschia/finschia-sdk/store/types" 8 ) 9 10 // cacheMergeIterator merges a parent Iterator and a cache Iterator. 11 // The cache iterator may return nil keys to signal that an item 12 // had been deleted (but not deleted in the parent). 13 // If the cache iterator has the same key as the parent, the 14 // cache shadows (overrides) the parent. 15 // 16 // TODO: Optimize by memoizing. 17 type cacheMergeIterator struct { 18 parent types.Iterator 19 cache types.Iterator 20 ascending bool 21 } 22 23 var _ types.Iterator = (*cacheMergeIterator)(nil) 24 25 func newCacheMergeIterator(parent, cache types.Iterator, ascending bool) *cacheMergeIterator { 26 iter := &cacheMergeIterator{ 27 parent: parent, 28 cache: cache, 29 ascending: ascending, 30 } 31 32 return iter 33 } 34 35 // Domain implements Iterator. 36 // It returns the union of the iter.Parent doman, and the iter.Cache domain. 37 // If the domains are disjoint, this includes the domain in between them as well. 38 func (iter *cacheMergeIterator) Domain() (start, end []byte) { 39 startP, endP := iter.parent.Domain() 40 startC, endC := iter.cache.Domain() 41 42 if iter.compare(startP, startC) < 0 { 43 start = startP 44 } else { 45 start = startC 46 } 47 48 if iter.compare(endP, endC) < 0 { 49 end = endC 50 } else { 51 end = endP 52 } 53 54 return start, end 55 } 56 57 // Valid implements Iterator. 58 func (iter *cacheMergeIterator) Valid() bool { 59 return iter.skipUntilExistsOrInvalid() 60 } 61 62 // Next implements Iterator 63 func (iter *cacheMergeIterator) Next() { 64 iter.skipUntilExistsOrInvalid() 65 iter.assertValid() 66 67 // If parent is invalid, get the next cache item. 68 if !iter.parent.Valid() { 69 iter.cache.Next() 70 return 71 } 72 73 // If cache is invalid, get the next parent item. 74 if !iter.cache.Valid() { 75 iter.parent.Next() 76 return 77 } 78 79 // Both are valid. Compare keys. 80 keyP, keyC := iter.parent.Key(), iter.cache.Key() 81 switch iter.compare(keyP, keyC) { 82 case -1: // parent < cache 83 iter.parent.Next() 84 case 0: // parent == cache 85 iter.parent.Next() 86 iter.cache.Next() 87 case 1: // parent > cache 88 iter.cache.Next() 89 } 90 } 91 92 // Key implements Iterator 93 func (iter *cacheMergeIterator) Key() []byte { 94 iter.skipUntilExistsOrInvalid() 95 iter.assertValid() 96 97 // If parent is invalid, get the cache key. 98 if !iter.parent.Valid() { 99 return iter.cache.Key() 100 } 101 102 // If cache is invalid, get the parent key. 103 if !iter.cache.Valid() { 104 return iter.parent.Key() 105 } 106 107 // Both are valid. Compare keys. 108 keyP, keyC := iter.parent.Key(), iter.cache.Key() 109 110 cmp := iter.compare(keyP, keyC) 111 switch cmp { 112 case -1: // parent < cache 113 return keyP 114 case 0: // parent == cache 115 return keyP 116 case 1: // parent > cache 117 return keyC 118 default: 119 panic("invalid compare result") 120 } 121 } 122 123 // Value implements Iterator 124 func (iter *cacheMergeIterator) Value() []byte { 125 iter.skipUntilExistsOrInvalid() 126 iter.assertValid() 127 128 // If parent is invalid, get the cache value. 129 if !iter.parent.Valid() { 130 return iter.cache.Value() 131 } 132 133 // If cache is invalid, get the parent value. 134 if !iter.cache.Valid() { 135 return iter.parent.Value() 136 } 137 138 // Both are valid. Compare keys. 139 keyP, keyC := iter.parent.Key(), iter.cache.Key() 140 141 cmp := iter.compare(keyP, keyC) 142 switch cmp { 143 case -1: // parent < cache 144 return iter.parent.Value() 145 case 0: // parent == cache 146 return iter.cache.Value() 147 case 1: // parent > cache 148 return iter.cache.Value() 149 default: 150 panic("invalid comparison result") 151 } 152 } 153 154 // Close implements Iterator 155 func (iter *cacheMergeIterator) Close() error { 156 if err := iter.parent.Close(); err != nil { 157 return err 158 } 159 160 return iter.cache.Close() 161 } 162 163 // Error returns an error if the cacheMergeIterator is invalid defined by the 164 // Valid method. 165 func (iter *cacheMergeIterator) Error() error { 166 if !iter.Valid() { 167 return errors.New("invalid cacheMergeIterator") 168 } 169 170 return nil 171 } 172 173 // If not valid, panics. 174 // NOTE: May have side-effect of iterating over cache. 175 func (iter *cacheMergeIterator) assertValid() { 176 if err := iter.Error(); err != nil { 177 panic(err) 178 } 179 } 180 181 // Like bytes.Compare but opposite if not ascending. 182 func (iter *cacheMergeIterator) compare(a, b []byte) int { 183 if iter.ascending { 184 return bytes.Compare(a, b) 185 } 186 187 return bytes.Compare(a, b) * -1 188 } 189 190 // Skip all delete-items from the cache w/ `key < until`. After this function, 191 // current cache item is a non-delete-item, or `until <= key`. 192 // If the current cache item is not a delete item, does nothing. 193 // If `until` is nil, there is no limit, and cache may end up invalid. 194 // CONTRACT: cache is valid. 195 func (iter *cacheMergeIterator) skipCacheDeletes(until []byte) { 196 for iter.cache.Valid() && 197 iter.cache.Value() == nil && 198 (until == nil || iter.compare(iter.cache.Key(), until) < 0) { 199 iter.cache.Next() 200 } 201 } 202 203 // Fast forwards cache (or parent+cache in case of deleted items) until current 204 // item exists, or until iterator becomes invalid. 205 // Returns whether the iterator is valid. 206 func (iter *cacheMergeIterator) skipUntilExistsOrInvalid() bool { 207 for { 208 // If parent is invalid, fast-forward cache. 209 if !iter.parent.Valid() { 210 iter.skipCacheDeletes(nil) 211 return iter.cache.Valid() 212 } 213 // Parent is valid. 214 215 if !iter.cache.Valid() { 216 return true 217 } 218 // Parent is valid, cache is valid. 219 220 // Compare parent and cache. 221 keyP := iter.parent.Key() 222 keyC := iter.cache.Key() 223 224 switch iter.compare(keyP, keyC) { 225 case -1: // parent < cache. 226 return true 227 228 case 0: // parent == cache. 229 // Skip over if cache item is a delete. 230 valueC := iter.cache.Value() 231 if valueC == nil { 232 iter.parent.Next() 233 iter.cache.Next() 234 235 continue 236 } 237 // Cache is not a delete. 238 239 return true // cache exists. 240 case 1: // cache < parent 241 // Skip over if cache item is a delete. 242 valueC := iter.cache.Value() 243 if valueC == nil { 244 iter.skipCacheDeletes(keyP) 245 continue 246 } 247 // Cache is not a delete. 248 249 return true // cache exists. 250 } 251 } 252 }