refactor_archive_status.v1.patch
application/octet-stream
Filename: refactor_archive_status.v1.patch
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
Series: patch v1
| File | + | − |
|---|---|---|
| src/backend/access/transam/xlog.c | 69 | 22 |
| src/backend/postmaster/pgarch.c | 1 | 25 |
| src/backend/replication/walreceiver.c | 7 | 0 |
| src/include/access/xlog_internal.h | 13 | 2 |
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index efd0347..393315f 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -605,7 +605,6 @@ typedef struct xl_restore_point
} xl_restore_point;
-static void XLogArchiveNotify(const char *xlog);
static void XLogArchiveNotifySeg(XLogSegNo segno);
static bool XLogArchiveCheckDone(const char *xlog);
static bool XLogArchiveIsBusy(const char *xlog);
@@ -1280,23 +1279,63 @@ XLogCheckBuffer(XLogRecData *rdata, bool doPageWrites,
}
/*
- * XLogArchiveNotify
+ * XLogSetArchiveStatus
*
- * Create an archive notification file
+ * Create an archive notification file with given archive status
*
* The name of the notification file is the message that will be picked up
* by the archiver, e.g. we write 0000000100000001000000C6.ready
* and the archiver then knows to archive XLOGDIR/0000000100000001000000C6,
* then when complete, rename it to 0000000100000001000000C6.done
*/
-static void
-XLogArchiveNotify(const char *xlog)
+void
+XLogSetArchiveStatus(const char *xlog, int archive_status)
{
char archiveStatusPath[MAXPGPATH];
+ struct stat stat_buf;
FILE *fd;
- /* insert an otherwise empty file called <XLOG>.ready */
- StatusFilePath(archiveStatusPath, xlog, ".ready");
+ switch (archive_status)
+ {
+ case XLOG_ARCHIVE_STATUS_READY:
+
+ /* If already marked READY then quick exit */
+ StatusFilePath(archiveStatusPath, xlog, XLOG_ARCHIVE_STATUS_READY);
+ if (stat(archiveStatusPath, &stat_buf) == 0)
+ return;
+
+ break;
+
+ case XLOG_ARCHIVE_STATUS_DONE:
+
+ /* If marked READY then rename to DONE */
+ StatusFilePath(archiveStatusPath, xlog, XLOG_ARCHIVE_STATUS_READY);
+ if (stat(archiveStatusPath, &stat_buf) == 0)
+ {
+ char archiveStatusDone[MAXPGPATH];
+
+ StatusFilePath(archiveStatusDone, xlog, XLOG_ARCHIVE_STATUS_DONE);
+
+ if (rename(archiveStatusPath, archiveStatusDone) < 0)
+ ereport(WARNING,
+ (errcode_for_file_access(),
+ errmsg("could not rename file \"%s\" to \"%s\": %m",
+ archiveStatusPath, archiveStatusDone)));
+ return;
+ }
+
+ /* If already marked DONE then exit */
+ StatusFilePath(archiveStatusPath, xlog, XLOG_ARCHIVE_STATUS_DONE);
+ if (stat(archiveStatusPath, &stat_buf) == 0)
+ return;
+
+ break;
+
+ default:
+ elog(ERROR, "invalud archive status");
+ }
+
+ /* insert an otherwise empty file with prefix that indicates archive_status */
fd = AllocateFile(archiveStatusPath, "w");
if (fd == NULL)
{
@@ -1315,13 +1354,15 @@ XLogArchiveNotify(const char *xlog)
return;
}
- /* Notify archiver that it's got something to do */
- if (IsUnderPostmaster)
+ /* Notify archiver that it's got something to do if .ready has been created */
+ if (IsUnderPostmaster && archive_status == XLOG_ARCHIVE_STATUS_READY)
SendPostmasterSignal(PMSIGNAL_WAKEN_ARCHIVER);
}
/*
* Convenience routine to notify using segment number representation of filename
+ *
+ * This always creates XLOG_ARCHIVE_STATUS_READY
*/
static void
XLogArchiveNotifySeg(XLogSegNo segno)
@@ -1329,7 +1370,7 @@ XLogArchiveNotifySeg(XLogSegNo segno)
char xlog[MAXFNAMELEN];
XLogFileName(xlog, ThisTimeLineID, segno);
- XLogArchiveNotify(xlog);
+ XLogSetArchiveStatus(xlog, XLOG_ARCHIVE_STATUS_READY);
}
/*
@@ -1357,22 +1398,22 @@ XLogArchiveCheckDone(const char *xlog)
return true;
/* First check for .done --- this means archiver is done with it */
- StatusFilePath(archiveStatusPath, xlog, ".done");
+ StatusFilePath(archiveStatusPath, xlog, XLOG_ARCHIVE_STATUS_DONE);
if (stat(archiveStatusPath, &stat_buf) == 0)
return true;
/* check for .ready --- this means archiver is still busy with it */
- StatusFilePath(archiveStatusPath, xlog, ".ready");
+ StatusFilePath(archiveStatusPath, xlog, XLOG_ARCHIVE_STATUS_READY);
if (stat(archiveStatusPath, &stat_buf) == 0)
return false;
/* Race condition --- maybe archiver just finished, so recheck */
- StatusFilePath(archiveStatusPath, xlog, ".done");
+ StatusFilePath(archiveStatusPath, xlog, XLOG_ARCHIVE_STATUS_DONE);
if (stat(archiveStatusPath, &stat_buf) == 0)
return true;
/* Retry creation of the .ready file */
- XLogArchiveNotify(xlog);
+ XLogSetArchiveStatus(xlog, XLOG_ARCHIVE_STATUS_READY);
return false;
}
@@ -1393,17 +1434,17 @@ XLogArchiveIsBusy(const char *xlog)
struct stat stat_buf;
/* First check for .done --- this means archiver is done with it */
- StatusFilePath(archiveStatusPath, xlog, ".done");
+ StatusFilePath(archiveStatusPath, xlog, XLOG_ARCHIVE_STATUS_DONE);
if (stat(archiveStatusPath, &stat_buf) == 0)
return false;
/* check for .ready --- this means archiver is still busy with it */
- StatusFilePath(archiveStatusPath, xlog, ".ready");
+ StatusFilePath(archiveStatusPath, xlog, XLOG_ARCHIVE_STATUS_READY);
if (stat(archiveStatusPath, &stat_buf) == 0)
return true;
/* Race condition --- maybe archiver just finished, so recheck */
- StatusFilePath(archiveStatusPath, xlog, ".done");
+ StatusFilePath(archiveStatusPath, xlog, XLOG_ARCHIVE_STATUS_DONE);
if (stat(archiveStatusPath, &stat_buf) == 0)
return false;
@@ -1431,12 +1472,12 @@ XLogArchiveCleanup(const char *xlog)
char archiveStatusPath[MAXPGPATH];
/* Remove the .done file */
- StatusFilePath(archiveStatusPath, xlog, ".done");
+ StatusFilePath(archiveStatusPath, xlog, XLOG_ARCHIVE_STATUS_DONE);
unlink(archiveStatusPath);
/* should we complain about failure? */
/* Remove the .ready file if present --- normally it shouldn't be */
- StatusFilePath(archiveStatusPath, xlog, ".ready");
+ StatusFilePath(archiveStatusPath, xlog, XLOG_ARCHIVE_STATUS_READY);
unlink(archiveStatusPath);
/* should we complain about failure? */
}
@@ -2806,6 +2847,12 @@ XLogFileRead(XLogSegNo segno, int emode, TimeLineID tli,
path, xlogfpath)));
/*
+ * Create .done file forcibly to prevent the restored segment from
+ * being archived again later.
+ */
+ XLogSetArchiveStatus(xlogfname, XLOG_ARCHIVE_STATUS_DONE);
+
+ /*
* If the existing segment was replaced, since walsenders might have
* it open, request them to reload a currently-open segment.
*/
@@ -3573,7 +3620,7 @@ ValidateXLOGDirectoryStructure(void)
/*
* Remove previous backup history files. This also retries creation of
- * .ready files for any backup history files for which XLogArchiveNotify
+ * .ready files for any backup history files for which XLogSetArchiveStatus
* failed earlier.
*/
static void
@@ -4669,7 +4716,7 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
/* The history file can be archived immediately. */
TLHistoryFileName(histfname, newTLI);
- XLogArchiveNotify(histfname);
+ XLogSetArchiveStatus(histfname, XLOG_ARCHIVE_STATUS_READY);
}
/*
@@ -5611,7 +5658,7 @@ exitArchiveRecovery(TimeLineID endTLI, XLogSegNo endLogSegNo)
if (XLogArchivingActive())
{
XLogFileName(xlogpath, endTLI, endLogSegNo);
- XLogArchiveNotify(xlogpath);
+ XLogSetArchiveStatus(xlogpath, XLOG_ARCHIVE_STATUS_READY);
}
}
diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c
index d5d8be0..1a51e17 100644
--- a/src/backend/postmaster/pgarch.c
+++ b/src/backend/postmaster/pgarch.c
@@ -111,7 +111,6 @@ static void pgarch_MainLoop(void);
static void pgarch_ArchiverCopyLoop(void);
static bool pgarch_archiveXlog(char *xlog);
static bool pgarch_readyXlog(char *xlog);
-static void pgarch_archiveDone(char *xlog);
/* ------------------------------------------------------------
@@ -492,7 +491,7 @@ pgarch_ArchiverCopyLoop(void)
if (pgarch_archiveXlog(xlog))
{
/* successful */
- pgarch_archiveDone(xlog);
+ XLogSetArchiveStatus(xlog, XLOG_ARCHIVE_STATUS_DONE);
break; /* out of inner retry loop */
}
else
@@ -730,26 +729,3 @@ pgarch_readyXlog(char *xlog)
}
return found;
}
-
-/*
- * pgarch_archiveDone
- *
- * Emit notification that an xlog file has been successfully archived.
- * We do this by renaming the status file from NNN.ready to NNN.done.
- * Eventually, a checkpoint process will notice this and delete both the
- * NNN.done file and the xlog file itself.
- */
-static void
-pgarch_archiveDone(char *xlog)
-{
- char rlogready[MAXPGPATH];
- char rlogdone[MAXPGPATH];
-
- StatusFilePath(rlogready, xlog, ".ready");
- StatusFilePath(rlogdone, xlog, ".done");
- if (rename(rlogready, rlogdone) < 0)
- ereport(WARNING,
- (errcode_for_file_access(),
- errmsg("could not rename file \"%s\" to \"%s\": %m",
- rlogready, rlogdone)));
-}
diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c
index b0a8b19..9d689c2 100644
--- a/src/backend/replication/walreceiver.c
+++ b/src/backend/replication/walreceiver.c
@@ -505,6 +505,13 @@ XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr)
(errcode_for_file_access(),
errmsg("could not close log segment %s: %m",
XLogFileNameP(recvFileTLI, recvSegNo))));
+
+ /*
+ * Create .done file forcibly to prevent the restored segment from
+ * being archived again later.
+ */
+ XLogSetArchiveStatus(XLogFileNameP(recvFileTLI, recvSegNo),
+ XLOG_ARCHIVE_STATUS_DONE);
}
recvFile = -1;
diff --git a/src/include/access/xlog_internal.h b/src/include/access/xlog_internal.h
index b5bfb7b..78849ce 100644
--- a/src/include/access/xlog_internal.h
+++ b/src/include/access/xlog_internal.h
@@ -192,8 +192,14 @@ typedef XLogLongPageHeaderData *XLogLongPageHeader;
#define TLHistoryFilePath(path, tli) \
snprintf(path, MAXPGPATH, XLOGDIR "/%08X.history", tli)
-#define StatusFilePath(path, xlog, suffix) \
- snprintf(path, MAXPGPATH, XLOGDIR "/archive_status/%s%s", xlog, suffix)
+#define XLOG_ARCHIVE_STATUS_INVALID 0
+#define XLOG_ARCHIVE_STATUS_READY 1
+#define XLOG_ARCHIVE_STATUS_DONE 2
+
+#define StatusFilePath(path, xlog, archive_status) \
+ snprintf(path, MAXPGPATH, XLOGDIR "/archive_status/%s%s", xlog, \
+ (archive_status == XLOG_ARCHIVE_STATUS_READY ? ".ready" : ".done"))
+
#define BackupHistoryFileName(fname, tli, logSegNo, offset) \
snprintf(fname, MAXFNAMELEN, "%08X%08X%08X.%08X.backup", tli, \
@@ -230,6 +236,11 @@ extern pg_time_t GetLastSegSwitchTime(void);
extern XLogRecPtr RequestXLogSwitch(void);
/*
+ * Exported to support xlog archive status setting from WALReceiver/Archiver
+ */
+extern void XLogSetArchiveStatus(const char *xlog, int archive_status);
+
+/*
* These aren't in xlog.h because I'd rather not include fmgr.h there.
*/
extern Datum pg_start_backup(PG_FUNCTION_ARGS);