From cb49c761f783d07067b7e7c1101a1b7aea0e6fe6 Mon Sep 17 00:00:00 2001
From: Robert Haas <rhaas@postgresql.org>
Date: Mon, 18 Apr 2022 16:01:13 -0400
Subject: [PATCH v4 2/2] Remove previous timeline ID from checkpoint.

Since recovery now always ends with an end-of-recovery record rather
than a checkpoint, a checkpoint never causes a timeline switch.
Therefore, it doesn't need to store a previous timeline ID and a
current timeline ID any more.

Note that this affects the signature of the SQL-callable function
pg_control_checkpoint().
---
 doc/src/sgml/func.sgml                    |  5 --
 src/backend/access/rmgrdesc/xlogdesc.c    |  3 +-
 src/backend/access/transam/xlog.c         |  2 -
 src/backend/access/transam/xlogrecovery.c | 32 +++++-------
 src/backend/utils/misc/pg_controldata.c   | 61 +++++++++++------------
 src/bin/pg_controldata/pg_controldata.c   |  2 -
 src/bin/pg_resetwal/pg_resetwal.c         |  4 --
 src/include/catalog/pg_control.h          |  4 +-
 src/include/catalog/pg_proc.dat           |  6 +--
 9 files changed, 45 insertions(+), 74 deletions(-)

diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 93ba39eff1..4c92e9e56d 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -27626,11 +27626,6 @@ SELECT collation for ('foo' COLLATE "de_DE");
        <entry><type>integer</type></entry>
       </row>
 
-      <row>
-       <entry><structfield>prev_timeline_id</structfield></entry>
-       <entry><type>integer</type></entry>
-      </row>
-
       <row>
        <entry><structfield>full_page_writes</structfield></entry>
        <entry><type>boolean</type></entry>
diff --git a/src/backend/access/rmgrdesc/xlogdesc.c b/src/backend/access/rmgrdesc/xlogdesc.c
index c0dfea40c7..a3e29b043f 100644
--- a/src/backend/access/rmgrdesc/xlogdesc.c
+++ b/src/backend/access/rmgrdesc/xlogdesc.c
@@ -45,13 +45,12 @@ xlog_desc(StringInfo buf, XLogReaderState *record)
 		CheckPoint *checkpoint = (CheckPoint *) rec;
 
 		appendStringInfo(buf, "redo %X/%X; "
-						 "tli %u; prev tli %u; fpw %s; xid %u:%u; oid %u; multi %u; offset %u; "
+						 "tli %u; fpw %s; xid %u:%u; oid %u; multi %u; offset %u; "
 						 "oldest xid %u in DB %u; oldest multi %u in DB %u; "
 						 "oldest/newest commit timestamp xid: %u/%u; "
 						 "oldest running xid %u; %s",
 						 LSN_FORMAT_ARGS(checkpoint->redo),
 						 checkpoint->ThisTimeLineID,
-						 checkpoint->PrevTimeLineID,
 						 checkpoint->fullPageWrites ? "true" : "false",
 						 EpochFromFullTransactionId(checkpoint->nextXid),
 						 XidFromFullTransactionId(checkpoint->nextXid),
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 6f67ffa3c3..c1784bb386 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -4539,7 +4539,6 @@ BootStrapXLOG(void)
 	 */
 	checkPoint.redo = wal_segment_size + SizeOfXLogLongPHD;
 	checkPoint.ThisTimeLineID = BootstrapTimeLineID;
-	checkPoint.PrevTimeLineID = BootstrapTimeLineID;
 	checkPoint.fullPageWrites = fullPageWrites;
 	checkPoint.nextXid = starting_fxid;
 	checkPoint.nextOid = FirstGenbkiObjectId;
@@ -6306,7 +6305,6 @@ CreateCheckPoint(int flags)
 	}
 
 	checkPoint.ThisTimeLineID = XLogCtl->InsertTimeLineID;
-	checkPoint.PrevTimeLineID = checkPoint.ThisTimeLineID;
 
 	checkPoint.fullPageWrites = Insert->fullPageWrites;
 
diff --git a/src/backend/access/transam/xlogrecovery.c b/src/backend/access/transam/xlogrecovery.c
index 39ef865ed9..14a3ee96a3 100644
--- a/src/backend/access/transam/xlogrecovery.c
+++ b/src/backend/access/transam/xlogrecovery.c
@@ -1833,36 +1833,28 @@ ApplyWalRecord(XLogReaderState *xlogreader, XLogRecord *record, TimeLineID *repl
 	 */
 	if (record->xl_rmid == RM_XLOG_ID)
 	{
-		TimeLineID	newReplayTLI = *replayTLI;
-		TimeLineID	prevReplayTLI = *replayTLI;
 		uint8		info = record->xl_info & ~XLR_INFO_MASK;
 
-		if (info == XLOG_CHECKPOINT_SHUTDOWN)
-		{
-			CheckPoint	checkPoint;
-
-			memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
-			newReplayTLI = checkPoint.ThisTimeLineID;
-			prevReplayTLI = checkPoint.PrevTimeLineID;
-		}
-		else if (info == XLOG_END_OF_RECOVERY)
+		if (info == XLOG_END_OF_RECOVERY)
 		{
 			xl_end_of_recovery xlrec;
+			TimeLineID	newReplayTLI;
+			TimeLineID	prevReplayTLI;
 
 			memcpy(&xlrec, XLogRecGetData(xlogreader), sizeof(xl_end_of_recovery));
 			newReplayTLI = xlrec.ThisTimeLineID;
 			prevReplayTLI = xlrec.PrevTimeLineID;
-		}
 
-		if (newReplayTLI != *replayTLI)
-		{
-			/* Check that it's OK to switch to this TLI */
-			checkTimeLineSwitch(xlogreader->EndRecPtr,
-								newReplayTLI, prevReplayTLI, *replayTLI);
+			if (newReplayTLI != *replayTLI)
+			{
+				/* Check that it's OK to switch to this TLI */
+				checkTimeLineSwitch(xlogreader->EndRecPtr,
+									newReplayTLI, prevReplayTLI, *replayTLI);
 
-			/* Following WAL records should be run with new TLI */
-			*replayTLI = newReplayTLI;
-			switchedTLI = true;
+				/* Following WAL records should be run with new TLI */
+				*replayTLI = newReplayTLI;
+				switchedTLI = true;
+			}
 		}
 	}
 
diff --git a/src/backend/utils/misc/pg_controldata.c b/src/backend/utils/misc/pg_controldata.c
index 781f8b8758..c30f380d07 100644
--- a/src/backend/utils/misc/pg_controldata.c
+++ b/src/backend/utils/misc/pg_controldata.c
@@ -101,33 +101,31 @@ pg_control_checkpoint(PG_FUNCTION_ARGS)
 					   TEXTOID, -1, 0);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 4, "timeline_id",
 					   INT4OID, -1, 0);
-	TupleDescInitEntry(tupdesc, (AttrNumber) 5, "prev_timeline_id",
-					   INT4OID, -1, 0);
-	TupleDescInitEntry(tupdesc, (AttrNumber) 6, "full_page_writes",
+	TupleDescInitEntry(tupdesc, (AttrNumber) 5, "full_page_writes",
 					   BOOLOID, -1, 0);
-	TupleDescInitEntry(tupdesc, (AttrNumber) 7, "next_xid",
+	TupleDescInitEntry(tupdesc, (AttrNumber) 6, "next_xid",
 					   TEXTOID, -1, 0);
-	TupleDescInitEntry(tupdesc, (AttrNumber) 8, "next_oid",
+	TupleDescInitEntry(tupdesc, (AttrNumber) 7, "next_oid",
 					   OIDOID, -1, 0);
-	TupleDescInitEntry(tupdesc, (AttrNumber) 9, "next_multixact_id",
+	TupleDescInitEntry(tupdesc, (AttrNumber) 8, "next_multixact_id",
 					   XIDOID, -1, 0);
-	TupleDescInitEntry(tupdesc, (AttrNumber) 10, "next_multi_offset",
+	TupleDescInitEntry(tupdesc, (AttrNumber) 9, "next_multi_offset",
 					   XIDOID, -1, 0);
-	TupleDescInitEntry(tupdesc, (AttrNumber) 11, "oldest_xid",
+	TupleDescInitEntry(tupdesc, (AttrNumber) 10, "oldest_xid",
 					   XIDOID, -1, 0);
-	TupleDescInitEntry(tupdesc, (AttrNumber) 12, "oldest_xid_dbid",
+	TupleDescInitEntry(tupdesc, (AttrNumber) 11, "oldest_xid_dbid",
 					   OIDOID, -1, 0);
-	TupleDescInitEntry(tupdesc, (AttrNumber) 13, "oldest_active_xid",
+	TupleDescInitEntry(tupdesc, (AttrNumber) 12, "oldest_active_xid",
 					   XIDOID, -1, 0);
-	TupleDescInitEntry(tupdesc, (AttrNumber) 14, "oldest_multi_xid",
+	TupleDescInitEntry(tupdesc, (AttrNumber) 13, "oldest_multi_xid",
 					   XIDOID, -1, 0);
-	TupleDescInitEntry(tupdesc, (AttrNumber) 15, "oldest_multi_dbid",
+	TupleDescInitEntry(tupdesc, (AttrNumber) 14, "oldest_multi_dbid",
 					   OIDOID, -1, 0);
-	TupleDescInitEntry(tupdesc, (AttrNumber) 16, "oldest_commit_ts_xid",
+	TupleDescInitEntry(tupdesc, (AttrNumber) 15, "oldest_commit_ts_xid",
 					   XIDOID, -1, 0);
-	TupleDescInitEntry(tupdesc, (AttrNumber) 17, "newest_commit_ts_xid",
+	TupleDescInitEntry(tupdesc, (AttrNumber) 16, "newest_commit_ts_xid",
 					   XIDOID, -1, 0);
-	TupleDescInitEntry(tupdesc, (AttrNumber) 18, "checkpoint_time",
+	TupleDescInitEntry(tupdesc, (AttrNumber) 17, "checkpoint_time",
 					   TIMESTAMPTZOID, -1, 0);
 	tupdesc = BlessTupleDesc(tupdesc);
 
@@ -158,50 +156,47 @@ pg_control_checkpoint(PG_FUNCTION_ARGS)
 	values[3] = Int32GetDatum(ControlFile->checkPointCopy.ThisTimeLineID);
 	nulls[3] = false;
 
-	values[4] = Int32GetDatum(ControlFile->checkPointCopy.PrevTimeLineID);
+	values[4] = BoolGetDatum(ControlFile->checkPointCopy.fullPageWrites);
 	nulls[4] = false;
 
-	values[5] = BoolGetDatum(ControlFile->checkPointCopy.fullPageWrites);
-	nulls[5] = false;
-
-	values[6] = CStringGetTextDatum(psprintf("%u:%u",
+	values[5] = CStringGetTextDatum(psprintf("%u:%u",
 											 EpochFromFullTransactionId(ControlFile->checkPointCopy.nextXid),
 											 XidFromFullTransactionId(ControlFile->checkPointCopy.nextXid)));
+	nulls[5] = false;
+
+	values[6] = ObjectIdGetDatum(ControlFile->checkPointCopy.nextOid);
 	nulls[6] = false;
 
-	values[7] = ObjectIdGetDatum(ControlFile->checkPointCopy.nextOid);
+	values[7] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMulti);
 	nulls[7] = false;
 
-	values[8] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMulti);
+	values[8] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMultiOffset);
 	nulls[8] = false;
 
-	values[9] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMultiOffset);
+	values[9] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestXid);
 	nulls[9] = false;
 
-	values[10] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestXid);
+	values[10] = ObjectIdGetDatum(ControlFile->checkPointCopy.oldestXidDB);
 	nulls[10] = false;
 
-	values[11] = ObjectIdGetDatum(ControlFile->checkPointCopy.oldestXidDB);
+	values[11] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestActiveXid);
 	nulls[11] = false;
 
-	values[12] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestActiveXid);
+	values[12] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestMulti);
 	nulls[12] = false;
 
-	values[13] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestMulti);
+	values[13] = ObjectIdGetDatum(ControlFile->checkPointCopy.oldestMultiDB);
 	nulls[13] = false;
 
-	values[14] = ObjectIdGetDatum(ControlFile->checkPointCopy.oldestMultiDB);
+	values[14] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestCommitTsXid);
 	nulls[14] = false;
 
-	values[15] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestCommitTsXid);
+	values[15] = TransactionIdGetDatum(ControlFile->checkPointCopy.newestCommitTsXid);
 	nulls[15] = false;
 
-	values[16] = TransactionIdGetDatum(ControlFile->checkPointCopy.newestCommitTsXid);
+	values[16] = TimestampTzGetDatum(time_t_to_timestamptz(ControlFile->checkPointCopy.time));
 	nulls[16] = false;
 
-	values[17] = TimestampTzGetDatum(time_t_to_timestamptz(ControlFile->checkPointCopy.time));
-	nulls[17] = false;
-
 	htup = heap_form_tuple(tupdesc, values, nulls);
 
 	PG_RETURN_DATUM(HeapTupleGetDatum(htup));
diff --git a/src/bin/pg_controldata/pg_controldata.c b/src/bin/pg_controldata/pg_controldata.c
index c390ec51ce..56dc8d0031 100644
--- a/src/bin/pg_controldata/pg_controldata.c
+++ b/src/bin/pg_controldata/pg_controldata.c
@@ -243,8 +243,6 @@ main(int argc, char *argv[])
 		   xlogfilename);
 	printf(_("Latest checkpoint's TimeLineID:       %u\n"),
 		   ControlFile->checkPointCopy.ThisTimeLineID);
-	printf(_("Latest checkpoint's PrevTimeLineID:   %u\n"),
-		   ControlFile->checkPointCopy.PrevTimeLineID);
 	printf(_("Latest checkpoint's full_page_writes: %s\n"),
 		   ControlFile->checkPointCopy.fullPageWrites ? _("on") : _("off"));
 	printf(_("Latest checkpoint's NextXID:          %u:%u\n"),
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index d4772a2965..2e2f35bf5c 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -444,10 +444,7 @@ main(int argc, char *argv[])
 		ControlFile.checkPointCopy.nextMultiOffset = set_mxoff;
 
 	if (minXlogTli > ControlFile.checkPointCopy.ThisTimeLineID)
-	{
 		ControlFile.checkPointCopy.ThisTimeLineID = minXlogTli;
-		ControlFile.checkPointCopy.PrevTimeLineID = minXlogTli;
-	}
 
 	if (set_wal_segsize != 0)
 		ControlFile.xlog_seg_size = WalSegSz;
@@ -650,7 +647,6 @@ GuessControlValues(void)
 
 	ControlFile.checkPointCopy.redo = SizeOfXLogLongPHD;
 	ControlFile.checkPointCopy.ThisTimeLineID = 1;
-	ControlFile.checkPointCopy.PrevTimeLineID = 1;
 	ControlFile.checkPointCopy.fullPageWrites = false;
 	ControlFile.checkPointCopy.nextXid =
 		FullTransactionIdFromEpochAndXid(0, FirstNormalTransactionId);
diff --git a/src/include/catalog/pg_control.h b/src/include/catalog/pg_control.h
index 06368e2366..b0da5cb1b5 100644
--- a/src/include/catalog/pg_control.h
+++ b/src/include/catalog/pg_control.h
@@ -22,7 +22,7 @@
 
 
 /* Version identifier for this pg_control format */
-#define PG_CONTROL_VERSION	1300
+#define PG_CONTROL_VERSION	1600
 
 /* Nonce key length, see below */
 #define MOCK_AUTH_NONCE_LEN		32
@@ -37,8 +37,6 @@ typedef struct CheckPoint
 	XLogRecPtr	redo;			/* next RecPtr available when we began to
 								 * create CheckPoint (i.e. REDO start point) */
 	TimeLineID	ThisTimeLineID; /* current TLI */
-	TimeLineID	PrevTimeLineID; /* previous TLI, if this record begins a new
-								 * timeline (equals ThisTimeLineID otherwise) */
 	bool		fullPageWrites; /* current full_page_writes */
 	FullTransactionId nextXid;	/* next free transaction ID */
 	Oid			nextOid;		/* next free OID */
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 6d378ff785..c2bd6f0801 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -11711,9 +11711,9 @@
   descr => 'pg_controldata checkpoint state information as a function',
   proname => 'pg_control_checkpoint', provolatile => 'v',
   prorettype => 'record', proargtypes => '',
-  proallargtypes => '{pg_lsn,pg_lsn,text,int4,int4,bool,text,oid,xid,xid,xid,oid,xid,xid,oid,xid,xid,timestamptz}',
-  proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
-  proargnames => '{checkpoint_lsn,redo_lsn,redo_wal_file,timeline_id,prev_timeline_id,full_page_writes,next_xid,next_oid,next_multixact_id,next_multi_offset,oldest_xid,oldest_xid_dbid,oldest_active_xid,oldest_multi_xid,oldest_multi_dbid,oldest_commit_ts_xid,newest_commit_ts_xid,checkpoint_time}',
+  proallargtypes => '{pg_lsn,pg_lsn,text,int4,bool,text,oid,xid,xid,xid,oid,xid,xid,oid,xid,xid,timestamptz}',
+  proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
+  proargnames => '{checkpoint_lsn,redo_lsn,redo_wal_file,timeline_id,full_page_writes,next_xid,next_oid,next_multixact_id,next_multi_offset,oldest_xid,oldest_xid_dbid,oldest_active_xid,oldest_multi_xid,oldest_multi_dbid,oldest_commit_ts_xid,newest_commit_ts_xid,checkpoint_time}',
   prosrc => 'pg_control_checkpoint' },
 
 { oid => '3443',
-- 
2.24.3 (Apple Git-128)

