|
|
|
@ -12,8 +12,62 @@ import (
|
|
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// this package creates coordinators responsible for keeping track of active clients and invoking managers
|
|
|
|
|
type SubCoordinator interface {
|
|
|
|
|
// this package creates the central coordiantor and sub coordiantors for clients
|
|
|
|
|
type CentralCoordinator struct {
|
|
|
|
|
ClientConnections *ClientPacket
|
|
|
|
|
CLisPort int
|
|
|
|
|
*SubCoordinators
|
|
|
|
|
*SystemViewer
|
|
|
|
|
Err chan error
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type SubCoordinators struct {
|
|
|
|
|
Directory map [string]*SubCoordinator
|
|
|
|
|
sync.Mutex
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func NewCentralCoordinator(port int, ch chan error) *CentralCoordinator {
|
|
|
|
|
c := &CentralCoordinator{CLisPort: port, Err: ch}
|
|
|
|
|
c.SystemViewer = NewSystemViewer()
|
|
|
|
|
go c.SystemViewer.Start()
|
|
|
|
|
s := make(map[string]*SubCoordinator)
|
|
|
|
|
sub := &SubCoordinators{Directory:s}
|
|
|
|
|
c.SubCoordinators = sub
|
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *CentralCoordinator) Start() {
|
|
|
|
|
// starts up associated funcs
|
|
|
|
|
clientChan := make(chan *ClientPacket)
|
|
|
|
|
l := NewListener(c.CLisPort,clientChan,c.Err)
|
|
|
|
|
go l.Start()
|
|
|
|
|
go c.ClientListener(clientChan)
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *CentralCoordinator) ClientListener(ch chan *ClientPacket) {
|
|
|
|
|
for client := range ch {
|
|
|
|
|
// basically loops until channel is closed
|
|
|
|
|
port := c.ClientHandler(client.Client)
|
|
|
|
|
client.Port <-port
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *CentralCoordinator) ClientHandler(cl *Client) int {
|
|
|
|
|
c.SubCoordinators.Lock()
|
|
|
|
|
defer c.SubCoordinators.Unlock()
|
|
|
|
|
subcoord, ok := c.SubCoordinators.Directory[cl.Type]
|
|
|
|
|
if !ok {
|
|
|
|
|
// Sub Coordinator does not exists
|
|
|
|
|
logging.Debug(logging.DSpawn,"CC0 01 Created %v Coordinator",cl.Type)
|
|
|
|
|
subcoord = NewSubCoordinator(cl.Type,c.SystemViewer, c.Err)
|
|
|
|
|
c.SubCoordinators.Directory[cl.Type] = subcoord
|
|
|
|
|
}
|
|
|
|
|
go subcoord.ClientHandler(cl)
|
|
|
|
|
return subcoord.Port
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ManagerInterface interface {
|
|
|
|
|
Start()
|
|
|
|
|
NewManager(*Client,*SystemViewer, chan error) GeneralManager
|
|
|
|
|
GetManager(uint32) (GeneralManager, bool)
|
|
|
|
@ -21,56 +75,47 @@ type SubCoordinator interface {
|
|
|
|
|
Register()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type GeneralManager interface {
|
|
|
|
|
// used by sub coordinator to interact with manager
|
|
|
|
|
Start()
|
|
|
|
|
UpdateClient(*Client)
|
|
|
|
|
ReactorStatusHandler(context.Context,*pb.ReactorStatusPing) (*pb.ReactorStatusResponse, error)
|
|
|
|
|
GetDevices(context.Context, *pb.GetDevicesRequest) (*pb.GetDevicesResponse, error)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Coordinator struct {
|
|
|
|
|
type SubCoordinator struct {
|
|
|
|
|
Port int // port that we set up gRPC endpoint on
|
|
|
|
|
//*Managers going to embed this in subcoordinator
|
|
|
|
|
SubCoordinator
|
|
|
|
|
ManagerInterface // embed an interface to create/manager managers
|
|
|
|
|
*SystemViewer
|
|
|
|
|
Err chan error
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Managers struct {
|
|
|
|
|
Directory map[uint32]GeneralManager
|
|
|
|
|
Directory map[uint32]interface{} // support for either manager
|
|
|
|
|
sync.RWMutex // potential perf
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// interface stuff
|
|
|
|
|
func NewCoordinator(clientType string, sys *SystemViewer, err chan error) *Coordinator {
|
|
|
|
|
d := make(map[uint32]GeneralManager)
|
|
|
|
|
m := &Managers{Directory:d}
|
|
|
|
|
c := &Coordinator{Err:err}
|
|
|
|
|
c.Port = 2023
|
|
|
|
|
sub, errs := NewSubCoordinator(clientType, m, err)
|
|
|
|
|
func NewSubCoordinator(clientType string, sys *SystemViewer, err chan error) *SubCoordinator {
|
|
|
|
|
c := &SubCoordinator{Err:err}
|
|
|
|
|
c.SystemViewer = sys
|
|
|
|
|
man, port, errs := NewCoordinatorType(clientType, err)
|
|
|
|
|
if errs != nil {
|
|
|
|
|
err <-errs
|
|
|
|
|
}
|
|
|
|
|
c.SubCoordinator = sub
|
|
|
|
|
c.SystemViewer = sys
|
|
|
|
|
//c.Managers = m
|
|
|
|
|
go c.Register()
|
|
|
|
|
c.Port = port
|
|
|
|
|
c.ManagerInterface = man
|
|
|
|
|
go man.Start()
|
|
|
|
|
go man.Register()
|
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *Coordinator) Start() {
|
|
|
|
|
// on start we need to create channel listener
|
|
|
|
|
// on each new connection we want to check its id against our mapping
|
|
|
|
|
c.SubCoordinator.Start()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *Coordinator) ClientHandler(cl *Client) int {
|
|
|
|
|
func (c *SubCoordinator) ClientHandler(cl *Client) int {
|
|
|
|
|
// (creates and) notifies manager of client connection
|
|
|
|
|
go c.UpdateManager(cl)
|
|
|
|
|
return c.Port
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *Coordinator) UpdateManager(cl *Client) {
|
|
|
|
|
func (c *SubCoordinator) UpdateManager(cl *Client) {
|
|
|
|
|
// shouldn't happen all that often so should be fine to lock
|
|
|
|
|
m, exists := c.GetManager(cl.Id)
|
|
|
|
|
if !exists {
|
|
|
|
@ -93,21 +138,27 @@ func (m *Managers) GetManager(id uint32) (GeneralManager, bool) {
|
|
|
|
|
m.RLock()
|
|
|
|
|
defer m.RUnlock()
|
|
|
|
|
man, exists := m.Directory[id]
|
|
|
|
|
return man, exists
|
|
|
|
|
if !exists {
|
|
|
|
|
return nil, exists
|
|
|
|
|
}
|
|
|
|
|
return man.(GeneralManager), exists
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func NewSubCoordinator(clientType string, m *Managers, err chan error) (SubCoordinator, error) {
|
|
|
|
|
func NewCoordinatorType(clientType string, err chan error) (ManagerInterface, int, error) {
|
|
|
|
|
|
|
|
|
|
m := make(map[uint32]interface{})
|
|
|
|
|
if clientType == "reactor" {
|
|
|
|
|
c := &reactorCoordinator{}
|
|
|
|
|
c.Managers = m
|
|
|
|
|
return c, nil
|
|
|
|
|
//m := make(map[uint32]*ReactorManager)
|
|
|
|
|
c.Managers = &Managers{Directory:m}
|
|
|
|
|
return c, 2023, nil
|
|
|
|
|
} else if clientType == "tui" {
|
|
|
|
|
c := &tuiCoordinator{}
|
|
|
|
|
c.Managers = m
|
|
|
|
|
return c, nil
|
|
|
|
|
//m := make(map[uint32]*TUIManager)
|
|
|
|
|
c.Managers = &Managers{Directory:m}
|
|
|
|
|
return c, 2024, nil
|
|
|
|
|
}
|
|
|
|
|
return &reactorCoordinator{}, errors.New("Unrecognized client type")
|
|
|
|
|
return &reactorCoordinator{}, 0, errors.New("Unrecognized client type")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// creating sub coordinators for associated gRPC handlers
|
|
|
|
@ -142,12 +193,16 @@ func (r *reactorCoordinator) ReactorStatusHandler(ctx context.Context, req *pb.R
|
|
|
|
|
if !exists {
|
|
|
|
|
return &pb.ReactorStatusResponse{}, errors.New("Manager doesn't exists for that client")
|
|
|
|
|
}
|
|
|
|
|
return m.ReactorStatusHandler(ctx, req)
|
|
|
|
|
rm, ok := m.(*ReactorManager)
|
|
|
|
|
if !ok {
|
|
|
|
|
return &pb.ReactorStatusResponse{}, errors.New("Manager is not a reactor manager!")
|
|
|
|
|
}
|
|
|
|
|
return rm.ReactorStatusHandler(ctx, req)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//tui coordinator
|
|
|
|
|
type tuiCoordinator struct {
|
|
|
|
|
*Managers
|
|
|
|
|
*Managers // by embedding general struct we allow coordinator to still call general funcs
|
|
|
|
|
pb.UnimplementedManagementServer
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -178,7 +233,11 @@ func (t *tuiCoordinator) GetDevices(ctx context.Context, req *pb.GetDevicesReque
|
|
|
|
|
// doesnt exist for some reason
|
|
|
|
|
return &pb.GetDevicesResponse{}, errors.New("Manager doesn't exists for client")
|
|
|
|
|
}
|
|
|
|
|
return m.GetDevices(ctx,req)
|
|
|
|
|
tm, ok := m.(*TUIManager)
|
|
|
|
|
if !ok {
|
|
|
|
|
return &pb.GetDevicesResponse{}, errors.New("Manager is not of type TUI")
|
|
|
|
|
}
|
|
|
|
|
return tm.GetDevices(ctx,req)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// unimplemented bs for grpc
|
|
|
|
|