still adding tui manager status mon. Deciding how to handle killing/reattaching

main
Keegan 3 years ago
parent 58d4c08ce4
commit 533e0325aa

@ -124,12 +124,22 @@ func (l *listener) RemoveListener(id uint32) error {
if lis, ok := l.Listeners[id]; !ok {
return errors.New("Listener doesn't exists!")
} else {
lis.Wait()
lis.StatusChan.Close()
go lis.Exit()
delete(l.Listeners,id)
}
return nil
}
func (l *lischan) Exit() {
for {
select {
case ls.Wait():
l.StatusChan.Close()
break;
case <-l.StatusChan:
// dump buffer
}
}
//func (s *InfoStream) GetLayout() map[uint32]*DeviceInfo {
//s.Layout.RLock()
//defer s.Layout.RUnlock()
@ -141,11 +151,6 @@ 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
}
@ -212,19 +217,21 @@ 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
func (s *SystemViewer) AddListener(tid uint32, rid ...uint32) (map[uint32]*DeviceInfo, *StatusMonitor) {
// adds status monitor as a listener and returns any already stored dev
// id serves as client id and limits them to one of each
var rid uint32
if len(ids) == 1 {
rid = uint32(ids[0])
} else if len(ids) != 0{
logging.Debug(logging.DError, "Too many arguements given to Add Listener")
os.Exit(1)
}
// id is either 0 or reactor we are interested in
rstatus, sm := s.ReactorStream.AddListener(id)
if sm
func (s *SystemViewer) GetBuffer(
/*
func (s *SystemViewer) GetReactorStatus() map[uint32]DeviceInfo {
devs := s.ReactorStream.GetLayout()

@ -17,13 +17,20 @@ import (
type TUIManager struct {
*Manager // embedded manager for access to methods and client
Ip string
*SystemViewer
Port *port
DevsMon *StatusMonitor // use it for all devs coming in
*SystemViewer
Err chan error
*DevBuffer
*Timeout
*pb.UnimplementedManagementServer
}
type DevBuffer struct {
Devs []map[uint32]*DeviceInfo
sync.Mutex
}
type Timeout struct {
Alert chan bool
LastSeen time.Time
@ -43,8 +50,14 @@ func NewTUIManager(ip string, c *Client, sys *SystemViewer, err chan error) Gene
alert := make(chan bool)
t.Timeout = &Timeout{Alert:alert,TO:time.Duration(2500*time.Millisecond)} // short time outs are fine because we will just rejoin
t.Manager = m
t.SystemViewer = sys
t.Ip = ip
mon, buf := sys.AddListener()
t.DevsMon = mon
t.SystemViewer = sys
t.DevBuffer = &DevBuffer{Devs:[2]map[uint32]*DeviceInfo{})}
t.DevBuffer[0] = make(map[uint32]*DeviceInfo)
t.DevBuffer[1] = make(map[uint32]*DeviceInfo) // maps for reactors and devs
go t.UpdateBuffer(buf)
return t
}
@ -53,6 +66,7 @@ func (t *TUIManager) Start(cl *Client) {
t.PingReset()
t.Manager.Start(cl)
logging.Debug(logging.DStart,"TMA %v starting", t.Id)
go t.DeviceListener()
go t.Timeoutd()
go t.Register() // begin tui server to respond to tui client reqs
//go t.Monitor(conn)
@ -62,6 +76,7 @@ func (t *TUIManager) Exit() {
t.Manager.Exit()
logging.Debug(logging.DExit,"TMA %v exiting",t.Id)
}
func (t *Timeout) PingReset() {
t.Lock()
defer t.Unlock()
@ -106,7 +121,7 @@ func (t *TUIManager) Register() {
go func(ch chan int,p int) {
ch <-p
}(t.Port.Chan, t.Port.int)
logging.Debug(logging.DClient, "TMA %v reayd for client conn", t.Id)
logging.Debug(logging.DClient, "TMA %v ready for client conn", t.Id)
// up and running
}
@ -116,39 +131,65 @@ func (t *TUIManager) GetPort() int {
}
// tui client requests and logic will be down here
func (t *TUIManager) ReactorListener() {
func (t *TUIManager) DeviceListener() {
// called on start requests reactor info and buffers updates
buffer, devchan := t.SystemViewer.AddReactorListener(t.Id)
for dev := range devchan {
go t.UpdateReactor(dev)
for dev := range t.DevsMon.StatusChan {
go t.UpdateBuffer(dev)
}
}
func (t *TUIManager) DeviceListener(id uint32) {
buffer, devchan := t.SystemViewer.AddDeviceListener(t.Id,id)
for _, dev
for dev := range devchan {
go t.UpdateDevices(dev)
func (d *DevBuffer) UpdateBuffer(dv *DeviceInfo) {
// TODO
// need a way to take incoming devices and only store most recent entry in the buffer
d.Lock()
defer d.Unlock()
if dv.Type == "Reactor" {
d.Devs[0][dv.Id] = dv
} else {
d.Devs[1][dv.Id] = dv
}
}
func (d *DevBuffer) EmptyBuffer() []*DeviceInfo {
// TODO
// need to grab the current buffer contents and empty them into the device reply
d.Lock()
defer d.Unlock()
ret := []*DeviceInfo{}
for _, mp := range d.Devs {
for _, dev := range mp {
ret = append(ret,dev)
}
}
d.Devs = []map[uint32]*DeviceInfo{}
return ret
}
func (t *TUIManager) AttachListener(id uint32) []*DeviceInfo {
// if a reactor is selected we need to
// empty the buffer
// get the dev info for the reactor
// add our devmon to the chan
func (t *TUIManager) GetDevices(ctx context.Context, req *pb.GetDevicesRequest) (*pb.GetDevicesResponse, error) {
go t.PingReset()
// doing 2 things, clearing reactor buffer and either
// a) clearing dev buffer
// b) killing old dev listener and getting new buffer
rid := req.GetReactorId()
devices := []*pb.Dev{}
resp := &pb.GetDevicesResponse{ClientId:t.Id,ReactorId:rid,Devices:devices}
reactors := t.SystemViewer.GetReactorStatus()
for _, v := range reactors {
resp.Devices = append(resp.Devices, &pb.Dev{Id:v.Id,Type:v.Type,Status:v.Status,Data:v.Data,Index:v.Index})
var devs []*DeviceInfo
if rid != 0 {
// reactor requested
devs = t.AttachListener(rid)
} else {
devs = t.EmptyBuffer()
}
if rid != 0 {
// need reactor devices
devs := t.SystemViewer.GetDeviceStatus(rid)
for _, v := range devs {
resp.Devices = append(resp.Devices, &pb.Dev{Id:v.Id,Type:v.Type,Status:v.Status,Data:v.Data,Index:v.Index})
}
for _, v := range devs {
resp.Devices = append(resp.Devices, &pb.Dev{Id:v.Id,Type:v.Type,Status:v.Status,Data:v.Data,Index:v.Index})
}
logging.Debug(logging.DClient,"TMA %v sending devices to client" ,t.Id)
return resp, nil

@ -128,7 +128,7 @@ func (t *TUIClient) GetDevices(id ...uint32) (map[uint32]*Device, error) {
client := pb.NewManagementClient(t.ClientConn)
resp, err := client.GetDevices(context.Background(), req)
if err != nil {
return r, nil
return r, err
}
for _, v := range resp.GetDevices() {
r[v.GetId()] = &Device{Type:v.GetType(),Status:v.GetStatus(),Id:v.GetId(),Data:v.GetData(),Index:v.GetIndex()}

@ -61,7 +61,7 @@ func (t *TUI) CreateDisplay() {
t.SelectedReactor = rc
t.SelectedDevice = dc
t.Flex.AddItem(t.ReactorList,0,1,true).
AddItem(t.DevicePages,0,2,false)
AddItem(t.DeviceList,0,2,false)
}
func (t *TUI) Monitor() {
@ -79,14 +79,16 @@ func (t *TUI) Monitor() {
case reactor := <-t.SelectedReactor:
// reactor has been selected in tui, grabbing devs
t.App.QueueUpdateDraw(func() {
t.Display.DeviceList.Clear()
t.UpdateDevices(reactor)
})
logging.Debug(logging.DClient, "%v getting reactor devices", t.Id)
case <-t.SelectedDevice:
case dev := <-t.SelectedDevice:
logging.Debug(logging.DClient, "%v editing device %v", t.Id, dev)
// TODO
case <-timer:
// time to ping for status
logging.Debug(logging.DClient, "%v getting reactor status", t.Id)
logging.Debug(logging.DClient, "%v pinging for updates", t.Id)
t.App.QueueUpdateDraw(func() {
t.UpdateDevices()
})
@ -98,13 +100,14 @@ func (t *TUI) UpdateDevices(r ...uint32) {
// get devices for the reactor and update the tui
var id uint32
// see if there is a page being displayed
/*
if name, _ := t.Display.DevicePages.GetFrontPage(); name != "" {
if tmp, err := strconv.ParseUint(name, 10, 32); err != nil {
log.Fatal(err)
} else {
id = uint32(tmp)
}
}
}*/
// overwrite if called as a func
if len(r) > 0 {
id = r[0]
@ -113,22 +116,22 @@ func (t *TUI) UpdateDevices(r ...uint32) {
if err != nil {
log.Fatal(err)
}
if id != 0 {
// reactor specificed split devs
reactors := make(map[uint32]*Device)
devices := make(map[uint32]*Device)
for id, dev := range devs {
if dev.Type == "Reactor" {
reactors[id] = dev
} else {
devices[id] = dev
}
//if id != 0 {
// split based on type to simplify update
reactors := make(map[uint32]*Device)
devices := make(map[uint32]*Device)
for id, dev := range devs {
if dev.Type == "Reactor" {
reactors[id] = dev
} else {
devices[id] = dev
}
t.DisplayDevices(devices, id)
t.DisplayReactors(reactors)
} else {
t.DisplayReactors(devs)
}
t.DisplayDevices(devices)
t.DisplayReactors(reactors)
// } else {
// t.DisplayReactors(devs)
//}
}
// display struct and logic
@ -136,8 +139,7 @@ type Display struct {
App *tview.Application
Flex *tview.Flex
ReactorList *tview.List
DevicePages *tview.Pages
DeviceList map[string]*tview.List
DeviceList *tview.List
SelectedReactor chan<- uint32
SelectedDevice chan<- uint32
sync.Mutex
@ -147,17 +149,16 @@ func NewDisplay(rc,dc chan uint32) *Display {
d := &Display{}
d.App = tview.NewApplication()
d.Flex = tview.NewFlex()
lists := make(map[string]*tview.List)
d.DeviceList = lists
d.ReactorList = tview.NewList()//.ShowSecondaryText(false)
d.DeviceList = tview.NewList()
d.ReactorList = tview.NewList()
d.ReactorList.AddItem("Quit","Press (q) to quit",113,func() {
d.App.Stop()
os.Exit(0)
})
d.DevicePages = tview.NewPages()
d.ReactorList.SetTitle("Reactors").SetBorder(true)
d.ReactorList.SetSelectedFunc(d.SelectReactor)
d.DevicePages.SetTitle("Devices").SetBorder(true)
d.DeviceList.SetTitle("Devices").SetBorder(true)
d.DeviceList.SetSelectedFunc(d.SelectDevice)
d.SelectedReactor = rc
d.SelectedDevice = dc
return d
@ -171,21 +172,36 @@ func (d *Display) Start() {
}
func (d *Display) DisplayReactors(r map[uint32]*Device) {
// function to display reactor list to table
//d.Lock()
//defer d.Unlock()
// locking may break the hell out of this gonna trust tview
// this func takes in a list of devices to update and loops over them
// works by padding list for entries not seen yet
for _, reactor := range r {
txt := fmt.Sprintf("%v %v", reactor.Id, reactor.Status)
if d.ReactorList.GetItemCount() > int(reactor.Index) + 1 {
d.ReactorList.RemoveItem(int(reactor.Index))
indx := int(reactor.Index)
for indx + 1 >= d.ReactorList.GetItemCount() {
// this prevent overwriting quit entry
d.ReactorList.InsertItem(-2,txt,reactor.Data,rune(48+d.ReactorList.GetItemCount()),nil)
}
if indx + 1 < d.ReactorList.GetItemCount() {
d.ReactorList.SetItemText(indx,txt,reactor.Data)
}
d.ReactorList.InsertItem(int(reactor.Index),txt,reactor.Data,rune(49+reactor.Index),nil)
}
}
func (d *Display) DisplayDevices(devs map[uint32]*Device, rid uint32) {
//d.Lock()
func (d *Display) DisplayDevices(devs map[uint32]*Device) {
// going to just clear every time as we reload new dev lists anyway
// going to clear on every reactor selection to simplify
// can probably just load from SM to save system resources on spam reloading
for _, dev := range devs {
txt := fmt.Sprintf("0x%x %v %v",dev.Id,dev.Status,dev.Type)
indx := int(dev.Index)
for indx >= d.DeviceList.GetItemCount() {
d.DeviceList.AddItem(txt,dev.Data,rune(49+d.DeviceList.GetItemCount()), nil)
}
if indx < d.DeviceList.GetItemCount() {
d.DeviceList.SetItemText(indx,txt,dev.Data)
}
}
/*
reactorPage := strconv.FormatUint(uint64(rid), 10)
var reactorList *tview.List
var ok bool
@ -203,6 +219,7 @@ func (d *Display) DisplayDevices(devs map[uint32]*Device, rid uint32) {
reactorList.InsertItem(int(dev.Index),txt,dev.Data,0,nil)
}
d.DevicePages.SwitchToPage(reactorPage)
*/
}
@ -219,10 +236,15 @@ func (d *Display) SelectReactor(index int, main, data string, r rune) {
}
}
func (d *Display) SelectDevice(index int, main, id string, r rune) {
func (d *Display) SelectDevice(index int, main, data string, r rune) {
// called when device is selected in sub menu
if id, err := strconv.ParseUint(id, 10, 32); err != nil {
log.Fatal(err)
maintxt := strings.Split(main," ")
id := maintxt[0]
id = strings.Trim(id,"0x \n")
logging.Debug(logging.DClient,"Selected dev %v", id)
if id, err := strconv.ParseUint(id, 16, 32); err != nil {
logging.Debug(logging.DError, "Error parsing: %v", err)
os.Exit(1)
} else {
d.SelectedDevice <-uint32(id)
}

Loading…
Cancel
Save