func (smm *SkyManagerMonitor) IsRunning() bool {
	return smm.GetCancelFunc() != nil
}
IsRunning determines if the SkyMgrMonitor is running or not.
This is assessed based on the assignment of the context cancel function (one is assigned if it is running).
package skymgrmon
import (
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"sync"
	"time"
	"github.com/BigOokie/skywire-wing-commander/internal/skynode"
	"github.com/BigOokie/skywire-wing-commander/internal/wcconst"
	log "github.com/sirupsen/logrus"
)
const (
	managerAPIGetAllConnectedNodes = "conn/getAll"
)
type SkyManagerMonitor struct {
	ManagerAddress       string
	DiscoveryAddress     string
	cancelFunc           func()
	monitorStatusMsgChan chan<- string
	connectedNodes       skynode.NodeInfoMap
	discConnNodeCount    int
	m                    sync.Mutex
	updateStarted        bool
	updateMsgChan        chan string
}
func (smm *SkyManagerMonitor) SetCancelFunc(cf func()) {
	smm.m.Lock()
	defer smm.m.Unlock()
	smm.cancelFunc = cf
}
func (smm *SkyManagerMonitor) GetCancelFunc() func() {
	smm.m.Lock()
	defer smm.m.Unlock()
	return smm.cancelFunc
}
func (smm *SkyManagerMonitor) DoCancelFunc() {
	smm.m.Lock()
	defer smm.m.Unlock()
	if smm.cancelFunc != nil {
		smm.cancelFunc()
	}
}
func (smm *SkyManagerMonitor) GetUpdateStarted() bool {
	smm.m.Lock()
	defer smm.m.Unlock()
	return smm.updateStarted
}
func (smm *SkyManagerMonitor) SetUpdateStarted(flag bool) {
	smm.m.Lock()
	defer smm.m.Unlock()
	smm.updateStarted = flag
}
func NewMonitor(manageraddress, discoveryaddress string) *SkyManagerMonitor {
	return &SkyManagerMonitor{
		ManagerAddress:       manageraddress,
		DiscoveryAddress:     discoveryaddress,
		cancelFunc:           nil,
		monitorStatusMsgChan: nil,
		connectedNodes:       make(skynode.NodeInfoMap),
		discConnNodeCount:    0,
		updateStarted:        false,
		updateMsgChan:        nil,
	}
}
func (smm *SkyManagerMonitor) RunManagerMonitor(runctx context.Context, doCancelFunc func(), statusMsgChan chan<- string, pollInt time.Duration) {
	log.Debugf("SkyManagerMonitor.RunManagerMonitor: Start (Interval: %v)", pollInt)
	defer log.Debugln("SkyManagerMonitor.RunManagerMonitor: End")
	smm.SetCancelFunc(doCancelFunc)
	smm.monitorStatusMsgChan = statusMsgChan
	ticker := time.NewTicker(pollInt)
	for {
		select {
		case <-ticker.C:
			newcns, err := getAllNodesList(smm.ManagerAddress)
			if err != nil {
				log.Error(err)
				statusMsgChan <- wcconst.MsgErrorGetNodes
			} else {
				smm.maintainConnectedNodesList(newcns, statusMsgChan)
			}
		case <-runctx.Done():
			log.Debugln("SkyManagerMonitor.RunManagerMonitor: Done Event.")
			return
		}
	}
}
func (smm *SkyManagerMonitor) StopManagerMonitor() {
	log.Debugln("SkyManagerMonitor.StopManagerMonitor: Start")
	defer log.Debugln("SkyManagerMonitor.StopManagerMonitor: End")
	if smm.IsRunning() {
		smm.DoCancelFunc()
		smm.SetCancelFunc(nil)
		close(smm.monitorStatusMsgChan)
		smm.monitorStatusMsgChan = nil
		log.Debug(wcconst.MsgMonitorStopped)
	}
}
func (smm *SkyManagerMonitor) ConnectedDiscNodeCount() (int, error) {
	log.Debug("SkyManagerMonitor.ConnectedDiscNodeCount: Start")
	defer log.Debugln("SkyManagerMonitor.ConnectedDiscNodeCount: End")
	discConnNodeCount := 0
	if smm.GetConnectedNodeCount() == 0 {
		log.Debug("SkyManagerMonitor.ConnectedDiscNodeCount: Connected Node list is empty. No work to do.")
		return discConnNodeCount, nil
	}
	discNodes, err := getAllNodesList(smm.DiscoveryAddress)
	if err != nil {
		log.Errorf("SkyManagerMonitor.ConnectedDiscNodeCount: Error contacting Discovery Server: %v", err)
		return discConnNodeCount, err
	} else if len(discNodes) == 0 {
		log.Debugln("SkyManagerMonitor.ConnectedDiscNodeCount: Empty Discovery Server Node List.")
		return discConnNodeCount, nil
	} else {
		log.Debugf("SkyManagerMonitor.ConnectedDiscNodeCount: Discovery Node Returned %v Nodes.", len(discNodes))
		smm.m.Lock()
		defer smm.m.Unlock()
		discNodeMap := skynode.NodeInfoSliceToMap(discNodes)
		for _, v := range smm.connectedNodes {
			_, hasKey := discNodeMap[v.Key]
			if hasKey {
				log.Debugf("SkyManagerMonitor.ConnectedDiscNodeCount: Node Connected:\n%s\n", v.FmtString())
				discConnNodeCount++
			} else {
				log.Debugf("SkyManagerMonitor.ConnectedDiscNodeCount: Node Not Connected:\n%s\n", v.FmtString())
			}
		}
		log.Debugf("SkyManagerMonitor.ConnectedDiscNodeCount: %d Nodes Connected to Discovery", discConnNodeCount)
	}
	return discConnNodeCount, nil
}