Example #1
0
func (db *DB) newIterator(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 = newIKey(slice.Start, kMaxSeq, tSeek)
		}
		if slice.Limit != nil {
			islice.Limit = newIKey(slice.Limit, kMaxSeq, tSeek)
		}
	}
	rawIter := db.newRawIterator(islice, ro)
	iter := &dbIter{
		db:     db,
		icmp:   db.s.icmp,
		iter:   rawIter,
		seq:    seq,
		strict: db.s.o.GetStrict(opt.StrictIterator) || ro.GetStrict(opt.StrictIterator),
		key:    make([]byte, 0),
		value:  make([]byte, 0),
	}
	atomic.AddInt32(&db.aliveIters, 1)
	runtime.SetFinalizer(iter, (*dbIter).Release)
	return iter
}
Example #2
0
// Find finds key/value pair whose key is greater than or equal to the
// given key. It returns ErrNotFound if the table doesn't contain
// such pair.
//
// The caller should not modify the contents of the returned slice, but
// it is safe to modify the contents of the argument after Find returns.
func (r *Reader) Find(key []byte, ro *opt.ReadOptions) (rkey, value []byte, err error) {
	r.mu.RLock()
	defer r.mu.RUnlock()

	if r.err != nil {
		err = r.err
		return
	}

	indexBlock, rel, err := r.getIndexBlock(true)
	if err != nil {
		return
	}
	defer rel.Release()

	index := indexBlock.newIterator(nil, true, nil)
	defer index.Release()
	if !index.Seek(key) {
		err = index.Error()
		if err == nil {
			err = ErrNotFound
		}
		return
	}
	dataBH, n := decodeBlockHandle(index.Value())
	if n == 0 {
		err = errors.New("leveldb/table: Reader: invalid table (bad data block handle)")
		return
	}
	if r.filter != nil {
		filterBlock, rel, ferr := r.getFilterBlock(true)
		if ferr == nil {
			if !filterBlock.contains(dataBH.offset, key) {
				rel.Release()
				return nil, nil, ErrNotFound
			}
			rel.Release()
		}
	}
	data := r.getDataIter(dataBH, nil, ro.GetStrict(opt.StrictBlockChecksum), !ro.GetDontFillCache())
	defer data.Release()
	if !data.Seek(key) {
		err = data.Error()
		if err == nil {
			err = ErrNotFound
		}
		return
	}
	// Don't use block buffer, no need to copy the buffer.
	rkey = data.Key()
	if r.bpool == nil {
		value = data.Value()
	} else {
		// Use block buffer, and since the buffer will be recycled, the buffer
		// need to be copied.
		value = append([]byte{}, data.Value()...)
	}
	return
}
Example #3
0
func (db *DB) newIterator(seq uint64, ro *opt.ReadOptions) *dbIter {
	rawIter := db.newRawIterator(ro)
	iter := &dbIter{
		cmp:    db.s.cmp.cmp,
		iter:   rawIter,
		seq:    seq,
		strict: db.s.o.GetStrict(opt.StrictIterator) || ro.GetStrict(opt.StrictIterator),
	}
	runtime.SetFinalizer(iter, (*dbIter).Release)
	return iter
}
Example #4
0
File: db.go Project: 29n/goleveldb
// Get get value for given key of the latest snapshot of database.
func (d *DB) Get(key []byte, ro *opt.ReadOptions) (value []byte, err error) {
	err = d.rok()
	if err != nil {
		return
	}

	value, err = d.get(key, d.getSeq(), ro)
	if ro.HasFlag(opt.RFDontCopyBuffer) {
		return
	}
	return dupBytes(value), err
}
Example #5
0
//	// return (start, end], not include start
func (d *DB) Iterator(start Bytes, end Bytes) (ret *Iterator) {
	if len(start) == 0 {
		start = nil
	}
	if len(end) == 0 {
		end = nil
	}
	var iopt opt.ReadOptions
	iopt.DontFillCache = true
	it := d.db.NewIterator(&util.Range{Start: start, Limit: end}, &iopt)
	return NewIterator(it, FORWARD)
}
Example #6
0
func (db *DB) newRawIterator(slice *util.Range, ro *opt.ReadOptions) iterator.Iterator {
	em, fm := db.getMems()
	v := db.s.version()

	ti := v.getIterators(slice, ro)
	n := len(ti) + 2
	i := make([]iterator.Iterator, 0, n)
	i = append(i, em.NewIterator(slice))
	if fm != nil {
		i = append(i, fm.NewIterator(slice))
	}
	i = append(i, ti...)
	strict := db.s.o.GetStrict(opt.StrictIterator) || ro.GetStrict(opt.StrictIterator)
	mi := iterator.NewMergedIterator(i, db.s.icmp, strict)
	mi.SetReleaser(&versionReleaser{v: v})
	return mi
}
Example #7
0
func (db *DB) newRawIterator(ro *opt.ReadOptions) iterator.Iterator {
	s := db.s

	mem, frozenMem := db.getMem()
	v := s.version()

	tableIters := v.getIterators(ro)
	iters := make([]iterator.Iterator, 0, len(tableIters)+2)
	iters = append(iters, mem.NewIterator())
	if frozenMem != nil {
		iters = append(iters, frozenMem.NewIterator())
	}
	iters = append(iters, tableIters...)
	strict := s.o.GetStrict(opt.StrictIterator) || ro.GetStrict(opt.StrictIterator)
	mi := iterator.NewMergedIterator(iters, s.cmp, strict)
	mi.SetReleaser(&versionReleaser{v: v})
	return mi
}
Example #8
0
func (v *version) getIterators(slice *util.Range, ro *opt.ReadOptions) (its []iterator.Iterator) {
	// Merge all level zero files together since they may overlap
	for _, t := range v.tables[0] {
		it := v.s.tops.newIterator(t, slice, ro)
		its = append(its, it)
	}

	strict := v.s.o.GetStrict(opt.StrictIterator) || ro.GetStrict(opt.StrictIterator)
	for _, tables := range v.tables[1:] {
		if len(tables) == 0 {
			continue
		}

		it := iterator.NewIndexedIterator(tables.newIndexIterator(v.s.tops, v.s.icmp, slice, ro), strict, true)
		its = append(its, it)
	}

	return
}
Example #9
0
// NewIterator return an iterator over the contents of this snapshot of
// database.
//
// Please note that the iterator is not thread-safe, you may not use same
// iterator instance concurrently without external synchronization.
func (p *Snapshot) NewIterator(ro *opt.ReadOptions) iterator.Iterator {
	if atomic.LoadUint32(&p.released) != 0 {
		return &iterator.EmptyIterator{errors.ErrSnapshotReleased}
	}

	d := p.d

	if err := d.rok(); err != nil {
		return &iterator.EmptyIterator{err}
	}

	return &dbIter{
		snap:       p,
		cmp:        d.s.cmp.cmp,
		it:         d.newRawIterator(ro),
		seq:        p.entry.seq,
		copyBuffer: !ro.HasFlag(opt.RFDontCopyBuffer),
	}
}
Example #10
0
// 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))
}
Example #11
0
func (v *version) getIterators(ro *opt.ReadOptions) (its []iterator.Iterator) {
	s := v.s
	icmp := s.cmp

	// Merge all level zero files together since they may overlap
	for _, t := range v.tables[0] {
		it := s.tops.newIterator(t, ro)
		its = append(its, it)
	}

	strict := s.o.GetStrict(opt.StrictIterator) || ro.GetStrict(opt.StrictIterator)
	for _, tt := range v.tables[1:] {
		if len(tt) == 0 {
			continue
		}

		it := iterator.NewIndexedIterator(tt.newIndexIterator(s.tops, icmp, ro), strict)
		its = append(its, it)
	}

	return
}
Example #12
0
func (db *DB) newIterator(seq uint64, slice *util.Range, ro *opt.ReadOptions) *dbIter {
	var slice_ *util.Range
	if slice != nil {
		slice_ = &util.Range{}
		if slice.Start != nil {
			slice_.Start = newIKey(slice.Start, kMaxSeq, tSeek)
		}
		if slice.Limit != nil {
			slice_.Limit = newIKey(slice.Limit, kMaxSeq, tSeek)
		}
	}
	rawIter := db.newRawIterator(slice_, ro)
	iter := &dbIter{
		cmp:    db.s.cmp.cmp,
		iter:   rawIter,
		seq:    seq,
		strict: db.s.o.GetStrict(opt.StrictIterator) || ro.GetStrict(opt.StrictIterator),
		key:    make([]byte, 0),
		value:  make([]byte, 0),
	}
	runtime.SetFinalizer(iter, (*dbIter).Release)
	return iter
}
Example #13
0
// Find finds key/value pair whose key is greater than or equal to the
// given key. It returns ErrNotFound if the table doesn't contain
// such pair.
//
// The caller should not modify the contents of the returned slice, but
// it is safe to modify the contents of the argument after Find returns.
func (r *Reader) Find(key []byte, ro *opt.ReadOptions) (rkey, value []byte, err error) {
	if r.err != nil {
		err = r.err
		return
	}

	index := r.indexBlock.newIterator(nil)
	defer index.Release()
	if !index.Seek(key) {
		err = index.Error()
		if err == nil {
			err = ErrNotFound
		}
		return
	}
	dataBH, n := decodeBlockHandle(index.Value())
	if n == 0 {
		err = errors.New("leveldb/table: Reader: invalid table (bad data block handle)")
		return
	}
	if r.filterBlock != nil && !r.filterBlock.contains(dataBH.offset, key) {
		err = ErrNotFound
		return
	}
	data := r.getDataIter(dataBH, ro.GetStrict(opt.StrictBlockChecksum), !ro.GetDontFillCache())
	defer data.Release()
	if !data.Seek(key) {
		err = data.Error()
		if err == nil {
			err = ErrNotFound
		}
		return
	}
	rkey = data.Key()
	value = data.Value()
	return
}
Example #14
0
// 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)
}
Example #15
0
// 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))
}
Example #16
0
// 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)
}
Example #17
0
func (r *Reader) find(key []byte, filtered bool, ro *opt.ReadOptions, noValue bool) (rkey, value []byte, err error) {
	r.mu.RLock()
	defer r.mu.RUnlock()

	if r.err != nil {
		err = r.err
		return
	}

	indexBlock, rel, err := r.getIndexBlock(true)
	if err != nil {
		return
	}
	defer rel.Release()

	index := r.newBlockIter(indexBlock, nil, nil, true)
	defer index.Release()
	if !index.Seek(key) {
		err = index.Error()
		if err == nil {
			err = ErrNotFound
		}
		return
	}
	dataBH, n := decodeBlockHandle(index.Value())
	if n == 0 {
		r.err = r.newErrCorruptedBH(r.indexBH, "bad data block handle")
		return
	}
	if filtered && r.filter != nil {
		filterBlock, frel, ferr := r.getFilterBlock(true)
		if ferr == nil {
			if !filterBlock.contains(r.filter, dataBH.offset, key) {
				frel.Release()
				return nil, nil, ErrNotFound
			}
			frel.Release()
		} else if !errors.IsCorrupted(ferr) {
			err = ferr
			return
		}
	}
	data := r.getDataIter(dataBH, nil, r.verifyChecksum, !ro.GetDontFillCache())
	defer data.Release()
	if !data.Seek(key) {
		err = data.Error()
		if err == nil {
			err = ErrNotFound
		}
		return
	}
	// Don't use block buffer, no need to copy the buffer.
	rkey = data.Key()
	if !noValue {
		if r.bpool == nil {
			value = data.Value()
		} else {
			// Use block buffer, and since the buffer will be recycled, the buffer
			// need to be copied.
			value = append([]byte{}, data.Value()...)
		}
	}
	return
}