Skip to content

Commit 6f4b8a4

Browse files
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
1 parent 7c055d6 commit 6f4b8a4

File tree

3 files changed

+78
-2
lines changed

3 files changed

+78
-2
lines changed

src/backend/access/transam/xlog.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,6 +1335,59 @@ XLogArchiveNotifySeg(uint32 log, uint32 seg)
13351335
XLogArchiveNotify(xlog);
13361336
}
13371337

1338+
/*
1339+
* XLogArchiveForceDone
1340+
*
1341+
* Emit notification forcibly that an XLOG segment file has been successfully
1342+
* archived, by creating <XLOG>.done regardless of whether <XLOG>.ready
1343+
* exists or not.
1344+
*/
1345+
void
1346+
XLogArchiveForceDone(const char *xlog)
1347+
{
1348+
char archiveReady[MAXPGPATH];
1349+
char archiveDone[MAXPGPATH];
1350+
struct stat stat_buf;
1351+
FILE *fd;
1352+
1353+
/* Exit if already known done */
1354+
StatusFilePath(archiveDone, xlog, ".done");
1355+
if (stat(archiveDone, &stat_buf) == 0)
1356+
return;
1357+
1358+
/* If .ready exists, rename it to .done */
1359+
StatusFilePath(archiveReady, xlog, ".ready");
1360+
if (stat(archiveReady, &stat_buf) == 0)
1361+
{
1362+
if (rename(archiveReady, archiveDone) < 0)
1363+
ereport(WARNING,
1364+
(errcode_for_file_access(),
1365+
errmsg("could not rename file \"%s\" to \"%s\": %m",
1366+
archiveReady, archiveDone)));
1367+
1368+
return;
1369+
}
1370+
1371+
/* insert an otherwise empty file called <XLOG>.done */
1372+
fd = AllocateFile(archiveDone, "w");
1373+
if (fd == NULL)
1374+
{
1375+
ereport(LOG,
1376+
(errcode_for_file_access(),
1377+
errmsg("could not create archive status file \"%s\": %m",
1378+
archiveDone)));
1379+
return;
1380+
}
1381+
if (FreeFile(fd))
1382+
{
1383+
ereport(LOG,
1384+
(errcode_for_file_access(),
1385+
errmsg("could not write archive status file \"%s\": %m",
1386+
archiveDone)));
1387+
return;
1388+
}
1389+
}
1390+
13381391
/*
13391392
* XLogArchiveCheckDone
13401393
*
@@ -2814,6 +2867,12 @@ XLogFileRead(uint32 log, uint32 seg, int emode, TimeLineID tli,
28142867
*/
28152868
strncpy(path, xlogfpath, MAXPGPATH);
28162869

2870+
/*
2871+
* Create .done file forcibly to prevent the restored segment from
2872+
* being archived again later.
2873+
*/
2874+
XLogArchiveForceDone(xlogfname);
2875+
28172876
/*
28182877
* If the existing segment was replaced, since walsenders might have
28192878
* it open, request them to reload a currently-open segment.

src/backend/replication/walreceiver.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,12 @@ walrcv_disconnect_type walrcv_disconnect = NULL;
6666
#define NAPTIME_PER_CYCLE 100 /* max sleep time between cycles (100ms) */
6767

6868
/*
69-
* These variables are used similarly to openLogFile/Id/Seg/Off,
70-
* but for walreceiver to write the XLOG.
69+
* These variables are used similarly to openLogFile/SegNo/Off,
70+
* but for walreceiver to write the XLOG. recvFileTLI is the TimeLineID
71+
* corresponding the filename of recvFile.
7172
*/
7273
static int recvFile = -1;
74+
static TimeLineID recvFileTLI = 0;
7375
static uint32 recvId = 0;
7476
static uint32 recvSeg = 0;
7577
static uint32 recvOff = 0;
@@ -492,6 +494,8 @@ XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr)
492494
*/
493495
if (recvFile >= 0)
494496
{
497+
char xlogfname[MAXFNAMELEN];
498+
495499
XLogWalRcvFlush(false);
496500

497501
/*
@@ -504,13 +508,21 @@ XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr)
504508
(errcode_for_file_access(),
505509
errmsg("could not close log file %u, segment %u: %m",
506510
recvId, recvSeg)));
511+
512+
/*
513+
* Create .done file forcibly to prevent the restored segment from
514+
* being archived again later.
515+
*/
516+
XLogFileName(xlogfname, recvFileTLI, recvId, recvSeg);
517+
XLogArchiveForceDone(xlogfname);
507518
}
508519
recvFile = -1;
509520

510521
/* Create/use new log file */
511522
XLByteToSeg(recptr, recvId, recvSeg);
512523
use_existent = true;
513524
recvFile = XLogFileInit(recvId, recvSeg, &use_existent, true);
525+
recvFileTLI = ThisTimeLineID;
514526
recvOff = 0;
515527
}
516528

src/include/access/xlog_internal.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,11 @@ extern const RmgrData RmgrTable[];
263263
extern pg_time_t GetLastSegSwitchTime(void);
264264
extern XLogRecPtr RequestXLogSwitch(void);
265265

266+
/*
267+
* Exported to support xlog archive status setting from WALReceiver
268+
*/
269+
extern void XLogArchiveForceDone(const char *xlog);
270+
266271
/*
267272
* These aren't in xlog.h because I'd rather not include fmgr.h there.
268273
*/

0 commit comments

Comments
 (0)