diff --git a/interfaces/healthTracker.go b/interfaces/healthTracker.go index faa31e8e48a2c072063f5aebf63a05cd297121f6..39441984ee0088b9e82e33e7b7a11ab689288f00 100644 --- a/interfaces/healthTracker.go +++ b/interfaces/healthTracker.go @@ -11,4 +11,5 @@ type HealthTracker interface { AddChannel(chan bool) AddFunc(f func(bool)) IsHealthy() bool + WasHealthy() bool } diff --git a/network/health/tracker.go b/network/health/tracker.go index c153cedfa1176565c8546ff9f1c1e451abf3afb5..d1cac14eaeaa88e026add438ae9aeec2a27b7071 100644 --- a/network/health/tracker.go +++ b/network/health/tracker.go @@ -28,8 +28,12 @@ type Tracker struct { running bool + // Determines the current health status isHealthy bool - mux sync.RWMutex + // Denotes the past health status + // wasHealthy is true if isHealthy has ever been true + wasHealthy bool + mux sync.RWMutex } // Creates a single HealthTracker thread, starts it, and returns a tracker and a stoppable @@ -79,8 +83,19 @@ func (t *Tracker) IsHealthy() bool { return t.isHealthy } +// Returns true if isHealthy has ever been true +func (t *Tracker) WasHealthy() bool { + t.mux.RLock() + defer t.mux.RUnlock() + return t.wasHealthy +} + func (t *Tracker) setHealth(h bool) { t.mux.Lock() + // Only set wasHealthy to true if either + // wasHealthy is true or + // wasHealthy false but h value is true + t.wasHealthy = t.wasHealthy || h t.isHealthy = h t.mux.Unlock() t.transmit(h) diff --git a/network/health/tracker_test.go b/network/health/tracker_test.go index 318a69f79d599f09444470efb702a6a340767913..4a10843c36ef23bcd3dc8cfbb5699e71a9643e78 100644 --- a/network/health/tracker_test.go +++ b/network/health/tracker_test.go @@ -72,6 +72,12 @@ func TestNewTracker(t *testing.T) { return } + // Check if the tracker was ever healthy + if !tracker.WasHealthy() { + t.Errorf("Tracker did not become healthy") + return + } + // Verify the heartbeat triggered the listening chan/func if counter != expectedCount { t.Errorf("Expected counter to be %d, got %d", expectedCount, counter) @@ -87,6 +93,13 @@ func TestNewTracker(t *testing.T) { return } + // Check if the tracker was ever healthy, + // after setting healthy to false + if !tracker.WasHealthy() { + t.Errorf("Tracker was healthy previously but not reported healthy") + return + } + // Verify the timeout triggered the listening chan/func if counter != expectedCount { t.Errorf("Expected counter to be %d, got %d", expectedCount, counter) diff --git a/ud/manager.go b/ud/manager.go index 7cbce3d6b793ea26a9a47fee81afff4137cd7c33..bea67fd599bdf22f4e67c0c2b1735e2027945c2f 100644 --- a/ud/manager.go +++ b/ud/manager.go @@ -18,20 +18,20 @@ import ( type Manager struct { //external - client *api.Client + client *api.Client comms *client.Comms rng *fastRNG.StreamGenerator sw interfaces.Switchboard storage *storage.Session - net interfaces.NetworkManager + net interfaces.NetworkManager //loaded from external access - udID *id.ID + udID *id.ID privKey *rsa.PrivateKey - grp *cyclic.Group + grp *cyclic.Group //internal maps - host *connect.Host + host *connect.Host inProgressLookup map[uint64]chan *LookupResponse inProgressLookupMux sync.RWMutex @@ -47,35 +47,34 @@ type Manager struct { // New manager builds a new user discovery manager. It requires that an // updated NDF is available and will error if one is not. -func NewManager(client *api.Client)(*Manager, error){ - - if !client.GetHealth().IsHealthy(){ +func NewManager(client *api.Client) (*Manager, error) { + if !client.GetHealth().WasHealthy() { return nil, errors.New("cannot start UD Manager when network " + - "is not healthy") + "was never healthy") } m := &Manager{ - client: client, - comms: client.GetComms(), - rng: client.GetRng(), - sw: client.GetSwitchboard(), - storage: client.GetStorage(), - net: client.GetNetworkInterface(), - inProgressLookup: make(map[uint64]chan *LookupResponse), - inProgressSearch: make(map[uint64]chan *SearchResponse), + client: client, + comms: client.GetComms(), + rng: client.GetRng(), + sw: client.GetSwitchboard(), + storage: client.GetStorage(), + net: client.GetNetworkInterface(), + inProgressLookup: make(map[uint64]chan *LookupResponse), + inProgressSearch: make(map[uint64]chan *SearchResponse), } var err error //check that user discovery is available in the ndf def := m.net.GetInstance().GetPartialNdf().Get() - if m.udID, err = id.Unmarshal(def.UDB.ID); err!=nil{ - return nil, errors.WithMessage(err,"NDF does not have User " + - "Discovery information, is there network access?: ID could not be " + + if m.udID, err = id.Unmarshal(def.UDB.ID); err != nil { + return nil, errors.WithMessage(err, "NDF does not have User "+ + "Discovery information, is there network access?: ID could not be "+ "unmarshaled") } - if def.UDB.Cert==""{ + if def.UDB.Cert == "" { return nil, errors.New("NDF does not have User " + "Discovery information, is there network access?: Cert " + "not present") @@ -84,9 +83,9 @@ func NewManager(client *api.Client)(*Manager, error){ //create the user discovery host object hp := connect.GetDefaultHostParams() - if m.host, err = m.comms.AddHost(m.udID, def.UDB.Address,[]byte(def.UDB.Cert), - hp); err!=nil{ - return nil, errors.WithMessage(err, "User Discovery host " + + if m.host, err = m.comms.AddHost(m.udID, def.UDB.Address, []byte(def.UDB.Cert), + hp); err != nil { + return nil, errors.WithMessage(err, "User Discovery host "+ "object could not be constructed") } @@ -105,7 +104,7 @@ func NewManager(client *api.Client)(*Manager, error){ return m, nil } -func (m *Manager) StartProcesses() { +func (m *Manager) StartProcesses() { m.client.AddService(m.startProcesses) } @@ -126,7 +125,3 @@ func (m *Manager) startProcesses() stoppable.Stoppable { udMulti.Add(searchStop) return lookupStop } - - - -