1/*-------------------------------------------------------------------------
4 * Base backups can be "targeted", which means that they can be sent
5 * somewhere other than to the client which requested the backup.
6 * Furthermore, new targets can be defined by extensions. This file
7 * contains code to support that functionality.
9 * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group
12 * src/backend/backup/basebackup_target.c
14 *-------------------------------------------------------------------------
24 void *(*check_detail) (
char *,
char *);
56 * Add a new base backup target type.
58 * This is intended for use by server extensions.
62 void *(*check_detail) (
char *,
char *),
69 /* If the target list is not yet initialized, do that first. */
73 /* Search the target type list for an existing entry with this name. */
81 * We found one, so update it.
83 * It is probably not a great idea to call BaseBackupAddTarget for
84 * the same name multiple times, but if it happens, this seems
85 * like the sanest behavior.
94 * We use TopMemoryContext for allocations here to make sure that the data
95 * we need doesn't vanish under us; that's also why we copy the target
96 * name into a newly-allocated chunk of memory.
108 * Look up a base backup target and validate the target_detail.
110 * Extensions that define new backup targets will probably define a new
111 * type of bbsink to match. Validation of the target_detail can be performed
112 * either in the check_detail routine called here, or in the bbsink
113 * constructor, which will be called from BaseBackupGetSink. It's mostly
114 * a matter of taste, but the check_detail function runs somewhat earlier.
121 /* If the target list is not yet initialized, do that first. */
125 /* Search the target type list for a match. */
130 if (strcmp(ttype->
name, target) == 0)
134 /* Found the target. */
136 handle->
type = ttype;
143 /* Did not find the target. */
145 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
146 errmsg(
"unrecognized target: \"%s\"", target)));
148 /* keep compiler quiet */
153 * Construct a bbsink that will implement the backup target.
155 * The get_sink function does all the real work, so all we have to do here
156 * is call it with the correct arguments. Whatever the check_detail function
157 * returned is here passed through to the get_sink function. This lets those
158 * two functions communicate with each other, if they wish. If not, the
159 * check_detail function can simply return the target_detail and let the
160 * get_sink function take it from there.
169 * Load predefined target types into BaseBackupTargetTypeList.
178 while (ttype->
name != NULL)
187 * Normally, a get_sink function should construct and return a new bbsink that
188 * implements the backup target, but the 'blackhole' target just throws the
189 * data away. We could implement that by adding a bbsink that does nothing
190 * but forward, but it's even cheaper to implement that by not adding a bbsink
200 * Create a bbsink implementing a server-side backup.
209 * Implement target-detail checking for a target that does not accept a
215 if (target_detail != NULL)
217 (
errcode(ERRCODE_SYNTAX_ERROR),
218 errmsg(
"target \"%s\" does not accept a target detail",
225 * Implement target-detail checking for a server-side backup.
227 * target_detail should be the name of the directory to which the backup
228 * should be written, but we don't check that here. Rather, that check,
229 * as well as the necessary permissions checking, happens in bbsink_server_new.
234 if (target_detail == NULL)
236 (
errcode(ERRCODE_SYNTAX_ERROR),
237 errmsg(
"target \"%s\" requires a target detail",
240 return target_detail;
bbsink * bbsink_server_new(bbsink *next, char *pathname)
struct BaseBackupTargetType BaseBackupTargetType
static void * reject_target_detail(char *target, char *target_detail)
BaseBackupTargetHandle * BaseBackupGetTargetHandle(char *target, char *target_detail)
static bbsink * server_get_sink(bbsink *next_sink, void *detail_arg)
static List * BaseBackupTargetTypeList
static bbsink * blackhole_get_sink(bbsink *next_sink, void *detail_arg)
bbsink * BaseBackupGetSink(BaseBackupTargetHandle *handle, bbsink *next_sink)
static BaseBackupTargetType builtin_backup_targets[]
static void * server_check_detail(char *target, char *target_detail)
void BaseBackupAddTarget(char *name, void *(*check_detail)(char *, char *), bbsink *(*get_sink)(bbsink *, void *))
static void initialize_target_list(void)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
List * lappend(List *list, void *datum)
char * pstrdup(const char *in)
MemoryContext TopMemoryContext
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
BaseBackupTargetType * type
void *(* check_detail)(char *, char *)
bbsink *(* get_sink)(bbsink *, void *)