Force archive_status of .done for xlogs created by dearchival/replication.
This prevents spurious attempts to archive xlog files after promotion of standby, a bug introduced by cascading replication patch in 9.2. Fujii Masao, simplified and extended to cover streaming by Simon Riggs
This commit is contained in:
parent
7c055d64a6
commit
6f4b8a4f4f
|
@ -1335,6 +1335,59 @@ XLogArchiveNotifySeg(uint32 log, uint32 seg)
|
||||||
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
|
||||||
*
|
*
|
||||||
|
@ -2814,6 +2867,12 @@ XLogFileRead(uint32 log, uint32 seg, int emode, TimeLineID tli,
|
||||||
*/
|
*/
|
||||||
strncpy(path, xlogfpath, MAXPGPATH);
|
strncpy(path, xlogfpath, MAXPGPATH);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create .done file forcibly to prevent the restored segment from
|
||||||
|
* being archived again later.
|
||||||
|
*/
|
||||||
|
XLogArchiveForceDone(xlogfname);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the existing segment was replaced, since walsenders might have
|
* If the existing segment was replaced, since walsenders might have
|
||||||
* it open, request them to reload a currently-open segment.
|
* it open, request them to reload a currently-open segment.
|
||||||
|
|
|
@ -66,10 +66,12 @@ walrcv_disconnect_type walrcv_disconnect = NULL;
|
||||||
#define NAPTIME_PER_CYCLE 100 /* max sleep time between cycles (100ms) */
|
#define NAPTIME_PER_CYCLE 100 /* max sleep time between cycles (100ms) */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These variables are used similarly to openLogFile/Id/Seg/Off,
|
* These variables are used similarly to openLogFile/SegNo/Off,
|
||||||
* but for walreceiver to write the XLOG.
|
* but for walreceiver to write the XLOG. recvFileTLI is the TimeLineID
|
||||||
|
* corresponding the filename of recvFile.
|
||||||
*/
|
*/
|
||||||
static int recvFile = -1;
|
static int recvFile = -1;
|
||||||
|
static TimeLineID recvFileTLI = 0;
|
||||||
static uint32 recvId = 0;
|
static uint32 recvId = 0;
|
||||||
static uint32 recvSeg = 0;
|
static uint32 recvSeg = 0;
|
||||||
static uint32 recvOff = 0;
|
static uint32 recvOff = 0;
|
||||||
|
@ -492,6 +494,8 @@ XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr)
|
||||||
*/
|
*/
|
||||||
if (recvFile >= 0)
|
if (recvFile >= 0)
|
||||||
{
|
{
|
||||||
|
char xlogfname[MAXFNAMELEN];
|
||||||
|
|
||||||
XLogWalRcvFlush(false);
|
XLogWalRcvFlush(false);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -504,6 +508,13 @@ XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr)
|
||||||
(errcode_for_file_access(),
|
(errcode_for_file_access(),
|
||||||
errmsg("could not close log file %u, segment %u: %m",
|
errmsg("could not close log file %u, segment %u: %m",
|
||||||
recvId, recvSeg)));
|
recvId, recvSeg)));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create .done file forcibly to prevent the restored segment from
|
||||||
|
* being archived again later.
|
||||||
|
*/
|
||||||
|
XLogFileName(xlogfname, recvFileTLI, recvId, recvSeg);
|
||||||
|
XLogArchiveForceDone(xlogfname);
|
||||||
}
|
}
|
||||||
recvFile = -1;
|
recvFile = -1;
|
||||||
|
|
||||||
|
@ -511,6 +522,7 @@ XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr)
|
||||||
XLByteToSeg(recptr, recvId, recvSeg);
|
XLByteToSeg(recptr, recvId, recvSeg);
|
||||||
use_existent = true;
|
use_existent = true;
|
||||||
recvFile = XLogFileInit(recvId, recvSeg, &use_existent, true);
|
recvFile = XLogFileInit(recvId, recvSeg, &use_existent, true);
|
||||||
|
recvFileTLI = ThisTimeLineID;
|
||||||
recvOff = 0;
|
recvOff = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -263,6 +263,11 @@ extern const RmgrData RmgrTable[];
|
||||||
extern pg_time_t GetLastSegSwitchTime(void);
|
extern pg_time_t GetLastSegSwitchTime(void);
|
||||||
extern XLogRecPtr RequestXLogSwitch(void);
|
extern XLogRecPtr RequestXLogSwitch(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exported to support xlog archive status setting from WALReceiver
|
||||||
|
*/
|
||||||
|
extern void XLogArchiveForceDone(const char *xlog);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These aren't in xlog.h because I'd rather not include fmgr.h there.
|
* These aren't in xlog.h because I'd rather not include fmgr.h there.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue