18
18
#include <time.h>
19
19
20
20
#include "access/xlog_internal.h" /* for pg_start/stop_backup */
21
+ #include "catalog/catalog.h"
21
22
#include "catalog/pg_type.h"
22
23
#include "lib/stringinfo.h"
23
24
#include "libpq/libpq.h"
@@ -44,6 +45,7 @@ typedef struct
44
45
45
46
46
47
static int64 sendDir (char * path , int basepathlen , bool sizeonly );
48
+ static int64 sendTablespace (char * path , bool sizeonly );
47
49
static bool sendFile (char * readfilename , char * tarfilename ,
48
50
struct stat * statbuf , bool missing_ok );
49
51
static void sendFileWithContent (const char * filename , const char * content );
@@ -137,7 +139,7 @@ perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
137
139
ti = palloc (sizeof (tablespaceinfo ));
138
140
ti -> oid = pstrdup (de -> d_name );
139
141
ti -> path = pstrdup (linkpath );
140
- ti -> size = opt -> progress ? sendDir ( linkpath , strlen ( linkpath ) , true) : -1 ;
142
+ ti -> size = opt -> progress ? sendTablespace ( fullpath , true) : -1 ;
141
143
tablespaces = lappend (tablespaces , ti );
142
144
#else
143
145
@@ -172,29 +174,26 @@ perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
172
174
pq_sendint (& buf , 0 , 2 ); /* natts */
173
175
pq_endmessage (& buf );
174
176
175
- /* In the main tar, include the backup_label first. */
176
- if (ti -> path == NULL )
177
- sendFileWithContent (BACKUP_LABEL_FILE , labelfile );
178
-
179
- sendDir (ti -> path == NULL ? "." : ti -> path ,
180
- ti -> path == NULL ? 1 : strlen (ti -> path ),
181
- false);
182
-
183
- /* In the main tar, include pg_control last. */
184
177
if (ti -> path == NULL )
185
178
{
186
179
struct stat statbuf ;
187
180
181
+ /* In the main tar, include the backup_label first... */
182
+ sendFileWithContent (BACKUP_LABEL_FILE , labelfile );
183
+
184
+ /* ... then the bulk of the files ... */
185
+ sendDir ("." , 1 , false);
186
+
187
+ /* ... and pg_control after everything else. */
188
188
if (lstat (XLOG_CONTROL_FILE , & statbuf ) != 0 )
189
- {
190
189
ereport (ERROR ,
191
190
(errcode_for_file_access (),
192
191
errmsg ("could not stat control file \"%s\": %m" ,
193
192
XLOG_CONTROL_FILE )));
194
- }
195
-
196
193
sendFile (XLOG_CONTROL_FILE , XLOG_CONTROL_FILE , & statbuf , false);
197
194
}
195
+ else
196
+ sendTablespace (ti -> path , false);
198
197
199
198
/*
200
199
* If we're including WAL, and this is the main data directory we
@@ -722,6 +721,49 @@ sendFileWithContent(const char *filename, const char *content)
722
721
}
723
722
}
724
723
724
+ /*
725
+ * Include the tablespace directory pointed to by 'path' in the output tar
726
+ * stream. If 'sizeonly' is true, we just calculate a total length and return
727
+ * it, without actually sending anything.
728
+ */
729
+ static int64
730
+ sendTablespace (char * path , bool sizeonly )
731
+ {
732
+ int64 size ;
733
+ char pathbuf [MAXPGPATH ];
734
+ struct stat statbuf ;
735
+
736
+ /*
737
+ * 'path' points to the tablespace location, but we only want to include
738
+ * the version directory in it that belongs to us.
739
+ */
740
+ snprintf (pathbuf , sizeof (pathbuf ), "%s/%s" , path ,
741
+ TABLESPACE_VERSION_DIRECTORY );
742
+
743
+ /*
744
+ * Store a directory entry in the tar file so we get the permissions right.
745
+ */
746
+ if (lstat (pathbuf , & statbuf ) != 0 )
747
+ {
748
+ if (errno != ENOENT )
749
+ ereport (ERROR ,
750
+ (errcode_for_file_access (),
751
+ errmsg ("could not stat file or directory \"%s\": %m" ,
752
+ pathbuf )));
753
+
754
+ /* If the tablespace went away while scanning, it's no error. */
755
+ return 0 ;
756
+ }
757
+ if (!sizeonly )
758
+ _tarWriteHeader (TABLESPACE_VERSION_DIRECTORY , NULL , & statbuf );
759
+ size = 512 ; /* Size of the header just added */
760
+
761
+ /* Send all the files in the tablespace version directory */
762
+ size += sendDir (pathbuf , strlen (path ), sizeonly );
763
+
764
+ return size ;
765
+ }
766
+
725
767
/*
726
768
* Include all files from the given directory in the output tar stream. If
727
769
* 'sizeonly' is true, we just calculate a total length and return it, without
0 commit comments