From 1c718dd8bffe9dcdf38b5a10991f4e1067e4821d Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 22 Jun 2006 20:43:20 +0000 Subject: 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. --- src/backend/access/transam/xlog.c | 61 ++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index c20025f38b..e7e55ce4d5 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.222.2.3 2006/03/28 22:01:25 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.222.2.4 2006/06/22 20:43:20 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -459,7 +459,7 @@ static bool InRedo = false; static void XLogArchiveNotify(const char *xlog); 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 readRecoveryCommandFile(void); static void exitArchiveRecovery(TimeLineID endTLI, @@ -482,7 +482,7 @@ static bool RestoreArchivedFile(char *path, const char *xlogfname, static int PreallocXlogFiles(XLogRecPtr endptr); static void MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr, int *nsegsremoved, int *nsegsrecycled); -static void RemoveOldBackupHistory(void); +static void CleanupBackupHistory(void); static XLogRecord *ReadRecord(XLogRecPtr *RecPtr, int emode); static bool ValidXLOGHeader(XLogPageHeader hdr, int emode); static XLogRecord *ReadCheckpointRecord(XLogRecPtr RecPtr, int whichChkpt); @@ -1071,24 +1071,30 @@ XLogArchiveNotifySeg(uint32 log, uint32 seg) } /* - * XLogArchiveIsDone + * XLogArchiveCheckDone * - * Checks for a ".done" archive notification file. This is called when we - * are ready to delete or recycle an old XLOG segment file. If it is okay - * to delete it then return true. + * This is called when we are ready to delete or recycle an old XLOG segment + * file or backup history file. If it is okay to delete it then return true. + * If it is not time to delete it, make sure a .ready file exists, and return + * false. * * If .done exists, then return true; else if .ready exists, - * then return false; else create .ready and return false. The - * last case covers the possibility that the original attempt to create - * .ready failed. + * then return false; else create .ready and return false. + * + * The reason we do things this way is so that if the original attempt to + * create .ready fails, we'll retry during subsequent checkpoints. */ static bool -XLogArchiveIsDone(const char *xlog) +XLogArchiveCheckDone(const char *xlog) { char archiveStatusPath[MAXPGPATH]; 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"); if (stat(archiveStatusPath, &stat_buf) == 0) return true; @@ -2383,14 +2389,7 @@ MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr, strspn(xlde->d_name, "0123456789ABCDEF") == 24 && strcmp(xlde->d_name + 8, lastoff + 8) <= 0) { - bool recycle; - - if (XLogArchivingActive()) - recycle = XLogArchiveIsDone(xlde->d_name); - else - recycle = true; - - if (recycle) + if (XLogArchiveCheckDone(xlde->d_name)) { snprintf(path, MAXPGPATH, XLOGDIR "/%s", xlde->d_name); @@ -2432,10 +2431,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 -RemoveOldBackupHistory(void) +CleanupBackupHistory(void) { DIR *xldir; struct dirent *xlde; @@ -2455,8 +2456,7 @@ RemoveOldBackupHistory(void) strcmp(xlde->d_name + strlen(xlde->d_name) - strlen(".backup"), ".backup") == 0) { - /* Remove any *.backup files that have been archived. */ - if (!XLogArchivingActive() || XLogArchiveIsDone(xlde->d_name)) + if (XLogArchiveCheckDone(xlde->d_name)) { ereport(DEBUG2, (errmsg("removing transaction log backup history file \"%s\"", @@ -5824,17 +5824,12 @@ pg_stop_backup(PG_FUNCTION_ARGS) errmsg("could not remove file \"%s\": %m", 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()) - { - BackupHistoryFileName(histfilepath, ThisTimeLineID, _logId, _logSeg, - startpoint.xrecoff % XLogSegSize); - XLogArchiveNotify(histfilepath); - } + CleanupBackupHistory(); /* * We're done. As a convenience, return the ending WAL offset. -- cgit v1.2.1