*** a/src/backend/access/transam/xlogarchive.c --- b/src/backend/access/transam/xlogarchive.c *************** *** 474,479 **** KeepFileRestoredFromArchive(char *path, char *xlogfname) --- 474,485 ---- 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 * open, request them to reload a currently-open segment. This is only * required for WAL segments, walsenders don't hold other files open, but *************** *** 545,550 **** XLogArchiveNotifySeg(XLogSegNo segno) --- 551,609 ---- } /* + * XLogArchiveForceDone + * + * Emit notification forcibly that an XLOG segment file has been successfully + * archived, by creating .done regardless of whether .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 .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 * * This is called when we are ready to delete or recycle an old XLOG segment *** a/src/backend/replication/walreceiver.c --- b/src/backend/replication/walreceiver.c *************** *** 83,89 **** walrcv_disconnect_type walrcv_disconnect = NULL; /* * These variables are used similarly to openLogFile/SegNo/Off, * but for walreceiver to write the XLOG. recvFileTLI is the TimeLineID ! * corresponding the filename of recvFile, used for error messages. */ static int recvFile = -1; static TimeLineID recvFileTLI = 0; --- 83,89 ---- /* * These variables are used similarly to openLogFile/SegNo/Off, * but for walreceiver to write the XLOG. recvFileTLI is the TimeLineID ! * corresponding the filename of recvFile. */ static int recvFile = -1; static TimeLineID recvFileTLI = 0; *************** *** 528,539 **** WalReceiverMain(void) --- 528,548 ---- */ if (recvFile >= 0) { + char xlogfname[MAXFNAMELEN]; + XLogWalRcvFlush(false); if (close(recvFile) != 0) ereport(PANIC, (errcode_for_file_access(), errmsg("could not close log segment %s: %m", XLogFileNameP(recvFileTLI, recvSegNo)))); + + /* + * Create .done file forcibly to prevent the streamed segment from + * being archived later. + */ + XLogFileName(xlogfname, recvFileTLI, recvSegNo); + XLogArchiveForceDone(xlogfname); } recvFile = -1; *************** *** 865,870 **** XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr) --- 874,881 ---- */ if (recvFile >= 0) { + char xlogfname[MAXFNAMELEN]; + XLogWalRcvFlush(false); /* *************** *** 877,882 **** XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr) --- 888,900 ---- (errcode_for_file_access(), errmsg("could not close log segment %s: %m", XLogFileNameP(recvFileTLI, recvSegNo)))); + + /* + * Create .done file forcibly to prevent the streamed segment from + * being archived later. + */ + XLogFileName(xlogfname, recvFileTLI, recvSegNo); + XLogArchiveForceDone(xlogfname); } recvFile = -1; *** a/src/include/access/xlog_internal.h --- b/src/include/access/xlog_internal.h *************** *** 278,283 **** extern void ExecuteRecoveryCommand(char *command, char *commandName, --- 278,284 ---- extern void KeepFileRestoredFromArchive(char *path, char *xlogfname); extern void XLogArchiveNotify(const char *xlog); extern void XLogArchiveNotifySeg(XLogSegNo segno); + extern void XLogArchiveForceDone(const char *xlog); extern bool XLogArchiveCheckDone(const char *xlog); extern bool XLogArchiveIsBusy(const char *xlog); extern void XLogArchiveCleanup(const char *xlog);