You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

112 lines
2.5 KiB
Go

package server
import (
//"log"
"time"
"math"
"sync"
"errors"
//"FRMS/internal/pkg/logging"
)
// 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
IncomingClient chan *Client
Hb time.Duration // used for managing hb timer for client
Active active
Sig chan bool
Err chan error
}
type active struct{
sync.Mutex
bool
int
}
func NewManager(cl chan *Client, err chan error) *Manager {
hb := time.Duration(1 * time.Second) //hb to
m := &Manager{Hb:hb,Err:err,IncomingClient:cl}
return m
}
func (m *Manager) Start() {
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
go m.ClientConnections()
}
func (m *Manager) Exit() {
// exit function to eventually allow saving to configs
if !m.Deactivate() {
m.Err <-errors.New("Manager already disabled!")
}
}
func (m *Manager) ClientConnections() {
for m.IsActive {
cl := <-m.IncomingClient
if m.IsActive {
logging.Debug(logging.DClient,"MAN Updating client old (%v) new (%v)",m.Id,cl.Id)
m.Client = cl
}
}
}
// 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 {
// slightly confusing but returns result of trying to activate
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 {
// result of trying to deactivate
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
}
}