-
Notifications
You must be signed in to change notification settings - Fork 44
/
client_manager.go
114 lines (90 loc) · 2.31 KB
/
client_manager.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
package routingtable
import (
"sync"
)
type ClientManagerMaster interface {
UpdateNewClient(RouteTableClient) error
}
// ClientOptions represents options for a client
type ClientOptions struct {
BestOnly bool
EcmpOnly bool
MaxPaths uint
}
// GetMaxPaths calculates the maximum amount of wanted paths given that ecmpPaths paths exist
func (c *ClientOptions) GetMaxPaths(ecmpPaths uint) uint {
if c.BestOnly {
return 1
}
if c.EcmpOnly {
return ecmpPaths
}
return c.MaxPaths
}
// ClientManager manages clients of routing tables (observer pattern)
type ClientManager struct {
clients map[RouteTableClient]ClientOptions
master ClientManagerMaster
mu sync.RWMutex
endOfLife bool // do not accept new clients when EOL
}
// NewClientManager creates and initializes a new client manager
func NewClientManager(master ClientManagerMaster) *ClientManager {
return &ClientManager{
clients: make(map[RouteTableClient]ClientOptions, 0),
master: master,
}
}
// ClientCount gets the number of registred clients
func (c *ClientManager) ClientCount() uint64 {
c.mu.RLock()
defer c.mu.RUnlock()
return uint64(len(c.clients))
}
// GetOptions gets the options for a registered client
func (c *ClientManager) GetOptions(client RouteTableClient) ClientOptions {
c.mu.RLock()
defer c.mu.RUnlock()
return c.clients[client]
}
// RegisterWithOptions registers a client with options for updates
func (c *ClientManager) RegisterWithOptions(client RouteTableClient, opt ClientOptions) {
c.mu.Lock()
if c.endOfLife {
return
}
c.clients[client] = opt
c.mu.Unlock()
c.master.UpdateNewClient(client)
}
// Unregister unregisters a client
func (c *ClientManager) Unregister(client RouteTableClient) bool {
c.mu.Lock()
defer c.mu.Unlock()
return c._unregister(client)
}
func (c *ClientManager) _unregister(client RouteTableClient) bool {
if _, ok := c.clients[client]; !ok {
return false
}
delete(c.clients, client)
return true
}
// Clients returns a list of registered clients
func (c *ClientManager) Clients() []RouteTableClient {
c.mu.RLock()
defer c.mu.RUnlock()
ret := make([]RouteTableClient, 0)
for rtc := range c.clients {
ret = append(ret, rtc)
}
return ret
}
func (c *ClientManager) Dispose() {
c.mu.Lock()
defer c.mu.Unlock()
c.endOfLife = true
for cli := range c.clients {
c._unregister(cli)
}
}