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:64
static void ResetCatalogCache(CatCache *cache)
Definition: catcache.c:636
#define CACHE_elog(...)
Definition: catcache.c:60
#define DEBUG2
Definition: elog.h:29
#define slist_container(type, membername, ptr)
Definition: ilist.h:1106
#define slist_foreach(iter, lhead)
Definition: ilist.h:1132
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:259

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:598
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:50
#define dlist_foreach_modify(iter, lhead)
Definition: ilist.h:640
#define dlist_container(type, membername, ptr)
Definition: ilist.h:593
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:200

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:141
MemoryContext CacheMemoryContext
Definition: mcxt.c:144
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:153

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CacheMemoryContext, and TopMemoryContext.

Referenced by assign_record_type_typmod(), BuildEventTriggerCache(), init_ts_config_cache(), InitCatCache(), InitializeAttoptCache(), InitializeRelfilenumberMap(), 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 1467 of file catcache.c.

1472 {
1473  /*
1474  * one-time startup overhead for each cache
1475  */
1476  if (cache->cc_tupdesc == NULL)
1478 
1479  /*
1480  * calculate the hash value
1481  */
1482  return CatalogCacheComputeHashValue(cache, cache->cc_nkeys, v1, v2, v3, v4);
1483 }
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:916
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  int i;
767 
768  /*
769  * nbuckets is the initial number of hash buckets to use in this catcache.
770  * It will be enlarged later if it becomes too full.
771  *
772  * nbuckets must be a power of two. We check this via Assert rather than
773  * a full runtime check because the values will be coming from constant
774  * tables.
775  *
776  * If you're confused by the power-of-two check, see comments in
777  * bitmapset.c for an explanation.
778  */
779  Assert(nbuckets > 0 && (nbuckets & -nbuckets) == nbuckets);
780 
781  /*
782  * first switch to the cache context so our allocations do not vanish at
783  * the end of a transaction
784  */
785  if (!CacheMemoryContext)
787 
789 
790  /*
791  * if first time through, initialize the cache group header
792  */
793  if (CacheHdr == NULL)
794  {
797  CacheHdr->ch_ntup = 0;
798 #ifdef CATCACHE_STATS
799  /* set up to dump stats at backend exit */
800  on_proc_exit(CatCachePrintStats, 0);
801 #endif
802  }
803 
804  /*
805  * Allocate a new cache structure, aligning to a cacheline boundary
806  *
807  * Note: we rely on zeroing to initialize all the dlist headers correctly
808  */
811  cp->cc_bucket = palloc0(nbuckets * sizeof(dlist_head));
812 
813  /*
814  * initialize the cache's relation information for the relation
815  * corresponding to this cache, and initialize some of the new cache's
816  * other internal fields. But don't open the relation yet.
817  */
818  cp->id = id;
819  cp->cc_relname = "(not known yet)";
820  cp->cc_reloid = reloid;
821  cp->cc_indexoid = indexoid;
822  cp->cc_relisshared = false; /* temporary */
823  cp->cc_tupdesc = (TupleDesc) NULL;
824  cp->cc_ntup = 0;
825  cp->cc_nbuckets = nbuckets;
826  cp->cc_nkeys = nkeys;
827  for (i = 0; i < nkeys; ++i)
828  cp->cc_keyno[i] = key[i];
829 
830  /*
831  * new cache is initialized as far as we can go for now. print some
832  * debugging information, if appropriate.
833  */
835 
836  /*
837  * add completed cache to top of group header's list
838  */
840 
841  /*
842  * back to the old context before we return...
843  */
844  MemoryContextSwitchTo(oldcxt);
845 
846  return cp;
847 }
void CreateCacheMemoryContext(void)
Definition: catcache.c:614
#define InitCatCache_DEBUG2
Definition: catcache.c:753
#define MCXT_ALLOC_ZERO
Definition: fe_memutils.h:18
static void slist_init(slist_head *head)
Definition: ilist.h:986
static void slist_push_head(slist_head *head, slist_node *node)
Definition: ilist.h:1006
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:1241
void * palloc_aligned(Size size, Size alignto, int flags)
Definition: mcxt.c:1426
void * palloc(Size size)
Definition: mcxt.c:1210
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:138
#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, 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, MCXT_ALLOC_ZERO, MemoryContextSwitchTo(), on_proc_exit(), palloc(), palloc0(), palloc_aligned(), PG_CACHE_LINE_SIZE, slist_init(), and slist_push_head().

Referenced by InitCatalogCache().

◆ InitCatCachePhase2()

void InitCatCachePhase2 ( CatCache cache,
bool  touch_index 
)

Definition at line 1025 of file catcache.c.

1026 {
1027  if (cache->cc_tupdesc == NULL)
1029 
1030  if (touch_index &&
1031  cache->id != AMOID &&
1032  cache->id != AMNAME)
1033  {
1034  Relation idesc;
1035 
1036  /*
1037  * We must lock the underlying catalog before opening the index to
1038  * avoid deadlock, since index_open could possibly result in reading
1039  * this same catalog, and if anyone else is exclusive-locking this
1040  * catalog and index they'll be doing it in that order.
1041  */
1043  idesc = index_open(cache->cc_indexoid, AccessShareLock);
1044 
1045  /*
1046  * While we've got the index open, let's check that it's unique (and
1047  * not just deferrable-unique, thank you very much). This is just to
1048  * catch thinkos in definitions of new catcaches, so we don't worry
1049  * about the pg_am indexes not getting tested.
1050  */
1051  Assert(idesc->rd_index->indisunique &&
1052  idesc->rd_index->indimmediate);
1053 
1054  index_close(idesc, AccessShareLock);
1056  }
1057 }
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:188
@ 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 2000 of file catcache.c.

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

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

2065 {
2066  CatCTup *ct = (CatCTup *) (((char *) tuple) -
2067  offsetof(CatCTup, tuple));
2068 
2069  /* Safety check to ensure we were handed a cache entry */
2070  Assert(ct->ct_magic == CT_MAGIC);
2071 
2072  elog(WARNING, "cache reference leak: cache %s (%d), tuple %u/%u has count %d",
2073  ct->my_cache->cc_relname, ct->my_cache->id,
2074  ItemPointerGetBlockNumber(&(tuple->t_self)),
2075  ItemPointerGetOffsetNumber(&(tuple->t_self)),
2076  ct->refcount);
2077 }
#define CT_MAGIC
Definition: catcache.h:89
#define WARNING
Definition: elog.h:36
static OffsetNumber ItemPointerGetOffsetNumber(const ItemPointerData *pointer)
Definition: itemptr.h:124
static BlockNumber ItemPointerGetBlockNumber(const ItemPointerData *pointer)
Definition: itemptr.h:103
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, catctup::refcount, HeapTupleData::t_self, and WARNING.

Referenced by ResourceOwnerReleaseInternal().

◆ PrintCatCacheListLeakWarning()

void PrintCatCacheListLeakWarning ( CatCList list)

Definition at line 2080 of file catcache.c.

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

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

Referenced by ResourceOwnerReleaseInternal().

◆ ReleaseCatCache()

void ReleaseCatCache ( HeapTuple  tuple)

Definition at line 1435 of file catcache.c.

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

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

Referenced by ReleaseSysCache(), and ResourceOwnerReleaseInternal().

◆ ReleaseCatCacheList()

void ReleaseCatCacheList ( CatCList list)

Definition at line 1776 of file catcache.c.

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

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

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

References catcache::cc_nkeys, and SearchCatCacheInternal().

Referenced by SearchSysCache().

◆ SearchCatCache1()

HeapTuple SearchCatCache1 ( CatCache cache,
Datum  v1 
)

Definition at line 1159 of file catcache.c.

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

References SearchCatCacheInternal().

Referenced by SearchSysCache1().

◆ SearchCatCache2()

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

Definition at line 1167 of file catcache.c.

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

References SearchCatCacheInternal().

Referenced by SearchSysCache2().

◆ SearchCatCache3()

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

Definition at line 1175 of file catcache.c.

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

References SearchCatCacheInternal().

Referenced by SearchSysCache3().

◆ SearchCatCache4()

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

Definition at line 1183 of file catcache.c.

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

References SearchCatCacheInternal().

Referenced by SearchSysCache4().

◆ SearchCatCacheList()

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

Definition at line 1501 of file catcache.c.

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

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, 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 144 of file mcxt.c.