iterator update

This commit is contained in:
siddontang 2014-05-07 14:18:11 +08:00
parent da25e2b37f
commit c9cefc35fa
4 changed files with 59 additions and 85 deletions

View File

@ -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 {

View File

@ -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()

View File

@ -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)
} }

View File

@ -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) {