-
Notifications
You must be signed in to change notification settings - Fork 68
/
iterator.go
146 lines (127 loc) · 4 KB
/
iterator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package grocksdb
// #include <stdlib.h>
// #include "rocksdb/c.h"
import "C"
import (
"bytes"
)
// Iterator provides a way to seek to specific keys and iterate through
// the keyspace from that point, as well as access the values of those keys.
//
// For example:
//
// it := db.NewIterator(readOpts)
// defer it.Close()
//
// it.Seek([]byte("foo"))
// for ; it.Valid(); it.Next() {
// fmt.Printf("Key: %v Value: %v\n", it.Key().Data(), it.Value().Data())
// }
//
// if err := it.Err(); err != nil {
// return err
// }
type Iterator struct {
c *C.rocksdb_iterator_t
}
// NewNativeIterator creates a Iterator object.
func newNativeIterator(c *C.rocksdb_iterator_t) *Iterator {
return &Iterator{c: c}
}
// Valid returns false only when an Iterator has iterated past either the
// first or the last key in the database.
func (iter *Iterator) Valid() bool {
return C.rocksdb_iter_valid(iter.c) != 0
}
// ValidForPrefix returns false only when an Iterator has iterated past the
// first or the last key in the database or the specified prefix.
func (iter *Iterator) ValidForPrefix(prefix []byte) bool {
if C.rocksdb_iter_valid(iter.c) == 0 {
return false
}
key := iter.Key()
result := bytes.HasPrefix(key.Data(), prefix)
key.Free()
return result
}
// Key returns the key the iterator currently holds.
func (iter *Iterator) Key() *Slice {
var cLen C.size_t
cKey := C.rocksdb_iter_key(iter.c, &cLen)
if cKey == nil {
return nil
}
return &Slice{data: cKey, size: cLen, freed: true}
}
// Timestamp returns the timestamp in the database the iterator currently holds.
func (iter *Iterator) Timestamp() *Slice {
var cLen C.size_t
cTs := C.rocksdb_iter_timestamp(iter.c, &cLen)
if cTs == nil {
return nil
}
return &Slice{data: cTs, size: cLen, freed: true}
}
// Value returns the value in the database the iterator currently holds.
func (iter *Iterator) Value() *Slice {
var cLen C.size_t
cVal := C.rocksdb_iter_value(iter.c, &cLen)
if cVal == nil {
return nil
}
return &Slice{data: cVal, size: cLen, freed: true}
}
// Next moves the iterator to the next sequential key in the database.
func (iter *Iterator) Next() {
C.rocksdb_iter_next(iter.c)
}
// Prev moves the iterator to the previous sequential key in the database.
func (iter *Iterator) Prev() {
C.rocksdb_iter_prev(iter.c)
}
// SeekToFirst moves the iterator to the first key in the database.
func (iter *Iterator) SeekToFirst() {
C.rocksdb_iter_seek_to_first(iter.c)
}
// SeekToLast moves the iterator to the last key in the database.
func (iter *Iterator) SeekToLast() {
C.rocksdb_iter_seek_to_last(iter.c)
}
// Seek moves the iterator to the position greater than or equal to the key.
func (iter *Iterator) Seek(key []byte) {
cKey := refGoBytes(key)
C.rocksdb_iter_seek(iter.c, cKey, C.size_t(len(key)))
}
// SeekForPrev moves the iterator to the last key that less than or equal
// to the target key, in contrast with Seek.
func (iter *Iterator) SeekForPrev(key []byte) {
cKey := refGoBytes(key)
C.rocksdb_iter_seek_for_prev(iter.c, cKey, C.size_t(len(key)))
}
// Err returns nil if no errors happened during iteration, or the actual
// error otherwise.
func (iter *Iterator) Err() (err error) {
var cErr *C.char
C.rocksdb_iter_get_error(iter.c, &cErr)
err = fromCError(cErr)
return
}
// Refresh if supported, the DB state that the iterator reads from is updated to
// the latest state. The iterator will be invalidated after the call.
// Regardless of whether the iterator was created/refreshed previously
// with or without a snapshot, the iterator will be reading the
// latest DB state after this call.
// Note that you will need to call a Seek*() function to get the iterator
// back into a valid state before calling a function that assumes the
// state is already valid, like Next().
func (iter *Iterator) Refresh() (err error) {
var cErr *C.char
C.rocksdb_iter_refresh(iter.c, &cErr)
err = fromCError(cErr)
return
}
// Close closes the iterator.
func (iter *Iterator) Close() {
C.rocksdb_iter_destroy(iter.c)
iter.c = nil
}