From 19558633522b64b92ac9491077273bd58507aec1 Mon Sep 17 00:00:00 2001
From: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>
Date: Thu, 13 Oct 2022 13:02:57 +0000
Subject: [PATCH v5] Add functions for xlogbackup.c to call back into xlog.c

---
 src/backend/access/transam/xlog.c  | 194 +++++++++++++++++++----------
 src/include/access/xlog.h          |   1 +
 src/include/access/xlog_internal.h |  11 ++
 3 files changed, 141 insertions(+), 65 deletions(-)

diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index c9c1c6f287..4412817804 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -8313,10 +8313,7 @@ do_pg_backup_start(const char *backupidstr, bool fast, List **tablespaces,
 	 * forcePageWrites, to ensure adequate interlocking against
 	 * XLogInsertRecord().
 	 */
-	WALInsertLockAcquireExclusive();
-	XLogCtl->Insert.runningBackups++;
-	XLogCtl->Insert.forcePageWrites = true;
-	WALInsertLockRelease();
+	SetXLogBackupActivity();
 
 	/* Ensure we release forcePageWrites if fail below */
 	PG_ENSURE_ERROR_CLEANUP(do_pg_abort_backup, DatumGetBool(false));
@@ -8382,12 +8379,8 @@ do_pg_backup_start(const char *backupidstr, bool fast, List **tablespaces,
 			 * to restore starting from the checkpoint is precisely the REDO
 			 * pointer.
 			 */
-			LWLockAcquire(ControlFileLock, LW_SHARED);
-			state->checkpointloc = ControlFile->checkPoint;
-			state->startpoint = ControlFile->checkPointCopy.redo;
-			state->starttli = ControlFile->checkPointCopy.ThisTimeLineID;
-			checkpointfpw = ControlFile->checkPointCopy.fullPageWrites;
-			LWLockRelease(ControlFileLock);
+			GetCheckpointLocation(&state->checkpointloc, &state->startpoint,
+								  &state->starttli, &checkpointfpw);
 
 			if (backup_started_in_recovery)
 			{
@@ -8398,9 +8391,7 @@ do_pg_backup_start(const char *backupidstr, bool fast, List **tablespaces,
 				 * (i.e., since last restartpoint used as backup starting
 				 * checkpoint) contain full-page writes.
 				 */
-				SpinLockAcquire(&XLogCtl->info_lck);
-				recptr = XLogCtl->lastFpwDisableRecPtr;
-				SpinLockRelease(&XLogCtl->info_lck);
+				recptr = GetlastFpwDisableRecPtr();
 
 				if (!checkpointfpw || state->startpoint <= recptr)
 					ereport(ERROR,
@@ -8433,13 +8424,7 @@ do_pg_backup_start(const char *backupidstr, bool fast, List **tablespaces,
 			 * taking a checkpoint right after another is not that expensive
 			 * either because only few buffers have been dirtied yet.
 			 */
-			WALInsertLockAcquireExclusive();
-			if (XLogCtl->Insert.lastBackupStart < state->startpoint)
-			{
-				XLogCtl->Insert.lastBackupStart = state->startpoint;
-				gotUniqueStartpoint = true;
-			}
-			WALInsertLockRelease();
+			gotUniqueStartpoint = SetlastBackupStart(state->startpoint);
 		} while (!gotUniqueStartpoint);
 
 		/*
@@ -8548,6 +8533,15 @@ get_backup_status(void)
 	return sessionBackupState;
 }
 
+/*
+ * Utility routine to reset the session-level status of a backup running.
+ */
+void
+reset_backup_status(void)
+{
+	sessionBackupState = SESSION_BACKUP_NONE;
+}
+
 /*
  * do_pg_backup_stop
  *
@@ -8594,33 +8588,11 @@ do_pg_backup_stop(BackupState *state, bool waitforarchive)
 	 * Note that CHECK_FOR_INTERRUPTS() must not occur while updating them.
 	 * Otherwise they can be updated inconsistently, and which might cause
 	 * do_pg_abort_backup() to fail.
-	 */
-	WALInsertLockAcquireExclusive();
-
-	/*
-	 * It is expected that each do_pg_backup_start() call is matched by
-	 * exactly one do_pg_backup_stop() call.
-	 */
-	Assert(XLogCtl->Insert.runningBackups > 0);
-	XLogCtl->Insert.runningBackups--;
-
-	if (XLogCtl->Insert.runningBackups == 0)
-	{
-		XLogCtl->Insert.forcePageWrites = false;
-	}
-
-	/*
-	 * Clean up session-level lock.
 	 *
-	 * You might think that WALInsertLockRelease() can be called before
-	 * cleaning up session-level lock because session-level lock doesn't need
-	 * to be protected with WAL insertion lock. But since
-	 * CHECK_FOR_INTERRUPTS() can occur in it, session-level lock must be
-	 * cleaned up before it.
+	 * It is expected that each do_pg_backup_start() call is matched by exactly
+	 * one do_pg_backup_stop() call.
 	 */
-	sessionBackupState = SESSION_BACKUP_NONE;
-
-	WALInsertLockRelease();
+	ResetXLogBackupActivity();
 
 	/*
 	 * If we are taking an online backup from the standby, we confirm that the
@@ -8670,9 +8642,7 @@ do_pg_backup_stop(BackupState *state, bool waitforarchive)
 		 * Check to see if all WAL replayed during online backup contain
 		 * full-page writes.
 		 */
-		SpinLockAcquire(&XLogCtl->info_lck);
-		recptr = XLogCtl->lastFpwDisableRecPtr;
-		SpinLockRelease(&XLogCtl->info_lck);
+		recptr = GetlastFpwDisableRecPtr();
 
 		if (state->startpoint <= recptr)
 			ereport(ERROR,
@@ -8684,11 +8654,7 @@ do_pg_backup_stop(BackupState *state, bool waitforarchive)
 							 "Enable full_page_writes and run CHECKPOINT on the primary, "
 							 "and then try an online backup again.")));
 
-
-		LWLockAcquire(ControlFileLock, LW_SHARED);
-		state->stoppoint = ControlFile->minRecoveryPoint;
-		state->stoptli = ControlFile->minRecoveryPointTLI;
-		LWLockRelease(ControlFileLock);
+		GetminRecoveryPoint(&state->stoppoint, &state->stoptli);
 	}
 	else
 	{
@@ -8706,7 +8672,7 @@ do_pg_backup_stop(BackupState *state, bool waitforarchive)
 		 * Given that we're not in recovery, InsertTimeLineID is set and can't
 		 * change, so we can read it without a lock.
 		 */
-		state->stoptli = XLogCtl->InsertTimeLineID;
+		state->stoptli = GetWALInsertionTimeLine();
 
 		/*
 		 * Force a switch to a new xlog segment file, so that the backup is
@@ -8848,17 +8814,7 @@ do_pg_abort_backup(int code, Datum arg)
 	if (sessionBackupState != SESSION_BACKUP_RUNNING)
 		return;
 
-	WALInsertLockAcquireExclusive();
-	Assert(XLogCtl->Insert.runningBackups > 0);
-	XLogCtl->Insert.runningBackups--;
-
-	if (XLogCtl->Insert.runningBackups == 0)
-	{
-		XLogCtl->Insert.forcePageWrites = false;
-	}
-
-	sessionBackupState = SESSION_BACKUP_NONE;
-	WALInsertLockRelease();
+	ResetXLogBackupActivity();
 
 	if (emit_warning)
 		ereport(WARNING,
@@ -8880,6 +8836,114 @@ register_persistent_abort_backup_handler(void)
 	already_done = true;
 }
 
+/*
+ * Get the checkpoint location.
+ */
+void
+GetCheckpointLocation(XLogRecPtr *loc, XLogRecPtr *redoloc,
+					  TimeLineID *tli, bool *fpw)
+{
+	LWLockAcquire(ControlFileLock, LW_SHARED);
+	*loc = ControlFile->checkPoint;
+	*redoloc = ControlFile->checkPointCopy.redo;
+	*tli = ControlFile->checkPointCopy.ThisTimeLineID;
+	*fpw = ControlFile->checkPointCopy.fullPageWrites;
+	LWLockRelease(ControlFileLock);
+}
+
+/*
+ * Get the minRecoveryPoint and minRecoveryPointTLI.
+ */
+void
+GetminRecoveryPoint(XLogRecPtr *loc, TimeLineID *tli)
+{
+	LWLockAcquire(ControlFileLock, LW_SHARED);
+	*loc = ControlFile->minRecoveryPoint;
+	*tli = ControlFile->minRecoveryPointTLI;
+	LWLockRelease(ControlFileLock);
+}
+
+/*
+ * Get the lastFpwDisableRecPtr.
+ */
+XLogRecPtr
+GetlastFpwDisableRecPtr(void)
+{
+	XLogRecPtr recptr;
+
+	SpinLockAcquire(&XLogCtl->info_lck);
+	recptr = XLogCtl->lastFpwDisableRecPtr;
+	SpinLockRelease(&XLogCtl->info_lck);
+
+	return recptr;
+}
+
+/*
+ * Set the lastBackupStar only if it is less than passed-in rectpr and return
+ * true. Otherwise return false.
+ *
+ * Note: For those who want to set lastBackupStar unconditionally, pass rectpr
+ * value as PG_UINT64_MAX, which is higher than any real XLogRecPtr value.
+ */
+bool
+SetlastBackupStart(XLogRecPtr recptr)
+{
+	bool is_set = false;
+
+	WALInsertLockAcquireExclusive();
+	if (XLogCtl->Insert.lastBackupStart < recptr)
+	{
+		XLogCtl->Insert.lastBackupStart = recptr;
+		is_set = true;
+	}
+	WALInsertLockRelease();
+
+	return is_set;
+}
+
+/*
+ * Reset backup activity such as runningBackups, forcePageWrites and
+ * session-level status.
+ */
+void
+ResetXLogBackupActivity(void)
+{
+	WALInsertLockAcquireExclusive();
+
+	Assert(XLogCtl->Insert.runningBackups > 0);
+	XLogCtl->Insert.runningBackups--;
+
+	if (XLogCtl->Insert.runningBackups == 0)
+	{
+		XLogCtl->Insert.forcePageWrites = false;
+	}
+
+	/*
+	 * Reset session-level lock.
+	 *
+	 * You might think that WALInsertLockRelease() can be called before
+	 * cleaning up session-level lock because session-level lock doesn't need
+	 * to be protected with WAL insertion lock. But since
+	 * CHECK_FOR_INTERRUPTS() can occur in it, session-level lock must be
+	 * cleaned up before it.
+	 */
+	reset_backup_status();
+
+	WALInsertLockRelease();
+}
+
+/*
+ * Set backup activity such as runningBackups and forcePageWrites.
+ */
+void
+SetXLogBackupActivity(void)
+{
+	WALInsertLockAcquireExclusive();
+	XLogCtl->Insert.runningBackups++;
+	XLogCtl->Insert.forcePageWrites = true;
+	WALInsertLockRelease();
+}
+
 /*
  * Get latest WAL insert pointer
  */
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index 1fbd48fbda..b46adca291 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -285,6 +285,7 @@ extern void do_pg_backup_stop(BackupState *state, bool waitforarchive);
 extern void do_pg_abort_backup(int code, Datum arg);
 extern void register_persistent_abort_backup_handler(void);
 extern SessionBackupState get_backup_status(void);
+extern void reset_backup_status(void);
 
 /* File path names (all relative to $PGDATA) */
 #define RECOVERY_SIGNAL_FILE	"recovery.signal"
diff --git a/src/include/access/xlog_internal.h b/src/include/access/xlog_internal.h
index 44291b337b..d1f53d2512 100644
--- a/src/include/access/xlog_internal.h
+++ b/src/include/access/xlog_internal.h
@@ -401,4 +401,15 @@ extern PGDLLIMPORT bool InArchiveRecovery;
 extern PGDLLIMPORT bool StandbyMode;
 extern PGDLLIMPORT char *recoveryRestoreCommand;
 
+/*
+ * Routines used by xlogbackup.c to call back into xlog.c during backup.
+ */
+extern void GetCheckpointLocation(XLogRecPtr *loc, XLogRecPtr *redoloc,
+								  TimeLineID *tli, bool *fpw);
+extern void GetminRecoveryPoint(XLogRecPtr *loc, TimeLineID *tli);
+extern XLogRecPtr GetlastFpwDisableRecPtr(void);
+extern bool SetlastBackupStart(XLogRecPtr recptr);
+extern void ResetXLogBackupActivity(void);
+extern void SetXLogBackupActivity(void);
+
 #endif							/* XLOG_INTERNAL_H */
-- 
2.34.1

