// 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 (p *Snapshot) NewIterator(slice *util.Range, ro *opt.ReadOptions) iterator.Iterator { db := p.db if err := db.ok(); err != nil { return iterator.NewEmptyIterator(err) } p.mu.Lock() defer p.mu.Unlock() if p.released { return iterator.NewEmptyIterator(ErrSnapshotReleased) } return db.newIterator(p.elem.seq, slice, ro) }
// 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) }
func (r *Reader) getDataIter(dataBH blockHandle, slice *util.Range, verifyChecksum, fillCache bool) iterator.Iterator { b, rel, err := r.readBlockCached(dataBH, verifyChecksum, fillCache) if err != nil { return iterator.NewEmptyIterator(err) } return r.newBlockIter(b, rel, slice, false) }
// NewIterator returns an iterator for the latest snapshot of the transaction. // The returned iterator is not safe for concurrent use, but it is safe to use // multiple iterators concurrently, with each in a dedicated goroutine. // It is also safe to use an iterator concurrently while writes to the // transaction. 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 (tr *Transaction) NewIterator(slice *util.Range, ro *opt.ReadOptions) iterator.Iterator { tr.lk.RLock() defer tr.lk.RUnlock() if tr.closed { return iterator.NewEmptyIterator(errTransactionDone) } tr.mem.incref() return tr.db.newIterator(tr.mem, tr.tables, tr.seq, slice, ro) }
// 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 { if r.err != nil { return iterator.NewEmptyIterator(r.err) } fillCache := !ro.GetDontFillCache() b, rel, err := r.readBlockCached(r.indexBH, true, fillCache) if err != nil { return iterator.NewEmptyIterator(err) } index := &indexIter{ blockIter: b.newIterator(slice, true, rel), slice: slice, checksum: ro.GetStrict(opt.StrictBlockChecksum), fillCache: !ro.GetDontFillCache(), } return iterator.NewIndexedIterator(index, r.strictIter || ro.GetStrict(opt.StrictIterator), false) }
// 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. // // The iterator must be released after use, by calling Release method. // // Also read Iterator documentation of the leveldb/iterator package. func (d *DB) NewIterator(ro *opt.ReadOptions) iterator.Iterator { if err := d.ok(); err != nil { return iterator.NewEmptyIterator(err) } p := d.newSnapshot() defer p.Release() return p.NewIterator(ro) }
func (t *tOps) newIterator(f *tFile, ro *opt.ReadOptions) iterator.Iterator { c, err := t.lookup(f) if err != nil { return iterator.NewEmptyIterator(err) } iter := c.Value().(*table.Reader).NewIterator(ro) iter.SetReleaser(c) return iter }
// Creates an iterator from the given table. func (t *tOps) newIterator(f *tFile, slice *util.Range, ro *opt.ReadOptions) iterator.Iterator { ch, err := t.open(f) if err != nil { return iterator.NewEmptyIterator(err) } iter := ch.Value().(*table.Reader).NewIterator(slice, ro) iter.SetReleaser(ch) return iter }
// 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) }
func (r *Reader) getDataIterErr(dataBH blockHandle, slice *util.Range, verifyChecksum, fillCache bool) iterator.Iterator { r.mu.RLock() defer r.mu.RUnlock() if r.err != nil { return iterator.NewEmptyIterator(r.err) } return r.getDataIter(dataBH, slice, verifyChecksum, fillCache) }
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 }
// 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) } se := db.acquireSnapshot() defer db.releaseSnapshot(se) // Iterator holds 'version' lock, 'version' is immutable so snapshot // can be released after iterator created. return db.newIterator(se.seq, slice, ro) }
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)")) } iter := i.tableReader.getDataIter(dataBH, i.checksum, i.fillCache) return iter }
// 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)) }
// 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: indexBlock.newIterator(slice, true, rel), slice: slice, checksum: ro.GetStrict(opt.StrictBlockChecksum), fillCache: !ro.GetDontFillCache(), } return iterator.NewIndexedIterator(index, r.strictIter || ro.GetStrict(opt.StrictIterator), true) }
// NewIterator returns an iterator of 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(ro *opt.ReadOptions) iterator.Iterator { if r.err != nil { return iterator.NewEmptyIterator(r.err) } index := &indexIter{ blockIter: *r.indexBlock.newIterator(nil), tableReader: r, checksum: ro.GetStrict(opt.StrictBlockChecksum), fillCache: !ro.GetDontFillCache(), } return iterator.NewIndexedIterator(index, r.strictIter || ro.GetStrict(opt.StrictIterator)) }
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 := r.cache.Get(dataBH.offset, func() (charge int, value interface{}) { if !fillCache { return 0, nil } var dataBlock *block dataBlock, err = r.readBlock(dataBH, checksum) if err != nil { return 0, nil } return int(dataBH.length), dataBlock }) if err != nil { return iterator.NewEmptyIterator(err) } if cache != nil { 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, dataBlock) return iter }
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) }
func (i *indexIter) Get() iterator.Iterator { value := i.Value() if value == nil { return nil } dataBH, n := decodeBlockHandle(value) if n == 0 { return iterator.NewEmptyIterator(i.tr.newErrCorruptedBH(i.tr.indexBH, "bad data block handle")) } var slice *util.Range if i.slice != nil && (i.blockIter.isFirst() || i.blockIter.isLast()) { slice = i.slice } return i.tr.getDataIterErr(dataBH, slice, i.tr.verifyChecksum, i.fillCache) }