summaryrefslogtreecommitdiff
path: root/src/backend/access
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>2008-04-05 01:34:06 +0000
committerBruce Momjian <bruce@momjian.us>2008-04-05 01:34:06 +0000
commit2a1cf97c22933368c8747711da0f30c35f4bddcd (patch)
tree59279eadb6955d135c10429f5843a6d71cc85f75 /src/backend/access
parenta0fad9762a22e739de69c85b51ff7a47e672732f (diff)
downloadpostgresql-2a1cf97c22933368c8747711da0f30c35f4bddcd.tar.gz
Have pg_stop_backup() wait for all archive files to be sent, rather than
returing right away. This guarantees that when pg_stop_backup() returns, you have a valid backup. Simon Riggs
Diffstat (limited to 'src/backend/access')
-rw-r--r--src/backend/access/transam/xlog.c49
1 files changed, 43 insertions, 6 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 1b6a58f661..b059e49bc3 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.295 2008/03/25 22:42:42 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.296 2008/04/05 01:34:06 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -382,7 +382,7 @@ static bool InRedo = false;
static void XLogArchiveNotify(const char *xlog);
static void XLogArchiveNotifySeg(uint32 log, uint32 seg);
-static bool XLogArchiveCheckDone(const char *xlog);
+static bool XLogArchiveCheckDone(const char *xlog, bool create_if_missing);
static void XLogArchiveCleanup(const char *xlog);
static void readRecoveryCommandFile(void);
static void exitArchiveRecovery(TimeLineID endTLI,
@@ -1128,7 +1128,7 @@ XLogArchiveNotifySeg(uint32 log, uint32 seg)
* create <XLOG>.ready fails, we'll retry during subsequent checkpoints.
*/
static bool
-XLogArchiveCheckDone(const char *xlog)
+XLogArchiveCheckDone(const char *xlog, bool create_if_missing)
{
char archiveStatusPath[MAXPGPATH];
struct stat stat_buf;
@@ -1153,7 +1153,9 @@ XLogArchiveCheckDone(const char *xlog)
return true;
/* Retry creation of the .ready file */
- XLogArchiveNotify(xlog);
+ if (create_if_missing)
+ XLogArchiveNotify(xlog);
+
return false;
}
@@ -2704,7 +2706,7 @@ RemoveOldXlogFiles(uint32 log, uint32 seg, XLogRecPtr endptr)
strspn(xlde->d_name, "0123456789ABCDEF") == 24 &&
strcmp(xlde->d_name + 8, lastoff + 8) <= 0)
{
- if (XLogArchiveCheckDone(xlde->d_name))
+ if (XLogArchiveCheckDone(xlde->d_name, true))
{
snprintf(path, MAXPGPATH, XLOGDIR "/%s", xlde->d_name);
@@ -2771,7 +2773,7 @@ CleanupBackupHistory(void)
strcmp(xlde->d_name + strlen(xlde->d_name) - strlen(".backup"),
".backup") == 0)
{
- if (XLogArchiveCheckDone(xlde->d_name))
+ if (XLogArchiveCheckDone(xlde->d_name, true))
{
ereport(DEBUG2,
(errmsg("removing transaction log backup history file \"%s\"",
@@ -6556,6 +6558,8 @@ pg_stop_backup(PG_FUNCTION_ARGS)
FILE *fp;
char ch;
int ich;
+ int seconds_before_warning;
+ int waits = 0;
if (!superuser())
ereport(ERROR,
@@ -6660,6 +6664,39 @@ pg_stop_backup(PG_FUNCTION_ARGS)
CleanupBackupHistory();
/*
+ * Wait until the history file has been archived. We assume that the
+ * alphabetic sorting property of the WAL files ensures the last WAL
+ * file is guaranteed archived by the time the history file is archived.
+ *
+ * We wait forever, since archive_command is supposed to work and
+ * we assume the admin wanted his backup to work completely. If you
+ * don't wish to wait, you can SET statement_timeout = xx;
+ *
+ * If the status file is missing, we assume that is because it was
+ * set to .ready before we slept, then while asleep it has been set
+ * to .done and then removed by a concurrent checkpoint.
+ */
+ BackupHistoryFileName(histfilepath, ThisTimeLineID, _logId, _logSeg,
+ startpoint.xrecoff % XLogSegSize);
+
+ seconds_before_warning = 60;
+ waits = 0;
+
+ while (!XLogArchiveCheckDone(histfilepath, false))
+ {
+ CHECK_FOR_INTERRUPTS();
+
+ pg_usleep(1000000L);
+
+ if (++waits >= seconds_before_warning)
+ {
+ seconds_before_warning *= 2; /* This wraps in >10 years... */
+ elog(WARNING, "pg_stop_backup() waiting for archive to complete "
+ "(%d seconds delay)", waits);
+ }
+ }
+
+ /*
* We're done. As a convenience, return the ending WAL location.
*/
snprintf(stopxlogfilename, sizeof(stopxlogfilename), "%X/%X",