Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 89ad3e1

Browse files
committed
Try again to add test coverage for pg_combinebackup w/tablespaces.
My previous attempt to add this had to be reverted in commit 82023d4. I've revised the problematic code a bit; hopefully it is OK now. Discussion: http://postgr.es/m/CA+Tgmobiv1QJR5PEJoDKeZDrJHZFRmi4XmWOqufN49DJj-3e2g@mail.gmail.com
1 parent ba3e6e2 commit 89ad3e1

File tree

3 files changed

+126
-28
lines changed

3 files changed

+126
-28
lines changed

src/bin/pg_basebackup/t/010_pg_basebackup.pl

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -407,25 +407,12 @@
407407

408408
my $node2 = PostgreSQL::Test::Cluster->new('replica');
409409

410-
# Recover main data directory
411-
$node2->init_from_backup($node, 'tarbackup2', tar_program => $tar);
412-
413-
# Recover tablespace into a new directory (not where it was!)
414-
my $repTsDir = "$tempdir/tblspc1replica";
415-
my $realRepTsDir = "$real_sys_tempdir/tblspc1replica";
416-
mkdir $repTsDir;
417-
PostgreSQL::Test::Utils::system_or_bail($tar, 'xf', $tblspc_tars[0],
418-
'-C', $repTsDir);
419-
420-
# Update tablespace map to point to new directory.
421-
# XXX Ideally pg_basebackup would handle this.
410+
# Recover the backup
422411
$tblspc_tars[0] =~ m|/([0-9]*)\.tar$|;
423412
my $tblspcoid = $1;
424-
my $escapedRepTsDir = $realRepTsDir;
425-
$escapedRepTsDir =~ s/\\/\\\\/g;
426-
open my $mapfile, '>', $node2->data_dir . '/tablespace_map' or die $!;
427-
print $mapfile "$tblspcoid $escapedRepTsDir\n";
428-
close $mapfile;
413+
my $realRepTsDir = "$real_sys_tempdir/tblspc1replica";
414+
$node2->init_from_backup($node, 'tarbackup2', tar_program => $tar,
415+
'tablespace_map' => { $tblspcoid => $realRepTsDir });
429416

430417
$node2->start;
431418
my $result = $node2->safe_psql('postgres', 'SELECT * FROM test1');

src/bin/pg_combinebackup/t/002_compare_backups.pl

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,15 @@
77
use PostgreSQL::Test::Utils;
88
use Test::More;
99

10+
my $tempdir = PostgreSQL::Test::Utils::tempdir_short();
11+
1012
# Set up a new database instance.
1113
my $primary = PostgreSQL::Test::Cluster->new('primary');
1214
$primary->init(has_archiving => 1, allows_streaming => 1);
1315
$primary->append_conf('postgresql.conf', 'summarize_wal = on');
1416
$primary->start;
17+
my $tsprimary = $tempdir . '/ts';
18+
mkdir($tsprimary) || die "mkdir $tsprimary: $!";
1519

1620
# Create some test tables, each containing one row of data, plus a whole
1721
# extra database.
@@ -29,33 +33,54 @@
2933
CREATE TABLE will_get_rewritten (a int, b text);
3034
INSERT INTO will_get_rewritten VALUES (1, 'initial test row');
3135
CREATE DATABASE db_will_get_dropped;
36+
CREATE TABLESPACE ts1 LOCATION '$tsprimary';
37+
CREATE TABLE will_not_change_in_ts (a int, b text) TABLESPACE ts1;
38+
INSERT INTO will_not_change_in_ts VALUES (1, 'initial test row');
39+
CREATE TABLE will_change_in_ts (a int, b text) TABLESPACE ts1;
40+
INSERT INTO will_change_in_ts VALUES (1, 'initial test row');
41+
CREATE TABLE will_get_dropped_in_ts (a int, b text);
42+
INSERT INTO will_get_dropped_in_ts VALUES (1, 'initial test row');
3243
EOM
3344

45+
# Read list of tablespace OIDs. There should be just one.
46+
my @tsoids = grep { /^\d+/ } slurp_dir($primary->data_dir . '/pg_tblspc');
47+
is(0+@tsoids, 1, "exactly one user-defined tablespace");
48+
my $tsoid = $tsoids[0];
49+
3450
# Take a full backup.
3551
my $backup1path = $primary->backup_dir . '/backup1';
52+
my $tsbackup1path = $tempdir . '/ts1backup';
53+
mkdir($tsbackup1path) || die "mkdir $tsbackup1path: $!";
3654
$primary->command_ok(
37-
[ 'pg_basebackup', '-D', $backup1path, '--no-sync', '-cfast' ],
38-
"full backup");
55+
[ 'pg_basebackup', '-D', $backup1path, '--no-sync', '-cfast',
56+
"-T${tsprimary}=${tsbackup1path}" ], "full backup");
3957

4058
# Now make some database changes.
4159
$primary->safe_psql('postgres', <<EOM);
4260
UPDATE will_change SET b = 'modified value' WHERE a = 1;
61+
UPDATE will_change_in_ts SET b = 'modified value' WHERE a = 1;
4362
INSERT INTO will_grow
4463
SELECT g, 'additional row' FROM generate_series(2, 5000) g;
4564
TRUNCATE will_shrink;
4665
VACUUM will_get_vacuumed;
4766
DROP TABLE will_get_dropped;
67+
DROP TABLE will_get_dropped_in_ts;
4868
CREATE TABLE newly_created (a int, b text);
4969
INSERT INTO newly_created VALUES (1, 'row for new table');
70+
CREATE TABLE newly_created_in_ts (a int, b text) TABLESPACE ts1;
71+
INSERT INTO newly_created_in_ts VALUES (1, 'row for new table');
5072
VACUUM FULL will_get_rewritten;
5173
DROP DATABASE db_will_get_dropped;
5274
CREATE DATABASE db_newly_created;
5375
EOM
5476

5577
# Take an incremental backup.
5678
my $backup2path = $primary->backup_dir . '/backup2';
79+
my $tsbackup2path = $tempdir . '/tsbackup2';
80+
mkdir($tsbackup2path) || die "mkdir $tsbackup2path: $!";
5781
$primary->command_ok(
5882
[ 'pg_basebackup', '-D', $backup2path, '--no-sync', '-cfast',
83+
"-T${tsprimary}=${tsbackup2path}",
5984
'--incremental', $backup1path . '/backup_manifest' ],
6085
"incremental backup");
6186

@@ -78,9 +103,11 @@
78103
# Perform PITR from the full backup. Disable archive_mode so that the archive
79104
# doesn't find out about the new timeline; that way, the later PITR below will
80105
# choose the same timeline.
106+
my $tspitr1path = $tempdir . '/tspitr1';
81107
my $pitr1 = PostgreSQL::Test::Cluster->new('pitr1');
82108
$pitr1->init_from_backup($primary, 'backup1',
83-
standby => 1, has_restoring => 1);
109+
standby => 1, has_restoring => 1,
110+
tablespace_map => { $tsoid => $tspitr1path });
84111
$pitr1->append_conf('postgresql.conf', qq{
85112
recovery_target_lsn = '$lsn'
86113
recovery_target_action = 'promote'
@@ -90,10 +117,12 @@
90117

91118
# Perform PITR to the same LSN from the incremental backup. Use the same
92119
# basic configuration as before.
120+
my $tspitr2path = $tempdir . '/tspitr2';
93121
my $pitr2 = PostgreSQL::Test::Cluster->new('pitr2');
94122
$pitr2->init_from_backup($primary, 'backup2',
95123
standby => 1, has_restoring => 1,
96-
combine_with_prior => [ 'backup1' ]);
124+
combine_with_prior => [ 'backup1' ],
125+
tablespace_map => { $tsbackup2path => $tspitr2path });
97126
$pitr2->append_conf('postgresql.conf', qq{
98127
recovery_target_lsn = '$lsn'
99128
recovery_target_action = 'promote'

src/test/perl/PostgreSQL/Test/Cluster.pm

Lines changed: 89 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,7 @@ sub backup_fs_cold
777777

778778
=pod
779779
780-
=item $node->init_from_backup(root_node, backup_name)
780+
=item $node->init_from_backup(root_node, backup_name, %params)
781781
782782
Initialize a node from a backup, which may come from this node or a different
783783
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.
787787
788788
By default, the backup is assumed to be plain format. To restore from
789789
a tar-format backup, pass the name of the tar program to use in the
790-
keyword parameter tar_program. Note that tablespace tar files aren't
791-
handled here.
790+
keyword parameter tar_program.
791+
792+
If there are tablespace present in the backup, include tablespace_map as
793+
a keyword parameter whose values is a hash. When combine_with_prior is used,
794+
the hash keys are the tablespace pathnames used in the backup; otherwise,
795+
they are tablespace OIDs. In either case, the values are the tablespace
796+
pathnames that should be used for the target cluster.
792797
793798
To restore from an incremental backup, pass the parameter combine_with_prior
794799
as a reference to an array of prior backup names with which this backup
@@ -843,24 +848,101 @@ sub init_from_backup
843848
}
844849

845850
local %ENV = $self->_get_env();
846-
PostgreSQL::Test::Utils::system_or_bail('pg_combinebackup', '-d',
847-
@prior_backup_path, $backup_path, '-o', $data_path);
851+
my @combineargs = ('pg_combinebackup', '-d');
852+
if (exists $params{tablespace_map})
853+
{
854+
while (my ($olddir, $newdir) = each %{$params{tablespace_map}})
855+
{
856+
push @combineargs, "-T$olddir=$newdir";
857+
}
858+
}
859+
push @combineargs, @prior_backup_path, $backup_path, '-o', $data_path;
860+
PostgreSQL::Test::Utils::system_or_bail(@combineargs);
848861
}
849862
elsif (defined $params{tar_program})
850863
{
851-
mkdir($data_path);
864+
mkdir($data_path) || die "mkdir $data_path: $!";
852865
PostgreSQL::Test::Utils::system_or_bail($params{tar_program}, 'xf',
853866
$backup_path . '/base.tar',
854867
'-C', $data_path);
855868
PostgreSQL::Test::Utils::system_or_bail(
856869
$params{tar_program}, 'xf',
857870
$backup_path . '/pg_wal.tar', '-C',
858871
$data_path . '/pg_wal');
872+
873+
# We need to generate a tablespace_map file.
874+
open(my $tsmap, ">", "$data_path/tablespace_map")
875+
|| die "$data_path/tablespace_map: $!";
876+
877+
# Extract tarfiles and add tablespace_map entries
878+
my @tstars = grep { /^\d+.tar/ }
879+
PostgreSQL::Test::Utils::slurp_dir($backup_path);
880+
for my $tstar (@tstars)
881+
{
882+
my $tsoid = $tstar;
883+
$tsoid =~ s/\.tar$//;
884+
885+
die "no tablespace mapping for $tstar"
886+
if !exists $params{tablespace_map} ||
887+
!exists $params{tablespace_map}{$tsoid};
888+
my $newdir = $params{tablespace_map}{$tsoid};
889+
890+
mkdir($newdir) || die "mkdir $newdir: $!";
891+
PostgreSQL::Test::Utils::system_or_bail($params{tar_program}, 'xf',
892+
$backup_path . '/' . $tstar, '-C', $newdir);
893+
894+
my $escaped_newdir = $newdir;
895+
$escaped_newdir =~ s/\\/\\\\/g;
896+
print $tsmap "$tsoid $escaped_newdir\n";
897+
}
898+
899+
# Close tablespace_map.
900+
close($tsmap);
859901
}
860902
else
861903
{
904+
my @tsoids;
862905
rmdir($data_path);
863-
PostgreSQL::Test::RecursiveCopy::copypath($backup_path, $data_path);
906+
907+
# Copy the main backup. If we see a tablespace directory for which we
908+
# have a tablespace mapping, skip it, but remember that we saw it.
909+
PostgreSQL::Test::RecursiveCopy::copypath($backup_path, $data_path,
910+
'filterfn' => sub {
911+
my ($path) = @_;
912+
if ($path =~ /^pg_tblspc\/(\d+)$/ &&
913+
exists $params{tablespace_map}{$1})
914+
{
915+
push @tsoids, $1;
916+
return 0;
917+
}
918+
return 1;
919+
});
920+
921+
if (@tsoids > 0)
922+
{
923+
# We need to generate a tablespace_map file.
924+
open(my $tsmap, ">", "$data_path/tablespace_map")
925+
|| die "$data_path/tablespace_map: $!";
926+
927+
# Now use the list of tablespace links to copy each tablespace.
928+
for my $tsoid (@tsoids)
929+
{
930+
die "no tablespace mapping for $tsoid"
931+
if !exists $params{tablespace_map} ||
932+
!exists $params{tablespace_map}{$tsoid};
933+
934+
my $olddir = $backup_path . '/pg_tblspc/' . $tsoid;
935+
my $newdir = $params{tablespace_map}{$tsoid};
936+
PostgreSQL::Test::RecursiveCopy::copypath($olddir, $newdir);
937+
938+
my $escaped_newdir = $newdir;
939+
$escaped_newdir =~ s/\\/\\\\/g;
940+
print $tsmap "$tsoid $escaped_newdir\n";
941+
}
942+
943+
# Close tablespace_map.
944+
close($tsmap);
945+
}
864946
}
865947
chmod(0700, $data_path) or die $!;
866948

0 commit comments

Comments
 (0)