marsadm: reimplement buggy primitive macros

The old version was complicated and error prone, due to historic
development.

Now the structure should be much simpler.
This commit is contained in:
Thomas Schoebel-Theuer 2016-02-11 20:56:22 +01:00 committed by Thomas Schoebel-Theuer
parent 8c3cfe97f3
commit 83ae4720fa
1 changed files with 95 additions and 79 deletions

View File

@ -719,6 +719,84 @@ sub compare_replaylinks {
##################################################################
sub get_amount {
my ($resdir, $host, $direction, $only_files) = @_;
my $level = 0;
my $firstpos = 0;
my $logpos = 0;
my $oldpos = 0;
my $sum = 0;
for (;;) {
my $val0 = 0;
my $ok = 0;
if (!$level) {
my $replay_path = sprintf("%s/replay-%s", $resdir, $host);
my $replay_link = get_link($replay_path, 1);
return (0, 0, 0, 0) if !$replay_link;
return (0, 0, 0, 0) if $replay_link !~ m:log-([0-9]+)-[^,]+,([0-9]+),([0-9]+):;
$firstpos = int($1);
$logpos = $firstpos;
if ($direction < 0) {
$sum = $2;
} else {
$val0 = $2;
$sum = $3;
}
}
if ($level > 0 || $direction > 0) {
my $file = sprintf("%s/log-%09d-%s", $resdir, $logpos, $host);
my @stat = stat($file);
my $val = 0;
if (@stat) {
$val = $stat[7];
$ok = 1;
} else {
my $glob = sprintf("%s/log-%09d-*", $resdir, $logpos);
foreach $file (glob($glob)) {
my @tstat = stat($file);
if (@tstat && $tstat[7] > $val) {
@stat = @tstat;
$val = $stat[7];
$ok = 1;
}
}
}
if (!$only_files) {
my $glob = sprintf("%s/version-%09d-*", $resdir, $logpos);
foreach $file (glob($glob)) {
my $vers_link = get_link($file, 1);
if ($vers_link && $vers_link =~ m;,([0-9]+):;) {
my $nval = $1;
$val = $nval if $nval > $val;
$ok = 1;
}
}
}
return ($sum, $firstpos, $oldpos, $level) unless $ok;
if ($level > 0) {
$sum += $val;
} else {
# the logfile may be bigger than the replay pos/length
my $new_sum = $val - $val0;
$sum = $new_sum if $new_sum > $sum;
$sum = 0 if $sum < 0;
}
}
$oldpos = $logpos;
if ($direction > 0) {
$logpos++;
} elsif ($direction < 0) {
$logpos--;
return ($sum, $firstpos, $oldpos, $level) if $logpos < 1;
} else {
return ($sum, $firstpos, $oldpos, $level);
}
$level++;
}
}
##################################################################
# versionlink path handling routines
my %visited_pos;
@ -3119,89 +3197,27 @@ sub eval_fn {
my $lnk = $$env{"resdir"} . "/syncstatus-" . $$env{"host"};
return get_link($lnk, 1);
}
if (/^(fetch|replay|work|syncpos)[-_]?(size|pos|lognr|basenr|_internal_)$/) {
if (/^(replay|work)[-_]?(pos|lognr|basenr)$/) {
my $what = $1;
my $op = $2;
my $sum = 0;
my $pos;
# work-* spans both the replay and fetch ranges
if ($what eq "work") {
$what = ($op eq "size") ? "fetch" : "replay";
}
my ($min, $max, $inter_sum) = (0, 0, 0);
if ($op eq "size" || ($what eq "fetch" && $op =~ /nr$/)) {
if ($what eq "replay") { # same as fetch-pos
return eval_fn($env, "fetch-pos", "");
}
my $primary = _get_designated_primary($$env{"res"});
$primary = $host if $primary eq "(none)";
my $replay_base_nr = eval_fn($env, "replay-basenr", "");
my $replay = get_link($$env{"resdir"} . "/replay-$primary", 1);
($pos, my $nr, my $from, $sum) = _parse_pos($$env{"resdir"}, $replay);
my $base_nr = $nr;
$pos = _get_prev_pos($$env{"resdir"}, $nr, $primary);
if ($pos) {
(my $plus, $base_nr) = _mark_path_backward($$env{"resdir"}, $pos, $primary, $replay_base_nr, $host);
$sum += $plus;
}
($min, $max) = get_minmax_versions($$env{"res"}, "-$primary");
my $check_pos = get_link($$env{"resdir"} . "/version-$max-$primary", 1);
$check_pos =~ s{^.*(log-[^:]*):.*$}{$1};
my ($test_pos, $test_nr, $test_from, $test_sum) = _parse_pos($$env{"resdir"}, $check_pos);
$test_pos = _get_prev_pos($$env{"resdir"}, $test_nr, $primary);
my $test_base_nr = $base_nr;
if ($test_pos) {
(my $test_plus, $test_base_nr) = _mark_path_backward($$env{"resdir"}, $test_pos, $primary, $replay_base_nr, $host);
$test_sum += $test_plus;
}
if ($test_sum > $sum) { # take the maximum
($pos, $nr, $from, $sum, $base_nr) = ($test_pos, $test_nr, $test_from, $test_sum, $test_base_nr);
}
return $nr if $op eq "lognr";
return $base_nr if $op eq "basenr";
return $sum;
} elsif ($what eq "fetch") { # fetch-pos
(my $stop_nr, my $stop_sum, $sum) = eval_fn($env, "replay-_internal_", "");
$sum -= $stop_sum;
$sum = 0 if $sum < 0;
# mark all path elements reachable by the designated primary
%visited_pos = ();
eval_fn($env, "fetch-size", "");
foreach my $file (sort(glob($$env{"resdir"} . "/log-*"))) {
$file =~ m:/log-([0-9]+)-(.*): or ldie "bad path '$file'\n";
my $nr = $1;
my $from = $2;
if ($nr < $stop_nr || !_is_visited($nr, $from)) {
next;
}
my @stat = stat($file);
$sum += $stat[7];
}
return $sum;
} elsif ($what =~ m/replay|syncpos/) {
my $replay = get_link($$env{"resdir"} . "/$what-" . $$env{"host"}, $what eq "syncpos" ? 2 : 1);
return 0 unless $replay;
my ($p, $nr, $from, $len) = _parse_pos($$env{"resdir"}, $replay);
return $nr if $op eq "lognr";
$min = $nr;
$sum = $len;
$inter_sum = $sum;
$pos = _get_prev_pos($$env{"resdir"}, $nr, $$env{"host"});
} else {
ldie "unknown combination '$what' '$op'\n";
}
if ($pos) {
my ($plus, $base_nr) = _mark_path_backward($$env{"resdir"}, $pos, $$env{"host"}, 1);
return $base_nr if $op eq "basenr";
$sum += $plus;
}
return $min if $op eq "basenr";
return (make_numeric($min), make_numeric($inter_sum), make_numeric($sum)) if $op eq "_internal_";
my ($sum, $firstpos, $logpos, $level) = get_amount($$env{"resdir"}, $$env{"host"}, -1, 0);
return $firstpos if $op eq "lognr";
return $logpos if $op eq "basenr";
return $sum;
}
if (/^(replay[-_]?size)|(fetch[-_]?pos)$/) {
my ($sum0) = get_amount($$env{"resdir"}, $$env{"host"}, -1, 0);
my ($sum, $firstpos, $logpos, $level) = get_amount($$env{"resdir"}, $$env{"host"}, 1, 1);
return $sum0 + $sum;
}
if (/^(fetch|work)[-_]?(size|lognr)$/) {
my $what = $1;
my $op = $2;
my ($sum0) = get_amount($$env{"resdir"}, $$env{"host"}, -1, 0);
my ($sum, $firstpos, $logpos, $level) = get_amount($$env{"resdir"}, $$env{"host"}, 1, 0);
return $logpos if $op eq "lognr";
return $sum0 + $sum;
}
if (/^(sync|fetch|replay|work)[-_]?(rest|(?:almost[-_]?|threshold[-_]?)?reached|percent|permille|vector)$/) {
my $what = $1;
my $op = $2;