From 931b6db39b808608a3c80c42b47e3cbcda9e66db Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Mon, 1 Nov 2010 09:56:45 +0200
Subject: [PATCH] Fix corner-case bug in tracking of latest removed WAL segment
 during streaming replication. We used log/seg 0/0 to indicate that no WAL
 segments have been removed since startup, but 0/0 is a valid value for the
 very first WAL segment after initdb. To make that disambiguous, store (latest
 removed WAL segment + 1) in the global variable.

Per report from Matt Chesler, also reproduced by Greg Smith.
---
 src/backend/access/transam/xlog.c   | 9 ++++++---
 src/backend/replication/walsender.c | 2 +-
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 6f1fedd1140..97dced113a9 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -364,7 +364,7 @@ typedef struct XLogCtlData
 	uint32		ckptXidEpoch;	/* nextXID & epoch of latest checkpoint */
 	TransactionId ckptXid;
 	XLogRecPtr	asyncXactLSN; /* LSN of newest async commit/abort */
-	uint32		lastRemovedLog; /* latest removed/recycled XLOG segment */
+	uint32		lastRemovedLog; /* latest removed/recycled XLOG segment + 1 */
 	uint32		lastRemovedSeg;
 
 	/* Protected by WALWriteLock: */
@@ -3218,8 +3218,10 @@ PreallocXlogFiles(XLogRecPtr endptr)
 }
 
 /*
- * Get the log/seg of the latest removed or recycled WAL segment.
- * Returns 0 if no WAL segments have been removed since startup.
+ * Get the log/seg of the first WAL segment that has not been removed or
+ * recycled. In other words, the log/seg of the last removed/recycled WAL
+ * segment + 1.
+ * Returns 0/0 if no WAL segments have been removed since startup.
  */
 void
 XLogGetLastRemoved(uint32 *log, uint32 *seg)
@@ -3247,6 +3249,7 @@ UpdateLastRemovedPtr(char *filename)
 				seg;
 
 	XLogFromFileName(filename, &tli, &log, &seg);
+	NextLogSeg(log, seg);
 
 	SpinLockAcquire(&xlogctl->info_lck);
 	if (log > xlogctl->lastRemovedLog ||
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index d2b9e5c5f9a..3dc794ccc9c 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -654,7 +654,7 @@ XLogRead(char *buf, XLogRecPtr recptr, Size nbytes)
 	XLogGetLastRemoved(&lastRemovedLog, &lastRemovedSeg);
 	XLByteToSeg(startRecPtr, log, seg);
 	if (log < lastRemovedLog ||
-		(log == lastRemovedLog && seg <= lastRemovedSeg))
+		(log == lastRemovedLog && seg < lastRemovedSeg))
 	{
 		char		filename[MAXFNAMELEN];
 
-- 
GitLab