From 6daa9c6f46337c6a5c924264d86a05c15edf7346 Mon Sep 17 00:00:00 2001 From: Bharath Rupireddy Date: Fri, 14 Oct 2022 12:46:00 +0000 Subject: [PATCH v6] 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 a079dba9c3..8308123a9d 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); /* @@ -736,3 +746,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