forked from lni/dragonboat
-
Notifications
You must be signed in to change notification settings - Fork 0
/
iterator.go
155 lines (136 loc) · 3.91 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
147
148
149
150
151
152
153
154
155
package gorocksdb
// #include <stdlib.h>
// #include "rocksdb/c.h"
// #include "extended.h"
import "C"
import (
"bytes"
"errors"
"unsafe"
)
// 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 {
cErr *C.char
cLen C.size_t
c *C.rocksdb_iterator_t
}
// NewNativeIterator creates a Iterator object.
func NewNativeIterator(c unsafe.Pointer) *Iterator {
return &Iterator{nil, 0, (*C.rocksdb_iterator_t)(c)}
}
func (iter *Iterator) IsValid() (bool, error) {
v := C.rocksdb_iter_valid_not_err(iter.c)
if v == -1 {
return false, errors.New("error occured when iterating rocksdb")
}
return v == 1, nil
}
// 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{cKey, cLen, 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{cVal, cLen, true}
}
// Key returns the key the iterator currently holds.
func (iter *Iterator) OKey() (Slice, bool) {
cKey := C.rocksdb_iter_key(iter.c, &iter.cLen)
if cKey == nil {
return Slice{}, false
}
return Slice{cKey, iter.cLen, true}, true
}
// Value returns the value in the database the iterator currently holds.
func (iter *Iterator) OValue() (Slice, bool) {
cVal := C.rocksdb_iter_value(iter.c, &iter.cLen)
if cVal == nil {
return Slice{}, false
}
return Slice{cVal, iter.cLen, true}, 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 := byteToChar(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 := byteToChar(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() error {
var cErr *C.char
C.rocksdb_iter_get_error(iter.c, &cErr)
if cErr != nil {
defer C.free(unsafe.Pointer(cErr))
return errors.New(C.GoString(cErr))
}
return nil
}
// Close closes the iterator.
func (iter *Iterator) Close() {
C.rocksdb_iter_destroy(iter.c)
iter.c = nil
}