15
15
package mvcc
16
16
17
17
import (
18
- "sync "
19
-
20
- "github.com/google/btree "
18
+ "bytes "
19
+ "fmt"
20
+ "github.com/VictorLowther/ibtree "
21
21
"go.uber.org/zap"
22
22
)
23
23
@@ -30,102 +30,115 @@ type index interface {
30
30
Tombstone (key []byte , rev Revision ) error
31
31
Compact (rev int64 ) map [Revision ]struct {}
32
32
Keep (rev int64 ) map [Revision ]struct {}
33
-
34
- Insert (ki * keyIndex )
35
- KeyIndex (ki * keyIndex ) * keyIndex
36
33
}
37
34
38
35
type treeIndex struct {
39
- sync. RWMutex
40
- tree * btree. BTreeG [ * keyIndex ]
41
- lg * zap.Logger
36
+ baseRev int64
37
+ revisionTree [] * ibtree. Tree [ keyRev ]
38
+ lg * zap.Logger
42
39
}
43
40
44
- func newTreeIndex (lg * zap.Logger ) * treeIndex {
45
- return & treeIndex {
46
- tree : btree .NewG (32 , func (aki * keyIndex , bki * keyIndex ) bool {
47
- return aki .Less (bki )
48
- }),
49
- lg : lg ,
50
- }
41
+ type keyRev struct {
42
+ key []byte
43
+ mod , created Revision
44
+ version int64
51
45
}
52
46
53
- func (ti * treeIndex ) Put (key []byte , rev Revision ) {
54
- keyi := & keyIndex {key : key }
55
-
56
- ti .Lock ()
57
- defer ti .Unlock ()
58
- okeyi , ok := ti .tree .Get (keyi )
59
- if ! ok {
60
- keyi .put (ti .lg , rev .Main , rev .Sub )
61
- ti .tree .ReplaceOrInsert (keyi )
62
- return
63
- }
64
- okeyi .put (ti .lg , rev .Main , rev .Sub )
47
+ var lessThen ibtree.LessThan [keyRev ] = func (k keyRev , k2 keyRev ) bool {
48
+ return compare (k , k2 ) == - 1
65
49
}
66
50
67
- func (ti * treeIndex ) Get (key []byte , atRev int64 ) (modified , created Revision , ver int64 , err error ) {
68
- ti .RLock ()
69
- defer ti .RUnlock ()
70
- return ti .unsafeGet (key , atRev )
51
+ func compare (k keyRev , k2 keyRev ) int {
52
+ return bytes .Compare (k .key , k2 .key )
71
53
}
72
54
73
- func (ti * treeIndex ) unsafeGet (key []byte , atRev int64 ) (modified , created Revision , ver int64 , err error ) {
74
- keyi := & keyIndex {key : key }
75
- if keyi = ti .keyIndex (keyi ); keyi == nil {
76
- return Revision {}, Revision {}, 0 , ErrRevisionNotFound
55
+ func compareKey (k []byte ) ibtree.CompareAgainst [keyRev ] {
56
+ return func (k2 keyRev ) int {
57
+ return bytes .Compare (k2 .key , k )
77
58
}
78
- return keyi .get (ti .lg , atRev )
79
59
}
80
60
81
- func ( ti * treeIndex ) KeyIndex ( keyi * keyIndex ) * keyIndex {
82
- ti . RLock ()
83
- defer ti . RUnlock ()
84
- return ti . keyIndex ( keyi )
61
+ func lessThanKey ( k [] byte ) ibtree. Test [ keyRev ] {
62
+ return func ( k2 keyRev ) bool {
63
+ return bytes . Compare ( k2 . key , k ) < 0
64
+ }
85
65
}
86
66
87
- func ( ti * treeIndex ) keyIndex ( keyi * keyIndex ) * keyIndex {
88
- if ki , ok := ti . tree . Get ( keyi ); ok {
89
- return ki
67
+ func greaterThanEqualKey ( k [] byte ) ibtree. Test [ keyRev ] {
68
+ return func ( k2 keyRev ) bool {
69
+ return bytes . Compare ( k2 . key , k ) >= 0
90
70
}
91
- return nil
92
71
}
93
72
94
- func (ti * treeIndex ) unsafeVisit (key , end []byte , f func (ki * keyIndex ) bool ) {
95
- keyi , endi := & keyIndex {key : key }, & keyIndex {key : end }
73
+ func newTreeIndex (lg * zap.Logger ) * treeIndex {
74
+ return & treeIndex {
75
+ baseRev : - 1 ,
76
+ lg : lg ,
77
+ }
78
+ }
96
79
97
- ti .tree .AscendGreaterOrEqual (keyi , func (item * keyIndex ) bool {
98
- if len (endi .key ) > 0 && ! item .Less (endi ) {
99
- return false
100
- }
101
- if ! f (item ) {
102
- return false
80
+ func (ti * treeIndex ) Put (key []byte , rev Revision ) {
81
+ if ti .baseRev == - 1 {
82
+ ti .baseRev = rev .Main - 1
83
+ ti .revisionTree = []* ibtree.Tree [keyRev ]{
84
+ ibtree.New [keyRev ](lessThen ),
103
85
}
104
- return true
105
- })
86
+ }
87
+ if rev .Main != ti .rev ()+ 1 {
88
+ panic (fmt .Sprintf ("append only, lastRev: %d, putRev: %d" , ti .rev (), rev .Main ))
89
+ }
90
+ prevTree := ti .revisionTree [len (ti .revisionTree )- 1 ]
91
+ item , found := prevTree .Get (compareKey (key ))
92
+ created := rev
93
+ var version int64 = 1
94
+ if found {
95
+ created = item .created
96
+ version = item .version + 1
97
+ }
98
+ ti .revisionTree = append (ti .revisionTree , prevTree .Insert (keyRev {
99
+ key : key ,
100
+ mod : rev ,
101
+ created : created ,
102
+ version : version ,
103
+ }))
104
+ }
105
+
106
+ func (ti * treeIndex ) rev () int64 {
107
+ return ti .baseRev + int64 (len (ti .revisionTree )) - 1
108
+ }
109
+
110
+ func (ti * treeIndex ) Get (key []byte , atRev int64 ) (modified , created Revision , ver int64 , err error ) {
111
+ idx := atRev - ti .baseRev
112
+ if idx < 0 || idx >= int64 (len (ti .revisionTree )) {
113
+ return Revision {}, Revision {}, 0 , ErrRevisionNotFound
114
+ }
115
+ tree := ti .revisionTree [idx ]
116
+
117
+ keyRev , found := tree .Get (compareKey (key ))
118
+ if ! found {
119
+ return Revision {}, Revision {}, 0 , ErrRevisionNotFound
120
+ }
121
+ return keyRev .mod , keyRev .created , keyRev .version , nil
106
122
}
107
123
108
124
// Revisions returns limited number of revisions from key(included) to end(excluded)
109
125
// at the given rev. The returned slice is sorted in the order of key. There is no limit if limit <= 0.
110
126
// The second return parameter isn't capped by the limit and reflects the total number of revisions.
111
127
func (ti * treeIndex ) Revisions (key , end []byte , atRev int64 , limit int ) (revs []Revision , total int ) {
112
- ti .RLock ()
113
- defer ti .RUnlock ()
114
-
115
128
if end == nil {
116
- rev , _ , _ , err := ti .unsafeGet (key , atRev )
129
+ rev , _ , _ , err := ti .Get (key , atRev )
117
130
if err != nil {
118
131
return nil , 0
119
132
}
120
133
return []Revision {rev }, 1
121
134
}
122
- ti .unsafeVisit (key , end , func (ki * keyIndex ) bool {
123
- if rev , _ , _ , err := ki .get (ti .lg , atRev ); err == nil {
124
- if limit <= 0 || len (revs ) < limit {
125
- revs = append (revs , rev )
126
- }
127
- total ++
135
+ idx := atRev - ti .baseRev
136
+ tree := ti .revisionTree [idx ]
137
+ tree .Range (lessThanKey (key ), greaterThanEqualKey (end ), func (kr keyRev ) bool {
138
+ if limit <= 0 || len (revs ) < limit {
139
+ revs = append (revs , kr .mod )
128
140
}
141
+ total ++
129
142
return true
130
143
})
131
144
return revs , total
@@ -134,119 +147,73 @@ func (ti *treeIndex) Revisions(key, end []byte, atRev int64, limit int) (revs []
134
147
// CountRevisions returns the number of revisions
135
148
// from key(included) to end(excluded) at the given rev.
136
149
func (ti * treeIndex ) CountRevisions (key , end []byte , atRev int64 ) int {
137
- ti .RLock ()
138
- defer ti .RUnlock ()
139
-
140
150
if end == nil {
141
- _ , _ , _ , err := ti .unsafeGet (key , atRev )
151
+ _ , _ , _ , err := ti .Get (key , atRev )
142
152
if err != nil {
143
153
return 0
144
154
}
145
155
return 1
146
156
}
157
+ idx := atRev - ti .baseRev
158
+ tree := ti .revisionTree [idx ]
147
159
total := 0
148
- ti .unsafeVisit (key , end , func (ki * keyIndex ) bool {
149
- if _ , _ , _ , err := ki .get (ti .lg , atRev ); err == nil {
150
- total ++
151
- }
160
+ tree .Range (lessThanKey (key ), greaterThanEqualKey (end ), func (kr keyRev ) bool {
161
+ total ++
152
162
return true
153
163
})
154
164
return total
155
165
}
156
166
157
167
func (ti * treeIndex ) Range (key , end []byte , atRev int64 ) (keys [][]byte , revs []Revision ) {
158
- ti .RLock ()
159
- defer ti .RUnlock ()
160
-
161
168
if end == nil {
162
- rev , _ , _ , err := ti .unsafeGet (key , atRev )
169
+ rev , _ , _ , err := ti .Get (key , atRev )
163
170
if err != nil {
164
171
return nil , nil
165
172
}
166
173
return [][]byte {key }, []Revision {rev }
167
174
}
168
- ti . unsafeVisit ( key , end , func ( ki * keyIndex ) bool {
169
- if rev , _ , _ , err := ki . get ( ti .lg , atRev ); err == nil {
170
- revs = append ( revs , rev )
171
- keys = append (keys , ki . key )
172
- }
175
+ idx := atRev - ti . baseRev
176
+ tree := ti .revisionTree [ idx ]
177
+ tree . Range ( lessThanKey ( key ), greaterThanEqualKey ( end ), func ( kr keyRev ) bool {
178
+ revs = append (revs , kr . mod )
179
+ keys = append ( keys , kr . key )
173
180
return true
174
181
})
175
182
return keys , revs
176
183
}
177
184
178
185
func (ti * treeIndex ) Tombstone (key []byte , rev Revision ) error {
179
- keyi := & keyIndex {key : key }
180
-
181
- ti .Lock ()
182
- defer ti .Unlock ()
183
- ki , ok := ti .tree .Get (keyi )
184
- if ! ok {
186
+ if rev .Main != ti .rev ()+ 1 {
187
+ panic (fmt .Sprintf ("append only, lastRev: %d, putRev: %d" , ti .rev (), rev .Main ))
188
+ }
189
+ prevTree := ti .revisionTree [len (ti .revisionTree )- 1 ]
190
+ newTree , _ , found := prevTree .Delete (keyRev {
191
+ key : key ,
192
+ })
193
+ if ! found {
185
194
return ErrRevisionNotFound
186
195
}
187
-
188
- return ki . tombstone ( ti . lg , rev . Main , rev . Sub )
196
+ ti . revisionTree = append ( ti . revisionTree , newTree )
197
+ return nil
189
198
}
190
199
191
200
func (ti * treeIndex ) Compact (rev int64 ) map [Revision ]struct {} {
192
201
available := make (map [Revision ]struct {})
193
202
ti .lg .Info ("compact tree index" , zap .Int64 ("revision" , rev ))
194
- ti .Lock ()
195
- clone := ti .tree .Clone ()
196
- ti .Unlock ()
197
-
198
- clone .Ascend (func (keyi * keyIndex ) bool {
199
- // Lock is needed here to prevent modification to the keyIndex while
200
- // compaction is going on or revision added to empty before deletion
201
- ti .Lock ()
202
- keyi .compact (ti .lg , rev , available )
203
- if keyi .isEmpty () {
204
- _ , ok := ti .tree .Delete (keyi )
205
- if ! ok {
206
- ti .lg .Panic ("failed to delete during compaction" )
207
- }
208
- }
209
- ti .Unlock ()
210
- return true
211
- })
203
+ idx := rev - ti .baseRev
204
+ ti .revisionTree = ti .revisionTree [idx :]
205
+ ti .baseRev = rev
212
206
return available
213
207
}
214
208
215
209
// Keep finds all revisions to be kept for a Compaction at the given rev.
216
210
func (ti * treeIndex ) Keep (rev int64 ) map [Revision ]struct {} {
217
211
available := make (map [Revision ]struct {})
218
- ti .RLock ()
219
- defer ti .RUnlock ()
220
- ti .tree .Ascend (func (keyi * keyIndex ) bool {
221
- keyi .keep (rev , available )
222
- return true
223
- })
224
- return available
225
- }
226
-
227
- func (ti * treeIndex ) Equal (bi index ) bool {
228
- b := bi .(* treeIndex )
229
-
230
- if ti .tree .Len () != b .tree .Len () {
231
- return false
212
+ idx := rev - ti .baseRev
213
+ tree := ti .revisionTree [idx ]
214
+ for it := tree .All (); it .Next (); {
215
+ keyRev := it .Item ()
216
+ available [keyRev .mod ] = struct {}{}
232
217
}
233
-
234
- equal := true
235
-
236
- ti .tree .Ascend (func (aki * keyIndex ) bool {
237
- bki , _ := b .tree .Get (aki )
238
- if ! aki .equal (bki ) {
239
- equal = false
240
- return false
241
- }
242
- return true
243
- })
244
-
245
- return equal
246
- }
247
-
248
- func (ti * treeIndex ) Insert (ki * keyIndex ) {
249
- ti .Lock ()
250
- defer ti .Unlock ()
251
- ti .tree .ReplaceOrInsert (ki )
218
+ return available
252
219
}
0 commit comments