-
Notifications
You must be signed in to change notification settings - Fork 0
/
multisegment.go
137 lines (118 loc) · 3.13 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
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
package leveldb
// 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) {
iterator.Next()
} else {
break
}
}
}
return
}
func (ms *multiSegment) size() uint64 {
var size uint64 = 0
for _, s := range ms.segments {
size += s.size()
}
return size
}
// Creates a new multiSegment. The passed segments should no longer be referenced.
func newMultiSegment(segments []segment) *multiSegment {
return &multiSegment{segments: segments}
}
func (ms *multiSegment) LowerID() uint64 {
panic("MultiSegment does not have an LowerID")
}
func (ms *multiSegment) UpperID() uint64 {
panic("MultiSegment does not have an UpperID")
}
func (ms *multiSegment) Put(key []byte, value []byte) ([]byte, error) {
panic("Put called on multiSegment")
}
func (ms *multiSegment) Close() error {
panic("Close called on multiSegment")
}
func (ms *multiSegment) removeSegment() error {
panic("removeSegment called on multiSegment")
}
func (ms *multiSegment) removeOnFinalize() {
panic("removeOnFinalize called on multiSegment")
}
func (ms *multiSegment) files() []string {
return []string{}
}
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
}