forked from cosmos/gorocksdb
-
Notifications
You must be signed in to change notification settings - Fork 1
/
iterator.go
126 lines (110 loc) · 3.18 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
package gorocksdb
// #include <stdlib.h>
// #include "rocksdb/c.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 {
c *C.rocksdb_iterator_t
}
// NewNativeIterator creates a Iterator object.
func NewNativeIterator(c unsafe.Pointer) *Iterator {
return &Iterator{(*C.rocksdb_iterator_t)(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{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}
}
// 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.rocksdb_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
}