From 22491ad5675625b8e6f40d94bbbf948df3fe4a70 Mon Sep 17 00:00:00 2001 From: carla Date: Thu, 18 Mar 2021 10:46:45 +0200 Subject: [PATCH] routing: add mission control import functionality --- routing/missioncontrol.go | 21 ++++++++++++++ routing/missioncontrol_state.go | 50 +++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/routing/missioncontrol.go b/routing/missioncontrol.go index 29d62dcc..a1793ad0 100644 --- a/routing/missioncontrol.go +++ b/routing/missioncontrol.go @@ -342,6 +342,27 @@ func (m *MissionControl) GetHistorySnapshot() *MissionControlSnapshot { return m.state.getSnapshot() } +// ImportHistory imports the set of mission control results provided to our +// in-memory state. These results are not persisted, so will not survive +// restarts. +func (m *MissionControl) ImportHistory(history *MissionControlSnapshot) error { + if history == nil { + return errors.New("cannot import nil history") + } + + m.Lock() + defer m.Unlock() + + log.Infof("Importing history snapshot with %v pairs to mission control", + len(history.Pairs)) + + imported := m.state.importSnapshot(history) + + log.Infof("Imported %v results to mission control", imported) + + return nil +} + // GetPairHistorySnapshot returns the stored history for a given node pair. func (m *MissionControl) GetPairHistorySnapshot( fromNode, toNode route.Vertex) TimedPairResult { diff --git a/routing/missioncontrol_state.go b/routing/missioncontrol_state.go index 06e2ef13..05e083b8 100644 --- a/routing/missioncontrol_state.go +++ b/routing/missioncontrol_state.go @@ -209,3 +209,53 @@ func (m *missionControlState) getSnapshot() *MissionControlSnapshot { return &snapshot } + +// importSnapshot takes an existing snapshot and merges it with our current +// state if the result provided are fresher than our current results. It returns +// the number of pairs that were used. +func (m *missionControlState) importSnapshot(snapshot *MissionControlSnapshot) int { + var imported int + + for _, pair := range snapshot.Pairs { + fromNode := pair.Pair.From + toNode := pair.Pair.To + + results, found := m.getLastPairResult(fromNode) + if !found { + results = make(map[route.Vertex]TimedPairResult) + } + + lastResult := results[toNode] + + failResult := failPairResult(pair.FailAmt) + imported += m.importResult( + lastResult.FailTime, pair.FailTime, failResult, + fromNode, toNode, + ) + + successResult := successPairResult(pair.SuccessAmt) + imported += m.importResult( + lastResult.SuccessTime, pair.SuccessTime, successResult, + fromNode, toNode, + ) + } + + return imported +} + +func (m *missionControlState) importResult(currentTs, importedTs time.Time, + importedResult pairResult, fromNode, toNode route.Vertex) int { + + if currentTs.After(importedTs) { + log.Debugf("Not setting pair result for %v->%v (%v) "+ + "success=%v, timestamp %v older than last result %v", + fromNode, toNode, importedResult.amt, + importedResult.success, importedTs, currentTs) + + return 0 + } + + m.setLastPairResult(fromNode, toNode, importedTs, &importedResult) + + return 1 +}