btrbk: cleanup of schedule(): sort by date and date_ext instead of dedicated "sort"

pull/30/head
Axel Burri 2015-04-02 16:24:13 +02:00
parent bf5f74498c
commit d7e9921643
1 changed files with 36 additions and 41 deletions

77
btrbk
View File

@ -888,7 +888,7 @@ sub get_date_tag($)
{ {
my $name = shift; my $name = shift;
$name =~ s/_([0-9]+)$//; $name =~ s/_([0-9]+)$//;
my $postfix_counter = $1; my $postfix_counter = $1 // 0;
my $date = undef; my $date = undef;
if($name =~ /\.([0-9]{4})([0-9]{2})([0-9]{2})$/) { if($name =~ /\.([0-9]{4})([0-9]{2})([0-9]{2})$/) {
$date = [ $1, $2, $3 ]; $date = [ $1, $2, $3 ];
@ -1040,12 +1040,19 @@ sub schedule(@)
INFO "Filter scheme: preserving last weekly of month, for $preserve_monthly months"; INFO "Filter scheme: preserving last weekly of month, for $preserve_monthly months";
} }
# sort the schedule, ascending by date
my @sorted_schedule = sort { ($a->{date}->[0] <=> $b->{date}->[0]) ||
($a->{date}->[1] <=> $b->{date}->[1]) ||
($a->{date}->[2] <=> $b->{date}->[2]) ||
($a->{date_ext} <=> $a->{date_ext})
} @$schedule;
# first, do our calendar calculations # first, do our calendar calculations
# note: our week starts on $preserve_day_of_week # note: our week starts on $preserve_day_of_week
my $delta_days_to_eow_from_today = $day_of_week_map{$preserve_day_of_week} - Day_of_Week(@today) - 1; my $delta_days_to_eow_from_today = $day_of_week_map{$preserve_day_of_week} - Day_of_Week(@today) - 1;
$delta_days_to_eow_from_today = $delta_days_to_eow_from_today + 7 if($delta_days_to_eow_from_today < 0); $delta_days_to_eow_from_today = $delta_days_to_eow_from_today + 7 if($delta_days_to_eow_from_today < 0);
TRACE "last day before next $preserve_day_of_week is in $delta_days_to_eow_from_today days"; TRACE "last day before next $preserve_day_of_week is in $delta_days_to_eow_from_today days";
foreach my $href (@$schedule) foreach my $href (@sorted_schedule)
{ {
my @date = @{$href->{date}}; my @date = @{$href->{date}};
my $delta_days = Delta_Days(@date, @today); my $delta_days = Delta_Days(@date, @today);
@ -1063,7 +1070,7 @@ sub schedule(@)
# filter daily, weekly, monthly # filter daily, weekly, monthly
my %first_in_delta_weeks; my %first_in_delta_weeks;
my %last_weekly_in_delta_months; my %last_weekly_in_delta_months;
foreach my $href (sort { $a->{sort} cmp $b->{sort} } @$schedule) { foreach my $href (@sorted_schedule) {
if($preserve_daily && (($preserve_daily eq "all") || ($href->{delta_days} <= $preserve_daily))) { if($preserve_daily && (($preserve_daily eq "all") || ($href->{delta_days} <= $preserve_daily))) {
$href->{preserve} ||= "preserved daily: $href->{delta_days} days ago"; $href->{preserve} ||= "preserved daily: $href->{delta_days} days ago";
} }
@ -1086,15 +1093,15 @@ sub schedule(@)
# assemble results # assemble results
my @delete; my @delete;
my @preserve; my @preserve;
foreach my $href (sort { $a->{sort} cmp $b->{sort} } @$schedule) foreach my $href (@sorted_schedule)
{ {
if($href->{preserve}) { if($href->{preserve}) {
INFO "=== $href->{sort}: $href->{preserve}" if($log_verbose); INFO "=== $href->{name}: $href->{preserve}" if($href->{name});
push(@preserve, $href->{name}); push(@preserve, $href->{value});
} }
else { else {
INFO "<<< $href->{sort}" if($log_verbose); INFO "<<< $href->{name}" if($href->{name});
push(@delete, $href->{name}); push(@delete, $href->{value});
} }
} }
DEBUG "Preserving " . @preserve . "/" . @$schedule . " items" unless($log_verbose); DEBUG "Preserving " . @preserve . "/" . @$schedule . " items" unless($log_verbose);
@ -1600,16 +1607,15 @@ MAIN:
} }
# resume missing backups (resume_missing) # resume missing backups (resume_missing)
my @schedule;
if(config_key($config_target, "resume_missing")) if(config_key($config_target, "resume_missing"))
{ {
INFO "Checking for missing backups of subvolume \"$sroot/$svol\" in: $droot/"; INFO "Checking for missing backups of subvolume \"$sroot/$svol\" in: $droot/";
my @schedule;
my $found_missing = 0;
# sort children of svol ascending by generation # sort children of svol ascending by generation
foreach my $child (get_snapshot_children($sroot, $svol)) foreach my $child (get_snapshot_children($sroot, $svol))
{ {
DEBUG "Checking for missing receive targets for \"$child->{FS_PATH}\" in: $droot/";
if(scalar get_receive_targets($droot, $child)) { if(scalar get_receive_targets($droot, $child)) {
DEBUG "Found matching receive target, skipping: $child->{FS_PATH}"; DEBUG "Found matching receive target, skipping: $child->{FS_PATH}";
} }
@ -1617,21 +1623,21 @@ MAIN:
DEBUG "No matching receive targets found, adding resume candidate: $child->{FS_PATH}"; DEBUG "No matching receive targets found, adding resume candidate: $child->{FS_PATH}";
# check if the target would be preserved # check if the target would be preserved
my ($date, undef) = get_date_tag($child->{SUBVOL_PATH}); my ($date, $date_ext) = get_date_tag($child->{SUBVOL_PATH});
my $child_vol = $child->{SUBVOL_PATH}; next unless($date && ($child->{SUBVOL_PATH} =~ /^$snapdir$svol\./));
next unless($date && ($child_vol =~ s/^$snapdir$svol\.//)); push(@schedule, { value => $child, date => $date, date_ext => $date_ext }),
push(@schedule, { name => $child, sort => $child_vol, date => $date }),
} }
} }
if(scalar @schedule) if(scalar @schedule)
{ {
DEBUG "Checking schedule for " . @schedule . " candidates"; DEBUG "Checking schedule for resume candidates";
# add all present backups to schedule # add all present backups to schedule, with no value
# these are needed for correct results of schedule()
foreach my $vol (keys %{$vol_info{$droot}}) { foreach my $vol (keys %{$vol_info{$droot}}) {
my ($date, undef) = get_date_tag($vol); my ($date, $date_ext) = get_date_tag($vol);
next unless($date && ($vol =~ s/^$svol\.//)); # use only the date suffix for sorting next unless($date && ($vol =~ s/^$svol\.//)); # use only the date suffix for sorting
push(@schedule, { name => "TARGET", sort => $vol, date => $date }); push(@schedule, { value => undef, date => $date, date_ext => $date_ext });
} }
my ($preserve, undef) = schedule( my ($preserve, undef) = schedule(
@ -1642,12 +1648,12 @@ MAIN:
preserve_weekly => config_key($config_target, "target_preserve_weekly"), preserve_weekly => config_key($config_target, "target_preserve_weekly"),
preserve_monthly => config_key($config_target, "target_preserve_monthly"), preserve_monthly => config_key($config_target, "target_preserve_monthly"),
); );
my @resume = grep ! /TARGET/, @$preserve; # remove target subvolumes from list my @resume = grep defined, @$preserve; # remove entries with no value from list (target subvolumes)
foreach my $child (sort { $a->{node}->{gen} <=> $b->{node}->{gen} } @resume) { foreach my $child (sort { $a->{node}->{gen} <=> $b->{node}->{gen} } @resume) {
my ($latest_common_src, $latest_common_target) = get_latest_common($sroot, $svol, $droot, $child->{node}->{gen});
INFO "Resuming subvolume backup (send-receive) for: $child->{FS_PATH}"; INFO "Resuming subvolume backup (send-receive) for: $child->{FS_PATH}";
$found_missing++;
my ($latest_common_src, $latest_common_target) = get_latest_common($sroot, $svol, $droot, $child->{node}->{gen});
if(macro_send_receive($config_target, if(macro_send_receive($config_target,
src => $child->{FS_PATH}, src => $child->{FS_PATH},
target => $droot, target => $droot,
@ -1665,8 +1671,10 @@ MAIN:
} }
} }
} }
else
{ if($found_missing) {
INFO "Resumed $found_missing backups";
} else {
INFO "No missing backups found"; INFO "No missing backups found";
} }
} }
@ -1724,9 +1732,9 @@ MAIN:
INFO "Cleaning backups of subvolume \"$sroot/$svol\": $droot/$svol.*"; INFO "Cleaning backups of subvolume \"$sroot/$svol\": $droot/$svol.*";
my @schedule; my @schedule;
foreach my $vol (keys %{$vol_info{$droot}}) { foreach my $vol (keys %{$vol_info{$droot}}) {
my ($date, undef) = get_date_tag($vol); my ($date, $date_ext) = get_date_tag($vol);
next unless($date && ($vol =~ /^$svol\./)); next unless($date && ($vol =~ /^$svol\./));
push(@schedule, { name => "$droot/$vol", sort => $vol, date => $date }); push(@schedule, { value => "$droot/$vol", name => $vol, date => $date, date_ext => $date_ext });
} }
my (undef, $delete) = schedule( my (undef, $delete) = schedule(
schedule => \@schedule, schedule => \@schedule,
@ -1746,7 +1754,6 @@ MAIN:
$config_target->{ABORTED} = "btrfs subvolume delete command failed"; $config_target->{ABORTED} = "btrfs subvolume delete command failed";
$target_aborted = 1; $target_aborted = 1;
} }
$config_target->{schedule} = \@schedule;
} }
# #
@ -1759,9 +1766,9 @@ MAIN:
INFO "Cleaning snapshots: $sroot/$snapdir$svol.*"; INFO "Cleaning snapshots: $sroot/$snapdir$svol.*";
my @schedule; my @schedule;
foreach my $vol (keys %{$vol_info{$sroot}}) { foreach my $vol (keys %{$vol_info{$sroot}}) {
my ($date, undef) = get_date_tag($vol); my ($date, $date_ext) = get_date_tag($vol);
next unless($date && ($vol =~ /^$snapdir$svol\./)); next unless($date && ($vol =~ /^$snapdir$svol\./));
push(@schedule, { name => "$sroot/$vol", sort => $vol, date => $date }); push(@schedule, { value => "$sroot/$vol", name => $vol, date => $date, date_ext => $date_ext });
} }
my (undef, $delete) = schedule( my (undef, $delete) = schedule(
schedule => \@schedule, schedule => \@schedule,
@ -1780,7 +1787,6 @@ MAIN:
else { else {
$config_subvol->{ABORTED} = "btrfs subvolume delete command failed"; $config_subvol->{ABORTED} = "btrfs subvolume delete command failed";
} }
$config_subvol->{schedule} = \@schedule;
} }
} }
} }
@ -1818,23 +1824,12 @@ MAIN:
print "!!! Subvolume \"$config_subvol->{svol}\" aborted: $config_subvol->{ABORTED}\n"; print "!!! Subvolume \"$config_subvol->{svol}\" aborted: $config_subvol->{ABORTED}\n";
$err_count++ unless($config_subvol->{ABORTED_NOERR}); $err_count++ unless($config_subvol->{ABORTED_NOERR});
} }
# if($config_subvol->{schedule}) {
# foreach (sort { $a->{sort} cmp $b->{sort} } @{$config_subvol->{schedule}}) {
# print(($_->{preserve} ? "===" : "---") . " $_->{name}\n");
# }
# }
print "+++ $config_subvol->{snapshot}\n" if($config_subvol->{snapshot}); print "+++ $config_subvol->{snapshot}\n" if($config_subvol->{snapshot});
if($config_subvol->{subvol_deleted}) { if($config_subvol->{subvol_deleted}) {
print "--- $_\n" foreach(sort { $b cmp $a} @{$config_subvol->{subvol_deleted}}); print "--- $_\n" foreach(sort { $b cmp $a} @{$config_subvol->{subvol_deleted}});
} }
foreach my $config_target (@{$config_subvol->{TARGET}}) foreach my $config_target (@{$config_subvol->{TARGET}})
{ {
# if($config_target->{schedule}) {
# foreach (sort { $a->{sort} cmp $b->{sort} } @{$config_target->{schedule}}) {
# print(($_->{preserve} ? "===" : "---") . " $_->{name}\n");
# }
# }
foreach(@{$config_target->{subvol_received} // []}) { foreach(@{$config_target->{subvol_received} // []}) {
my $create_mode = "***"; my $create_mode = "***";
$create_mode = ">>>" if($_->{parent}); $create_mode = ">>>" if($_->{parent});