From 3a4e841c7318b861b067c6f5a1bbd21ebb17d4f6 Mon Sep 17 00:00:00 2001 From: Christian Schwarz Date: Sat, 29 Aug 2020 17:29:08 +0200 Subject: [PATCH] [#292] pruning: grid: add all snapshots that do not match the regex to the rule's destroy list Before this patch, multiple grids with disjoint regexes would result in no snapshots being destroyed at all. fixes #292 --- pruning/keep_grid.go | 17 ++++++++++------- pruning/keep_helpers.go | 11 +++++++++++ pruning/pruning_test.go | 22 ++++++++++++++++++++++ 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/pruning/keep_grid.go b/pruning/keep_grid.go index a62c9c9..2dffc07 100644 --- a/pruning/keep_grid.go +++ b/pruning/keep_grid.go @@ -99,17 +99,21 @@ func (a retentionGridAdaptor) LessThan(b retentiongrid.Entry) bool { // Prune filters snapshots with the retention grid. func (p *KeepGrid) KeepRule(snaps []Snapshot) (destroyList []Snapshot) { - snaps = filterSnapList(snaps, func(snapshot Snapshot) bool { + matching, notMatching := partitionSnapList(snaps, func(snapshot Snapshot) bool { return p.re.MatchString(snapshot.Name()) }) - if len(snaps) == 0 { - return nil + + // snaps that don't match the regex are not kept by this rule + destroyList = append(destroyList, notMatching...) + + if len(matching) == 0 { + return destroyList } // Build adaptors for retention grid adaptors := make([]retentiongrid.Entry, 0) - for i := range snaps { - adaptors = append(adaptors, retentionGridAdaptor{snaps[i]}) + for i := range matching { + adaptors = append(adaptors, retentionGridAdaptor{matching[i]}) } // determine 'now' edge @@ -122,9 +126,8 @@ func (p *KeepGrid) KeepRule(snaps []Snapshot) (destroyList []Snapshot) { _, removea := p.retentionGrid.FitEntries(now, adaptors) // Revert adaptors - destroyList = make([]Snapshot, len(removea)) for i := range removea { - destroyList[i] = removea[i].(retentionGridAdaptor).Snapshot + destroyList = append(destroyList, removea[i].(retentionGridAdaptor).Snapshot) } return destroyList } diff --git a/pruning/keep_helpers.go b/pruning/keep_helpers.go index a756ce7..7c31d68 100644 --- a/pruning/keep_helpers.go +++ b/pruning/keep_helpers.go @@ -10,6 +10,17 @@ func filterSnapList(snaps []Snapshot, predicate func(Snapshot) bool) []Snapshot return r } +func partitionSnapList(snaps []Snapshot, predicate func(Snapshot) bool) (sTrue, sFalse []Snapshot) { + for i := range snaps { + if predicate(snaps[i]) { + sTrue = append(sTrue, snaps[i]) + } else { + sFalse = append(sFalse, snaps[i]) + } + } + return +} + func shallowCopySnapList(snaps []Snapshot) []Snapshot { c := make([]Snapshot, len(snaps)) copy(c, snaps) diff --git a/pruning/pruning_test.go b/pruning/pruning_test.go index 0927333..9a33e7a 100644 --- a/pruning/pruning_test.go +++ b/pruning/pruning_test.go @@ -75,6 +75,10 @@ func TestPruneSnapshots(t *testing.T) { }, } + reltime := func(secs int64) time.Time { + return time.Unix(secs, 0) + } + tcs := map[string]testCase{ "simple": { inputs: inputs["s1"], @@ -121,6 +125,24 @@ func TestPruneSnapshots(t *testing.T) { }, expDestroy: map[string]bool{}, }, + "multiple_grids_with_disjoint_regexes": { + inputs: []Snapshot{ + stubSnap{"p1_a", false, reltime(4)}, + stubSnap{"p2_a", false, reltime(5)}, + stubSnap{"p1_b", false, reltime(14)}, + stubSnap{"p2_b", false, reltime(15)}, + stubSnap{"p1_c", false, reltime(29)}, + stubSnap{"p2_c", false, reltime(30)}, + }, + rules: []KeepRule{ + MustNewKeepGrid("^p1_", `1x10s | 1x10s`), + MustNewKeepGrid("^p2_", `1x10s | 1x10s`), + }, + expDestroy: map[string]bool{ + "p1_a": true, + "p2_a": true, + }, + }, } testTable(tcs, t)