Commit c2f79ba2 authored by Simon Riggs's avatar Simon Riggs Committed by Heikki Linnakangas

Force archive_status of .done for xlogs created by dearchival/replication.

This is a forward-patch of commit 6f4b8a4f4f7a2d683ff79ab59d3693714b965e3d,
applied to 9.2 back in August. The plan was to do something else in master,
but it looks like it's not going to happen, so let's just apply the 9.2
solution to master as well.

Fujii Masao
parent c9cc7e05
...@@ -473,6 +473,12 @@ KeepFileRestoredFromArchive(char *path, char *xlogfname) ...@@ -473,6 +473,12 @@ KeepFileRestoredFromArchive(char *path, char *xlogfname)
errmsg("could not rename file \"%s\" to \"%s\": %m", errmsg("could not rename file \"%s\" to \"%s\": %m",
path, xlogfpath))); path, xlogfpath)));
/*
* Create .done file forcibly to prevent the restored segment from
* being archived again later.
*/
XLogArchiveForceDone(xlogfname);
/* /*
* If the existing file was replaced, since walsenders might have it * If the existing file was replaced, since walsenders might have it
* open, request them to reload a currently-open segment. This is only * open, request them to reload a currently-open segment. This is only
...@@ -544,6 +550,59 @@ XLogArchiveNotifySeg(XLogSegNo segno) ...@@ -544,6 +550,59 @@ XLogArchiveNotifySeg(XLogSegNo segno)
XLogArchiveNotify(xlog); XLogArchiveNotify(xlog);
} }
/*
* XLogArchiveForceDone
*
* Emit notification forcibly that an XLOG segment file has been successfully
* archived, by creating <XLOG>.done regardless of whether <XLOG>.ready
* exists or not.
*/
void
XLogArchiveForceDone(const char *xlog)
{
char archiveReady[MAXPGPATH];
char archiveDone[MAXPGPATH];
struct stat stat_buf;
FILE *fd;
/* Exit if already known done */
StatusFilePath(archiveDone, xlog, ".done");
if (stat(archiveDone, &stat_buf) == 0)
return;
/* If .ready exists, rename it to .done */
StatusFilePath(archiveReady, xlog, ".ready");
if (stat(archiveReady, &stat_buf) == 0)
{
if (rename(archiveReady, archiveDone) < 0)
ereport(WARNING,
(errcode_for_file_access(),
errmsg("could not rename file \"%s\" to \"%s\": %m",
archiveReady, archiveDone)));
return;
}
/* insert an otherwise empty file called <XLOG>.done */
fd = AllocateFile(archiveDone, "w");
if (fd == NULL)
{
ereport(LOG,
(errcode_for_file_access(),
errmsg("could not create archive status file \"%s\": %m",
archiveDone)));
return;
}
if (FreeFile(fd))
{
ereport(LOG,
(errcode_for_file_access(),
errmsg("could not write archive status file \"%s\": %m",
archiveDone)));
return;
}
}
/* /*
* XLogArchiveCheckDone * XLogArchiveCheckDone
* *
......
...@@ -83,7 +83,7 @@ walrcv_disconnect_type walrcv_disconnect = NULL; ...@@ -83,7 +83,7 @@ walrcv_disconnect_type walrcv_disconnect = NULL;
/* /*
* These variables are used similarly to openLogFile/SegNo/Off, * These variables are used similarly to openLogFile/SegNo/Off,
* but for walreceiver to write the XLOG. recvFileTLI is the TimeLineID * but for walreceiver to write the XLOG. recvFileTLI is the TimeLineID
* corresponding the filename of recvFile, used for error messages. * corresponding the filename of recvFile.
*/ */
static int recvFile = -1; static int recvFile = -1;
static TimeLineID recvFileTLI = 0; static TimeLineID recvFileTLI = 0;
...@@ -528,12 +528,21 @@ WalReceiverMain(void) ...@@ -528,12 +528,21 @@ WalReceiverMain(void)
*/ */
if (recvFile >= 0) if (recvFile >= 0)
{ {
char xlogfname[MAXFNAMELEN];
XLogWalRcvFlush(false); XLogWalRcvFlush(false);
if (close(recvFile) != 0) if (close(recvFile) != 0)
ereport(PANIC, ereport(PANIC,
(errcode_for_file_access(), (errcode_for_file_access(),
errmsg("could not close log segment %s: %m", errmsg("could not close log segment %s: %m",
XLogFileNameP(recvFileTLI, recvSegNo)))); XLogFileNameP(recvFileTLI, recvSegNo))));
/*
* Create .done file forcibly to prevent the streamed segment from
* being archived later.
*/
XLogFileName(xlogfname, recvFileTLI, recvSegNo);
XLogArchiveForceDone(xlogfname);
} }
recvFile = -1; recvFile = -1;
...@@ -865,6 +874,8 @@ XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr) ...@@ -865,6 +874,8 @@ XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr)
*/ */
if (recvFile >= 0) if (recvFile >= 0)
{ {
char xlogfname[MAXFNAMELEN];
XLogWalRcvFlush(false); XLogWalRcvFlush(false);
/* /*
...@@ -877,6 +888,13 @@ XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr) ...@@ -877,6 +888,13 @@ XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr)
(errcode_for_file_access(), (errcode_for_file_access(),
errmsg("could not close log segment %s: %m", errmsg("could not close log segment %s: %m",
XLogFileNameP(recvFileTLI, recvSegNo)))); XLogFileNameP(recvFileTLI, recvSegNo))));
/*
* Create .done file forcibly to prevent the streamed segment from
* being archived later.
*/
XLogFileName(xlogfname, recvFileTLI, recvSegNo);
XLogArchiveForceDone(xlogfname);
} }
recvFile = -1; recvFile = -1;
......
...@@ -278,6 +278,7 @@ extern void ExecuteRecoveryCommand(char *command, char *commandName, ...@@ -278,6 +278,7 @@ extern void ExecuteRecoveryCommand(char *command, char *commandName,
extern void KeepFileRestoredFromArchive(char *path, char *xlogfname); extern void KeepFileRestoredFromArchive(char *path, char *xlogfname);
extern void XLogArchiveNotify(const char *xlog); extern void XLogArchiveNotify(const char *xlog);
extern void XLogArchiveNotifySeg(XLogSegNo segno); extern void XLogArchiveNotifySeg(XLogSegNo segno);
extern void XLogArchiveForceDone(const char *xlog);
extern bool XLogArchiveCheckDone(const char *xlog); extern bool XLogArchiveCheckDone(const char *xlog);
extern bool XLogArchiveIsBusy(const char *xlog); extern bool XLogArchiveIsBusy(const char *xlog);
extern void XLogArchiveCleanup(const char *xlog); extern void XLogArchiveCleanup(const char *xlog);
......
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