|
|
|
@ -29,6 +29,17 @@ type InfoStream struct {
|
|
|
|
|
// NewListener will add the statusmon to the list of devs to echo to
|
|
|
|
|
Stream chan *DeviceInfo
|
|
|
|
|
Layout *syslayout
|
|
|
|
|
*listeners
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type listeners struct {
|
|
|
|
|
sync.RWMutex
|
|
|
|
|
Listeners map[uint32]*lischan
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type lischan struct {
|
|
|
|
|
sync.WaitGroup
|
|
|
|
|
*StatusMonitor
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type syslayout struct {
|
|
|
|
@ -42,6 +53,7 @@ func NewInfoStream() *InfoStream {
|
|
|
|
|
s := &InfoStream{Stream:dch}
|
|
|
|
|
m := make(map[uint32]*DeviceInfo)
|
|
|
|
|
s.Layout = &syslayout{Devs:m}
|
|
|
|
|
s.listeners = &listeners{Listeners:make(map[uint32]*lischan)}
|
|
|
|
|
return s
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -59,6 +71,7 @@ func (s *InfoStream) Listener() {
|
|
|
|
|
for {
|
|
|
|
|
deviceInfo := <-s.Stream
|
|
|
|
|
go s.Update(deviceInfo)
|
|
|
|
|
go s.Echo(deviceInfo)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -74,23 +87,49 @@ func (s *InfoStream) Update(d *DeviceInfo) {
|
|
|
|
|
go s.Echo(d)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *InfoStream) Echo(d *DeviceInfo) {
|
|
|
|
|
s.Listeners.RLock()
|
|
|
|
|
defer s.Listeners.RUnlock()
|
|
|
|
|
func (l *listener) Echo(d *DeviceInfo) {
|
|
|
|
|
l.RLock()
|
|
|
|
|
defer l.RUnlock()
|
|
|
|
|
// read only lock
|
|
|
|
|
for _, lis := range s.Listeners {
|
|
|
|
|
go func(){
|
|
|
|
|
lis <-d
|
|
|
|
|
}()
|
|
|
|
|
for _, lis := range l.Listeners {
|
|
|
|
|
lis.Add(1)
|
|
|
|
|
go func(listener *lischan, dev *DeviceInfo){
|
|
|
|
|
defer listener.Done()
|
|
|
|
|
listener.StatusChan <-dev
|
|
|
|
|
}(lis,d)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *InfoStream) AddListner(ch chan *DeviceInfo) {
|
|
|
|
|
s.Listeners.Lock()
|
|
|
|
|
defer s.Listeners.Unlock()
|
|
|
|
|
s.Listeners = append(s.Listeners, ch)
|
|
|
|
|
func (s *InfoStream) AddListener(id uint32, ch chan *DeviceInfo) (map[uint32]*DeviceInfo, *StatusMonitor) {
|
|
|
|
|
s.listener.Lock()
|
|
|
|
|
s.Layout.Lock()
|
|
|
|
|
defer s.listner.Unlock()
|
|
|
|
|
defer s.Layout.Unlock()
|
|
|
|
|
if sm, ok l.listener.Listeners[id]; ok {
|
|
|
|
|
// listener already exists return nil
|
|
|
|
|
// going to delete and create a new one here just because f it
|
|
|
|
|
|
|
|
|
|
return s.Layout.Devs, sm
|
|
|
|
|
} else {
|
|
|
|
|
ch := make(chan *DeviceInfo)
|
|
|
|
|
sm := NewStatusMonitor(ch)
|
|
|
|
|
s.listener.Listeners[id] = sm
|
|
|
|
|
return s.Layout.Devs, sm
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (l *listener) RemoveListener(id uint32) error {
|
|
|
|
|
l.Lock()
|
|
|
|
|
defer l.Unlock()
|
|
|
|
|
if lis, ok := l.Listeners[id]; !ok {
|
|
|
|
|
return errors.New("Listener doesn't exists!")
|
|
|
|
|
} else {
|
|
|
|
|
lis.Wait()
|
|
|
|
|
lis.StatusChan.Close()
|
|
|
|
|
delete(l.Listeners,id)
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
//func (s *InfoStream) GetLayout() map[uint32]*DeviceInfo {
|
|
|
|
|
//s.Layout.RLock()
|
|
|
|
|
//defer s.Layout.RUnlock()
|
|
|
|
@ -102,6 +141,12 @@ type StatusMonitor struct {
|
|
|
|
|
// serve as base to embed in managers to send/receive device info
|
|
|
|
|
TransactionId chan uint32 // monotonically increases to track outdated reqs
|
|
|
|
|
StatusChan chan *DeviceInfo // sending reactor info in same fmt
|
|
|
|
|
Buffer *buf
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type buf struct {
|
|
|
|
|
Buffer map[uint32]*DeviceInfo //directory of changes since last req
|
|
|
|
|
sync.Mutex
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *StatusMonitor) Start() {
|
|
|
|
@ -133,6 +178,7 @@ type SystemViewer struct {
|
|
|
|
|
|
|
|
|
|
type ds struct {
|
|
|
|
|
Reactors map[uint32]*InfoStream //map from reactor id to its device info stream
|
|
|
|
|
Clients map[uint32]uint32 // maps tui ids to checked out reactor dev ids
|
|
|
|
|
sync.Mutex
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -140,7 +186,8 @@ func NewSystemViewer() *SystemViewer {
|
|
|
|
|
rs := NewInfoStream()
|
|
|
|
|
s := &SystemViewer{ReactorStream:rs}
|
|
|
|
|
m := make(map[uint32]*InfoStream)
|
|
|
|
|
s.DeviceStream = &ds{Reactors:m}
|
|
|
|
|
c := make(map[uint32]uint32)
|
|
|
|
|
s.DeviceStream = &ds{Reactors:m,Clients:c}
|
|
|
|
|
return s
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -165,6 +212,20 @@ func (s *SystemViewer) AddDeviceSender(reactorId uint32) *StatusMonitor {
|
|
|
|
|
return ds.AddSender()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *SystemViewer) AddReactorListener(tid uint32) (map[uint32]*DeviceInfo, *StatusMonitor) {
|
|
|
|
|
// adds status monitor as a listener and returns any reactors loaded before our channel is active
|
|
|
|
|
// id serves as client id and limits them to one of each
|
|
|
|
|
rstatus, ch := s.ReactorStream.AddListener(id)
|
|
|
|
|
if sm
|
|
|
|
|
|
|
|
|
|
func (s *SystemViewer) AddDeviceListener(rid, tid uint32) (map[uint32]*DeviceInfo, *StatusMonitor) {
|
|
|
|
|
// adds status monitor as a listener and returns any reactors loaded before our channel is active
|
|
|
|
|
// id serves as client id and limits them to one of each
|
|
|
|
|
rstatus, sm := s.ReactorStream.AddListener(id)
|
|
|
|
|
if sm
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
func (s *SystemViewer) GetReactorStatus() map[uint32]DeviceInfo {
|
|
|
|
|
devs := s.ReactorStream.GetLayout()
|
|
|
|
|
ret := make(map[uint32]DeviceInfo)
|
|
|
|
@ -185,3 +246,4 @@ func (s *SystemViewer) GetDeviceStatus(reactorId uint32) map[uint32]DeviceInfo {
|
|
|
|
|
}
|
|
|
|
|
return ret
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|