X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FXapcmd.pm;h=106856369c689007470b7ec364796e29079821f6;hb=14fa0abdcc7b6513540e529375e53edd74ce13e8;hp=daef896c37e9a435639505211d7d68e3f74a531f;hpb=76f5361d8b8d2bea828ac66dc98a0de24b761b3d;p=public-inbox.git diff --git a/lib/PublicInbox/Xapcmd.pm b/lib/PublicInbox/Xapcmd.pm index daef896c..10685636 100644 --- a/lib/PublicInbox/Xapcmd.pm +++ b/lib/PublicInbox/Xapcmd.pm @@ -1,8 +1,9 @@ -# Copyright (C) 2018-2021 all contributors +# Copyright (C) all contributors # License: AGPL-3.0+ package PublicInbox::Xapcmd; use strict; -use PublicInbox::Spawn qw(which popen_rd nodatacow_dir); +use PublicInbox::Spawn qw(which popen_rd); +use PublicInbox::Syscall; use PublicInbox::Admin qw(setup_signals); use PublicInbox::Over; use PublicInbox::SearchIdx; @@ -20,16 +21,23 @@ sub commit_changes ($$$$) { my $reshard = $opt->{reshard}; $SIG{INT} or die 'BUG: $SIG{INT} not handled'; - my @old_shard; - my $over_chg; - my $mode; - - while (my ($old, $newdir) = each %$tmp) { + my (@old_shard, $over_chg); + + # Sort shards highest-to-lowest, since ->xdb_shards_flat + # determines the number of shards to load based on the max; + # and we'd rather xdb_shards_flat to momentarily fail rather + # than load out-of-date shards + my @order = sort { + my ($x) = ($a =~ m!/([0-9]+)/*\z!); + my ($y) = ($b =~ m!/([0-9]+)/*\z!); + ($y // -1) <=> ($x // -1) # we may have non-shards + } keys %$tmp; + + my ($dname) = ($order[0] =~ m!(.*/)[^/]+/*\z!); + my $mode = (stat($dname))[2]; + for my $old (@order) { next if $old eq ''; # no invalid paths - $mode //= do { - my ($dname) = ($old =~ m!(.*/)[^/]+/*\z!); - (stat($dname))[2]; - }; + my $newdir = $tmp->{$old}; my $have_old = -e $old; if (!$have_old && !defined($opt->{reshard})) { die "failed to stat($old): $!"; @@ -57,11 +65,7 @@ sub commit_changes ($$$$) { die "rename $old => $new/old: $!\n"; } rename($new, $old) or die "rename $new => $old: $!\n"; - if ($have_old) { - my $prev = "$old/old"; - remove_tree($prev) or - die "failed to remove $prev: $!\n"; - } + push @old_shard, "$old/old" if $have_old; } # trigger ->check_inodes in read-only daemons @@ -208,7 +212,7 @@ sub prepare_run { my $v = PublicInbox::Search::SCHEMA_VERSION(); my $wip = File::Temp->newdir("xapian$v-XXXX", DIR => $dir); $tmp->{$old} = $wip; - nodatacow_dir($wip->dirname); + PublicInbox::Syscall::nodatacow_dir($wip->dirname); push @queue, [ $old, $wip ]; } elsif (defined $old) { opendir my $dh, $old or die "Failed to opendir $old: $!\n"; @@ -239,7 +243,7 @@ sub prepare_run { same_fs_or_die($old, $wip->dirname); my $cur = "$old/$dn"; push @queue, [ $src // $cur , $wip ]; - nodatacow_dir($wip->dirname); + PublicInbox::Syscall::nodatacow_dir($wip->dirname); $tmp->{$cur} = $wip; } # mark old shards to be unlinked @@ -440,7 +444,7 @@ sub cpdb ($$) { # cb_spawn callback $ft = File::Temp->newdir("$new.compact-XXXX", DIR => $dir); setup_signals(); $tmp = $ft->dirname; - nodatacow_dir($tmp); + PublicInbox::Syscall::nodatacow_dir($tmp); } else { $tmp = $new; }