@@ -2,20 +2,19 @@ package distribution
22
33import (
44 "bytes"
5+ "sort"
56 "sync"
67 "sync/atomic"
78)
89
9- // Route represents mapping from key range to raft group.
10- // The key range is half-open: [Start, End)
11- // meaning Start is inclusive and End is exclusive. If End is nil or empty
12- // the range is unbounded and covers all keys >= Start.
10+ // Route represents a mapping from a starting key to a raft group.
11+ // Ranges are right half-open infinite intervals : [Start, next Start).
12+ // Start is inclusive and the range extends up to (but excluding) the next
13+ // route's start. The last route is unbounded and covers all keys >= Start.
1314type Route struct {
1415 // Start marks the inclusive beginning of the range.
1516 Start []byte
16- // End marks the exclusive end of the range. When empty, the range has
17- // no upper bound.
18- End []byte
17+ // GroupID identifies the raft group for the range starting at Start.
1918 GroupID uint64
2019}
2120
@@ -31,27 +30,34 @@ func NewEngine() *Engine {
3130 return & Engine {routes : make ([]Route , 0 )}
3231}
3332
34- // UpdateRoute registers or updates a route. The range is [start, end). If end
35- // is nil or empty the range is treated as unbounded above .
36- func (e * Engine ) UpdateRoute (start , end []byte , group uint64 ) {
33+ // UpdateRoute registers or updates a route starting at the given key.
34+ // Routes are stored sorted by Start .
35+ func (e * Engine ) UpdateRoute (start []byte , group uint64 ) {
3736 e .mu .Lock ()
3837 defer e .mu .Unlock ()
39- e .routes = append (e .routes , Route {Start : start , End : end , GroupID : group })
38+ e .routes = append (e .routes , Route {Start : start , GroupID : group })
39+ sort .Slice (e .routes , func (i , j int ) bool {
40+ return bytes .Compare (e .routes [i ].Start , e .routes [j ].Start ) < 0
41+ })
4042}
4143
42- // GetRoute finds a route for the given key. The search uses half-open ranges
43- // [Start, End). If End is empty the range is treated as unbounded above .
44+ // GetRoute finds a route for the given key using right half-open infinite
45+ // intervals .
4446func (e * Engine ) GetRoute (key []byte ) (Route , bool ) {
4547 e .mu .RLock ()
4648 defer e .mu .RUnlock ()
47- for _ , r := range e .routes {
48- if bytes .Compare (key , r .Start ) >= 0 {
49- if len (r .End ) == 0 || bytes .Compare (key , r .End ) < 0 {
50- return r , true
51- }
52- }
53- }
54- return Route {}, false
49+ if len (e .routes ) == 0 {
50+ return Route {}, false
51+ }
52+
53+ // Find the first route with Start > key.
54+ i := sort .Search (len (e .routes ), func (i int ) bool {
55+ return bytes .Compare (e .routes [i ].Start , key ) > 0
56+ })
57+ if i == 0 {
58+ return Route {}, false
59+ }
60+ return e .routes [i - 1 ], true
5561}
5662
5763// NextTimestamp returns a monotonic increasing timestamp.
0 commit comments