PostgreSQL Source Code git master
resowner.c File Reference
#include "postgres.h"
#include "common/hashfn.h"
#include "common/int.h"
#include "storage/ipc.h"
#include "storage/predicate.h"
#include "storage/proc.h"
#include "utils/memutils.h"
#include "utils/resowner.h"
Include dependency graph for resowner.c:

Go to the source code of this file.

Data Structures

struct  ResourceElem
 
struct  ResourceOwnerData
 
struct  ResourceReleaseCallbackItem
 

Macros

#define RESOWNER_ARRAY_SIZE   32
 
#define RESOWNER_HASH_INIT_SIZE   64
 
#define RESOWNER_HASH_MAX_ITEMS(capacity)    Min(capacity - RESOWNER_ARRAY_SIZE, (capacity)/4 * 3)
 
#define MAX_RESOWNER_LOCKS   15
 

Typedefs

typedef struct ResourceElem ResourceElem
 
typedef struct ResourceReleaseCallbackItem ResourceReleaseCallbackItem
 

Functions

 StaticAssertDecl (RESOWNER_HASH_MAX_ITEMS(RESOWNER_HASH_INIT_SIZE) >=RESOWNER_ARRAY_SIZE, "initial hash size too small compared to array size")
 
static uint32 hash_resource_elem (Datum value, const ResourceOwnerDesc *kind)
 
static void ResourceOwnerAddToHash (ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
 
static int resource_priority_cmp (const void *a, const void *b)
 
static void ResourceOwnerSort (ResourceOwner owner)
 
static void ResourceOwnerReleaseAll (ResourceOwner owner, ResourceReleasePhase phase, bool printLeakWarnings)
 
static void ResourceOwnerReleaseInternal (ResourceOwner owner, ResourceReleasePhase phase, bool isCommit, bool isTopLevel)
 
static void ReleaseAuxProcessResourcesCallback (int code, Datum arg)
 
ResourceOwner ResourceOwnerCreate (ResourceOwner parent, const char *name)
 
void ResourceOwnerEnlarge (ResourceOwner owner)
 
void ResourceOwnerRemember (ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
 
void ResourceOwnerForget (ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
 
void ResourceOwnerRelease (ResourceOwner owner, ResourceReleasePhase phase, bool isCommit, bool isTopLevel)
 
void ResourceOwnerReleaseAllOfKind (ResourceOwner owner, const ResourceOwnerDesc *kind)
 
void ResourceOwnerDelete (ResourceOwner owner)
 
ResourceOwner ResourceOwnerGetParent (ResourceOwner owner)
 
void ResourceOwnerNewParent (ResourceOwner owner, ResourceOwner newparent)
 
void RegisterResourceReleaseCallback (ResourceReleaseCallback callback, void *arg)
 
void UnregisterResourceReleaseCallback (ResourceReleaseCallback callback, void *arg)
 
void CreateAuxProcessResourceOwner (void)
 
void ReleaseAuxProcessResources (bool isCommit)
 
void ResourceOwnerRememberLock (ResourceOwner owner, LOCALLOCK *locallock)
 
void ResourceOwnerForgetLock (ResourceOwner owner, LOCALLOCK *locallock)
 

Variables

ResourceOwner CurrentResourceOwner = NULL
 
ResourceOwner CurTransactionResourceOwner = NULL
 
ResourceOwner TopTransactionResourceOwner = NULL
 
ResourceOwner AuxProcessResourceOwner = NULL
 
static ResourceReleaseCallbackItemResourceRelease_callbacks = NULL
 

Macro Definition Documentation

◆ MAX_RESOWNER_LOCKS

#define MAX_RESOWNER_LOCKS   15

Definition at line 105 of file resowner.c.

◆ RESOWNER_ARRAY_SIZE

#define RESOWNER_ARRAY_SIZE   32

Definition at line 71 of file resowner.c.

◆ RESOWNER_HASH_INIT_SIZE

#define RESOWNER_HASH_INIT_SIZE   64

Definition at line 77 of file resowner.c.

◆ RESOWNER_HASH_MAX_ITEMS

#define RESOWNER_HASH_MAX_ITEMS (   capacity)     Min(capacity - RESOWNER_ARRAY_SIZE, (capacity)/4 * 3)

Definition at line 89 of file resowner.c.

Typedef Documentation

◆ ResourceElem

typedef struct ResourceElem ResourceElem

◆ ResourceReleaseCallbackItem

Function Documentation

◆ CreateAuxProcessResourceOwner()

void CreateAuxProcessResourceOwner ( void  )

Definition at line 982 of file resowner.c.

983{
986 AuxProcessResourceOwner = ResourceOwnerCreate(NULL, "AuxiliaryProcess");
988
989 /*
990 * Register a shmem-exit callback for cleanup of aux-process resource
991 * owner. (This needs to run after, e.g., ShutdownXLOG.)
992 */
994}
#define Assert(condition)
Definition: c.h:815
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:365
static void ReleaseAuxProcessResourcesCallback(int code, Datum arg)
Definition: resowner.c:1027
ResourceOwner ResourceOwnerCreate(ResourceOwner parent, const char *name)
Definition: resowner.c:413
ResourceOwner CurrentResourceOwner
Definition: resowner.c:165
ResourceOwner AuxProcessResourceOwner
Definition: resowner.c:168

References Assert, AuxProcessResourceOwner, CurrentResourceOwner, on_shmem_exit(), ReleaseAuxProcessResourcesCallback(), and ResourceOwnerCreate().

Referenced by AuxiliaryProcessMainCommon(), and InitPostgres().

◆ hash_resource_elem()

static uint32 hash_resource_elem ( Datum  value,
const ResourceOwnerDesc kind 
)
inlinestatic

Definition at line 214 of file resowner.c.

215{
216 /*
217 * Most resource kinds store a pointer in 'value', and pointers are unique
218 * all on their own. But some resources store plain integers (Files and
219 * Buffers as of this writing), so we want to incorporate the 'kind' in
220 * the hash too, otherwise those resources will collide a lot. But
221 * because there are only a few resource kinds like that - and only a few
222 * resource kinds to begin with - we don't need to work too hard to mix
223 * 'kind' into the hash. Just add it with hash_combine(), it perturbs the
224 * result enough for our purposes.
225 */
226#if SIZEOF_DATUM == 8
227 return hash_combine64(murmurhash64((uint64) value), (uint64) kind);
228#else
229 return hash_combine(murmurhash32((uint32) value), (uint32) kind);
230#endif
231}
uint64_t uint64
Definition: c.h:489
uint32_t uint32
Definition: c.h:488
static uint64 hash_combine64(uint64 a, uint64 b)
Definition: hashfn.h:80
static uint64 murmurhash64(uint64 data)
Definition: hashfn.h:106
static uint32 hash_combine(uint32 a, uint32 b)
Definition: hashfn.h:68
static uint32 murmurhash32(uint32 data)
Definition: hashfn.h:92
static struct @162 value

References hash_combine(), hash_combine64(), murmurhash32(), murmurhash64(), and value.

Referenced by ResourceOwnerAddToHash(), and ResourceOwnerForget().

◆ RegisterResourceReleaseCallback()

void RegisterResourceReleaseCallback ( ResourceReleaseCallback  callback,
void *  arg 
)

Definition at line 944 of file resowner.c.

945{
947
951 item->callback = callback;
952 item->arg = arg;
955}
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1181
MemoryContext TopMemoryContext
Definition: mcxt.c:149
void * arg
static ResourceReleaseCallbackItem * ResourceRelease_callbacks
Definition: resowner.c:187
struct ResourceReleaseCallbackItem * next
Definition: resowner.c:182
ResourceReleaseCallback callback
Definition: resowner.c:183
static void callback(struct sockaddr *addr, struct sockaddr *mask, void *unused)
Definition: test_ifaddrs.c:46

References ResourceReleaseCallbackItem::arg, arg, ResourceReleaseCallbackItem::callback, callback(), MemoryContextAlloc(), ResourceReleaseCallbackItem::next, ResourceRelease_callbacks, and TopMemoryContext.

◆ ReleaseAuxProcessResources()

void ReleaseAuxProcessResources ( bool  isCommit)

Definition at line 1002 of file resowner.c.

1003{
1004 /*
1005 * At this writing, the only thing that could actually get released is
1006 * buffer pins; but we may as well do the full release protocol.
1007 */
1010 isCommit, true);
1013 isCommit, true);
1016 isCommit, true);
1017 /* allow it to be reused */
1020}
void ResourceOwnerRelease(ResourceOwner owner, ResourceReleasePhase phase, bool isCommit, bool isTopLevel)
Definition: resowner.c:648
@ RESOURCE_RELEASE_LOCKS
Definition: resowner.h:55
@ RESOURCE_RELEASE_BEFORE_LOCKS
Definition: resowner.h:54
@ RESOURCE_RELEASE_AFTER_LOCKS
Definition: resowner.h:56

References AuxProcessResourceOwner, ResourceOwnerData::releasing, RESOURCE_RELEASE_AFTER_LOCKS, RESOURCE_RELEASE_BEFORE_LOCKS, RESOURCE_RELEASE_LOCKS, ResourceOwnerRelease(), and ResourceOwnerData::sorted.

Referenced by BackgroundWriterMain(), CheckpointerMain(), InitPostgres(), perform_base_backup(), pgarch_archiveXlog(), ReleaseAuxProcessResourcesCallback(), UploadManifest(), WalSndErrorCleanup(), WalSummarizerMain(), and WalWriterMain().

◆ ReleaseAuxProcessResourcesCallback()

static void ReleaseAuxProcessResourcesCallback ( int  code,
Datum  arg 
)
static

Definition at line 1027 of file resowner.c.

1028{
1029 bool isCommit = (code == 0);
1030
1032}
void ReleaseAuxProcessResources(bool isCommit)
Definition: resowner.c:1002

References ReleaseAuxProcessResources().

Referenced by CreateAuxProcessResourceOwner().

◆ resource_priority_cmp()

static int resource_priority_cmp ( const void *  a,
const void *  b 
)
static

Definition at line 261 of file resowner.c.

262{
263 const ResourceElem *ra = (const ResourceElem *) a;
264 const ResourceElem *rb = (const ResourceElem *) b;
265
266 /* Note: reverse order */
267 if (ra->kind->release_phase == rb->kind->release_phase)
269 else if (ra->kind->release_phase > rb->kind->release_phase)
270 return -1;
271 else
272 return 1;
273}
static int pg_cmp_u32(uint32 a, uint32 b)
Definition: int.h:652
int b
Definition: isn.c:69
int a
Definition: isn.c:68
const ResourceOwnerDesc * kind
Definition: resowner.c:65
ResourceReleasePhase release_phase
Definition: resowner.h:96
ResourceReleasePriority release_priority
Definition: resowner.h:97

References a, b, ResourceElem::kind, pg_cmp_u32(), ResourceOwnerDesc::release_phase, and ResourceOwnerDesc::release_priority.

Referenced by ResourceOwnerSort().

◆ ResourceOwnerAddToHash()

static void ResourceOwnerAddToHash ( ResourceOwner  owner,
Datum  value,
const ResourceOwnerDesc kind 
)
static

Definition at line 237 of file resowner.c.

238{
239 uint32 mask = owner->capacity - 1;
240 uint32 idx;
241
242 Assert(kind != NULL);
243
244 /* Insert into first free slot at or after hash location. */
245 idx = hash_resource_elem(value, kind) & mask;
246 for (;;)
247 {
248 if (owner->hash[idx].kind == NULL)
249 break; /* found a free slot */
250 idx = (idx + 1) & mask;
251 }
252 owner->hash[idx].item = value;
253 owner->hash[idx].kind = kind;
254 owner->nhash++;
255}
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:259
static uint32 hash_resource_elem(Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:214
Datum item
Definition: resowner.c:64
ResourceElem * hash
Definition: resowner.c:152

References Assert, ResourceOwnerData::capacity, ResourceOwnerData::hash, hash_resource_elem(), idx(), ResourceElem::item, ResourceElem::kind, ResourceOwnerData::nhash, and value.

Referenced by ResourceOwnerEnlarge().

◆ ResourceOwnerCreate()

ResourceOwner ResourceOwnerCreate ( ResourceOwner  parent,
const char *  name 
)

Definition at line 413 of file resowner.c.

414{
415 ResourceOwner owner;
416
418 sizeof(struct ResourceOwnerData));
419 owner->name = name;
420
421 if (parent)
422 {
423 owner->parent = parent;
424 owner->nextchild = parent->firstchild;
425 parent->firstchild = owner;
426 }
427
428 return owner;
429}
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1215
struct ResourceOwnerData * ResourceOwner
Definition: resowner.h:27
ResourceOwner parent
Definition: resowner.c:112
const char * name
Definition: resowner.c:115
ResourceOwner nextchild
Definition: resowner.c:114
ResourceOwner firstchild
Definition: resowner.c:113
const char * name

References ResourceOwnerData::firstchild, MemoryContextAllocZero(), name, ResourceOwnerData::name, ResourceOwnerData::nextchild, ResourceOwnerData::parent, and TopMemoryContext.

Referenced by AtStart_ResourceOwner(), AtSubStart_ResourceOwner(), CreateAuxProcessResourceOwner(), CreatePortal(), plpgsql_call_handler(), plpgsql_create_econtext(), plpgsql_inline_handler(), test_dsa_resowners(), test_resowner_forget_between_phases(), test_resowner_leak(), test_resowner_many(), test_resowner_priorities(), and test_resowner_remember_between_phases().

◆ ResourceOwnerDelete()

void ResourceOwnerDelete ( ResourceOwner  owner)

Definition at line 854 of file resowner.c.

855{
856 /* We had better not be deleting CurrentResourceOwner ... */
858
859 /* And it better not own any resources, either */
860 Assert(owner->narr == 0);
861 Assert(owner->nhash == 0);
862 Assert(owner->nlocks == 0 || owner->nlocks == MAX_RESOWNER_LOCKS + 1);
863
864 /*
865 * Delete children. The recursive call will delink the child from me, so
866 * just iterate as long as there is a child.
867 */
868 while (owner->firstchild != NULL)
870
871 /*
872 * We delink the owner from its parent before deleting it, so that if
873 * there's an error we won't have deleted/busted owners still attached to
874 * the owner tree. Better a leak than a crash.
875 */
876 ResourceOwnerNewParent(owner, NULL);
877
878 /* And free the object. */
879 if (owner->hash)
880 pfree(owner->hash);
881 pfree(owner);
882}
void pfree(void *pointer)
Definition: mcxt.c:1521
void ResourceOwnerNewParent(ResourceOwner owner, ResourceOwner newparent)
Definition: resowner.c:897
#define MAX_RESOWNER_LOCKS
Definition: resowner.c:105
void ResourceOwnerDelete(ResourceOwner owner)
Definition: resowner.c:854

References Assert, CurrentResourceOwner, ResourceOwnerData::firstchild, ResourceOwnerData::hash, MAX_RESOWNER_LOCKS, ResourceOwnerData::narr, ResourceOwnerData::nhash, ResourceOwnerData::nlocks, pfree(), ResourceOwnerDelete(), and ResourceOwnerNewParent().

Referenced by CleanupSubTransaction(), CleanupTransaction(), CommitSubTransaction(), CommitTransaction(), plpgsql_call_handler(), plpgsql_inline_handler(), PortalDrop(), PrepareTransaction(), ResourceOwnerDelete(), test_dsa_resowners(), test_resowner_leak(), test_resowner_many(), and test_resowner_priorities().

◆ ResourceOwnerEnlarge()

void ResourceOwnerEnlarge ( ResourceOwner  owner)

Definition at line 442 of file resowner.c.

443{
444 /*
445 * Mustn't try to remember more resources after we have already started
446 * releasing
447 */
448 if (owner->releasing)
449 elog(ERROR, "ResourceOwnerEnlarge called after release started");
450
451 if (owner->narr < RESOWNER_ARRAY_SIZE)
452 return; /* no work needed */
453
454 /*
455 * Is there space in the hash? If not, enlarge it.
456 */
457 if (owner->narr + owner->nhash >= owner->grow_at)
458 {
459 uint32 i,
460 oldcap,
461 newcap;
462 ResourceElem *oldhash;
463 ResourceElem *newhash;
464
465 oldhash = owner->hash;
466 oldcap = owner->capacity;
467
468 /* Double the capacity (it must stay a power of 2!) */
469 newcap = (oldcap > 0) ? oldcap * 2 : RESOWNER_HASH_INIT_SIZE;
471 newcap * sizeof(ResourceElem));
472
473 /*
474 * We assume we can't fail below this point, so OK to scribble on the
475 * owner
476 */
477 owner->hash = newhash;
478 owner->capacity = newcap;
479 owner->grow_at = RESOWNER_HASH_MAX_ITEMS(newcap);
480 owner->nhash = 0;
481
482 if (oldhash != NULL)
483 {
484 /*
485 * Transfer any pre-existing entries into the new hash table; they
486 * don't necessarily go where they were before, so this simple
487 * logic is the best way.
488 */
489 for (i = 0; i < oldcap; i++)
490 {
491 if (oldhash[i].kind != NULL)
492 ResourceOwnerAddToHash(owner, oldhash[i].item, oldhash[i].kind);
493 }
494
495 /* And release old hash table. */
496 pfree(oldhash);
497 }
498 }
499
500 /* Move items from the array to the hash */
501 for (int i = 0; i < owner->narr; i++)
502 ResourceOwnerAddToHash(owner, owner->arr[i].item, owner->arr[i].kind);
503 owner->narr = 0;
504
505 Assert(owner->nhash <= owner->grow_at);
506}
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
int i
Definition: isn.c:72
#define RESOWNER_HASH_INIT_SIZE
Definition: resowner.c:77
#define RESOWNER_HASH_MAX_ITEMS(capacity)
Definition: resowner.c:89
static void ResourceOwnerAddToHash(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:237
#define RESOWNER_ARRAY_SIZE
Definition: resowner.c:71
ResourceElem arr[RESOWNER_ARRAY_SIZE]
Definition: resowner.c:140

References ResourceOwnerData::arr, Assert, ResourceOwnerData::capacity, elog, ERROR, ResourceOwnerData::grow_at, ResourceOwnerData::hash, i, ResourceElem::item, ResourceElem::kind, MemoryContextAllocZero(), ResourceOwnerData::narr, ResourceOwnerData::nhash, pfree(), ResourceOwnerData::releasing, ResourceOwnerAddToHash(), RESOWNER_ARRAY_SIZE, RESOWNER_HASH_INIT_SIZE, RESOWNER_HASH_MAX_ITEMS, and TopMemoryContext.

Referenced by BufferAlloc(), CachedPlanAllowsSimpleValidityCheck(), CachedPlanIsSimplyValid(), CreateWaitEventSet(), dsm_create_descriptor(), dsm_unpin_mapping(), EvictUnpinnedBuffer(), ExtendBufferedRelLocal(), ExtendBufferedRelShared(), FlushDatabaseBuffers(), FlushRelationBuffers(), FlushRelationsAllBuffers(), GetCachedPlan(), GetLocalVictimBuffer(), GetVictimBuffer(), IncrBufferRefCount(), IncrTupleDescRefCount(), llvm_create_context(), LocalBufferAlloc(), OpenTemporaryFile(), PathNameCreateTemporaryFile(), PathNameOpenTemporaryFile(), pg_cryptohash_create(), pg_hmac_create(), px_find_cipher(), px_find_digest(), ReadRecentBuffer(), RegisterSnapshotOnOwner(), RelationIncrementReferenceCount(), RememberManyTestResources(), SearchCatCacheInternal(), SearchCatCacheList(), SearchCatCacheMiss(), StartBufferIO(), SyncOneBuffer(), test_resowner_forget_between_phases(), test_resowner_leak(), test_resowner_priorities(), and test_resowner_remember_between_phases().

◆ ResourceOwnerForget()

void ResourceOwnerForget ( ResourceOwner  owner,
Datum  value,
const ResourceOwnerDesc kind 
)

Definition at line 554 of file resowner.c.

555{
556 /*
557 * Mustn't call this after we have already started releasing resources.
558 * (Release callback functions are not allowed to release additional
559 * resources.)
560 */
561 if (owner->releasing)
562 elog(ERROR, "ResourceOwnerForget called for %s after release started", kind->name);
563 Assert(!owner->sorted);
564
565 /* Search through all items in the array first. */
566 for (int i = owner->narr - 1; i >= 0; i--)
567 {
568 if (owner->arr[i].item == value &&
569 owner->arr[i].kind == kind)
570 {
571 owner->arr[i] = owner->arr[owner->narr - 1];
572 owner->narr--;
573
574#ifdef RESOWNER_STATS
575 narray_lookups++;
576#endif
577 return;
578 }
579 }
580
581 /* Search hash */
582 if (owner->nhash > 0)
583 {
584 uint32 mask = owner->capacity - 1;
585 uint32 idx;
586
587 idx = hash_resource_elem(value, kind) & mask;
588 for (uint32 i = 0; i < owner->capacity; i++)
589 {
590 if (owner->hash[idx].item == value &&
591 owner->hash[idx].kind == kind)
592 {
593 owner->hash[idx].item = (Datum) 0;
594 owner->hash[idx].kind = NULL;
595 owner->nhash--;
596
597#ifdef RESOWNER_STATS
598 nhash_lookups++;
599#endif
600 return;
601 }
602 idx = (idx + 1) & mask;
603 }
604 }
605
606 /*
607 * Use %p to print the reference, since most objects tracked by a resource
608 * owner are pointers. It's a bit misleading if it's not a pointer, but
609 * this is a programmer error, anyway.
610 */
611 elog(ERROR, "%s %p is not owned by resource owner %s",
612 kind->name, DatumGetPointer(value), owner->name);
613}
uintptr_t Datum
Definition: postgres.h:69
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:317
const char * name
Definition: resowner.h:93

References ResourceOwnerData::arr, Assert, ResourceOwnerData::capacity, DatumGetPointer(), elog, ERROR, ResourceOwnerData::hash, hash_resource_elem(), i, idx(), ResourceElem::item, ResourceElem::kind, ResourceOwnerData::name, ResourceOwnerDesc::name, ResourceOwnerData::narr, ResourceOwnerData::nhash, ResourceOwnerData::releasing, ResourceOwnerData::sorted, and value.

Referenced by ForgetManyTestResources(), ResourceOwnerForgetBuffer(), ResourceOwnerForgetBufferIO(), ResourceOwnerForgetCatCacheListRef(), ResourceOwnerForgetCatCacheRef(), ResourceOwnerForgetCryptoHash(), ResourceOwnerForgetDSM(), ResourceOwnerForgetFile(), ResourceOwnerForgetHMAC(), ResourceOwnerForgetJIT(), ResourceOwnerForgetOSSLCipher(), ResourceOwnerForgetOSSLDigest(), ResourceOwnerForgetPlanCacheRef(), ResourceOwnerForgetRelationRef(), ResourceOwnerForgetSnapshot(), ResourceOwnerForgetTupleDesc(), ResourceOwnerForgetWaitEventSet(), and test_resowner_forget_between_phases().

◆ ResourceOwnerForgetLock()

void ResourceOwnerForgetLock ( ResourceOwner  owner,
LOCALLOCK locallock 
)

Definition at line 1065 of file resowner.c.

1066{
1067 int i;
1068
1069 if (owner->nlocks > MAX_RESOWNER_LOCKS)
1070 return; /* we have overflowed */
1071
1072 Assert(owner->nlocks > 0);
1073 for (i = owner->nlocks - 1; i >= 0; i--)
1074 {
1075 if (locallock == owner->locks[i])
1076 {
1077 owner->locks[i] = owner->locks[owner->nlocks - 1];
1078 owner->nlocks--;
1079 return;
1080 }
1081 }
1082 elog(ERROR, "lock reference %p is not owned by resource owner %s",
1083 locallock, owner->name);
1084}
LOCALLOCK * locks[MAX_RESOWNER_LOCKS]
Definition: resowner.c:157

References Assert, elog, ERROR, i, ResourceOwnerData::locks, MAX_RESOWNER_LOCKS, ResourceOwnerData::name, and ResourceOwnerData::nlocks.

Referenced by LockReassignOwner(), LockRelease(), LockReleaseAll(), ReleaseLockIfHeld(), and RemoveLocalLock().

◆ ResourceOwnerGetParent()

ResourceOwner ResourceOwnerGetParent ( ResourceOwner  owner)

Definition at line 888 of file resowner.c.

889{
890 return owner->parent;
891}

References ResourceOwnerData::parent.

Referenced by LockReassignCurrentOwner().

◆ ResourceOwnerNewParent()

void ResourceOwnerNewParent ( ResourceOwner  owner,
ResourceOwner  newparent 
)

Definition at line 897 of file resowner.c.

899{
900 ResourceOwner oldparent = owner->parent;
901
902 if (oldparent)
903 {
904 if (owner == oldparent->firstchild)
905 oldparent->firstchild = owner->nextchild;
906 else
907 {
908 ResourceOwner child;
909
910 for (child = oldparent->firstchild; child; child = child->nextchild)
911 {
912 if (owner == child->nextchild)
913 {
914 child->nextchild = owner->nextchild;
915 break;
916 }
917 }
918 }
919 }
920
921 if (newparent)
922 {
923 Assert(owner != newparent);
924 owner->parent = newparent;
925 owner->nextchild = newparent->firstchild;
926 newparent->firstchild = owner;
927 }
928 else
929 {
930 owner->parent = NULL;
931 owner->nextchild = NULL;
932 }
933}

References Assert, ResourceOwnerData::firstchild, ResourceOwnerData::nextchild, and ResourceOwnerData::parent.

Referenced by AtSubAbort_Portals(), AtSubCommit_Portals(), and ResourceOwnerDelete().

◆ ResourceOwnerRelease()

void ResourceOwnerRelease ( ResourceOwner  owner,
ResourceReleasePhase  phase,
bool  isCommit,
bool  isTopLevel 
)

Definition at line 648 of file resowner.c.

652{
653 /* There's not currently any setup needed before recursing */
654 ResourceOwnerReleaseInternal(owner, phase, isCommit, isTopLevel);
655
656#ifdef RESOWNER_STATS
657 if (isTopLevel)
658 {
659 elog(LOG, "RESOWNER STATS: lookups: array %d, hash %d",
660 narray_lookups, nhash_lookups);
661 narray_lookups = 0;
662 nhash_lookups = 0;
663 }
664#endif
665}
#define LOG
Definition: elog.h:31
static void ResourceOwnerReleaseInternal(ResourceOwner owner, ResourceReleasePhase phase, bool isCommit, bool isTopLevel)
Definition: resowner.c:668

References elog, LOG, and ResourceOwnerReleaseInternal().

Referenced by AbortSubTransaction(), AbortTransaction(), CommitSubTransaction(), CommitTransaction(), PortalDrop(), PrepareTransaction(), ReleaseAuxProcessResources(), test_dsa_resowners(), test_resowner_forget_between_phases(), test_resowner_leak(), test_resowner_many(), test_resowner_priorities(), and test_resowner_remember_between_phases().

◆ ResourceOwnerReleaseAll()

static void ResourceOwnerReleaseAll ( ResourceOwner  owner,
ResourceReleasePhase  phase,
bool  printLeakWarnings 
)
static

Definition at line 340 of file resowner.c.

342{
345
346 /*
347 * ResourceOwnerSort must've been called already. All the resources are
348 * either in the array or the hash.
349 */
350 Assert(owner->releasing);
351 Assert(owner->sorted);
352 if (owner->nhash == 0)
353 {
354 items = owner->arr;
355 nitems = owner->narr;
356 }
357 else
358 {
359 Assert(owner->narr == 0);
360 items = owner->hash;
361 nitems = owner->nhash;
362 }
363
364 /*
365 * The resources are sorted in reverse priority order. Release them
366 * starting from the end, until we hit the end of the phase that we are
367 * releasing now. We will continue from there when called again for the
368 * next phase.
369 */
370 while (nitems > 0)
371 {
372 uint32 idx = nitems - 1;
373 Datum value = items[idx].item;
374 const ResourceOwnerDesc *kind = items[idx].kind;
375
376 if (kind->release_phase > phase)
377 break;
378 Assert(kind->release_phase == phase);
379
380 if (printLeakWarnings)
381 {
382 char *res_str;
383
384 res_str = kind->DebugPrint ?
385 kind->DebugPrint(value)
386 : psprintf("%s %p", kind->name, DatumGetPointer(value));
387 elog(WARNING, "resource was not closed: %s", res_str);
388 pfree(res_str);
389 }
390 kind->ReleaseResource(value);
391 nitems--;
392 }
393 if (owner->nhash == 0)
394 owner->narr = nitems;
395 else
396 owner->nhash = nitems;
397}
#define WARNING
Definition: elog.h:36
#define nitems(x)
Definition: indent.h:31
char * psprintf(const char *fmt,...)
Definition: psprintf.c:43
char *(* DebugPrint)(Datum res)
Definition: resowner.h:118
void(* ReleaseResource)(Datum res)
Definition: resowner.h:108
static ItemArray items
Definition: test_tidstore.c:48

References ResourceOwnerData::arr, Assert, DatumGetPointer(), ResourceOwnerDesc::DebugPrint, elog, ResourceOwnerData::hash, idx(), items, ResourceOwnerDesc::name, ResourceOwnerData::narr, ResourceOwnerData::nhash, nitems, pfree(), psprintf(), ResourceOwnerDesc::release_phase, ResourceOwnerDesc::ReleaseResource, ResourceOwnerData::releasing, ResourceOwnerData::sorted, value, and WARNING.

Referenced by ResourceOwnerReleaseInternal().

◆ ResourceOwnerReleaseAllOfKind()

void ResourceOwnerReleaseAllOfKind ( ResourceOwner  owner,
const ResourceOwnerDesc kind 
)

Definition at line 801 of file resowner.c.

802{
803 /* Mustn't call this after we have already started releasing resources. */
804 if (owner->releasing)
805 elog(ERROR, "ResourceOwnerForget called for %s after release started", kind->name);
806 Assert(!owner->sorted);
807
808 /*
809 * Temporarily set 'releasing', to prevent calls to ResourceOwnerRemember
810 * while we're scanning the owner. Enlarging the hash would cause us to
811 * lose track of the point we're scanning.
812 */
813 owner->releasing = true;
814
815 /* Array first */
816 for (int i = 0; i < owner->narr; i++)
817 {
818 if (owner->arr[i].kind == kind)
819 {
820 Datum value = owner->arr[i].item;
821
822 owner->arr[i] = owner->arr[owner->narr - 1];
823 owner->narr--;
824 i--;
825
826 kind->ReleaseResource(value);
827 }
828 }
829
830 /* Then hash */
831 for (int i = 0; i < owner->capacity; i++)
832 {
833 if (owner->hash[i].kind == kind)
834 {
835 Datum value = owner->hash[i].item;
836
837 owner->hash[i].item = (Datum) 0;
838 owner->hash[i].kind = NULL;
839 owner->nhash--;
840
841 kind->ReleaseResource(value);
842 }
843 }
844 owner->releasing = false;
845}

References ResourceOwnerData::arr, Assert, ResourceOwnerData::capacity, elog, ERROR, ResourceOwnerData::hash, i, ResourceElem::item, ResourceElem::kind, ResourceOwnerDesc::name, ResourceOwnerData::narr, ResourceOwnerData::nhash, ResourceOwnerDesc::ReleaseResource, ResourceOwnerData::releasing, ResourceOwnerData::sorted, and value.

Referenced by ReleaseAllPlanCacheRefsInOwner().

◆ ResourceOwnerReleaseInternal()

static void ResourceOwnerReleaseInternal ( ResourceOwner  owner,
ResourceReleasePhase  phase,
bool  isCommit,
bool  isTopLevel 
)
static

Definition at line 668 of file resowner.c.

672{
673 ResourceOwner child;
674 ResourceOwner save;
677
678 /* Recurse to handle descendants */
679 for (child = owner->firstchild; child != NULL; child = child->nextchild)
680 ResourceOwnerReleaseInternal(child, phase, isCommit, isTopLevel);
681
682 /*
683 * To release the resources in the right order, sort them by phase and
684 * priority.
685 *
686 * The ReleaseResource callback functions are not allowed to remember or
687 * forget any other resources after this. Otherwise we lose track of where
688 * we are in processing the hash/array.
689 */
690 if (!owner->releasing)
691 {
693 Assert(!owner->sorted);
694 owner->releasing = true;
695 }
696 else
697 {
698 /*
699 * Phase is normally > RESOURCE_RELEASE_BEFORE_LOCKS, if this is not
700 * the first call to ResourceOwnerRelease. But if an error happens
701 * between the release phases, we might get called again for the same
702 * ResourceOwner from AbortTransaction.
703 */
704 }
705 if (!owner->sorted)
706 {
707 ResourceOwnerSort(owner);
708 owner->sorted = true;
709 }
710
711 /*
712 * Make CurrentResourceOwner point to me, so that the release callback
713 * functions know which resource owner is been released.
714 */
716 CurrentResourceOwner = owner;
717
719 {
720 /*
721 * Release all resources that need to be released before the locks.
722 *
723 * During a commit, there shouldn't be any remaining resources ---
724 * that would indicate failure to clean up the executor correctly ---
725 * so issue warnings. In the abort case, just clean up quietly.
726 */
727 ResourceOwnerReleaseAll(owner, phase, isCommit);
728 }
729 else if (phase == RESOURCE_RELEASE_LOCKS)
730 {
731 if (isTopLevel)
732 {
733 /*
734 * For a top-level xact we are going to release all locks (or at
735 * least all non-session locks), so just do a single lmgr call at
736 * the top of the recursion.
737 */
738 if (owner == TopTransactionResourceOwner)
739 {
740 ProcReleaseLocks(isCommit);
741 ReleasePredicateLocks(isCommit, false);
742 }
743 }
744 else
745 {
746 /*
747 * Release locks retail. Note that if we are committing a
748 * subtransaction, we do NOT release its locks yet, but transfer
749 * them to the parent.
750 */
751 LOCALLOCK **locks;
752 int nlocks;
753
754 Assert(owner->parent != NULL);
755
756 /*
757 * Pass the list of locks owned by this resource owner to the lock
758 * manager, unless it has overflowed.
759 */
760 if (owner->nlocks > MAX_RESOWNER_LOCKS)
761 {
762 locks = NULL;
763 nlocks = 0;
764 }
765 else
766 {
767 locks = owner->locks;
768 nlocks = owner->nlocks;
769 }
770
771 if (isCommit)
772 LockReassignCurrentOwner(locks, nlocks);
773 else
774 LockReleaseCurrentOwner(locks, nlocks);
775 }
776 }
777 else if (phase == RESOURCE_RELEASE_AFTER_LOCKS)
778 {
779 /*
780 * Release all resources that need to be released after the locks.
781 */
782 ResourceOwnerReleaseAll(owner, phase, isCommit);
783 }
784
785 /* Let add-on modules get a chance too */
786 for (item = ResourceRelease_callbacks; item; item = next)
787 {
788 /* allow callbacks to unregister themselves when called */
789 next = item->next;
790 item->callback(phase, isCommit, isTopLevel, item->arg);
791 }
792
794}
static int32 next
Definition: blutils.c:221
void LockReassignCurrentOwner(LOCALLOCK **locallocks, int nlocks)
Definition: lock.c:2615
void LockReleaseCurrentOwner(LOCALLOCK **locallocks, int nlocks)
Definition: lock.c:2520
void ReleasePredicateLocks(bool isCommit, bool isReadOnlySafe)
Definition: predicate.c:3302
ResourceOwner TopTransactionResourceOwner
Definition: resowner.c:167
static void ResourceOwnerReleaseAll(ResourceOwner owner, ResourceReleasePhase phase, bool printLeakWarnings)
Definition: resowner.c:340
static void ResourceOwnerSort(ResourceOwner owner)
Definition: resowner.c:284
void ProcReleaseLocks(bool isCommit)
Definition: proc.c:840

References ResourceReleaseCallbackItem::arg, Assert, ResourceReleaseCallbackItem::callback, CurrentResourceOwner, ResourceOwnerData::firstchild, LockReassignCurrentOwner(), LockReleaseCurrentOwner(), ResourceOwnerData::locks, MAX_RESOWNER_LOCKS, next, ResourceReleaseCallbackItem::next, ResourceOwnerData::nextchild, ResourceOwnerData::nlocks, ResourceOwnerData::parent, ProcReleaseLocks(), ReleasePredicateLocks(), ResourceOwnerData::releasing, RESOURCE_RELEASE_AFTER_LOCKS, RESOURCE_RELEASE_BEFORE_LOCKS, RESOURCE_RELEASE_LOCKS, ResourceOwnerReleaseAll(), ResourceOwnerReleaseInternal(), ResourceOwnerSort(), ResourceRelease_callbacks, ResourceOwnerData::sorted, and TopTransactionResourceOwner.

Referenced by ResourceOwnerRelease(), and ResourceOwnerReleaseInternal().

◆ ResourceOwnerRemember()

void ResourceOwnerRemember ( ResourceOwner  owner,
Datum  value,
const ResourceOwnerDesc kind 
)

Definition at line 514 of file resowner.c.

515{
516 uint32 idx;
517
518 /* sanity check the ResourceOwnerDesc */
519 Assert(kind->release_phase != 0);
520 Assert(kind->release_priority != 0);
521
522 /*
523 * Mustn't try to remember more resources after we have already started
524 * releasing. We already checked this in ResourceOwnerEnlarge.
525 */
526 Assert(!owner->releasing);
527 Assert(!owner->sorted);
528
529 if (owner->narr >= RESOWNER_ARRAY_SIZE)
530 {
531 /* forgot to call ResourceOwnerEnlarge? */
532 elog(ERROR, "ResourceOwnerRemember called but array was full");
533 }
534
535 /* Append to the array. */
536 idx = owner->narr;
537 owner->arr[idx].item = value;
538 owner->arr[idx].kind = kind;
539 owner->narr++;
540}

References ResourceOwnerData::arr, Assert, elog, ERROR, idx(), ResourceElem::item, ResourceElem::kind, ResourceOwnerData::narr, ResourceOwnerDesc::release_phase, ResourceOwnerDesc::release_priority, ResourceOwnerData::releasing, RESOWNER_ARRAY_SIZE, ResourceOwnerData::sorted, and value.

Referenced by RememberManyTestResources(), ResourceOwnerRememberBuffer(), ResourceOwnerRememberBufferIO(), ResourceOwnerRememberCatCacheListRef(), ResourceOwnerRememberCatCacheRef(), ResourceOwnerRememberCryptoHash(), ResourceOwnerRememberDSM(), ResourceOwnerRememberFile(), ResourceOwnerRememberHMAC(), ResourceOwnerRememberJIT(), ResourceOwnerRememberOSSLCipher(), ResourceOwnerRememberOSSLDigest(), ResourceOwnerRememberPlanCacheRef(), ResourceOwnerRememberRelationRef(), ResourceOwnerRememberSnapshot(), ResourceOwnerRememberTupleDesc(), ResourceOwnerRememberWaitEventSet(), test_resowner_forget_between_phases(), test_resowner_leak(), test_resowner_priorities(), and test_resowner_remember_between_phases().

◆ ResourceOwnerRememberLock()

void ResourceOwnerRememberLock ( ResourceOwner  owner,
LOCALLOCK locallock 
)

Definition at line 1045 of file resowner.c.

1046{
1047 Assert(locallock != NULL);
1048
1049 if (owner->nlocks > MAX_RESOWNER_LOCKS)
1050 return; /* we have already overflowed */
1051
1052 if (owner->nlocks < MAX_RESOWNER_LOCKS)
1053 owner->locks[owner->nlocks] = locallock;
1054 else
1055 {
1056 /* overflowed */
1057 }
1058 owner->nlocks++;
1059}

References Assert, ResourceOwnerData::locks, MAX_RESOWNER_LOCKS, and ResourceOwnerData::nlocks.

Referenced by GrantLockLocal(), and LockReassignOwner().

◆ ResourceOwnerSort()

static void ResourceOwnerSort ( ResourceOwner  owner)
static

Definition at line 284 of file resowner.c.

285{
288
289 if (owner->nhash == 0)
290 {
291 items = owner->arr;
292 nitems = owner->narr;
293 }
294 else
295 {
296 /*
297 * Compact the hash table, so that all the elements are in the
298 * beginning of the 'hash' array, with no empty elements.
299 */
300 uint32 dst = 0;
301
302 for (int idx = 0; idx < owner->capacity; idx++)
303 {
304 if (owner->hash[idx].kind != NULL)
305 {
306 if (dst != idx)
307 owner->hash[dst] = owner->hash[idx];
308 dst++;
309 }
310 }
311
312 /*
313 * Move all entries from the fixed-size array to 'hash'.
314 *
315 * RESOWNER_HASH_MAX_ITEMS is defined so that there is always enough
316 * free space to move all the elements from the fixed-size array to
317 * the hash.
318 */
319 Assert(dst + owner->narr <= owner->capacity);
320 for (int idx = 0; idx < owner->narr; idx++)
321 {
322 owner->hash[dst] = owner->arr[idx];
323 dst++;
324 }
325 Assert(dst == owner->nhash + owner->narr);
326 owner->narr = 0;
327 owner->nhash = dst;
328
329 items = owner->hash;
330 nitems = owner->nhash;
331 }
332
334}
#define qsort(a, b, c, d)
Definition: port.h:475
static int resource_priority_cmp(const void *a, const void *b)
Definition: resowner.c:261

References ResourceOwnerData::arr, Assert, ResourceOwnerData::capacity, ResourceOwnerData::hash, idx(), items, ResourceElem::kind, ResourceOwnerData::narr, ResourceOwnerData::nhash, nitems, qsort, and resource_priority_cmp().

Referenced by ResourceOwnerReleaseInternal().

◆ StaticAssertDecl()

StaticAssertDecl ( RESOWNER_HASH_MAX_ITEMS(RESOWNER_HASH_INIT_SIZE) >=  RESOWNER_ARRAY_SIZE,
"initial hash size too small compared to array size  
)

◆ UnregisterResourceReleaseCallback()

void UnregisterResourceReleaseCallback ( ResourceReleaseCallback  callback,
void *  arg 
)

Definition at line 958 of file resowner.c.

959{
962
963 prev = NULL;
964 for (item = ResourceRelease_callbacks; item; prev = item, item = item->next)
965 {
966 if (item->callback == callback && item->arg == arg)
967 {
968 if (prev)
969 prev->next = item->next;
970 else
972 pfree(item);
973 break;
974 }
975 }
976}

References ResourceReleaseCallbackItem::arg, arg, ResourceReleaseCallbackItem::callback, callback(), ResourceReleaseCallbackItem::next, pfree(), and ResourceRelease_callbacks.

Variable Documentation

◆ AuxProcessResourceOwner

◆ CurrentResourceOwner

ResourceOwner CurrentResourceOwner = NULL

Definition at line 165 of file resowner.c.

Referenced by _SPI_execute_plan(), apply_spooled_messages(), AssignTransactionId(), AtAbort_ResourceOwner(), AtStart_ResourceOwner(), AtSubAbort_ResourceOwner(), AtSubStart_ResourceOwner(), attach_internal(), BufferAlloc(), CleanupSubTransaction(), CleanupTransaction(), close_lo_relation(), CommitSubTransaction(), CommitTransaction(), create_internal(), CreateAuxProcessResourceOwner(), DecrTupleDescRefCount(), dsm_create_descriptor(), dsm_unpin_mapping(), EvictUnpinnedBuffer(), exec_eval_simple_expr(), exec_init_tuple_store(), exec_simple_check_plan(), exec_stmt_block(), ExecAppendAsyncEventWait(), ExplainExecuteQuery(), ExtendBufferedRelLocal(), ExtendBufferedRelShared(), extendBufFile(), FlushDatabaseBuffers(), FlushRelationBuffers(), FlushRelationsAllBuffers(), get_segment_by_index(), GetCurrentFDWTuplestore(), GetLocalVictimBuffer(), GetVictimBuffer(), IncrBufferRefCount(), IncrTupleDescRefCount(), InitPostgres(), llvm_create_context(), LocalBufferAlloc(), lock_and_open_sequence(), LockAcquireExtended(), LockReassignCurrentOwner(), LockReassignOwner(), LockRelease(), LogicalSlotAdvanceAndCheckSnapState(), make_callstmt_target(), make_new_segment(), makeBufFileCommon(), MakeTransitionCaptureState(), open_lo_relation(), OpenTemporaryFile(), PathNameCreateTemporaryFile(), PathNameOpenTemporaryFile(), perform_base_backup(), PersistHoldablePortal(), pg_cryptohash_create(), pg_hmac_create(), pg_logical_slot_get_changes_guts(), PinBuffer(), PinBuffer_Locked(), PinLocalBuffer(), plperl_spi_exec(), plperl_spi_exec_prepared(), plperl_spi_fetchrow(), plperl_spi_prepare(), plperl_spi_query(), plperl_spi_query_prepared(), plpgsql_estate_setup(), pltcl_func_handler(), pltcl_init_tuple_store(), pltcl_returnnext(), pltcl_SPI_execute(), pltcl_SPI_execute_plan(), pltcl_SPI_prepare(), pltcl_subtrans_abort(), pltcl_subtrans_commit(), pltcl_subtransaction(), PLy_abort_open_subtransactions(), PLy_cursor_fetch(), PLy_cursor_iternext(), PLy_cursor_plan(), PLy_cursor_query(), PLy_spi_execute_plan(), PLy_spi_execute_query(), PLy_spi_prepare(), PLy_spi_subtransaction_abort(), PLy_spi_subtransaction_commit(), PLy_subtransaction_enter(), PLy_subtransaction_exit(), PopTransaction(), PortalCleanup(), PortalRun(), PortalRunFetch(), PortalStart(), PrepareTransaction(), px_find_cipher(), px_find_digest(), ReadRecentBuffer(), RegisterSnapshot(), RegisterTemporaryFile(), RelationDecrementReferenceCount(), RelationIncrementReferenceCount(), ReleaseCatCache(), ReleaseCatCacheList(), ReleaseCatCacheListWithOwner(), ReleaseCatCacheWithOwner(), ReleaseLockIfHeld(), ResourceOwnerDelete(), ResourceOwnerReleaseInternal(), SearchCatCacheInternal(), SearchCatCacheList(), SearchCatCacheMiss(), ShutdownXLOG(), SnapBuildClearExportedSnapshot(), SnapBuildExportSnapshot(), SPI_plan_get_cached_plan(), StartBufferIO(), StartupXLOG(), SyncOneBuffer(), TerminateBufferIO(), test_dsa_resowners(), test_resowner_forget_between_phases(), test_resowner_leak(), test_resowner_many(), test_resowner_priorities(), test_resowner_remember_between_phases(), tuplestore_begin_common(), tuplestore_puttuple_common(), UnpinBuffer(), UnpinLocalBuffer(), UnregisterSnapshot(), UploadManifest(), and WaitLatchOrSocket().

◆ CurTransactionResourceOwner

◆ ResourceRelease_callbacks

ResourceReleaseCallbackItem* ResourceRelease_callbacks = NULL
static

◆ TopTransactionResourceOwner