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:674
void CallSyscacheCallbacks(int cacheid, uint32 hashvalue)
Definition: inval.c:1487
slist_head ch_caches
Definition: catcache.h:184
#define CACHE_elog(...)
Definition: catcache.c:60
#define slist_foreach(iter, lhead)
Definition: ilist.h:700

◆ 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:524
#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:477
#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:475
#define Assert(condition)
Definition: c.h:732
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:170
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
MemoryContext TopMemoryContext
Definition: mcxt.c:44
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ GetCatCacheHashValue()

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

Definition at line 1472 of file catcache.c.

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

Referenced by GetSysCacheHashValue().

1477 {
1478  /*
1479  * one-time startup overhead for each cache
1480  */
1481  if (cache->cc_tupdesc == NULL)
1483 
1484  /*
1485  * calculate the hash value
1486  */
1487  return CatalogCacheComputeHashValue(cache, cache->cc_nkeys, v1, v2, v3, v4);
1488 }
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: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:980
slist_head ch_caches
Definition: catcache.h:184
#define InitCatCache_DEBUG2
Definition: catcache.c:759
#define Assert(condition)
Definition: c.h:732
int cc_nbuckets
Definition: catcache.h:47
#define CACHELINEALIGN(LEN)
Definition: c.h:688
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:949
int i
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ 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:199
#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:143
Oid cc_reloid
Definition: catcache.h:58
TupleDesc cc_tupdesc
Definition: catcache.h:48
#define Assert(condition)
Definition: c.h:732
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:152
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:108
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:126

◆ PrepareToInvalidateCacheTuple()

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

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

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

◆ PrintCatCacheLeakWarning()

void PrintCatCacheLeakWarning ( HeapTuple  tuple)

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

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

◆ PrintCatCacheListLeakWarning()

void PrintCatCacheListLeakWarning ( CatCList list)

Definition at line 2087 of file catcache.c.

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

Referenced by ResourceOwnerReleaseInternal().

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

◆ ReleaseCatCache()

void ReleaseCatCache ( HeapTuple  tuple)

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

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

◆ ReleaseCatCacheList()

void ReleaseCatCacheList ( CatCList list)

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

1783 {
1784  /* Safety checks to ensure we were handed a cache entry */
1785  Assert(list->cl_magic == CL_MAGIC);
1786  Assert(list->refcount > 0);
1787  list->refcount--;
1789 
1790  if (
1791 #ifndef CATCACHE_FORCE_RELEASE
1792  list->dead &&
1793 #endif
1794  list->refcount == 0)
1795  CatCacheRemoveCList(list->my_cache, list);
1796 }
ResourceOwner CurrentResourceOwner
Definition: resowner.c:142
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:1037
#define Assert(condition)
Definition: c.h:732
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:674
slist_head ch_caches
Definition: catcache.h:184
#define CACHE_elog(...)
Definition: catcache.c:60
#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 1147 of file catcache.c.

References catcache::cc_nkeys, and SearchCatCacheInternal().

Referenced by SearchSysCache().

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

◆ SearchCatCache1()

HeapTuple SearchCatCache1 ( CatCache cache,
Datum  v1 
)

Definition at line 1164 of file catcache.c.

References SearchCatCacheInternal().

Referenced by SearchSysCache1().

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

◆ SearchCatCache2()

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

Definition at line 1172 of file catcache.c.

References SearchCatCacheInternal().

Referenced by SearchSysCache2().

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

◆ SearchCatCache3()

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

Definition at line 1180 of file catcache.c.

References SearchCatCacheInternal().

Referenced by SearchSysCache3().

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

◆ SearchCatCache4()

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

Definition at line 1188 of file catcache.c.

References SearchCatCacheInternal().

Referenced by SearchSysCache4().

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

◆ SearchCatCacheList()

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

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

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

Variable Documentation

◆ CacheMemoryContext

PGDLLIMPORT MemoryContext CacheMemoryContext

Definition at line 47 of file mcxt.c.