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 16@8cea358b128 vs 17@8cea358b128 Lines: 89.8 % 49 44 5 44
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 8 8 8
Baseline: 16@8cea358b128 Branches: 65.6 % 32 21 11 21
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed (240..) days: 89.8 % 49 44 5 44
Function coverage date bins:
(240..) days: 100.0 % 8 8 8
Branch coverage date bins:
(240..) days: 65.6 % 32 21 11 21

 Age         Owner                    Branch data    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-2024, 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
  761 rhaas@postgresql.org       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                 :                :              */
  761 rhaas@postgresql.org       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                 :                :      */
  761 rhaas@postgresql.org       98                 :CBC           1 :     oldcontext = MemoryContextSwitchTo(TopMemoryContext);
  603 drowley@postgresql.o       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);
  761 rhaas@postgresql.org      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)
  761 rhaas@postgresql.org      216         [ #  # ]:UBC           0 :         ereport(ERROR,
                                217                 :                :                 (errcode(ERRCODE_SYNTAX_ERROR),
                                218                 :                :                  errmsg("target \"%s\" does not accept a target detail",
                                219                 :                :                         target)));
                                220                 :                : 
  761 rhaas@postgresql.org      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)
  761 rhaas@postgresql.org      235         [ #  # ]:UBC           0 :         ereport(ERROR,
                                236                 :                :                 (errcode(ERRCODE_SYNTAX_ERROR),
                                237                 :                :                  errmsg("target \"%s\" requires a target detail",
                                238                 :                :                         target)));
                                239                 :                : 
  761 rhaas@postgresql.org      240                 :CBC           7 :     return target_detail;
                                241                 :                : }
        

Generated by: LCOV version 2.1-beta2-3-g6141622