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.

◆ CL_MAGIC

#define CL_MAGIC   0x52765103

Definition at line 160 of file catcache.h.

◆ CT_MAGIC

#define CT_MAGIC   0x57261502

Definition at line 89 of file catcache.h.

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 713 of file catcache.c.

714 {
715  slist_iter iter;
716 
717  CACHE_elog(DEBUG2, "CatalogCacheFlushCatalog called for %u", catId);
718 
720  {
721  CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
722 
723  /* Does this cache store tuples of the target catalog? */
724  if (cache->cc_reloid == catId)
725  {
726  /* Yes, so flush all its contents */
727  ResetCatalogCache(cache);
728 
729  /* Tell inval.c to call syscache callbacks for this cache */
730  CallSyscacheCallbacks(cache->id, 0);
731  }
732  }
733 
734  CACHE_elog(DEBUG2, "end of CatalogCacheFlushCatalog call");
735 }
static CatCacheHeader * CacheHdr
Definition: catcache.c:65
static void ResetCatalogCache(CatCache *cache)
Definition: catcache.c:636
#define CACHE_elog(...)
Definition: catcache.c:61
#define DEBUG2
Definition: elog.h:23
#define slist_container(type, membername, ptr)
Definition: ilist.h:693
#define slist_foreach(iter, lhead)
Definition: ilist.h:719
void CallSyscacheCallbacks(int cacheid, uint32 hashvalue)
Definition: inval.c:1580
Oid cc_reloid
Definition: catcache.h:58
int id
Definition: catcache.h:46
slist_head ch_caches
Definition: catcache.h:184
slist_node * cur
Definition: ilist.h:226

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

Referenced by LocalExecuteInvalidationMessage().

◆ CatCacheInvalidate()

void CatCacheInvalidate ( CatCache cache,
uint32  hashValue 
)

Definition at line 546 of file catcache.c.

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

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().

◆ CreateCacheMemoryContext()

void CreateCacheMemoryContext ( void  )

Definition at line 614 of file catcache.c.

615 {
616  /*
617  * Purely for paranoia, check that context doesn't exist; caller probably
618  * did so already.
619  */
620  if (!CacheMemoryContext)
622  "CacheMemoryContext",
624 }
MemoryContext TopMemoryContext
Definition: mcxt.c:48
MemoryContext CacheMemoryContext
Definition: mcxt.c:51
#define AllocSetContextCreate
Definition: memutils.h:173
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:197

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().

◆ GetCatCacheHashValue()

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

Definition at line 1468 of file catcache.c.

1473 {
1474  /*
1475  * one-time startup overhead for each cache
1476  */
1477  if (cache->cc_tupdesc == NULL)
1479 
1480  /*
1481  * calculate the hash value
1482  */
1483  return CatalogCacheComputeHashValue(cache, cache->cc_nkeys, v1, v2, v3, v4);
1484 }
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:917
static uint32 CatalogCacheComputeHashValue(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:271
int cc_nkeys
Definition: catcache.h:56
TupleDesc cc_tupdesc
Definition: catcache.h:48

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

Referenced by GetSysCacheHashValue().

◆ InitCatCache()

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

Definition at line 757 of file catcache.c.

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

References Assert(), CacheHdr, 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, sort-test::key, MemoryContextSwitchTo(), on_proc_exit(), palloc(), palloc0(), PG_CACHE_LINE_SIZE, slist_init(), and slist_push_head().

Referenced by InitCatalogCache().

◆ InitCatCachePhase2()

void InitCatCachePhase2 ( CatCache cache,
bool  touch_index 
)

Definition at line 1026 of file catcache.c.

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

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().

◆ PrepareToInvalidateCacheTuple()

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

Definition at line 2001 of file catcache.c.

2005 {
2006  slist_iter iter;
2007  Oid reloid;
2008 
2009  CACHE_elog(DEBUG2, "PrepareToInvalidateCacheTuple: called");
2010 
2011  /*
2012  * sanity checks
2013  */
2014  Assert(RelationIsValid(relation));
2015  Assert(HeapTupleIsValid(tuple));
2016  Assert(PointerIsValid(function));
2017  Assert(CacheHdr != NULL);
2018 
2019  reloid = RelationGetRelid(relation);
2020 
2021  /* ----------------
2022  * for each cache
2023  * if the cache contains tuples from the specified relation
2024  * compute the tuple's hash value(s) in this cache,
2025  * and call the passed function to register the information.
2026  * ----------------
2027  */
2028 
2030  {
2031  CatCache *ccp = slist_container(CatCache, cc_next, iter.cur);
2032  uint32 hashvalue;
2033  Oid dbid;
2034 
2035  if (ccp->cc_reloid != reloid)
2036  continue;
2037 
2038  /* Just in case cache hasn't finished initialization yet... */
2039  if (ccp->cc_tupdesc == NULL)
2041 
2042  hashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, tuple);
2043  dbid = ccp->cc_relisshared ? (Oid) 0 : MyDatabaseId;
2044 
2045  (*function) (ccp->id, hashvalue, dbid);
2046 
2047  if (newtuple)
2048  {
2049  uint32 newhashvalue;
2050 
2051  newhashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, newtuple);
2052 
2053  if (newhashvalue != hashvalue)
2054  (*function) (ccp->id, newhashvalue, dbid);
2055  }
2056  }
2057 }
unsigned int uint32
Definition: c.h:452
#define PointerIsValid(pointer)
Definition: c.h:709
static uint32 CatalogCacheComputeTupleHashValue(CatCache *cache, int nkeys, HeapTuple tuple)
Definition: catcache.c:313
Oid MyDatabaseId
Definition: globals.c:89
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
unsigned int Oid
Definition: postgres_ext.h:31
#define RelationGetRelid(relation)
Definition: rel.h:488
#define RelationIsValid(relation)
Definition: rel.h:461

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

◆ PrintCatCacheLeakWarning()

void PrintCatCacheLeakWarning ( HeapTuple  tuple)

Definition at line 2065 of file catcache.c.

2066 {
2067  CatCTup *ct = (CatCTup *) (((char *) tuple) -
2068  offsetof(CatCTup, tuple));
2069 
2070  /* Safety check to ensure we were handed a cache entry */
2071  Assert(ct->ct_magic == CT_MAGIC);
2072 
2073  elog(WARNING, "cache reference leak: cache %s (%d), tuple %u/%u has count %d",
2074  ct->my_cache->cc_relname, ct->my_cache->id,
2075  ItemPointerGetBlockNumber(&(tuple->t_self)),
2076  ItemPointerGetOffsetNumber(&(tuple->t_self)),
2077  ct->refcount);
2078 }
#define offsetof(type, field)
Definition: c.h:738
#define CT_MAGIC
Definition: catcache.h:89
#define WARNING
Definition: elog.h:30
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:98
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:117
int ct_magic
Definition: catcache.h:88
CatCache * my_cache
Definition: catcache.h:132

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

Referenced by ResourceOwnerReleaseInternal().

◆ PrintCatCacheListLeakWarning()

void PrintCatCacheListLeakWarning ( CatCList list)

Definition at line 2081 of file catcache.c.

2082 {
2083  elog(WARNING, "cache reference leak: cache %s (%d), list %p has count %d",
2084  list->my_cache->cc_relname, list->my_cache->id,
2085  list, list->refcount);
2086 }

References elog(), sort-test::list, and WARNING.

Referenced by ResourceOwnerReleaseInternal().

◆ ReleaseCatCache()

void ReleaseCatCache ( HeapTuple  tuple)

Definition at line 1436 of file catcache.c.

1437 {
1438  CatCTup *ct = (CatCTup *) (((char *) tuple) -
1439  offsetof(CatCTup, tuple));
1440 
1441  /* Safety checks to ensure we were handed a cache entry */
1442  Assert(ct->ct_magic == CT_MAGIC);
1443  Assert(ct->refcount > 0);
1444 
1445  ct->refcount--;
1447 
1448  if (
1449 #ifndef CATCACHE_FORCE_RELEASE
1450  ct->dead &&
1451 #endif
1452  ct->refcount == 0 &&
1453  (ct->c_list == NULL || ct->c_list->refcount == 0))
1454  CatCacheRemoveCTup(ct->my_cache, ct);
1455 }
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
void ResourceOwnerForgetCatCacheRef(ResourceOwner owner, HeapTuple tuple)
Definition: resowner.c:1054
HeapTupleData tuple
Definition: catcache.h:121

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().

◆ ReleaseCatCacheList()

void ReleaseCatCacheList ( CatCList list)

Definition at line 1777 of file catcache.c.

1778 {
1779  /* Safety checks to ensure we were handed a cache entry */
1780  Assert(list->cl_magic == CL_MAGIC);
1781  Assert(list->refcount > 0);
1782  list->refcount--;
1784 
1785  if (
1786 #ifndef CATCACHE_FORCE_RELEASE
1787  list->dead &&
1788 #endif
1789  list->refcount == 0)
1790  CatCacheRemoveCList(list->my_cache, list);
1791 }
#define CL_MAGIC
Definition: catcache.h:160
void ResourceOwnerForgetCatCacheListRef(ResourceOwner owner, CatCList *list)
Definition: resowner.c:1089

References Assert(), CatCacheRemoveCList(), CL_MAGIC, CurrentResourceOwner, sort-test::list, and ResourceOwnerForgetCatCacheListRef().

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

◆ ResetCatalogCaches()

void ResetCatalogCaches ( void  )

Definition at line 683 of file catcache.c.

684 {
685  slist_iter iter;
686 
687  CACHE_elog(DEBUG2, "ResetCatalogCaches called");
688 
690  {
691  CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
692 
693  ResetCatalogCache(cache);
694  }
695 
696  CACHE_elog(DEBUG2, "end of ResetCatalogCaches call");
697 }

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

Referenced by InvalidateSystemCachesExtended().

◆ SearchCatCache()

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

Definition at line 1143 of file catcache.c.

1148 {
1149  return SearchCatCacheInternal(cache, cache->cc_nkeys, v1, v2, v3, v4);
1150 }
static HeapTuple SearchCatCacheInternal(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1194

References catcache::cc_nkeys, and SearchCatCacheInternal().

Referenced by SearchSysCache().

◆ SearchCatCache1()

HeapTuple SearchCatCache1 ( CatCache cache,
Datum  v1 
)

Definition at line 1160 of file catcache.c.

1162 {
1163  return SearchCatCacheInternal(cache, 1, v1, 0, 0, 0);
1164 }

References SearchCatCacheInternal().

Referenced by SearchSysCache1().

◆ SearchCatCache2()

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

Definition at line 1168 of file catcache.c.

1170 {
1171  return SearchCatCacheInternal(cache, 2, v1, v2, 0, 0);
1172 }

References SearchCatCacheInternal().

Referenced by SearchSysCache2().

◆ SearchCatCache3()

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

Definition at line 1176 of file catcache.c.

1178 {
1179  return SearchCatCacheInternal(cache, 3, v1, v2, v3, 0);
1180 }

References SearchCatCacheInternal().

Referenced by SearchSysCache3().

◆ SearchCatCache4()

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

Definition at line 1184 of file catcache.c.

1186 {
1187  return SearchCatCacheInternal(cache, 4, v1, v2, v3, v4);
1188 }

References SearchCatCacheInternal().

Referenced by SearchSysCache4().

◆ SearchCatCacheList()

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

Definition at line 1502 of file catcache.c.

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

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().

Variable Documentation

◆ CacheMemoryContext

PGDLLIMPORT MemoryContext CacheMemoryContext
extern

Definition at line 51 of file mcxt.c.