diff options
author | Robert Haas <rhaas@postgresql.org> | 2024-04-17 15:56:33 -0400 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2024-04-19 13:08:03 -0400 |
commit | 6bf5c42b5546984df29289918f952e6211069c54 (patch) | |
tree | 1314b11ac2e6395aa4ee80fdcc97424b26ebd166 /src/test/perl/PostgreSQL/Test/Cluster.pm | |
parent | 41d2c6f952edc4841763d05296b65f3c0edad4f2 (diff) | |
download | postgresql-6bf5c42b5546984df29289918f952e6211069c54.tar.gz postgresql-6bf5c42b5546984df29289918f952e6211069c54.zip |
Make PostgreSQL::Test::Cluster::init_from_backup handle tablespaces.
This commit doesn't use this infrastructure for anything new, although
it does adapt 010_pg_basebackup.pl to use it. However, a future commit
will use this to improve test coverage for pg_combinebackup.
Patch by me, reviewed (but not fully endorsed) by Andres Freund.
Discussion: http://postgr.es/m/CA+TgmoYdXTjo9iQeoipTccDpWZzvBNS6EndY2uARM+T4yG_yDg@mail.gmail.com
Diffstat (limited to 'src/test/perl/PostgreSQL/Test/Cluster.pm')
-rw-r--r-- | src/test/perl/PostgreSQL/Test/Cluster.pm | 93 |
1 files changed, 86 insertions, 7 deletions
diff --git a/src/test/perl/PostgreSQL/Test/Cluster.pm b/src/test/perl/PostgreSQL/Test/Cluster.pm index 9b2879c145c..52972a97465 100644 --- a/src/test/perl/PostgreSQL/Test/Cluster.pm +++ b/src/test/perl/PostgreSQL/Test/Cluster.pm @@ -777,7 +777,7 @@ sub backup_fs_cold =pod -=item $node->init_from_backup(root_node, backup_name) +=item $node->init_from_backup(root_node, backup_name, %params) Initialize a node from a backup, which may come from this node or a different node. root_node must be a PostgreSQL::Test::Cluster reference, backup_name the string name @@ -787,8 +787,13 @@ Does not start the node after initializing it. By default, the backup is assumed to be plain format. To restore from a tar-format backup, pass the name of the tar program to use in the -keyword parameter tar_program. Note that tablespace tar files aren't -handled here. +keyword parameter tar_program. + +If there are tablespace present in the backup, include tablespace_map as +a keyword parameter whose values is a hash. When tar_program is used, the +hash keys are tablespace OIDs; otherwise, they are the tablespace pathnames +used in the backup. In either case, the values are the tablespace pathnames +that should be used for the target cluster. To restore from an incremental backup, pass the parameter combine_with_prior as a reference to an array of prior backup names with which this backup @@ -843,12 +848,20 @@ sub init_from_backup } local %ENV = $self->_get_env(); - PostgreSQL::Test::Utils::system_or_bail('pg_combinebackup', '-d', - @prior_backup_path, $backup_path, '-o', $data_path); + my @combineargs = ('pg_combinebackup', '-d'); + if (exists $params{tablespace_map}) + { + while (my ($olddir, $newdir) = each %{$params{tablespace_map}}) + { + push @combineargs, "-T$olddir=$newdir"; + } + } + push @combineargs, @prior_backup_path, $backup_path, '-o', $data_path; + PostgreSQL::Test::Utils::system_or_bail(@combineargs); } elsif (defined $params{tar_program}) { - mkdir($data_path); + mkdir($data_path) || die "mkdir $data_path: $!"; PostgreSQL::Test::Utils::system_or_bail($params{tar_program}, 'xf', $backup_path . '/base.tar', '-C', $data_path); @@ -856,11 +869,77 @@ sub init_from_backup $params{tar_program}, 'xf', $backup_path . '/pg_wal.tar', '-C', $data_path . '/pg_wal'); + + # We need to generate a tablespace_map file. + open(my $tsmap, ">", "$data_path/tablespace_map") + || die "$data_path/tablespace_map: $!"; + + # Extract tarfiles and add tablespace_map entries + my @tstars = grep { /^\d+.tar/ } + PostgreSQL::Test::Utils::slurp_dir($backup_path); + for my $tstar (@tstars) + { + my $tsoid = $tstar; + $tsoid =~ s/\.tar$//; + + die "no tablespace mapping for $tstar" + if !exists $params{tablespace_map} || + !exists $params{tablespace_map}{$tsoid}; + my $newdir = $params{tablespace_map}{$tsoid}; + + mkdir($newdir) || die "mkdir $newdir: $!"; + PostgreSQL::Test::Utils::system_or_bail($params{tar_program}, 'xf', + $backup_path . '/' . $tstar, '-C', $newdir); + + my $escaped_newdir = $newdir; + $escaped_newdir =~ s/\\/\\\\/g; + print $tsmap "$tsoid $escaped_newdir\n"; + } + + # Close tablespace_map. + close($tsmap); } else { + my @tsoids; rmdir($data_path); - PostgreSQL::Test::RecursiveCopy::copypath($backup_path, $data_path); + + # Copy the main backup. Exclude tablespace links, but remember them. + PostgreSQL::Test::RecursiveCopy::copypath($backup_path, $data_path, + 'filterfn' => sub { + my ($path) = @_; + if ($path =~ /^pg_tblspc\/(\d+)$/ && -l "$backup_path/$path") + { + push @tsoids, $1; + return 0; + } + return 1; + }); + + # We need to generate a tablespace_map file. + open(my $tsmap, ">", "$data_path/tablespace_map") + || die "$data_path/tablespace_map: $!"; + + # Now use the list of tablespace links to copy each tablespace. + for my $tsoid (@tsoids) + { + my $olddir = readlink("$backup_path/pg_tblspc/$tsoid") + || die "readlink $backup_path/pg_tblspc/$tsoid: $!"; + + die "no tablespace mapping for $olddir" + if !exists $params{tablespace_map} || + !exists $params{tablespace_map}{$olddir}; + + my $newdir = $params{tablespace_map}{$olddir}; + PostgreSQL::Test::RecursiveCopy::copypath($olddir, $newdir); + + my $escaped_newdir = $newdir; + $escaped_newdir =~ s/\\/\\\\/g; + print $tsmap "$tsoid $escaped_newdir\n"; + } + + # Close tablespace_map. + close($tsmap); } chmod(0700, $data_path) or die $!; |