LCOV - differential code coverage report
Current view: top level - src/backend/utils/resowner - resowner.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 85.5 % 463 396 3 27 36 1 10 246 21 119 56 247 3
Current Date: 2023-04-08 15:15:32 Functions: 86.6 % 67 58 9 55 3 9 58
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * resowner.c
       4                 :  *    POSTGRES resource owner management code.
       5                 :  *
       6                 :  * Query-lifespan resources are tracked by associating them with
       7                 :  * ResourceOwner objects.  This provides a simple mechanism for ensuring
       8                 :  * that such resources are freed at the right time.
       9                 :  * See utils/resowner/README for more info.
      10                 :  *
      11                 :  *
      12                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
      13                 :  * Portions Copyright (c) 1994, Regents of the University of California
      14                 :  *
      15                 :  *
      16                 :  * IDENTIFICATION
      17                 :  *    src/backend/utils/resowner/resowner.c
      18                 :  *
      19                 :  *-------------------------------------------------------------------------
      20                 :  */
      21                 : #include "postgres.h"
      22                 : 
      23                 : #include "common/cryptohash.h"
      24                 : #include "common/hashfn.h"
      25                 : #include "common/hmac.h"
      26                 : #include "jit/jit.h"
      27                 : #include "storage/bufmgr.h"
      28                 : #include "storage/ipc.h"
      29                 : #include "storage/predicate.h"
      30                 : #include "storage/proc.h"
      31                 : #include "utils/memutils.h"
      32                 : #include "utils/rel.h"
      33                 : #include "utils/resowner_private.h"
      34                 : #include "utils/snapmgr.h"
      35                 : 
      36                 : 
      37                 : /*
      38                 :  * All resource IDs managed by this code are required to fit into a Datum,
      39                 :  * which is fine since they are generally pointers or integers.
      40                 :  *
      41                 :  * Provide Datum conversion macros for a couple of things that are really
      42                 :  * just "int".
      43                 :  */
      44                 : #define FileGetDatum(file) Int32GetDatum(file)
      45                 : #define DatumGetFile(datum) ((File) DatumGetInt32(datum))
      46                 : #define BufferGetDatum(buffer) Int32GetDatum(buffer)
      47                 : #define DatumGetBuffer(datum) ((Buffer) DatumGetInt32(datum))
      48                 : 
      49                 : /*
      50                 :  * ResourceArray is a common structure for storing all types of resource IDs.
      51                 :  *
      52                 :  * We manage small sets of resource IDs by keeping them in a simple array:
      53                 :  * itemsarr[k] holds an ID, for 0 <= k < nitems <= maxitems = capacity.
      54                 :  *
      55                 :  * If a set grows large, we switch over to using open-addressing hashing.
      56                 :  * Then, itemsarr[] is a hash table of "capacity" slots, with each
      57                 :  * slot holding either an ID or "invalidval".  nitems is the number of valid
      58                 :  * items present; if it would exceed maxitems, we enlarge the array and
      59                 :  * re-hash.  In this mode, maxitems should be rather less than capacity so
      60                 :  * that we don't waste too much time searching for empty slots.
      61                 :  *
      62                 :  * In either mode, lastidx remembers the location of the last item inserted
      63                 :  * or returned by GetAny; this speeds up searches in ResourceArrayRemove.
      64                 :  */
      65                 : typedef struct ResourceArray
      66                 : {
      67                 :     Datum      *itemsarr;       /* buffer for storing values */
      68                 :     Datum       invalidval;     /* value that is considered invalid */
      69                 :     uint32      capacity;       /* allocated length of itemsarr[] */
      70                 :     uint32      nitems;         /* how many items are stored in items array */
      71                 :     uint32      maxitems;       /* current limit on nitems before enlarging */
      72                 :     uint32      lastidx;        /* index of last item returned by GetAny */
      73                 : } ResourceArray;
      74                 : 
      75                 : /*
      76                 :  * Initially allocated size of a ResourceArray.  Must be power of two since
      77                 :  * we'll use (arraysize - 1) as mask for hashing.
      78                 :  */
      79                 : #define RESARRAY_INIT_SIZE 16
      80                 : 
      81                 : /*
      82                 :  * When to switch to hashing vs. simple array logic in a ResourceArray.
      83                 :  */
      84                 : #define RESARRAY_MAX_ARRAY 64
      85                 : #define RESARRAY_IS_ARRAY(resarr) ((resarr)->capacity <= RESARRAY_MAX_ARRAY)
      86                 : 
      87                 : /*
      88                 :  * How many items may be stored in a resource array of given capacity.
      89                 :  * When this number is reached, we must resize.
      90                 :  */
      91                 : #define RESARRAY_MAX_ITEMS(capacity) \
      92                 :     ((capacity) <= RESARRAY_MAX_ARRAY ? (capacity) : (capacity)/4 * 3)
      93                 : 
      94                 : /*
      95                 :  * To speed up bulk releasing or reassigning locks from a resource owner to
      96                 :  * its parent, each resource owner has a small cache of locks it owns. The
      97                 :  * lock manager has the same information in its local lock hash table, and
      98                 :  * we fall back on that if cache overflows, but traversing the hash table
      99                 :  * is slower when there are a lot of locks belonging to other resource owners.
     100                 :  *
     101                 :  * MAX_RESOWNER_LOCKS is the size of the per-resource owner cache. It's
     102                 :  * chosen based on some testing with pg_dump with a large schema. When the
     103                 :  * tests were done (on 9.2), resource owners in a pg_dump run contained up
     104                 :  * to 9 locks, regardless of the schema size, except for the top resource
     105                 :  * owner which contained much more (overflowing the cache). 15 seems like a
     106                 :  * nice round number that's somewhat higher than what pg_dump needs. Note that
     107                 :  * making this number larger is not free - the bigger the cache, the slower
     108                 :  * it is to release locks (in retail), when a resource owner holds many locks.
     109                 :  */
     110                 : #define MAX_RESOWNER_LOCKS 15
     111                 : 
     112                 : /*
     113                 :  * ResourceOwner objects look like this
     114                 :  */
     115                 : typedef struct ResourceOwnerData
     116                 : {
     117                 :     ResourceOwner parent;       /* NULL if no parent (toplevel owner) */
     118                 :     ResourceOwner firstchild;   /* head of linked list of children */
     119                 :     ResourceOwner nextchild;    /* next child of same parent */
     120                 :     const char *name;           /* name (just for debugging) */
     121                 : 
     122                 :     /* We have built-in support for remembering: */
     123                 :     ResourceArray bufferarr;    /* owned buffers */
     124                 :     ResourceArray bufferioarr;  /* in-progress buffer IO */
     125                 :     ResourceArray catrefarr;    /* catcache references */
     126                 :     ResourceArray catlistrefarr;    /* catcache-list pins */
     127                 :     ResourceArray relrefarr;    /* relcache references */
     128                 :     ResourceArray planrefarr;   /* plancache references */
     129                 :     ResourceArray tupdescarr;   /* tupdesc references */
     130                 :     ResourceArray snapshotarr;  /* snapshot references */
     131                 :     ResourceArray filearr;      /* open temporary files */
     132                 :     ResourceArray dsmarr;       /* dynamic shmem segments */
     133                 :     ResourceArray jitarr;       /* JIT contexts */
     134                 :     ResourceArray cryptohasharr;    /* cryptohash contexts */
     135                 :     ResourceArray hmacarr;      /* HMAC contexts */
     136                 : 
     137                 :     /* We can remember up to MAX_RESOWNER_LOCKS references to local locks. */
     138                 :     int         nlocks;         /* number of owned locks */
     139                 :     LOCALLOCK  *locks[MAX_RESOWNER_LOCKS];  /* list of owned locks */
     140                 : }           ResourceOwnerData;
     141                 : 
     142                 : 
     143                 : /*****************************************************************************
     144                 :  *    GLOBAL MEMORY                                                          *
     145                 :  *****************************************************************************/
     146                 : 
     147                 : ResourceOwner CurrentResourceOwner = NULL;
     148                 : ResourceOwner CurTransactionResourceOwner = NULL;
     149                 : ResourceOwner TopTransactionResourceOwner = NULL;
     150                 : ResourceOwner AuxProcessResourceOwner = NULL;
     151                 : 
     152                 : /*
     153                 :  * List of add-on callbacks for resource releasing
     154                 :  */
     155                 : typedef struct ResourceReleaseCallbackItem
     156                 : {
     157                 :     struct ResourceReleaseCallbackItem *next;
     158                 :     ResourceReleaseCallback callback;
     159                 :     void       *arg;
     160                 : } ResourceReleaseCallbackItem;
     161                 : 
     162                 : static ResourceReleaseCallbackItem *ResourceRelease_callbacks = NULL;
     163                 : 
     164                 : 
     165                 : /* Internal routines */
     166                 : static void ResourceArrayInit(ResourceArray *resarr, Datum invalidval);
     167                 : static void ResourceArrayEnlarge(ResourceArray *resarr);
     168                 : static void ResourceArrayAdd(ResourceArray *resarr, Datum value);
     169                 : static bool ResourceArrayRemove(ResourceArray *resarr, Datum value);
     170                 : static bool ResourceArrayGetAny(ResourceArray *resarr, Datum *value);
     171                 : static void ResourceArrayFree(ResourceArray *resarr);
     172                 : static void ResourceOwnerReleaseInternal(ResourceOwner owner,
     173                 :                                          ResourceReleasePhase phase,
     174                 :                                          bool isCommit,
     175                 :                                          bool isTopLevel);
     176                 : static void ReleaseAuxProcessResourcesCallback(int code, Datum arg);
     177                 : static void PrintRelCacheLeakWarning(Relation rel);
     178                 : static void PrintPlanCacheLeakWarning(CachedPlan *plan);
     179                 : static void PrintTupleDescLeakWarning(TupleDesc tupdesc);
     180                 : static void PrintSnapshotLeakWarning(Snapshot snapshot);
     181                 : static void PrintFileLeakWarning(File file);
     182                 : static void PrintDSMLeakWarning(dsm_segment *seg);
     183                 : static void PrintCryptoHashLeakWarning(Datum handle);
     184                 : static void PrintHMACLeakWarning(Datum handle);
     185                 : 
     186                 : 
     187                 : /*****************************************************************************
     188                 :  *    INTERNAL ROUTINES                                                      *
     189                 :  *****************************************************************************/
     190                 : 
     191                 : 
     192                 : /*
     193                 :  * Initialize a ResourceArray
     194                 :  */
     195                 : static void
     196 GIC    13078767 : ResourceArrayInit(ResourceArray *resarr, Datum invalidval)
     197 ECB             : {
     198                 :     /* Assert it's empty */
     199 GIC    13078767 :     Assert(resarr->itemsarr == NULL);
     200 CBC    13078767 :     Assert(resarr->capacity == 0);
     201        13078767 :     Assert(resarr->nitems == 0);
     202        13078767 :     Assert(resarr->maxitems == 0);
     203 ECB             :     /* Remember the appropriate "invalid" value */
     204 GIC    13078767 :     resarr->invalidval = invalidval;
     205 ECB             :     /* We don't allocate any storage until needed */
     206 GIC    13078767 : }
     207 ECB             : 
     208                 : /*
     209                 :  * Make sure there is room for at least one more resource in an array.
     210                 :  *
     211                 :  * This is separate from actually inserting a resource because if we run out
     212                 :  * of memory, it's critical to do so *before* acquiring the resource.
     213                 :  */
     214                 : static void
     215 GIC   208923634 : ResourceArrayEnlarge(ResourceArray *resarr)
     216 ECB             : {
     217                 :     uint32      i,
     218                 :                 oldcap,
     219                 :                 newcap;
     220                 :     Datum      *olditemsarr;
     221                 :     Datum      *newitemsarr;
     222                 : 
     223 GIC   208923634 :     if (resarr->nitems < resarr->maxitems)
     224 CBC   205506208 :         return;                 /* no work needed */
     225 ECB             : 
     226 GIC     3417426 :     olditemsarr = resarr->itemsarr;
     227 CBC     3417426 :     oldcap = resarr->capacity;
     228 ECB             : 
     229                 :     /* Double the capacity of the array (capacity must stay a power of 2!) */
     230 GIC     3417426 :     newcap = (oldcap > 0) ? oldcap * 2 : RESARRAY_INIT_SIZE;
     231 CBC     3417426 :     newitemsarr = (Datum *) MemoryContextAlloc(TopMemoryContext,
     232 ECB             :                                                newcap * sizeof(Datum));
     233 GIC    59757586 :     for (i = 0; i < newcap; i++)
     234 CBC    56340160 :         newitemsarr[i] = resarr->invalidval;
     235 ECB             : 
     236                 :     /* We assume we can't fail below this point, so OK to scribble on resarr */
     237 GIC     3417426 :     resarr->itemsarr = newitemsarr;
     238 CBC     3417426 :     resarr->capacity = newcap;
     239         3417426 :     resarr->maxitems = RESARRAY_MAX_ITEMS(newcap);
     240         3417426 :     resarr->nitems = 0;
     241 ECB             : 
     242 GIC     3417426 :     if (olditemsarr != NULL)
     243 ECB             :     {
     244                 :         /*
     245                 :          * Transfer any pre-existing entries into the new array; they don't
     246                 :          * necessarily go where they were before, so this simple logic is the
     247                 :          * best way.  Note that if we were managing the set as a simple array,
     248                 :          * the entries after nitems are garbage, but that shouldn't matter
     249                 :          * because we won't get here unless nitems was equal to oldcap.
     250                 :          */
     251 GIC      953306 :         for (i = 0; i < oldcap; i++)
     252 ECB             :         {
     253 GIC      939680 :             if (olditemsarr[i] != resarr->invalidval)
     254 CBC      769696 :                 ResourceArrayAdd(resarr, olditemsarr[i]);
     255 ECB             :         }
     256                 : 
     257                 :         /* And release old array. */
     258 GIC       13626 :         pfree(olditemsarr);
     259 ECB             :     }
     260                 : 
     261 GIC     3417426 :     Assert(resarr->nitems < resarr->maxitems);
     262 ECB             : }
     263                 : 
     264                 : /*
     265                 :  * Add a resource to ResourceArray
     266                 :  *
     267                 :  * Caller must have previously done ResourceArrayEnlarge()
     268                 :  */
     269                 : static void
     270 GIC   206595945 : ResourceArrayAdd(ResourceArray *resarr, Datum value)
     271 ECB             : {
     272                 :     uint32      idx;
     273                 : 
     274 GIC   206595945 :     Assert(value != resarr->invalidval);
     275 CBC   206595945 :     Assert(resarr->nitems < resarr->maxitems);
     276 ECB             : 
     277 GIC   206595945 :     if (RESARRAY_IS_ARRAY(resarr))
     278 ECB             :     {
     279                 :         /* Append to linear array. */
     280 GIC   205411741 :         idx = resarr->nitems;
     281 ECB             :     }
     282                 :     else
     283                 :     {
     284                 :         /* Insert into first free slot at or after hash location. */
     285 GIC     1184204 :         uint32      mask = resarr->capacity - 1;
     286 ECB             : 
     287 GIC     1184204 :         idx = DatumGetUInt32(hash_any((void *) &value, sizeof(value))) & mask;
     288 ECB             :         for (;;)
     289                 :         {
     290 GIC   392068502 :             if (resarr->itemsarr[idx] == resarr->invalidval)
     291 CBC     1184204 :                 break;
     292       390884298 :             idx = (idx + 1) & mask;
     293 ECB             :         }
     294                 :     }
     295 GIC   206595945 :     resarr->lastidx = idx;
     296 CBC   206595945 :     resarr->itemsarr[idx] = value;
     297       206595945 :     resarr->nitems++;
     298       206595945 : }
     299 ECB             : 
     300                 : /*
     301                 :  * Remove a resource from ResourceArray
     302                 :  *
     303                 :  * Returns true on success, false if resource was not found.
     304                 :  *
     305                 :  * Note: if same resource ID appears more than once, one instance is removed.
     306                 :  */
     307                 : static bool
     308 GIC   205826244 : ResourceArrayRemove(ResourceArray *resarr, Datum value)
     309 ECB             : {
     310                 :     uint32      i,
     311                 :                 idx,
     312 GIC   205826244 :                 lastidx = resarr->lastidx;
     313 ECB             : 
     314 GIC   205826244 :     Assert(value != resarr->invalidval);
     315 ECB             : 
     316                 :     /* Search through all items, but try lastidx first. */
     317 GIC   205826244 :     if (RESARRAY_IS_ARRAY(resarr))
     318 ECB             :     {
     319 GIC   205151992 :         if (lastidx < resarr->nitems &&
     320 CBC   205151992 :             resarr->itemsarr[lastidx] == value)
     321 ECB             :         {
     322 GIC   199281187 :             resarr->itemsarr[lastidx] = resarr->itemsarr[resarr->nitems - 1];
     323 CBC   199281187 :             resarr->nitems--;
     324 ECB             :             /* Update lastidx to make reverse-order removals fast. */
     325 GIC   199281187 :             resarr->lastidx = resarr->nitems - 1;
     326 CBC   199281187 :             return true;
     327 ECB             :         }
     328 GIC    12783604 :         for (i = 0; i < resarr->nitems; i++)
     329 ECB             :         {
     330 GIC    12783604 :             if (resarr->itemsarr[i] == value)
     331 ECB             :             {
     332 GIC     5870805 :                 resarr->itemsarr[i] = resarr->itemsarr[resarr->nitems - 1];
     333 CBC     5870805 :                 resarr->nitems--;
     334 ECB             :                 /* Update lastidx to make reverse-order removals fast. */
     335 GIC     5870805 :                 resarr->lastidx = resarr->nitems - 1;
     336 CBC     5870805 :                 return true;
     337 ECB             :             }
     338                 :         }
     339                 :     }
     340                 :     else
     341                 :     {
     342 GIC      674252 :         uint32      mask = resarr->capacity - 1;
     343 ECB             : 
     344 GIC      674252 :         if (lastidx < resarr->capacity &&
     345 CBC      674252 :             resarr->itemsarr[lastidx] == value)
     346 ECB             :         {
     347 GIC      199252 :             resarr->itemsarr[lastidx] = resarr->invalidval;
     348 CBC      199252 :             resarr->nitems--;
     349          199252 :             return true;
     350 ECB             :         }
     351 GIC      475000 :         idx = DatumGetUInt32(hash_any((void *) &value, sizeof(value))) & mask;
     352 CBC   171789826 :         for (i = 0; i < resarr->capacity; i++)
     353 ECB             :         {
     354 GIC   171789826 :             if (resarr->itemsarr[idx] == value)
     355 ECB             :             {
     356 GIC      475000 :                 resarr->itemsarr[idx] = resarr->invalidval;
     357 CBC      475000 :                 resarr->nitems--;
     358          475000 :                 return true;
     359 ECB             :             }
     360 GIC   171314826 :             idx = (idx + 1) & mask;
     361 ECB             :         }
     362                 :     }
     363                 : 
     364 UIC           0 :     return false;
     365 EUB             : }
     366                 : 
     367                 : /*
     368                 :  * Get any convenient entry in a ResourceArray.
     369                 :  *
     370                 :  * "Convenient" is defined as "easy for ResourceArrayRemove to remove";
     371                 :  * we help that along by setting lastidx to match.  This avoids O(N^2) cost
     372                 :  * when removing all ResourceArray items during ResourceOwner destruction.
     373                 :  *
     374                 :  * Returns true if we found an element, or false if the array is empty.
     375                 :  */
     376                 : static bool
     377 GIC    13180874 : ResourceArrayGetAny(ResourceArray *resarr, Datum *value)
     378 ECB             : {
     379 GIC    13180874 :     if (resarr->nitems == 0)
     380 CBC    13088006 :         return false;
     381 ECB             : 
     382 GIC       92868 :     if (RESARRAY_IS_ARRAY(resarr))
     383 ECB             :     {
     384                 :         /* Linear array: just return the first element. */
     385 GIC       83885 :         resarr->lastidx = 0;
     386 ECB             :     }
     387                 :     else
     388                 :     {
     389                 :         /* Hash: search forward from wherever we were last. */
     390 GIC        8983 :         uint32      mask = resarr->capacity - 1;
     391 ECB             : 
     392                 :         for (;;)
     393                 :         {
     394 GIC       22149 :             resarr->lastidx &= mask;
     395 CBC       22149 :             if (resarr->itemsarr[resarr->lastidx] != resarr->invalidval)
     396            8983 :                 break;
     397           13166 :             resarr->lastidx++;
     398 ECB             :         }
     399                 :     }
     400                 : 
     401 GIC       92868 :     *value = resarr->itemsarr[resarr->lastidx];
     402 CBC       92868 :     return true;
     403 ECB             : }
     404                 : 
     405                 : /*
     406                 :  * Trash a ResourceArray (we don't care about its state after this)
     407                 :  */
     408                 : static void
     409 GIC    13047411 : ResourceArrayFree(ResourceArray *resarr)
     410 ECB             : {
     411 GIC    13047411 :     if (resarr->itemsarr)
     412 CBC     3400021 :         pfree(resarr->itemsarr);
     413        13047411 : }
     414 ECB             : 
     415                 : 
     416                 : /*****************************************************************************
     417                 :  *    EXPORTED ROUTINES                                                      *
     418                 :  *****************************************************************************/
     419                 : 
     420                 : 
     421                 : /*
     422                 :  * ResourceOwnerCreate
     423                 :  *      Create an empty ResourceOwner.
     424                 :  *
     425                 :  * All ResourceOwner objects are kept in TopMemoryContext, since they should
     426                 :  * only be freed explicitly.
     427                 :  */
     428                 : ResourceOwner
     429 GIC     1006059 : ResourceOwnerCreate(ResourceOwner parent, const char *name)
     430 ECB             : {
     431                 :     ResourceOwner owner;
     432                 : 
     433 GIC     1006059 :     owner = (ResourceOwner) MemoryContextAllocZero(TopMemoryContext,
     434 ECB             :                                                    sizeof(ResourceOwnerData));
     435 GIC     1006059 :     owner->name = name;
     436 ECB             : 
     437 GIC     1006059 :     if (parent)
     438 ECB             :     {
     439 GIC      516105 :         owner->parent = parent;
     440 CBC      516105 :         owner->nextchild = parent->firstchild;
     441          516105 :         parent->firstchild = owner;
     442 ECB             :     }
     443                 : 
     444 GIC     1006059 :     ResourceArrayInit(&(owner->bufferarr), BufferGetDatum(InvalidBuffer));
     445 GNC     1006059 :     ResourceArrayInit(&(owner->bufferioarr), BufferGetDatum(InvalidBuffer));
     446 CBC     1006059 :     ResourceArrayInit(&(owner->catrefarr), PointerGetDatum(NULL));
     447         1006059 :     ResourceArrayInit(&(owner->catlistrefarr), PointerGetDatum(NULL));
     448         1006059 :     ResourceArrayInit(&(owner->relrefarr), PointerGetDatum(NULL));
     449         1006059 :     ResourceArrayInit(&(owner->planrefarr), PointerGetDatum(NULL));
     450         1006059 :     ResourceArrayInit(&(owner->tupdescarr), PointerGetDatum(NULL));
     451         1006059 :     ResourceArrayInit(&(owner->snapshotarr), PointerGetDatum(NULL));
     452         1006059 :     ResourceArrayInit(&(owner->filearr), FileGetDatum(-1));
     453         1006059 :     ResourceArrayInit(&(owner->dsmarr), PointerGetDatum(NULL));
     454         1006059 :     ResourceArrayInit(&(owner->jitarr), PointerGetDatum(NULL));
     455         1006059 :     ResourceArrayInit(&(owner->cryptohasharr), PointerGetDatum(NULL));
     456         1006059 :     ResourceArrayInit(&(owner->hmacarr), PointerGetDatum(NULL));
     457 ECB             : 
     458 CBC     1006059 :     return owner;
     459                 : }
     460 ECB             : 
     461                 : /*
     462                 :  * ResourceOwnerRelease
     463                 :  *      Release all resources owned by a ResourceOwner and its descendants,
     464                 :  *      but don't delete the owner objects themselves.
     465                 :  *
     466                 :  * Note that this executes just one phase of release, and so typically
     467                 :  * must be called three times.  We do it this way because (a) we want to
     468                 :  * do all the recursion separately for each phase, thereby preserving
     469                 :  * the needed order of operations; and (b) xact.c may have other operations
     470                 :  * to do between the phases.
     471                 :  *
     472                 :  * phase: release phase to execute
     473                 :  * isCommit: true for successful completion of a query or transaction,
     474                 :  *          false for unsuccessful
     475                 :  * isTopLevel: true if completing a main transaction, else false
     476                 :  *
     477                 :  * isCommit is passed because some modules may expect that their resources
     478                 :  * were all released already if the transaction or portal finished normally.
     479                 :  * If so it is reasonable to give a warning (NOT an error) should any
     480                 :  * unreleased resources be present.  When isCommit is false, such warnings
     481                 :  * are generally inappropriate.
     482                 :  *
     483                 :  * isTopLevel is passed when we are releasing TopTransactionResourceOwner
     484                 :  * at completion of a main transaction.  This generally means that *all*
     485                 :  * resources will be released, and so we can optimize things a bit.
     486                 :  */
     487                 : void
     488 GIC     2932668 : ResourceOwnerRelease(ResourceOwner owner,
     489                 :                      ResourceReleasePhase phase,
     490 ECB             :                      bool isCommit,
     491                 :                      bool isTopLevel)
     492                 : {
     493                 :     /* There's not currently any setup needed before recursing */
     494 GIC     2932668 :     ResourceOwnerReleaseInternal(owner, phase, isCommit, isTopLevel);
     495         2932668 : }
     496 ECB             : 
     497                 : static void
     498 GIC     3018624 : ResourceOwnerReleaseInternal(ResourceOwner owner,
     499                 :                              ResourceReleasePhase phase,
     500 ECB             :                              bool isCommit,
     501                 :                              bool isTopLevel)
     502                 : {
     503                 :     ResourceOwner child;
     504                 :     ResourceOwner save;
     505                 :     ResourceReleaseCallbackItem *item;
     506                 :     ResourceReleaseCallbackItem *next;
     507                 :     Datum       foundres;
     508                 : 
     509                 :     /* Recurse to handle descendants */
     510 GIC     3104580 :     for (child = owner->firstchild; child != NULL; child = child->nextchild)
     511           85956 :         ResourceOwnerReleaseInternal(child, phase, isCommit, isTopLevel);
     512                 : 
     513 ECB             :     /*
     514                 :      * Make CurrentResourceOwner point to me, so that ReleaseBuffer etc don't
     515                 :      * get confused.
     516                 :      */
     517 GIC     3018624 :     save = CurrentResourceOwner;
     518         3018624 :     CurrentResourceOwner = owner;
     519                 : 
     520 CBC     3018624 :     if (phase == RESOURCE_RELEASE_BEFORE_LOCKS)
     521 ECB             :     {
     522                 :         /*
     523                 :          * Abort failed buffer IO. AbortBufferIO()->TerminateBufferIO() calls
     524                 :          * ResourceOwnerForgetBufferIOs(), so we just have to iterate till
     525                 :          * there are none.
     526                 :          *
     527                 :          * Needs to be before we release buffer pins.
     528                 :          *
     529                 :          * During a commit, there shouldn't be any in-progress IO.
     530                 :          */
     531 GNC     1006221 :         while (ResourceArrayGetAny(&(owner->bufferioarr), &foundres))
     532                 :         {
     533              13 :             Buffer      res = DatumGetBuffer(foundres);
     534                 : 
     535              13 :             if (isCommit)
     536 UNC           0 :                 elog(PANIC, "lost track of buffer IO on buffer %u", res);
     537 GNC          13 :             AbortBufferIO(res);
     538                 :         }
     539                 : 
     540                 :         /*
     541 ECB             :          * Release buffer pins.  Note that ReleaseBuffer will remove the
     542                 :          * buffer entry from our array, so we just have to iterate till there
     543                 :          * are none.
     544                 :          *
     545                 :          * During a commit, there shouldn't be any remaining pins --- that
     546                 :          * would indicate failure to clean up the executor correctly --- so
     547                 :          * issue warnings.  In the abort case, just clean up quietly.
     548                 :          */
     549 GIC     1009873 :         while (ResourceArrayGetAny(&(owner->bufferarr), &foundres))
     550                 :         {
     551            3665 :             Buffer      res = DatumGetBuffer(foundres);
     552 ECB             : 
     553 GIC        3665 :             if (isCommit)
     554 LBC           0 :                 PrintBufferLeakWarning(res);
     555 GIC        3665 :             ReleaseBuffer(res);
     556 ECB             :         }
     557 EUB             : 
     558 ECB             :         /* Ditto for relcache references */
     559 GIC     1022070 :         while (ResourceArrayGetAny(&(owner->relrefarr), &foundres))
     560                 :         {
     561           15862 :             Relation    res = (Relation) DatumGetPointer(foundres);
     562                 : 
     563           15862 :             if (isCommit)
     564 UIC           0 :                 PrintRelCacheLeakWarning(res);
     565 GIC       15862 :             RelationClose(res);
     566                 :         }
     567                 : 
     568                 :         /* Ditto for dynamic shared memory segments */
     569         1006208 :         while (ResourceArrayGetAny(&(owner->dsmarr), &foundres))
     570 ECB             :         {
     571 UIC           0 :             dsm_segment *res = (dsm_segment *) DatumGetPointer(foundres);
     572 ECB             : 
     573 UIC           0 :             if (isCommit)
     574 LBC           0 :                 PrintDSMLeakWarning(res);
     575 UBC           0 :             dsm_detach(res);
     576 ECB             :         }
     577                 : 
     578                 :         /* Ditto for JIT contexts */
     579 GIC     1006216 :         while (ResourceArrayGetAny(&(owner->jitarr), &foundres))
     580 ECB             :         {
     581 GNC           8 :             JitContext *context = (JitContext *) DatumGetPointer(foundres);
     582 ECB             : 
     583 GIC           8 :             jit_release_context(context);
     584 ECB             :         }
     585 EUB             : 
     586 ECB             :         /* Ditto for cryptohash contexts */
     587 GIC     1006212 :         while (ResourceArrayGetAny(&(owner->cryptohasharr), &foundres))
     588                 :         {
     589                 :             pg_cryptohash_ctx *context =
     590 GNC           4 :             (pg_cryptohash_ctx *) DatumGetPointer(foundres);
     591                 : 
     592 GBC           4 :             if (isCommit)
     593 UIC           0 :                 PrintCryptoHashLeakWarning(foundres);
     594 GBC           4 :             pg_cryptohash_free(context);
     595 EUB             :         }
     596                 : 
     597                 :         /* Ditto for HMAC contexts */
     598 GIC     1006208 :         while (ResourceArrayGetAny(&(owner->hmacarr), &foundres))
     599                 :         {
     600 UNC           0 :             pg_hmac_ctx *context = (pg_hmac_ctx *) DatumGetPointer(foundres);
     601                 : 
     602 LBC           0 :             if (isCommit)
     603 UIC           0 :                 PrintHMACLeakWarning(foundres);
     604 LBC           0 :             pg_hmac_free(context);
     605                 :         }
     606                 :     }
     607 GIC     2012416 :     else if (phase == RESOURCE_RELEASE_LOCKS)
     608 ECB             :     {
     609 GIC     1006208 :         if (isTopLevel)
     610                 :         {
     611 ECB             :             /*
     612                 :              * For a top-level xact we are going to release all locks (or at
     613                 :              * least all non-session locks), so just do a single lmgr call at
     614 EUB             :              * the top of the recursion.
     615 ECB             :              */
     616 GIC      518632 :             if (owner == TopTransactionResourceOwner)
     617                 :             {
     618          486958 :                 ProcReleaseLocks(isCommit);
     619 CBC      486958 :                 ReleasePredicateLocks(isCommit, false);
     620                 :             }
     621 EUB             :         }
     622                 :         else
     623                 :         {
     624                 :             /*
     625                 :              * Release locks retail.  Note that if we are committing a
     626                 :              * subtransaction, we do NOT release its locks yet, but transfer
     627                 :              * them to the parent.
     628 ECB             :              */
     629                 :             LOCALLOCK **locks;
     630                 :             int         nlocks;
     631                 : 
     632 GIC      487576 :             Assert(owner->parent != NULL);
     633                 : 
     634                 :             /*
     635                 :              * Pass the list of locks owned by this resource owner to the lock
     636                 :              * manager, unless it has overflowed.
     637 ECB             :              */
     638 GIC      487576 :             if (owner->nlocks > MAX_RESOWNER_LOCKS)
     639 ECB             :             {
     640 CBC        3495 :                 locks = NULL;
     641 GIC        3495 :                 nlocks = 0;
     642                 :             }
     643                 :             else
     644                 :             {
     645          484081 :                 locks = owner->locks;
     646          484081 :                 nlocks = owner->nlocks;
     647                 :             }
     648                 : 
     649          487576 :             if (isCommit)
     650          482967 :                 LockReassignCurrentOwner(locks, nlocks);
     651                 :             else
     652            4609 :                 LockReleaseCurrentOwner(locks, nlocks);
     653 ECB             :         }
     654                 :     }
     655 GIC     1006208 :     else if (phase == RESOURCE_RELEASE_AFTER_LOCKS)
     656                 :     {
     657                 :         /*
     658                 :          * Release catcache references.  Note that ReleaseCatCache will remove
     659 ECB             :          * the catref entry from our array, so we just have to iterate till
     660                 :          * there are none.
     661                 :          *
     662                 :          * As with buffer pins, warn if any are left at commit time.
     663                 :          */
     664 GIC     1010879 :         while (ResourceArrayGetAny(&(owner->catrefarr), &foundres))
     665                 :         {
     666 CBC        4671 :             HeapTuple   res = (HeapTuple) DatumGetPointer(foundres);
     667 ECB             : 
     668 GIC        4671 :             if (isCommit)
     669 UIC           0 :                 PrintCatCacheLeakWarning(res);
     670 CBC        4671 :             ReleaseCatCache(res);
     671 ECB             :         }
     672                 : 
     673                 :         /* Ditto for catcache lists */
     674 GIC     1006226 :         while (ResourceArrayGetAny(&(owner->catlistrefarr), &foundres))
     675                 :         {
     676 CBC          18 :             CatCList   *res = (CatCList *) DatumGetPointer(foundres);
     677                 : 
     678 GIC          18 :             if (isCommit)
     679 UIC           0 :                 PrintCatCacheListLeakWarning(res);
     680 GIC          18 :             ReleaseCatCacheList(res);
     681                 :         }
     682                 : 
     683                 :         /* Ditto for plancache references */
     684         1011274 :         while (ResourceArrayGetAny(&(owner->planrefarr), &foundres))
     685 ECB             :         {
     686 GIC        5066 :             CachedPlan *res = (CachedPlan *) DatumGetPointer(foundres);
     687 ECB             : 
     688 GIC        5066 :             if (isCommit)
     689 LBC           0 :                 PrintPlanCacheLeakWarning(res);
     690 GBC        5066 :             ReleaseCachedPlan(res, owner);
     691 ECB             :         }
     692                 : 
     693                 :         /* Ditto for tupdesc references */
     694 GIC     1011717 :         while (ResourceArrayGetAny(&(owner->tupdescarr), &foundres))
     695 ECB             :         {
     696 GIC        5509 :             TupleDesc   res = (TupleDesc) DatumGetPointer(foundres);
     697 ECB             : 
     698 GIC        5509 :             if (isCommit)
     699 LBC           0 :                 PrintTupleDescLeakWarning(res);
     700 GBC        5509 :             DecrTupleDescRefCount(res);
     701 ECB             :         }
     702                 : 
     703                 :         /* Ditto for snapshot references */
     704 GIC     1031379 :         while (ResourceArrayGetAny(&(owner->snapshotarr), &foundres))
     705 ECB             :         {
     706 GIC       25171 :             Snapshot    res = (Snapshot) DatumGetPointer(foundres);
     707 ECB             : 
     708 GIC       25171 :             if (isCommit)
     709 LBC           0 :                 PrintSnapshotLeakWarning(res);
     710 GBC       25171 :             UnregisterSnapshot(res);
     711 ECB             :         }
     712                 : 
     713                 :         /* Ditto for temporary files */
     714 GIC     1006212 :         while (ResourceArrayGetAny(&(owner->filearr), &foundres))
     715 ECB             :         {
     716 GIC           4 :             File        res = DatumGetFile(foundres);
     717 ECB             : 
     718 GIC           4 :             if (isCommit)
     719 LBC           0 :                 PrintFileLeakWarning(res);
     720 GBC           4 :             FileClose(res);
     721 ECB             :         }
     722                 :     }
     723                 : 
     724                 :     /* Let add-on modules get a chance too */
     725 GNC     3020262 :     for (item = ResourceRelease_callbacks; item; item = next)
     726                 :     {
     727                 :         /* allow callbacks to unregister themselves when called */
     728            1638 :         next = item->next;
     729 GIC        1638 :         item->callback(phase, isCommit, isTopLevel, item->arg);
     730                 :     }
     731 ECB             : 
     732 GIC     3018624 :     CurrentResourceOwner = save;
     733 CBC     3018624 : }
     734 EUB             : 
     735 ECB             : /*
     736                 :  * ResourceOwnerReleaseAllPlanCacheRefs
     737                 :  *      Release the plancache references (only) held by this owner.
     738                 :  *
     739                 :  * We might eventually add similar functions for other resource types,
     740                 :  * but for now, only this is needed.
     741                 :  */
     742                 : void
     743 CBC        7302 : ResourceOwnerReleaseAllPlanCacheRefs(ResourceOwner owner)
     744 EUB             : {
     745 ECB             :     Datum       foundres;
     746                 : 
     747 GIC       40179 :     while (ResourceArrayGetAny(&(owner->planrefarr), &foundres))
     748                 :     {
     749           32877 :         CachedPlan *res = (CachedPlan *) DatumGetPointer(foundres);
     750 ECB             : 
     751 GIC       32877 :         ReleaseCachedPlan(res, owner);
     752                 :     }
     753 CBC        7302 : }
     754 ECB             : 
     755                 : /*
     756                 :  * ResourceOwnerDelete
     757                 :  *      Delete an owner object and its descendants.
     758                 :  *
     759                 :  * The caller must have already released all resources in the object tree.
     760                 :  */
     761                 : void
     762 GIC     1003647 : ResourceOwnerDelete(ResourceOwner owner)
     763                 : {
     764                 :     /* We had better not be deleting CurrentResourceOwner ... */
     765         1003647 :     Assert(owner != CurrentResourceOwner);
     766                 : 
     767                 :     /* And it better not own any resources, either */
     768 CBC     1003647 :     Assert(owner->bufferarr.nitems == 0);
     769 GNC     1003647 :     Assert(owner->bufferioarr.nitems == 0);
     770 GIC     1003647 :     Assert(owner->catrefarr.nitems == 0);
     771         1003647 :     Assert(owner->catlistrefarr.nitems == 0);
     772         1003647 :     Assert(owner->relrefarr.nitems == 0);
     773 CBC     1003647 :     Assert(owner->planrefarr.nitems == 0);
     774 GIC     1003647 :     Assert(owner->tupdescarr.nitems == 0);
     775 CBC     1003647 :     Assert(owner->snapshotarr.nitems == 0);
     776 GIC     1003647 :     Assert(owner->filearr.nitems == 0);
     777 CBC     1003647 :     Assert(owner->dsmarr.nitems == 0);
     778 GIC     1003647 :     Assert(owner->jitarr.nitems == 0);
     779 CBC     1003647 :     Assert(owner->cryptohasharr.nitems == 0);
     780 GIC     1003647 :     Assert(owner->hmacarr.nitems == 0);
     781         1003647 :     Assert(owner->nlocks == 0 || owner->nlocks == MAX_RESOWNER_LOCKS + 1);
     782                 : 
     783                 :     /*
     784                 :      * Delete children.  The recursive call will delink the child from me, so
     785                 :      * just iterate as long as there is a child.
     786                 :      */
     787         1032302 :     while (owner->firstchild != NULL)
     788 CBC       28655 :         ResourceOwnerDelete(owner->firstchild);
     789                 : 
     790                 :     /*
     791 ECB             :      * We delink the owner from its parent before deleting it, so that if
     792                 :      * there's an error we won't have deleted/busted owners still attached to
     793                 :      * the owner tree.  Better a leak than a crash.
     794                 :      */
     795 CBC     1003647 :     ResourceOwnerNewParent(owner, NULL);
     796 ECB             : 
     797                 :     /* And free the object. */
     798 CBC     1003647 :     ResourceArrayFree(&(owner->bufferarr));
     799 GNC     1003647 :     ResourceArrayFree(&(owner->bufferioarr));
     800 CBC     1003647 :     ResourceArrayFree(&(owner->catrefarr));
     801         1003647 :     ResourceArrayFree(&(owner->catlistrefarr));
     802         1003647 :     ResourceArrayFree(&(owner->relrefarr));
     803         1003647 :     ResourceArrayFree(&(owner->planrefarr));
     804         1003647 :     ResourceArrayFree(&(owner->tupdescarr));
     805         1003647 :     ResourceArrayFree(&(owner->snapshotarr));
     806         1003647 :     ResourceArrayFree(&(owner->filearr));
     807         1003647 :     ResourceArrayFree(&(owner->dsmarr));
     808         1003647 :     ResourceArrayFree(&(owner->jitarr));
     809 GIC     1003647 :     ResourceArrayFree(&(owner->cryptohasharr));
     810         1003647 :     ResourceArrayFree(&(owner->hmacarr));
     811                 : 
     812         1003647 :     pfree(owner);
     813         1003647 : }
     814 ECB             : 
     815                 : /*
     816                 :  * Fetch parent of a ResourceOwner (returns NULL if top-level owner)
     817                 :  */
     818                 : ResourceOwner
     819 GIC      482967 : ResourceOwnerGetParent(ResourceOwner owner)
     820                 : {
     821          482967 :     return owner->parent;
     822 ECB             : }
     823                 : 
     824                 : /*
     825                 :  * Reassign a ResourceOwner to have a new parent
     826                 :  */
     827                 : void
     828 CBC     1003682 : ResourceOwnerNewParent(ResourceOwner owner,
     829 ECB             :                        ResourceOwner newparent)
     830                 : {
     831 CBC     1003682 :     ResourceOwner oldparent = owner->parent;
     832 ECB             : 
     833 CBC     1003682 :     if (oldparent)
     834 ECB             :     {
     835 CBC      516140 :         if (owner == oldparent->firstchild)
     836          508911 :             oldparent->firstchild = owner->nextchild;
     837 ECB             :         else
     838                 :         {
     839                 :             ResourceOwner child;
     840                 : 
     841 GIC        8148 :             for (child = oldparent->firstchild; child; child = child->nextchild)
     842                 :             {
     843            8148 :                 if (owner == child->nextchild)
     844                 :                 {
     845            7229 :                     child->nextchild = owner->nextchild;
     846 CBC        7229 :                     break;
     847                 :                 }
     848 ECB             :             }
     849                 :         }
     850                 :     }
     851                 : 
     852 GIC     1003682 :     if (newparent)
     853                 :     {
     854              35 :         Assert(owner != newparent);
     855 CBC          35 :         owner->parent = newparent;
     856 GIC          35 :         owner->nextchild = newparent->firstchild;
     857              35 :         newparent->firstchild = owner;
     858 ECB             :     }
     859                 :     else
     860                 :     {
     861 GIC     1003647 :         owner->parent = NULL;
     862 CBC     1003647 :         owner->nextchild = NULL;
     863 ECB             :     }
     864 GIC     1003682 : }
     865                 : 
     866                 : /*
     867                 :  * Register or deregister callback functions for resource cleanup
     868 ECB             :  *
     869                 :  * These functions are intended for use by dynamically loaded modules.
     870                 :  * For built-in modules we generally just hardwire the appropriate calls.
     871                 :  *
     872                 :  * Note that the callback occurs post-commit or post-abort, so the callback
     873                 :  * functions can only do noncritical cleanup.
     874                 :  */
     875                 : void
     876 GIC          23 : RegisterResourceReleaseCallback(ResourceReleaseCallback callback, void *arg)
     877                 : {
     878                 :     ResourceReleaseCallbackItem *item;
     879 ECB             : 
     880                 :     item = (ResourceReleaseCallbackItem *)
     881 CBC          23 :         MemoryContextAlloc(TopMemoryContext,
     882 ECB             :                            sizeof(ResourceReleaseCallbackItem));
     883 CBC          23 :     item->callback = callback;
     884              23 :     item->arg = arg;
     885 GIC          23 :     item->next = ResourceRelease_callbacks;
     886              23 :     ResourceRelease_callbacks = item;
     887              23 : }
     888 ECB             : 
     889                 : void
     890 UIC           0 : UnregisterResourceReleaseCallback(ResourceReleaseCallback callback, void *arg)
     891 ECB             : {
     892                 :     ResourceReleaseCallbackItem *item;
     893                 :     ResourceReleaseCallbackItem *prev;
     894                 : 
     895 UIC           0 :     prev = NULL;
     896               0 :     for (item = ResourceRelease_callbacks; item; prev = item, item = item->next)
     897                 :     {
     898               0 :         if (item->callback == callback && item->arg == arg)
     899                 :         {
     900               0 :             if (prev)
     901               0 :                 prev->next = item->next;
     902                 :             else
     903 LBC           0 :                 ResourceRelease_callbacks = item->next;
     904 UIC           0 :             pfree(item);
     905               0 :             break;
     906                 :         }
     907                 :     }
     908 LBC           0 : }
     909                 : 
     910 ECB             : /*
     911                 :  * Establish an AuxProcessResourceOwner for the current process.
     912                 :  */
     913                 : void
     914 CBC        2407 : CreateAuxProcessResourceOwner(void)
     915                 : {
     916 GIC        2407 :     Assert(AuxProcessResourceOwner == NULL);
     917 GBC        2407 :     Assert(CurrentResourceOwner == NULL);
     918 GIC        2407 :     AuxProcessResourceOwner = ResourceOwnerCreate(NULL, "AuxiliaryProcess");
     919            2407 :     CurrentResourceOwner = AuxProcessResourceOwner;
     920                 : 
     921                 :     /*
     922 EUB             :      * Register a shmem-exit callback for cleanup of aux-process resource
     923                 :      * owner.  (This needs to run after, e.g., ShutdownXLOG.)
     924                 :      */
     925 GBC        2407 :     on_shmem_exit(ReleaseAuxProcessResourcesCallback, 0);
     926 GIC        2407 : }
     927 EUB             : 
     928                 : /*
     929                 :  * Convenience routine to release all resources tracked in
     930                 :  * AuxProcessResourceOwner (but that resowner is not destroyed here).
     931                 :  * Warn about leaked resources if isCommit is true.
     932                 :  */
     933                 : void
     934 GIC        3026 : ReleaseAuxProcessResources(bool isCommit)
     935 EUB             : {
     936                 :     /*
     937                 :      * At this writing, the only thing that could actually get released is
     938                 :      * buffer pins; but we may as well do the full release protocol.
     939                 :      */
     940 GIC        3026 :     ResourceOwnerRelease(AuxProcessResourceOwner,
     941 ECB             :                          RESOURCE_RELEASE_BEFORE_LOCKS,
     942                 :                          isCommit, true);
     943 CBC        3026 :     ResourceOwnerRelease(AuxProcessResourceOwner,
     944 ECB             :                          RESOURCE_RELEASE_LOCKS,
     945                 :                          isCommit, true);
     946 CBC        3026 :     ResourceOwnerRelease(AuxProcessResourceOwner,
     947                 :                          RESOURCE_RELEASE_AFTER_LOCKS,
     948                 :                          isCommit, true);
     949 GIC        3026 : }
     950                 : 
     951                 : /*
     952 ECB             :  * Shmem-exit callback for the same.
     953                 :  * Warn about leaked resources if process exit code is zero (ie normal).
     954                 :  */
     955                 : static void
     956 GIC        2407 : ReleaseAuxProcessResourcesCallback(int code, Datum arg)
     957                 : {
     958            2407 :     bool        isCommit = (code == 0);
     959                 : 
     960            2407 :     ReleaseAuxProcessResources(isCommit);
     961 CBC        2407 : }
     962                 : 
     963                 : 
     964                 : /*
     965                 :  * Make sure there is room for at least one more entry in a ResourceOwner's
     966                 :  * buffer array.
     967 ECB             :  *
     968                 :  * This is separate from actually inserting an entry because if we run out
     969                 :  * of memory, it's critical to do so *before* acquiring the resource.
     970                 :  */
     971                 : void
     972 GIC    84925049 : ResourceOwnerEnlargeBuffers(ResourceOwner owner)
     973 ECB             : {
     974                 :     /* We used to allow pinning buffers without a resowner, but no more */
     975 GIC    84925049 :     Assert(owner != NULL);
     976 CBC    84925049 :     ResourceArrayEnlarge(&(owner->bufferarr));
     977 GIC    84925049 : }
     978                 : 
     979                 : /*
     980                 :  * Remember that a buffer pin is owned by a ResourceOwner
     981                 :  *
     982                 :  * Caller must have previously done ResourceOwnerEnlargeBuffers()
     983 ECB             :  */
     984                 : void
     985 CBC    83570573 : ResourceOwnerRememberBuffer(ResourceOwner owner, Buffer buffer)
     986                 : {
     987        83570573 :     ResourceArrayAdd(&(owner->bufferarr), BufferGetDatum(buffer));
     988        83570573 : }
     989                 : 
     990                 : /*
     991                 :  * Forget that a buffer pin is owned by a ResourceOwner
     992                 :  */
     993                 : void
     994 GIC    83570573 : ResourceOwnerForgetBuffer(ResourceOwner owner, Buffer buffer)
     995                 : {
     996        83570573 :     if (!ResourceArrayRemove(&(owner->bufferarr), BufferGetDatum(buffer)))
     997 UIC           0 :         elog(ERROR, "buffer %d is not owned by resource owner %s",
     998                 :              buffer, owner->name);
     999 CBC    83570573 : }
    1000                 : 
    1001                 : 
    1002                 : /*
    1003                 :  * Make sure there is room for at least one more entry in a ResourceOwner's
    1004                 :  * buffer array.
    1005                 :  *
    1006                 :  * This is separate from actually inserting an entry because if we run out
    1007                 :  * of memory, it's critical to do so *before* acquiring the resource.
    1008                 :  */
    1009                 : void
    1010 GNC     2601190 : ResourceOwnerEnlargeBufferIOs(ResourceOwner owner)
    1011                 : {
    1012                 :     /* We used to allow pinning buffers without a resowner, but no more */
    1013         2601190 :     Assert(owner != NULL);
    1014         2601190 :     ResourceArrayEnlarge(&(owner->bufferioarr));
    1015         2601190 : }
    1016                 : 
    1017                 : /*
    1018                 :  * Remember that a buffer IO is owned by a ResourceOwner
    1019                 :  *
    1020                 :  * Caller must have previously done ResourceOwnerEnlargeBufferIOs()
    1021                 :  */
    1022                 : void
    1023         2599422 : ResourceOwnerRememberBufferIO(ResourceOwner owner, Buffer buffer)
    1024                 : {
    1025         2599422 :     ResourceArrayAdd(&(owner->bufferioarr), BufferGetDatum(buffer));
    1026         2599422 : }
    1027                 : 
    1028                 : /*
    1029                 :  * Forget that a buffer IO is owned by a ResourceOwner
    1030                 :  */
    1031                 : void
    1032         2599422 : ResourceOwnerForgetBufferIO(ResourceOwner owner, Buffer buffer)
    1033                 : {
    1034         2599422 :     if (!ResourceArrayRemove(&(owner->bufferioarr), BufferGetDatum(buffer)))
    1035 UNC           0 :         elog(PANIC, "buffer IO %d is not owned by resource owner %s",
    1036                 :              buffer, owner->name);
    1037 GNC     2599422 : }
    1038                 : 
    1039                 : /*
    1040 ECB             :  * Remember that a Local Lock is owned by a ResourceOwner
    1041                 :  *
    1042                 :  * This is different from the other Remember functions in that the list of
    1043                 :  * locks is only a lossy cache. It can hold up to MAX_RESOWNER_LOCKS entries,
    1044                 :  * and when it overflows, we stop tracking locks. The point of only remembering
    1045                 :  * only up to MAX_RESOWNER_LOCKS entries is that if a lot of locks are held,
    1046                 :  * ResourceOwnerForgetLock doesn't need to scan through a large array to find
    1047                 :  * the entry.
    1048                 :  */
    1049                 : void
    1050 CBC    27048592 : ResourceOwnerRememberLock(ResourceOwner owner, LOCALLOCK *locallock)
    1051                 : {
    1052        27048592 :     Assert(locallock != NULL);
    1053 ECB             : 
    1054 GIC    27048592 :     if (owner->nlocks > MAX_RESOWNER_LOCKS)
    1055         2034678 :         return;                 /* we have already overflowed */
    1056                 : 
    1057        25013914 :     if (owner->nlocks < MAX_RESOWNER_LOCKS)
    1058        25005006 :         owner->locks[owner->nlocks] = locallock;
    1059 ECB             :     else
    1060                 :     {
    1061                 :         /* overflowed */
    1062 EUB             :     }
    1063 GIC    25013914 :     owner->nlocks++;
    1064 ECB             : }
    1065                 : 
    1066                 : /*
    1067                 :  * Forget that a Local Lock is owned by a ResourceOwner
    1068                 :  */
    1069                 : void
    1070 GIC    27048592 : ResourceOwnerForgetLock(ResourceOwner owner, LOCALLOCK *locallock)
    1071                 : {
    1072                 :     int         i;
    1073                 : 
    1074        27048592 :     if (owner->nlocks > MAX_RESOWNER_LOCKS)
    1075 CBC     2177206 :         return;                 /* we have overflowed */
    1076                 : 
    1077 GIC    24871386 :     Assert(owner->nlocks > 0);
    1078 CBC    28514759 :     for (i = owner->nlocks - 1; i >= 0; i--)
    1079 ECB             :     {
    1080 CBC    28514759 :         if (locallock == owner->locks[i])
    1081                 :         {
    1082 GIC    24871386 :             owner->locks[i] = owner->locks[owner->nlocks - 1];
    1083        24871386 :             owner->nlocks--;
    1084        24871386 :             return;
    1085                 :         }
    1086                 :     }
    1087 UIC           0 :     elog(ERROR, "lock reference %p is not owned by resource owner %s",
    1088 ECB             :          locallock, owner->name);
    1089                 : }
    1090                 : 
    1091                 : /*
    1092                 :  * Make sure there is room for at least one more entry in a ResourceOwner's
    1093                 :  * catcache reference array.
    1094                 :  *
    1095                 :  * This is separate from actually inserting an entry because if we run out
    1096                 :  * of memory, it's critical to do so *before* acquiring the resource.
    1097                 :  */
    1098                 : void
    1099 CBC    48196159 : ResourceOwnerEnlargeCatCacheRefs(ResourceOwner owner)
    1100 EUB             : {
    1101 GIC    48196159 :     ResourceArrayEnlarge(&(owner->catrefarr));
    1102 CBC    48196159 : }
    1103                 : 
    1104                 : /*
    1105                 :  * Remember that a catcache reference is owned by a ResourceOwner
    1106                 :  *
    1107                 :  * Caller must have previously done ResourceOwnerEnlargeCatCacheRefs()
    1108                 :  */
    1109                 : void
    1110 GIC    48196159 : ResourceOwnerRememberCatCacheRef(ResourceOwner owner, HeapTuple tuple)
    1111                 : {
    1112        48196159 :     ResourceArrayAdd(&(owner->catrefarr), PointerGetDatum(tuple));
    1113        48196159 : }
    1114                 : 
    1115 ECB             : /*
    1116                 :  * Forget that a catcache reference is owned by a ResourceOwner
    1117                 :  */
    1118                 : void
    1119 CBC    48196159 : ResourceOwnerForgetCatCacheRef(ResourceOwner owner, HeapTuple tuple)
    1120 ECB             : {
    1121 GIC    48196159 :     if (!ResourceArrayRemove(&(owner->catrefarr), PointerGetDatum(tuple)))
    1122 LBC           0 :         elog(ERROR, "catcache reference %p is not owned by resource owner %s",
    1123 ECB             :              tuple, owner->name);
    1124 GIC    48196159 : }
    1125                 : 
    1126                 : /*
    1127                 :  * Make sure there is room for at least one more entry in a ResourceOwner's
    1128 ECB             :  * catcache-list reference array.
    1129                 :  *
    1130                 :  * This is separate from actually inserting an entry because if we run out
    1131                 :  * of memory, it's critical to do so *before* acquiring the resource.
    1132                 :  */
    1133                 : void
    1134 GIC     1600190 : ResourceOwnerEnlargeCatCacheListRefs(ResourceOwner owner)
    1135 ECB             : {
    1136 GIC     1600190 :     ResourceArrayEnlarge(&(owner->catlistrefarr));
    1137         1600190 : }
    1138                 : 
    1139 ECB             : /*
    1140                 :  * Remember that a catcache-list reference is owned by a ResourceOwner
    1141                 :  *
    1142                 :  * Caller must have previously done ResourceOwnerEnlargeCatCacheListRefs()
    1143                 :  */
    1144                 : void
    1145 CBC     1600190 : ResourceOwnerRememberCatCacheListRef(ResourceOwner owner, CatCList *list)
    1146                 : {
    1147         1600190 :     ResourceArrayAdd(&(owner->catlistrefarr), PointerGetDatum(list));
    1148         1600190 : }
    1149 ECB             : 
    1150                 : /*
    1151                 :  * Forget that a catcache-list reference is owned by a ResourceOwner
    1152 EUB             :  */
    1153                 : void
    1154 GIC     1600190 : ResourceOwnerForgetCatCacheListRef(ResourceOwner owner, CatCList *list)
    1155                 : {
    1156         1600190 :     if (!ResourceArrayRemove(&(owner->catlistrefarr), PointerGetDatum(list)))
    1157 UIC           0 :         elog(ERROR, "catcache list reference %p is not owned by resource owner %s",
    1158                 :              list, owner->name);
    1159 GIC     1600190 : }
    1160                 : 
    1161                 : /*
    1162                 :  * Make sure there is room for at least one more entry in a ResourceOwner's
    1163                 :  * relcache reference array.
    1164 ECB             :  *
    1165                 :  * This is separate from actually inserting an entry because if we run out
    1166                 :  * of memory, it's critical to do so *before* acquiring the resource.
    1167                 :  */
    1168                 : void
    1169 GIC    40884389 : ResourceOwnerEnlargeRelationRefs(ResourceOwner owner)
    1170                 : {
    1171        40884389 :     ResourceArrayEnlarge(&(owner->relrefarr));
    1172        40884389 : }
    1173                 : 
    1174                 : /*
    1175 ECB             :  * Remember that a relcache reference is owned by a ResourceOwner
    1176                 :  *
    1177                 :  * Caller must have previously done ResourceOwnerEnlargeRelationRefs()
    1178                 :  */
    1179                 : void
    1180 GIC    39145584 : ResourceOwnerRememberRelationRef(ResourceOwner owner, Relation rel)
    1181                 : {
    1182        39145584 :     ResourceArrayAdd(&(owner->relrefarr), PointerGetDatum(rel));
    1183        39145584 : }
    1184 ECB             : 
    1185                 : /*
    1186                 :  * Forget that a relcache reference is owned by a ResourceOwner
    1187 EUB             :  */
    1188                 : void
    1189 CBC    39145584 : ResourceOwnerForgetRelationRef(ResourceOwner owner, Relation rel)
    1190                 : {
    1191 GIC    39145584 :     if (!ResourceArrayRemove(&(owner->relrefarr), PointerGetDatum(rel)))
    1192 UIC           0 :         elog(ERROR, "relcache reference %s is not owned by resource owner %s",
    1193                 :              RelationGetRelationName(rel), owner->name);
    1194 GIC    39145584 : }
    1195                 : 
    1196                 : /*
    1197                 :  * Debugging subroutine
    1198                 :  */
    1199 ECB             : static void
    1200 UIC           0 : PrintRelCacheLeakWarning(Relation rel)
    1201 ECB             : {
    1202 LBC           0 :     elog(WARNING, "relcache reference leak: relation \"%s\" not closed",
    1203                 :          RelationGetRelationName(rel));
    1204 UIC           0 : }
    1205                 : 
    1206                 : /*
    1207                 :  * Make sure there is room for at least one more entry in a ResourceOwner's
    1208                 :  * plancache reference array.
    1209                 :  *
    1210 ECB             :  * This is separate from actually inserting an entry because if we run out
    1211                 :  * of memory, it's critical to do so *before* acquiring the resource.
    1212                 :  */
    1213                 : void
    1214 GIC       83803 : ResourceOwnerEnlargePlanCacheRefs(ResourceOwner owner)
    1215                 : {
    1216           83803 :     ResourceArrayEnlarge(&(owner->planrefarr));
    1217           83803 : }
    1218                 : 
    1219 ECB             : /*
    1220                 :  * Remember that a plancache reference is owned by a ResourceOwner
    1221                 :  *
    1222 EUB             :  * Caller must have previously done ResourceOwnerEnlargePlanCacheRefs()
    1223                 :  */
    1224 ECB             : void
    1225 GIC       83803 : ResourceOwnerRememberPlanCacheRef(ResourceOwner owner, CachedPlan *plan)
    1226                 : {
    1227           83803 :     ResourceArrayAdd(&(owner->planrefarr), PointerGetDatum(plan));
    1228           83803 : }
    1229                 : 
    1230                 : /*
    1231                 :  * Forget that a plancache reference is owned by a ResourceOwner
    1232                 :  */
    1233                 : void
    1234 CBC       83803 : ResourceOwnerForgetPlanCacheRef(ResourceOwner owner, CachedPlan *plan)
    1235                 : {
    1236           83803 :     if (!ResourceArrayRemove(&(owner->planrefarr), PointerGetDatum(plan)))
    1237 LBC           0 :         elog(ERROR, "plancache reference %p is not owned by resource owner %s",
    1238                 :              plan, owner->name);
    1239 GIC       83803 : }
    1240                 : 
    1241                 : /*
    1242                 :  * Debugging subroutine
    1243                 :  */
    1244                 : static void
    1245 LBC           0 : PrintPlanCacheLeakWarning(CachedPlan *plan)
    1246                 : {
    1247               0 :     elog(WARNING, "plancache reference leak: plan %p not closed", plan);
    1248               0 : }
    1249                 : 
    1250                 : /*
    1251                 :  * Make sure there is room for at least one more entry in a ResourceOwner's
    1252                 :  * tupdesc reference array.
    1253                 :  *
    1254 ECB             :  * This is separate from actually inserting an entry because if we run out
    1255                 :  * of memory, it's critical to do so *before* acquiring the resource.
    1256                 :  */
    1257 EUB             : void
    1258 GIC    21264947 : ResourceOwnerEnlargeTupleDescs(ResourceOwner owner)
    1259 ECB             : {
    1260 GIC    21264947 :     ResourceArrayEnlarge(&(owner->tupdescarr));
    1261        21264947 : }
    1262                 : 
    1263                 : /*
    1264                 :  * Remember that a tupdesc reference is owned by a ResourceOwner
    1265 EUB             :  *
    1266                 :  * Caller must have previously done ResourceOwnerEnlargeTupleDescs()
    1267                 :  */
    1268                 : void
    1269 GBC    21264947 : ResourceOwnerRememberTupleDesc(ResourceOwner owner, TupleDesc tupdesc)
    1270                 : {
    1271 GIC    21264947 :     ResourceArrayAdd(&(owner->tupdescarr), PointerGetDatum(tupdesc));
    1272        21264947 : }
    1273                 : 
    1274                 : /*
    1275                 :  * Forget that a tupdesc reference is owned by a ResourceOwner
    1276                 :  */
    1277                 : void
    1278        21264947 : ResourceOwnerForgetTupleDesc(ResourceOwner owner, TupleDesc tupdesc)
    1279 ECB             : {
    1280 GIC    21264947 :     if (!ResourceArrayRemove(&(owner->tupdescarr), PointerGetDatum(tupdesc)))
    1281 LBC           0 :         elog(ERROR, "tupdesc reference %p is not owned by resource owner %s",
    1282 ECB             :              tupdesc, owner->name);
    1283 GIC    21264947 : }
    1284                 : 
    1285                 : /*
    1286                 :  * Debugging subroutine
    1287                 :  */
    1288                 : static void
    1289 UIC           0 : PrintTupleDescLeakWarning(TupleDesc tupdesc)
    1290 ECB             : {
    1291 UIC           0 :     elog(WARNING,
    1292 ECB             :          "TupleDesc reference leak: TupleDesc %p (%u,%d) still referenced",
    1293                 :          tupdesc, tupdesc->tdtypeid, tupdesc->tdtypmod);
    1294 UIC           0 : }
    1295                 : 
    1296                 : /*
    1297                 :  * Make sure there is room for at least one more entry in a ResourceOwner's
    1298                 :  * snapshot reference array.
    1299 ECB             :  *
    1300                 :  * This is separate from actually inserting an entry because if we run out
    1301                 :  * of memory, it's critical to do so *before* acquiring the resource.
    1302 EUB             :  */
    1303                 : void
    1304 CBC     8845361 : ResourceOwnerEnlargeSnapshots(ResourceOwner owner)
    1305                 : {
    1306 GIC     8845361 :     ResourceArrayEnlarge(&(owner->snapshotarr));
    1307         8845361 : }
    1308                 : 
    1309                 : /*
    1310 EUB             :  * Remember that a snapshot reference is owned by a ResourceOwner
    1311                 :  *
    1312                 :  * Caller must have previously done ResourceOwnerEnlargeSnapshots()
    1313                 :  */
    1314                 : void
    1315 GIC     8845361 : ResourceOwnerRememberSnapshot(ResourceOwner owner, Snapshot snapshot)
    1316                 : {
    1317         8845361 :     ResourceArrayAdd(&(owner->snapshotarr), PointerGetDatum(snapshot));
    1318         8845361 : }
    1319                 : 
    1320                 : /*
    1321                 :  * Forget that a snapshot reference is owned by a ResourceOwner
    1322                 :  */
    1323 ECB             : void
    1324 GIC     8845361 : ResourceOwnerForgetSnapshot(ResourceOwner owner, Snapshot snapshot)
    1325 ECB             : {
    1326 CBC     8845361 :     if (!ResourceArrayRemove(&(owner->snapshotarr), PointerGetDatum(snapshot)))
    1327 UIC           0 :         elog(ERROR, "snapshot reference %p is not owned by resource owner %s",
    1328                 :              snapshot, owner->name);
    1329 GIC     8845361 : }
    1330                 : 
    1331                 : /*
    1332                 :  * Debugging subroutine
    1333                 :  */
    1334 ECB             : static void
    1335 UIC           0 : PrintSnapshotLeakWarning(Snapshot snapshot)
    1336 ECB             : {
    1337 LBC           0 :     elog(WARNING, "Snapshot reference leak: Snapshot %p still referenced",
    1338                 :          snapshot);
    1339 UIC           0 : }
    1340                 : 
    1341                 : 
    1342                 : /*
    1343 ECB             :  * Make sure there is room for at least one more entry in a ResourceOwner's
    1344                 :  * files reference array.
    1345                 :  *
    1346 EUB             :  * This is separate from actually inserting an entry because if we run out
    1347                 :  * of memory, it's critical to do so *before* acquiring the resource.
    1348 ECB             :  */
    1349                 : void
    1350 GIC        7446 : ResourceOwnerEnlargeFiles(ResourceOwner owner)
    1351                 : {
    1352            7446 :     ResourceArrayEnlarge(&(owner->filearr));
    1353            7446 : }
    1354 EUB             : 
    1355                 : /*
    1356                 :  * Remember that a temporary file is owned by a ResourceOwner
    1357                 :  *
    1358                 :  * Caller must have previously done ResourceOwnerEnlargeFiles()
    1359                 :  */
    1360                 : void
    1361 GIC        5110 : ResourceOwnerRememberFile(ResourceOwner owner, File file)
    1362                 : {
    1363            5110 :     ResourceArrayAdd(&(owner->filearr), FileGetDatum(file));
    1364            5110 : }
    1365                 : 
    1366                 : /*
    1367                 :  * Forget that a temporary file is owned by a ResourceOwner
    1368                 :  */
    1369 ECB             : void
    1370 GIC        5110 : ResourceOwnerForgetFile(ResourceOwner owner, File file)
    1371 ECB             : {
    1372 CBC        5110 :     if (!ResourceArrayRemove(&(owner->filearr), FileGetDatum(file)))
    1373 UIC           0 :         elog(ERROR, "temporary file %d is not owned by resource owner %s",
    1374                 :              file, owner->name);
    1375 GIC        5110 : }
    1376                 : 
    1377                 : /*
    1378                 :  * Debugging subroutine
    1379                 :  */
    1380 ECB             : static void
    1381 UIC           0 : PrintFileLeakWarning(File file)
    1382 ECB             : {
    1383 LBC           0 :     elog(WARNING, "temporary file leak: File %d still referenced",
    1384                 :          file);
    1385 UIC           0 : }
    1386                 : 
    1387                 : /*
    1388                 :  * Make sure there is room for at least one more entry in a ResourceOwner's
    1389 ECB             :  * dynamic shmem segment reference array.
    1390                 :  *
    1391                 :  * This is separate from actually inserting an entry because if we run out
    1392 EUB             :  * of memory, it's critical to do so *before* acquiring the resource.
    1393                 :  */
    1394 ECB             : void
    1395 GIC       14798 : ResourceOwnerEnlargeDSMs(ResourceOwner owner)
    1396                 : {
    1397           14798 :     ResourceArrayEnlarge(&(owner->dsmarr));
    1398           14798 : }
    1399                 : 
    1400 EUB             : /*
    1401                 :  * Remember that a dynamic shmem segment is owned by a ResourceOwner
    1402                 :  *
    1403                 :  * Caller must have previously done ResourceOwnerEnlargeDSMs()
    1404                 :  */
    1405                 : void
    1406 GIC       14798 : ResourceOwnerRememberDSM(ResourceOwner owner, dsm_segment *seg)
    1407                 : {
    1408           14798 :     ResourceArrayAdd(&(owner->dsmarr), PointerGetDatum(seg));
    1409           14798 : }
    1410                 : 
    1411                 : /*
    1412                 :  * Forget that a dynamic shmem segment is owned by a ResourceOwner
    1413                 :  */
    1414                 : void
    1415 CBC       14798 : ResourceOwnerForgetDSM(ResourceOwner owner, dsm_segment *seg)
    1416                 : {
    1417           14798 :     if (!ResourceArrayRemove(&(owner->dsmarr), PointerGetDatum(seg)))
    1418 LBC           0 :         elog(ERROR, "dynamic shared memory segment %u is not owned by resource owner %s",
    1419                 :              dsm_segment_handle(seg), owner->name);
    1420 GIC       14798 : }
    1421                 : 
    1422                 : /*
    1423                 :  * Debugging subroutine
    1424                 :  */
    1425                 : static void
    1426 LBC           0 : PrintDSMLeakWarning(dsm_segment *seg)
    1427                 : {
    1428               0 :     elog(WARNING, "dynamic shared memory leak: segment %u still referenced",
    1429 ECB             :          dsm_segment_handle(seg));
    1430 UIC           0 : }
    1431                 : 
    1432                 : /*
    1433                 :  * Make sure there is room for at least one more entry in a ResourceOwner's
    1434                 :  * JIT context reference array.
    1435 ECB             :  *
    1436                 :  * This is separate from actually inserting an entry because if we run out of
    1437                 :  * memory, it's critical to do so *before* acquiring the resource.
    1438 EUB             :  */
    1439                 : void
    1440 CBC         839 : ResourceOwnerEnlargeJIT(ResourceOwner owner)
    1441                 : {
    1442 GIC         839 :     ResourceArrayEnlarge(&(owner->jitarr));
    1443             839 : }
    1444                 : 
    1445                 : /*
    1446 EUB             :  * Remember that a JIT context is owned by a ResourceOwner
    1447                 :  *
    1448                 :  * Caller must have previously done ResourceOwnerEnlargeJIT()
    1449                 :  */
    1450                 : void
    1451 GIC         839 : ResourceOwnerRememberJIT(ResourceOwner owner, Datum handle)
    1452                 : {
    1453             839 :     ResourceArrayAdd(&(owner->jitarr), handle);
    1454             839 : }
    1455                 : 
    1456                 : /*
    1457                 :  * Forget that a JIT context is owned by a ResourceOwner
    1458                 :  */
    1459                 : void
    1460 CBC         839 : ResourceOwnerForgetJIT(ResourceOwner owner, Datum handle)
    1461                 : {
    1462             839 :     if (!ResourceArrayRemove(&(owner->jitarr), handle))
    1463 LBC           0 :         elog(ERROR, "JIT context %p is not owned by resource owner %s",
    1464                 :              DatumGetPointer(handle), owner->name);
    1465 GIC         839 : }
    1466                 : 
    1467                 : /*
    1468                 :  * Make sure there is room for at least one more entry in a ResourceOwner's
    1469                 :  * cryptohash context reference array.
    1470                 :  *
    1471 ECB             :  * This is separate from actually inserting an entry because if we run out of
    1472                 :  * memory, it's critical to do so *before* acquiring the resource.
    1473                 :  */
    1474                 : void
    1475 GIC      499247 : ResourceOwnerEnlargeCryptoHash(ResourceOwner owner)
    1476                 : {
    1477          499247 :     ResourceArrayEnlarge(&(owner->cryptohasharr));
    1478          499247 : }
    1479                 : 
    1480 ECB             : /*
    1481                 :  * Remember that a cryptohash context is owned by a ResourceOwner
    1482                 :  *
    1483 EUB             :  * Caller must have previously done ResourceOwnerEnlargeCryptoHash()
    1484                 :  */
    1485 ECB             : void
    1486 GIC      499247 : ResourceOwnerRememberCryptoHash(ResourceOwner owner, Datum handle)
    1487                 : {
    1488          499247 :     ResourceArrayAdd(&(owner->cryptohasharr), handle);
    1489          499247 : }
    1490                 : 
    1491 EUB             : /*
    1492                 :  * Forget that a cryptohash context is owned by a ResourceOwner
    1493                 :  */
    1494                 : void
    1495 GBC      499242 : ResourceOwnerForgetCryptoHash(ResourceOwner owner, Datum handle)
    1496                 : {
    1497 GIC      499242 :     if (!ResourceArrayRemove(&(owner->cryptohasharr), handle))
    1498 UIC           0 :         elog(ERROR, "cryptohash context %p is not owned by resource owner %s",
    1499                 :              DatumGetPointer(handle), owner->name);
    1500 GIC      499242 : }
    1501                 : 
    1502                 : /*
    1503                 :  * Debugging subroutine
    1504                 :  */
    1505 ECB             : static void
    1506 UIC           0 : PrintCryptoHashLeakWarning(Datum handle)
    1507 ECB             : {
    1508 LBC           0 :     elog(WARNING, "cryptohash context reference leak: context %p still referenced",
    1509                 :          DatumGetPointer(handle));
    1510 UIC           0 : }
    1511                 : 
    1512                 : /*
    1513                 :  * Make sure there is room for at least one more entry in a ResourceOwner's
    1514                 :  * hmac context reference array.
    1515                 :  *
    1516 ECB             :  * This is separate from actually inserting an entry because if we run out of
    1517                 :  * memory, it's critical to do so *before* acquiring the resource.
    1518                 :  */
    1519                 : void
    1520 GIC         216 : ResourceOwnerEnlargeHMAC(ResourceOwner owner)
    1521                 : {
    1522             216 :     ResourceArrayEnlarge(&(owner->hmacarr));
    1523             216 : }
    1524                 : 
    1525 ECB             : /*
    1526                 :  * Remember that a HMAC context is owned by a ResourceOwner
    1527                 :  *
    1528 EUB             :  * Caller must have previously done ResourceOwnerEnlargeHMAC()
    1529                 :  */
    1530 ECB             : void
    1531 GIC         216 : ResourceOwnerRememberHMAC(ResourceOwner owner, Datum handle)
    1532                 : {
    1533             216 :     ResourceArrayAdd(&(owner->hmacarr), handle);
    1534             216 : }
    1535                 : 
    1536                 : /*
    1537                 :  * Forget that a HMAC context is owned by a ResourceOwner
    1538                 :  */
    1539                 : void
    1540 CBC         216 : ResourceOwnerForgetHMAC(ResourceOwner owner, Datum handle)
    1541                 : {
    1542             216 :     if (!ResourceArrayRemove(&(owner->hmacarr), handle))
    1543 LBC           0 :         elog(ERROR, "HMAC context %p is not owned by resource owner %s",
    1544                 :              DatumGetPointer(handle), owner->name);
    1545 GIC         216 : }
    1546                 : 
    1547                 : /*
    1548                 :  * Debugging subroutine
    1549                 :  */
    1550                 : static void
    1551 LBC           0 : PrintHMACLeakWarning(Datum handle)
    1552                 : {
    1553               0 :     elog(WARNING, "HMAC context reference leak: context %p still referenced",
    1554 ECB             :          DatumGetPointer(handle));
    1555 UIC           0 : }
        

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