-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathmultisegment.go
110 lines (92 loc) · 2.39 KB
/
multisegment.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
package keydb
// multiSegment presents multiple segments as a single segment. The segments are ordered, since the different segments
// may contain the same key with different values (due to an update or a remove)
type multiSegment struct {
segments []segment
}
type multiSegmentIterator struct {
iterators []LookupIterator
}
func (msi *multiSegmentIterator) peekKey() ([]byte, error) {
panic("peekKey called on multiSegmentIterator")
}
func (msi *multiSegmentIterator) Next() (key []byte, value []byte, err error) {
var currentIndex = -1
var lowest []byte
// find the lowest next non-deleted key in any of the iterators
for i := len(msi.iterators) - 1; i >= 0; i-- {
iterator := msi.iterators[i]
var key []byte
var err error
for {
key, err = iterator.peekKey()
if err == nil && key == nil {
iterator.Next()
} else {
break
}
}
if err != nil {
continue
}
if lowest == nil || less(key, lowest) {
lowest = make([]byte, len(key))
copy(lowest, key)
currentIndex = i
}
}
if currentIndex == -1 {
return nil, nil, EndOfIterator
}
key, value, err = msi.iterators[currentIndex].Next()
// advance all of the iterators past the current
for i := len(msi.iterators) - 1; i >= 0; i-- {
if i == currentIndex {
continue
}
iterator := msi.iterators[i]
for {
key, err := iterator.peekKey()
if err != nil {
break
}
if key == nil || !less(lowest, key) {
msi.Next()
} else {
break
}
}
}
return
}
func newMultiSegment(segments []segment) *multiSegment {
return &multiSegment{segments: segments}
}
func (ms *multiSegment) Put(key []byte, value []byte) error {
panic("Put called on multiSegmentIterator")
}
func (ms *multiSegment) Get(key []byte) ([]byte, error) {
// segments are in chronological order, so search in reverse
for i := len(ms.segments) - 1; i >= 0; i-- {
s := ms.segments[i]
val, err := s.Get(key)
if err == nil {
return val, nil
}
}
return nil, KeyNotFound
}
func (ms *multiSegment) Remove(key []byte) ([]byte, error) {
panic("Remove called on multiSegmentIterator")
}
func (ms *multiSegment) Lookup(lower []byte, upper []byte) (LookupIterator, error) {
iterators := make([]LookupIterator, 0)
for _, v := range ms.segments {
iterator, err := v.Lookup(lower, upper)
if err != nil {
return nil, err
}
iterators = append(iterators, iterator)
}
return &multiSegmentIterator{iterators: iterators}, nil
}