LCOV - differential code coverage report
Current view: top level - src/backend/storage/ipc - dsm_registry.c (source / functions) Coverage Total Hit UNC GNC
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 89.5 % 57 51 6 51
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 4 4 4
Baseline: 16@8cea358b128 Branches: 41.7 % 36 15 21 15
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed [..60] days: 100.0 % 1 1 1
(60,120] days: 89.3 % 56 50 6 50
Function coverage date bins:
(60,120] days: 100.0 % 4 4 4
Branch coverage date bins:
(60,120] days: 41.7 % 36 15 21 15

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * dsm_registry.c
                                  4                 :                :  *    Functions for interfacing with the dynamic shared memory registry.
                                  5                 :                :  *
                                  6                 :                :  * This provides a way for libraries to use shared memory without needing
                                  7                 :                :  * to request it at startup time via a shmem_request_hook.  The registry
                                  8                 :                :  * stores dynamic shared memory (DSM) segment handles keyed by a
                                  9                 :                :  * library-specified string.
                                 10                 :                :  *
                                 11                 :                :  * The registry is accessed by calling GetNamedDSMSegment().  If a segment
                                 12                 :                :  * with the provided name does not yet exist, it is created and initialized
                                 13                 :                :  * with the provided init_callback callback function.  Otherwise,
                                 14                 :                :  * GetNamedDSMSegment() simply ensures that the segment is attached to the
                                 15                 :                :  * current backend.  This function guarantees that only one backend
                                 16                 :                :  * initializes the segment and that all other backends just attach it.
                                 17                 :                :  *
                                 18                 :                :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
                                 19                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                 20                 :                :  *
                                 21                 :                :  * IDENTIFICATION
                                 22                 :                :  *    src/backend/storage/ipc/dsm_registry.c
                                 23                 :                :  *
                                 24                 :                :  *-------------------------------------------------------------------------
                                 25                 :                :  */
                                 26                 :                : 
                                 27                 :                : #include "postgres.h"
                                 28                 :                : 
                                 29                 :                : #include "lib/dshash.h"
                                 30                 :                : #include "storage/dsm_registry.h"
                                 31                 :                : #include "storage/lwlock.h"
                                 32                 :                : #include "storage/shmem.h"
                                 33                 :                : #include "utils/memutils.h"
                                 34                 :                : 
                                 35                 :                : typedef struct DSMRegistryCtxStruct
                                 36                 :                : {
                                 37                 :                :     dsa_handle  dsah;
                                 38                 :                :     dshash_table_handle dshh;
                                 39                 :                : } DSMRegistryCtxStruct;
                                 40                 :                : 
                                 41                 :                : static DSMRegistryCtxStruct *DSMRegistryCtx;
                                 42                 :                : 
                                 43                 :                : typedef struct DSMRegistryEntry
                                 44                 :                : {
                                 45                 :                :     char        name[64];
                                 46                 :                :     dsm_handle  handle;
                                 47                 :                :     size_t      size;
                                 48                 :                : } DSMRegistryEntry;
                                 49                 :                : 
                                 50                 :                : static const dshash_parameters dsh_params = {
                                 51                 :                :     offsetof(DSMRegistryEntry, handle),
                                 52                 :                :     sizeof(DSMRegistryEntry),
                                 53                 :                :     dshash_strcmp,
                                 54                 :                :     dshash_strhash,
                                 55                 :                :     dshash_strcpy,
                                 56                 :                :     LWTRANCHE_DSM_REGISTRY_HASH
                                 57                 :                : };
                                 58                 :                : 
                                 59                 :                : static dsa_area *dsm_registry_dsa;
                                 60                 :                : static dshash_table *dsm_registry_table;
                                 61                 :                : 
                                 62                 :                : Size
   86 nathan@postgresql.or       63                 :GNC        2577 : DSMRegistryShmemSize(void)
                                 64                 :                : {
                                 65                 :           2577 :     return MAXALIGN(sizeof(DSMRegistryCtxStruct));
                                 66                 :                : }
                                 67                 :                : 
                                 68                 :                : void
                                 69                 :            898 : DSMRegistryShmemInit(void)
                                 70                 :                : {
                                 71                 :                :     bool        found;
                                 72                 :                : 
                                 73                 :            898 :     DSMRegistryCtx = (DSMRegistryCtxStruct *)
                                 74                 :            898 :         ShmemInitStruct("DSM Registry Data",
                                 75                 :                :                         DSMRegistryShmemSize(),
                                 76                 :                :                         &found);
                                 77                 :                : 
                                 78         [ +  - ]:            898 :     if (!found)
                                 79                 :                :     {
                                 80                 :            898 :         DSMRegistryCtx->dsah = DSA_HANDLE_INVALID;
                                 81                 :            898 :         DSMRegistryCtx->dshh = DSHASH_HANDLE_INVALID;
                                 82                 :                :     }
                                 83                 :            898 : }
                                 84                 :                : 
                                 85                 :                : /*
                                 86                 :                :  * Initialize or attach to the dynamic shared hash table that stores the DSM
                                 87                 :                :  * registry entries, if not already done.  This must be called before accessing
                                 88                 :                :  * the table.
                                 89                 :                :  */
                                 90                 :                : static void
                                 91                 :             16 : init_dsm_registry(void)
                                 92                 :                : {
                                 93                 :                :     /* Quick exit if we already did this. */
                                 94         [ -  + ]:             16 :     if (dsm_registry_table)
   86 nathan@postgresql.or       95                 :UNC           0 :         return;
                                 96                 :                : 
                                 97                 :                :     /* Otherwise, use a lock to ensure only one process creates the table. */
   86 nathan@postgresql.or       98                 :GNC          16 :     LWLockAcquire(DSMRegistryLock, LW_EXCLUSIVE);
                                 99                 :                : 
                                100         [ +  + ]:             16 :     if (DSMRegistryCtx->dshh == DSHASH_HANDLE_INVALID)
                                101                 :                :     {
                                102                 :                :         /* Initialize dynamic shared hash table for registry. */
                                103                 :              7 :         dsm_registry_dsa = dsa_create(LWTRANCHE_DSM_REGISTRY_DSA);
                                104                 :              7 :         dsa_pin(dsm_registry_dsa);
                                105                 :              7 :         dsa_pin_mapping(dsm_registry_dsa);
                                106                 :              7 :         dsm_registry_table = dshash_create(dsm_registry_dsa, &dsh_params, NULL);
                                107                 :                : 
                                108                 :                :         /* Store handles in shared memory for other backends to use. */
                                109                 :              7 :         DSMRegistryCtx->dsah = dsa_get_handle(dsm_registry_dsa);
                                110                 :              7 :         DSMRegistryCtx->dshh = dshash_get_hash_table_handle(dsm_registry_table);
                                111                 :                :     }
                                112                 :                :     else
                                113                 :                :     {
                                114                 :                :         /* Attach to existing dynamic shared hash table. */
                                115                 :              9 :         dsm_registry_dsa = dsa_attach(DSMRegistryCtx->dsah);
                                116                 :              9 :         dsa_pin_mapping(dsm_registry_dsa);
                                117                 :              9 :         dsm_registry_table = dshash_attach(dsm_registry_dsa, &dsh_params,
                                118                 :              9 :                                            DSMRegistryCtx->dshh, NULL);
                                119                 :                :     }
                                120                 :                : 
                                121                 :             16 :     LWLockRelease(DSMRegistryLock);
                                122                 :                : }
                                123                 :                : 
                                124                 :                : /*
                                125                 :                :  * Initialize or attach a named DSM segment.
                                126                 :                :  *
                                127                 :                :  * This routine returns the address of the segment.  init_callback is called to
                                128                 :                :  * initialize the segment when it is first created.
                                129                 :                :  */
                                130                 :                : void *
                                131                 :             16 : GetNamedDSMSegment(const char *name, size_t size,
                                132                 :                :                    void (*init_callback) (void *ptr), bool *found)
                                133                 :                : {
                                134                 :                :     DSMRegistryEntry *entry;
                                135                 :                :     MemoryContext oldcontext;
                                136                 :                :     void       *ret;
                                137                 :                : 
                                138         [ -  + ]:             16 :     Assert(found);
                                139                 :                : 
                                140   [ +  -  -  + ]:             16 :     if (!name || *name == '\0')
   86 nathan@postgresql.or      141         [ #  # ]:UNC           0 :         ereport(ERROR,
                                142                 :                :                 (errmsg("DSM segment name cannot be empty")));
                                143                 :                : 
   86 nathan@postgresql.or      144         [ -  + ]:GNC          16 :     if (strlen(name) >= offsetof(DSMRegistryEntry, handle))
   86 nathan@postgresql.or      145         [ #  # ]:UNC           0 :         ereport(ERROR,
                                146                 :                :                 (errmsg("DSM segment name too long")));
                                147                 :                : 
   86 nathan@postgresql.or      148         [ -  + ]:GNC          16 :     if (size == 0)
   86 nathan@postgresql.or      149         [ #  # ]:UNC           0 :         ereport(ERROR,
                                150                 :                :                 (errmsg("DSM segment size must be nonzero")));
                                151                 :                : 
                                152                 :                :     /* Be sure any local memory allocated by DSM/DSA routines is persistent. */
   86 nathan@postgresql.or      153                 :GNC          16 :     oldcontext = MemoryContextSwitchTo(TopMemoryContext);
                                154                 :                : 
                                155                 :                :     /* Connect to the registry. */
                                156                 :             16 :     init_dsm_registry();
                                157                 :                : 
   48                           158                 :             16 :     entry = dshash_find_or_insert(dsm_registry_table, name, found);
   86                           159         [ +  + ]:             16 :     if (!(*found))
                                160                 :                :     {
                                161                 :                :         /* Initialize the segment. */
                                162                 :              7 :         dsm_segment *seg = dsm_create(size, 0);
                                163                 :                : 
                                164                 :              7 :         dsm_pin_segment(seg);
                                165                 :              7 :         dsm_pin_mapping(seg);
                                166                 :              7 :         entry->handle = dsm_segment_handle(seg);
                                167                 :              7 :         entry->size = size;
                                168                 :              7 :         ret = dsm_segment_address(seg);
                                169                 :                : 
                                170         [ +  - ]:              7 :         if (init_callback)
                                171                 :              7 :             (*init_callback) (ret);
                                172                 :                :     }
                                173         [ -  + ]:              9 :     else if (entry->size != size)
                                174                 :                :     {
   86 nathan@postgresql.or      175         [ #  # ]:UNC           0 :         ereport(ERROR,
                                176                 :                :                 (errmsg("requested DSM segment size does not match size of "
                                177                 :                :                         "existing segment")));
                                178                 :                :     }
                                179                 :                :     else
                                180                 :                :     {
   83 nathan@postgresql.or      181                 :GNC           9 :         dsm_segment *seg = dsm_find_mapping(entry->handle);
                                182                 :                : 
                                183                 :                :         /* If the existing segment is not already attached, attach it now. */
                                184         [ +  - ]:              9 :         if (seg == NULL)
                                185                 :                :         {
                                186                 :              9 :             seg = dsm_attach(entry->handle);
                                187         [ -  + ]:              9 :             if (seg == NULL)
   83 nathan@postgresql.or      188         [ #  # ]:UNC           0 :                 elog(ERROR, "could not map dynamic shared memory segment");
                                189                 :                : 
   83 nathan@postgresql.or      190                 :GNC           9 :             dsm_pin_mapping(seg);
                                191                 :                :         }
                                192                 :                : 
   86                           193                 :              9 :         ret = dsm_segment_address(seg);
                                194                 :                :     }
                                195                 :                : 
                                196                 :             16 :     dshash_release_lock(dsm_registry_table, entry);
                                197                 :             16 :     MemoryContextSwitchTo(oldcontext);
                                198                 :                : 
                                199                 :             16 :     return ret;
                                200                 :                : }
        

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