removed garbage directory
parent
31c1a702a7
commit
e045f3046e
@ -1,70 +0,0 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"log"
|
||||
)
|
||||
|
||||
// this package creates coordinators responsible for keeping track of active clients and invoking managers
|
||||
|
||||
type Coordinator struct {
|
||||
Type string // ["reactor","tui"]
|
||||
IncomingClients <-chan *Client
|
||||
*Managers
|
||||
Err chan error
|
||||
}
|
||||
|
||||
type Managers struct {
|
||||
Directory map[uint32](chan<- bool)
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
func NewCoordinator(t string,ch chan *Client, err chan error) *Coordinator {
|
||||
d := make(map[uint32](chan<- bool))
|
||||
m := &Managers{Directory:d}
|
||||
c := &Coordinator{Type: t,IncomingClients: ch,Err:err}
|
||||
c.Managers = m
|
||||
return c
|
||||
}
|
||||
|
||||
func FindNewManager(c *Client,ch chan bool, err chan error) {
|
||||
switch c.Type {
|
||||
case "reactor":
|
||||
NewReactorManager(c,ch,err)
|
||||
case "tui":
|
||||
NewTUIManager(c,ch,err)
|
||||
default:
|
||||
log.Fatal(fmt.Sprintf("ERROR %v NOT FOUND",c.Type))
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
go c.Listen()
|
||||
}
|
||||
|
||||
func (c *Coordinator) Listen() {
|
||||
for {
|
||||
cl := <-c.IncomingClients
|
||||
go c.ClientHandler(cl)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Coordinator) ClientHandler(cl *Client) {
|
||||
// (creates and) notifies manager of client connection
|
||||
c.Managers.Lock()
|
||||
defer c.Managers.Unlock()
|
||||
if m, exists := c.Managers.Directory[cl.Id]; exists {
|
||||
// manager in memory
|
||||
m <-true
|
||||
} else {
|
||||
// create channel and manager
|
||||
ch := make(chan bool)
|
||||
FindNewManager(cl, ch,c.Err)
|
||||
c.Managers.Directory[cl.Id] = ch
|
||||
// will block until manager is ready
|
||||
ch <-true
|
||||
}
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"log"
|
||||
"sync"
|
||||
"context"
|
||||
"FRMS/internal/pkg/system"
|
||||
"google.golang.org/grpc"
|
||||
pb "FRMS/internal/pkg/grpc"
|
||||
)
|
||||
|
||||
// the goal here is to set up a gRPC server to respond to client pings with their IP and to establish a new manager for that specific client
|
||||
|
||||
// going to rename shit to be more general
|
||||
type Listener struct { // exporting for easy use in the short term
|
||||
// Reactor map[uint32]*ReactorManager this will go in eventual "coordinator" struct
|
||||
Ip string
|
||||
Port int
|
||||
*Coordinators
|
||||
Err chan error
|
||||
pb.UnimplementedHandshakeServer
|
||||
}
|
||||
|
||||
type Coordinators struct {
|
||||
Channel map[string](chan<- *Client)
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
Ip string
|
||||
Port int
|
||||
Id uint32
|
||||
Model string
|
||||
Type string
|
||||
}
|
||||
|
||||
func NewClient(ip, model, t string, port int, id uint32) *Client {
|
||||
return &Client{Ip:ip,Port:port,Id:id,Model:model,Type:t}
|
||||
}
|
||||
|
||||
func GetIp(e string) (string, error) {
|
||||
return system.GetIp(e)
|
||||
}
|
||||
|
||||
func NewListener(ifconfig string,ch chan error) (*Listener, error) {
|
||||
//m := make(map[uint32]*ReactorManager)
|
||||
var ip string
|
||||
var err error
|
||||
if ip, err = GetIp(ifconfig); err != nil {
|
||||
return &Listener{}, err
|
||||
}
|
||||
m := make(map[string](chan<- *Client))
|
||||
c := &Coordinators{Channel:m}
|
||||
l := &Listener{Ip:ip,Err:ch}
|
||||
l.Coordinators = c
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func (l *Listener) Start() {
|
||||
// start grpc server and implement reciever
|
||||
if err := l.Register(); err != nil {
|
||||
l.Err <- err
|
||||
}
|
||||
// listener started and grpc handler registered
|
||||
fmt.Printf("Started listener on %v:%v\n",l.Ip,l.Port)
|
||||
}
|
||||
|
||||
func (l *Listener) Register() error {
|
||||
// creates a gRPC service and binds it to our handler
|
||||
lis, err := net.Listen("tcp", fmt.Sprintf("%v:0",l.Ip)) // by binding to :0 we should get assigned an empty port
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l.Port = lis.Addr().(*net.TCPAddr).Port // getting the port we were assigned
|
||||
grpcServer := grpc.NewServer()
|
||||
pb.RegisterHandshakeServer(grpcServer, l)
|
||||
go grpcServer.Serve(lis)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *Listener) ClientDiscoveryHandler(ctx context.Context, ping *pb.ClientDiscoveryRequest) (*pb.ClientDiscoveryResponse, error) {
|
||||
// incoming reactor ping need to spawn coord
|
||||
c := NewClient(ping.GetIp(),ping.GetModel(),ping.GetClientType(),int(ping.GetPort()),ping.GetId())
|
||||
fmt.Printf("%v Client %v has connected from %v:%v\n",c.Type,c.Id,c.Ip,c.Port)
|
||||
go l.ConnectClient(c)
|
||||
// we dont handle any actual logic about the creation so we just respon true if the request was received
|
||||
return &pb.ClientDiscoveryResponse{Success:true}, nil
|
||||
}
|
||||
|
||||
func (l *Listener) ConnectClient(c *Client){
|
||||
// send to reactor coordinator for ease
|
||||
l.Coordinators.Lock()
|
||||
defer l.Coordinators.Unlock()
|
||||
switch c.Type {
|
||||
case "reactor","tui":
|
||||
if ch, exists := l.Coordinators.Channel[c.Type]; exists {
|
||||
ch <-c
|
||||
} else {
|
||||
ch := make(chan *Client)
|
||||
newC := NewCoordinator(c.Type, ch, l.Err)
|
||||
go newC.Start()
|
||||
l.Coordinators.Channel[c.Type] = ch
|
||||
ch <-c
|
||||
}
|
||||
default:
|
||||
log.Fatal("Error! client %v not supported!",c.Type)
|
||||
}
|
||||
}
|
@ -1,135 +0,0 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"math"
|
||||
"sync"
|
||||
"errors"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
)
|
||||
|
||||
// this package will implement a boilerplate manager
|
||||
// manager connects to client on start and returns the gRPC connection to make gRPC clients
|
||||
|
||||
type Manager struct {
|
||||
*Client // gives access to c.Ip c.Id etc
|
||||
Hb time.Duration
|
||||
Active active
|
||||
Err chan error
|
||||
}
|
||||
|
||||
type active struct{
|
||||
sync.Mutex
|
||||
bool
|
||||
int
|
||||
}
|
||||
|
||||
func NewManager(c *Client, err chan error) *Manager {
|
||||
hb := time.Duration(1) //hb to
|
||||
m := &Manager{Hb:hb,Err:err}
|
||||
m.Client = c
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *Manager) Start() {
|
||||
// establish connection with client and start pinging at set intervals
|
||||
if !m.Activate() {
|
||||
// manager already running
|
||||
m.Err <-errors.New("Manager already running!")
|
||||
} // if we get here, manager is atomically activated and we can ensure start wont run again
|
||||
}
|
||||
|
||||
func (m *Manager) Exit() {
|
||||
// exit function to eventually allow saving to configs
|
||||
if !m.Deactivate() {
|
||||
m.Err <-errors.New("Manager already disabled!")
|
||||
}
|
||||
fmt.Printf("Manager %v exiting\n", m.Id)
|
||||
}
|
||||
|
||||
// reactor manager atomic operations
|
||||
|
||||
func (m *Manager) IsActive() bool {
|
||||
m.Active.Lock()
|
||||
defer m.Active.Unlock()
|
||||
return m.Active.bool
|
||||
}
|
||||
|
||||
func (m *Manager) Activate() bool {
|
||||
m.Active.Lock()
|
||||
defer m.Active.Unlock()
|
||||
alive := m.Active.bool
|
||||
if alive {
|
||||
return false
|
||||
} else {
|
||||
m.Active.bool = true
|
||||
m.Active.int = 0
|
||||
return m.Active.bool
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Manager) Deactivate() bool {
|
||||
m.Active.Lock()
|
||||
defer m.Active.Unlock()
|
||||
alive := m.Active.bool
|
||||
if alive {
|
||||
m.Active.bool = false
|
||||
return true
|
||||
} else {
|
||||
return m.Active.bool
|
||||
}
|
||||
}
|
||||
|
||||
// connection stuff
|
||||
|
||||
func (m *Manager) Timeout() int {
|
||||
// keeps track of and generates timeout [0-1.2s) over span of ~2.5s
|
||||
// returns 0 on TO elapse
|
||||
m.Active.Lock()
|
||||
defer m.Active.Unlock()
|
||||
if m.Active.int < 9 {
|
||||
v := int(5 * math.Pow(float64(2), float64(m.Active.int)))
|
||||
m.Active.int += 1
|
||||
return v
|
||||
} else {
|
||||
// exceeded retries
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Manager) Connect() *grpc.ClientConn{
|
||||
// establish initial gRPC connection with client
|
||||
var opts []grpc.DialOption
|
||||
var conn *grpc.ClientConn
|
||||
opts = append(opts,grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
for {
|
||||
if !m.IsActive() {
|
||||
fmt.Printf("Aborting connection attempt\n")
|
||||
return &grpc.ClientConn{}
|
||||
}
|
||||
var err error
|
||||
conn, err = grpc.Dial(fmt.Sprintf("%v:%v",m.Ip,m.Port),opts...)
|
||||
// begin error handling
|
||||
code := status.Code(err)
|
||||
if code != 0 { // != OK
|
||||
if code == (5 | 14) { // == unavailable or not found
|
||||
to := m.Timeout()
|
||||
if to == 0 {
|
||||
fmt.Printf("Client not responding\n")
|
||||
m.Exit()
|
||||
return&grpc.ClientConn{}
|
||||
}
|
||||
fmt.Printf("gRPC endpoint currently unavailable, retrying in %v ms\n",to)
|
||||
time.Sleep(time.Duration(to) * time.Millisecond)
|
||||
} else {
|
||||
fmt.Printf("ERR GRPC: %v\n",code)
|
||||
m.Err <-err
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return conn
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"context"
|
||||
"sync"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/status"
|
||||
pb "FRMS/internal/pkg/grpc"
|
||||
)
|
||||
|
||||
// this package will implement a reactor coordinator and associated go routines
|
||||
|
||||
type ReactorManager struct {
|
||||
*Manager
|
||||
Devs *Devices
|
||||
ClientConnections <-chan bool
|
||||
}
|
||||
|
||||
type Devices struct {
|
||||
mu sync.Mutex
|
||||
D map[int]Device
|
||||
}
|
||||
|
||||
func NewReactorManager(c *Client,ch chan bool,err chan error) {
|
||||
d := new(Devices)
|
||||
r := &ReactorManager{Devs:d,ClientConnections:ch}
|
||||
r.Manager = NewManager(c, err)
|
||||
go r.Listen()
|
||||
}
|
||||
|
||||
func (r *ReactorManager) Listen() {
|
||||
for {
|
||||
c := <-r.ClientConnections
|
||||
if c {
|
||||
r.Start()
|
||||
} else {
|
||||
r.Exit()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *ReactorManager) Start() {
|
||||
r.Manager.Start()
|
||||
conn := r.Connect()
|
||||
go r.Monitor(conn)
|
||||
}
|
||||
|
||||
func (r *ReactorManager) Monitor(conn *grpc.ClientConn) {
|
||||
defer conn.Close()
|
||||
client := pb.NewMonitoringClient(conn)
|
||||
for r.IsActive() {
|
||||
req := &pb.ReactorStatusRequest{Id:r.Id}
|
||||
resp, err := client.GetReactorStatus(context.Background(),req)
|
||||
code := status.Code(err)
|
||||
if code != 0 { // if != OK
|
||||
fmt.Printf("Reactor %v down! ", r.Id)
|
||||
r.Exit()
|
||||
}
|
||||
for _,v := range resp.GetDevices() {
|
||||
fmt.Printf("%v is %v, ",v.GetType(),v.GetStatus())
|
||||
}
|
||||
fmt.Print("\n")
|
||||
time.Sleep(r.Hb * time.Second) // time between sensor pings
|
||||
}
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// implement tui specific manager to be called for each client conn
|
||||
|
||||
type TUIManager struct {
|
||||
*Manager // embedded manager for access to methods and client
|
||||
Sys *KnownReactors
|
||||
ClientConnections <-chan bool
|
||||
Err chan error
|
||||
Hb time.Duration
|
||||
}
|
||||
|
||||
type KnownReactors struct {
|
||||
Reactors map[uint32]*Reactor
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
type Reactor struct {
|
||||
Devices map[string]*Device
|
||||
}
|
||||
|
||||
type Device struct {
|
||||
Status DeviceStatus
|
||||
Type string
|
||||
Addr int
|
||||
}
|
||||
|
||||
type DeviceStatus uint32
|
||||
|
||||
const (
|
||||
READY DeviceStatus = iota
|
||||
ACTIVE
|
||||
DISABLED
|
||||
)
|
||||
|
||||
func (d DeviceStatus) String() string {
|
||||
return [...]string{"Ready","Active","Disabled"}[d]
|
||||
}
|
||||
|
||||
func (d Device) String() string {
|
||||
return fmt.Sprintf("%v is %v at %x",d.Type,d.Status,d.Addr)
|
||||
}
|
||||
|
||||
type DeviceManager interface{
|
||||
// GetStatus() uint32 UNSUPPORTED: arguable memory benifit but until we support 100s of sensors across 10s of tui clients im not implementing it
|
||||
PrintSatus() string
|
||||
GetType() string
|
||||
}
|
||||
|
||||
func NewTUIManager(c *Client,ch chan bool, err chan error) {
|
||||
k := new(KnownReactors)
|
||||
m := NewManager(c, err)
|
||||
hb := time.Duration(5)
|
||||
t := &TUIManager{Hb: hb,Sys: k,Err: err, ClientConnections: ch}
|
||||
t.Manager = m
|
||||
go t.Listen()
|
||||
}
|
||||
|
||||
func (t *TUIManager) Listen() {
|
||||
for {
|
||||
c := <-t.ClientConnections
|
||||
if c {
|
||||
t.Start()
|
||||
} else {
|
||||
t.Exit()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TUIManager) Start() {
|
||||
t.Manager.Start()
|
||||
//conn := t.Conn()
|
||||
//go t.Monitor(conn)
|
||||
}
|
Loading…
Reference in New Issue