Commit 3a04f53e authored by Tom Lane's avatar Tom Lane

pg_stop_backup was calling XLogArchiveNotify() twice for the newly created

backup history file.  Bug introduced by the 8.1 change to make pg_stop_backup
delete older history files.  Per report from Masao Fujii.
parent 39bed3b3
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.240 2006/06/18 18:30:20 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.241 2006/06/22 20:42:57 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -460,7 +460,7 @@ static bool InRedo = false; ...@@ -460,7 +460,7 @@ static bool InRedo = false;
static void XLogArchiveNotify(const char *xlog); static void XLogArchiveNotify(const char *xlog);
static void XLogArchiveNotifySeg(uint32 log, uint32 seg); static void XLogArchiveNotifySeg(uint32 log, uint32 seg);
static bool XLogArchiveIsDone(const char *xlog); static bool XLogArchiveCheckDone(const char *xlog);
static void XLogArchiveCleanup(const char *xlog); static void XLogArchiveCleanup(const char *xlog);
static void readRecoveryCommandFile(void); static void readRecoveryCommandFile(void);
static void exitArchiveRecovery(TimeLineID endTLI, static void exitArchiveRecovery(TimeLineID endTLI,
...@@ -484,7 +484,7 @@ static bool RestoreArchivedFile(char *path, const char *xlogfname, ...@@ -484,7 +484,7 @@ static bool RestoreArchivedFile(char *path, const char *xlogfname,
static int PreallocXlogFiles(XLogRecPtr endptr); static int PreallocXlogFiles(XLogRecPtr endptr);
static void MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr, static void MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr,
int *nsegsremoved, int *nsegsrecycled); int *nsegsremoved, int *nsegsrecycled);
static void RemoveOldBackupHistory(void); static void CleanupBackupHistory(void);
static XLogRecord *ReadRecord(XLogRecPtr *RecPtr, int emode); static XLogRecord *ReadRecord(XLogRecPtr *RecPtr, int emode);
static bool ValidXLOGHeader(XLogPageHeader hdr, int emode); static bool ValidXLOGHeader(XLogPageHeader hdr, int emode);
static XLogRecord *ReadCheckpointRecord(XLogRecPtr RecPtr, int whichChkpt); static XLogRecord *ReadCheckpointRecord(XLogRecPtr RecPtr, int whichChkpt);
...@@ -1109,24 +1109,30 @@ XLogArchiveNotifySeg(uint32 log, uint32 seg) ...@@ -1109,24 +1109,30 @@ XLogArchiveNotifySeg(uint32 log, uint32 seg)
} }
/* /*
* XLogArchiveIsDone * XLogArchiveCheckDone
* *
* Checks for a ".done" archive notification file. This is called when we * This is called when we are ready to delete or recycle an old XLOG segment
* are ready to delete or recycle an old XLOG segment file. If it is okay * file or backup history file. If it is okay to delete it then return true.
* to delete it then return true. * If it is not time to delete it, make sure a .ready file exists, and return
* false.
* *
* If <XLOG>.done exists, then return true; else if <XLOG>.ready exists, * If <XLOG>.done exists, then return true; else if <XLOG>.ready exists,
* then return false; else create <XLOG>.ready and return false. The * then return false; else create <XLOG>.ready and return false.
* last case covers the possibility that the original attempt to create *
* <XLOG>.ready failed. * The reason we do things this way is so that if the original attempt to
* create <XLOG>.ready fails, we'll retry during subsequent checkpoints.
*/ */
static bool static bool
XLogArchiveIsDone(const char *xlog) XLogArchiveCheckDone(const char *xlog)
{ {
char archiveStatusPath[MAXPGPATH]; char archiveStatusPath[MAXPGPATH];
struct stat stat_buf; struct stat stat_buf;
/* First check for .done --- this is the expected case */ /* Always deletable if archiving is off */
if (!XLogArchivingActive())
return true;
/* First check for .done --- this means archiver is done with it */
StatusFilePath(archiveStatusPath, xlog, ".done"); StatusFilePath(archiveStatusPath, xlog, ".done");
if (stat(archiveStatusPath, &stat_buf) == 0) if (stat(archiveStatusPath, &stat_buf) == 0)
return true; return true;
...@@ -2438,14 +2444,7 @@ MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr, ...@@ -2438,14 +2444,7 @@ MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr,
strspn(xlde->d_name, "0123456789ABCDEF") == 24 && strspn(xlde->d_name, "0123456789ABCDEF") == 24 &&
strcmp(xlde->d_name + 8, lastoff + 8) <= 0) strcmp(xlde->d_name + 8, lastoff + 8) <= 0)
{ {
bool recycle; if (XLogArchiveCheckDone(xlde->d_name))
if (XLogArchivingActive())
recycle = XLogArchiveIsDone(xlde->d_name);
else
recycle = true;
if (recycle)
{ {
snprintf(path, MAXPGPATH, XLOGDIR "/%s", xlde->d_name); snprintf(path, MAXPGPATH, XLOGDIR "/%s", xlde->d_name);
...@@ -2487,10 +2486,12 @@ MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr, ...@@ -2487,10 +2486,12 @@ MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr,
} }
/* /*
* Remove previous backup history files * Remove previous backup history files. This also retries creation of
* .ready files for any backup history files for which XLogArchiveNotify
* failed earlier.
*/ */
static void static void
RemoveOldBackupHistory(void) CleanupBackupHistory(void)
{ {
DIR *xldir; DIR *xldir;
struct dirent *xlde; struct dirent *xlde;
...@@ -2510,8 +2511,7 @@ RemoveOldBackupHistory(void) ...@@ -2510,8 +2511,7 @@ RemoveOldBackupHistory(void)
strcmp(xlde->d_name + strlen(xlde->d_name) - strlen(".backup"), strcmp(xlde->d_name + strlen(xlde->d_name) - strlen(".backup"),
".backup") == 0) ".backup") == 0)
{ {
/* Remove any *.backup files that have been archived. */ if (XLogArchiveCheckDone(xlde->d_name))
if (!XLogArchivingActive() || XLogArchiveIsDone(xlde->d_name))
{ {
ereport(DEBUG2, ereport(DEBUG2,
(errmsg("removing transaction log backup history file \"%s\"", (errmsg("removing transaction log backup history file \"%s\"",
...@@ -5968,17 +5968,12 @@ pg_stop_backup(PG_FUNCTION_ARGS) ...@@ -5968,17 +5968,12 @@ pg_stop_backup(PG_FUNCTION_ARGS)
errmsg("could not remove file \"%s\": %m", errmsg("could not remove file \"%s\": %m",
BACKUP_LABEL_FILE))); BACKUP_LABEL_FILE)));
RemoveOldBackupHistory();
/* /*
* Notify archiver that history file may be archived immediately * Clean out any no-longer-needed history files. As a side effect,
* this will post a .ready file for the newly created history file,
* notifying the archiver that history file may be archived immediately.
*/ */
if (XLogArchivingActive()) CleanupBackupHistory();
{
BackupHistoryFileName(histfilepath, ThisTimeLineID, _logId, _logSeg,
startpoint.xrecoff % XLogSegSize);
XLogArchiveNotify(histfilepath);
}
/* /*
* We're done. As a convenience, return the ending WAL offset. * We're done. As a convenience, return the ending WAL offset.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment