mirror of
https://github.com/postgres/postgres.git
synced 2025-06-13 07:41:39 +03:00
Redesign archive modules
A new callback named startup_cb, called shortly after a module is loaded, is added. This makes possible the initialization of any additional state data required by a module. This initial state data can be saved in a ArchiveModuleState, that is now passed down to all the callbacks that can be defined in a module. With this design, it is possible to have a per-module state, aimed at opening the door to the support of more than one archive module. The initialization of the callbacks is changed so as _PG_archive_module_init() does not anymore give in input a ArchiveModuleCallbacks that a module has to fill in with callback definitions. Instead, a module now needs to return a const ArchiveModuleCallbacks. All the structure and callback definitions of archive modules are moved into their own header, named archive_module.h, from pgarch.h. Command-based archiving follows the same line, with a new set of files named shell_archive.{c,h}. There are a few more items that are under discussion to improve the design of archive modules, like the fact that basic_archive calls sigsetjmp() by itself to define its own error handling flow. These will be adjusted later, the changes done here cover already a good portion of what has been discussed. Any modules created for v15 will need to be adjusted to this new design. Author: Nathan Bossart Reviewed-by: Andres Freund Discussion: https://postgr.es/m/20230130194810.6fztfgbn32e7qarj@awork3.anarazel.de
This commit is contained in:
@ -30,9 +30,9 @@
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "archive/archive_module.h"
|
||||
#include "common/int.h"
|
||||
#include "miscadmin.h"
|
||||
#include "postmaster/pgarch.h"
|
||||
#include "storage/copydir.h"
|
||||
#include "storage/fd.h"
|
||||
#include "utils/guc.h"
|
||||
@ -40,14 +40,27 @@
|
||||
|
||||
PG_MODULE_MAGIC;
|
||||
|
||||
static char *archive_directory = NULL;
|
||||
static MemoryContext basic_archive_context;
|
||||
typedef struct BasicArchiveData
|
||||
{
|
||||
MemoryContext context;
|
||||
} BasicArchiveData;
|
||||
|
||||
static bool basic_archive_configured(void);
|
||||
static bool basic_archive_file(const char *file, const char *path);
|
||||
static char *archive_directory = NULL;
|
||||
|
||||
static void basic_archive_startup(ArchiveModuleState *state);
|
||||
static bool basic_archive_configured(ArchiveModuleState *state);
|
||||
static bool basic_archive_file(ArchiveModuleState *state, const char *file, const char *path);
|
||||
static void basic_archive_file_internal(const char *file, const char *path);
|
||||
static bool check_archive_directory(char **newval, void **extra, GucSource source);
|
||||
static bool compare_files(const char *file1, const char *file2);
|
||||
static void basic_archive_shutdown(ArchiveModuleState *state);
|
||||
|
||||
static const ArchiveModuleCallbacks basic_archive_callbacks = {
|
||||
.startup_cb = basic_archive_startup,
|
||||
.check_configured_cb = basic_archive_configured,
|
||||
.archive_file_cb = basic_archive_file,
|
||||
.shutdown_cb = basic_archive_shutdown
|
||||
};
|
||||
|
||||
/*
|
||||
* _PG_init
|
||||
@ -67,10 +80,6 @@ _PG_init(void)
|
||||
check_archive_directory, NULL, NULL);
|
||||
|
||||
MarkGUCPrefixReserved("basic_archive");
|
||||
|
||||
basic_archive_context = AllocSetContextCreate(TopMemoryContext,
|
||||
"basic_archive",
|
||||
ALLOCSET_DEFAULT_SIZES);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -78,11 +87,28 @@ _PG_init(void)
|
||||
*
|
||||
* Returns the module's archiving callbacks.
|
||||
*/
|
||||
void
|
||||
_PG_archive_module_init(ArchiveModuleCallbacks *cb)
|
||||
const ArchiveModuleCallbacks *
|
||||
_PG_archive_module_init(void)
|
||||
{
|
||||
cb->check_configured_cb = basic_archive_configured;
|
||||
cb->archive_file_cb = basic_archive_file;
|
||||
return &basic_archive_callbacks;
|
||||
}
|
||||
|
||||
/*
|
||||
* basic_archive_startup
|
||||
*
|
||||
* Creates the module's memory context.
|
||||
*/
|
||||
void
|
||||
basic_archive_startup(ArchiveModuleState *state)
|
||||
{
|
||||
BasicArchiveData *data;
|
||||
|
||||
data = (BasicArchiveData *) MemoryContextAllocZero(TopMemoryContext,
|
||||
sizeof(BasicArchiveData));
|
||||
data->context = AllocSetContextCreate(TopMemoryContext,
|
||||
"basic_archive",
|
||||
ALLOCSET_DEFAULT_SIZES);
|
||||
state->private_data = (void *) data;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -133,7 +159,7 @@ check_archive_directory(char **newval, void **extra, GucSource source)
|
||||
* Checks that archive_directory is not blank.
|
||||
*/
|
||||
static bool
|
||||
basic_archive_configured(void)
|
||||
basic_archive_configured(ArchiveModuleState *state)
|
||||
{
|
||||
return archive_directory != NULL && archive_directory[0] != '\0';
|
||||
}
|
||||
@ -144,10 +170,12 @@ basic_archive_configured(void)
|
||||
* Archives one file.
|
||||
*/
|
||||
static bool
|
||||
basic_archive_file(const char *file, const char *path)
|
||||
basic_archive_file(ArchiveModuleState *state, const char *file, const char *path)
|
||||
{
|
||||
sigjmp_buf local_sigjmp_buf;
|
||||
MemoryContext oldcontext;
|
||||
BasicArchiveData *data = (BasicArchiveData *) state->private_data;
|
||||
MemoryContext basic_archive_context = data->context;
|
||||
|
||||
/*
|
||||
* We run basic_archive_file_internal() in our own memory context so that
|
||||
@ -366,3 +394,35 @@ compare_files(const char *file1, const char *file2)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* basic_archive_shutdown
|
||||
*
|
||||
* Frees our allocated state.
|
||||
*/
|
||||
static void
|
||||
basic_archive_shutdown(ArchiveModuleState *state)
|
||||
{
|
||||
BasicArchiveData *data = (BasicArchiveData *) state->private_data;
|
||||
MemoryContext basic_archive_context;
|
||||
|
||||
/*
|
||||
* If we didn't get to storing the pointer to our allocated state, we don't
|
||||
* have anything to clean up.
|
||||
*/
|
||||
if (data == NULL)
|
||||
return;
|
||||
|
||||
basic_archive_context = data->context;
|
||||
Assert(CurrentMemoryContext != basic_archive_context);
|
||||
|
||||
if (MemoryContextIsValid(basic_archive_context))
|
||||
MemoryContextDelete(basic_archive_context);
|
||||
data->context = NULL;
|
||||
|
||||
/*
|
||||
* Finally, free the state.
|
||||
*/
|
||||
pfree(data);
|
||||
state->private_data = NULL;
|
||||
}
|
||||
|
Reference in New Issue
Block a user