diff --git a/internal/routewatch/peeringhandler.go b/internal/routewatch/peeringhandler.go index b1cddc4..8e5f801 100644 --- a/internal/routewatch/peeringhandler.go +++ b/internal/routewatch/peeringhandler.go @@ -46,7 +46,7 @@ type PeeringHandler struct { // and the latest time an update carried it. mu sync.Mutex asPaths map[string]database.SeenTimes - droppedPaths int // paths dropped because the map was full + droppedPaths int // paths dropped since the last run because the map was full // writing is how many paths processPeerings took from asPaths and has // not finished writing the peerings of. writing int @@ -190,12 +190,14 @@ func (h *PeeringHandler) processLoop() { func (h *PeeringHandler) processPeerings() { // Take the accumulated paths and replace the map with a fresh empty one // under the lock. Each path is processed exactly once and the memory is - // released, so the map never grows past a single interval's traffic. + // released, so the map never grows past a single interval's traffic. The + // count of dropped paths starts again with the new map. h.mu.Lock() paths := h.asPaths h.asPaths = make(map[string]database.SeenTimes) h.writing = len(paths) dropped := h.droppedPaths + h.droppedPaths = 0 h.mu.Unlock() if len(paths) == 0 { diff --git a/internal/routewatch/peeringhandler_internal_test.go b/internal/routewatch/peeringhandler_internal_test.go index 75bc05a..6cbac03 100644 --- a/internal/routewatch/peeringhandler_internal_test.go +++ b/internal/routewatch/peeringhandler_internal_test.go @@ -264,6 +264,36 @@ func TestPeeringHandlerCapDropsAndCounts(t *testing.T) { } } +// TestPeeringHandlerRunResetsTheDroppedCount fills the map, has the handler +// drop one path, and runs the processing. The count of dropped paths is the +// run's own, so it is 0 again after the run. +func TestPeeringHandlerRunResetsTheDroppedCount(t *testing.T) { + t.Parallel() + + h := newTestHandler(newMockStore()) + + now := time.Now().UTC() + + // Paths of one AS carry no peering, so the run records nothing. + h.mu.Lock() + for asn := 1; len(h.asPaths) < maxTrackedPaths; asn++ { + h.asPaths[pathKey(t, asn)] = database.SeenTimes{First: now, Last: now} + } + h.mu.Unlock() + + handle(h, now, testASNA, testASNB) + + if _, dropped := snapshot(h); dropped != 1 { + t.Fatalf("want dropped count 1 with the map full, got %d", dropped) + } + + h.ProcessPeeringsNow() + + if _, dropped := snapshot(h); dropped != 0 { + t.Errorf("want dropped count 0 after a run, got %d", dropped) + } +} + // TestPeeringHandlerStoresTheEarliestAndLatestTimesOfANewPeering handles two // updates whose path carries a peering the database does not hold yet, the // second 5 seconds after the first, in one run into a real database. The