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)
 
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:431
#define CACHE1_elog(a, b)
Definition: catcache.c:66
#define Assert(condition)
Definition: c.h:688
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:197
MemoryContext TopMemoryContext
Definition: mcxt.c:43
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:165
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:299
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:864
struct tupleDesc * TupleDesc
slist_head ch_caches
Definition: catcache.h:184
#define InitCatCache_DEBUG2
Definition: catcache.c:775
#define Assert(condition)
Definition: c.h:688
int cc_nbuckets
Definition: catcache.h:47
#define CACHELINEALIGN(LEN)
Definition: c.h:644
void CreateCacheMemoryContext(void)
Definition: catcache.c:636
const char * cc_relname
Definition: catcache.h:57
void * palloc(Size size)
Definition: mcxt.c:835
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:688
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:177
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 2035 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().

2039 {
2040  slist_iter iter;
2041  Oid reloid;
2042 
2043  CACHE1_elog(DEBUG2, "PrepareToInvalidateCacheTuple: called");
2044 
2045  /*
2046  * sanity checks
2047  */
2048  Assert(RelationIsValid(relation));
2049  Assert(HeapTupleIsValid(tuple));
2050  Assert(PointerIsValid(function));
2051  Assert(CacheHdr != NULL);
2052 
2053  reloid = RelationGetRelid(relation);
2054 
2055  /* ----------------
2056  * for each cache
2057  * if the cache contains tuples from the specified relation
2058  * compute the tuple's hash value(s) in this cache,
2059  * and call the passed function to register the information.
2060  * ----------------
2061  */
2062 
2064  {
2065  CatCache *ccp = slist_container(CatCache, cc_next, iter.cur);
2066  uint32 hashvalue;
2067  Oid dbid;
2068 
2069  if (ccp->cc_reloid != reloid)
2070  continue;
2071 
2072  /* Just in case cache hasn't finished initialization yet... */
2073  if (ccp->cc_tupdesc == NULL)
2075 
2076  hashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, tuple);
2077  dbid = ccp->cc_relisshared ? (Oid) 0 : MyDatabaseId;
2078 
2079  (*function) (ccp->id, hashvalue, dbid);
2080 
2081  if (newtuple)
2082  {
2083  uint32 newhashvalue;
2084 
2085  newhashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, newtuple);
2086 
2087  if (newhashvalue != hashvalue)
2088  (*function) (ccp->id, newhashvalue, dbid);
2089  }
2090  }
2091 }
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:314
#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:688
#define slist_foreach(iter, lhead)
Definition: ilist.h:700
#define PointerIsValid(pointer)
Definition: c.h:582
#define RelationGetRelid(relation)
Definition: rel.h:425

◆ PrintCatCacheLeakWarning()

void PrintCatCacheLeakWarning ( HeapTuple  tuple)

Definition at line 2099 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().

2100 {
2101  CatCTup *ct = (CatCTup *) (((char *) tuple) -
2102  offsetof(CatCTup, tuple));
2103 
2104  /* Safety check to ensure we were handed a cache entry */
2105  Assert(ct->ct_magic == CT_MAGIC);
2106 
2107  elog(WARNING, "cache reference leak: cache %s (%d), tuple %u/%u has count %d",
2108  ct->my_cache->cc_relname, ct->my_cache->id,
2109  ItemPointerGetBlockNumber(&(tuple->t_self)),
2110  ItemPointerGetOffsetNumber(&(tuple->t_self)),
2111  ct->refcount);
2112 }
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:688
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:611
int ct_magic
Definition: catcache.h:88

◆ PrintCatCacheListLeakWarning()

void PrintCatCacheListLeakWarning ( CatCList list)

Definition at line 2115 of file catcache.c.

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

Referenced by ResourceOwnerReleaseInternal().

2116 {
2117  elog(WARNING, "cache reference leak: cache %s (%d), list %p has count %d",
2118  list->my_cache->cc_relname, list->my_cache->id,
2119  list, list->refcount);
2120 }
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:688
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:611
int ct_magic
Definition: catcache.h:88
bool dead
Definition: catcache.h:119

◆ ReleaseCatCacheList()

void ReleaseCatCacheList ( CatCList list)

Definition at line 1800 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(), spgvalidate(), and transformFrameOffset().

1801 {
1802  /* Safety checks to ensure we were handed a cache entry */
1803  Assert(list->cl_magic == CL_MAGIC);
1804  Assert(list->refcount > 0);
1805  list->refcount--;
1807 
1808  if (
1809 #ifndef CATCACHE_FORCE_RELEASE
1810  list->dead &&
1811 #endif
1812  list->refcount == 0)
1813  CatCacheRemoveCList(list->my_cache, list);
1814 }
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:688
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 
)

Definition at line 1524 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().

1529 {
1530  Datum v4 = 0; /* dummy last-column value */
1532  uint32 lHashValue;
1533  dlist_iter iter;
1534  CatCList *cl;
1535  CatCTup *ct;
1536  List *volatile ctlist;
1537  ListCell *ctlist_item;
1538  int nmembers;
1539  bool ordered;
1540  HeapTuple ntp;
1541  MemoryContext oldcxt;
1542  int i;
1543 
1544  /*
1545  * one-time startup overhead for each cache
1546  */
1547  if (cache->cc_tupdesc == NULL)
1549 
1550  Assert(nkeys > 0 && nkeys < cache->cc_nkeys);
1551 
1552 #ifdef CATCACHE_STATS
1553  cache->cc_lsearches++;
1554 #endif
1555 
1556  /* Initialize local parameter array */
1557  arguments[0] = v1;
1558  arguments[1] = v2;
1559  arguments[2] = v3;
1560  arguments[3] = v4;
1561 
1562  /*
1563  * compute a hash value of the given keys for faster search. We don't
1564  * presently divide the CatCList items into buckets, but this still lets
1565  * us skip non-matching items quickly most of the time.
1566  */
1567  lHashValue = CatalogCacheComputeHashValue(cache, nkeys, v1, v2, v3, v4);
1568 
1569  /*
1570  * scan the items until we find a match or exhaust our list
1571  *
1572  * Note: it's okay to use dlist_foreach here, even though we modify the
1573  * dlist within the loop, because we don't continue the loop afterwards.
1574  */
1575  dlist_foreach(iter, &cache->cc_lists)
1576  {
1577  cl = dlist_container(CatCList, cache_elem, iter.cur);
1578 
1579  if (cl->dead)
1580  continue; /* ignore dead entries */
1581 
1582  if (cl->hash_value != lHashValue)
1583  continue; /* quickly skip entry if wrong hash val */
1584 
1585  /*
1586  * see if the cached list matches our key.
1587  */
1588  if (cl->nkeys != nkeys)
1589  continue;
1590 
1591  if (!CatalogCacheCompareTuple(cache, nkeys, cl->keys, arguments))
1592  continue;
1593 
1594  /*
1595  * We found a matching list. Move the list to the front of the
1596  * cache's list-of-lists, to speed subsequent searches. (We do not
1597  * move the members to the fronts of their hashbucket lists, however,
1598  * since there's no point in that unless they are searched for
1599  * individually.)
1600  */
1601  dlist_move_head(&cache->cc_lists, &cl->cache_elem);
1602 
1603  /* Bump the list's refcount and return it */
1605  cl->refcount++;
1607 
1608  CACHE2_elog(DEBUG2, "SearchCatCacheList(%s): found list",
1609  cache->cc_relname);
1610 
1611 #ifdef CATCACHE_STATS
1612  cache->cc_lhits++;
1613 #endif
1614 
1615  return cl;
1616  }
1617 
1618  /*
1619  * List was not found in cache, so we have to build it by reading the
1620  * relation. For each matching tuple found in the relation, use an
1621  * existing cache entry if possible, else build a new one.
1622  *
1623  * We have to bump the member refcounts temporarily to ensure they won't
1624  * get dropped from the cache while loading other members. We use a PG_TRY
1625  * block to ensure we can undo those refcounts if we get an error before
1626  * we finish constructing the CatCList.
1627  */
1629 
1630  ctlist = NIL;
1631 
1632  PG_TRY();
1633  {
1634  ScanKeyData cur_skey[CATCACHE_MAXKEYS];
1635  Relation relation;
1636  SysScanDesc scandesc;
1637 
1638  /*
1639  * Ok, need to make a lookup in the relation, copy the scankey and
1640  * fill out any per-call fields.
1641  */
1642  memcpy(cur_skey, cache->cc_skey, sizeof(ScanKeyData) * cache->cc_nkeys);
1643  cur_skey[0].sk_argument = v1;
1644  cur_skey[1].sk_argument = v2;
1645  cur_skey[2].sk_argument = v3;
1646  cur_skey[3].sk_argument = v4;
1647 
1648  relation = heap_open(cache->cc_reloid, AccessShareLock);
1649 
1650  scandesc = systable_beginscan(relation,
1651  cache->cc_indexoid,
1652  IndexScanOK(cache, cur_skey),
1653  NULL,
1654  nkeys,
1655  cur_skey);
1656 
1657  /* The list will be ordered iff we are doing an index scan */
1658  ordered = (scandesc->irel != NULL);
1659 
1660  while (HeapTupleIsValid(ntp = systable_getnext(scandesc)))
1661  {
1662  uint32 hashValue;
1663  Index hashIndex;
1664  bool found = false;
1665  dlist_head *bucket;
1666 
1667  /*
1668  * See if there's an entry for this tuple already.
1669  */
1670  ct = NULL;
1671  hashValue = CatalogCacheComputeTupleHashValue(cache, cache->cc_nkeys, ntp);
1672  hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
1673 
1674  bucket = &cache->cc_bucket[hashIndex];
1675  dlist_foreach(iter, bucket)
1676  {
1677  ct = dlist_container(CatCTup, cache_elem, iter.cur);
1678 
1679  if (ct->dead || ct->negative)
1680  continue; /* ignore dead and negative entries */
1681 
1682  if (ct->hash_value != hashValue)
1683  continue; /* quickly skip entry if wrong hash val */
1684 
1685  if (!ItemPointerEquals(&(ct->tuple.t_self), &(ntp->t_self)))
1686  continue; /* not same tuple */
1687 
1688  /*
1689  * Found a match, but can't use it if it belongs to another
1690  * list already
1691  */
1692  if (ct->c_list)
1693  continue;
1694 
1695  found = true;
1696  break; /* A-OK */
1697  }
1698 
1699  if (!found)
1700  {
1701  /* We didn't find a usable entry, so make a new one */
1702  ct = CatalogCacheCreateEntry(cache, ntp, arguments,
1703  hashValue, hashIndex,
1704  false);
1705  }
1706 
1707  /* Careful here: add entry to ctlist, then bump its refcount */
1708  /* This way leaves state correct if lappend runs out of memory */
1709  ctlist = lappend(ctlist, ct);
1710  ct->refcount++;
1711  }
1712 
1713  systable_endscan(scandesc);
1714 
1715  heap_close(relation, AccessShareLock);
1716 
1717  /* Now we can build the CatCList entry. */
1719  nmembers = list_length(ctlist);
1720  cl = (CatCList *)
1721  palloc(offsetof(CatCList, members) + nmembers * sizeof(CatCTup *));
1722 
1723  /* Extract key values */
1724  CatCacheCopyKeys(cache->cc_tupdesc, nkeys, cache->cc_keyno,
1725  arguments, cl->keys);
1726  MemoryContextSwitchTo(oldcxt);
1727 
1728  /*
1729  * We are now past the last thing that could trigger an elog before we
1730  * have finished building the CatCList and remembering it in the
1731  * resource owner. So it's OK to fall out of the PG_TRY, and indeed
1732  * we'd better do so before we start marking the members as belonging
1733  * to the list.
1734  */
1735 
1736  }
1737  PG_CATCH();
1738  {
1739  foreach(ctlist_item, ctlist)
1740  {
1741  ct = (CatCTup *) lfirst(ctlist_item);
1742  Assert(ct->c_list == NULL);
1743  Assert(ct->refcount > 0);
1744  ct->refcount--;
1745  if (
1746 #ifndef CATCACHE_FORCE_RELEASE
1747  ct->dead &&
1748 #endif
1749  ct->refcount == 0 &&
1750  (ct->c_list == NULL || ct->c_list->refcount == 0))
1751  CatCacheRemoveCTup(cache, ct);
1752  }
1753 
1754  PG_RE_THROW();
1755  }
1756  PG_END_TRY();
1757 
1758  cl->cl_magic = CL_MAGIC;
1759  cl->my_cache = cache;
1760  cl->refcount = 0; /* for the moment */
1761  cl->dead = false;
1762  cl->ordered = ordered;
1763  cl->nkeys = nkeys;
1764  cl->hash_value = lHashValue;
1765  cl->n_members = nmembers;
1766 
1767  i = 0;
1768  foreach(ctlist_item, ctlist)
1769  {
1770  cl->members[i++] = ct = (CatCTup *) lfirst(ctlist_item);
1771  Assert(ct->c_list == NULL);
1772  ct->c_list = cl;
1773  /* release the temporary refcount on the member */
1774  Assert(ct->refcount > 0);
1775  ct->refcount--;
1776  /* mark list dead if any members already dead */
1777  if (ct->dead)
1778  cl->dead = true;
1779  }
1780  Assert(i == nmembers);
1781 
1782  dlist_push_head(&cache->cc_lists, &cl->cache_elem);
1783 
1784  /* Finally, bump the list's refcount and return it */
1785  cl->refcount++;
1787 
1788  CACHE3_elog(DEBUG2, "SearchCatCacheList(%s): made list of %d members",
1789  cache->cc_relname, nmembers);
1790 
1791  return cl;
1792 }
int cc_keyno[CATCACHE_MAXKEYS]
Definition: catcache.h:53
#define NIL
Definition: pg_list.h:69
Relation irel
Definition: relscan.h:157
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:1956
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:1823
#define DEBUG2
Definition: elog.h:24
unsigned int uint32
Definition: c.h:314
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:365
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:431
#define PG_CATCH()
Definition: elog.h:293
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:688
#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:835
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:611
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.