github.com/turingchain2020/turingchain@v1.1.21/common/db/merge_iter.go (about) 1 package db 2 3 //合并两个迭代器成一个迭代器 4 5 import ( 6 "errors" 7 8 "github.com/syndtr/goleveldb/leveldb/comparer" 9 ) 10 11 type dir int 12 13 const ( 14 dirReleased dir = iota - 1 15 dirSOI 16 dirEOI 17 dirForward 18 dirSeek 19 ) 20 21 //合并错误列表 22 var ( 23 ErrIterReleased = errors.New("ErrIterReleased") 24 ) 25 26 type mergedIterator struct { 27 itBase 28 cmp comparer.Comparer 29 iters []Iterator 30 strict bool 31 reverse bool 32 keys [][]byte 33 prevKey []byte 34 index int 35 dir dir 36 err error 37 } 38 39 func assertKey(key []byte) []byte { 40 if key == nil { 41 panic("leveldb/iterator: nil key") 42 } 43 return key 44 } 45 46 func (i *mergedIterator) iterErr(iter Iterator) bool { 47 if err := iter.Error(); err != nil { 48 if i.strict { 49 i.err = err 50 return true 51 } 52 } 53 return false 54 } 55 56 func (i *mergedIterator) Valid() bool { 57 return i.err == nil && i.dir > dirEOI 58 } 59 60 func (i *mergedIterator) Rewind() bool { 61 if i.err != nil { 62 return false 63 } else if i.dir == dirReleased { 64 i.err = ErrIterReleased 65 return false 66 } 67 68 for x, iter := range i.iters { 69 switch { 70 case iter.Rewind(): 71 i.keys[x] = assertKey(iter.Key()) 72 case i.iterErr(iter): 73 return false 74 default: 75 i.keys[x] = nil 76 } 77 } 78 i.dir = dirSOI 79 return i.next(false) 80 } 81 82 func (i *mergedIterator) Seek(key []byte) bool { 83 if i.err != nil { 84 return false 85 } else if i.dir == dirReleased { 86 i.err = ErrIterReleased 87 return false 88 } 89 for x, iter := range i.iters { 90 switch { 91 case iter.Seek(key): 92 i.keys[x] = assertKey(iter.Key()) 93 case i.iterErr(iter): 94 return false 95 default: 96 i.keys[x] = nil 97 } 98 } 99 i.dir = dirSOI 100 if i.next(true) { 101 i.dir = dirSeek 102 return true 103 } 104 i.dir = dirSOI 105 return false 106 } 107 108 func (i *mergedIterator) compare(tkey []byte, key []byte, ignoreReverse bool) int { 109 if ignoreReverse { 110 return i.cmp.Compare(tkey, key) 111 } 112 if tkey == nil && key != nil { 113 return 1 114 } 115 if tkey != nil && key == nil { 116 return -1 117 } 118 result := i.cmp.Compare(tkey, key) 119 if i.reverse { 120 return -result 121 } 122 return result 123 } 124 125 func (i *mergedIterator) next(ignoreReverse bool) bool { 126 var key []byte 127 for x, tkey := range i.keys { 128 if tkey != nil && (key == nil || i.compare(tkey, key, ignoreReverse) < 0) { 129 key = tkey 130 i.index = x 131 } 132 } 133 if key == nil { 134 i.dir = dirEOI 135 return false 136 } 137 if i.dir == dirSOI { 138 i.prevKey = cloneByte(key) 139 } 140 i.dir = dirForward 141 return true 142 } 143 144 func (i *mergedIterator) Next() bool { 145 for { 146 ok, isrewind := i.nextInternal() 147 if !ok { 148 break 149 } 150 if isrewind { 151 return true 152 } 153 if i.compare(i.Key(), i.prevKey, true) != 0 { 154 i.prevKey = cloneByte(i.Key()) 155 return true 156 } 157 } 158 return false 159 } 160 161 func (i *mergedIterator) nextInternal() (bool, bool) { 162 if i.dir == dirEOI || i.err != nil { 163 return false, false 164 } else if i.dir == dirReleased { 165 i.err = ErrIterReleased 166 return false, false 167 } 168 switch i.dir { 169 case dirSOI: 170 return i.Rewind(), true 171 case dirSeek: 172 if !i.reverse { 173 break 174 } 175 key := append([]byte{}, i.keys[i.index]...) 176 for x, iter := range i.iters { 177 if x == i.index { 178 continue 179 } 180 seek := iter.Seek(key) 181 switch { 182 case seek && iter.Next(), !seek && iter.Rewind(): 183 i.keys[x] = assertKey(iter.Key()) 184 case i.iterErr(iter): 185 return false, false 186 default: 187 i.keys[x] = nil 188 } 189 } 190 } 191 x := i.index 192 iter := i.iters[x] 193 switch { 194 case iter.Next(): 195 i.keys[x] = assertKey(iter.Key()) 196 case i.iterErr(iter): 197 return false, false 198 default: 199 i.keys[x] = nil 200 } 201 return i.next(false), false 202 } 203 204 func (i *mergedIterator) Key() []byte { 205 if i.err != nil || i.dir <= dirEOI { 206 return nil 207 } 208 return i.keys[i.index] 209 } 210 211 func (i *mergedIterator) Value() []byte { 212 if i.err != nil || i.dir <= dirEOI { 213 return nil 214 } 215 return i.iters[i.index].Value() 216 } 217 218 func (i *mergedIterator) ValueCopy() []byte { 219 if i.err != nil || i.dir <= dirEOI { 220 return nil 221 } 222 v := i.iters[i.index].Value() 223 return cloneByte(v) 224 } 225 226 func (i *mergedIterator) Close() { 227 if i.dir != dirReleased { 228 i.dir = dirReleased 229 for _, iter := range i.iters { 230 iter.Close() 231 } 232 i.iters = nil 233 i.keys = nil 234 } 235 } 236 237 func (i *mergedIterator) Error() error { 238 return i.err 239 } 240 241 // NewMergedIterator returns an iterator that merges its input. Walking the 242 // resultant iterator will return all key/value pairs of all input iterators 243 // in strictly increasing key order, as defined by cmp. 244 // The input's key ranges may overlap, but there are assumed to be no duplicate 245 // keys: if iters[i] contains a key k then iters[j] will not contain that key k. 246 // None of the iters may be nil. 247 // 248 // If strict is true the any 'corruption errors' (i.e errors.IsCorrupted(err) == true) 249 // won't be ignored and will halt 'merged iterator', otherwise the iterator will 250 // continue to the next 'input iterator'. 251 func NewMergedIterator(iters []Iterator) Iterator { 252 reverse := true 253 if len(iters) >= 2 { 254 reverse = iters[0].IsReverse() 255 for i := 1; i < len(iters); i++ { 256 if reverse != iters[i].IsReverse() { 257 panic("merge iter not support diff reverse flag") 258 } 259 } 260 } 261 return &mergedIterator{ 262 iters: iters, 263 reverse: reverse, 264 cmp: comparer.DefaultComparer, 265 strict: true, 266 keys: make([][]byte, len(iters)), 267 } 268 } 269 270 type mergedIteratorDB struct { 271 iters []IteratorDB 272 } 273 274 //NewMergedIteratorDB 合并两个迭代数据库 275 func NewMergedIteratorDB(iters []IteratorDB) IteratorDB { 276 return &mergedIteratorDB{iters: iters} 277 } 278 279 func (merge *mergedIteratorDB) Iterator(start []byte, end []byte, reverse bool) Iterator { 280 iters := make([]Iterator, len(merge.iters)) 281 for i := 0; i < len(merge.iters); i++ { 282 iters[i] = merge.iters[i].Iterator(start, end, reverse) 283 } 284 return NewMergedIterator(iters) 285 }