btrbk: bugfix: correct scheduling of "first weekly backup in month/year"

In the scheduler, a month (or year) does not start at the first day,
but at the first `preserve_day_of_week`. Make sure that all days
before `preserve_day_of_week` in a month get delta_months+1.

Example (corner case):
  - `preserve_day_of_week  sunday`
  - `target_preserve  *m`
  - no backups in 2018-02
  - backup with timestamp 2018-03-01 (which is a thursday)
  - backup with timestamp 2018-03-04 (which is a sunday)

Without this patch, because there are no sunday backups in 2018-02,
the first backup is considered a weekly (+4d after sunday), and as
such "first weekly of month 2018-03", and the second one is discarded.

With this patch, the first item is considered "first weekly of month
2018-02", and the second gets "first weekly of month 2018-03".

NOTE: This change may result in (previously preserved) backups to be
deleted!
pull/219/head
Axel Burri 2018-04-05 16:42:26 +02:00
parent e9c30e91fb
commit 719fb5fb74
2 changed files with 20 additions and 5 deletions

View File

@ -1,6 +1,9 @@
btrbk-0.27.0-dev
* Add "preserve_hour_of_day" configuration option (close #202).
* Bugfix: correct scheduling of "first weekly backup in month/year"
(close #217). Note that this change may result in (previously
preserved) backups to be deleted!
btrbk-0.26.1

22
btrbk
View File

@ -3746,7 +3746,9 @@ sub schedule(@)
# first, do our calendar calculations
# - days start on $preserve_hour_of_day (or 00:00 if timestamp_format=short)
# - weeks start on $preserve_day_of_week
# - leap hours are NOT taken into account for $delta_hours
# - months start on first $preserve_day_of_week of month
# - years start on first $preserve_day_of_week of year
# NOTE: leap hours are NOT taken into account for $delta_hours
my $now_h = timegm_nocheck( 0, 0, $tm_now[2], $tm_now[3], $tm_now[4], $tm_now[5] ); # use timelocal() here (and below) if you want to honor leap hours
foreach my $href (@sorted_schedule)
@ -3762,13 +3764,23 @@ sub schedule(@)
if($delta_days_from_eow < 0) {
$delta_days_from_eow += 7;
}
my $month_corr = $tm[4]; # [0..11]
my $year_corr = $tm[5];
if($tm[3] <= $delta_days_from_eow) {
# our month/year start on first $preserve_day_of_week, corrected value
$month_corr -= 1;
if($month_corr < 0) {
$month_corr = 11;
$year_corr -= 1;
}
}
# check timegm: ignores leap hours
my $delta_hours = int(($now_h - timegm_nocheck( 0, 0, $tm[2], $tm[3], $tm[4], $tm[5] ) ) / (60 * 60));
my $delta_days = int(($delta_hours + $delta_hours_from_hod) / 24); # days from beginning of day
my $delta_weeks = int(($delta_days + $delta_days_from_eow) / 7); # weeks from beginning of week
my $delta_years = ($tm_now[5] - $tm[5]);
my $delta_months = $delta_years * 12 + ($tm_now[4] - $tm[4]);
my $delta_years = ($tm_now[5] - $year_corr);
my $delta_months = $delta_years * 12 + ($tm_now[4] - $month_corr);
$href->{delta_hours} = $delta_hours;
$href->{delta_days} = $delta_days;
@ -3777,8 +3789,8 @@ sub schedule(@)
$href->{delta_years} = $delta_years;
# these are only needed for text output (format_preserve_delta)
$href->{year} = $tm[5] + 1900;
$href->{month} = $tm[4] + 1;
$href->{year} = $year_corr + 1900;
$href->{month} = $month_corr + 1;
$href->{delta_hours_from_hod} = $delta_hours_from_hod;
$href->{delta_days_from_eow} = $delta_days_from_eow;
$href->{real_hod} = $preserve_hour_of_day if($has_exact_time);