From 3a04f53e7f850a18388256abb0ba03416e6e67c4 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 22 Jun 2006 20:42:57 +0000 Subject: [PATCH] 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 85618fcf01..e540ba672c 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * 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; 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, @@ -484,7 +484,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); @@ -1109,24 +1109,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; @@ -2438,14 +2444,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); @@ -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 -RemoveOldBackupHistory(void) +CleanupBackupHistory(void) { DIR *xldir; struct dirent *xlde; @@ -2510,8 +2511,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\"", @@ -5968,17 +5968,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. -- 2.40.0