From 10425b3c062ed3972c0ad067adb7c14c5dca43c8 Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horikyoga.ntt@gmail.com>
Date: Thu, 18 Jun 2020 14:49:48 +0900
Subject: [PATCH v2 2/2] Forcibly initialize lastRemovedSegNo at the first
 checkpoint

If we have a replication slot retaining all existing WAL segments, a
checkpoint doesn't initialize lastRemovedSegNo. That means
pg_replication_slots can not show min_safe_lsn until any slot loses a
segment. Forcibly initialize it even if no WAL segments are removed at
the first checkpoint.
---
 src/backend/access/transam/xlog.c | 33 +++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 940f5fcb18..282bac32ab 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -4025,6 +4025,16 @@ RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr lastredoptr, XLogRecPtr endptr)
 	DIR		   *xldir;
 	struct dirent *xlde;
 	char		lastoff[MAXFNAMELEN];
+	char		oldest[MAXFNAMELEN];
+	bool		remember_oldest = false;
+
+	/*
+	 * If we haven't set the initial last removed segno, force to set it even
+	 * if we wouldn't have removed any segments.
+	 */
+	oldest[0] = 0;
+	if (XLogGetLastRemovedSegno() == 0)
+		remember_oldest = true;
 
 	/*
 	 * Construct a filename of the last segment to be kept. The timeline ID
@@ -4062,10 +4072,33 @@ RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr lastredoptr, XLogRecPtr endptr)
 			{
 				/* Update the last removed location in shared memory first */
 				UpdateLastRemovedPtr(xlde->d_name);
+				remember_oldest = false;
 
 				RemoveXlogFile(xlde->d_name, lastredoptr, endptr);
 			}
 		}
+		/* Remember the oldest file left in the directotry */
+		else if(remember_oldest &&
+				(oldest[0] == 0 || strcmp(xlde->d_name + 8, oldest + 8) < 0))
+			strncpy(oldest, xlde->d_name, MAXFNAMELEN);
+	}
+
+	/*
+	 * We haven't initialize the pointer, initialize it.
+	 * The last removed pointer is the oldest existing segment minus 1.
+	 */
+	if (remember_oldest && oldest[0] != 0)
+	{
+		uint32		tli;
+		XLogSegNo	segno;
+
+		XLogFromFileName(oldest, &tli, &segno, wal_segment_size);
+
+		if (segno > 1)
+		{
+			XLogFileName(oldest, tli, segno - 1, wal_segment_size);
+			UpdateLastRemovedPtr(oldest);
+		}
 	}
 
 	FreeDir(xldir);
-- 
2.18.4

