LCOV - differential code coverage report
Current view: top level - src/backend/backup - basebackup_target.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 89.8 % 49 44 5 44
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 8 8 8
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (180,240] days: 100.0 % 5 5 5
Legend: Lines: hit not hit (240..) days: 88.6 % 44 39 5 39
Function coverage date bins:
(240..) days: 100.0 % 8 8 8

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * basebackup_target.c
                                  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.
                                  8                 :  *
                                  9                 :  * Portions Copyright (c) 2010-2023, PostgreSQL Global Development Group
                                 10                 :  *
                                 11                 :  * IDENTIFICATION
                                 12                 :  *    src/backend/backup/basebackup_target.c
                                 13                 :  *
                                 14                 :  *-------------------------------------------------------------------------
                                 15                 :  */
                                 16                 : #include "postgres.h"
                                 17                 : 
                                 18                 : #include "backup/basebackup_target.h"
                                 19                 : #include "utils/memutils.h"
                                 20                 : 
                                 21                 : typedef struct BaseBackupTargetType
                                 22                 : {
                                 23                 :     char       *name;
                                 24                 :     void       *(*check_detail) (char *, char *);
                                 25                 :     bbsink     *(*get_sink) (bbsink *, void *);
                                 26                 : } BaseBackupTargetType;
                                 27                 : 
                                 28                 : struct BaseBackupTargetHandle
                                 29                 : {
                                 30                 :     BaseBackupTargetType *type;
                                 31                 :     void       *detail_arg;
                                 32                 : };
                                 33                 : 
                                 34                 : static void initialize_target_list(void);
                                 35                 : static bbsink *blackhole_get_sink(bbsink *next_sink, void *detail_arg);
                                 36                 : static bbsink *server_get_sink(bbsink *next_sink, void *detail_arg);
                                 37                 : static void *reject_target_detail(char *target, char *target_detail);
                                 38                 : static void *server_check_detail(char *target, char *target_detail);
                                 39                 : 
                                 40                 : static BaseBackupTargetType builtin_backup_targets[] =
                                 41                 : {
                                 42                 :     {
                                 43                 :         "blackhole", reject_target_detail, blackhole_get_sink
                                 44                 :     },
                                 45                 :     {
                                 46                 :         "server", server_check_detail, server_get_sink
                                 47                 :     },
                                 48                 :     {
                                 49                 :         NULL
                                 50                 :     }
                                 51                 : };
                                 52                 : 
                                 53                 : static List *BaseBackupTargetTypeList = NIL;
                                 54                 : 
                                 55                 : /*
                                 56                 :  * Add a new base backup target type.
                                 57                 :  *
                                 58                 :  * This is intended for use by server extensions.
                                 59                 :  */
                                 60                 : void
  390 rhaas                      61 CBC           1 : BaseBackupAddTarget(char *name,
                                 62                 :                     void *(*check_detail) (char *, char *),
                                 63                 :                     bbsink *(*get_sink) (bbsink *, void *))
                                 64                 : {
                                 65                 :     BaseBackupTargetType *newtype;
                                 66                 :     MemoryContext oldcontext;
                                 67                 :     ListCell   *lc;
                                 68                 : 
                                 69                 :     /* If the target list is not yet initialized, do that first. */
                                 70               1 :     if (BaseBackupTargetTypeList == NIL)
                                 71               1 :         initialize_target_list();
                                 72                 : 
                                 73                 :     /* Search the target type list for an existing entry with this name. */
                                 74               3 :     foreach(lc, BaseBackupTargetTypeList)
                                 75                 :     {
                                 76               2 :         BaseBackupTargetType *ttype = lfirst(lc);
                                 77                 : 
                                 78               2 :         if (strcmp(ttype->name, name) == 0)
                                 79                 :         {
                                 80                 :             /*
                                 81                 :              * We found one, so update it.
                                 82                 :              *
                                 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.
                                 86                 :              */
  390 rhaas                      87 UBC           0 :             ttype->check_detail = check_detail;
                                 88               0 :             ttype->get_sink = get_sink;
                                 89               0 :             return;
                                 90                 :         }
                                 91                 :     }
                                 92                 : 
                                 93                 :     /*
                                 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.
                                 97                 :      */
  390 rhaas                      98 CBC           1 :     oldcontext = MemoryContextSwitchTo(TopMemoryContext);
  232 drowley                    99               1 :     newtype = palloc(sizeof(BaseBackupTargetType));
                                100               1 :     newtype->name = pstrdup(name);
                                101               1 :     newtype->check_detail = check_detail;
                                102               1 :     newtype->get_sink = get_sink;
                                103               1 :     BaseBackupTargetTypeList = lappend(BaseBackupTargetTypeList, newtype);
  390 rhaas                     104               1 :     MemoryContextSwitchTo(oldcontext);
                                105                 : }
                                106                 : 
                                107                 : /*
                                108                 :  * Look up a base backup target and validate the target_detail.
                                109                 :  *
                                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.
                                115                 :  */
                                116                 : BaseBackupTargetHandle *
                                117              15 : BaseBackupGetTargetHandle(char *target, char *target_detail)
                                118                 : {
                                119                 :     ListCell   *lc;
                                120                 : 
                                121                 :     /* If the target list is not yet initialized, do that first. */
                                122              15 :     if (BaseBackupTargetTypeList == NIL)
                                123               9 :         initialize_target_list();
                                124                 : 
                                125                 :     /* Search the target type list for a match. */
                                126              36 :     foreach(lc, BaseBackupTargetTypeList)
                                127                 :     {
                                128              35 :         BaseBackupTargetType *ttype = lfirst(lc);
                                129                 : 
                                130              35 :         if (strcmp(ttype->name, target) == 0)
                                131                 :         {
                                132                 :             BaseBackupTargetHandle *handle;
                                133                 : 
                                134                 :             /* Found the target. */
                                135              14 :             handle = palloc(sizeof(BaseBackupTargetHandle));
                                136              14 :             handle->type = ttype;
                                137              14 :             handle->detail_arg = ttype->check_detail(target, target_detail);
                                138                 : 
                                139              13 :             return handle;
                                140                 :         }
                                141                 :     }
                                142                 : 
                                143                 :     /* Did not find the target. */
                                144               1 :     ereport(ERROR,
                                145                 :             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                146                 :              errmsg("unrecognized target: \"%s\"", target)));
                                147                 : 
                                148                 :     /* keep compiler quiet */
                                149                 :     return NULL;
                                150                 : }
                                151                 : 
                                152                 : /*
                                153                 :  * Construct a bbsink that will implement the backup target.
                                154                 :  *
                                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.
                                161                 :  */
                                162                 : bbsink *
                                163              13 : BaseBackupGetSink(BaseBackupTargetHandle *handle, bbsink *next_sink)
                                164                 : {
                                165              13 :     return handle->type->get_sink(next_sink, handle->detail_arg);
                                166                 : }
                                167                 : 
                                168                 : /*
                                169                 :  * Load predefined target types into BaseBackupTargetTypeList.
                                170                 :  */
                                171                 : static void
                                172              10 : initialize_target_list(void)
                                173                 : {
                                174              10 :     BaseBackupTargetType *ttype = builtin_backup_targets;
                                175                 :     MemoryContext oldcontext;
                                176                 : 
                                177              10 :     oldcontext = MemoryContextSwitchTo(TopMemoryContext);
                                178              30 :     while (ttype->name != NULL)
                                179                 :     {
                                180              20 :         BaseBackupTargetTypeList = lappend(BaseBackupTargetTypeList, ttype);
                                181              20 :         ++ttype;
                                182                 :     }
                                183              10 :     MemoryContextSwitchTo(oldcontext);
                                184              10 : }
                                185                 : 
                                186                 : /*
                                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
                                191                 :  * at all.
                                192                 :  */
                                193                 : static bbsink *
                                194               1 : blackhole_get_sink(bbsink *next_sink, void *detail_arg)
                                195                 : {
                                196               1 :     return next_sink;
                                197                 : }
                                198                 : 
                                199                 : /*
                                200                 :  * Create a bbsink implementing a server-side backup.
                                201                 :  */
                                202                 : static bbsink *
                                203               7 : server_get_sink(bbsink *next_sink, void *detail_arg)
                                204                 : {
                                205               7 :     return bbsink_server_new(next_sink, detail_arg);
                                206                 : }
                                207                 : 
                                208                 : /*
                                209                 :  * Implement target-detail checking for a target that does not accept a
                                210                 :  * detail.
                                211                 :  */
                                212                 : static void *
                                213               1 : reject_target_detail(char *target, char *target_detail)
                                214                 : {
                                215               1 :     if (target_detail != NULL)
  390 rhaas                     216 UBC           0 :         ereport(ERROR,
                                217                 :                 (errcode(ERRCODE_SYNTAX_ERROR),
                                218                 :                  errmsg("target \"%s\" does not accept a target detail",
                                219                 :                         target)));
                                220                 : 
  390 rhaas                     221 CBC           1 :     return NULL;
                                222                 : }
                                223                 : 
                                224                 : /*
                                225                 :  * Implement target-detail checking for a server-side backup.
                                226                 :  *
                                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.
                                230                 :  */
                                231                 : static void *
                                232               7 : server_check_detail(char *target, char *target_detail)
                                233                 : {
                                234               7 :     if (target_detail == NULL)
  390 rhaas                     235 UBC           0 :         ereport(ERROR,
                                236                 :                 (errcode(ERRCODE_SYNTAX_ERROR),
                                237                 :                  errmsg("target \"%s\" requires a target detail",
                                238                 :                         target)));
                                239                 : 
  390 rhaas                     240 CBC           7 :     return target_detail;
                                241                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a