From efa1393e63d44931322c9efc33823f917438bf17 Mon Sep 17 00:00:00 2001
From: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>
Date: Thu, 13 Oct 2022 13:17:14 +0000
Subject: [PATCH v5] Move backup-related code from xlogfuncs.c to xlogbackup.c

---
 src/backend/access/transam/xlogbackup.c | 134 +++++++++++++++++++++++-
 src/backend/access/transam/xlogfuncs.c  | 131 -----------------------
 2 files changed, 133 insertions(+), 132 deletions(-)

diff --git a/src/backend/access/transam/xlogbackup.c b/src/backend/access/transam/xlogbackup.c
index 085ca93928..be378f97ad 100644
--- a/src/backend/access/transam/xlogbackup.c
+++ b/src/backend/access/transam/xlogbackup.c
@@ -1,7 +1,7 @@
 /*-------------------------------------------------------------------------
  *
  * xlogbackup.c
- *		Internal routines for base backups.
+ *		Internal routines and SQL-callable functions for base backups.
  *
  * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
@@ -24,12 +24,16 @@
 #include "backup/basebackup.h"
 #include "catalog/pg_control.h"
 #include "common/file_utils.h"
+#include "funcapi.h"
 #include "miscadmin.h"
 #include "postmaster/bgwriter.h"
 #include "storage/fd.h"
 #include "storage/ipc.h"
 #include "storage/latch.h"
 #include "storage/lwlock.h"
+#include "utils/builtins.h"
+#include "utils/memutils.h"
+#include "utils/pg_lsn.h"
 #include "utils/wait_event.h"
 
 /*
@@ -38,6 +42,12 @@
  */
 static SessionBackupState sessionBackupState = SESSION_BACKUP_NONE;
 
+/*
+ * Session-level backup-related variables for SQL-callable functions.
+ */
+static BackupState *backup_state = NULL;
+static StringInfo tablespace_map = NULL;
+
 static void CleanupBackupHistory(void);
 
 /*
@@ -735,3 +745,125 @@ register_persistent_abort_backup_handler(void)
 	before_shmem_exit(do_pg_abort_backup, DatumGetBool(true));
 	already_done = true;
 }
+
+/*
+ * pg_backup_start: set up for taking an on-line backup dump
+ *
+ * Essentially what this does is to create the contents required for the
+ * backup_label file and the tablespace map.
+ *
+ * Permission checking for this function is managed through the normal
+ * GRANT system.
+ */
+Datum
+pg_backup_start(PG_FUNCTION_ARGS)
+{
+	text	   *backupid = PG_GETARG_TEXT_PP(0);
+	bool		fast = PG_GETARG_BOOL(1);
+	char	   *backupidstr;
+	SessionBackupState status = get_backup_status();
+	MemoryContext oldcontext;
+
+	backupidstr = text_to_cstring(backupid);
+
+	if (status == SESSION_BACKUP_RUNNING)
+		ereport(ERROR,
+				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+				 errmsg("a backup is already in progress in this session")));
+
+	/*
+	 * backup_state and tablespace_map need to be long-lived as they are used
+	 * in pg_backup_stop().
+	 */
+	oldcontext = MemoryContextSwitchTo(TopMemoryContext);
+
+	/* Allocate backup state or reset it, if it comes from a previous run */
+	if (backup_state == NULL)
+		backup_state = (BackupState *) palloc0(sizeof(BackupState));
+	else
+		MemSet(backup_state, 0, sizeof(BackupState));
+
+	/*
+	 * tablespace_map may have been created in a previous backup, so take this
+	 * occasion to clean it.
+	 */
+	if (tablespace_map != NULL)
+	{
+		pfree(tablespace_map->data);
+		pfree(tablespace_map);
+		tablespace_map = NULL;
+	}
+
+	tablespace_map = makeStringInfo();
+	MemoryContextSwitchTo(oldcontext);
+
+	register_persistent_abort_backup_handler();
+	do_pg_backup_start(backupidstr, fast, NULL, backup_state, tablespace_map);
+
+	PG_RETURN_LSN(backup_state->startpoint);
+}
+
+/*
+ * pg_backup_stop: finish taking an on-line backup.
+ *
+ * The first parameter (variable 'waitforarchive'), which is optional,
+ * allows the user to choose if they want to wait for the WAL to be archived
+ * or if we should just return as soon as the WAL record is written.
+ *
+ * This function stops an in-progress backup, creates backup_label contents and
+ * it returns the backup stop LSN, backup_label and tablespace_map contents.
+ *
+ * The backup_label contains the user-supplied label string (typically this
+ * would be used to tell where the backup dump will be stored), the starting
+ * time, starting WAL location for the dump and so on.  It is the caller's
+ * responsibility to write the backup_label and tablespace_map files in the
+ * data folder that will be restored from this backup.
+ *
+ * Permission checking for this function is managed through the normal
+ * GRANT system.
+ */
+Datum
+pg_backup_stop(PG_FUNCTION_ARGS)
+{
+#define PG_BACKUP_STOP_V2_COLS 3
+	TupleDesc	tupdesc;
+	Datum		values[PG_BACKUP_STOP_V2_COLS] = {0};
+	bool		nulls[PG_BACKUP_STOP_V2_COLS] = {0};
+	bool		waitforarchive = PG_GETARG_BOOL(0);
+	char	   *backup_label;
+	SessionBackupState status = get_backup_status();
+
+	/* Initialize attributes information in the tuple descriptor */
+	if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
+		elog(ERROR, "return type must be a row type");
+
+	if (status != SESSION_BACKUP_RUNNING)
+		ereport(ERROR,
+				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+				 errmsg("backup is not in progress"),
+				 errhint("Did you call pg_backup_start()?")));
+
+	Assert(backup_state != NULL);
+	Assert(tablespace_map != NULL);
+
+	/* Stop the backup */
+	do_pg_backup_stop(backup_state, waitforarchive);
+
+	/* Build the contents of backup_label */
+	backup_label = build_backup_content(backup_state, false);
+
+	values[0] = LSNGetDatum(backup_state->stoppoint);
+	values[1] = CStringGetTextDatum(backup_label);
+	values[2] = CStringGetTextDatum(tablespace_map->data);
+
+	/* Deallocate backup-related variables */
+	pfree(backup_state);
+	backup_state = NULL;
+	pfree(tablespace_map->data);
+	pfree(tablespace_map);
+	tablespace_map = NULL;
+	pfree(backup_label);
+
+	/* Returns the record as Datum */
+	PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
+}
diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c
index a801a94fe8..bd049d0e6d 100644
--- a/src/backend/access/transam/xlogfuncs.c
+++ b/src/backend/access/transam/xlogfuncs.c
@@ -20,7 +20,6 @@
 
 #include "access/htup_details.h"
 #include "access/xlog_internal.h"
-#include "access/xlogbackup.h"
 #include "access/xlogrecovery.h"
 #include "access/xlogutils.h"
 #include "catalog/pg_type.h"
@@ -33,141 +32,11 @@
 #include "storage/smgr.h"
 #include "utils/builtins.h"
 #include "utils/guc.h"
-#include "utils/memutils.h"
 #include "utils/numeric.h"
 #include "utils/pg_lsn.h"
 #include "utils/timestamp.h"
 #include "utils/tuplestore.h"
 
-/*
- * Backup-related variables.
- */
-static BackupState *backup_state = NULL;
-static StringInfo tablespace_map = NULL;
-
-/*
- * pg_backup_start: set up for taking an on-line backup dump
- *
- * Essentially what this does is to create the contents required for the
- * backup_label file and the tablespace map.
- *
- * Permission checking for this function is managed through the normal
- * GRANT system.
- */
-Datum
-pg_backup_start(PG_FUNCTION_ARGS)
-{
-	text	   *backupid = PG_GETARG_TEXT_PP(0);
-	bool		fast = PG_GETARG_BOOL(1);
-	char	   *backupidstr;
-	SessionBackupState status = get_backup_status();
-	MemoryContext oldcontext;
-
-	backupidstr = text_to_cstring(backupid);
-
-	if (status == SESSION_BACKUP_RUNNING)
-		ereport(ERROR,
-				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
-				 errmsg("a backup is already in progress in this session")));
-
-	/*
-	 * backup_state and tablespace_map need to be long-lived as they are used
-	 * in pg_backup_stop().
-	 */
-	oldcontext = MemoryContextSwitchTo(TopMemoryContext);
-
-	/* Allocate backup state or reset it, if it comes from a previous run */
-	if (backup_state == NULL)
-		backup_state = (BackupState *) palloc0(sizeof(BackupState));
-	else
-		MemSet(backup_state, 0, sizeof(BackupState));
-
-	/*
-	 * tablespace_map may have been created in a previous backup, so take this
-	 * occasion to clean it.
-	 */
-	if (tablespace_map != NULL)
-	{
-		pfree(tablespace_map->data);
-		pfree(tablespace_map);
-		tablespace_map = NULL;
-	}
-
-	tablespace_map = makeStringInfo();
-	MemoryContextSwitchTo(oldcontext);
-
-	register_persistent_abort_backup_handler();
-	do_pg_backup_start(backupidstr, fast, NULL, backup_state, tablespace_map);
-
-	PG_RETURN_LSN(backup_state->startpoint);
-}
-
-
-/*
- * pg_backup_stop: finish taking an on-line backup.
- *
- * The first parameter (variable 'waitforarchive'), which is optional,
- * allows the user to choose if they want to wait for the WAL to be archived
- * or if we should just return as soon as the WAL record is written.
- *
- * This function stops an in-progress backup, creates backup_label contents and
- * it returns the backup stop LSN, backup_label and tablespace_map contents.
- *
- * The backup_label contains the user-supplied label string (typically this
- * would be used to tell where the backup dump will be stored), the starting
- * time, starting WAL location for the dump and so on.  It is the caller's
- * responsibility to write the backup_label and tablespace_map files in the
- * data folder that will be restored from this backup.
- *
- * Permission checking for this function is managed through the normal
- * GRANT system.
- */
-Datum
-pg_backup_stop(PG_FUNCTION_ARGS)
-{
-#define PG_BACKUP_STOP_V2_COLS 3
-	TupleDesc	tupdesc;
-	Datum		values[PG_BACKUP_STOP_V2_COLS] = {0};
-	bool		nulls[PG_BACKUP_STOP_V2_COLS] = {0};
-	bool		waitforarchive = PG_GETARG_BOOL(0);
-	char	   *backup_label;
-	SessionBackupState status = get_backup_status();
-
-	/* Initialize attributes information in the tuple descriptor */
-	if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
-		elog(ERROR, "return type must be a row type");
-
-	if (status != SESSION_BACKUP_RUNNING)
-		ereport(ERROR,
-				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
-				 errmsg("backup is not in progress"),
-				 errhint("Did you call pg_backup_start()?")));
-
-	Assert(backup_state != NULL);
-	Assert(tablespace_map != NULL);
-
-	/* Stop the backup */
-	do_pg_backup_stop(backup_state, waitforarchive);
-
-	/* Build the contents of backup_label */
-	backup_label = build_backup_content(backup_state, false);
-
-	values[0] = LSNGetDatum(backup_state->stoppoint);
-	values[1] = CStringGetTextDatum(backup_label);
-	values[2] = CStringGetTextDatum(tablespace_map->data);
-
-	/* Deallocate backup-related variables */
-	pfree(backup_state);
-	backup_state = NULL;
-	pfree(tablespace_map->data);
-	pfree(tablespace_map);
-	tablespace_map = NULL;
-	pfree(backup_label);
-
-	/* Returns the record as Datum */
-	PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
-}
-
 /*
  * pg_switch_wal: switch to next xlog file
  *
-- 
2.34.1

