forked from cosmos/iavl
-
Notifications
You must be signed in to change notification settings - Fork 1
/
fast_iterator.go
135 lines (108 loc) · 2.73 KB
/
fast_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
package iavl
import (
"errors"
dbm "github.com/cometbft/cometbft-db"
"github.com/cosmos/iavl/fastnode"
)
var errFastIteratorNilNdbGiven = errors.New("fast iterator must be created with a nodedb but it was nil")
// FastIterator is a dbm.Iterator for ImmutableTree
// it iterates over the latest state via fast nodes,
// taking advantage of keys being located in sequence in the underlying database.
type FastIterator struct {
start, end []byte
valid bool
ascending bool
err error
ndb *nodeDB
nextFastNode *fastnode.Node
fastIterator dbm.Iterator
}
var _ dbm.Iterator = (*FastIterator)(nil)
func NewFastIterator(start, end []byte, ascending bool, ndb *nodeDB) *FastIterator {
iter := &FastIterator{
start: start,
end: end,
err: nil,
ascending: ascending,
ndb: ndb,
nextFastNode: nil,
fastIterator: nil,
}
// Move iterator before the first element
iter.Next()
return iter
}
// Domain implements dbm.Iterator.
// Maps the underlying nodedb iterator domain, to the 'logical' keys involved.
func (iter *FastIterator) Domain() ([]byte, []byte) {
if iter.fastIterator == nil {
return iter.start, iter.end
}
start, end := iter.fastIterator.Domain()
if start != nil {
start = start[1:]
if len(start) == 0 {
start = nil
}
}
if end != nil {
end = end[1:]
if len(end) == 0 {
end = nil
}
}
return start, end
}
// Valid implements dbm.Iterator.
func (iter *FastIterator) Valid() bool {
return iter.fastIterator != nil && iter.fastIterator.Valid() && iter.valid
}
// Key implements dbm.Iterator
func (iter *FastIterator) Key() []byte {
if iter.valid {
return iter.nextFastNode.GetKey()
}
return nil
}
// Value implements dbm.Iterator
func (iter *FastIterator) Value() []byte {
if iter.valid {
return iter.nextFastNode.GetValue()
}
return nil
}
// Next implements dbm.Iterator
func (iter *FastIterator) Next() {
if iter.ndb == nil {
iter.err = errFastIteratorNilNdbGiven
iter.valid = false
return
}
if iter.fastIterator == nil {
iter.fastIterator, iter.err = iter.ndb.getFastIterator(iter.start, iter.end, iter.ascending)
iter.valid = true
} else {
iter.fastIterator.Next()
}
if iter.err == nil {
iter.err = iter.fastIterator.Error()
}
iter.valid = iter.valid && iter.fastIterator.Valid()
if iter.valid {
iter.nextFastNode, iter.err = fastnode.DeserializeNode(iter.fastIterator.Key()[1:], iter.fastIterator.Value())
iter.valid = iter.err == nil
}
}
// Close implements dbm.Iterator
func (iter *FastIterator) Close() error {
if iter.fastIterator != nil {
iter.err = iter.fastIterator.Close()
}
iter.valid = false
iter.fastIterator = nil
return iter.err
}
// Error implements dbm.Iterator
func (iter *FastIterator) Error() error {
return iter.err
}