From b29747de93fb70d3a7a6f843e232d3dec747451e Mon Sep 17 00:00:00 2001 From: Asim R P Date: Fri, 20 Sep 2019 17:31:25 +0530 Subject: [PATCH v10 1/4] Support node initialization from backup with tablespaces User defined tablespaces appear as symlinks in in the backup. This commit tweaks recursive copy subroutine to allow for symlinks specific to tablespaces. Authored by Kyotaro Horiguchi --- src/test/perl/PostgresNode.pm | 29 ++++++++++++++++++++++++++++- src/test/perl/RecursiveCopy.pm | 40 +++++++++++++++++++++++++++++++++------- 2 files changed, 61 insertions(+), 8 deletions(-) diff --git a/src/test/perl/PostgresNode.pm b/src/test/perl/PostgresNode.pm index 1407359aef6..e1ddb36ff1d 100644 --- a/src/test/perl/PostgresNode.pm +++ b/src/test/perl/PostgresNode.pm @@ -593,6 +593,32 @@ sub backup_fs_cold return; } +sub _srcsymlink +{ + my ($srcpath, $destpath) = @_; + + croak "Cannot operate on symlink \"$srcpath\"" + if ($srcpath !~ qr{/(pg_tblspc/[0-9]+)$}); + + # We have mapped tablespaces. Copy them individually + my $tmpdir = TestLib::tempdir; + my $dstrealdir = TestLib::perl2host($tmpdir); + my $srcrealdir = readlink($srcpath); + + opendir(my $dh, $srcrealdir); + while (my $entry = (readdir $dh)) + { + next if ($entry eq '.' or $entry eq '..'); + my $spath = "$srcrealdir/$entry"; + my $dpath = "$dstrealdir/$entry"; + RecursiveCopy::copypath($spath, $dpath); + } + closedir $dh; + + symlink $dstrealdir, $destpath; + + return 1; +} # Common sub of backup_fs_hot and backup_fs_cold sub _backup_fs @@ -684,7 +710,8 @@ sub init_from_backup my $data_path = $self->data_dir; rmdir($data_path); - RecursiveCopy::copypath($backup_path, $data_path); + RecursiveCopy::copypath($backup_path, $data_path, + srcsymlinkfn => \&_srcsymlink); chmod(0700, $data_path); # Base configuration for this node diff --git a/src/test/perl/RecursiveCopy.pm b/src/test/perl/RecursiveCopy.pm index baf5d0ac63b..715edcdedd0 100644 --- a/src/test/perl/RecursiveCopy.pm +++ b/src/test/perl/RecursiveCopy.pm @@ -66,6 +66,7 @@ sub copypath { my ($base_src_dir, $base_dest_dir, %params) = @_; my $filterfn; + my $srcsymlinkfn; if (defined $params{filterfn}) { @@ -80,31 +81,55 @@ sub copypath $filterfn = sub { return 1; }; } + if (defined $params{srcsymlinkfn}) + { + croak "if specified, srcsymlinkfn must be a subroutine reference" + unless defined(ref $params{srcsymlinkfn}) + and (ref $params{srcsymlinkfn} eq 'CODE'); + + $srcsymlinkfn = $params{srcsymlinkfn}; + } + else + { + $srcsymlinkfn = undef; + } + # Complain if original path is bogus, because _copypath_recurse won't. croak "\"$base_src_dir\" does not exist" if !-e $base_src_dir; # Start recursive copy from current directory - return _copypath_recurse($base_src_dir, $base_dest_dir, "", $filterfn); + return _copypath_recurse($base_src_dir, $base_dest_dir, "", $filterfn, $srcsymlinkfn); } # Recursive private guts of copypath sub _copypath_recurse { - my ($base_src_dir, $base_dest_dir, $curr_path, $filterfn) = @_; + my ($base_src_dir, $base_dest_dir, $curr_path, $filterfn, + $srcsymlinkfn) = @_; my $srcpath = "$base_src_dir/$curr_path"; my $destpath = "$base_dest_dir/$curr_path"; # invoke the filter and skip all further operation if it returns false return 1 unless &$filterfn($curr_path); - # Check for symlink -- needed only on source dir - # (note: this will fall through quietly if file is already gone) - croak "Cannot operate on symlink \"$srcpath\"" if -l $srcpath; - # Abort if destination path already exists. Should we allow directories # to exist already? croak "Destination path \"$destpath\" already exists" if -e $destpath; + # Check for symlink -- needed only on source dir + # If caller provided us with a callback, call it; otherwise we're out. + if (-l $srcpath) + { + if (defined $srcsymlinkfn) + { + return &$srcsymlinkfn($srcpath, $destpath); + } + else + { + croak "Cannot operate on symlink \"$srcpath\""; + } + } + # If this source path is a file, simply copy it to destination with the # same name and we're done. if (-f $srcpath) @@ -137,7 +162,8 @@ sub _copypath_recurse { next if ($entry eq '.' or $entry eq '..'); _copypath_recurse($base_src_dir, $base_dest_dir, - $curr_path eq '' ? $entry : "$curr_path/$entry", $filterfn) + $curr_path eq '' ? $entry : "$curr_path/$entry", $filterfn, + $srcsymlinkfn) or die "copypath $srcpath/$entry -> $destpath/$entry failed"; } -- 2.14.3