forked from TrueCloudLab/restic
Merge pull request #4366 from gautammenghani/master
Issue #3624: Preserve oldest snapshot when keep-* values are not sati…
This commit is contained in:
commit
9cbc2502c6
6 changed files with 83 additions and 2 deletions
9
changelog/unreleased/issue-3624
Normal file
9
changelog/unreleased/issue-3624
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
Enhancement: Keep oldest snapshot when there are not enough snapshots
|
||||||
|
|
||||||
|
The `forget` command now additionally preserves the oldest snapshot if fewer
|
||||||
|
snapshots are kept than allowed by the `--keep-*` parameters. This maximizes
|
||||||
|
amount of history kept while the specified limits are not yet reached.
|
||||||
|
|
||||||
|
https://github.com/restic/restic/issues/3624
|
||||||
|
https://github.com/restic/restic/pull/4366
|
||||||
|
https://forum.restic.net/t/keeping-yearly-snapshots-policy-when-backup-began-during-the-year/4670/2
|
|
@ -183,6 +183,7 @@ type KeepReason struct {
|
||||||
// according to the policy p. list is sorted in the process. reasons contains
|
// according to the policy p. list is sorted in the process. reasons contains
|
||||||
// the reasons to keep each snapshot, it is in the same order as keep.
|
// the reasons to keep each snapshot, it is in the same order as keep.
|
||||||
func ApplyPolicy(list Snapshots, p ExpirePolicy) (keep, remove Snapshots, reasons []KeepReason) {
|
func ApplyPolicy(list Snapshots, p ExpirePolicy) (keep, remove Snapshots, reasons []KeepReason) {
|
||||||
|
// sort newest snapshots first
|
||||||
sort.Stable(list)
|
sort.Stable(list)
|
||||||
|
|
||||||
if p.Empty() {
|
if p.Empty() {
|
||||||
|
@ -256,7 +257,9 @@ func ApplyPolicy(list Snapshots, p ExpirePolicy) (keep, remove Snapshots, reason
|
||||||
// -1 means "keep all"
|
// -1 means "keep all"
|
||||||
if b.Count > 0 || b.Count == -1 {
|
if b.Count > 0 || b.Count == -1 {
|
||||||
val := b.bucker(cur.Time, nr)
|
val := b.bucker(cur.Time, nr)
|
||||||
if val != b.Last {
|
// also keep the oldest snapshot if the bucket has some counts left. This maximizes the
|
||||||
|
// the history length kept while some counts are left.
|
||||||
|
if val != b.Last || nr == len(list)-1 {
|
||||||
debug.Log("keep %v %v, bucker %v, val %v\n", cur.Time, cur.id.Str(), i, val)
|
debug.Log("keep %v %v, bucker %v, val %v\n", cur.Time, cur.id.Str(), i, val)
|
||||||
keepSnap = true
|
keepSnap = true
|
||||||
buckets[i].Last = val
|
buckets[i].Last = val
|
||||||
|
@ -275,7 +278,7 @@ func ApplyPolicy(list Snapshots, p ExpirePolicy) (keep, remove Snapshots, reason
|
||||||
|
|
||||||
if cur.Time.After(t) {
|
if cur.Time.After(t) {
|
||||||
val := b.bucker(cur.Time, nr)
|
val := b.bucker(cur.Time, nr)
|
||||||
if val != b.Last {
|
if val != b.Last || nr == len(list)-1 {
|
||||||
debug.Log("keep %v, time %v, ID %v, bucker %v, val %v %v\n", b.reason, cur.Time, cur.id.Str(), i, val, b.Last)
|
debug.Log("keep %v, time %v, ID %v, bucker %v, val %v %v\n", b.reason, cur.Time, cur.id.Str(), i, val, b.Last)
|
||||||
keepSnap = true
|
keepSnap = true
|
||||||
bucketsWithin[i].Last = val
|
bucketsWithin[i].Last = val
|
||||||
|
|
|
@ -14,6 +14,11 @@
|
||||||
"time": "2014-11-22T10:20:30Z",
|
"time": "2014-11-22T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "2014-08-08T10:20:30Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"reasons": [
|
"reasons": [
|
||||||
|
@ -55,6 +60,19 @@
|
||||||
"counters": {
|
"counters": {
|
||||||
"yearly": 7
|
"yearly": 7
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"snapshot": {
|
||||||
|
"time": "2014-08-08T10:20:30Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": null
|
||||||
|
},
|
||||||
|
"matches": [
|
||||||
|
"yearly snapshot"
|
||||||
|
],
|
||||||
|
"counters": {
|
||||||
|
"yearly": 6
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -49,6 +49,11 @@
|
||||||
"time": "2014-11-22T10:20:30Z",
|
"time": "2014-11-22T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "2014-08-08T10:20:30Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"reasons": [
|
"reasons": [
|
||||||
|
@ -201,6 +206,19 @@
|
||||||
"counters": {
|
"counters": {
|
||||||
"yearly": 7
|
"yearly": 7
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"snapshot": {
|
||||||
|
"time": "2014-08-08T10:20:30Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": null
|
||||||
|
},
|
||||||
|
"matches": [
|
||||||
|
"yearly snapshot"
|
||||||
|
],
|
||||||
|
"counters": {
|
||||||
|
"yearly": 6
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -44,6 +44,11 @@
|
||||||
"time": "2014-11-22T10:20:30Z",
|
"time": "2014-11-22T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "2014-08-08T10:20:30Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"reasons": [
|
"reasons": [
|
||||||
|
@ -152,6 +157,17 @@
|
||||||
"yearly within 9999y"
|
"yearly within 9999y"
|
||||||
],
|
],
|
||||||
"counters": {}
|
"counters": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"snapshot": {
|
||||||
|
"time": "2014-08-08T10:20:30Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": null
|
||||||
|
},
|
||||||
|
"matches": [
|
||||||
|
"yearly within 9999y"
|
||||||
|
],
|
||||||
|
"counters": {}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -57,6 +57,11 @@
|
||||||
"time": "2014-08-22T10:20:30Z",
|
"time": "2014-08-22T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "2014-08-08T10:20:30Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"reasons": [
|
"reasons": [
|
||||||
|
@ -189,6 +194,18 @@
|
||||||
"monthly snapshot"
|
"monthly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Monthly": -1, "Yearly": -1}
|
"counters": {"Monthly": -1, "Yearly": -1}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"snapshot": {
|
||||||
|
"time": "2014-08-08T10:20:30Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": null
|
||||||
|
},
|
||||||
|
"matches": [
|
||||||
|
"monthly snapshot",
|
||||||
|
"yearly snapshot"
|
||||||
|
],
|
||||||
|
"counters": {"Monthly": -1, "Yearly": -1}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
Loading…
Reference in a new issue