コード例 #1
0
ファイル: db_iter.go プロジェクト: baa-archieve/syncthing
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
}
コード例 #2
0
ファイル: reader.go プロジェクト: baa-archieve/syncthing
// 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
}
コード例 #3
0
ファイル: db_iter.go プロジェクト: pombredanne/goleveldb
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
}
コード例 #4
0
ファイル: reader.go プロジェクト: pombredanne/goleveldb
// 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))
}
コード例 #5
0
ファイル: db_iter.go プロジェクト: retgoat/syncthing
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
}
コード例 #6
0
ファイル: db_iter.go プロジェクト: pombredanne/goleveldb
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
}
コード例 #7
0
ファイル: reader.go プロジェクト: chenfj068/goleveldb
// 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)
}
コード例 #8
0
ファイル: version.go プロジェクト: GDXN/syncthing
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
}
コード例 #9
0
ファイル: reader.go プロジェクト: baa-archieve/syncthing
// 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)
}
コード例 #10
0
ファイル: version.go プロジェクト: pombredanne/goleveldb
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
}
コード例 #11
0
ファイル: db_iter.go プロジェクト: kennylixi/goleveldb
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
}
コード例 #12
0
ファイル: reader.go プロジェクト: pombredanne/goleveldb
// 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
}