LCOV - code coverage report
Current view: top level - src/backend/storage/ipc - dsm_registry.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 35.4 % 198 70
Test Date: 2026-01-26 10:56:24 Functions: 57.1 % 7 4
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 12.9 % 132 17

             Branch data     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                 :             :  * A DSA can be created in or retrieved from the registry by calling
      19                 :             :  * GetNamedDSA().  As with GetNamedDSMSegment(), if a DSA with the provided
      20                 :             :  * name does not yet exist, it is created.  Otherwise, GetNamedDSA()
      21                 :             :  * ensures the DSA is attached to the current backend.  This function
      22                 :             :  * guarantees that only one backend initializes the DSA and that all other
      23                 :             :  * backends just attach it.
      24                 :             :  *
      25                 :             :  * A dshash table can be created in or retrieved from the registry by
      26                 :             :  * calling GetNamedDSHash().  As with GetNamedDSMSegment(), if a hash
      27                 :             :  * table with the provided name does not yet exist, it is created.
      28                 :             :  * Otherwise, GetNamedDSHash() ensures the hash table is attached to the
      29                 :             :  * current backend.  This function guarantees that only one backend
      30                 :             :  * initializes the table and that all other backends just attach it.
      31                 :             :  *
      32                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
      33                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
      34                 :             :  *
      35                 :             :  * IDENTIFICATION
      36                 :             :  *        src/backend/storage/ipc/dsm_registry.c
      37                 :             :  *
      38                 :             :  *-------------------------------------------------------------------------
      39                 :             :  */
      40                 :             : 
      41                 :             : #include "postgres.h"
      42                 :             : 
      43                 :             : #include "funcapi.h"
      44                 :             : #include "lib/dshash.h"
      45                 :             : #include "storage/dsm_registry.h"
      46                 :             : #include "storage/lwlock.h"
      47                 :             : #include "storage/shmem.h"
      48                 :             : #include "utils/builtins.h"
      49                 :             : #include "utils/memutils.h"
      50                 :             : 
      51                 :             : typedef struct DSMRegistryCtxStruct
      52                 :             : {
      53                 :             :         dsa_handle      dsah;
      54                 :             :         dshash_table_handle dshh;
      55                 :             : } DSMRegistryCtxStruct;
      56                 :             : 
      57                 :             : static DSMRegistryCtxStruct *DSMRegistryCtx;
      58                 :             : 
      59                 :             : typedef struct NamedDSMState
      60                 :             : {
      61                 :             :         dsm_handle      handle;
      62                 :             :         size_t          size;
      63                 :             : } NamedDSMState;
      64                 :             : 
      65                 :             : typedef struct NamedDSAState
      66                 :             : {
      67                 :             :         dsa_handle      handle;
      68                 :             :         int                     tranche;
      69                 :             : } NamedDSAState;
      70                 :             : 
      71                 :             : typedef struct NamedDSHState
      72                 :             : {
      73                 :             :         dsa_handle dsa_handle;
      74                 :             :         dshash_table_handle dsh_handle;
      75                 :             :         int                     tranche;
      76                 :             : } NamedDSHState;
      77                 :             : 
      78                 :             : typedef enum DSMREntryType
      79                 :             : {
      80                 :             :         DSMR_ENTRY_TYPE_DSM,
      81                 :             :         DSMR_ENTRY_TYPE_DSA,
      82                 :             :         DSMR_ENTRY_TYPE_DSH,
      83                 :             : } DSMREntryType;
      84                 :             : 
      85                 :             : static const char *const DSMREntryTypeNames[] =
      86                 :             : {
      87                 :             :         [DSMR_ENTRY_TYPE_DSM] = "segment",
      88                 :             :         [DSMR_ENTRY_TYPE_DSA] = "area",
      89                 :             :         [DSMR_ENTRY_TYPE_DSH] = "hash",
      90                 :             : };
      91                 :             : 
      92                 :             : typedef struct DSMRegistryEntry
      93                 :             : {
      94                 :             :         char            name[NAMEDATALEN];
      95                 :             :         DSMREntryType type;
      96                 :             :         union
      97                 :             :         {
      98                 :             :                 NamedDSMState dsm;
      99                 :             :                 NamedDSAState dsa;
     100                 :             :                 NamedDSHState dsh;
     101                 :             :         };
     102                 :             : } DSMRegistryEntry;
     103                 :             : 
     104                 :             : static const dshash_parameters dsh_params = {
     105                 :             :         offsetof(DSMRegistryEntry, type),
     106                 :             :         sizeof(DSMRegistryEntry),
     107                 :             :         dshash_strcmp,
     108                 :             :         dshash_strhash,
     109                 :             :         dshash_strcpy,
     110                 :             :         LWTRANCHE_DSM_REGISTRY_HASH
     111                 :             : };
     112                 :             : 
     113                 :             : static dsa_area *dsm_registry_dsa;
     114                 :             : static dshash_table *dsm_registry_table;
     115                 :             : 
     116                 :             : Size
     117                 :          15 : DSMRegistryShmemSize(void)
     118                 :             : {
     119                 :          15 :         return MAXALIGN(sizeof(DSMRegistryCtxStruct));
     120                 :             : }
     121                 :             : 
     122                 :             : void
     123                 :           6 : DSMRegistryShmemInit(void)
     124                 :             : {
     125                 :           6 :         bool            found;
     126                 :             : 
     127                 :           6 :         DSMRegistryCtx = (DSMRegistryCtxStruct *)
     128                 :           6 :                 ShmemInitStruct("DSM Registry Data",
     129                 :           6 :                                                 DSMRegistryShmemSize(),
     130                 :             :                                                 &found);
     131                 :             : 
     132         [ -  + ]:           6 :         if (!found)
     133                 :             :         {
     134                 :           6 :                 DSMRegistryCtx->dsah = DSA_HANDLE_INVALID;
     135                 :           6 :                 DSMRegistryCtx->dshh = DSHASH_HANDLE_INVALID;
     136                 :           6 :         }
     137                 :           6 : }
     138                 :             : 
     139                 :             : /*
     140                 :             :  * Initialize or attach to the dynamic shared hash table that stores the DSM
     141                 :             :  * registry entries, if not already done.  This must be called before accessing
     142                 :             :  * the table.
     143                 :             :  */
     144                 :             : static void
     145                 :         253 : init_dsm_registry(void)
     146                 :             : {
     147                 :             :         /* Quick exit if we already did this. */
     148         [ -  + ]:         253 :         if (dsm_registry_table)
     149                 :           0 :                 return;
     150                 :             : 
     151                 :             :         /* Otherwise, use a lock to ensure only one process creates the table. */
     152                 :         253 :         LWLockAcquire(DSMRegistryLock, LW_EXCLUSIVE);
     153                 :             : 
     154         [ +  + ]:         253 :         if (DSMRegistryCtx->dshh == DSHASH_HANDLE_INVALID)
     155                 :             :         {
     156                 :             :                 /* Initialize dynamic shared hash table for registry. */
     157                 :           1 :                 dsm_registry_dsa = dsa_create(LWTRANCHE_DSM_REGISTRY_DSA);
     158                 :           1 :                 dsm_registry_table = dshash_create(dsm_registry_dsa, &dsh_params, NULL);
     159                 :             : 
     160                 :           1 :                 dsa_pin(dsm_registry_dsa);
     161                 :           1 :                 dsa_pin_mapping(dsm_registry_dsa);
     162                 :             : 
     163                 :             :                 /* Store handles in shared memory for other backends to use. */
     164                 :           1 :                 DSMRegistryCtx->dsah = dsa_get_handle(dsm_registry_dsa);
     165                 :           1 :                 DSMRegistryCtx->dshh = dshash_get_hash_table_handle(dsm_registry_table);
     166                 :           1 :         }
     167                 :             :         else
     168                 :             :         {
     169                 :             :                 /* Attach to existing dynamic shared hash table. */
     170                 :         252 :                 dsm_registry_dsa = dsa_attach(DSMRegistryCtx->dsah);
     171                 :         252 :                 dsa_pin_mapping(dsm_registry_dsa);
     172                 :         504 :                 dsm_registry_table = dshash_attach(dsm_registry_dsa, &dsh_params,
     173                 :         252 :                                                                                    DSMRegistryCtx->dshh, NULL);
     174                 :             :         }
     175                 :             : 
     176                 :         253 :         LWLockRelease(DSMRegistryLock);
     177                 :         253 : }
     178                 :             : 
     179                 :             : /*
     180                 :             :  * Initialize or attach a named DSM segment.
     181                 :             :  *
     182                 :             :  * This routine returns the address of the segment.  init_callback is called to
     183                 :             :  * initialize the segment when it is first created.  'arg' is passed through to
     184                 :             :  * the initialization callback function.
     185                 :             :  */
     186                 :             : void *
     187                 :         253 : GetNamedDSMSegment(const char *name, size_t size,
     188                 :             :                                    void (*init_callback) (void *ptr, void *arg),
     189                 :             :                                    bool *found, void *arg)
     190                 :             : {
     191                 :         253 :         DSMRegistryEntry *entry;
     192                 :         253 :         MemoryContext oldcontext;
     193                 :         253 :         void       *ret;
     194                 :         253 :         NamedDSMState *state;
     195                 :         253 :         dsm_segment *seg;
     196                 :             : 
     197         [ +  - ]:         253 :         Assert(found);
     198                 :             : 
     199         [ +  - ]:         253 :         if (!name || *name == '\0')
     200   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     201                 :             :                                 (errmsg("DSM segment name cannot be empty")));
     202                 :             : 
     203         [ +  - ]:         253 :         if (strlen(name) >= offsetof(DSMRegistryEntry, type))
     204   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     205                 :             :                                 (errmsg("DSM segment name too long")));
     206                 :             : 
     207         [ +  - ]:         253 :         if (size == 0)
     208   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     209                 :             :                                 (errmsg("DSM segment size must be nonzero")));
     210                 :             : 
     211                 :             :         /* Be sure any local memory allocated by DSM/DSA routines is persistent. */
     212                 :         253 :         oldcontext = MemoryContextSwitchTo(TopMemoryContext);
     213                 :             : 
     214                 :             :         /* Connect to the registry. */
     215                 :         253 :         init_dsm_registry();
     216                 :             : 
     217                 :         253 :         entry = dshash_find_or_insert(dsm_registry_table, name, found);
     218                 :         253 :         state = &entry->dsm;
     219         [ +  + ]:         253 :         if (!(*found))
     220                 :             :         {
     221                 :           1 :                 entry->type = DSMR_ENTRY_TYPE_DSM;
     222                 :           1 :                 state->handle = DSM_HANDLE_INVALID;
     223                 :           1 :                 state->size = size;
     224                 :           1 :         }
     225         [ +  - ]:         252 :         else if (entry->type != DSMR_ENTRY_TYPE_DSM)
     226   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     227                 :             :                                 (errmsg("requested DSM segment does not match type of existing entry")));
     228         [ +  - ]:         252 :         else if (state->size != size)
     229   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     230                 :             :                                 (errmsg("requested DSM segment size does not match size of existing segment")));
     231                 :             : 
     232         [ +  + ]:         253 :         if (state->handle == DSM_HANDLE_INVALID)
     233                 :             :         {
     234                 :           1 :                 *found = false;
     235                 :             : 
     236                 :             :                 /* Initialize the segment. */
     237                 :           1 :                 seg = dsm_create(size, 0);
     238                 :             : 
     239         [ -  + ]:           1 :                 if (init_callback)
     240                 :           1 :                         (*init_callback) (dsm_segment_address(seg), arg);
     241                 :             : 
     242                 :           1 :                 dsm_pin_segment(seg);
     243                 :           1 :                 dsm_pin_mapping(seg);
     244                 :           1 :                 state->handle = dsm_segment_handle(seg);
     245                 :           1 :         }
     246                 :             :         else
     247                 :             :         {
     248                 :             :                 /* If the existing segment is not already attached, attach it now. */
     249                 :         252 :                 seg = dsm_find_mapping(state->handle);
     250         [ -  + ]:         252 :                 if (seg == NULL)
     251                 :             :                 {
     252                 :         252 :                         seg = dsm_attach(state->handle);
     253         [ +  - ]:         252 :                         if (seg == NULL)
     254   [ #  #  #  # ]:           0 :                                 elog(ERROR, "could not map dynamic shared memory segment");
     255                 :             : 
     256                 :         252 :                         dsm_pin_mapping(seg);
     257                 :         252 :                 }
     258                 :             :         }
     259                 :             : 
     260                 :         253 :         ret = dsm_segment_address(seg);
     261                 :         253 :         dshash_release_lock(dsm_registry_table, entry);
     262                 :         253 :         MemoryContextSwitchTo(oldcontext);
     263                 :             : 
     264                 :         506 :         return ret;
     265                 :         253 : }
     266                 :             : 
     267                 :             : /*
     268                 :             :  * Initialize or attach a named DSA.
     269                 :             :  *
     270                 :             :  * This routine returns a pointer to the DSA.  A new LWLock tranche ID will be
     271                 :             :  * generated if needed.  Note that the lock tranche will be registered with the
     272                 :             :  * provided name.  Also note that this should be called at most once for a
     273                 :             :  * given DSA in each backend.
     274                 :             :  */
     275                 :             : dsa_area *
     276                 :           0 : GetNamedDSA(const char *name, bool *found)
     277                 :             : {
     278                 :           0 :         DSMRegistryEntry *entry;
     279                 :           0 :         MemoryContext oldcontext;
     280                 :           0 :         dsa_area   *ret;
     281                 :           0 :         NamedDSAState *state;
     282                 :             : 
     283         [ #  # ]:           0 :         Assert(found);
     284                 :             : 
     285         [ #  # ]:           0 :         if (!name || *name == '\0')
     286   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     287                 :             :                                 (errmsg("DSA name cannot be empty")));
     288                 :             : 
     289         [ #  # ]:           0 :         if (strlen(name) >= offsetof(DSMRegistryEntry, type))
     290   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     291                 :             :                                 (errmsg("DSA name too long")));
     292                 :             : 
     293                 :             :         /* Be sure any local memory allocated by DSM/DSA routines is persistent. */
     294                 :           0 :         oldcontext = MemoryContextSwitchTo(TopMemoryContext);
     295                 :             : 
     296                 :             :         /* Connect to the registry. */
     297                 :           0 :         init_dsm_registry();
     298                 :             : 
     299                 :           0 :         entry = dshash_find_or_insert(dsm_registry_table, name, found);
     300                 :           0 :         state = &entry->dsa;
     301         [ #  # ]:           0 :         if (!(*found))
     302                 :             :         {
     303                 :           0 :                 entry->type = DSMR_ENTRY_TYPE_DSA;
     304                 :           0 :                 state->handle = DSA_HANDLE_INVALID;
     305                 :           0 :                 state->tranche = -1;
     306                 :           0 :         }
     307         [ #  # ]:           0 :         else if (entry->type != DSMR_ENTRY_TYPE_DSA)
     308   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     309                 :             :                                 (errmsg("requested DSA does not match type of existing entry")));
     310                 :             : 
     311         [ #  # ]:           0 :         if (state->tranche == -1)
     312                 :             :         {
     313                 :           0 :                 *found = false;
     314                 :             : 
     315                 :             :                 /* Initialize the LWLock tranche for the DSA. */
     316                 :           0 :                 state->tranche = LWLockNewTrancheId(name);
     317                 :           0 :         }
     318                 :             : 
     319         [ #  # ]:           0 :         if (state->handle == DSA_HANDLE_INVALID)
     320                 :             :         {
     321                 :           0 :                 *found = false;
     322                 :             : 
     323                 :             :                 /* Initialize the DSA. */
     324                 :           0 :                 ret = dsa_create(state->tranche);
     325                 :           0 :                 dsa_pin(ret);
     326                 :           0 :                 dsa_pin_mapping(ret);
     327                 :             : 
     328                 :             :                 /* Store handle for other backends to use. */
     329                 :           0 :                 state->handle = dsa_get_handle(ret);
     330                 :           0 :         }
     331         [ #  # ]:           0 :         else if (dsa_is_attached(state->handle))
     332   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     333                 :             :                                 (errmsg("requested DSA already attached to current process")));
     334                 :             :         else
     335                 :             :         {
     336                 :             :                 /* Attach to existing DSA. */
     337                 :           0 :                 ret = dsa_attach(state->handle);
     338                 :           0 :                 dsa_pin_mapping(ret);
     339                 :             :         }
     340                 :             : 
     341                 :           0 :         dshash_release_lock(dsm_registry_table, entry);
     342                 :           0 :         MemoryContextSwitchTo(oldcontext);
     343                 :             : 
     344                 :           0 :         return ret;
     345                 :           0 : }
     346                 :             : 
     347                 :             : /*
     348                 :             :  * Initialize or attach a named dshash table.
     349                 :             :  *
     350                 :             :  * This routine returns the address of the table.  The tranche_id member of
     351                 :             :  * params is ignored; a new LWLock tranche ID will be generated if needed.
     352                 :             :  * Note that the lock tranche will be registered with the provided name.  Also
     353                 :             :  * note that this should be called at most once for a given table in each
     354                 :             :  * backend.
     355                 :             :  */
     356                 :             : dshash_table *
     357                 :           0 : GetNamedDSHash(const char *name, const dshash_parameters *params, bool *found)
     358                 :             : {
     359                 :           0 :         DSMRegistryEntry *entry;
     360                 :           0 :         MemoryContext oldcontext;
     361                 :           0 :         dshash_table *ret;
     362                 :           0 :         NamedDSHState *dsh_state;
     363                 :             : 
     364         [ #  # ]:           0 :         Assert(params);
     365         [ #  # ]:           0 :         Assert(found);
     366                 :             : 
     367         [ #  # ]:           0 :         if (!name || *name == '\0')
     368   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     369                 :             :                                 (errmsg("DSHash name cannot be empty")));
     370                 :             : 
     371         [ #  # ]:           0 :         if (strlen(name) >= offsetof(DSMRegistryEntry, type))
     372   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     373                 :             :                                 (errmsg("DSHash name too long")));
     374                 :             : 
     375                 :             :         /* Be sure any local memory allocated by DSM/DSA routines is persistent. */
     376                 :           0 :         oldcontext = MemoryContextSwitchTo(TopMemoryContext);
     377                 :             : 
     378                 :             :         /* Connect to the registry. */
     379                 :           0 :         init_dsm_registry();
     380                 :             : 
     381                 :           0 :         entry = dshash_find_or_insert(dsm_registry_table, name, found);
     382                 :           0 :         dsh_state = &entry->dsh;
     383         [ #  # ]:           0 :         if (!(*found))
     384                 :             :         {
     385                 :           0 :                 entry->type = DSMR_ENTRY_TYPE_DSH;
     386                 :           0 :                 dsh_state->dsa_handle = DSA_HANDLE_INVALID;
     387                 :           0 :                 dsh_state->dsh_handle = DSHASH_HANDLE_INVALID;
     388                 :           0 :                 dsh_state->tranche = -1;
     389                 :           0 :         }
     390         [ #  # ]:           0 :         else if (entry->type != DSMR_ENTRY_TYPE_DSH)
     391   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     392                 :             :                                 (errmsg("requested DSHash does not match type of existing entry")));
     393                 :             : 
     394         [ #  # ]:           0 :         if (dsh_state->tranche == -1)
     395                 :             :         {
     396                 :           0 :                 *found = false;
     397                 :             : 
     398                 :             :                 /* Initialize the LWLock tranche for the hash table. */
     399                 :           0 :                 dsh_state->tranche = LWLockNewTrancheId(name);
     400                 :           0 :         }
     401                 :             : 
     402         [ #  # ]:           0 :         if (dsh_state->dsa_handle == DSA_HANDLE_INVALID)
     403                 :             :         {
     404                 :           0 :                 dshash_parameters params_copy;
     405                 :           0 :                 dsa_area   *dsa;
     406                 :             : 
     407                 :           0 :                 *found = false;
     408                 :             : 
     409                 :             :                 /* Initialize the DSA for the hash table. */
     410                 :           0 :                 dsa = dsa_create(dsh_state->tranche);
     411                 :             : 
     412                 :             :                 /* Initialize the dshash table. */
     413                 :           0 :                 memcpy(&params_copy, params, sizeof(dshash_parameters));
     414                 :           0 :                 params_copy.tranche_id = dsh_state->tranche;
     415                 :           0 :                 ret = dshash_create(dsa, &params_copy, NULL);
     416                 :             : 
     417                 :           0 :                 dsa_pin(dsa);
     418                 :           0 :                 dsa_pin_mapping(dsa);
     419                 :             : 
     420                 :             :                 /* Store handles for other backends to use. */
     421                 :           0 :                 dsh_state->dsa_handle = dsa_get_handle(dsa);
     422                 :           0 :                 dsh_state->dsh_handle = dshash_get_hash_table_handle(ret);
     423                 :           0 :         }
     424         [ #  # ]:           0 :         else if (dsa_is_attached(dsh_state->dsa_handle))
     425   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     426                 :             :                                 (errmsg("requested DSHash already attached to current process")));
     427                 :             :         else
     428                 :             :         {
     429                 :           0 :                 dsa_area   *dsa;
     430                 :             : 
     431                 :             :                 /* XXX: Should we verify params matches what table was created with? */
     432                 :             : 
     433                 :             :                 /* Attach to existing DSA for the hash table. */
     434                 :           0 :                 dsa = dsa_attach(dsh_state->dsa_handle);
     435                 :           0 :                 dsa_pin_mapping(dsa);
     436                 :             : 
     437                 :             :                 /* Attach to existing dshash table. */
     438                 :           0 :                 ret = dshash_attach(dsa, params, dsh_state->dsh_handle, NULL);
     439                 :           0 :         }
     440                 :             : 
     441                 :           0 :         dshash_release_lock(dsm_registry_table, entry);
     442                 :           0 :         MemoryContextSwitchTo(oldcontext);
     443                 :             : 
     444                 :           0 :         return ret;
     445                 :           0 : }
     446                 :             : 
     447                 :             : Datum
     448                 :           0 : pg_get_dsm_registry_allocations(PG_FUNCTION_ARGS)
     449                 :             : {
     450                 :           0 :         ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
     451                 :           0 :         DSMRegistryEntry *entry;
     452                 :           0 :         MemoryContext oldcontext;
     453                 :           0 :         dshash_seq_status status;
     454                 :             : 
     455                 :           0 :         InitMaterializedSRF(fcinfo, MAT_SRF_USE_EXPECTED_DESC);
     456                 :             : 
     457                 :             :         /* Be sure any local memory allocated by DSM/DSA routines is persistent. */
     458                 :           0 :         oldcontext = MemoryContextSwitchTo(TopMemoryContext);
     459                 :           0 :         init_dsm_registry();
     460                 :           0 :         MemoryContextSwitchTo(oldcontext);
     461                 :             : 
     462                 :           0 :         dshash_seq_init(&status, dsm_registry_table, false);
     463         [ #  # ]:           0 :         while ((entry = dshash_seq_next(&status)) != NULL)
     464                 :             :         {
     465                 :           0 :                 Datum           vals[3];
     466                 :           0 :                 bool            nulls[3] = {0};
     467                 :             : 
     468                 :           0 :                 vals[0] = CStringGetTextDatum(entry->name);
     469                 :           0 :                 vals[1] = CStringGetTextDatum(DSMREntryTypeNames[entry->type]);
     470                 :             : 
     471                 :             :                 /* Be careful to only return the sizes of initialized entries. */
     472   [ #  #  #  # ]:           0 :                 if (entry->type == DSMR_ENTRY_TYPE_DSM &&
     473                 :           0 :                         entry->dsm.handle != DSM_HANDLE_INVALID)
     474                 :           0 :                         vals[2] = Int64GetDatum(entry->dsm.size);
     475   [ #  #  #  # ]:           0 :                 else if (entry->type == DSMR_ENTRY_TYPE_DSA &&
     476                 :           0 :                                  entry->dsa.handle != DSA_HANDLE_INVALID)
     477                 :           0 :                         vals[2] = Int64GetDatum(dsa_get_total_size_from_handle(entry->dsa.handle));
     478   [ #  #  #  # ]:           0 :                 else if (entry->type == DSMR_ENTRY_TYPE_DSH &&
     479                 :           0 :                                  entry->dsh.dsa_handle !=DSA_HANDLE_INVALID)
     480                 :           0 :                         vals[2] = Int64GetDatum(dsa_get_total_size_from_handle(entry->dsh.dsa_handle));
     481                 :             :                 else
     482                 :           0 :                         nulls[2] = true;
     483                 :             : 
     484                 :           0 :                 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, vals, nulls);
     485                 :           0 :         }
     486                 :           0 :         dshash_seq_term(&status);
     487                 :             : 
     488                 :           0 :         return (Datum) 0;
     489                 :           0 : }
        

Generated by: LCOV version 2.3.2-1