aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/cache
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/cache')
-rw-r--r--src/backend/utils/cache/catcache.c125
-rw-r--r--src/backend/utils/cache/plancache.c50
-rw-r--r--src/backend/utils/cache/relcache.c64
3 files changed, 210 insertions, 29 deletions
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index 18db7e78e21..2e2e4d9f1f7 100644
--- a/src/backend/utils/cache/catcache.c
+++ b/src/backend/utils/cache/catcache.c
@@ -31,12 +31,13 @@
#endif
#include "storage/lmgr.h"
#include "utils/builtins.h"
+#include "utils/catcache.h"
#include "utils/datum.h"
#include "utils/fmgroids.h"
#include "utils/inval.h"
#include "utils/memutils.h"
#include "utils/rel.h"
-#include "utils/resowner_private.h"
+#include "utils/resowner.h"
#include "utils/syscache.h"
@@ -94,6 +95,8 @@ static CatCTup *CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp,
uint32 hashValue, Index hashIndex,
bool negative);
+static void ReleaseCatCacheWithOwner(HeapTuple tuple, ResourceOwner resowner);
+static void ReleaseCatCacheListWithOwner(CatCList *list, ResourceOwner resowner);
static void CatCacheFreeKeys(TupleDesc tupdesc, int nkeys, int *attnos,
Datum *keys);
static void CatCacheCopyKeys(TupleDesc tupdesc, int nkeys, int *attnos,
@@ -104,6 +107,56 @@ static void CatCacheCopyKeys(TupleDesc tupdesc, int nkeys, int *attnos,
* internal support functions
*/
+/* ResourceOwner callbacks to hold catcache references */
+
+static void ResOwnerReleaseCatCache(Datum res);
+static char *ResOwnerPrintCatCache(Datum res);
+static void ResOwnerReleaseCatCacheList(Datum res);
+static char *ResOwnerPrintCatCacheList(Datum res);
+
+static const ResourceOwnerDesc catcache_resowner_desc =
+{
+ /* catcache references */
+ .name = "catcache reference",
+ .release_phase = RESOURCE_RELEASE_AFTER_LOCKS,
+ .release_priority = RELEASE_PRIO_CATCACHE_REFS,
+ .ReleaseResource = ResOwnerReleaseCatCache,
+ .DebugPrint = ResOwnerPrintCatCache
+};
+
+static const ResourceOwnerDesc catlistref_resowner_desc =
+{
+ /* catcache-list pins */
+ .name = "catcache list reference",
+ .release_phase = RESOURCE_RELEASE_AFTER_LOCKS,
+ .release_priority = RELEASE_PRIO_CATCACHE_LIST_REFS,
+ .ReleaseResource = ResOwnerReleaseCatCacheList,
+ .DebugPrint = ResOwnerPrintCatCacheList
+};
+
+/* Convenience wrappers over ResourceOwnerRemember/Forget */
+static inline void
+ResourceOwnerRememberCatCacheRef(ResourceOwner owner, HeapTuple tuple)
+{
+ ResourceOwnerRemember(owner, PointerGetDatum(tuple), &catcache_resowner_desc);
+}
+static inline void
+ResourceOwnerForgetCatCacheRef(ResourceOwner owner, HeapTuple tuple)
+{
+ ResourceOwnerForget(owner, PointerGetDatum(tuple), &catcache_resowner_desc);
+}
+static inline void
+ResourceOwnerRememberCatCacheListRef(ResourceOwner owner, CatCList *list)
+{
+ ResourceOwnerRemember(owner, PointerGetDatum(list), &catlistref_resowner_desc);
+}
+static inline void
+ResourceOwnerForgetCatCacheListRef(ResourceOwner owner, CatCList *list)
+{
+ ResourceOwnerForget(owner, PointerGetDatum(list), &catlistref_resowner_desc);
+}
+
+
/*
* Hash and equality functions for system types that are used as cache key
* fields. In some cases, we just call the regular SQL-callable functions for
@@ -1268,7 +1321,7 @@ SearchCatCacheInternal(CatCache *cache,
*/
if (!ct->negative)
{
- ResourceOwnerEnlargeCatCacheRefs(CurrentResourceOwner);
+ ResourceOwnerEnlarge(CurrentResourceOwner);
ct->refcount++;
ResourceOwnerRememberCatCacheRef(CurrentResourceOwner, &ct->tuple);
@@ -1369,7 +1422,7 @@ SearchCatCacheMiss(CatCache *cache,
hashValue, hashIndex,
false);
/* immediately set the refcount to 1 */
- ResourceOwnerEnlargeCatCacheRefs(CurrentResourceOwner);
+ ResourceOwnerEnlarge(CurrentResourceOwner);
ct->refcount++;
ResourceOwnerRememberCatCacheRef(CurrentResourceOwner, &ct->tuple);
break; /* assume only one match */
@@ -1437,6 +1490,12 @@ SearchCatCacheMiss(CatCache *cache,
void
ReleaseCatCache(HeapTuple tuple)
{
+ ReleaseCatCacheWithOwner(tuple, CurrentResourceOwner);
+}
+
+static void
+ReleaseCatCacheWithOwner(HeapTuple tuple, ResourceOwner resowner)
+{
CatCTup *ct = (CatCTup *) (((char *) tuple) -
offsetof(CatCTup, tuple));
@@ -1445,7 +1504,8 @@ ReleaseCatCache(HeapTuple tuple)
Assert(ct->refcount > 0);
ct->refcount--;
- ResourceOwnerForgetCatCacheRef(CurrentResourceOwner, &ct->tuple);
+ if (resowner)
+ ResourceOwnerForgetCatCacheRef(CurrentResourceOwner, &ct->tuple);
if (
#ifndef CATCACHE_FORCE_RELEASE
@@ -1581,7 +1641,7 @@ SearchCatCacheList(CatCache *cache,
dlist_move_head(&cache->cc_lists, &cl->cache_elem);
/* Bump the list's refcount and return it */
- ResourceOwnerEnlargeCatCacheListRefs(CurrentResourceOwner);
+ ResourceOwnerEnlarge(CurrentResourceOwner);
cl->refcount++;
ResourceOwnerRememberCatCacheListRef(CurrentResourceOwner, cl);
@@ -1693,7 +1753,7 @@ SearchCatCacheList(CatCache *cache,
table_close(relation, AccessShareLock);
/* Make sure the resource owner has room to remember this entry. */
- ResourceOwnerEnlargeCatCacheListRefs(CurrentResourceOwner);
+ ResourceOwnerEnlarge(CurrentResourceOwner);
/* Now we can build the CatCList entry. */
oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
@@ -1779,11 +1839,18 @@ SearchCatCacheList(CatCache *cache,
void
ReleaseCatCacheList(CatCList *list)
{
+ ReleaseCatCacheListWithOwner(list, CurrentResourceOwner);
+}
+
+static void
+ReleaseCatCacheListWithOwner(CatCList *list, ResourceOwner resowner)
+{
/* Safety checks to ensure we were handed a cache entry */
Assert(list->cl_magic == CL_MAGIC);
Assert(list->refcount > 0);
list->refcount--;
- ResourceOwnerForgetCatCacheListRef(CurrentResourceOwner, list);
+ if (resowner)
+ ResourceOwnerForgetCatCacheListRef(CurrentResourceOwner, list);
if (
#ifndef CATCACHE_FORCE_RELEASE
@@ -2059,31 +2126,43 @@ PrepareToInvalidateCacheTuple(Relation relation,
}
}
+/* ResourceOwner callbacks */
-/*
- * Subroutines for warning about reference leaks. These are exported so
- * that resowner.c can call them.
- */
-void
-PrintCatCacheLeakWarning(HeapTuple tuple)
+static void
+ResOwnerReleaseCatCache(Datum res)
{
+ ReleaseCatCacheWithOwner((HeapTuple) DatumGetPointer(res), NULL);
+}
+
+static char *
+ResOwnerPrintCatCache(Datum res)
+{
+ HeapTuple tuple = (HeapTuple) DatumGetPointer(res);
CatCTup *ct = (CatCTup *) (((char *) tuple) -
offsetof(CatCTup, tuple));
/* Safety check to ensure we were handed a cache entry */
Assert(ct->ct_magic == CT_MAGIC);
- elog(WARNING, "cache reference leak: cache %s (%d), tuple %u/%u has count %d",
- ct->my_cache->cc_relname, ct->my_cache->id,
- ItemPointerGetBlockNumber(&(tuple->t_self)),
- ItemPointerGetOffsetNumber(&(tuple->t_self)),
- ct->refcount);
+ return psprintf("cache %s (%d), tuple %u/%u has count %d",
+ ct->my_cache->cc_relname, ct->my_cache->id,
+ ItemPointerGetBlockNumber(&(tuple->t_self)),
+ ItemPointerGetOffsetNumber(&(tuple->t_self)),
+ ct->refcount);
}
-void
-PrintCatCacheListLeakWarning(CatCList *list)
+static void
+ResOwnerReleaseCatCacheList(Datum res)
{
- elog(WARNING, "cache reference leak: cache %s (%d), list %p has count %d",
- list->my_cache->cc_relname, list->my_cache->id,
- list, list->refcount);
+ ReleaseCatCacheListWithOwner((CatCList *) DatumGetPointer(res), NULL);
+}
+
+static char *
+ResOwnerPrintCatCacheList(Datum res)
+{
+ CatCList *list = (CatCList *) DatumGetPointer(res);
+
+ return psprintf("cache %s (%d), list %p has count %d",
+ list->my_cache->cc_relname, list->my_cache->id,
+ list, list->refcount);
}
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c
index 7d4168f82f5..8f95520f2fb 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -69,7 +69,7 @@
#include "tcop/utility.h"
#include "utils/inval.h"
#include "utils/memutils.h"
-#include "utils/resowner_private.h"
+#include "utils/resowner.h"
#include "utils/rls.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
@@ -119,6 +119,31 @@ static void PlanCacheRelCallback(Datum arg, Oid relid);
static void PlanCacheObjectCallback(Datum arg, int cacheid, uint32 hashvalue);
static void PlanCacheSysCallback(Datum arg, int cacheid, uint32 hashvalue);
+/* ResourceOwner callbacks to track plancache references */
+static void ResOwnerReleaseCachedPlan(Datum res);
+
+static const ResourceOwnerDesc planref_resowner_desc =
+{
+ .name = "plancache reference",
+ .release_phase = RESOURCE_RELEASE_AFTER_LOCKS,
+ .release_priority = RELEASE_PRIO_PLANCACHE_REFS,
+ .ReleaseResource = ResOwnerReleaseCachedPlan,
+ .DebugPrint = NULL /* the default message is fine */
+};
+
+/* Convenience wrappers over ResourceOwnerRemember/Forget */
+static inline void
+ResourceOwnerRememberPlanCacheRef(ResourceOwner owner, CachedPlan *plan)
+{
+ ResourceOwnerRemember(owner, PointerGetDatum(plan), &planref_resowner_desc);
+}
+static inline void
+ResourceOwnerForgetPlanCacheRef(ResourceOwner owner, CachedPlan *plan)
+{
+ ResourceOwnerForget(owner, PointerGetDatum(plan), &planref_resowner_desc);
+}
+
+
/* GUC parameter */
int plan_cache_mode = PLAN_CACHE_MODE_AUTO;
@@ -1233,7 +1258,7 @@ GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams,
/* Flag the plan as in use by caller */
if (owner)
- ResourceOwnerEnlargePlanCacheRefs(owner);
+ ResourceOwnerEnlarge(owner);
plan->refcount++;
if (owner)
ResourceOwnerRememberPlanCacheRef(owner, plan);
@@ -1396,7 +1421,7 @@ CachedPlanAllowsSimpleValidityCheck(CachedPlanSource *plansource,
/* Bump refcount if requested. */
if (owner)
{
- ResourceOwnerEnlargePlanCacheRefs(owner);
+ ResourceOwnerEnlarge(owner);
plan->refcount++;
ResourceOwnerRememberPlanCacheRef(owner, plan);
}
@@ -1457,7 +1482,7 @@ CachedPlanIsSimplyValid(CachedPlanSource *plansource, CachedPlan *plan,
/* It's still good. Bump refcount if requested. */
if (owner)
{
- ResourceOwnerEnlargePlanCacheRefs(owner);
+ ResourceOwnerEnlarge(owner);
plan->refcount++;
ResourceOwnerRememberPlanCacheRef(owner, plan);
}
@@ -2203,3 +2228,20 @@ ResetPlanCache(void)
cexpr->is_valid = false;
}
}
+
+/*
+ * Release all CachedPlans remembered by 'owner'
+ */
+void
+ReleaseAllPlanCacheRefsInOwner(ResourceOwner owner)
+{
+ ResourceOwnerReleaseAllOfKind(owner, &planref_resowner_desc);
+}
+
+/* ResourceOwner callbacks */
+
+static void
+ResOwnerReleaseCachedPlan(Datum res)
+{
+ ReleaseCachedPlan((CachedPlan *) DatumGetPointer(res), NULL);
+}
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index a49ab465b36..b3faccbefe5 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -80,13 +80,14 @@
#include "storage/smgr.h"
#include "utils/array.h"
#include "utils/builtins.h"
+#include "utils/catcache.h"
#include "utils/datum.h"
#include "utils/fmgroids.h"
#include "utils/inval.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/relmapper.h"
-#include "utils/resowner_private.h"
+#include "utils/resowner.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
@@ -273,6 +274,7 @@ static HTAB *OpClassCache = NULL;
/* non-export function prototypes */
+static void RelationCloseCleanup(Relation relation);
static void RelationDestroyRelation(Relation relation, bool remember_tupdesc);
static void RelationClearRelation(Relation relation, bool rebuild);
@@ -2115,6 +2117,31 @@ RelationIdGetRelation(Oid relationId)
* ----------------------------------------------------------------
*/
+/* ResourceOwner callbacks to track relcache references */
+static void ResOwnerReleaseRelation(Datum res);
+static char *ResOwnerPrintRelCache(Datum res);
+
+static const ResourceOwnerDesc relref_resowner_desc =
+{
+ .name = "relcache reference",
+ .release_phase = RESOURCE_RELEASE_BEFORE_LOCKS,
+ .release_priority = RELEASE_PRIO_RELCACHE_REFS,
+ .ReleaseResource = ResOwnerReleaseRelation,
+ .DebugPrint = ResOwnerPrintRelCache
+};
+
+/* Convenience wrappers over ResourceOwnerRemember/Forget */
+static inline void
+ResourceOwnerRememberRelationRef(ResourceOwner owner, Relation rel)
+{
+ ResourceOwnerRemember(owner, PointerGetDatum(rel), &relref_resowner_desc);
+}
+static inline void
+ResourceOwnerForgetRelationRef(ResourceOwner owner, Relation rel)
+{
+ ResourceOwnerForget(owner, PointerGetDatum(rel), &relref_resowner_desc);
+}
+
/*
* RelationIncrementReferenceCount
* Increments relation reference count.
@@ -2126,7 +2153,7 @@ RelationIdGetRelation(Oid relationId)
void
RelationIncrementReferenceCount(Relation rel)
{
- ResourceOwnerEnlargeRelationRefs(CurrentResourceOwner);
+ ResourceOwnerEnlarge(CurrentResourceOwner);
rel->rd_refcnt += 1;
if (!IsBootstrapProcessingMode())
ResourceOwnerRememberRelationRef(CurrentResourceOwner, rel);
@@ -2162,6 +2189,12 @@ RelationClose(Relation relation)
/* Note: no locking manipulations needed */
RelationDecrementReferenceCount(relation);
+ RelationCloseCleanup(relation);
+}
+
+static void
+RelationCloseCleanup(Relation relation)
+{
/*
* If the relation is no longer open in this session, we can clean up any
* stale partition descriptors it has. This is unlikely, so check to see
@@ -6813,3 +6846,30 @@ unlink_initfile(const char *initfilename, int elevel)
initfilename)));
}
}
+
+/*
+ * ResourceOwner callbacks
+ */
+static char *
+ResOwnerPrintRelCache(Datum res)
+{
+ Relation rel = (Relation) DatumGetPointer(res);
+
+ return psprintf("relation \"%s\"", RelationGetRelationName(rel));
+}
+
+static void
+ResOwnerReleaseRelation(Datum res)
+{
+ Relation rel = (Relation) DatumGetPointer(res);
+
+ /*
+ * This reference has already been removed from the resource owner, so
+ * just decrement reference count without calling
+ * ResourceOwnerForgetRelationRef.
+ */
+ Assert(rel->rd_refcnt > 0);
+ rel->rd_refcnt -= 1;
+
+ RelationCloseCleanup((Relation) res);
+}