github.com/df-mc/goleveldb@v1.1.9/leveldb/db_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 leveldb 8 9 import ( 10 "errors" 11 "math/rand" 12 "runtime" 13 "sync" 14 "sync/atomic" 15 16 "github.com/df-mc/goleveldb/leveldb/iterator" 17 "github.com/df-mc/goleveldb/leveldb/opt" 18 "github.com/df-mc/goleveldb/leveldb/util" 19 ) 20 21 var ( 22 errInvalidInternalKey = errors.New("leveldb: Iterator: invalid internal key") 23 ) 24 25 type memdbReleaser struct { 26 once sync.Once 27 m *memDB 28 } 29 30 func (mr *memdbReleaser) Release() { 31 mr.once.Do(func() { 32 mr.m.decref() 33 }) 34 } 35 36 func (db *DB) newRawIterator(auxm *memDB, auxt tFiles, slice *util.Range, ro *opt.ReadOptions) iterator.Iterator { 37 strict := opt.GetStrict(db.s.o.Options, ro, opt.StrictReader) 38 em, fm := db.getMems() 39 v := db.s.version() 40 41 tableIts := v.getIterators(slice, ro) 42 n := len(tableIts) + len(auxt) + 3 43 its := make([]iterator.Iterator, 0, n) 44 45 if auxm != nil { 46 ami := auxm.NewIterator(slice) 47 ami.SetReleaser(&memdbReleaser{m: auxm}) 48 its = append(its, ami) 49 } 50 for _, t := range auxt { 51 its = append(its, v.s.tops.newIterator(t, slice, ro)) 52 } 53 54 emi := em.NewIterator(slice) 55 emi.SetReleaser(&memdbReleaser{m: em}) 56 its = append(its, emi) 57 if fm != nil { 58 fmi := fm.NewIterator(slice) 59 fmi.SetReleaser(&memdbReleaser{m: fm}) 60 its = append(its, fmi) 61 } 62 its = append(its, tableIts...) 63 mi := iterator.NewMergedIterator(its, db.s.icmp, strict) 64 mi.SetReleaser(&versionReleaser{v: v}) 65 return mi 66 } 67 68 func (db *DB) newIterator(auxm *memDB, auxt tFiles, seq uint64, slice *util.Range, ro *opt.ReadOptions) *dbIter { 69 var islice *util.Range 70 if slice != nil { 71 islice = &util.Range{} 72 if slice.Start != nil { 73 islice.Start = makeInternalKey(nil, slice.Start, keyMaxSeq, keyTypeSeek) 74 } 75 if slice.Limit != nil { 76 islice.Limit = makeInternalKey(nil, slice.Limit, keyMaxSeq, keyTypeSeek) 77 } 78 } 79 rawIter := db.newRawIterator(auxm, auxt, islice, ro) 80 iter := &dbIter{ 81 db: db, 82 icmp: db.s.icmp, 83 iter: rawIter, 84 seq: seq, 85 strict: opt.GetStrict(db.s.o.Options, ro, opt.StrictReader), 86 disableSampling: db.s.o.GetDisableSeeksCompaction() || db.s.o.GetIteratorSamplingRate() <= 0, 87 key: make([]byte, 0), 88 value: make([]byte, 0), 89 } 90 if !iter.disableSampling { 91 iter.samplingGap = db.iterSamplingRate() 92 } 93 atomic.AddInt32(&db.aliveIters, 1) 94 runtime.SetFinalizer(iter, (*dbIter).Release) 95 return iter 96 } 97 98 func (db *DB) iterSamplingRate() int { 99 return rand.Intn(2 * db.s.o.GetIteratorSamplingRate()) 100 } 101 102 type dir int 103 104 const ( 105 dirReleased dir = iota - 1 106 dirSOI 107 dirEOI 108 dirBackward 109 dirForward 110 ) 111 112 // dbIter represent an interator states over a database session. 113 type dbIter struct { 114 db *DB 115 icmp *iComparer 116 iter iterator.Iterator 117 seq uint64 118 strict bool 119 disableSampling bool 120 121 samplingGap int 122 dir dir 123 key []byte 124 value []byte 125 err error 126 releaser util.Releaser 127 } 128 129 func (i *dbIter) sampleSeek() { 130 if i.disableSampling { 131 return 132 } 133 134 ikey := i.iter.Key() 135 i.samplingGap -= len(ikey) + len(i.iter.Value()) 136 for i.samplingGap < 0 { 137 i.samplingGap += i.db.iterSamplingRate() 138 i.db.sampleSeek(ikey) 139 } 140 } 141 142 func (i *dbIter) setErr(err error) { 143 i.err = err 144 i.key = nil 145 i.value = nil 146 } 147 148 func (i *dbIter) iterErr() { 149 if err := i.iter.Error(); err != nil { 150 i.setErr(err) 151 } 152 } 153 154 func (i *dbIter) Valid() bool { 155 return i.err == nil && i.dir > dirEOI 156 } 157 158 func (i *dbIter) First() bool { 159 if i.err != nil { 160 return false 161 } else if i.dir == dirReleased { 162 i.err = ErrIterReleased 163 return false 164 } 165 166 if i.iter.First() { 167 i.dir = dirSOI 168 return i.next() 169 } 170 i.dir = dirEOI 171 i.iterErr() 172 return false 173 } 174 175 func (i *dbIter) Last() bool { 176 if i.err != nil { 177 return false 178 } else if i.dir == dirReleased { 179 i.err = ErrIterReleased 180 return false 181 } 182 183 if i.iter.Last() { 184 return i.prev() 185 } 186 i.dir = dirSOI 187 i.iterErr() 188 return false 189 } 190 191 func (i *dbIter) Seek(key []byte) bool { 192 if i.err != nil { 193 return false 194 } else if i.dir == dirReleased { 195 i.err = ErrIterReleased 196 return false 197 } 198 199 ikey := makeInternalKey(nil, key, i.seq, keyTypeSeek) 200 if i.iter.Seek(ikey) { 201 i.dir = dirSOI 202 return i.next() 203 } 204 i.dir = dirEOI 205 i.iterErr() 206 return false 207 } 208 209 func (i *dbIter) next() bool { 210 for { 211 if ukey, seq, kt, kerr := parseInternalKey(i.iter.Key()); kerr == nil { 212 i.sampleSeek() 213 if seq <= i.seq { 214 switch kt { 215 case keyTypeDel: 216 // Skip deleted key. 217 i.key = append(i.key[:0], ukey...) 218 i.dir = dirForward 219 case keyTypeVal: 220 if i.dir == dirSOI || i.icmp.uCompare(ukey, i.key) > 0 { 221 i.key = append(i.key[:0], ukey...) 222 i.value = append(i.value[:0], i.iter.Value()...) 223 i.dir = dirForward 224 return true 225 } 226 } 227 } 228 } else if i.strict { 229 i.setErr(kerr) 230 break 231 } 232 if !i.iter.Next() { 233 i.dir = dirEOI 234 i.iterErr() 235 break 236 } 237 } 238 return false 239 } 240 241 func (i *dbIter) Next() bool { 242 if i.dir == dirEOI || i.err != nil { 243 return false 244 } else if i.dir == dirReleased { 245 i.err = ErrIterReleased 246 return false 247 } 248 249 if !i.iter.Next() || (i.dir == dirBackward && !i.iter.Next()) { 250 i.dir = dirEOI 251 i.iterErr() 252 return false 253 } 254 return i.next() 255 } 256 257 func (i *dbIter) prev() bool { 258 i.dir = dirBackward 259 del := true 260 if i.iter.Valid() { 261 for { 262 if ukey, seq, kt, kerr := parseInternalKey(i.iter.Key()); kerr == nil { 263 i.sampleSeek() 264 if seq <= i.seq { 265 if !del && i.icmp.uCompare(ukey, i.key) < 0 { 266 return true 267 } 268 del = (kt == keyTypeDel) 269 if !del { 270 i.key = append(i.key[:0], ukey...) 271 i.value = append(i.value[:0], i.iter.Value()...) 272 } 273 } 274 } else if i.strict { 275 i.setErr(kerr) 276 return false 277 } 278 if !i.iter.Prev() { 279 break 280 } 281 } 282 } 283 if del { 284 i.dir = dirSOI 285 i.iterErr() 286 return false 287 } 288 return true 289 } 290 291 func (i *dbIter) Prev() bool { 292 if i.dir == dirSOI || i.err != nil { 293 return false 294 } else if i.dir == dirReleased { 295 i.err = ErrIterReleased 296 return false 297 } 298 299 switch i.dir { 300 case dirEOI: 301 return i.Last() 302 case dirForward: 303 for i.iter.Prev() { 304 if ukey, _, _, kerr := parseInternalKey(i.iter.Key()); kerr == nil { 305 i.sampleSeek() 306 if i.icmp.uCompare(ukey, i.key) < 0 { 307 goto cont 308 } 309 } else if i.strict { 310 i.setErr(kerr) 311 return false 312 } 313 } 314 i.dir = dirSOI 315 i.iterErr() 316 return false 317 } 318 319 cont: 320 return i.prev() 321 } 322 323 func (i *dbIter) Key() []byte { 324 if i.err != nil || i.dir <= dirEOI { 325 return nil 326 } 327 return i.key 328 } 329 330 func (i *dbIter) Value() []byte { 331 if i.err != nil || i.dir <= dirEOI { 332 return nil 333 } 334 return i.value 335 } 336 337 func (i *dbIter) Release() { 338 if i.dir != dirReleased { 339 // Clear the finalizer. 340 runtime.SetFinalizer(i, nil) 341 342 if i.releaser != nil { 343 i.releaser.Release() 344 i.releaser = nil 345 } 346 347 i.dir = dirReleased 348 i.key = nil 349 i.value = nil 350 i.iter.Release() 351 i.iter = nil 352 atomic.AddInt32(&i.db.aliveIters, -1) 353 i.db = nil 354 } 355 } 356 357 func (i *dbIter) SetReleaser(releaser util.Releaser) { 358 if i.dir == dirReleased { 359 panic(util.ErrReleased) 360 } 361 if i.releaser != nil && releaser != nil { 362 panic(util.ErrHasReleaser) 363 } 364 i.releaser = releaser 365 } 366 367 func (i *dbIter) Error() error { 368 return i.err 369 }