mirror of https://github.com/siddontang/go.git
iterator update
This commit is contained in:
parent
da25e2b37f
commit
c9cefc35fa
|
@ -116,7 +116,7 @@ func (db *DB) Destroy() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) Clear() {
|
func (db *DB) Clear() {
|
||||||
it := db.Iterator(NewRange(nil, nil), 0)
|
it := db.Iterator(nil, nil, 0, 0)
|
||||||
for ; it.Valid(); it.Next() {
|
for ; it.Valid(); it.Next() {
|
||||||
db.Delete(it.Key())
|
db.Delete(it.Key())
|
||||||
}
|
}
|
||||||
|
@ -141,14 +141,14 @@ func (db *DB) NewWriteBatch() *WriteBatch {
|
||||||
return wb
|
return wb
|
||||||
}
|
}
|
||||||
|
|
||||||
//limit <= 0, no limit
|
//limit <= 0, unlimit
|
||||||
func (db *DB) Iterator(r *Range, limit int) *Iterator {
|
func (db *DB) Iterator(min []byte, max []byte, rangeType uint8, limit int) *Iterator {
|
||||||
return newIterator(db, db.iteratorOpts, r, limit, forward)
|
return newIterator(db, db.iteratorOpts, NewRange(min, max, rangeType), limit, IteratorForward)
|
||||||
}
|
}
|
||||||
|
|
||||||
//limit <= 0, no limit
|
//limit <= 0, unlimit
|
||||||
func (db *DB) ReverseIterator(r *Range, limit int) *Iterator {
|
func (db *DB) RevIterator(min []byte, max []byte, rangeType uint8, limit int) *Iterator {
|
||||||
return newIterator(db, db.iteratorOpts, r, limit, backward)
|
return newIterator(db, db.iteratorOpts, NewRange(min, max, rangeType), limit, IteratorBackward)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) NewSnapshot() *Snapshot {
|
func (db *DB) NewSnapshot() *Snapshot {
|
||||||
|
|
|
@ -5,35 +5,33 @@ import (
|
||||||
"github.com/jmhodges/levigo"
|
"github.com/jmhodges/levigo"
|
||||||
)
|
)
|
||||||
|
|
||||||
const forward uint8 = 0
|
const (
|
||||||
const backward uint8 = 1
|
IteratorForward uint8 = 0
|
||||||
|
IteratorBackward uint8 = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
RangeClose uint8 = 0x00
|
||||||
|
RangeLOpen uint8 = 0x01
|
||||||
|
RangeROpen uint8 = 0x10
|
||||||
|
RangeOpen uint8 = 0x11
|
||||||
|
)
|
||||||
|
|
||||||
//min must less or equal than max
|
//min must less or equal than max
|
||||||
//MinEx if true, range is left open interval (min, ...
|
//range type:
|
||||||
//MaxEx if true, range is right open interval ..., max)
|
//close: [min, max]
|
||||||
//Default range is close interval
|
//open: (min, max)
|
||||||
|
//lopen: (min, max]
|
||||||
|
//ropen: [min, max)
|
||||||
type Range struct {
|
type Range struct {
|
||||||
Min []byte
|
Min []byte
|
||||||
Max []byte
|
Max []byte
|
||||||
|
|
||||||
MinEx bool
|
Type uint8
|
||||||
MaxEx bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRange(min []byte, max []byte) *Range {
|
func NewRange(min []byte, max []byte, tp uint8) *Range {
|
||||||
return &Range{min, max, false, false}
|
return &Range{min, max, tp}
|
||||||
}
|
|
||||||
|
|
||||||
func NewOpenRange(min []byte, max []byte) *Range {
|
|
||||||
return &Range{min, max, true, true}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewLOpenRange(min []byte, max []byte) *Range {
|
|
||||||
return &Range{min, max, true, false}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewROpenRange(min []byte, max []byte) *Range {
|
|
||||||
return &Range{min, max, true, true}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Iterator struct {
|
type Iterator struct {
|
||||||
|
@ -45,7 +43,7 @@ type Iterator struct {
|
||||||
|
|
||||||
step int
|
step int
|
||||||
|
|
||||||
//0 for forward, 1 for backward
|
//0 for IteratorForward, 1 for IteratorBackward
|
||||||
direction uint8
|
direction uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,15 +54,16 @@ func newIterator(db *DB, opts *levigo.ReadOptions, r *Range, limit int, directio
|
||||||
it.r = r
|
it.r = r
|
||||||
it.limit = limit
|
it.limit = limit
|
||||||
it.direction = direction
|
it.direction = direction
|
||||||
|
|
||||||
it.step = 0
|
it.step = 0
|
||||||
|
|
||||||
if direction == forward {
|
if direction == IteratorForward {
|
||||||
if r.Min == nil {
|
if r.Min == nil {
|
||||||
it.it.SeekToFirst()
|
it.it.SeekToFirst()
|
||||||
} else {
|
} else {
|
||||||
it.it.Seek(r.Min)
|
it.it.Seek(r.Min)
|
||||||
|
|
||||||
if r.MinEx {
|
if r.Type&RangeLOpen > 0 {
|
||||||
if it.Valid() && bytes.Equal(it.Key(), r.Min) {
|
if it.Valid() && bytes.Equal(it.Key(), r.Min) {
|
||||||
it.it.Next()
|
it.it.Next()
|
||||||
}
|
}
|
||||||
|
@ -80,7 +79,7 @@ func newIterator(db *DB, opts *levigo.ReadOptions, r *Range, limit int, directio
|
||||||
it.it.Prev()
|
it.it.Prev()
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.MaxEx {
|
if r.Type&RangeROpen > 0 {
|
||||||
if it.Valid() && bytes.Equal(it.Key(), r.Max) {
|
if it.Valid() && bytes.Equal(it.Key(), r.Max) {
|
||||||
it.it.Prev()
|
it.it.Prev()
|
||||||
}
|
}
|
||||||
|
@ -100,22 +99,22 @@ func (it *Iterator) Valid() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if it.direction == forward {
|
if it.direction == IteratorForward {
|
||||||
if it.r.Max != nil {
|
if it.r.Max != nil {
|
||||||
r := bytes.Compare(it.Key(), it.r.Max)
|
r := bytes.Compare(it.Key(), it.r.Max)
|
||||||
if !it.r.MaxEx {
|
if it.r.Type&RangeROpen > 0 {
|
||||||
return !(r > 0)
|
|
||||||
} else {
|
|
||||||
return !(r >= 0)
|
return !(r >= 0)
|
||||||
|
} else {
|
||||||
|
return !(r > 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if it.r.Min != nil {
|
if it.r.Min != nil {
|
||||||
r := bytes.Compare(it.Key(), it.r.Min)
|
r := bytes.Compare(it.Key(), it.r.Min)
|
||||||
if !it.r.MinEx {
|
if it.r.Type&RangeLOpen > 0 {
|
||||||
return !(r < 0)
|
|
||||||
} else {
|
|
||||||
return !(r <= 0)
|
return !(r <= 0)
|
||||||
|
} else {
|
||||||
|
return !(r < 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,7 +129,7 @@ func (it *Iterator) GetError() error {
|
||||||
func (it *Iterator) Next() {
|
func (it *Iterator) Next() {
|
||||||
it.step++
|
it.step++
|
||||||
|
|
||||||
if it.direction == forward {
|
if it.direction == IteratorForward {
|
||||||
it.it.Next()
|
it.it.Next()
|
||||||
} else {
|
} else {
|
||||||
it.it.Prev()
|
it.it.Prev()
|
||||||
|
|
|
@ -129,34 +129,6 @@ func checkIterator(it *Iterator, cv ...int) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func testKeyRange(min int, max int) *Range {
|
|
||||||
return &Range{
|
|
||||||
[]byte(fmt.Sprintf("key_%d", min)),
|
|
||||||
[]byte(fmt.Sprintf("key_%d", max)),
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testLKeyRange(min int, max int) *Range {
|
|
||||||
r := testKeyRange(min, max)
|
|
||||||
r.MinEx = true
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func testRKeyRange(min int, max int) *Range {
|
|
||||||
r := testKeyRange(min, max)
|
|
||||||
r.MaxEx = true
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func testOpenKeyRange(min int, max int) *Range {
|
|
||||||
r := testKeyRange(min, max)
|
|
||||||
r.MinEx = true
|
|
||||||
r.MaxEx = true
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIterator(t *testing.T) {
|
func TestIterator(t *testing.T) {
|
||||||
db := getTestDB()
|
db := getTestDB()
|
||||||
|
|
||||||
|
@ -170,52 +142,56 @@ func TestIterator(t *testing.T) {
|
||||||
|
|
||||||
var it *Iterator
|
var it *Iterator
|
||||||
|
|
||||||
it = db.Iterator(testKeyRange(1, 5), 0)
|
k := func(i int) []byte {
|
||||||
|
return []byte(fmt.Sprintf("key_%d", i))
|
||||||
|
}
|
||||||
|
|
||||||
|
it = db.Iterator(k(1), k(5), RangeClose, 0)
|
||||||
if err := checkIterator(it, 1, 2, 3, 4, 5); err != nil {
|
if err := checkIterator(it, 1, 2, 3, 4, 5); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
it = db.Iterator(testKeyRange(1, 9), 5)
|
it = db.Iterator(k(1), k(5), RangeClose, 3)
|
||||||
if err := checkIterator(it, 1, 2, 3, 4, 5); err != nil {
|
if err := checkIterator(it, 1, 2, 3); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
it = db.Iterator(testLKeyRange(1, 5), 0)
|
it = db.Iterator(k(1), k(5), RangeLOpen, 0)
|
||||||
if err := checkIterator(it, 2, 3, 4, 5); err != nil {
|
if err := checkIterator(it, 2, 3, 4, 5); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
it = db.Iterator(testRKeyRange(1, 5), 0)
|
it = db.Iterator(k(1), k(5), RangeROpen, 0)
|
||||||
if err := checkIterator(it, 1, 2, 3, 4); err != nil {
|
if err := checkIterator(it, 1, 2, 3, 4); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
it = db.Iterator(testOpenKeyRange(1, 5), 0)
|
it = db.Iterator(k(1), k(5), RangeOpen, 0)
|
||||||
if err := checkIterator(it, 2, 3, 4); err != nil {
|
if err := checkIterator(it, 2, 3, 4); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
it = db.ReverseIterator(testKeyRange(1, 5), 0)
|
it = db.RevIterator(k(1), k(5), RangeClose, 0)
|
||||||
if err := checkIterator(it, 5, 4, 3, 2, 1); err != nil {
|
if err := checkIterator(it, 5, 4, 3, 2, 1); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
it = db.ReverseIterator(testKeyRange(1, 9), 5)
|
it = db.RevIterator(k(1), k(5), RangeClose, 3)
|
||||||
if err := checkIterator(it, 9, 8, 7, 6, 5); err != nil {
|
if err := checkIterator(it, 5, 4, 3); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
it = db.ReverseIterator(testLKeyRange(1, 5), 0)
|
it = db.RevIterator(k(1), k(5), RangeLOpen, 0)
|
||||||
if err := checkIterator(it, 5, 4, 3, 2); err != nil {
|
if err := checkIterator(it, 5, 4, 3, 2); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
it = db.ReverseIterator(testRKeyRange(1, 5), 0)
|
it = db.RevIterator(k(1), k(5), RangeROpen, 0)
|
||||||
if err := checkIterator(it, 4, 3, 2, 1); err != nil {
|
if err := checkIterator(it, 4, 3, 2, 1); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
it = db.ReverseIterator(testOpenKeyRange(1, 5), 0)
|
it = db.RevIterator(k(1), k(5), RangeOpen, 0)
|
||||||
if err := checkIterator(it, 4, 3, 2); err != nil {
|
if err := checkIterator(it, 4, 3, 2); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,13 +37,12 @@ func (s *Snapshot) Get(key []byte) ([]byte, error) {
|
||||||
return s.db.db.Get(s.readOpts, key)
|
return s.db.db.Get(s.readOpts, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
//same as db iterator and reverse iterator
|
func (s *Snapshot) Iterator(min []byte, max []byte, rangeType uint8, limit int) *Iterator {
|
||||||
func (s *Snapshot) Iterator(r *Range, limit int) *Iterator {
|
return newIterator(s.db, s.iteratorOpts, NewRange(min, max, rangeType), limit, IteratorForward)
|
||||||
return newIterator(s.db, s.iteratorOpts, r, limit, forward)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Snapshot) ReverseIterator(r *Range, limit int) *Iterator {
|
func (s *Snapshot) RevIterator(min []byte, max []byte, rangeType uint8, limit int) *Iterator {
|
||||||
return newIterator(s.db, s.iteratorOpts, r, limit, backward)
|
return newIterator(s.db, s.iteratorOpts, NewRange(min, max, rangeType), limit, IteratorBackward)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Snapshot) GetInt(key []byte) (int64, error) {
|
func (s *Snapshot) GetInt(key []byte) (int64, error) {
|
||||||
|
|
Loading…
Reference in New Issue