github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/syndtr/goleveldb/leveldb/iterator/merged_iter.go (about) 1 // Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com> 2 // All rights reserved. 3 // 4 // Use of this source code is governed by a BSD-style license that can be 5 // found in the LICENSE file. 6 7 package iterator 8 9 import ( 10 "github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/comparer" 11 "github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/errors" 12 "github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/util" 13 ) 14 15 type dir int 16 17 const ( 18 dirReleased dir = iota - 1 19 dirSOI 20 dirEOI 21 dirBackward 22 dirForward 23 ) 24 25 type mergedIterator struct { 26 cmp comparer.Comparer 27 iters []Iterator 28 strict bool 29 30 keys [][]byte 31 index int 32 dir dir 33 err error 34 errf func(err error) 35 releaser util.Releaser 36 } 37 38 func assertKey(key []byte) []byte { 39 if key == nil { 40 panic("leveldb/iterator: nil key") 41 } 42 return key 43 } 44 45 func (i *mergedIterator) iterErr(iter Iterator) bool { 46 if err := iter.Error(); err != nil { 47 if i.errf != nil { 48 i.errf(err) 49 } 50 if i.strict || !errors.IsCorrupted(err) { 51 i.err = err 52 return true 53 } 54 } 55 return false 56 } 57 58 func (i *mergedIterator) Valid() bool { 59 return i.err == nil && i.dir > dirEOI 60 } 61 62 func (i *mergedIterator) First() bool { 63 if i.err != nil { 64 return false 65 } else if i.dir == dirReleased { 66 i.err = ErrIterReleased 67 return false 68 } 69 70 for x, iter := range i.iters { 71 switch { 72 case iter.First(): 73 i.keys[x] = assertKey(iter.Key()) 74 case i.iterErr(iter): 75 return false 76 default: 77 i.keys[x] = nil 78 } 79 } 80 i.dir = dirSOI 81 return i.next() 82 } 83 84 func (i *mergedIterator) Last() bool { 85 if i.err != nil { 86 return false 87 } else if i.dir == dirReleased { 88 i.err = ErrIterReleased 89 return false 90 } 91 92 for x, iter := range i.iters { 93 switch { 94 case iter.Last(): 95 i.keys[x] = assertKey(iter.Key()) 96 case i.iterErr(iter): 97 return false 98 default: 99 i.keys[x] = nil 100 } 101 } 102 i.dir = dirEOI 103 return i.prev() 104 } 105 106 func (i *mergedIterator) Seek(key []byte) bool { 107 if i.err != nil { 108 return false 109 } else if i.dir == dirReleased { 110 i.err = ErrIterReleased 111 return false 112 } 113 114 for x, iter := range i.iters { 115 switch { 116 case iter.Seek(key): 117 i.keys[x] = assertKey(iter.Key()) 118 case i.iterErr(iter): 119 return false 120 default: 121 i.keys[x] = nil 122 } 123 } 124 i.dir = dirSOI 125 return i.next() 126 } 127 128 func (i *mergedIterator) next() bool { 129 var key []byte 130 if i.dir == dirForward { 131 key = i.keys[i.index] 132 } 133 for x, tkey := range i.keys { 134 if tkey != nil && (key == nil || i.cmp.Compare(tkey, key) < 0) { 135 key = tkey 136 i.index = x 137 } 138 } 139 if key == nil { 140 i.dir = dirEOI 141 return false 142 } 143 i.dir = dirForward 144 return true 145 } 146 147 func (i *mergedIterator) Next() bool { 148 if i.dir == dirEOI || i.err != nil { 149 return false 150 } else if i.dir == dirReleased { 151 i.err = ErrIterReleased 152 return false 153 } 154 155 switch i.dir { 156 case dirSOI: 157 return i.First() 158 case dirBackward: 159 key := append([]byte{}, i.keys[i.index]...) 160 if !i.Seek(key) { 161 return false 162 } 163 return i.Next() 164 } 165 166 x := i.index 167 iter := i.iters[x] 168 switch { 169 case iter.Next(): 170 i.keys[x] = assertKey(iter.Key()) 171 case i.iterErr(iter): 172 return false 173 default: 174 i.keys[x] = nil 175 } 176 return i.next() 177 } 178 179 func (i *mergedIterator) prev() bool { 180 var key []byte 181 if i.dir == dirBackward { 182 key = i.keys[i.index] 183 } 184 for x, tkey := range i.keys { 185 if tkey != nil && (key == nil || i.cmp.Compare(tkey, key) > 0) { 186 key = tkey 187 i.index = x 188 } 189 } 190 if key == nil { 191 i.dir = dirSOI 192 return false 193 } 194 i.dir = dirBackward 195 return true 196 } 197 198 func (i *mergedIterator) Prev() bool { 199 if i.dir == dirSOI || i.err != nil { 200 return false 201 } else if i.dir == dirReleased { 202 i.err = ErrIterReleased 203 return false 204 } 205 206 switch i.dir { 207 case dirEOI: 208 return i.Last() 209 case dirForward: 210 key := append([]byte{}, i.keys[i.index]...) 211 for x, iter := range i.iters { 212 if x == i.index { 213 continue 214 } 215 seek := iter.Seek(key) 216 switch { 217 case seek && iter.Prev(), !seek && iter.Last(): 218 i.keys[x] = assertKey(iter.Key()) 219 case i.iterErr(iter): 220 return false 221 default: 222 i.keys[x] = nil 223 } 224 } 225 } 226 227 x := i.index 228 iter := i.iters[x] 229 switch { 230 case iter.Prev(): 231 i.keys[x] = assertKey(iter.Key()) 232 case i.iterErr(iter): 233 return false 234 default: 235 i.keys[x] = nil 236 } 237 return i.prev() 238 } 239 240 func (i *mergedIterator) Key() []byte { 241 if i.err != nil || i.dir <= dirEOI { 242 return nil 243 } 244 return i.keys[i.index] 245 } 246 247 func (i *mergedIterator) Value() []byte { 248 if i.err != nil || i.dir <= dirEOI { 249 return nil 250 } 251 return i.iters[i.index].Value() 252 } 253 254 func (i *mergedIterator) Release() { 255 if i.dir != dirReleased { 256 i.dir = dirReleased 257 for _, iter := range i.iters { 258 iter.Release() 259 } 260 i.iters = nil 261 i.keys = nil 262 if i.releaser != nil { 263 i.releaser.Release() 264 i.releaser = nil 265 } 266 } 267 } 268 269 func (i *mergedIterator) SetReleaser(releaser util.Releaser) { 270 if i.dir == dirReleased { 271 panic(util.ErrReleased) 272 } 273 if i.releaser != nil && releaser != nil { 274 panic(util.ErrHasReleaser) 275 } 276 i.releaser = releaser 277 } 278 279 func (i *mergedIterator) Error() error { 280 return i.err 281 } 282 283 func (i *mergedIterator) SetErrorCallback(f func(err error)) { 284 i.errf = f 285 } 286 287 // NewMergedIterator returns an iterator that merges its input. Walking the 288 // resultant iterator will return all key/value pairs of all input iterators 289 // in strictly increasing key order, as defined by cmp. 290 // The input's key ranges may overlap, but there are assumed to be no duplicate 291 // keys: if iters[i] contains a key k then iters[j] will not contain that key k. 292 // None of the iters may be nil. 293 // 294 // If strict is true the any 'corruption errors' (i.e errors.IsCorrupted(err) == true) 295 // won't be ignored and will halt 'merged iterator', otherwise the iterator will 296 // continue to the next 'input iterator'. 297 func NewMergedIterator(iters []Iterator, cmp comparer.Comparer, strict bool) Iterator { 298 return &mergedIterator{ 299 iters: iters, 300 cmp: cmp, 301 strict: strict, 302 keys: make([][]byte, len(iters)), 303 } 304 }