-
Notifications
You must be signed in to change notification settings - Fork 3
/
latency_map.go
123 lines (97 loc) · 2.32 KB
/
latency_map.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
package overlay
import (
"github.com/danalex97/Speer/underlay"
"math/rand"
"strconv"
"sync"
)
// A bootstraping mechanism which provides a contact node for a newly arrived
// node. It is also used to expose new ids for nodes via the function NewId.
type Bootstrap interface {
Join(id string) string
NewId() string
}
// The LatencyMap provides a bootstraping mechanism along with an ID allocation
// mechanism and ID - router translation functions.
type LatencyMap interface {
Bootstrap
Router(id string) underlay.Router // ID -> underlay.Router
Id(router underlay.Router) string // underlay.Router -> ID
}
// The NetworkMap is the implementation of the LatencyMap. It uses two maps for
// translating between ids and rounters(and viceversa). Since it can be
// accessed by multiple threads at the same time, the access is protected via a
// read-write mutex.
type NetworkMap struct {
*sync.RWMutex
network *underlay.Network
id map[string]underlay.Router
inv map[underlay.Router]string
idCtr map[string]int
}
func NewNetworkMap(network *underlay.Network) LatencyMap {
return &NetworkMap{
RWMutex: new(sync.RWMutex),
network: network,
id: make(map[string]underlay.Router),
inv: make(map[underlay.Router]string),
idCtr: make(map[string]int),
}
}
func newId(mp *NetworkMap, domain string) (id string) {
if _, ok := mp.idCtr[domain]; !ok {
mp.idCtr[domain] = 0
}
id = strconv.Itoa(mp.idCtr[domain])
if domain != "" {
id = domain + "." + id
}
mp.idCtr[domain]++
return
}
func (mp *NetworkMap) NewId() string {
mp.Lock()
defer mp.Unlock()
for {
router := mp.network.RandomRouter()
if _, ok := mp.inv[router]; !ok {
routerId := newId(mp, router.Domain())
mp.id[routerId] = router
mp.inv[router] = routerId
return routerId
}
}
}
func (mp *NetworkMap) Join(id string) string {
i := rand.Intn(len(mp.id))
for k := range mp.id {
if i == 0 {
if k == id && len(mp.id) > 1 {
return mp.Join(id)
}
if k != id {
return k
}
}
i--
}
return ""
}
func (mp *NetworkMap) Router(id string) underlay.Router {
mp.RLock()
defer mp.RUnlock()
if router, ok := mp.id[id]; ok {
return router
} else {
return nil
}
}
func (mp *NetworkMap) Id(router underlay.Router) string {
mp.RLock()
defer mp.RUnlock()
if id, ok := mp.inv[router]; ok {
return id
} else {
return ""
}
}