@@ -777,7 +777,7 @@ sub backup_fs_cold
777
777
778
778
=pod
779
779
780
- =item $node->init_from_backup(root_node, backup_name)
780
+ =item $node->init_from_backup(root_node, backup_name, %params )
781
781
782
782
Initialize a node from a backup, which may come from this node or a different
783
783
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.
787
787
788
788
By default, the backup is assumed to be plain format. To restore from
789
789
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.
792
797
793
798
To restore from an incremental backup, pass the parameter combine_with_prior
794
799
as a reference to an array of prior backup names with which this backup
@@ -843,24 +848,101 @@ sub init_from_backup
843
848
}
844
849
845
850
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 );
848
861
}
849
862
elsif (defined $params {tar_program })
850
863
{
851
- mkdir ($data_path );
864
+ mkdir ($data_path ) || die " mkdir $data_path : $! " ;
852
865
PostgreSQL::Test::Utils::system_or_bail($params {tar_program }, ' xf' ,
853
866
$backup_path . ' /base.tar' ,
854
867
' -C' , $data_path );
855
868
PostgreSQL::Test::Utils::system_or_bail(
856
869
$params {tar_program }, ' xf' ,
857
870
$backup_path . ' /pg_wal.tar' , ' -C' ,
858
871
$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 );
859
901
}
860
902
else
861
903
{
904
+ my @tsoids ;
862
905
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
+ }
864
946
}
865
947
chmod (0700, $data_path ) or die $! ;
866
948
0 commit comments