Skip to content

Commit 27cf08a

Browse files
committed
update iterator test
1 parent 239b2ee commit 27cf08a

File tree

3 files changed

+65
-4
lines changed

3 files changed

+65
-4
lines changed

index/btree.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ func newMemoryBTreeIterator(tree *btree.BTree, reverse bool) *memoryBTreeIterato
177177
}
178178
valid = true
179179
}
180+
180181
return &memoryBTreeIterator{
181182
tree: tree.Clone(),
182183
reverse: reverse,
@@ -189,17 +190,20 @@ func (it *memoryBTreeIterator) Rewind() {
189190
if it.tree == nil || it.tree.Len() == 0 {
190191
return
191192
}
193+
192194
if it.reverse {
193195
it.current = it.tree.Max().(*item)
194196
} else {
195197
it.current = it.tree.Min().(*item)
196198
}
199+
it.valid = true
197200
}
198201

199202
func (it *memoryBTreeIterator) Seek(key []byte) {
200203
if it.tree == nil || !it.valid {
201204
return
202205
}
206+
203207
seekItem := &item{key: key}
204208
it.valid = false
205209
if it.reverse {
@@ -221,6 +225,7 @@ func (it *memoryBTreeIterator) Next() {
221225
if it.tree == nil || !it.valid {
222226
return
223227
}
228+
224229
it.valid = false
225230
if it.reverse {
226231
it.tree.DescendLessOrEqual(it.current, func(i btree.Item) bool {
@@ -241,6 +246,7 @@ func (it *memoryBTreeIterator) Next() {
241246
return false
242247
})
243248
}
249+
244250
if !it.valid {
245251
it.current = nil
246252
}

iterator.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ type Item struct {
1414
Value []byte
1515
}
1616

17-
// Iterator represents a database-level iterator that provides methods to traverse over the key/value pairs in the database.
18-
// It wraps the index iterator and adds functionality to retrieve the actual values from the database.
17+
// Iterator represents a database-level iterator that
18+
// provides methods to traverse over the key/value pairs in the database.
19+
// It wraps the index iterator and adds functionality to
20+
// retrieve the actual values from the database.
1921
type Iterator struct {
2022
indexIter index.IndexIterator // index iterator for traversing keys
2123
db *DB // database instance for retrieving values
@@ -76,6 +78,7 @@ func (it *Iterator) Item() *Item {
7678
if it.db == nil || it.indexIter == nil || !it.Valid() {
7779
return nil
7880
}
81+
7982
record := it.skipToNext()
8083
if record == nil {
8184
return nil
@@ -91,6 +94,7 @@ func (it *Iterator) Close() {
9194
if it.db == nil || it.indexIter == nil {
9295
return
9396
}
97+
9498
it.indexIter.Close()
9599
it.indexIter = nil
96100
it.db = nil
@@ -119,13 +123,13 @@ func (it *Iterator) skipToNext() *LogRecord {
119123
}
120124
}
121125

122-
// Check if the key is expired
123126
position := it.indexIter.Value()
124127
if position == nil {
125128
it.indexIter.Next()
126129
continue
127130
}
128131

132+
// read the record from data file
129133
chunk, err := it.db.dataFiles.Read(position)
130134
if err != nil {
131135
it.lastError = err
@@ -140,7 +144,8 @@ func (it *Iterator) skipToNext() *LogRecord {
140144

141145
// Skip if record is deleted or expired
142146
record := decodeLogRecord(chunk)
143-
if record.Type == LogRecordDeleted || record.IsExpired(time.Now().UnixNano()) {
147+
now := time.Now().UnixNano()
148+
if record.Type == LogRecordDeleted || record.IsExpired(now) {
144149
it.indexIter.Next()
145150
continue
146151
}

iterator_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,3 +246,53 @@ func TestIterator_Error(t *testing.T) {
246246
assert.False(t, iter.Valid())
247247
iter.Close()
248248
}
249+
250+
func TestIterator_UseTwice(t *testing.T) {
251+
options := DefaultOptions
252+
db, err := Open(options)
253+
assert.Nil(t, err)
254+
defer destroyDB(db)
255+
256+
db.Put([]byte("aceds"), []byte("value1"))
257+
db.Put([]byte("eedsq"), []byte("value2"))
258+
db.Put([]byte("sedas"), []byte("value3"))
259+
db.Put([]byte("efeds"), []byte("value4"))
260+
db.Put([]byte("bbdes"), []byte("value5"))
261+
262+
iteratorOptions := DefaultIteratorOptions
263+
iter := db.NewIterator(iteratorOptions)
264+
265+
for iter.Seek([]byte("bbe")); iter.Valid(); iter.Next() {
266+
item := iter.Item()
267+
assert.NotNil(t, item)
268+
}
269+
270+
// rewind and iterate again
271+
iter.Rewind()
272+
assert.Equal(t, iter.Valid(), true)
273+
for iter.Seek([]byte("bbe")); iter.Valid(); iter.Next() {
274+
item := iter.Item()
275+
assert.NotNil(t, item)
276+
}
277+
}
278+
279+
func TestIterator_UseAfterClose(t *testing.T) {
280+
options := DefaultOptions
281+
db, err := Open(options)
282+
assert.Nil(t, err)
283+
defer destroyDB(db)
284+
285+
db.Put([]byte("aceds"), []byte("value1"))
286+
db.Put([]byte("eedsq"), []byte("value2"))
287+
288+
iteratorOptions := DefaultIteratorOptions
289+
iter := db.NewIterator(iteratorOptions)
290+
291+
for iter.Seek([]byte("bbe")); iter.Valid(); iter.Next() {
292+
item := iter.Item()
293+
assert.NotNil(t, item)
294+
}
295+
296+
iter.Close()
297+
assert.Equal(t, iter.Valid(), false)
298+
}

0 commit comments

Comments
 (0)