77 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
88 * Portions Copyright (c) 1994, Regents of the University of California
99 *
10- * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.295 2008/03/25 22:42:42 tgl Exp $
10+ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.296 2008/04/05 01:34:06 momjian Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
@@ -382,7 +382,7 @@ static bool InRedo = false;
382382
383383static void XLogArchiveNotify (const char * xlog );
384384static void XLogArchiveNotifySeg (uint32 log ,uint32 seg );
385- static bool XLogArchiveCheckDone (const char * xlog );
385+ static bool XLogArchiveCheckDone (const char * xlog , bool create_if_missing );
386386static void XLogArchiveCleanup (const char * xlog );
387387static void readRecoveryCommandFile (void );
388388static void exitArchiveRecovery (TimeLineID endTLI ,
@@ -1128,7 +1128,7 @@ XLogArchiveNotifySeg(uint32 log, uint32 seg)
11281128 * create <XLOG>.ready fails, we'll retry during subsequent checkpoints.
11291129 */
11301130static bool
1131- XLogArchiveCheckDone (const char * xlog )
1131+ XLogArchiveCheckDone (const char * xlog , bool create_if_missing )
11321132{
11331133char archiveStatusPath [MAXPGPATH ];
11341134struct stat stat_buf ;
@@ -1153,7 +1153,9 @@ XLogArchiveCheckDone(const char *xlog)
11531153return true;
11541154
11551155/* Retry creation of the .ready file */
1156- XLogArchiveNotify (xlog );
1156+ if (create_if_missing )
1157+ XLogArchiveNotify (xlog );
1158+
11571159return false;
11581160}
11591161
@@ -2704,7 +2706,7 @@ RemoveOldXlogFiles(uint32 log, uint32 seg, XLogRecPtr endptr)
27042706strspn (xlde -> d_name ,"0123456789ABCDEF" )== 24 &&
27052707strcmp (xlde -> d_name + 8 ,lastoff + 8 ) <=0 )
27062708{
2707- if (XLogArchiveCheckDone (xlde -> d_name ))
2709+ if (XLogArchiveCheckDone (xlde -> d_name , true ))
27082710{
27092711snprintf (path ,MAXPGPATH ,XLOGDIR "/%s" ,xlde -> d_name );
27102712
@@ -2771,7 +2773,7 @@ CleanupBackupHistory(void)
27712773strcmp (xlde -> d_name + strlen (xlde -> d_name )- strlen (".backup" ),
27722774".backup" )== 0 )
27732775{
2774- if (XLogArchiveCheckDone (xlde -> d_name ))
2776+ if (XLogArchiveCheckDone (xlde -> d_name , true ))
27752777{
27762778ereport (DEBUG2 ,
27772779(errmsg ("removing transaction log backup history file \"%s\"" ,
@@ -6556,6 +6558,8 @@ pg_stop_backup(PG_FUNCTION_ARGS)
65566558FILE * fp ;
65576559char ch ;
65586560int ich ;
6561+ int seconds_before_warning ;
6562+ int waits = 0 ;
65596563
65606564if (!superuser ())
65616565ereport (ERROR ,
@@ -6659,6 +6663,39 @@ pg_stop_backup(PG_FUNCTION_ARGS)
66596663 */
66606664CleanupBackupHistory ();
66616665
6666+ /*
6667+ * Wait until the history file has been archived. We assume that the
6668+ * alphabetic sorting property of the WAL files ensures the last WAL
6669+ * file is guaranteed archived by the time the history file is archived.
6670+ *
6671+ * We wait forever, since archive_command is supposed to work and
6672+ * we assume the admin wanted his backup to work completely. If you
6673+ * don't wish to wait, you can SET statement_timeout = xx;
6674+ *
6675+ * If the status file is missing, we assume that is because it was
6676+ * set to .ready before we slept, then while asleep it has been set
6677+ * to .done and then removed by a concurrent checkpoint.
6678+ */
6679+ BackupHistoryFileName (histfilepath ,ThisTimeLineID ,_logId ,_logSeg ,
6680+ startpoint .xrecoff %XLogSegSize );
6681+
6682+ seconds_before_warning = 60 ;
6683+ waits = 0 ;
6684+
6685+ while (!XLogArchiveCheckDone (histfilepath , false))
6686+ {
6687+ CHECK_FOR_INTERRUPTS ();
6688+
6689+ pg_usleep (1000000L );
6690+
6691+ if (++ waits >=seconds_before_warning )
6692+ {
6693+ seconds_before_warning *=2 ;/* This wraps in >10 years... */
6694+ elog (WARNING ,"pg_stop_backup() waiting for archive to complete "
6695+ "(%d seconds delay)" ,waits );
6696+ }
6697+ }
6698+
66626699/*
66636700 * We're done. As a convenience, return the ending WAL location.
66646701 */