summaryrefslogtreecommitdiff
path: root/src/bin/pg_basebackup/pg_basebackup.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/pg_basebackup/pg_basebackup.c')
-rw-r--r--src/bin/pg_basebackup/pg_basebackup.c148
1 files changed, 108 insertions, 40 deletions
diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c
index d6fef38760e..af1c4de58f9 100644
--- a/src/bin/pg_basebackup/pg_basebackup.c
+++ b/src/bin/pg_basebackup/pg_basebackup.c
@@ -131,7 +131,7 @@ static int has_xlogendptr = 0;
static volatile LONG has_xlogendptr = 0;
#endif
-/* Contents of recovery.conf to be generated */
+/* Contents of configuration file to be generated */
static PQExpBuffer recoveryconfcontents = NULL;
/* Function headers */
@@ -346,7 +346,7 @@ usage(void)
printf(_(" -r, --max-rate=RATE maximum transfer rate to transfer data directory\n"
" (in kB/s, or use suffix \"k\" or \"M\")\n"));
printf(_(" -R, --write-recovery-conf\n"
- " write recovery.conf for replication\n"));
+ " write configuration for replication\n"));
printf(_(" -T, --tablespace-mapping=OLDDIR=NEWDIR\n"
" relocate tablespace in OLDDIR to NEWDIR\n"));
printf(_(" --waldir=WALDIR location for the write-ahead log directory\n"));
@@ -974,6 +974,9 @@ ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
bool basetablespace = PQgetisnull(res, rownum, 0);
bool in_tarhdr = true;
bool skip_file = false;
+ bool is_postgresql_auto_conf = false;
+ bool found_postgresql_auto_conf = false;
+ int file_padding_len = 0;
size_t tarhdrsz = 0;
pgoff_t filesz = 0;
@@ -1113,8 +1116,8 @@ ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
{
/*
* End of chunk. If requested, and this is the base tablespace,
- * write recovery.conf into the tarfile. When done, close the file
- * (but not stdout).
+ * write configuration file into the tarfile. When done, close the
+ * file (but not stdout).
*
* Also, write two completely empty blocks at the end of the tar
* file, as required by some tar programs.
@@ -1126,19 +1129,31 @@ ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
if (basetablespace && writerecoveryconf)
{
char header[512];
- int padding;
- tarCreateHeader(header, "recovery.conf", NULL,
- recoveryconfcontents->len,
+ if (!found_postgresql_auto_conf)
+ {
+ int padding;
+
+ tarCreateHeader(header, "postgresql.auto.conf", NULL,
+ recoveryconfcontents->len,
+ pg_file_create_mode, 04000, 02000,
+ time(NULL));
+
+ padding = ((recoveryconfcontents->len + 511) & ~511) - recoveryconfcontents->len;
+
+ WRITE_TAR_DATA(header, sizeof(header));
+ WRITE_TAR_DATA(recoveryconfcontents->data, recoveryconfcontents->len);
+ if (padding)
+ WRITE_TAR_DATA(zerobuf, padding);
+ }
+
+ tarCreateHeader(header, "standby.signal", NULL,
+ 0, /* zero-length file */
pg_file_create_mode, 04000, 02000,
time(NULL));
- padding = ((recoveryconfcontents->len + 511) & ~511) - recoveryconfcontents->len;
-
WRITE_TAR_DATA(header, sizeof(header));
- WRITE_TAR_DATA(recoveryconfcontents->data, recoveryconfcontents->len);
- if (padding)
- WRITE_TAR_DATA(zerobuf, padding);
+ WRITE_TAR_DATA(zerobuf, 511);
}
/* 2 * 512 bytes empty data at end of file */
@@ -1182,8 +1197,8 @@ ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
if (!writerecoveryconf || !basetablespace)
{
/*
- * When not writing recovery.conf, or when not working on the base
- * tablespace, we never have to look for an existing recovery.conf
+ * When not writing config file, or when not working on the base
+ * tablespace, we never have to look for an existing configuration
* file in the stream.
*/
WRITE_TAR_DATA(copybuf, r);
@@ -1191,7 +1206,7 @@ ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
else
{
/*
- * Look for a recovery.conf in the existing tar stream. If it's
+ * Look for a config file in the existing tar stream. If it's
* there, we must skip it so we can later overwrite it with our
* own version of the file.
*
@@ -1235,29 +1250,46 @@ ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
{
/*
* We have the complete header structure in tarhdr,
- * look at the file metadata: - the subsequent file
- * contents have to be skipped if the filename is
- * recovery.conf - find out the size of the file
- * padded to the next multiple of 512
+ * look at the file metadata: we may want append
+ * recovery info into postgresql.auto.conf and skip
+ * standby.signal file. In both cases we must
+ * calculate tar padding
*/
- int padding;
-
- skip_file = (strcmp(&tarhdr[0], "recovery.conf") == 0);
+ skip_file = (strcmp(&tarhdr[0], "standby.signal") == 0);
+ is_postgresql_auto_conf = (strcmp(&tarhdr[0], "postgresql.auto.conf") == 0);
filesz = read_tar_number(&tarhdr[124], 12);
+ file_padding_len = ((filesz + 511) & ~511) - filesz;
+
+ if (is_postgresql_auto_conf && writerecoveryconf)
+ {
+ /* replace tar header */
+ char header[512];
- padding = ((filesz + 511) & ~511) - filesz;
- filesz += padding;
+ tarCreateHeader(header, "postgresql.auto.conf", NULL,
+ filesz + recoveryconfcontents->len,
+ pg_file_create_mode, 04000, 02000,
+ time(NULL));
+
+ WRITE_TAR_DATA(header, sizeof(header));
+ }
+ else
+ {
+ /* copy stream with padding */
+ filesz += file_padding_len;
+
+ if (!skip_file)
+ {
+ /*
+ * If we're not skipping the file, write the
+ * tar header unmodified.
+ */
+ WRITE_TAR_DATA(tarhdr, 512);
+ }
+ }
/* Next part is the file, not the header */
in_tarhdr = false;
-
- /*
- * If we're not skipping the file, write the tar
- * header unmodified.
- */
- if (!skip_file)
- WRITE_TAR_DATA(tarhdr, 512);
}
}
else
@@ -1281,6 +1313,32 @@ ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
pos += bytes2write;
filesz -= bytes2write;
}
+ else if (is_postgresql_auto_conf && writerecoveryconf)
+ {
+ /* append recovery config to postgresql.auto.conf */
+ int padding;
+ int tailsize;
+
+ tailsize = (512 - file_padding_len) + recoveryconfcontents->len;
+ padding = ((tailsize + 511) & ~511) - tailsize;
+
+ WRITE_TAR_DATA(recoveryconfcontents->data, recoveryconfcontents->len);
+
+ if (padding)
+ {
+ char zerobuf[512];
+
+ MemSet(zerobuf, 0, sizeof(zerobuf));
+ WRITE_TAR_DATA(zerobuf, padding);
+ }
+
+ /* skip original file padding */
+ is_postgresql_auto_conf = false;
+ skip_file = true;
+ filesz += file_padding_len;
+
+ found_postgresql_auto_conf = true;
+ }
else
{
/*
@@ -1289,6 +1347,7 @@ ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
*/
in_tarhdr = true;
skip_file = false;
+ is_postgresql_auto_conf = false;
tarhdrsz = 0;
filesz = 0;
}
@@ -1614,7 +1673,7 @@ escape_quotes(const char *src)
}
/*
- * Create a recovery.conf file in memory using a PQExpBuffer
+ * Create a configuration file in memory using a PQExpBuffer
*/
static void
GenerateRecoveryConf(PGconn *conn)
@@ -1638,8 +1697,6 @@ GenerateRecoveryConf(PGconn *conn)
disconnect_and_exit(1);
}
- appendPQExpBufferStr(recoveryconfcontents, "standby_mode = 'on'\n");
-
initPQExpBuffer(&conninfo_buf);
for (option = connOptions; option && option->keyword; option++)
{
@@ -1698,8 +1755,9 @@ GenerateRecoveryConf(PGconn *conn)
/*
- * Write a recovery.conf file into the directory specified in basedir,
+ * Write the configuration file into the directory specified in basedir,
* with the contents already collected in memory.
+ * Then write the signal file into the basedir also.
*/
static void
WriteRecoveryConf(void)
@@ -1707,12 +1765,12 @@ WriteRecoveryConf(void)
char filename[MAXPGPATH];
FILE *cf;
- sprintf(filename, "%s/recovery.conf", basedir);
+ snprintf(filename, MAXPGPATH, "%s/%s", basedir, "postgresql.auto.conf");
- cf = fopen(filename, "w");
+ cf = fopen(filename, "a");
if (cf == NULL)
{
- fprintf(stderr, _("%s: could not create file \"%s\": %s\n"), progname, filename, strerror(errno));
+ fprintf(stderr, _("%s: could not open file \"%s\": %s\n"), progname, filename, strerror(errno));
disconnect_and_exit(1);
}
@@ -1725,6 +1783,16 @@ WriteRecoveryConf(void)
}
fclose(cf);
+
+ snprintf(filename, MAXPGPATH, "%s/%s", basedir, "standby.signal");
+ cf = fopen(filename, "w");
+ if (cf == NULL)
+ {
+ fprintf(stderr, _("%s: could not create file \"%s\": %s\n"), progname, filename, strerror(errno));
+ disconnect_and_exit(1);
+ }
+
+ fclose(cf);
}
@@ -1780,7 +1848,7 @@ BaseBackup(void)
}
/*
- * Build contents of recovery.conf if requested
+ * Build contents of configuration file if requested
*/
if (writerecoveryconf)
GenerateRecoveryConf(conn);
@@ -2094,7 +2162,7 @@ BaseBackup(void)
#endif
}
- /* Free the recovery.conf contents */
+ /* Free the configuration file contents */
destroyPQExpBuffer(recoveryconfcontents);
/*