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

typedef struct catcache CatCache

◆ CatCacheHeader

◆ CatCList

typedef struct catclist CatCList

◆ CatCTup

typedef struct catctup 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 719 of file catcache.c.

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

Referenced by LocalExecuteInvalidationMessage().

720 {
721  slist_iter iter;
722 
723  CACHE_elog(DEBUG2, "CatalogCacheFlushCatalog called for %u", catId);
724 
726  {
727  CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
728 
729  /* Does this cache store tuples of the target catalog? */
730  if (cache->cc_reloid == catId)
731  {
732  /* Yes, so flush all its contents */
733  ResetCatalogCache(cache);
734 
735  /* Tell inval.c to call syscache callbacks for this cache */
736  CallSyscacheCallbacks(cache->id, 0);
737  }
738  }
739 
740  CACHE_elog(DEBUG2, "end of CatalogCacheFlushCatalog call");
741 }
static void ResetCatalogCache(CatCache *cache)
Definition: catcache.c:642
static CatCacheHeader * CacheHdr
Definition: catcache.c:64
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:693
void CallSyscacheCallbacks(int cacheid, uint32 hashvalue)
Definition: inval.c:1495
slist_head ch_caches
Definition: catcache.h:184
#define CACHE_elog(...)
Definition: catcache.c:60
#define slist_foreach(iter, lhead)
Definition: ilist.h:719

◆ CatCacheInvalidate()

void CatCacheInvalidate ( CatCache cache,
uint32  hashValue 
)

Definition at line 552 of file catcache.c.

References Assert, catctup::c_list, CACHE_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().

553 {
554  Index hashIndex;
555  dlist_mutable_iter iter;
556 
557  CACHE_elog(DEBUG2, "CatCacheInvalidate: called");
558 
559  /*
560  * We don't bother to check whether the cache has finished initialization
561  * yet; if not, there will be no entries in it so no problem.
562  */
563 
564  /*
565  * Invalidate *all* CatCLists in this cache; it's too hard to tell which
566  * searches might still be correct, so just zap 'em all.
567  */
568  dlist_foreach_modify(iter, &cache->cc_lists)
569  {
570  CatCList *cl = dlist_container(CatCList, cache_elem, iter.cur);
571 
572  if (cl->refcount > 0)
573  cl->dead = true;
574  else
575  CatCacheRemoveCList(cache, cl);
576  }
577 
578  /*
579  * inspect the proper hash bucket for tuple matches
580  */
581  hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
582  dlist_foreach_modify(iter, &cache->cc_bucket[hashIndex])
583  {
584  CatCTup *ct = dlist_container(CatCTup, cache_elem, iter.cur);
585 
586  if (hashValue == ct->hash_value)
587  {
588  if (ct->refcount > 0 ||
589  (ct->c_list && ct->c_list->refcount > 0))
590  {
591  ct->dead = true;
592  /* list, if any, was marked dead above */
593  Assert(ct->c_list == NULL || ct->c_list->dead);
594  }
595  else
596  CatCacheRemoveCTup(cache, ct);
597  CACHE_elog(DEBUG2, "CatCacheInvalidate: invalidated");
598 #ifdef CATCACHE_STATS
599  cache->cc_invals++;
600 #endif
601  /* could be multiple matches, so keep looking! */
602  }
603  }
604 }
dlist_node * cur
Definition: ilist.h:180
uint32 hash_value
Definition: catcache.h:91
#define dlist_foreach_modify(iter, lhead)
Definition: ilist.h:543
#define HASH_INDEX(h, sz)
Definition: catcache.c:50
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:496
#define DEBUG2
Definition: elog.h:24
static void CatCacheRemoveCList(CatCache *cache, CatCList *cl)
Definition: catcache.c:499
static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
Definition: catcache.c:457
unsigned int Index
Definition: c.h:549
#define Assert(condition)
Definition: c.h:804
int cc_nbuckets
Definition: catcache.h:47
int refcount
Definition: catcache.h:118
#define CACHE_elog(...)
Definition: catcache.c:60
int refcount
Definition: catcache.h:172
bool dead
Definition: catcache.h:119

◆ CreateCacheMemoryContext()

void CreateCacheMemoryContext ( void  )

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

621 {
622  /*
623  * Purely for paranoia, check that context doesn't exist; caller probably
624  * did so already.
625  */
626  if (!CacheMemoryContext)
628  "CacheMemoryContext",
630 }
#define AllocSetContextCreate
Definition: memutils.h:173
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:195
MemoryContext TopMemoryContext
Definition: mcxt.c:48
MemoryContext CacheMemoryContext
Definition: mcxt.c:51

◆ GetCatCacheHashValue()

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

Definition at line 1474 of file catcache.c.

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

Referenced by GetSysCacheHashValue().

1479 {
1480  /*
1481  * one-time startup overhead for each cache
1482  */
1483  if (cache->cc_tupdesc == NULL)
1485 
1486  /*
1487  * calculate the hash value
1488  */
1489  return CatalogCacheComputeHashValue(cache, cache->cc_nkeys, v1, v2, v3, v4);
1490 }
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:923
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:270

◆ InitCatCache()

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

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

769 {
770  CatCache *cp;
771  MemoryContext oldcxt;
772  size_t sz;
773  int i;
774 
775  /*
776  * nbuckets is the initial number of hash buckets to use in this catcache.
777  * It will be enlarged later if it becomes too full.
778  *
779  * nbuckets must be a power of two. We check this via Assert rather than
780  * a full runtime check because the values will be coming from constant
781  * tables.
782  *
783  * If you're confused by the power-of-two check, see comments in
784  * bitmapset.c for an explanation.
785  */
786  Assert(nbuckets > 0 && (nbuckets & -nbuckets) == nbuckets);
787 
788  /*
789  * first switch to the cache context so our allocations do not vanish at
790  * the end of a transaction
791  */
792  if (!CacheMemoryContext)
794 
796 
797  /*
798  * if first time through, initialize the cache group header
799  */
800  if (CacheHdr == NULL)
801  {
804  CacheHdr->ch_ntup = 0;
805 #ifdef CATCACHE_STATS
806  /* set up to dump stats at backend exit */
807  on_proc_exit(CatCachePrintStats, 0);
808 #endif
809  }
810 
811  /*
812  * Allocate a new cache structure, aligning to a cacheline boundary
813  *
814  * Note: we rely on zeroing to initialize all the dlist headers correctly
815  */
816  sz = sizeof(CatCache) + PG_CACHE_LINE_SIZE;
817  cp = (CatCache *) CACHELINEALIGN(palloc0(sz));
818  cp->cc_bucket = palloc0(nbuckets * sizeof(dlist_head));
819 
820  /*
821  * initialize the cache's relation information for the relation
822  * corresponding to this cache, and initialize some of the new cache's
823  * other internal fields. But don't open the relation yet.
824  */
825  cp->id = id;
826  cp->cc_relname = "(not known yet)";
827  cp->cc_reloid = reloid;
828  cp->cc_indexoid = indexoid;
829  cp->cc_relisshared = false; /* temporary */
830  cp->cc_tupdesc = (TupleDesc) NULL;
831  cp->cc_ntup = 0;
832  cp->cc_nbuckets = nbuckets;
833  cp->cc_nkeys = nkeys;
834  for (i = 0; i < nkeys; ++i)
835  cp->cc_keyno[i] = key[i];
836 
837  /*
838  * new cache is initialized as far as we can go for now. print some
839  * debugging information, if appropriate.
840  */
842 
843  /*
844  * add completed cache to top of group header's list
845  */
847 
848  /*
849  * back to the old context before we return...
850  */
851  MemoryContextSwitchTo(oldcxt);
852 
853  return cp;
854 }
#define PG_CACHE_LINE_SIZE
int cc_keyno[CATCACHE_MAXKEYS]
Definition: catcache.h:53
static CatCacheHeader * CacheHdr
Definition: catcache.c:64
void on_proc_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:305
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:593
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:573
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:1093
slist_head ch_caches
Definition: catcache.h:184
#define InitCatCache_DEBUG2
Definition: catcache.c:759
#define Assert(condition)
Definition: c.h:804
int cc_nbuckets
Definition: catcache.h:47
#define CACHELINEALIGN(LEN)
Definition: c.h:760
void CreateCacheMemoryContext(void)
Definition: catcache.c:620
const char * cc_relname
Definition: catcache.h:57
struct TupleDescData * TupleDesc
Definition: tupdesc.h:89
void * palloc(Size size)
Definition: mcxt.c:1062
int i
MemoryContext CacheMemoryContext
Definition: mcxt.c:51

◆ InitCatCachePhase2()

void InitCatCachePhase2 ( CatCache cache,
bool  touch_index 
)

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

1033 {
1034  if (cache->cc_tupdesc == NULL)
1036 
1037  if (touch_index &&
1038  cache->id != AMOID &&
1039  cache->id != AMNAME)
1040  {
1041  Relation idesc;
1042 
1043  /*
1044  * We must lock the underlying catalog before opening the index to
1045  * avoid deadlock, since index_open could possibly result in reading
1046  * this same catalog, and if anyone else is exclusive-locking this
1047  * catalog and index they'll be doing it in that order.
1048  */
1050  idesc = index_open(cache->cc_indexoid, AccessShareLock);
1051 
1052  /*
1053  * While we've got the index open, let's check that it's unique (and
1054  * not just deferrable-unique, thank you very much). This is just to
1055  * catch thinkos in definitions of new catcaches, so we don't worry
1056  * about the pg_am indexes not getting tested.
1057  */
1058  Assert(idesc->rd_index->indisunique &&
1059  idesc->rd_index->indimmediate);
1060 
1061  index_close(idesc, AccessShareLock);
1063  }
1064 }
Definition: syscache.h:36
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:200
#define AccessShareLock
Definition: lockdefs.h:36
int id
Definition: catcache.h:46
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:923
Oid cc_indexoid
Definition: catcache.h:59
Form_pg_index rd_index
Definition: rel.h:187
Oid cc_reloid
Definition: catcache.h:58
TupleDesc cc_tupdesc
Definition: catcache.h:48
#define Assert(condition)
Definition: c.h:804
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:158
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:109
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:132

◆ PrepareToInvalidateCacheTuple()

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

Definition at line 2009 of file catcache.c.

References Assert, CACHE_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().

2013 {
2014  slist_iter iter;
2015  Oid reloid;
2016 
2017  CACHE_elog(DEBUG2, "PrepareToInvalidateCacheTuple: called");
2018 
2019  /*
2020  * sanity checks
2021  */
2022  Assert(RelationIsValid(relation));
2023  Assert(HeapTupleIsValid(tuple));
2024  Assert(PointerIsValid(function));
2025  Assert(CacheHdr != NULL);
2026 
2027  reloid = RelationGetRelid(relation);
2028 
2029  /* ----------------
2030  * for each cache
2031  * if the cache contains tuples from the specified relation
2032  * compute the tuple's hash value(s) in this cache,
2033  * and call the passed function to register the information.
2034  * ----------------
2035  */
2036 
2038  {
2039  CatCache *ccp = slist_container(CatCache, cc_next, iter.cur);
2040  uint32 hashvalue;
2041  Oid dbid;
2042 
2043  if (ccp->cc_reloid != reloid)
2044  continue;
2045 
2046  /* Just in case cache hasn't finished initialization yet... */
2047  if (ccp->cc_tupdesc == NULL)
2049 
2050  hashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, tuple);
2051  dbid = ccp->cc_relisshared ? (Oid) 0 : MyDatabaseId;
2052 
2053  (*function) (ccp->id, hashvalue, dbid);
2054 
2055  if (newtuple)
2056  {
2057  uint32 newhashvalue;
2058 
2059  newhashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, newtuple);
2060 
2061  if (newhashvalue != hashvalue)
2062  (*function) (ccp->id, newhashvalue, dbid);
2063  }
2064  }
2065 }
static CatCacheHeader * CacheHdr
Definition: catcache.c:64
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:923
bool cc_relisshared
Definition: catcache.h:60
static uint32 CatalogCacheComputeTupleHashValue(CatCache *cache, int nkeys, HeapTuple tuple)
Definition: catcache.c:319
Oid cc_reloid
Definition: catcache.h:58
int cc_nkeys
Definition: catcache.h:56
#define RelationIsValid(relation)
Definition: rel.h:442
TupleDesc cc_tupdesc
Definition: catcache.h:48
#define DEBUG2
Definition: elog.h:24
unsigned int uint32
Definition: c.h:441
#define slist_container(type, membername, ptr)
Definition: ilist.h:693
Oid MyDatabaseId
Definition: globals.c:88
slist_head ch_caches
Definition: catcache.h:184
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:804
#define CACHE_elog(...)
Definition: catcache.c:60
#define slist_foreach(iter, lhead)
Definition: ilist.h:719
#define PointerIsValid(pointer)
Definition: c.h:698
#define RelationGetRelid(relation)
Definition: rel.h:469

◆ PrintCatCacheLeakWarning()

void PrintCatCacheLeakWarning ( HeapTuple  tuple)

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

2074 {
2075  CatCTup *ct = (CatCTup *) (((char *) tuple) -
2076  offsetof(CatCTup, tuple));
2077 
2078  /* Safety check to ensure we were handed a cache entry */
2079  Assert(ct->ct_magic == CT_MAGIC);
2080 
2081  elog(WARNING, "cache reference leak: cache %s (%d), tuple %u/%u has count %d",
2082  ct->my_cache->cc_relname, ct->my_cache->id,
2083  ItemPointerGetBlockNumber(&(tuple->t_self)),
2084  ItemPointerGetOffsetNumber(&(tuple->t_self)),
2085  ct->refcount);
2086 }
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:804
int refcount
Definition: catcache.h:118
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:117
const char * cc_relname
Definition: catcache.h:57
#define elog(elevel,...)
Definition: elog.h:232
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:98
#define offsetof(type, field)
Definition: c.h:727
int ct_magic
Definition: catcache.h:88

◆ PrintCatCacheListLeakWarning()

void PrintCatCacheListLeakWarning ( CatCList list)

Definition at line 2089 of file catcache.c.

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

Referenced by ResourceOwnerReleaseInternal().

2090 {
2091  elog(WARNING, "cache reference leak: cache %s (%d), list %p has count %d",
2092  list->my_cache->cc_relname, list->my_cache->id,
2093  list, list->refcount);
2094 }
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(elevel,...)
Definition: elog.h:232
int refcount
Definition: catcache.h:172

◆ ReleaseCatCache()

void ReleaseCatCache ( HeapTuple  tuple)

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

1443 {
1444  CatCTup *ct = (CatCTup *) (((char *) tuple) -
1445  offsetof(CatCTup, tuple));
1446 
1447  /* Safety checks to ensure we were handed a cache entry */
1448  Assert(ct->ct_magic == CT_MAGIC);
1449  Assert(ct->refcount > 0);
1450 
1451  ct->refcount--;
1453 
1454  if (
1455 #ifndef CATCACHE_FORCE_RELEASE
1456  ct->dead &&
1457 #endif
1458  ct->refcount == 0 &&
1459  (ct->c_list == NULL || ct->c_list->refcount == 0))
1460  CatCacheRemoveCTup(ct->my_cache, ct);
1461 }
CatCache * my_cache
Definition: catcache.h:132
#define CT_MAGIC
Definition: catcache.h:89
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
void ResourceOwnerForgetCatCacheRef(ResourceOwner owner, HeapTuple tuple)
Definition: resowner.c:1055
struct catclist * c_list
Definition: catcache.h:130
static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
Definition: catcache.c:457
#define Assert(condition)
Definition: c.h:804
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:727
int ct_magic
Definition: catcache.h:88
bool dead
Definition: catcache.h:119

◆ ReleaseCatCacheList()

void ReleaseCatCacheList ( CatCList list)

Definition at line 1784 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(), opclass_for_family_datatype(), RenameEnumLabel(), ResourceOwnerReleaseInternal(), sepgsql_relation_drop(), spgvalidate(), and transformFrameOffset().

1785 {
1786  /* Safety checks to ensure we were handed a cache entry */
1787  Assert(list->cl_magic == CL_MAGIC);
1788  Assert(list->refcount > 0);
1789  list->refcount--;
1791 
1792  if (
1793 #ifndef CATCACHE_FORCE_RELEASE
1794  list->dead &&
1795 #endif
1796  list->refcount == 0)
1797  CatCacheRemoveCList(list->my_cache, list);
1798 }
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
int cl_magic
Definition: catcache.h:159
bool dead
Definition: catcache.h:173
static void CatCacheRemoveCList(CatCache *cache, CatCList *cl)
Definition: catcache.c:499
#define CL_MAGIC
Definition: catcache.h:160
CatCache * my_cache
Definition: catcache.h:177
void ResourceOwnerForgetCatCacheListRef(ResourceOwner owner, CatCList *list)
Definition: resowner.c:1090
#define Assert(condition)
Definition: c.h:804
int refcount
Definition: catcache.h:172

◆ ResetCatalogCaches()

void ResetCatalogCaches ( void  )

Definition at line 689 of file catcache.c.

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

Referenced by InvalidateSystemCaches().

690 {
691  slist_iter iter;
692 
693  CACHE_elog(DEBUG2, "ResetCatalogCaches called");
694 
696  {
697  CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
698 
699  ResetCatalogCache(cache);
700  }
701 
702  CACHE_elog(DEBUG2, "end of ResetCatalogCaches call");
703 }
static void ResetCatalogCache(CatCache *cache)
Definition: catcache.c:642
static CatCacheHeader * CacheHdr
Definition: catcache.c:64
slist_node * cur
Definition: ilist.h:226
#define DEBUG2
Definition: elog.h:24
#define slist_container(type, membername, ptr)
Definition: ilist.h:693
slist_head ch_caches
Definition: catcache.h:184
#define CACHE_elog(...)
Definition: catcache.c:60
#define slist_foreach(iter, lhead)
Definition: ilist.h:719

◆ SearchCatCache()

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

Definition at line 1149 of file catcache.c.

References catcache::cc_nkeys, and SearchCatCacheInternal().

Referenced by SearchSysCache().

1154 {
1155  return SearchCatCacheInternal(cache, cache->cc_nkeys, v1, v2, v3, v4);
1156 }
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:1200

◆ SearchCatCache1()

HeapTuple SearchCatCache1 ( CatCache cache,
Datum  v1 
)

Definition at line 1166 of file catcache.c.

References SearchCatCacheInternal().

Referenced by SearchSysCache1().

1168 {
1169  return SearchCatCacheInternal(cache, 1, v1, 0, 0, 0);
1170 }
static HeapTuple SearchCatCacheInternal(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1200

◆ SearchCatCache2()

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

Definition at line 1174 of file catcache.c.

References SearchCatCacheInternal().

Referenced by SearchSysCache2().

1176 {
1177  return SearchCatCacheInternal(cache, 2, v1, v2, 0, 0);
1178 }
static HeapTuple SearchCatCacheInternal(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1200

◆ SearchCatCache3()

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

Definition at line 1182 of file catcache.c.

References SearchCatCacheInternal().

Referenced by SearchSysCache3().

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

◆ SearchCatCache4()

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

Definition at line 1190 of file catcache.c.

References SearchCatCacheInternal().

Referenced by SearchSysCache4().

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

◆ SearchCatCacheList()

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

Definition at line 1508 of file catcache.c.

References AccessShareLock, Assert, catctup::c_list, catclist::cache_elem, CACHE_elog, 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, 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, table_close(), table_open(), and catctup::tuple.

Referenced by SearchSysCacheList().

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

Variable Documentation

◆ CacheMemoryContext

PGDLLIMPORT MemoryContext CacheMemoryContext

Definition at line 51 of file mcxt.c.