Fix alert expiry crashbug.

No, the array representation of a binary heap is of course *not* sorted.

Change-Id: Ib18c9b7e1bee24391f98d73135ac19c77026b168
This commit is contained in:
Julius Volz 2014-10-27 23:50:12 +01:00
parent 20b146657b
commit 0642137a11
1 changed files with 15 additions and 20 deletions

View File

@ -15,7 +15,6 @@ package manager
import ( import (
"container/heap" "container/heap"
"sort"
"strings" "strings"
"sync" "sync"
"time" "time"
@ -98,6 +97,15 @@ func (aggs aggregatesByNextNotification) Less(i, j int) bool {
return aggs.AlertAggregates[i].NextNotification.Before(aggs.AlertAggregates[j].NextNotification) return aggs.AlertAggregates[i].NextNotification.Before(aggs.AlertAggregates[j].NextNotification)
} }
// rebuildFrom rebuilds the aggregatesByNextNotification index from a provided
// authoritative AlertAggregates slice.
func (aggs *aggregatesByNextNotification) rebuildFrom(aa AlertAggregates) {
aggs.AlertAggregates = aggs.AlertAggregates[:0]
for _, a := range aa {
aggs.Push(a)
}
}
func (aggs AlertAggregates) Swap(i, j int) { func (aggs AlertAggregates) Swap(i, j int) {
aggs[i], aggs[j] = aggs[j], aggs[i] aggs[i], aggs[j] = aggs[j], aggs[i]
} }
@ -264,36 +272,23 @@ func (s *memoryAlertManager) removeExpiredAggregates() {
// aggregates remain in the heap. // aggregates remain in the heap.
for { for {
if len(s.aggregatesByLastRefreshed.AlertAggregates) == 0 { if len(s.aggregatesByLastRefreshed.AlertAggregates) == 0 {
return break
} }
agg := heap.Pop(&s.aggregatesByLastRefreshed).(*AlertAggregate) agg := heap.Pop(&s.aggregatesByLastRefreshed).(*AlertAggregate)
if time.Since(agg.LastRefreshed) > s.minRefreshInterval { if time.Since(agg.LastRefreshed) > s.minRefreshInterval {
delete(s.aggregates, agg.Alert.Fingerprint()) delete(s.aggregates, agg.Alert.Fingerprint())
// Also remove the aggregate from the last-notification-time index.
n := len(s.aggregatesByNextNotification.AlertAggregates)
i := sort.Search(n, func(i int) bool {
return !agg.NextNotification.After(s.aggregatesByNextNotification.AlertAggregates[i].NextNotification)
})
if i == n {
panic("Missing alert aggregate in aggregatesByNextNotification index")
} else {
for j := i; j < n; j++ {
if s.aggregatesByNextNotification.AlertAggregates[j] == agg {
heap.Remove(&s.aggregatesByNextNotification, j)
break
}
}
}
s.needsNotificationRefresh = true s.needsNotificationRefresh = true
} else { } else {
heap.Push(&s.aggregatesByLastRefreshed, agg) heap.Push(&s.aggregatesByLastRefreshed, agg)
return break
} }
} }
if s.needsNotificationRefresh {
s.aggregatesByNextNotification.rebuildFrom(s.aggregatesByLastRefreshed.AlertAggregates)
}
} }
// Check whether one of the filtered (uninhibited, unsilenced) alerts should // Check whether one of the filtered (uninhibited, unsilenced) alerts should