PostgreSQL Source Code  git master
catcache.h File Reference
#include "access/htup.h"
#include "access/skey.h"
#include "lib/ilist.h"
#include "utils/relcache.h"
Include dependency graph for catcache.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  catcache
 
struct  catctup
 
struct  catclist
 
struct  catcacheheader
 

Macros

#define CATCACHE_MAXKEYS   4
 
#define CT_MAGIC   0x57261502
 
#define CL_MAGIC   0x52765103
 

Typedefs

typedef uint32(* CCHashFN) (Datum datum)
 
typedef bool(* CCFastEqualFN) (Datum a, Datum b)
 
typedef struct catcache CatCache
 
typedef struct catctup CatCTup
 
typedef struct catclist CatCList
 
typedef struct catcacheheader CatCacheHeader
 

Functions

void CreateCacheMemoryContext (void)
 
CatCacheInitCatCache (int id, Oid reloid, Oid indexoid, int nkeys, const int *key, int nbuckets)
 
void InitCatCachePhase2 (CatCache *cache, bool touch_index)
 
HeapTuple SearchCatCache (CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
 
HeapTuple SearchCatCache1 (CatCache *cache, Datum v1)
 
HeapTuple SearchCatCache2 (CatCache *cache, Datum v1, Datum v2)
 
HeapTuple SearchCatCache3 (CatCache *cache, Datum v1, Datum v2, Datum v3)
 
HeapTuple SearchCatCache4 (CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
 
void ReleaseCatCache (HeapTuple tuple)
 
uint32 GetCatCacheHashValue (CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
 
CatCListSearchCatCacheList (CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
 
void ReleaseCatCacheList (CatCList *list)
 
void ResetCatalogCaches (void)
 
void CatalogCacheFlushCatalog (Oid catId)
 
void CatCacheInvalidate (CatCache *cache, uint32 hashValue)
 
void PrepareToInvalidateCacheTuple (Relation relation, HeapTuple tuple, HeapTuple newtuple, void(*function)(int, uint32, Oid))
 
void PrintCatCacheLeakWarning (HeapTuple tuple)
 
void PrintCatCacheListLeakWarning (CatCList *list)
 

Variables

PGDLLIMPORT MemoryContext CacheMemoryContext
 

Macro Definition Documentation

◆ CATCACHE_MAXKEYS

#define CATCACHE_MAXKEYS   4

Definition at line 35 of file catcache.h.

Referenced by SearchCatCacheInternal(), SearchCatCacheList(), and SearchCatCacheMiss().

◆ CL_MAGIC

#define CL_MAGIC   0x52765103

Definition at line 160 of file catcache.h.

Referenced by ReleaseCatCacheList(), and SearchCatCacheList().

◆ CT_MAGIC

#define CT_MAGIC   0x57261502

Definition at line 89 of file catcache.h.

Referenced by CatalogCacheCreateEntry(), PrintCatCacheLeakWarning(), and ReleaseCatCache().

Typedef Documentation

◆ CatCache

◆ CatCacheHeader

◆ CatCList

◆ CatCTup

◆ CCFastEqualFN

typedef bool(* CCFastEqualFN) (Datum a, Datum b)

Definition at line 42 of file catcache.h.

◆ CCHashFN

typedef uint32(* CCHashFN) (Datum datum)

Definition at line 39 of file catcache.h.

Function Documentation

◆ CatalogCacheFlushCatalog()

void CatalogCacheFlushCatalog ( Oid  catId)

Definition at line 735 of file catcache.c.

References CACHE1_elog, CACHE2_elog, CallSyscacheCallbacks(), catcache::cc_reloid, catcacheheader::ch_caches, slist_iter::cur, DEBUG2, catcache::id, ResetCatalogCache(), slist_container, and slist_foreach.

Referenced by LocalExecuteInvalidationMessage().

736 {
737  slist_iter iter;
738 
739  CACHE2_elog(DEBUG2, "CatalogCacheFlushCatalog called for %u", catId);
740 
742  {
743  CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
744 
745  /* Does this cache store tuples of the target catalog? */
746  if (cache->cc_reloid == catId)
747  {
748  /* Yes, so flush all its contents */
749  ResetCatalogCache(cache);
750 
751  /* Tell inval.c to call syscache callbacks for this cache */
752  CallSyscacheCallbacks(cache->id, 0);
753  }
754  }
755 
756  CACHE1_elog(DEBUG2, "end of CatalogCacheFlushCatalog call");
757 }
static void ResetCatalogCache(CatCache *cache)
Definition: catcache.c:658
static CatCacheHeader * CacheHdr
Definition: catcache.c:75
slist_node * cur
Definition: ilist.h:226
int id
Definition: catcache.h:46
Oid cc_reloid
Definition: catcache.h:58
#define DEBUG2
Definition: elog.h:24
#define slist_container(type, membername, ptr)
Definition: ilist.h:674
void CallSyscacheCallbacks(int cacheid, uint32 hashvalue)
Definition: inval.c:1450
#define CACHE1_elog(a, b)
Definition: catcache.c:66
slist_head ch_caches
Definition: catcache.h:184
#define slist_foreach(iter, lhead)
Definition: ilist.h:700
#define CACHE2_elog(a, b, c)
Definition: catcache.c:67

◆ CatCacheInvalidate()

void CatCacheInvalidate ( CatCache cache,
uint32  hashValue 
)

Definition at line 568 of file catcache.c.

References Assert, catctup::c_list, CACHE1_elog, CatCacheRemoveCList(), CatCacheRemoveCTup(), catcache::cc_bucket, catcache::cc_lists, catcache::cc_nbuckets, dlist_mutable_iter::cur, catctup::dead, catclist::dead, DEBUG2, dlist_container, dlist_foreach_modify, HASH_INDEX, catctup::hash_value, catctup::refcount, and catclist::refcount.

Referenced by SysCacheInvalidate().

569 {
570  Index hashIndex;
571  dlist_mutable_iter iter;
572 
573  CACHE1_elog(DEBUG2, "CatCacheInvalidate: called");
574 
575  /*
576  * We don't bother to check whether the cache has finished initialization
577  * yet; if not, there will be no entries in it so no problem.
578  */
579 
580  /*
581  * Invalidate *all* CatCLists in this cache; it's too hard to tell which
582  * searches might still be correct, so just zap 'em all.
583  */
584  dlist_foreach_modify(iter, &cache->cc_lists)
585  {
586  CatCList *cl = dlist_container(CatCList, cache_elem, iter.cur);
587 
588  if (cl->refcount > 0)
589  cl->dead = true;
590  else
591  CatCacheRemoveCList(cache, cl);
592  }
593 
594  /*
595  * inspect the proper hash bucket for tuple matches
596  */
597  hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
598  dlist_foreach_modify(iter, &cache->cc_bucket[hashIndex])
599  {
600  CatCTup *ct = dlist_container(CatCTup, cache_elem, iter.cur);
601 
602  if (hashValue == ct->hash_value)
603  {
604  if (ct->refcount > 0 ||
605  (ct->c_list && ct->c_list->refcount > 0))
606  {
607  ct->dead = true;
608  /* list, if any, was marked dead above */
609  Assert(ct->c_list == NULL || ct->c_list->dead);
610  }
611  else
612  CatCacheRemoveCTup(cache, ct);
613  CACHE1_elog(DEBUG2, "CatCacheInvalidate: invalidated");
614 #ifdef CATCACHE_STATS
615  cache->cc_invals++;
616 #endif
617  /* could be multiple matches, so keep looking! */
618  }
619  }
620 }
dlist_node * cur
Definition: ilist.h:180
uint32 hash_value
Definition: catcache.h:91
#define dlist_foreach_modify(iter, lhead)
Definition: ilist.h:524
#define HASH_INDEX(h, sz)
Definition: catcache.c:51
dlist_head * cc_bucket
Definition: catcache.h:49
bool dead
Definition: catcache.h:173
dlist_head cc_lists
Definition: catcache.h:54
struct catclist * c_list
Definition: catcache.h:130
#define dlist_container(type, membername, ptr)
Definition: ilist.h:477
#define DEBUG2
Definition: elog.h:24
static void CatCacheRemoveCList(CatCache *cache, CatCList *cl)
Definition: catcache.c:515
static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
Definition: catcache.c:473
unsigned int Index
Definition: c.h:413
#define CACHE1_elog(a, b)
Definition: catcache.c:66
#define Assert(condition)
Definition: c.h:670
int cc_nbuckets
Definition: catcache.h:47
int refcount
Definition: catcache.h:118
int refcount
Definition: catcache.h:172
bool dead
Definition: catcache.h:119

◆ CreateCacheMemoryContext()

void CreateCacheMemoryContext ( void  )

Definition at line 636 of file catcache.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), CacheMemoryContext, and TopMemoryContext.

Referenced by assign_record_type_typmod(), BuildEventTriggerCache(), init_ts_config_cache(), InitCatCache(), InitializeAttoptCache(), InitializeRelfilenodeMap(), InitializeTableSpaceCache(), lookup_ts_dictionary_cache(), lookup_ts_parser_cache(), lookup_type_cache(), LookupOpclassInfo(), RelationBuildLocalRelation(), and RelationCacheInitialize().

637 {
638  /*
639  * Purely for paranoia, check that context doesn't exist; caller probably
640  * did so already.
641  */
642  if (!CacheMemoryContext)
644  "CacheMemoryContext",
646 }
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:170
MemoryContext TopMemoryContext
Definition: mcxt.c:43
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
MemoryContext CacheMemoryContext
Definition: mcxt.c:46

◆ GetCatCacheHashValue()

uint32 GetCatCacheHashValue ( CatCache cache,
Datum  v1,
Datum  v2,
Datum  v3,
Datum  v4 
)

Definition at line 1490 of file catcache.c.

References CatalogCacheComputeHashValue(), CatalogCacheInitializeCache(), catcache::cc_nkeys, and catcache::cc_tupdesc.

Referenced by GetSysCacheHashValue().

1495 {
1496  /*
1497  * one-time startup overhead for each cache
1498  */
1499  if (cache->cc_tupdesc == NULL)
1501 
1502  /*
1503  * calculate the hash value
1504  */
1505  return CatalogCacheComputeHashValue(cache, cache->cc_nkeys, v1, v2, v3, v4);
1506 }
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:939
int cc_nkeys
Definition: catcache.h:56
TupleDesc cc_tupdesc
Definition: catcache.h:48
static uint32 CatalogCacheComputeHashValue(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:276

◆ InitCatCache()

CatCache* InitCatCache ( int  id,
Oid  reloid,
Oid  indexoid,
int  nkeys,
const int *  key,
int  nbuckets 
)

Definition at line 779 of file catcache.c.

References Assert, CACHELINEALIGN, CacheMemoryContext, catcache::cc_bucket, catcache::cc_indexoid, catcache::cc_keyno, catcache::cc_nbuckets, catcache::cc_next, catcache::cc_nkeys, catcache::cc_ntup, catcache::cc_relisshared, catcache::cc_relname, catcache::cc_reloid, catcache::cc_tupdesc, catcacheheader::ch_caches, catcacheheader::ch_ntup, CreateCacheMemoryContext(), i, catcache::id, InitCatCache_DEBUG2, MemoryContextSwitchTo(), on_proc_exit(), palloc(), palloc0(), PG_CACHE_LINE_SIZE, slist_init(), and slist_push_head().

Referenced by InitCatalogCache().

785 {
786  CatCache *cp;
787  MemoryContext oldcxt;
788  size_t sz;
789  int i;
790 
791  /*
792  * nbuckets is the initial number of hash buckets to use in this catcache.
793  * It will be enlarged later if it becomes too full.
794  *
795  * nbuckets must be a power of two. We check this via Assert rather than
796  * a full runtime check because the values will be coming from constant
797  * tables.
798  *
799  * If you're confused by the power-of-two check, see comments in
800  * bitmapset.c for an explanation.
801  */
802  Assert(nbuckets > 0 && (nbuckets & -nbuckets) == nbuckets);
803 
804  /*
805  * first switch to the cache context so our allocations do not vanish at
806  * the end of a transaction
807  */
808  if (!CacheMemoryContext)
810 
812 
813  /*
814  * if first time through, initialize the cache group header
815  */
816  if (CacheHdr == NULL)
817  {
820  CacheHdr->ch_ntup = 0;
821 #ifdef CATCACHE_STATS
822  /* set up to dump stats at backend exit */
823  on_proc_exit(CatCachePrintStats, 0);
824 #endif
825  }
826 
827  /*
828  * Allocate a new cache structure, aligning to a cacheline boundary
829  *
830  * Note: we rely on zeroing to initialize all the dlist headers correctly
831  */
832  sz = sizeof(CatCache) + PG_CACHE_LINE_SIZE;
833  cp = (CatCache *) CACHELINEALIGN(palloc0(sz));
834  cp->cc_bucket = palloc0(nbuckets * sizeof(dlist_head));
835 
836  /*
837  * initialize the cache's relation information for the relation
838  * corresponding to this cache, and initialize some of the new cache's
839  * other internal fields. But don't open the relation yet.
840  */
841  cp->id = id;
842  cp->cc_relname = "(not known yet)";
843  cp->cc_reloid = reloid;
844  cp->cc_indexoid = indexoid;
845  cp->cc_relisshared = false; /* temporary */
846  cp->cc_tupdesc = (TupleDesc) NULL;
847  cp->cc_ntup = 0;
848  cp->cc_nbuckets = nbuckets;
849  cp->cc_nkeys = nkeys;
850  for (i = 0; i < nkeys; ++i)
851  cp->cc_keyno[i] = key[i];
852 
853  /*
854  * new cache is initialized as far as we can go for now. print some
855  * debugging information, if appropriate.
856  */
858 
859  /*
860  * add completed cache to top of group header's list
861  */
863 
864  /*
865  * back to the old context before we return...
866  */
867  MemoryContextSwitchTo(oldcxt);
868 
869  return cp;
870 }
#define PG_CACHE_LINE_SIZE
int cc_keyno[CATCACHE_MAXKEYS]
Definition: catcache.h:53
static CatCacheHeader * CacheHdr
Definition: catcache.c:75
void on_proc_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:292
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
dlist_head * cc_bucket
Definition: catcache.h:49
static void slist_push_head(slist_head *head, slist_node *node)
Definition: ilist.h:574
slist_node cc_next
Definition: catcache.h:61
int id
Definition: catcache.h:46
struct catcache CatCache
bool cc_relisshared
Definition: catcache.h:60
Oid cc_indexoid
Definition: catcache.h:59
static void slist_init(slist_head *head)
Definition: ilist.h:554
Oid cc_reloid
Definition: catcache.h:58
int cc_nkeys
Definition: catcache.h:56
TupleDesc cc_tupdesc
Definition: catcache.h:48
int cc_ntup
Definition: catcache.h:55
void * palloc0(Size size)
Definition: mcxt.c:877
struct tupleDesc * TupleDesc
slist_head ch_caches
Definition: catcache.h:184
#define InitCatCache_DEBUG2
Definition: catcache.c:775
#define Assert(condition)
Definition: c.h:670
int cc_nbuckets
Definition: catcache.h:47
#define CACHELINEALIGN(LEN)
Definition: c.h:626
void CreateCacheMemoryContext(void)
Definition: catcache.c:636
const char * cc_relname
Definition: catcache.h:57
void * palloc(Size size)
Definition: mcxt.c:848
int i
MemoryContext CacheMemoryContext
Definition: mcxt.c:46

◆ InitCatCachePhase2()

void InitCatCachePhase2 ( CatCache cache,
bool  touch_index 
)

Definition at line 1050 of file catcache.c.

References AccessShareLock, AMNAME, AMOID, Assert, CatalogCacheInitializeCache(), catcache::cc_indexoid, catcache::cc_reloid, catcache::cc_tupdesc, catcache::id, index_close(), index_open(), LockRelationOid(), RelationData::rd_index, and UnlockRelationOid().

Referenced by InitCatalogCachePhase2(), and SysCacheGetAttr().

1051 {
1052  if (cache->cc_tupdesc == NULL)
1054 
1055  if (touch_index &&
1056  cache->id != AMOID &&
1057  cache->id != AMNAME)
1058  {
1059  Relation idesc;
1060 
1061  /*
1062  * We must lock the underlying catalog before opening the index to
1063  * avoid deadlock, since index_open could possibly result in reading
1064  * this same catalog, and if anyone else is exclusive-locking this
1065  * catalog and index they'll be doing it in that order.
1066  */
1068  idesc = index_open(cache->cc_indexoid, AccessShareLock);
1069 
1070  /*
1071  * While we've got the index open, let's check that it's unique (and
1072  * not just deferrable-unique, thank you very much). This is just to
1073  * catch thinkos in definitions of new catcaches, so we don't worry
1074  * about the pg_am indexes not getting tested.
1075  */
1076  Assert(idesc->rd_index->indisunique &&
1077  idesc->rd_index->indimmediate);
1078 
1079  index_close(idesc, AccessShareLock);
1081  }
1082 }
Definition: syscache.h:36
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:182
#define AccessShareLock
Definition: lockdefs.h:36
int id
Definition: catcache.h:46
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:939
Oid cc_indexoid
Definition: catcache.h:59
Form_pg_index rd_index
Definition: rel.h:159
Oid cc_reloid
Definition: catcache.h:58
TupleDesc cc_tupdesc
Definition: catcache.h:48
#define Assert(condition)
Definition: c.h:670
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:176
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:105
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:151

◆ PrepareToInvalidateCacheTuple()

void PrepareToInvalidateCacheTuple ( Relation  relation,
HeapTuple  tuple,
HeapTuple  newtuple,
void(*)(int, uint32, Oid function 
)

Definition at line 2030 of file catcache.c.

References Assert, CACHE1_elog, CatalogCacheComputeTupleHashValue(), CatalogCacheInitializeCache(), catcache::cc_nkeys, catcache::cc_relisshared, catcache::cc_reloid, catcache::cc_tupdesc, catcacheheader::ch_caches, slist_iter::cur, DEBUG2, HeapTupleIsValid, catcache::id, MyDatabaseId, PointerIsValid, RelationGetRelid, RelationIsValid, slist_container, and slist_foreach.

Referenced by CacheInvalidateHeapTuple().

2034 {
2035  slist_iter iter;
2036  Oid reloid;
2037 
2038  CACHE1_elog(DEBUG2, "PrepareToInvalidateCacheTuple: called");
2039 
2040  /*
2041  * sanity checks
2042  */
2043  Assert(RelationIsValid(relation));
2044  Assert(HeapTupleIsValid(tuple));
2045  Assert(PointerIsValid(function));
2046  Assert(CacheHdr != NULL);
2047 
2048  reloid = RelationGetRelid(relation);
2049 
2050  /* ----------------
2051  * for each cache
2052  * if the cache contains tuples from the specified relation
2053  * compute the tuple's hash value(s) in this cache,
2054  * and call the passed function to register the information.
2055  * ----------------
2056  */
2057 
2059  {
2060  CatCache *ccp = slist_container(CatCache, cc_next, iter.cur);
2061  uint32 hashvalue;
2062  Oid dbid;
2063 
2064  if (ccp->cc_reloid != reloid)
2065  continue;
2066 
2067  /* Just in case cache hasn't finished initialization yet... */
2068  if (ccp->cc_tupdesc == NULL)
2070 
2071  hashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, tuple);
2072  dbid = ccp->cc_relisshared ? (Oid) 0 : MyDatabaseId;
2073 
2074  (*function) (ccp->id, hashvalue, dbid);
2075 
2076  if (newtuple)
2077  {
2078  uint32 newhashvalue;
2079 
2080  newhashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, newtuple);
2081 
2082  if (newhashvalue != hashvalue)
2083  (*function) (ccp->id, newhashvalue, dbid);
2084  }
2085  }
2086 }
static CatCacheHeader * CacheHdr
Definition: catcache.c:75
slist_node * cur
Definition: ilist.h:226
int id
Definition: catcache.h:46
unsigned int Oid
Definition: postgres_ext.h:31
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:939
bool cc_relisshared
Definition: catcache.h:60
static uint32 CatalogCacheComputeTupleHashValue(CatCache *cache, int nkeys, HeapTuple tuple)
Definition: catcache.c:327
Oid cc_reloid
Definition: catcache.h:58
int cc_nkeys
Definition: catcache.h:56
#define RelationIsValid(relation)
Definition: rel.h:398
TupleDesc cc_tupdesc
Definition: catcache.h:48
#define DEBUG2
Definition: elog.h:24
unsigned int uint32
Definition: c.h:296
#define slist_container(type, membername, ptr)
Definition: ilist.h:674
Oid MyDatabaseId
Definition: globals.c:77
#define CACHE1_elog(a, b)
Definition: catcache.c:66
slist_head ch_caches
Definition: catcache.h:184
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:670
#define slist_foreach(iter, lhead)
Definition: ilist.h:700
#define PointerIsValid(pointer)
Definition: c.h:564
#define RelationGetRelid(relation)
Definition: rel.h:425

◆ PrintCatCacheLeakWarning()

void PrintCatCacheLeakWarning ( HeapTuple  tuple)

Definition at line 2094 of file catcache.c.

References Assert, catcache::cc_relname, catctup::ct_magic, CT_MAGIC, elog, catcache::id, ItemPointerGetBlockNumber, ItemPointerGetOffsetNumber, catctup::my_cache, offsetof, catctup::refcount, and WARNING.

Referenced by ResourceOwnerReleaseInternal().

2095 {
2096  CatCTup *ct = (CatCTup *) (((char *) tuple) -
2097  offsetof(CatCTup, tuple));
2098 
2099  /* Safety check to ensure we were handed a cache entry */
2100  Assert(ct->ct_magic == CT_MAGIC);
2101 
2102  elog(WARNING, "cache reference leak: cache %s (%d), tuple %u/%u has count %d",
2103  ct->my_cache->cc_relname, ct->my_cache->id,
2104  ItemPointerGetBlockNumber(&(tuple->t_self)),
2105  ItemPointerGetOffsetNumber(&(tuple->t_self)),
2106  ct->refcount);
2107 }
CatCache * my_cache
Definition: catcache.h:132
#define CT_MAGIC
Definition: catcache.h:89
int id
Definition: catcache.h:46
#define WARNING
Definition: elog.h:40
#define Assert(condition)
Definition: c.h:670
int refcount
Definition: catcache.h:118
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:95
const char * cc_relname
Definition: catcache.h:57
#define elog
Definition: elog.h:219
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:76
#define offsetof(type, field)
Definition: c.h:593
int ct_magic
Definition: catcache.h:88

◆ PrintCatCacheListLeakWarning()

void PrintCatCacheListLeakWarning ( CatCList list)

Definition at line 2110 of file catcache.c.

References catcache::cc_relname, elog, catcache::id, catclist::my_cache, catclist::refcount, and WARNING.

Referenced by ResourceOwnerReleaseInternal().

2111 {
2112  elog(WARNING, "cache reference leak: cache %s (%d), list %p has count %d",
2113  list->my_cache->cc_relname, list->my_cache->id,
2114  list, list->refcount);
2115 }
int id
Definition: catcache.h:46
#define WARNING
Definition: elog.h:40
CatCache * my_cache
Definition: catcache.h:177
const char * cc_relname
Definition: catcache.h:57
#define elog
Definition: elog.h:219
int refcount
Definition: catcache.h:172

◆ ReleaseCatCache()

void ReleaseCatCache ( HeapTuple  tuple)

Definition at line 1458 of file catcache.c.

References Assert, catctup::c_list, CatCacheRemoveCTup(), catctup::ct_magic, CT_MAGIC, CurrentResourceOwner, catctup::dead, catctup::my_cache, offsetof, catctup::refcount, catclist::refcount, ResourceOwnerForgetCatCacheRef(), and catctup::tuple.

Referenced by ReleaseSysCache(), and ResourceOwnerReleaseInternal().

1459 {
1460  CatCTup *ct = (CatCTup *) (((char *) tuple) -
1461  offsetof(CatCTup, tuple));
1462 
1463  /* Safety checks to ensure we were handed a cache entry */
1464  Assert(ct->ct_magic == CT_MAGIC);
1465  Assert(ct->refcount > 0);
1466 
1467  ct->refcount--;
1469 
1470  if (
1471 #ifndef CATCACHE_FORCE_RELEASE
1472  ct->dead &&
1473 #endif
1474  ct->refcount == 0 &&
1475  (ct->c_list == NULL || ct->c_list->refcount == 0))
1476  CatCacheRemoveCTup(ct->my_cache, ct);
1477 }
CatCache * my_cache
Definition: catcache.h:132
#define CT_MAGIC
Definition: catcache.h:89
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
void ResourceOwnerForgetCatCacheRef(ResourceOwner owner, HeapTuple tuple)
Definition: resowner.c:944
struct catclist * c_list
Definition: catcache.h:130
static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
Definition: catcache.c:473
#define Assert(condition)
Definition: c.h:670
int refcount
Definition: catcache.h:118
HeapTupleData tuple
Definition: catcache.h:121
int refcount
Definition: catcache.h:172
#define offsetof(type, field)
Definition: c.h:593
int ct_magic
Definition: catcache.h:88
bool dead
Definition: catcache.h:119

◆ ReleaseCatCacheList()

void ReleaseCatCacheList ( CatCList list)

Definition at line 1795 of file catcache.c.

References Assert, CatCacheRemoveCList(), catclist::cl_magic, CL_MAGIC, CurrentResourceOwner, catclist::dead, catclist::my_cache, catclist::refcount, and ResourceOwnerForgetCatCacheListRef().

Referenced by AddEnumLabel(), blvalidate(), brinvalidate(), btvalidate(), ginvalidate(), gistvalidate(), hashvalidate(), opfamily_can_sort_type(), RenameEnumLabel(), ResourceOwnerReleaseInternal(), sepgsql_relation_drop(), and spgvalidate().

1796 {
1797  /* Safety checks to ensure we were handed a cache entry */
1798  Assert(list->cl_magic == CL_MAGIC);
1799  Assert(list->refcount > 0);
1800  list->refcount--;
1802 
1803  if (
1804 #ifndef CATCACHE_FORCE_RELEASE
1805  list->dead &&
1806 #endif
1807  list->refcount == 0)
1808  CatCacheRemoveCList(list->my_cache, list);
1809 }
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
int cl_magic
Definition: catcache.h:159
bool dead
Definition: catcache.h:173
static void CatCacheRemoveCList(CatCache *cache, CatCList *cl)
Definition: catcache.c:515
#define CL_MAGIC
Definition: catcache.h:160
CatCache * my_cache
Definition: catcache.h:177
void ResourceOwnerForgetCatCacheListRef(ResourceOwner owner, CatCList *list)
Definition: resowner.c:979
#define Assert(condition)
Definition: c.h:670
int refcount
Definition: catcache.h:172

◆ ResetCatalogCaches()

void ResetCatalogCaches ( void  )

Definition at line 705 of file catcache.c.

References CACHE1_elog, catcacheheader::ch_caches, slist_iter::cur, DEBUG2, ResetCatalogCache(), slist_container, and slist_foreach.

Referenced by InvalidateSystemCaches().

706 {
707  slist_iter iter;
708 
709  CACHE1_elog(DEBUG2, "ResetCatalogCaches called");
710 
712  {
713  CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
714 
715  ResetCatalogCache(cache);
716  }
717 
718  CACHE1_elog(DEBUG2, "end of ResetCatalogCaches call");
719 }
static void ResetCatalogCache(CatCache *cache)
Definition: catcache.c:658
static CatCacheHeader * CacheHdr
Definition: catcache.c:75
slist_node * cur
Definition: ilist.h:226
#define DEBUG2
Definition: elog.h:24
#define slist_container(type, membername, ptr)
Definition: ilist.h:674
#define CACHE1_elog(a, b)
Definition: catcache.c:66
slist_head ch_caches
Definition: catcache.h:184
#define slist_foreach(iter, lhead)
Definition: ilist.h:700

◆ SearchCatCache()

HeapTuple SearchCatCache ( CatCache cache,
Datum  v1,
Datum  v2,
Datum  v3,
Datum  v4 
)

Definition at line 1165 of file catcache.c.

References catcache::cc_nkeys, and SearchCatCacheInternal().

Referenced by SearchSysCache().

1170 {
1171  return SearchCatCacheInternal(cache, cache->cc_nkeys, v1, v2, v3, v4);
1172 }
int cc_nkeys
Definition: catcache.h:56
static HeapTuple SearchCatCacheInternal(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1216

◆ SearchCatCache1()

HeapTuple SearchCatCache1 ( CatCache cache,
Datum  v1 
)

Definition at line 1182 of file catcache.c.

References SearchCatCacheInternal().

Referenced by SearchSysCache1().

1184 {
1185  return SearchCatCacheInternal(cache, 1, v1, 0, 0, 0);
1186 }
static HeapTuple SearchCatCacheInternal(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1216

◆ SearchCatCache2()

HeapTuple SearchCatCache2 ( CatCache cache,
Datum  v1,
Datum  v2 
)

Definition at line 1190 of file catcache.c.

References SearchCatCacheInternal().

Referenced by SearchSysCache2().

1192 {
1193  return SearchCatCacheInternal(cache, 2, v1, v2, 0, 0);
1194 }
static HeapTuple SearchCatCacheInternal(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1216

◆ SearchCatCache3()

HeapTuple SearchCatCache3 ( CatCache cache,
Datum  v1,
Datum  v2,
Datum  v3 
)

Definition at line 1198 of file catcache.c.

References SearchCatCacheInternal().

Referenced by SearchSysCache3().

1200 {
1201  return SearchCatCacheInternal(cache, 3, v1, v2, v3, 0);
1202 }
static HeapTuple SearchCatCacheInternal(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1216

◆ SearchCatCache4()

HeapTuple SearchCatCache4 ( CatCache cache,
Datum  v1,
Datum  v2,
Datum  v3,
Datum  v4 
)

Definition at line 1206 of file catcache.c.

References SearchCatCacheInternal().

Referenced by SearchSysCache4().

1208 {
1209  return SearchCatCacheInternal(cache, 4, v1, v2, v3, v4);
1210 }
static HeapTuple SearchCatCacheInternal(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1216

◆ SearchCatCacheList()

CatCList* SearchCatCacheList ( CatCache cache,
int  nkeys,
Datum  v1,
Datum  v2,
Datum  v3,
Datum  v4 
)

Definition at line 1519 of file catcache.c.

References AccessShareLock, Assert, catctup::c_list, CACHE2_elog, CACHE3_elog, catclist::cache_elem, CacheMemoryContext, CatalogCacheCompareTuple(), CatalogCacheComputeHashValue(), CatalogCacheComputeTupleHashValue(), CatalogCacheCreateEntry(), CatalogCacheInitializeCache(), CATCACHE_MAXKEYS, CatCacheCopyKeys(), CatCacheRemoveCTup(), catcache::cc_bucket, catcache::cc_indexoid, catcache::cc_keyno, catcache::cc_lists, catcache::cc_nbuckets, catcache::cc_nkeys, catcache::cc_relname, catcache::cc_reloid, catcache::cc_skey, catcache::cc_tupdesc, catclist::cl_magic, CL_MAGIC, dlist_iter::cur, CurrentResourceOwner, catctup::dead, catclist::dead, DEBUG2, dlist_container, dlist_foreach, dlist_move_head(), dlist_push_head(), HASH_INDEX, catctup::hash_value, catclist::hash_value, heap_close, heap_open(), HeapTupleIsValid, i, IndexScanOK(), SysScanDescData::irel, ItemPointerEquals(), catclist::keys, lappend(), lfirst, list_length(), catclist::members, MemoryContextSwitchTo(), catclist::my_cache, catclist::n_members, catctup::negative, NIL, catclist::nkeys, offsetof, catclist::ordered, palloc(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, catctup::refcount, catclist::refcount, ResourceOwnerEnlargeCatCacheListRefs(), ResourceOwnerRememberCatCacheListRef(), ScanKeyData::sk_argument, systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, and catctup::tuple.

Referenced by SearchSysCacheList().

1525 {
1527  uint32 lHashValue;
1528  dlist_iter iter;
1529  CatCList *cl;
1530  CatCTup *ct;
1531  List *volatile ctlist;
1532  ListCell *ctlist_item;
1533  int nmembers;
1534  bool ordered;
1535  HeapTuple ntp;
1536  MemoryContext oldcxt;
1537  int i;
1538 
1539  /*
1540  * one-time startup overhead for each cache
1541  */
1542  if (cache->cc_tupdesc == NULL)
1544 
1545  Assert(nkeys > 0 && nkeys < cache->cc_nkeys);
1546 
1547 #ifdef CATCACHE_STATS
1548  cache->cc_lsearches++;
1549 #endif
1550 
1551  /* Initialize local parameter array */
1552  arguments[0] = v1;
1553  arguments[1] = v2;
1554  arguments[2] = v3;
1555  arguments[3] = v4;
1556 
1557  /*
1558  * compute a hash value of the given keys for faster search. We don't
1559  * presently divide the CatCList items into buckets, but this still lets
1560  * us skip non-matching items quickly most of the time.
1561  */
1562  lHashValue = CatalogCacheComputeHashValue(cache, nkeys, v1, v2, v3, v4);
1563 
1564  /*
1565  * scan the items until we find a match or exhaust our list
1566  *
1567  * Note: it's okay to use dlist_foreach here, even though we modify the
1568  * dlist within the loop, because we don't continue the loop afterwards.
1569  */
1570  dlist_foreach(iter, &cache->cc_lists)
1571  {
1572  cl = dlist_container(CatCList, cache_elem, iter.cur);
1573 
1574  if (cl->dead)
1575  continue; /* ignore dead entries */
1576 
1577  if (cl->hash_value != lHashValue)
1578  continue; /* quickly skip entry if wrong hash val */
1579 
1580  /*
1581  * see if the cached list matches our key.
1582  */
1583  if (cl->nkeys != nkeys)
1584  continue;
1585 
1586  if (!CatalogCacheCompareTuple(cache, nkeys, cl->keys, arguments))
1587  continue;
1588 
1589  /*
1590  * We found a matching list. Move the list to the front of the
1591  * cache's list-of-lists, to speed subsequent searches. (We do not
1592  * move the members to the fronts of their hashbucket lists, however,
1593  * since there's no point in that unless they are searched for
1594  * individually.)
1595  */
1596  dlist_move_head(&cache->cc_lists, &cl->cache_elem);
1597 
1598  /* Bump the list's refcount and return it */
1600  cl->refcount++;
1602 
1603  CACHE2_elog(DEBUG2, "SearchCatCacheList(%s): found list",
1604  cache->cc_relname);
1605 
1606 #ifdef CATCACHE_STATS
1607  cache->cc_lhits++;
1608 #endif
1609 
1610  return cl;
1611  }
1612 
1613  /*
1614  * List was not found in cache, so we have to build it by reading the
1615  * relation. For each matching tuple found in the relation, use an
1616  * existing cache entry if possible, else build a new one.
1617  *
1618  * We have to bump the member refcounts temporarily to ensure they won't
1619  * get dropped from the cache while loading other members. We use a PG_TRY
1620  * block to ensure we can undo those refcounts if we get an error before
1621  * we finish constructing the CatCList.
1622  */
1624 
1625  ctlist = NIL;
1626 
1627  PG_TRY();
1628  {
1629  ScanKeyData cur_skey[CATCACHE_MAXKEYS];
1630  Relation relation;
1631  SysScanDesc scandesc;
1632 
1633  /*
1634  * Ok, need to make a lookup in the relation, copy the scankey and
1635  * fill out any per-call fields.
1636  */
1637  memcpy(cur_skey, cache->cc_skey, sizeof(ScanKeyData) * cache->cc_nkeys);
1638  cur_skey[0].sk_argument = v1;
1639  cur_skey[1].sk_argument = v2;
1640  cur_skey[2].sk_argument = v3;
1641  cur_skey[3].sk_argument = v4;
1642 
1643  relation = heap_open(cache->cc_reloid, AccessShareLock);
1644 
1645  scandesc = systable_beginscan(relation,
1646  cache->cc_indexoid,
1647  IndexScanOK(cache, cur_skey),
1648  NULL,
1649  nkeys,
1650  cur_skey);
1651 
1652  /* The list will be ordered iff we are doing an index scan */
1653  ordered = (scandesc->irel != NULL);
1654 
1655  while (HeapTupleIsValid(ntp = systable_getnext(scandesc)))
1656  {
1657  uint32 hashValue;
1658  Index hashIndex;
1659  bool found = false;
1660  dlist_head *bucket;
1661 
1662  /*
1663  * See if there's an entry for this tuple already.
1664  */
1665  ct = NULL;
1666  hashValue = CatalogCacheComputeTupleHashValue(cache, cache->cc_nkeys, ntp);
1667  hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
1668 
1669  bucket = &cache->cc_bucket[hashIndex];
1670  dlist_foreach(iter, bucket)
1671  {
1672  ct = dlist_container(CatCTup, cache_elem, iter.cur);
1673 
1674  if (ct->dead || ct->negative)
1675  continue; /* ignore dead and negative entries */
1676 
1677  if (ct->hash_value != hashValue)
1678  continue; /* quickly skip entry if wrong hash val */
1679 
1680  if (!ItemPointerEquals(&(ct->tuple.t_self), &(ntp->t_self)))
1681  continue; /* not same tuple */
1682 
1683  /*
1684  * Found a match, but can't use it if it belongs to another
1685  * list already
1686  */
1687  if (ct->c_list)
1688  continue;
1689 
1690  found = true;
1691  break; /* A-OK */
1692  }
1693 
1694  if (!found)
1695  {
1696  /* We didn't find a usable entry, so make a new one */
1697  ct = CatalogCacheCreateEntry(cache, ntp, arguments,
1698  hashValue, hashIndex,
1699  false);
1700  }
1701 
1702  /* Careful here: add entry to ctlist, then bump its refcount */
1703  /* This way leaves state correct if lappend runs out of memory */
1704  ctlist = lappend(ctlist, ct);
1705  ct->refcount++;
1706  }
1707 
1708  systable_endscan(scandesc);
1709 
1710  heap_close(relation, AccessShareLock);
1711 
1712  /* Now we can build the CatCList entry. */
1714  nmembers = list_length(ctlist);
1715  cl = (CatCList *)
1716  palloc(offsetof(CatCList, members) + nmembers * sizeof(CatCTup *));
1717 
1718  /* Extract key values */
1719  CatCacheCopyKeys(cache->cc_tupdesc, nkeys, cache->cc_keyno,
1720  arguments, cl->keys);
1721  MemoryContextSwitchTo(oldcxt);
1722 
1723  /*
1724  * We are now past the last thing that could trigger an elog before we
1725  * have finished building the CatCList and remembering it in the
1726  * resource owner. So it's OK to fall out of the PG_TRY, and indeed
1727  * we'd better do so before we start marking the members as belonging
1728  * to the list.
1729  */
1730 
1731  }
1732  PG_CATCH();
1733  {
1734  foreach(ctlist_item, ctlist)
1735  {
1736  ct = (CatCTup *) lfirst(ctlist_item);
1737  Assert(ct->c_list == NULL);
1738  Assert(ct->refcount > 0);
1739  ct->refcount--;
1740  if (
1741 #ifndef CATCACHE_FORCE_RELEASE
1742  ct->dead &&
1743 #endif
1744  ct->refcount == 0 &&
1745  (ct->c_list == NULL || ct->c_list->refcount == 0))
1746  CatCacheRemoveCTup(cache, ct);
1747  }
1748 
1749  PG_RE_THROW();
1750  }
1751  PG_END_TRY();
1752 
1753  cl->cl_magic = CL_MAGIC;
1754  cl->my_cache = cache;
1755  cl->refcount = 0; /* for the moment */
1756  cl->dead = false;
1757  cl->ordered = ordered;
1758  cl->nkeys = nkeys;
1759  cl->hash_value = lHashValue;
1760  cl->n_members = nmembers;
1761 
1762  i = 0;
1763  foreach(ctlist_item, ctlist)
1764  {
1765  cl->members[i++] = ct = (CatCTup *) lfirst(ctlist_item);
1766  Assert(ct->c_list == NULL);
1767  ct->c_list = cl;
1768  /* release the temporary refcount on the member */
1769  Assert(ct->refcount > 0);
1770  ct->refcount--;
1771  /* mark list dead if any members already dead */
1772  if (ct->dead)
1773  cl->dead = true;
1774  }
1775  Assert(i == nmembers);
1776 
1777  dlist_push_head(&cache->cc_lists, &cl->cache_elem);
1778 
1779  /* Finally, bump the list's refcount and return it */
1780  cl->refcount++;
1782 
1783  CACHE3_elog(DEBUG2, "SearchCatCacheList(%s): made list of %d members",
1784  cache->cc_relname, nmembers);
1785 
1786  return cl;
1787 }
int cc_keyno[CATCACHE_MAXKEYS]
Definition: catcache.h:53
#define NIL
Definition: pg_list.h:69
Relation irel
Definition: relscan.h:156
int n_members
Definition: catcache.h:176
uint32 hash_value
Definition: catcache.h:162
uint32 hash_value
Definition: catcache.h:91
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define CACHE3_elog(a, b, c, d)
Definition: catcache.c:68
#define HASH_INDEX(h, sz)
Definition: catcache.c:51
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:300
#define dlist_foreach(iter, lhead)
Definition: ilist.h:507
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
dlist_head * cc_bucket
Definition: catcache.h:49
#define AccessShareLock
Definition: lockdefs.h:36
void ResourceOwnerEnlargeCatCacheListRefs(ResourceOwner owner)
Definition: resowner.c:959
int cl_magic
Definition: catcache.h:159
bool dead
Definition: catcache.h:173
#define heap_close(r, l)
Definition: heapam.h:97
dlist_head cc_lists
Definition: catcache.h:54
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:939
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
Datum keys[CATCACHE_MAXKEYS]
Definition: catcache.h:170
short nkeys
Definition: catcache.h:175
static uint32 CatalogCacheComputeTupleHashValue(CatCache *cache, int nkeys, HeapTuple tuple)
Definition: catcache.c:327
struct catclist * c_list
Definition: catcache.h:130
static void CatCacheCopyKeys(TupleDesc tupdesc, int nkeys, int *attnos, Datum *srckeys, Datum *dstkeys)
Definition: catcache.c:1951
CatCTup * members[FLEXIBLE_ARRAY_MEMBER]
Definition: catcache.h:178
Oid cc_indexoid
Definition: catcache.h:59
#define dlist_container(type, membername, ptr)
Definition: ilist.h:477
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#define CATCACHE_MAXKEYS
Definition: catcache.h:35
Oid cc_reloid
Definition: catcache.h:58
int cc_nkeys
Definition: catcache.h:56
ItemPointerData t_self
Definition: htup.h:65
TupleDesc cc_tupdesc
Definition: catcache.h:48
static CatCTup * CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp, Datum *arguments, uint32 hashValue, Index hashIndex, bool negative)
Definition: catcache.c:1818
#define DEBUG2
Definition: elog.h:24
unsigned int uint32
Definition: c.h:296
List * lappend(List *list, void *datum)
Definition: list.c:128
static bool CatalogCacheCompareTuple(const CatCache *cache, int nkeys, const Datum *cachekeys, const Datum *searchkeys)
Definition: catcache.c:390
dlist_node cache_elem
Definition: catcache.h:164
#define CL_MAGIC
Definition: catcache.h:160
static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
Definition: catcache.c:473
static bool IndexScanOK(CatCache *cache, ScanKey cur_skey)
Definition: catcache.c:1101
uintptr_t Datum
Definition: postgres.h:372
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
CatCache * my_cache
Definition: catcache.h:177
dlist_node * cur
Definition: ilist.h:161
unsigned int Index
Definition: c.h:413
#define PG_CATCH()
Definition: elog.h:293
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
int cc_nbuckets
Definition: catcache.h:47
static int list_length(const List *l)
Definition: pg_list.h:89
int refcount
Definition: catcache.h:118
const char * cc_relname
Definition: catcache.h:57
#define PG_RE_THROW()
Definition: elog.h:314
static uint32 CatalogCacheComputeHashValue(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:276
bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)
Definition: itemptr.c:29
static void dlist_move_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:385
bool negative
Definition: catcache.h:120
bool ordered
Definition: catcache.h:174
void * palloc(Size size)
Definition: mcxt.c:848
int i
HeapTupleData tuple
Definition: catcache.h:121
#define CACHE2_elog(a, b, c)
Definition: catcache.c:67
int refcount
Definition: catcache.h:172
#define PG_TRY()
Definition: elog.h:284
ScanKeyData cc_skey[CATCACHE_MAXKEYS]
Definition: catcache.h:62
Definition: pg_list.h:45
Datum sk_argument
Definition: skey.h:72
#define PG_END_TRY()
Definition: elog.h:300
#define offsetof(type, field)
Definition: c.h:593
bool dead
Definition: catcache.h:119
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void ResourceOwnerRememberCatCacheListRef(ResourceOwner owner, CatCList *list)
Definition: resowner.c:970

Variable Documentation

◆ CacheMemoryContext

PGDLLIMPORT MemoryContext CacheMemoryContext

Definition at line 46 of file mcxt.c.