@@ -37,6 +37,33 @@ import (
3737 "github.com/Workiva/go-datastructures/slice/skip"
3838)
3939
40+ // keyed is required as in the rangetree code we often want to compare
41+ // two different types of bundles and this allows us to do so without
42+ // checking for each one.
43+ type keyed interface {
44+ key () uint64
45+ }
46+
47+ type skipEntry uint64
48+
49+ // Compare is required by the skip.Entry interface.
50+ func (se skipEntry ) Compare (other skip.Entry ) int {
51+ otherSe := other .(skipEntry )
52+ if se == otherSe {
53+ return 0
54+ }
55+
56+ if se > otherSe {
57+ return 1
58+ }
59+
60+ return - 1
61+ }
62+
63+ func (se skipEntry ) key () uint64 {
64+ return uint64 (se )
65+ }
66+
4067// isLastDimension simply returns dimension == lastDimension-1.
4168// This panics if dimension >= lastDimension.
4269func isLastDimension (dimension , lastDimension uint64 ) bool {
@@ -63,25 +90,55 @@ func needsDeletion(value, index, number int64) bool {
6390// dimensionalBundle is an intermediate holder up to the last
6491// dimension and represents a wrapper around a skiplist.
6592type dimensionalBundle struct {
66- key uint64
67- sl * skip.SkipList
93+ id uint64
94+ sl * skip.SkipList
6895}
6996
70- // Key returns the key for this bundle. Fulfills skip.Entry interface.
71- func (db * dimensionalBundle ) Key () uint64 {
72- return db .key
97+ // Compare returns a value indicating the relative relationship and the
98+ // provided bundle.
99+ func (db * dimensionalBundle ) Compare (e skip.Entry ) int {
100+ keyed := e .(keyed )
101+ if db .id == keyed .key () {
102+ return 0
103+ }
104+
105+ if db .id > keyed .key () {
106+ return 1
107+ }
108+
109+ return - 1
110+ }
111+
112+ // key returns the key for this bundle.
113+ func (db * dimensionalBundle ) key () uint64 {
114+ return db .id
73115}
74116
75117// lastBundle represents a bundle living at the last dimension
76118// of the tree.
77119type lastBundle struct {
78- key uint64
120+ id uint64
79121 entry rangetree.Entry
80122}
81123
82- // Key returns the key for this bundle. Fulfills skip.Entry interface.
83- func (lb * lastBundle ) Key () uint64 {
84- return lb .key
124+ // Compare returns a value indicating the relative relationship and the
125+ // provided bundle.
126+ func (lb * lastBundle ) Compare (e skip.Entry ) int {
127+ keyed := e .(keyed )
128+ if lb .id == keyed .key () {
129+ return 0
130+ }
131+
132+ if lb .id > keyed .key () {
133+ return 1
134+ }
135+
136+ return - 1
137+ }
138+
139+ // Key returns the key for this bundle.
140+ func (lb * lastBundle ) key () uint64 {
141+ return lb .id
85142}
86143
87144type skipListRT struct {
@@ -105,7 +162,7 @@ func (rt *skipListRT) add(entry rangetree.Entry) rangetree.Entry {
105162
106163 for i := uint64 (0 ); i < rt .dimensions ; i ++ {
107164 value = entry .ValueAtDimension (i )
108- e = sl .Get (uint64 (value ))[0 ]
165+ e = sl .Get (skipEntry (value ))[0 ]
109166 if isLastDimension (i , rt .dimensions ) {
110167 if e != nil { // this is an overwrite
111168 lb = e .(* lastBundle )
@@ -115,14 +172,14 @@ func (rt *skipListRT) add(entry rangetree.Entry) rangetree.Entry {
115172 }
116173
117174 // need to add new sl entry
118- lb = & lastBundle {key : uint64 (value ), entry : entry }
175+ lb = & lastBundle {id : uint64 (value ), entry : entry }
119176 rt .number ++
120177 sl .Insert (lb )
121178 return nil
122179 }
123180
124181 if e == nil { // we need the intermediate dimension
125- db = & dimensionalBundle {key : uint64 (value ), sl : skip .New (uint64 (0 ))}
182+ db = & dimensionalBundle {id : uint64 (value ), sl : skip .New (uint64 (0 ))}
126183 sl .Insert (db )
127184 } else {
128185 db = e .(* dimensionalBundle )
@@ -155,7 +212,7 @@ func (rt *skipListRT) get(entry rangetree.Entry) rangetree.Entry {
155212 )
156213 for i := uint64 (0 ); i < rt .dimensions ; i ++ {
157214 value = uint64 (entry .ValueAtDimension (i ))
158- e = sl .Get (value )[0 ]
215+ e = sl .Get (skipEntry ( value ) )[0 ]
159216 if e == nil {
160217 return nil
161218 }
@@ -195,7 +252,7 @@ func (rt *skipListRT) deleteRecursive(sl *skip.SkipList, dimension uint64,
195252
196253 value := entry .ValueAtDimension (dimension )
197254 if isLastDimension (dimension , rt .dimensions ) {
198- entries := sl .Delete (uint64 (value ))
255+ entries := sl .Delete (skipEntry (value ))
199256 if entries [0 ] == nil {
200257 return nil
201258 }
@@ -204,7 +261,7 @@ func (rt *skipListRT) deleteRecursive(sl *skip.SkipList, dimension uint64,
204261 return entries [0 ].(* lastBundle ).entry
205262 }
206263
207- db , ok := sl .Get (uint64 (value ))[0 ].(* dimensionalBundle )
264+ db , ok := sl .Get (skipEntry (value ))[0 ].(* dimensionalBundle )
208265 if ! ok { // value was not found
209266 return nil
210267 }
@@ -215,7 +272,7 @@ func (rt *skipListRT) deleteRecursive(sl *skip.SkipList, dimension uint64,
215272 }
216273
217274 if db .sl .Len () == 0 {
218- sl .Delete (db . key )
275+ sl .Delete (db )
219276 }
220277
221278 return result
@@ -239,9 +296,9 @@ func (rt *skipListRT) apply(sl *skip.SkipList, dimension uint64,
239296
240297 var e skip.Entry
241298
242- for iter := sl .Iter (uint64 (lowValue )); iter .Next (); {
299+ for iter := sl .Iter (skipEntry (lowValue )); iter .Next (); {
243300 e = iter .Value ()
244- if int64 (e .Key ()) >= highValue {
301+ if int64 (e .( keyed ). key ()) >= highValue {
245302 break
246303 }
247304
@@ -282,7 +339,7 @@ func (rt *skipListRT) Query(interval rangetree.Interval) rangetree.Entries {
282339
283340func (rt * skipListRT ) flatten (sl * skip.SkipList , dimension uint64 , entries * rangetree.Entries ) {
284341 lastDimension := isLastDimension (dimension , rt .dimensions )
285- for iter := sl .Iter (0 ); iter .Next (); {
342+ for iter := sl .Iter (skipEntry ( 0 ) ); iter .Next (); {
286343 if lastDimension {
287344 * entries = append (* entries , iter .Value ().(* lastBundle ).entry )
288345 } else {
@@ -299,9 +356,9 @@ func (rt *skipListRT) insert(sl *skip.SkipList, dimension, insertDimension uint6
299356 affectedDimension := dimension == insertDimension
300357 var iter skip.Iterator
301358 if dimension == insertDimension {
302- iter = sl .Iter (uint64 (index ))
359+ iter = sl .Iter (skipEntry (index ))
303360 } else {
304- iter = sl .Iter (0 )
361+ iter = sl .Iter (skipEntry ( 0 ) )
305362 }
306363
307364 var toDelete skip.Entries
@@ -317,32 +374,30 @@ func (rt *skipListRT) insert(sl *skip.SkipList, dimension, insertDimension uint6
317374 )
318375 continue
319376 }
320- if needsDeletion (int64 (e .Key ()), index , number ) {
377+ if needsDeletion (int64 (e .( keyed ). key ()), index , number ) {
321378 toDelete = append (toDelete , e )
322379 continue
323380 }
324381
325382 if lastDimension {
326- e .(* lastBundle ).key += uint64 (number )
383+ e .(* lastBundle ).id += uint64 (number )
327384 * affected = append (* affected , e .(* lastBundle ).entry )
328385 } else {
329- e .(* dimensionalBundle ).key += uint64 (number )
386+ e .(* dimensionalBundle ).id += uint64 (number )
330387 rt .flatten (e .(* dimensionalBundle ).sl , dimension + 1 , affected )
331388 }
332389 }
333390
334391 if len (toDelete ) > 0 {
335- keys := make ([]uint64 , 0 , len (toDelete ))
336392 for _ , e := range toDelete {
337393 if lastDimension {
338394 * deleted = append (* deleted , e .(* lastBundle ).entry )
339395 } else {
340396 rt .flatten (e .(* dimensionalBundle ).sl , dimension + 1 , deleted )
341397 }
342- keys = append (keys , e .Key ())
343398 }
344399
345- sl .Delete (keys ... )
400+ sl .Delete (toDelete ... )
346401 }
347402}
348403
0 commit comments