package routingtable import ( "sync" ) // 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 RouteTableClient mu sync.RWMutex } // NewClientManager creates and initializes a new client manager func NewClientManager(master RouteTableClient) ClientManager { return ClientManager{ clients: make(map[RouteTableClient]ClientOptions, 0), master: master, } } // GetOptions gets the options for a registred client func (c *ClientManager) GetOptions(client RouteTableClient) ClientOptions { c.mu.RLock() defer c.mu.RUnlock() return c.clients[client] } // Register registers a client for updates func (c *ClientManager) Register(client RouteTableClient) { c.RegisterWithOptions(client, ClientOptions{BestOnly: true}) } // RegisterWithOptions registers a client with options for updates func (c *ClientManager) RegisterWithOptions(client RouteTableClient, opt ClientOptions) { c.mu.Lock() defer c.mu.Unlock() c.clients[client] = opt c.master.UpdateNewClient(client) } // Unregister unregisters a client func (c *ClientManager) Unregister(client RouteTableClient) { c.mu.Lock() defer c.mu.Unlock() if _, ok := c.clients[client]; !ok { return } delete(c.clients, client) } // 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 }