func (db *DB) newRawIterator(auxm *memDB, auxt tFiles, slice *util.Range, ro *opt.ReadOptions) iterator.Iterator { strict := opt.GetStrict(db.s.o.Options, ro, opt.StrictReader) em, fm := db.getMems() v := db.s.version() tableIts := v.getIterators(slice, ro) n := len(tableIts) + len(auxt) + 3 its := make([]iterator.Iterator, 0, n) if auxm != nil { ami := auxm.NewIterator(slice) ami.SetReleaser(&memdbReleaser{m: auxm}) its = append(its, ami) } for _, t := range auxt { its = append(its, v.s.tops.newIterator(t, slice, ro)) } emi := em.NewIterator(slice) emi.SetReleaser(&memdbReleaser{m: em}) its = append(its, emi) if fm != nil { fmi := fm.NewIterator(slice) fmi.SetReleaser(&memdbReleaser{m: fm}) its = append(its, fmi) } its = append(its, tableIts...) mi := iterator.NewMergedIterator(its, db.s.icmp, strict) mi.SetReleaser(&versionReleaser{v: v}) return mi }
func (db *DB) newIterator(auxm *memDB, auxt tFiles, seq uint64, slice *util.Range, ro *opt.ReadOptions) *dbIter { var islice *util.Range if slice != nil { islice = &util.Range{} if slice.Start != nil { islice.Start = makeInternalKey(nil, slice.Start, keyMaxSeq, keyTypeSeek) } if slice.Limit != nil { islice.Limit = makeInternalKey(nil, slice.Limit, keyMaxSeq, keyTypeSeek) } } rawIter := db.newRawIterator(auxm, auxt, islice, ro) iter := &dbIter{ db: db, icmp: db.s.icmp, iter: rawIter, seq: seq, strict: opt.GetStrict(db.s.o.Options, ro, opt.StrictReader), key: make([]byte, 0), value: make([]byte, 0), } atomic.AddInt32(&db.aliveIters, 1) runtime.SetFinalizer(iter, (*dbIter).Release) return iter }
func (v *version) getIterators(slice *util.Range, ro *opt.ReadOptions) (its []iterator.Iterator) { strict := opt.GetStrict(v.s.o.Options, ro, opt.StrictReader) for level, tables := range v.levels { if level == 0 { // Merge all level zero files together since they may overlap. for _, t := range tables { its = append(its, v.s.tops.newIterator(t, slice, ro)) } } else if len(tables) != 0 { its = append(its, iterator.NewIndexedIterator(tables.newIndexIterator(v.s.tops, v.s.icmp, slice, ro), strict)) } } return }
// NewIterator creates an iterator from the table. // // Slice allows slicing the iterator to only contains keys in the given // range. A nil Range.Start is treated as a key before all keys in the // table. And a nil Range.Limit is treated as a key after all keys in // the table. // // The returned iterator is not goroutine-safe and should be released // when not used. // // Also read Iterator documentation of the leveldb/iterator package. func (r *Reader) NewIterator(slice *util.Range, ro *opt.ReadOptions) iterator.Iterator { r.mu.RLock() defer r.mu.RUnlock() if r.err != nil { return iterator.NewEmptyIterator(r.err) } fillCache := !ro.GetDontFillCache() indexBlock, rel, err := r.getIndexBlock(fillCache) if err != nil { return iterator.NewEmptyIterator(err) } index := &indexIter{ blockIter: r.newBlockIter(indexBlock, rel, slice, true), tr: r, slice: slice, fillCache: !ro.GetDontFillCache(), } return iterator.NewIndexedIterator(index, opt.GetStrict(r.o, ro, opt.StrictReader)) }