// NewIterator returns an iterator for the snapshot of the uderlying DB. // The returned iterator is not goroutine-safe, but it is safe to use // multiple iterators concurrently, with each in a dedicated goroutine. // It is also safe to use an iterator concurrently with modifying its // underlying DB. The resultant key/value pairs are guaranteed to be // consistent. // // 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 // DB. And a nil Range.Limit is treated as a key after all keys in // the DB. // // The iterator must be released after use, by calling Release method. // Releasing the snapshot doesn't mean releasing the iterator too, the // iterator would be still valid until released. // // Also read Iterator documentation of the leveldb/iterator package. func (snap *Snapshot) NewIterator(slice *util.Range, ro *opt.ReadOptions) iterator.Iterator { if err := snap.db.ok(); err != nil { return iterator.NewEmptyIterator(err) } snap.mu.Lock() defer snap.mu.Unlock() if snap.released { return iterator.NewEmptyIterator(ErrSnapshotReleased) } // Since iterator already hold version ref, it doesn't need to // hold snapshot ref. return snap.db.newIterator(snap.elem.seq, slice, ro) }
// NewIterator returns an iterator for the latest snapshot of the // uderlying DB. // The returned iterator is not goroutine-safe, but it is safe to use // multiple iterators concurrently, with each in a dedicated goroutine. // It is also safe to use an iterator concurrently with modifying its // underlying DB. The resultant key/value pairs are guaranteed to be // consistent. // // 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 // DB. And a nil Range.Limit is treated as a key after all keys in // the DB. // // The iterator must be released after use, by calling Release method. // // Also read Iterator documentation of the leveldb/iterator package. func (db *DB) NewIterator(slice *util.Range, ro *opt.ReadOptions) iterator.Iterator { if err := db.ok(); err != nil { return iterator.NewEmptyIterator(err) } snap := db.newSnapshot() defer snap.Release() return snap.NewIterator(slice, ro) }
// Creates an iterator from the given table. func (t *tOps) newIterator(f *tFile, slice *util.Range, ro *opt.ReadOptions) iterator.Iterator { c, err := t.open(f) if err != nil { return iterator.NewEmptyIterator(err) } iter := c.Value().(*table.Reader).NewIterator(slice, ro) iter.SetReleaser(c) return iter }
func (r *Reader) getDataIter(dataBH blockHandle, slice *util.Range, checksum, fillCache bool) iterator.Iterator { if r.cache != nil { // Get/set block cache. var err error cache, ok := r.cache.Get(dataBH.offset, func() (ok bool, value interface{}, charge int, fin cache.SetFin) { if !fillCache { return } var dataBlock *block dataBlock, err = r.readBlock(dataBH, checksum) if err == nil { ok = true value = dataBlock charge = int(dataBH.length) fin = func() { r.bpool.Put(dataBlock.data) dataBlock.data = nil } } return }) if err != nil { return iterator.NewEmptyIterator(err) } if ok { dataBlock := cache.Value().(*block) if !dataBlock.checksum && (r.checksum || checksum) { if !verifyChecksum(dataBlock.data) { return iterator.NewEmptyIterator(errors.New("leveldb/table: Reader: invalid block (checksum mismatch)")) } dataBlock.checksum = true } iter := dataBlock.newIterator(slice, false, cache) return iter } } dataBlock, err := r.readBlock(dataBH, checksum) if err != nil { return iterator.NewEmptyIterator(err) } iter := dataBlock.newIterator(slice, false, releaseBlock{r, dataBlock}) return iter }
func (r *Reader) NewIterator(slice *util.Range, ro *opt.ReadOptions) iterator.Iterator { if r.err != nil { return iterator.NewEmptyIterator(r.err) } index := &indexIter{ blockIter: *r.indexBlock.newIterator(slice, true, nil), tableReader: r, slice: slice, checksum: ro.GetStrict(opt.StrictBlockChecksum), fillCache: !ro.GetDontFillCache(), } return iterator.NewIndexedIterator(index, r.strictIter || ro.GetStrict(opt.StrictIterator), false) }
func (i *indexIter) Get() iterator.Iterator { value := i.Value() if value == nil { return nil } dataBH, n := decodeBlockHandle(value) if n == 0 { return iterator.NewEmptyIterator(errors.New("leveldb/table: Reader: invalid table (bad data block handle)")) } var slice *util.Range if i.slice != nil && (i.blockIter.isFirst() || i.blockIter.isLast()) { slice = i.slice } return i.tableReader.getDataIter(dataBH, slice, i.checksum, i.fillCache) }