summaryrefslogtreecommitdiff
path: root/src/bin/pg_basebackup/pg_basebackup.c
diff options
context:
space:
mode:
authorAndres Freund <andres@anarazel.de>2015-01-03 20:51:52 +0100
committerAndres Freund <andres@anarazel.de>2015-01-03 20:54:13 +0100
commitf6cea45029dfc0ad09ef24f73cac936c676f83ed (patch)
tree744e581750e73498a40a175ca1ef0908f52af83c /src/bin/pg_basebackup/pg_basebackup.c
parentbb2e2ce6e2ea4835ed99593508d0909af0e402d6 (diff)
Prevent WAL files created by pg_basebackup -x/X from being archived again.
WAL (and timeline history) files created by pg_basebackup did not maintain the new base backup's archive status. That's currently not a problem if the new node is used as a standby - but if that node is promoted all still existing files can get archived again. With a high wal_keep_segment settings that can happen a significant time later - which is quite confusing. Change both the backend (for the -x/-X fetch case) and pg_basebackup (for -X stream) itself to always mark WAL/timeline files included in the base backup as .done. That's in line with walreceiver.c doing so. The verbosity of the pg_basebackup changes show pretty clearly that it needs some refactoring, but that'd result in not be backpatchable changes. Backpatch to 9.1 where pg_basebackup was introduced. Discussion: 20141205002854.GE21964@awork2.anarazel.de
Diffstat (limited to 'src/bin/pg_basebackup/pg_basebackup.c')
-rw-r--r--src/bin/pg_basebackup/pg_basebackup.c32
1 files changed, 23 insertions, 9 deletions
diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c
index b1bcf698eb6..e63bb7c53af 100644
--- a/src/bin/pg_basebackup/pg_basebackup.c
+++ b/src/bin/pg_basebackup/pg_basebackup.c
@@ -28,6 +28,7 @@
#include <zlib.h>
#endif
+#include "common/string.h"
#include "getopt_long.h"
#include "receivelog.h"
@@ -266,7 +267,7 @@ LogStreamerMain(logstreamer_param *param)
if (!ReceiveXlogStream(param->bgconn, param->startptr, param->timeline,
param->sysidentifier, param->xlogdir,
reached_end_position, standby_message_timeout,
- NULL))
+ NULL, true))
/*
* Any errors will already have been reported in the function process,
@@ -290,6 +291,7 @@ StartLogStreamer(char *startpos, uint32 timeline, char *sysidentifier)
logstreamer_param *param;
uint32 hi,
lo;
+ char statusdir[MAXPGPATH];
param = pg_malloc0(sizeof(logstreamer_param));
param->timeline = timeline;
@@ -324,13 +326,23 @@ StartLogStreamer(char *startpos, uint32 timeline, char *sysidentifier)
/* Error message already written in GetConnection() */
exit(1);
+ snprintf(param->xlogdir, sizeof(param->xlogdir), "%s/pg_xlog", basedir);
+
/*
- * Always in plain format, so we can write to basedir/pg_xlog. But the
- * directory entry in the tar file may arrive later, so make sure it's
- * created before we start.
+ * Create pg_xlog/archive_status (and thus pg_xlog) so we can can write to
+ * basedir/pg_xlog as the directory entry in the tar file may arrive
+ * later.
*/
- snprintf(param->xlogdir, sizeof(param->xlogdir), "%s/pg_xlog", basedir);
- verify_dir_is_empty_or_create(param->xlogdir);
+ snprintf(statusdir, sizeof(statusdir), "%s/pg_xlog/archive_status",
+ basedir);
+
+ if (pg_mkdir_p(statusdir, S_IRWXU) != 0 && errno != EEXIST)
+ {
+ fprintf(stderr,
+ _("%s: could not create directory \"%s\": %s\n"),
+ progname, statusdir, strerror(errno));
+ disconnect_and_exit(1);
+ }
/*
* Start a child process and tell it to start streaming. On Unix, this is
@@ -1003,10 +1015,12 @@ ReceiveAndUnpackTarFile(PGconn *conn, PGresult *res, int rownum)
{
/*
* When streaming WAL, pg_xlog will have been created
- * by the wal receiver process, so just ignore failure
- * on that.
+ * by the wal receiver process. So just ignore creation
+ * failures on related directories.
*/
- if (!streamwal || strcmp(filename + strlen(filename) - 8, "/pg_xlog") != 0)
+ if (!((pg_str_endswith(filename, "/pg_xlog") ||
+ pg_str_endswith(filename, "/archive_status")) &&
+ errno == EEXIST))
{
fprintf(stderr,
_("%s: could not create directory \"%s\": %s\n"),