PostgreSQL Source Code  git master
catcache.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/heaptoast.h"
#include "access/relscan.h"
#include "access/sysattr.h"
#include "access/table.h"
#include "access/valid.h"
#include "access/xact.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_type.h"
#include "common/hashfn.h"
#include "miscadmin.h"
#include "storage/lmgr.h"
#include "utils/builtins.h"
#include "utils/datum.h"
#include "utils/fmgroids.h"
#include "utils/inval.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "utils/resowner_private.h"
#include "utils/syscache.h"
Include dependency graph for catcache.c:

Go to the source code of this file.

Macros

#define HASH_INDEX(h, sz)   ((Index) ((h) & ((sz) - 1)))
 
#define CACHE_elog(...)
 
#define InitCatCache_DEBUG2
 
#define CatalogCacheInitializeCache_DEBUG1
 
#define CatalogCacheInitializeCache_DEBUG2
 

Functions

static HeapTuple SearchCatCacheInternal (CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
 
static pg_noinline HeapTuple SearchCatCacheMiss (CatCache *cache, int nkeys, uint32 hashValue, Index hashIndex, Datum v1, Datum v2, Datum v3, Datum v4)
 
static uint32 CatalogCacheComputeHashValue (CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
 
static uint32 CatalogCacheComputeTupleHashValue (CatCache *cache, int nkeys, HeapTuple tuple)
 
static bool CatalogCacheCompareTuple (const CatCache *cache, int nkeys, const Datum *cachekeys, const Datum *searchkeys)
 
static void CatCacheRemoveCTup (CatCache *cache, CatCTup *ct)
 
static void CatCacheRemoveCList (CatCache *cache, CatCList *cl)
 
static void CatalogCacheInitializeCache (CatCache *cache)
 
static CatCTupCatalogCacheCreateEntry (CatCache *cache, HeapTuple ntp, Datum *arguments, uint32 hashValue, Index hashIndex, bool negative)
 
static void CatCacheFreeKeys (TupleDesc tupdesc, int nkeys, int *attnos, Datum *keys)
 
static void CatCacheCopyKeys (TupleDesc tupdesc, int nkeys, int *attnos, Datum *srckeys, Datum *dstkeys)
 
static bool chareqfast (Datum a, Datum b)
 
static uint32 charhashfast (Datum datum)
 
static bool nameeqfast (Datum a, Datum b)
 
static uint32 namehashfast (Datum datum)
 
static bool int2eqfast (Datum a, Datum b)
 
static uint32 int2hashfast (Datum datum)
 
static bool int4eqfast (Datum a, Datum b)
 
static uint32 int4hashfast (Datum datum)
 
static bool texteqfast (Datum a, Datum b)
 
static uint32 texthashfast (Datum datum)
 
static bool oidvectoreqfast (Datum a, Datum b)
 
static uint32 oidvectorhashfast (Datum datum)
 
static void GetCCHashEqFuncs (Oid keytype, CCHashFN *hashfunc, RegProcedure *eqfunc, CCFastEqualFN *fasteqfunc)
 
void CatCacheInvalidate (CatCache *cache, uint32 hashValue)
 
void CreateCacheMemoryContext (void)
 
static void ResetCatalogCache (CatCache *cache)
 
void ResetCatalogCaches (void)
 
void CatalogCacheFlushCatalog (Oid catId)
 
CatCacheInitCatCache (int id, Oid reloid, Oid indexoid, int nkeys, const int *key, int nbuckets)
 
static void RehashCatCache (CatCache *cp)
 
void InitCatCachePhase2 (CatCache *cache, bool touch_index)
 
static bool IndexScanOK (CatCache *cache, ScanKey cur_skey)
 
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 PrepareToInvalidateCacheTuple (Relation relation, HeapTuple tuple, HeapTuple newtuple, void(*function)(int, uint32, Oid))
 
void PrintCatCacheLeakWarning (HeapTuple tuple)
 
void PrintCatCacheListLeakWarning (CatCList *list)
 

Variables

static CatCacheHeaderCacheHdr = NULL
 

Macro Definition Documentation

◆ CACHE_elog

◆ CatalogCacheInitializeCache_DEBUG1

#define CatalogCacheInitializeCache_DEBUG1

Definition at line 918 of file catcache.c.

Referenced by CatalogCacheInitializeCache().

◆ CatalogCacheInitializeCache_DEBUG2

#define CatalogCacheInitializeCache_DEBUG2

Definition at line 919 of file catcache.c.

Referenced by CatalogCacheInitializeCache().

◆ HASH_INDEX

#define HASH_INDEX (   h,
  sz 
)    ((Index) ((h) & ((sz) - 1)))

◆ InitCatCache_DEBUG2

#define InitCatCache_DEBUG2

Definition at line 759 of file catcache.c.

Referenced by InitCatCache().

Function Documentation

◆ CatalogCacheCompareTuple()

static bool CatalogCacheCompareTuple ( const CatCache cache,
int  nkeys,
const Datum cachekeys,
const Datum searchkeys 
)
inlinestatic

Definition at line 374 of file catcache.c.

References arg, catcache::cc_fastequal, catcache::cc_indexoid, catcache::cc_ntup, catcache::cc_relname, catcacheheader::ch_caches, catcacheheader::ch_ntup, slist_iter::cur, DEBUG2, elog, i, slist_container, and slist_foreach.

Referenced by SearchCatCacheInternal(), and SearchCatCacheList().

377 {
378  const CCFastEqualFN *cc_fastequal = cache->cc_fastequal;
379  int i;
380 
381  for (i = 0; i < nkeys; i++)
382  {
383  if (!(cc_fastequal[i]) (cachekeys[i], searchkeys[i]))
384  return false;
385  }
386  return true;
387 }
CCFastEqualFN cc_fastequal[CATCACHE_MAXKEYS]
Definition: catcache.h:51
int i
bool(* CCFastEqualFN)(Datum a, Datum b)
Definition: catcache.h:42

◆ CatalogCacheComputeHashValue()

static uint32 CatalogCacheComputeHashValue ( CatCache cache,
int  nkeys,
Datum  v1,
Datum  v2,
Datum  v3,
Datum  v4 
)
static

Definition at line 270 of file catcache.c.

References CACHE_elog, catcache::cc_hashfunc, catcache::cc_relname, DEBUG2, elog, and FATAL.

Referenced by CatalogCacheComputeTupleHashValue(), GetCatCacheHashValue(), SearchCatCacheInternal(), and SearchCatCacheList().

272 {
273  uint32 hashValue = 0;
274  uint32 oneHash;
275  CCHashFN *cc_hashfunc = cache->cc_hashfunc;
276 
277  CACHE_elog(DEBUG2, "CatalogCacheComputeHashValue %s %d %p",
278  cache->cc_relname, nkeys, cache);
279 
280  switch (nkeys)
281  {
282  case 4:
283  oneHash = (cc_hashfunc[3]) (v4);
284 
285  hashValue ^= oneHash << 24;
286  hashValue ^= oneHash >> 8;
287  /* FALLTHROUGH */
288  case 3:
289  oneHash = (cc_hashfunc[2]) (v3);
290 
291  hashValue ^= oneHash << 16;
292  hashValue ^= oneHash >> 16;
293  /* FALLTHROUGH */
294  case 2:
295  oneHash = (cc_hashfunc[1]) (v2);
296 
297  hashValue ^= oneHash << 8;
298  hashValue ^= oneHash >> 24;
299  /* FALLTHROUGH */
300  case 1:
301  oneHash = (cc_hashfunc[0]) (v1);
302 
303  hashValue ^= oneHash;
304  break;
305  default:
306  elog(FATAL, "wrong number of hash keys: %d", nkeys);
307  break;
308  }
309 
310  return hashValue;
311 }
CCHashFN cc_hashfunc[CATCACHE_MAXKEYS]
Definition: catcache.h:50
#define FATAL
Definition: elog.h:49
#define DEBUG2
Definition: elog.h:24
unsigned int uint32
Definition: c.h:441
uint32(* CCHashFN)(Datum datum)
Definition: catcache.h:39
#define CACHE_elog(...)
Definition: catcache.c:60
const char * cc_relname
Definition: catcache.h:57
#define elog(elevel,...)
Definition: elog.h:232

◆ CatalogCacheComputeTupleHashValue()

static uint32 CatalogCacheComputeTupleHashValue ( CatCache cache,
int  nkeys,
HeapTuple  tuple 
)
static

Definition at line 319 of file catcache.c.

References Assert, CatalogCacheComputeHashValue(), catcache::cc_keyno, catcache::cc_tupdesc, elog, fastgetattr, and FATAL.

Referenced by PrepareToInvalidateCacheTuple(), and SearchCatCacheList().

320 {
321  Datum v1 = 0,
322  v2 = 0,
323  v3 = 0,
324  v4 = 0;
325  bool isNull = false;
326  int *cc_keyno = cache->cc_keyno;
327  TupleDesc cc_tupdesc = cache->cc_tupdesc;
328 
329  /* Now extract key fields from tuple, insert into scankey */
330  switch (nkeys)
331  {
332  case 4:
333  v4 = fastgetattr(tuple,
334  cc_keyno[3],
335  cc_tupdesc,
336  &isNull);
337  Assert(!isNull);
338  /* FALLTHROUGH */
339  case 3:
340  v3 = fastgetattr(tuple,
341  cc_keyno[2],
342  cc_tupdesc,
343  &isNull);
344  Assert(!isNull);
345  /* FALLTHROUGH */
346  case 2:
347  v2 = fastgetattr(tuple,
348  cc_keyno[1],
349  cc_tupdesc,
350  &isNull);
351  Assert(!isNull);
352  /* FALLTHROUGH */
353  case 1:
354  v1 = fastgetattr(tuple,
355  cc_keyno[0],
356  cc_tupdesc,
357  &isNull);
358  Assert(!isNull);
359  break;
360  default:
361  elog(FATAL, "wrong number of hash keys: %d", nkeys);
362  break;
363  }
364 
365  return CatalogCacheComputeHashValue(cache, nkeys, v1, v2, v3, v4);
366 }
int cc_keyno[CATCACHE_MAXKEYS]
Definition: catcache.h:53
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:711
#define FATAL
Definition: elog.h:49
TupleDesc cc_tupdesc
Definition: catcache.h:48
uintptr_t Datum
Definition: postgres.h:411
#define Assert(condition)
Definition: c.h:804
static uint32 CatalogCacheComputeHashValue(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:270
#define elog(elevel,...)
Definition: elog.h:232

◆ CatalogCacheCreateEntry()

static CatCTup * CatalogCacheCreateEntry ( CatCache cache,
HeapTuple  ntp,
Datum arguments,
uint32  hashValue,
Index  hashIndex,
bool  negative 
)
static

Definition at line 1807 of file catcache.c.

References Assert, catctup::c_list, catctup::cache_elem, CacheMemoryContext, CatCacheCopyKeys(), catcache::cc_bucket, catcache::cc_keyno, catcache::cc_nbuckets, catcache::cc_nkeys, catcache::cc_ntup, catcache::cc_tupdesc, catcacheheader::ch_ntup, catctup::ct_magic, CT_MAGIC, catctup::dead, dlist_push_head(), catctup::hash_value, heap_freetuple(), heap_getattr, HeapTupleHasExternal, i, catctup::keys, MAXALIGN, MemoryContextSwitchTo(), catctup::my_cache, catctup::negative, palloc(), catctup::refcount, RehashCatCache(), HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, toast_flatten_tuple(), and catctup::tuple.

Referenced by SearchCatCacheList(), and SearchCatCacheMiss().

1810 {
1811  CatCTup *ct;
1812  HeapTuple dtp;
1813  MemoryContext oldcxt;
1814 
1815  /* negative entries have no tuple associated */
1816  if (ntp)
1817  {
1818  int i;
1819 
1820  Assert(!negative);
1821 
1822  /*
1823  * If there are any out-of-line toasted fields in the tuple, expand
1824  * them in-line. This saves cycles during later use of the catcache
1825  * entry, and also protects us against the possibility of the toast
1826  * tuples being freed before we attempt to fetch them, in case of
1827  * something using a slightly stale catcache entry.
1828  */
1829  if (HeapTupleHasExternal(ntp))
1830  dtp = toast_flatten_tuple(ntp, cache->cc_tupdesc);
1831  else
1832  dtp = ntp;
1833 
1834  /* Allocate memory for CatCTup and the cached tuple in one go */
1836 
1837  ct = (CatCTup *) palloc(sizeof(CatCTup) +
1838  MAXIMUM_ALIGNOF + dtp->t_len);
1839  ct->tuple.t_len = dtp->t_len;
1840  ct->tuple.t_self = dtp->t_self;
1841  ct->tuple.t_tableOid = dtp->t_tableOid;
1842  ct->tuple.t_data = (HeapTupleHeader)
1843  MAXALIGN(((char *) ct) + sizeof(CatCTup));
1844  /* copy tuple contents */
1845  memcpy((char *) ct->tuple.t_data,
1846  (const char *) dtp->t_data,
1847  dtp->t_len);
1848  MemoryContextSwitchTo(oldcxt);
1849 
1850  if (dtp != ntp)
1851  heap_freetuple(dtp);
1852 
1853  /* extract keys - they'll point into the tuple if not by-value */
1854  for (i = 0; i < cache->cc_nkeys; i++)
1855  {
1856  Datum atp;
1857  bool isnull;
1858 
1859  atp = heap_getattr(&ct->tuple,
1860  cache->cc_keyno[i],
1861  cache->cc_tupdesc,
1862  &isnull);
1863  Assert(!isnull);
1864  ct->keys[i] = atp;
1865  }
1866  }
1867  else
1868  {
1869  Assert(negative);
1871  ct = (CatCTup *) palloc(sizeof(CatCTup));
1872 
1873  /*
1874  * Store keys - they'll point into separately allocated memory if not
1875  * by-value.
1876  */
1877  CatCacheCopyKeys(cache->cc_tupdesc, cache->cc_nkeys, cache->cc_keyno,
1878  arguments, ct->keys);
1879  MemoryContextSwitchTo(oldcxt);
1880  }
1881 
1882  /*
1883  * Finish initializing the CatCTup header, and add it to the cache's
1884  * linked list and counts.
1885  */
1886  ct->ct_magic = CT_MAGIC;
1887  ct->my_cache = cache;
1888  ct->c_list = NULL;
1889  ct->refcount = 0; /* for the moment */
1890  ct->dead = false;
1891  ct->negative = negative;
1892  ct->hash_value = hashValue;
1893 
1894  dlist_push_head(&cache->cc_bucket[hashIndex], &ct->cache_elem);
1895 
1896  cache->cc_ntup++;
1897  CacheHdr->ch_ntup++;
1898 
1899  /*
1900  * If the hash table has become too full, enlarge the buckets array. Quite
1901  * arbitrarily, we enlarge when fill factor > 2.
1902  */
1903  if (cache->cc_ntup > cache->cc_nbuckets * 2)
1904  RehashCatCache(cache);
1905 
1906  return ct;
1907 }
int cc_keyno[CATCACHE_MAXKEYS]
Definition: catcache.h:53
uint32 hash_value
Definition: catcache.h:91
CatCache * my_cache
Definition: catcache.h:132
static CatCacheHeader * CacheHdr
Definition: catcache.c:64
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:300
#define CT_MAGIC
Definition: catcache.h:89
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
dlist_head * cc_bucket
Definition: catcache.h:49
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
Datum keys[CATCACHE_MAXKEYS]
Definition: catcache.h:97
struct catclist * c_list
Definition: catcache.h:130
static void CatCacheCopyKeys(TupleDesc tupdesc, int nkeys, int *attnos, Datum *srckeys, Datum *dstkeys)
Definition: catcache.c:1938
HeapTupleHeader t_data
Definition: htup.h:68
static void RehashCatCache(CatCache *cp)
Definition: catcache.c:860
int cc_nkeys
Definition: catcache.h:56
ItemPointerData t_self
Definition: htup.h:65
TupleDesc cc_tupdesc
Definition: catcache.h:48
int cc_ntup
Definition: catcache.h:55
HeapTuple toast_flatten_tuple(HeapTuple tup, TupleDesc tupleDesc)
Definition: heaptoast.c:350
uint32 t_len
Definition: htup.h:64
Oid t_tableOid
Definition: htup.h:66
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:761
uintptr_t Datum
Definition: postgres.h:411
#define Assert(condition)
Definition: c.h:804
int cc_nbuckets
Definition: catcache.h:47
int refcount
Definition: catcache.h:118
#define MAXALIGN(LEN)
Definition: c.h:757
dlist_node cache_elem
Definition: catcache.h:104
bool negative
Definition: catcache.h:120
#define HeapTupleHasExternal(tuple)
Definition: htup_details.h:672
void * palloc(Size size)
Definition: mcxt.c:1062
int i
HeapTupleData tuple
Definition: catcache.h:121
int ct_magic
Definition: catcache.h:88
bool dead
Definition: catcache.h:119
MemoryContext CacheMemoryContext
Definition: mcxt.c:51

◆ CatalogCacheFlushCatalog()

void CatalogCacheFlushCatalog ( Oid  catId)

Definition at line 719 of file catcache.c.

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

Referenced by LocalExecuteInvalidationMessage().

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

◆ CatalogCacheInitializeCache()

static void CatalogCacheInitializeCache ( CatCache cache)
static

Definition at line 923 of file catcache.c.

References AccessShareLock, Assert, BTEqualStrategyNumber, CACHE_elog, CacheMemoryContext, CatalogCacheInitializeCache_DEBUG1, CatalogCacheInitializeCache_DEBUG2, catcache::cc_fastequal, catcache::cc_hashfunc, catcache::cc_keyno, catcache::cc_nkeys, catcache::cc_relisshared, catcache::cc_relname, catcache::cc_reloid, catcache::cc_skey, catcache::cc_tupdesc, CreateTupleDescCopyConstr(), DEBUG2, elog, FATAL, fmgr_info_cxt(), GetCCHashEqFuncs(), i, InvalidOid, MemoryContextSwitchTo(), pstrdup(), RelationGetDescr, RelationGetForm, RelationGetRelationName, ScanKeyData::sk_attno, ScanKeyData::sk_collation, ScanKeyData::sk_func, ScanKeyData::sk_strategy, ScanKeyData::sk_subtype, table_close(), table_open(), and TupleDescAttr.

Referenced by GetCatCacheHashValue(), InitCatCachePhase2(), PrepareToInvalidateCacheTuple(), SearchCatCacheInternal(), and SearchCatCacheList().

924 {
925  Relation relation;
926  MemoryContext oldcxt;
927  TupleDesc tupdesc;
928  int i;
929 
931 
932  relation = table_open(cache->cc_reloid, AccessShareLock);
933 
934  /*
935  * switch to the cache context so our allocations do not vanish at the end
936  * of a transaction
937  */
938  Assert(CacheMemoryContext != NULL);
939 
941 
942  /*
943  * copy the relcache's tuple descriptor to permanent cache storage
944  */
945  tupdesc = CreateTupleDescCopyConstr(RelationGetDescr(relation));
946 
947  /*
948  * save the relation's name and relisshared flag, too (cc_relname is used
949  * only for debugging purposes)
950  */
951  cache->cc_relname = pstrdup(RelationGetRelationName(relation));
952  cache->cc_relisshared = RelationGetForm(relation)->relisshared;
953 
954  /*
955  * return to the caller's memory context and close the rel
956  */
957  MemoryContextSwitchTo(oldcxt);
958 
959  table_close(relation, AccessShareLock);
960 
961  CACHE_elog(DEBUG2, "CatalogCacheInitializeCache: %s, %d keys",
962  cache->cc_relname, cache->cc_nkeys);
963 
964  /*
965  * initialize cache's key information
966  */
967  for (i = 0; i < cache->cc_nkeys; ++i)
968  {
969  Oid keytype;
970  RegProcedure eqfunc;
971 
973 
974  if (cache->cc_keyno[i] > 0)
975  {
976  Form_pg_attribute attr = TupleDescAttr(tupdesc,
977  cache->cc_keyno[i] - 1);
978 
979  keytype = attr->atttypid;
980  /* cache key columns should always be NOT NULL */
981  Assert(attr->attnotnull);
982  }
983  else
984  {
985  if (cache->cc_keyno[i] < 0)
986  elog(FATAL, "sys attributes are not supported in caches");
987  keytype = OIDOID;
988  }
989 
990  GetCCHashEqFuncs(keytype,
991  &cache->cc_hashfunc[i],
992  &eqfunc,
993  &cache->cc_fastequal[i]);
994 
995  /*
996  * Do equality-function lookup (we assume this won't need a catalog
997  * lookup for any supported type)
998  */
999  fmgr_info_cxt(eqfunc,
1000  &cache->cc_skey[i].sk_func,
1002 
1003  /* Initialize sk_attno suitably for HeapKeyTest() and heap scans */
1004  cache->cc_skey[i].sk_attno = cache->cc_keyno[i];
1005 
1006  /* Fill in sk_strategy as well --- always standard equality */
1008  cache->cc_skey[i].sk_subtype = InvalidOid;
1009  /* If a catcache key requires a collation, it must be C collation */
1010  cache->cc_skey[i].sk_collation = C_COLLATION_OID;
1011 
1012  CACHE_elog(DEBUG2, "CatalogCacheInitializeCache %s %d %p",
1013  cache->cc_relname, i, cache);
1014  }
1015 
1016  /*
1017  * mark this cache fully initialized
1018  */
1019  cache->cc_tupdesc = tupdesc;
1020 }
int cc_keyno[CATCACHE_MAXKEYS]
Definition: catcache.h:53
Oid sk_subtype
Definition: skey.h:69
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define CatalogCacheInitializeCache_DEBUG1
Definition: catcache.c:918
#define RelationGetDescr(relation)
Definition: rel.h:503
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
CCHashFN cc_hashfunc[CATCACHE_MAXKEYS]
Definition: catcache.h:50
#define RelationGetForm(relation)
Definition: rel.h:471
char * pstrdup(const char *in)
Definition: mcxt.c:1299
regproc RegProcedure
Definition: c.h:585
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
unsigned int Oid
Definition: postgres_ext.h:31
bool cc_relisshared
Definition: catcache.h:60
Oid cc_reloid
Definition: catcache.h:58
int cc_nkeys
Definition: catcache.h:56
#define FATAL
Definition: elog.h:49
StrategyNumber sk_strategy
Definition: skey.h:68
TupleDesc cc_tupdesc
Definition: catcache.h:48
#define DEBUG2
Definition: elog.h:24
FmgrInfo sk_func
Definition: skey.h:71
#define RelationGetRelationName(relation)
Definition: rel.h:511
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
#define CatalogCacheInitializeCache_DEBUG2
Definition: catcache.c:919
TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc)
Definition: tupdesc.c:151
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:136
static void GetCCHashEqFuncs(Oid keytype, CCHashFN *hashfunc, RegProcedure *eqfunc, CCFastEqualFN *fasteqfunc)
Definition: catcache.c:201
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:804
CCFastEqualFN cc_fastequal[CATCACHE_MAXKEYS]
Definition: catcache.h:51
#define CACHE_elog(...)
Definition: catcache.c:60
const char * cc_relname
Definition: catcache.h:57
Oid sk_collation
Definition: skey.h:70
#define elog(elevel,...)
Definition: elog.h:232
int i
ScanKeyData cc_skey[CATCACHE_MAXKEYS]
Definition: catcache.h:62
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31
AttrNumber sk_attno
Definition: skey.h:67
MemoryContext CacheMemoryContext
Definition: mcxt.c:51

◆ CatCacheCopyKeys()

static void CatCacheCopyKeys ( TupleDesc  tupdesc,
int  nkeys,
int *  attnos,
Datum srckeys,
Datum dstkeys 
)
static

Definition at line 1938 of file catcache.c.

References attnum, datumCopy(), DatumGetCString, i, NameGetDatum, namestrcpy(), and TupleDescAttr.

Referenced by CatalogCacheCreateEntry(), and SearchCatCacheList().

1940 {
1941  int i;
1942 
1943  /*
1944  * XXX: memory and lookup performance could possibly be improved by
1945  * storing all keys in one allocation.
1946  */
1947 
1948  for (i = 0; i < nkeys; i++)
1949  {
1950  int attnum = attnos[i];
1951  Form_pg_attribute att = TupleDescAttr(tupdesc, attnum - 1);
1952  Datum src = srckeys[i];
1953  NameData srcname;
1954 
1955  /*
1956  * Must be careful in case the caller passed a C string where a NAME
1957  * is wanted: convert the given argument to a correctly padded NAME.
1958  * Otherwise the memcpy() done by datumCopy() could fall off the end
1959  * of memory.
1960  */
1961  if (att->atttypid == NAMEOID)
1962  {
1963  namestrcpy(&srcname, DatumGetCString(src));
1964  src = NameGetDatum(&srcname);
1965  }
1966 
1967  dstkeys[i] = datumCopy(src,
1968  att->attbyval,
1969  att->attlen);
1970  }
1971 
1972 }
#define NameGetDatum(X)
Definition: postgres.h:639
void namestrcpy(Name name, const char *str)
Definition: name.c:233
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define DatumGetCString(X)
Definition: postgres.h:610
Definition: c.h:675
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:131
uintptr_t Datum
Definition: postgres.h:411
int16 attnum
Definition: pg_attribute.h:83
int i

◆ CatCacheFreeKeys()

static void CatCacheFreeKeys ( TupleDesc  tupdesc,
int  nkeys,
int *  attnos,
Datum keys 
)
static

Definition at line 1913 of file catcache.c.

References Assert, attnum, DatumGetPointer, i, pfree(), and TupleDescAttr.

Referenced by CatCacheRemoveCList(), and CatCacheRemoveCTup().

1914 {
1915  int i;
1916 
1917  for (i = 0; i < nkeys; i++)
1918  {
1919  int attnum = attnos[i];
1920  Form_pg_attribute att;
1921 
1922  /* system attribute are not supported in caches */
1923  Assert(attnum > 0);
1924 
1925  att = TupleDescAttr(tupdesc, attnum - 1);
1926 
1927  if (!att->attbyval)
1928  pfree(DatumGetPointer(keys[i]));
1929  }
1930 }
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
void pfree(void *pointer)
Definition: mcxt.c:1169
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
int16 attnum
Definition: pg_attribute.h:83
#define Assert(condition)
Definition: c.h:804
#define DatumGetPointer(X)
Definition: postgres.h:593
int i

◆ CatCacheInvalidate()

void CatCacheInvalidate ( CatCache cache,
uint32  hashValue 
)

Definition at line 552 of file catcache.c.

References Assert, catctup::c_list, CACHE_elog, CatCacheRemoveCList(), CatCacheRemoveCTup(), catcache::cc_bucket, catcache::cc_lists, catcache::cc_nbuckets, dlist_mutable_iter::cur, catctup::dead, catclist::dead, DEBUG2, dlist_container, dlist_foreach_modify, HASH_INDEX, catctup::hash_value, catctup::refcount, and catclist::refcount.

Referenced by SysCacheInvalidate().

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

◆ CatCacheRemoveCList()

static void CatCacheRemoveCList ( CatCache cache,
CatCList cl 
)
static

Definition at line 499 of file catcache.c.

References Assert, catctup::c_list, catclist::cache_elem, CatCacheFreeKeys(), CatCacheRemoveCTup(), catcache::cc_keyno, catcache::cc_tupdesc, catctup::dead, dlist_delete(), i, catclist::keys, catclist::members, catclist::my_cache, catclist::n_members, catclist::nkeys, pfree(), catctup::refcount, and catclist::refcount.

Referenced by CatCacheInvalidate(), CatCacheRemoveCTup(), ReleaseCatCacheList(), and ResetCatalogCache().

500 {
501  int i;
502 
503  Assert(cl->refcount == 0);
504  Assert(cl->my_cache == cache);
505 
506  /* delink from member tuples */
507  for (i = cl->n_members; --i >= 0;)
508  {
509  CatCTup *ct = cl->members[i];
510 
511  Assert(ct->c_list == cl);
512  ct->c_list = NULL;
513  /* if the member is dead and now has no references, remove it */
514  if (
515 #ifndef CATCACHE_FORCE_RELEASE
516  ct->dead &&
517 #endif
518  ct->refcount == 0)
519  CatCacheRemoveCTup(cache, ct);
520  }
521 
522  /* delink from linked list */
523  dlist_delete(&cl->cache_elem);
524 
525  /* free associated column data */
526  CatCacheFreeKeys(cache->cc_tupdesc, cl->nkeys,
527  cache->cc_keyno, cl->keys);
528 
529  pfree(cl);
530 }
int cc_keyno[CATCACHE_MAXKEYS]
Definition: catcache.h:53
int n_members
Definition: catcache.h:176
Datum keys[CATCACHE_MAXKEYS]
Definition: catcache.h:170
short nkeys
Definition: catcache.h:175
struct catclist * c_list
Definition: catcache.h:130
CatCTup * members[FLEXIBLE_ARRAY_MEMBER]
Definition: catcache.h:178
void pfree(void *pointer)
Definition: mcxt.c:1169
TupleDesc cc_tupdesc
Definition: catcache.h:48
static void dlist_delete(dlist_node *node)
Definition: ilist.h:358
dlist_node cache_elem
Definition: catcache.h:164
static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
Definition: catcache.c:457
CatCache * my_cache
Definition: catcache.h:177
#define Assert(condition)
Definition: c.h:804
int refcount
Definition: catcache.h:118
int i
int refcount
Definition: catcache.h:172
static void CatCacheFreeKeys(TupleDesc tupdesc, int nkeys, int *attnos, Datum *keys)
Definition: catcache.c:1913
bool dead
Definition: catcache.h:119

◆ CatCacheRemoveCTup()

static void CatCacheRemoveCTup ( CatCache cache,
CatCTup ct 
)
static

Definition at line 457 of file catcache.c.

References Assert, catctup::c_list, catctup::cache_elem, CatCacheFreeKeys(), CatCacheRemoveCList(), catcache::cc_keyno, catcache::cc_nkeys, catcache::cc_ntup, catcache::cc_tupdesc, catcacheheader::ch_ntup, catctup::dead, dlist_delete(), catctup::keys, catctup::my_cache, catctup::negative, pfree(), and catctup::refcount.

Referenced by CatCacheInvalidate(), CatCacheRemoveCList(), ReleaseCatCache(), ResetCatalogCache(), and SearchCatCacheList().

458 {
459  Assert(ct->refcount == 0);
460  Assert(ct->my_cache == cache);
461 
462  if (ct->c_list)
463  {
464  /*
465  * The cleanest way to handle this is to call CatCacheRemoveCList,
466  * which will recurse back to me, and the recursive call will do the
467  * work. Set the "dead" flag to make sure it does recurse.
468  */
469  ct->dead = true;
470  CatCacheRemoveCList(cache, ct->c_list);
471  return; /* nothing left to do */
472  }
473 
474  /* delink from linked list */
475  dlist_delete(&ct->cache_elem);
476 
477  /*
478  * Free keys when we're dealing with a negative entry, normal entries just
479  * point into tuple, allocated together with the CatCTup.
480  */
481  if (ct->negative)
482  CatCacheFreeKeys(cache->cc_tupdesc, cache->cc_nkeys,
483  cache->cc_keyno, ct->keys);
484 
485  pfree(ct);
486 
487  --cache->cc_ntup;
488  --CacheHdr->ch_ntup;
489 }
int cc_keyno[CATCACHE_MAXKEYS]
Definition: catcache.h:53
CatCache * my_cache
Definition: catcache.h:132
static CatCacheHeader * CacheHdr
Definition: catcache.c:64
Datum keys[CATCACHE_MAXKEYS]
Definition: catcache.h:97
struct catclist * c_list
Definition: catcache.h:130
void pfree(void *pointer)
Definition: mcxt.c:1169
int cc_nkeys
Definition: catcache.h:56
TupleDesc cc_tupdesc
Definition: catcache.h:48
int cc_ntup
Definition: catcache.h:55
static void dlist_delete(dlist_node *node)
Definition: ilist.h:358
static void CatCacheRemoveCList(CatCache *cache, CatCList *cl)
Definition: catcache.c:499
#define Assert(condition)
Definition: c.h:804
int refcount
Definition: catcache.h:118
dlist_node cache_elem
Definition: catcache.h:104
bool negative
Definition: catcache.h:120
static void CatCacheFreeKeys(TupleDesc tupdesc, int nkeys, int *attnos, Datum *keys)
Definition: catcache.c:1913
bool dead
Definition: catcache.h:119

◆ chareqfast()

static bool chareqfast ( Datum  a,
Datum  b 
)
static

Definition at line 118 of file catcache.c.

References DatumGetChar.

Referenced by GetCCHashEqFuncs().

119 {
120  return DatumGetChar(a) == DatumGetChar(b);
121 }
#define DatumGetChar(X)
Definition: postgres.h:453

◆ charhashfast()

static uint32 charhashfast ( Datum  datum)
static

Definition at line 124 of file catcache.c.

References DatumGetChar, and murmurhash32().

Referenced by GetCCHashEqFuncs().

125 {
126  return murmurhash32((int32) DatumGetChar(datum));
127 }
static uint32 murmurhash32(uint32 data)
Definition: hashfn.h:92
signed int int32
Definition: c.h:429
#define DatumGetChar(X)
Definition: postgres.h:453

◆ CreateCacheMemoryContext()

void CreateCacheMemoryContext ( void  )

Definition at line 620 of file catcache.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CacheMemoryContext, and TopMemoryContext.

Referenced by assign_record_type_typmod(), BuildEventTriggerCache(), init_ts_config_cache(), InitCatCache(), InitializeAttoptCache(), InitializeRelfilenodeMap(), InitializeTableSpaceCache(), lookup_ts_dictionary_cache(), lookup_ts_parser_cache(), lookup_type_cache(), LookupOpclassInfo(), RelationBuildLocalRelation(), and RelationCacheInitialize().

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

◆ GetCatCacheHashValue()

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

Definition at line 1474 of file catcache.c.

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

Referenced by GetSysCacheHashValue().

1479 {
1480  /*
1481  * one-time startup overhead for each cache
1482  */
1483  if (cache->cc_tupdesc == NULL)
1485 
1486  /*
1487  * calculate the hash value
1488  */
1489  return CatalogCacheComputeHashValue(cache, cache->cc_nkeys, v1, v2, v3, v4);
1490 }
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:923
int cc_nkeys
Definition: catcache.h:56
TupleDesc cc_tupdesc
Definition: catcache.h:48
static uint32 CatalogCacheComputeHashValue(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:270

◆ GetCCHashEqFuncs()

static void GetCCHashEqFuncs ( Oid  keytype,
CCHashFN hashfunc,
RegProcedure eqfunc,
CCFastEqualFN fasteqfunc 
)
static

Definition at line 201 of file catcache.c.

References chareqfast(), charhashfast(), elog, FATAL, int2eqfast(), int2hashfast(), int4eqfast(), int4hashfast(), InvalidOid, nameeqfast(), namehashfast(), oidvectoreqfast(), oidvectorhashfast(), texteqfast(), and texthashfast().

Referenced by CatalogCacheInitializeCache().

202 {
203  switch (keytype)
204  {
205  case BOOLOID:
206  *hashfunc = charhashfast;
207  *fasteqfunc = chareqfast;
208  *eqfunc = F_BOOLEQ;
209  break;
210  case CHAROID:
211  *hashfunc = charhashfast;
212  *fasteqfunc = chareqfast;
213  *eqfunc = F_CHAREQ;
214  break;
215  case NAMEOID:
216  *hashfunc = namehashfast;
217  *fasteqfunc = nameeqfast;
218  *eqfunc = F_NAMEEQ;
219  break;
220  case INT2OID:
221  *hashfunc = int2hashfast;
222  *fasteqfunc = int2eqfast;
223  *eqfunc = F_INT2EQ;
224  break;
225  case INT4OID:
226  *hashfunc = int4hashfast;
227  *fasteqfunc = int4eqfast;
228  *eqfunc = F_INT4EQ;
229  break;
230  case TEXTOID:
231  *hashfunc = texthashfast;
232  *fasteqfunc = texteqfast;
233  *eqfunc = F_TEXTEQ;
234  break;
235  case OIDOID:
236  case REGPROCOID:
237  case REGPROCEDUREOID:
238  case REGOPEROID:
239  case REGOPERATOROID:
240  case REGCLASSOID:
241  case REGTYPEOID:
242  case REGCONFIGOID:
243  case REGDICTIONARYOID:
244  case REGROLEOID:
245  case REGNAMESPACEOID:
246  *hashfunc = int4hashfast;
247  *fasteqfunc = int4eqfast;
248  *eqfunc = F_OIDEQ;
249  break;
250  case OIDVECTOROID:
251  *hashfunc = oidvectorhashfast;
252  *fasteqfunc = oidvectoreqfast;
253  *eqfunc = F_OIDVECTOREQ;
254  break;
255  default:
256  elog(FATAL, "type %u not supported as catcache key", keytype);
257  *hashfunc = NULL; /* keep compiler quiet */
258 
259  *eqfunc = InvalidOid;
260  break;
261  }
262 }
static uint32 namehashfast(Datum datum)
Definition: catcache.c:139
static bool texteqfast(Datum a, Datum b)
Definition: catcache.c:171
static bool nameeqfast(Datum a, Datum b)
Definition: catcache.c:130
#define FATAL
Definition: elog.h:49
static uint32 int2hashfast(Datum datum)
Definition: catcache.c:153
static bool oidvectoreqfast(Datum a, Datum b)
Definition: catcache.c:188
static bool chareqfast(Datum a, Datum b)
Definition: catcache.c:118
static uint32 charhashfast(Datum datum)
Definition: catcache.c:124
#define InvalidOid
Definition: postgres_ext.h:36
static bool int2eqfast(Datum a, Datum b)
Definition: catcache.c:147
static bool int4eqfast(Datum a, Datum b)
Definition: catcache.c:159
#define elog(elevel,...)
Definition: elog.h:232
static uint32 texthashfast(Datum datum)
Definition: catcache.c:181
static uint32 int4hashfast(Datum datum)
Definition: catcache.c:165
static uint32 oidvectorhashfast(Datum datum)
Definition: catcache.c:194

◆ IndexScanOK()

static bool IndexScanOK ( CatCache cache,
ScanKey  cur_skey 
)
static

Definition at line 1084 of file catcache.c.

References AMNAME, AMOID, AUTHMEMMEMROLE, AUTHNAME, AUTHOID, criticalRelcachesBuilt, criticalSharedRelcachesBuilt, DATABASEOID, catcache::id, and INDEXRELID.

Referenced by SearchCatCacheList(), and SearchCatCacheMiss().

1085 {
1086  switch (cache->id)
1087  {
1088  case INDEXRELID:
1089 
1090  /*
1091  * Rather than tracking exactly which indexes have to be loaded
1092  * before we can use indexscans (which changes from time to time),
1093  * just force all pg_index searches to be heap scans until we've
1094  * built the critical relcaches.
1095  */
1097  return false;
1098  break;
1099 
1100  case AMOID:
1101  case AMNAME:
1102 
1103  /*
1104  * Always do heap scans in pg_am, because it's so small there's
1105  * not much point in an indexscan anyway. We *must* do this when
1106  * initially building critical relcache entries, but we might as
1107  * well just always do it.
1108  */
1109  return false;
1110 
1111  case AUTHNAME:
1112  case AUTHOID:
1113  case AUTHMEMMEMROLE:
1114  case DATABASEOID:
1115 
1116  /*
1117  * Protect authentication lookups occurring before relcache has
1118  * collected entries for shared indexes.
1119  */
1121  return false;
1122  break;
1123 
1124  default:
1125  break;
1126  }
1127 
1128  /* Normal case, allow index scan */
1129  return true;
1130 }
Definition: syscache.h:36
int id
Definition: catcache.h:46
bool criticalSharedRelcachesBuilt
Definition: relcache.c:143
bool criticalRelcachesBuilt
Definition: relcache.c:137

◆ InitCatCache()

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

Definition at line 763 of file catcache.c.

References Assert, CACHELINEALIGN, CacheMemoryContext, catcache::cc_bucket, catcache::cc_indexoid, catcache::cc_keyno, catcache::cc_nbuckets, catcache::cc_next, catcache::cc_nkeys, catcache::cc_ntup, catcache::cc_relisshared, catcache::cc_relname, catcache::cc_reloid, catcache::cc_tupdesc, catcacheheader::ch_caches, catcacheheader::ch_ntup, CreateCacheMemoryContext(), i, catcache::id, InitCatCache_DEBUG2, MemoryContextSwitchTo(), on_proc_exit(), palloc(), palloc0(), PG_CACHE_LINE_SIZE, slist_init(), and slist_push_head().

Referenced by InitCatalogCache().

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

◆ InitCatCachePhase2()

void InitCatCachePhase2 ( CatCache cache,
bool  touch_index 
)

Definition at line 1032 of file catcache.c.

References AccessShareLock, AMNAME, AMOID, Assert, CatalogCacheInitializeCache(), catcache::cc_indexoid, catcache::cc_reloid, catcache::cc_tupdesc, catcache::id, index_close(), index_open(), LockRelationOid(), RelationData::rd_index, and UnlockRelationOid().

Referenced by InitCatalogCachePhase2(), and SysCacheGetAttr().

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

◆ int2eqfast()

static bool int2eqfast ( Datum  a,
Datum  b 
)
static

Definition at line 147 of file catcache.c.

References DatumGetInt16.

Referenced by GetCCHashEqFuncs().

148 {
149  return DatumGetInt16(a) == DatumGetInt16(b);
150 }
#define DatumGetInt16(X)
Definition: postgres.h:488

◆ int2hashfast()

static uint32 int2hashfast ( Datum  datum)
static

Definition at line 153 of file catcache.c.

References DatumGetInt16, and murmurhash32().

Referenced by GetCCHashEqFuncs().

154 {
155  return murmurhash32((int32) DatumGetInt16(datum));
156 }
static uint32 murmurhash32(uint32 data)
Definition: hashfn.h:92
signed int int32
Definition: c.h:429
#define DatumGetInt16(X)
Definition: postgres.h:488

◆ int4eqfast()

static bool int4eqfast ( Datum  a,
Datum  b 
)
static

Definition at line 159 of file catcache.c.

References DatumGetInt32.

Referenced by GetCCHashEqFuncs().

160 {
161  return DatumGetInt32(a) == DatumGetInt32(b);
162 }
#define DatumGetInt32(X)
Definition: postgres.h:516

◆ int4hashfast()

static uint32 int4hashfast ( Datum  datum)
static

Definition at line 165 of file catcache.c.

References DatumGetInt32, and murmurhash32().

Referenced by GetCCHashEqFuncs().

166 {
167  return murmurhash32((int32) DatumGetInt32(datum));
168 }
#define DatumGetInt32(X)
Definition: postgres.h:516
static uint32 murmurhash32(uint32 data)
Definition: hashfn.h:92
signed int int32
Definition: c.h:429

◆ nameeqfast()

static bool nameeqfast ( Datum  a,
Datum  b 
)
static

Definition at line 130 of file catcache.c.

References DatumGetName, NAMEDATALEN, and NameStr.

Referenced by GetCCHashEqFuncs().

131 {
132  char *ca = NameStr(*DatumGetName(a));
133  char *cb = NameStr(*DatumGetName(b));
134 
135  return strncmp(ca, cb, NAMEDATALEN) == 0;
136 }
#define NAMEDATALEN
#define DatumGetName(X)
Definition: postgres.h:629
#define NameStr(name)
Definition: c.h:681

◆ namehashfast()

static uint32 namehashfast ( Datum  datum)
static

Definition at line 139 of file catcache.c.

References DatumGetName, hash_any(), sort-test::key, and NameStr.

Referenced by GetCCHashEqFuncs().

140 {
141  char *key = NameStr(*DatumGetName(datum));
142 
143  return hash_any((unsigned char *) key, strlen(key));
144 }
#define DatumGetName(X)
Definition: postgres.h:629
static Datum hash_any(const unsigned char *k, int keylen)
Definition: hashfn.h:31
#define NameStr(name)
Definition: c.h:681

◆ oidvectoreqfast()

static bool oidvectoreqfast ( Datum  a,
Datum  b 
)
static

Definition at line 188 of file catcache.c.

References DatumGetBool, DirectFunctionCall2, and oidvectoreq().

Referenced by GetCCHashEqFuncs().

189 {
191 }
#define DatumGetBool(X)
Definition: postgres.h:437
Datum oidvectoreq(PG_FUNCTION_ARGS)
Definition: oid.c:426
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:628

◆ oidvectorhashfast()

static uint32 oidvectorhashfast ( Datum  datum)
static

Definition at line 194 of file catcache.c.

References DatumGetInt32, DirectFunctionCall1, and hashoidvector().

Referenced by GetCCHashEqFuncs().

195 {
197 }
#define DatumGetInt32(X)
Definition: postgres.h:516
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:626
Datum hashoidvector(PG_FUNCTION_ARGS)
Definition: hashfunc.c:210

◆ PrepareToInvalidateCacheTuple()

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

Definition at line 2009 of file catcache.c.

References Assert, CACHE_elog, CatalogCacheComputeTupleHashValue(), CatalogCacheInitializeCache(), catcache::cc_nkeys, catcache::cc_relisshared, catcache::cc_reloid, catcache::cc_tupdesc, catcacheheader::ch_caches, slist_iter::cur, DEBUG2, HeapTupleIsValid, catcache::id, MyDatabaseId, PointerIsValid, RelationGetRelid, RelationIsValid, slist_container, and slist_foreach.

Referenced by CacheInvalidateHeapTuple().

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

◆ PrintCatCacheLeakWarning()

void PrintCatCacheLeakWarning ( HeapTuple  tuple)

Definition at line 2073 of file catcache.c.

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

Referenced by ResourceOwnerReleaseInternal().

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

◆ PrintCatCacheListLeakWarning()

void PrintCatCacheListLeakWarning ( CatCList list)

Definition at line 2089 of file catcache.c.

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

Referenced by ResourceOwnerReleaseInternal().

2090 {
2091  elog(WARNING, "cache reference leak: cache %s (%d), list %p has count %d",
2092  list->my_cache->cc_relname, list->my_cache->id,
2093  list, list->refcount);
2094 }
int id
Definition: catcache.h:46
#define WARNING
Definition: elog.h:40
CatCache * my_cache
Definition: catcache.h:177
const char * cc_relname
Definition: catcache.h:57
#define elog(elevel,...)
Definition: elog.h:232
int refcount
Definition: catcache.h:172

◆ RehashCatCache()

static void RehashCatCache ( CatCache cp)
static

Definition at line 860 of file catcache.c.

References catctup::cache_elem, CacheMemoryContext, catcache::cc_bucket, catcache::cc_nbuckets, catcache::cc_ntup, catcache::cc_relname, dlist_mutable_iter::cur, DEBUG1, dlist_container, dlist_delete(), dlist_foreach_modify, dlist_push_head(), elog, HASH_INDEX, catctup::hash_value, i, catcache::id, MemoryContextAllocZero(), and pfree().

Referenced by CatalogCacheCreateEntry().

861 {
862  dlist_head *newbucket;
863  int newnbuckets;
864  int i;
865 
866  elog(DEBUG1, "rehashing catalog cache id %d for %s; %d tups, %d buckets",
867  cp->id, cp->cc_relname, cp->cc_ntup, cp->cc_nbuckets);
868 
869  /* Allocate a new, larger, hash table. */
870  newnbuckets = cp->cc_nbuckets * 2;
871  newbucket = (dlist_head *) MemoryContextAllocZero(CacheMemoryContext, newnbuckets * sizeof(dlist_head));
872 
873  /* Move all entries from old hash table to new. */
874  for (i = 0; i < cp->cc_nbuckets; i++)
875  {
876  dlist_mutable_iter iter;
877 
878  dlist_foreach_modify(iter, &cp->cc_bucket[i])
879  {
880  CatCTup *ct = dlist_container(CatCTup, cache_elem, iter.cur);
881  int hashIndex = HASH_INDEX(ct->hash_value, newnbuckets);
882 
883  dlist_delete(iter.cur);
884  dlist_push_head(&newbucket[hashIndex], &ct->cache_elem);
885  }
886  }
887 
888  /* Switch to the new array. */
889  pfree(cp->cc_bucket);
890  cp->cc_nbuckets = newnbuckets;
891  cp->cc_bucket = newbucket;
892 }
#define DEBUG1
Definition: elog.h:25
dlist_node * cur
Definition: ilist.h:180
uint32 hash_value
Definition: catcache.h:91
#define dlist_foreach_modify(iter, lhead)
Definition: ilist.h:543
#define HASH_INDEX(h, sz)
Definition: catcache.c:50
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:300
dlist_head * cc_bucket
Definition: catcache.h:49
int id
Definition: catcache.h:46
#define dlist_container(type, membername, ptr)
Definition: ilist.h:496
void pfree(void *pointer)
Definition: mcxt.c:1169
int cc_ntup
Definition: catcache.h:55
static void dlist_delete(dlist_node *node)
Definition: ilist.h:358
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:906
int cc_nbuckets
Definition: catcache.h:47
const char * cc_relname
Definition: catcache.h:57
dlist_node cache_elem
Definition: catcache.h:104
#define elog(elevel,...)
Definition: elog.h:232
int i
MemoryContext CacheMemoryContext
Definition: mcxt.c:51

◆ ReleaseCatCache()

void ReleaseCatCache ( HeapTuple  tuple)

Definition at line 1442 of file catcache.c.

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

Referenced by ReleaseSysCache(), and ResourceOwnerReleaseInternal().

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

◆ ReleaseCatCacheList()

void ReleaseCatCacheList ( CatCList list)

Definition at line 1784 of file catcache.c.

References Assert, CatCacheRemoveCList(), catclist::cl_magic, CL_MAGIC, CurrentResourceOwner, catclist::dead, catclist::my_cache, catclist::refcount, and ResourceOwnerForgetCatCacheListRef().

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

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

◆ ResetCatalogCache()

static void ResetCatalogCache ( CatCache cache)
static

Definition at line 642 of file catcache.c.

References Assert, catctup::c_list, CatCacheRemoveCList(), CatCacheRemoveCTup(), catcache::cc_bucket, catcache::cc_lists, catcache::cc_nbuckets, dlist_mutable_iter::cur, catctup::dead, catclist::dead, dlist_container, dlist_foreach_modify, i, catctup::refcount, and catclist::refcount.

Referenced by CatalogCacheFlushCatalog(), and ResetCatalogCaches().

643 {
644  dlist_mutable_iter iter;
645  int i;
646 
647  /* Remove each list in this cache, or at least mark it dead */
648  dlist_foreach_modify(iter, &cache->cc_lists)
649  {
650  CatCList *cl = dlist_container(CatCList, cache_elem, iter.cur);
651 
652  if (cl->refcount > 0)
653  cl->dead = true;
654  else
655  CatCacheRemoveCList(cache, cl);
656  }
657 
658  /* Remove each tuple in this cache, or at least mark it dead */
659  for (i = 0; i < cache->cc_nbuckets; i++)
660  {
661  dlist_head *bucket = &cache->cc_bucket[i];
662 
663  dlist_foreach_modify(iter, bucket)
664  {
665  CatCTup *ct = dlist_container(CatCTup, cache_elem, iter.cur);
666 
667  if (ct->refcount > 0 ||
668  (ct->c_list && ct->c_list->refcount > 0))
669  {
670  ct->dead = true;
671  /* list, if any, was marked dead above */
672  Assert(ct->c_list == NULL || ct->c_list->dead);
673  }
674  else
675  CatCacheRemoveCTup(cache, ct);
676 #ifdef CATCACHE_STATS
677  cache->cc_invals++;
678 #endif
679  }
680  }
681 }
dlist_node * cur
Definition: ilist.h:180
#define dlist_foreach_modify(iter, lhead)
Definition: ilist.h:543
dlist_head * cc_bucket
Definition: catcache.h:49
bool dead
Definition: catcache.h:173
dlist_head cc_lists
Definition: catcache.h:54
struct catclist * c_list
Definition: catcache.h:130
#define dlist_container(type, membername, ptr)
Definition: ilist.h:496
static void CatCacheRemoveCList(CatCache *cache, CatCList *cl)
Definition: catcache.c:499
static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
Definition: catcache.c:457
#define Assert(condition)
Definition: c.h:804
int cc_nbuckets
Definition: catcache.h:47
int refcount
Definition: catcache.h:118
int i
int refcount
Definition: catcache.h:172
bool dead
Definition: catcache.h:119

◆ ResetCatalogCaches()

void ResetCatalogCaches ( void  )

Definition at line 689 of file catcache.c.

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

Referenced by InvalidateSystemCaches().

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

◆ SearchCatCache()

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

Definition at line 1149 of file catcache.c.

References catcache::cc_nkeys, and SearchCatCacheInternal().

Referenced by SearchSysCache().

1154 {
1155  return SearchCatCacheInternal(cache, cache->cc_nkeys, v1, v2, v3, v4);
1156 }
int cc_nkeys
Definition: catcache.h:56
static HeapTuple SearchCatCacheInternal(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1200

◆ SearchCatCache1()

HeapTuple SearchCatCache1 ( CatCache cache,
Datum  v1 
)

Definition at line 1166 of file catcache.c.

References SearchCatCacheInternal().

Referenced by SearchSysCache1().

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

◆ SearchCatCache2()

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

Definition at line 1174 of file catcache.c.

References SearchCatCacheInternal().

Referenced by SearchSysCache2().

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

◆ SearchCatCache3()

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

Definition at line 1182 of file catcache.c.

References SearchCatCacheInternal().

Referenced by SearchSysCache3().

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

◆ SearchCatCache4()

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

Definition at line 1190 of file catcache.c.

References SearchCatCacheInternal().

Referenced by SearchSysCache4().

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

◆ SearchCatCacheInternal()

static HeapTuple SearchCatCacheInternal ( CatCache cache,
int  nkeys,
Datum  v1,
Datum  v2,
Datum  v3,
Datum  v4 
)
inlinestatic

Definition at line 1200 of file catcache.c.

References Assert, catctup::cache_elem, CACHE_elog, CatalogCacheCompareTuple(), CatalogCacheComputeHashValue(), CatalogCacheInitializeCache(), CATCACHE_MAXKEYS, catcache::cc_bucket, catcache::cc_nbuckets, catcache::cc_nkeys, catcache::cc_relname, catcache::cc_tupdesc, dlist_iter::cur, CurrentResourceOwner, catctup::dead, DEBUG2, dlist_container, dlist_foreach, dlist_move_head(), HASH_INDEX, catctup::hash_value, IsTransactionState(), catctup::keys, catctup::negative, pg_noinline, catctup::refcount, ResourceOwnerEnlargeCatCacheRefs(), ResourceOwnerRememberCatCacheRef(), SearchCatCacheMiss(), catctup::tuple, and unlikely.

Referenced by SearchCatCache(), SearchCatCache1(), SearchCatCache2(), SearchCatCache3(), and SearchCatCache4().

1206 {
1208  uint32 hashValue;
1209  Index hashIndex;
1210  dlist_iter iter;
1211  dlist_head *bucket;
1212  CatCTup *ct;
1213 
1214  /* Make sure we're in an xact, even if this ends up being a cache hit */
1216 
1217  Assert(cache->cc_nkeys == nkeys);
1218 
1219  /*
1220  * one-time startup overhead for each cache
1221  */
1222  if (unlikely(cache->cc_tupdesc == NULL))
1224 
1225 #ifdef CATCACHE_STATS
1226  cache->cc_searches++;
1227 #endif
1228 
1229  /* Initialize local parameter array */
1230  arguments[0] = v1;
1231  arguments[1] = v2;
1232  arguments[2] = v3;
1233  arguments[3] = v4;
1234 
1235  /*
1236  * find the hash bucket in which to look for the tuple
1237  */
1238  hashValue = CatalogCacheComputeHashValue(cache, nkeys, v1, v2, v3, v4);
1239  hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
1240 
1241  /*
1242  * scan the hash bucket until we find a match or exhaust our tuples
1243  *
1244  * Note: it's okay to use dlist_foreach here, even though we modify the
1245  * dlist within the loop, because we don't continue the loop afterwards.
1246  */
1247  bucket = &cache->cc_bucket[hashIndex];
1248  dlist_foreach(iter, bucket)
1249  {
1250  ct = dlist_container(CatCTup, cache_elem, iter.cur);
1251 
1252  if (ct->dead)
1253  continue; /* ignore dead entries */
1254 
1255  if (ct->hash_value != hashValue)
1256  continue; /* quickly skip entry if wrong hash val */
1257 
1258  if (!CatalogCacheCompareTuple(cache, nkeys, ct->keys, arguments))
1259  continue;
1260 
1261  /*
1262  * We found a match in the cache. Move it to the front of the list
1263  * for its hashbucket, in order to speed subsequent searches. (The
1264  * most frequently accessed elements in any hashbucket will tend to be
1265  * near the front of the hashbucket's list.)
1266  */
1267  dlist_move_head(bucket, &ct->cache_elem);
1268 
1269  /*
1270  * If it's a positive entry, bump its refcount and return it. If it's
1271  * negative, we can report failure to the caller.
1272  */
1273  if (!ct->negative)
1274  {
1276  ct->refcount++;
1278 
1279  CACHE_elog(DEBUG2, "SearchCatCache(%s): found in bucket %d",
1280  cache->cc_relname, hashIndex);
1281 
1282 #ifdef CATCACHE_STATS
1283  cache->cc_hits++;
1284 #endif
1285 
1286  return &ct->tuple;
1287  }
1288  else
1289  {
1290  CACHE_elog(DEBUG2, "SearchCatCache(%s): found neg entry in bucket %d",
1291  cache->cc_relname, hashIndex);
1292 
1293 #ifdef CATCACHE_STATS
1294  cache->cc_neg_hits++;
1295 #endif
1296 
1297  return NULL;
1298  }
1299  }
1300 
1301  return SearchCatCacheMiss(cache, nkeys, hashValue, hashIndex, v1, v2, v3, v4);
1302 }
void ResourceOwnerRememberCatCacheRef(ResourceOwner owner, HeapTuple tuple)
Definition: resowner.c:1046
uint32 hash_value
Definition: catcache.h:91
#define HASH_INDEX(h, sz)
Definition: catcache.c:50
#define dlist_foreach(iter, lhead)
Definition: ilist.h:526
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
static pg_noinline HeapTuple SearchCatCacheMiss(CatCache *cache, int nkeys, uint32 hashValue, Index hashIndex, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1312
dlist_head * cc_bucket
Definition: catcache.h:49
Datum keys[CATCACHE_MAXKEYS]
Definition: catcache.h:97
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:923
#define dlist_container(type, membername, ptr)
Definition: ilist.h:496
#define CATCACHE_MAXKEYS
Definition: catcache.h:35
int cc_nkeys
Definition: catcache.h:56
TupleDesc cc_tupdesc
Definition: catcache.h:48
#define DEBUG2
Definition: elog.h:24
unsigned int uint32
Definition: c.h:441
static bool CatalogCacheCompareTuple(const CatCache *cache, int nkeys, const Datum *cachekeys, const Datum *searchkeys)
Definition: catcache.c:374
uintptr_t Datum
Definition: postgres.h:411
dlist_node * cur
Definition: ilist.h:161
unsigned int Index
Definition: c.h:549
#define Assert(condition)
Definition: c.h:804
int cc_nbuckets
Definition: catcache.h:47
int refcount
Definition: catcache.h:118
#define CACHE_elog(...)
Definition: catcache.c:60
bool IsTransactionState(void)
Definition: xact.c:371
const char * cc_relname
Definition: catcache.h:57
static uint32 CatalogCacheComputeHashValue(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:270
static void dlist_move_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:385
dlist_node cache_elem
Definition: catcache.h:104
bool negative
Definition: catcache.h:120
#define unlikely(x)
Definition: c.h:273
HeapTupleData tuple
Definition: catcache.h:121
void ResourceOwnerEnlargeCatCacheRefs(ResourceOwner owner)
Definition: resowner.c:1035
bool dead
Definition: catcache.h:119

◆ SearchCatCacheList()

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

Definition at line 1508 of file catcache.c.

References AccessShareLock, Assert, catctup::c_list, catclist::cache_elem, CACHE_elog, CacheMemoryContext, CatalogCacheCompareTuple(), CatalogCacheComputeHashValue(), CatalogCacheComputeTupleHashValue(), CatalogCacheCreateEntry(), CatalogCacheInitializeCache(), CATCACHE_MAXKEYS, CatCacheCopyKeys(), CatCacheRemoveCTup(), catcache::cc_bucket, catcache::cc_indexoid, catcache::cc_keyno, catcache::cc_lists, catcache::cc_nbuckets, catcache::cc_nkeys, catcache::cc_relname, catcache::cc_reloid, catcache::cc_skey, catcache::cc_tupdesc, catclist::cl_magic, CL_MAGIC, dlist_iter::cur, CurrentResourceOwner, catctup::dead, catclist::dead, DEBUG2, dlist_container, dlist_foreach, dlist_move_head(), dlist_push_head(), HASH_INDEX, catctup::hash_value, catclist::hash_value, HeapTupleIsValid, i, IndexScanOK(), SysScanDescData::irel, ItemPointerEquals(), catclist::keys, lappend(), lfirst, list_length(), catclist::members, MemoryContextSwitchTo(), catclist::my_cache, catclist::n_members, catctup::negative, NIL, catclist::nkeys, offsetof, catclist::ordered, palloc(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, catctup::refcount, catclist::refcount, ResourceOwnerEnlargeCatCacheListRefs(), ResourceOwnerRememberCatCacheListRef(), ScanKeyData::sk_argument, systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), table_open(), and catctup::tuple.

Referenced by SearchSysCacheList().

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

◆ SearchCatCacheMiss()

static pg_noinline HeapTuple SearchCatCacheMiss ( CatCache cache,
int  nkeys,
uint32  hashValue,
Index  hashIndex,
Datum  v1,
Datum  v2,
Datum  v3,
Datum  v4 
)
static

Definition at line 1312 of file catcache.c.

References AccessShareLock, CACHE_elog, CatalogCacheCreateEntry(), CATCACHE_MAXKEYS, catcache::cc_indexoid, catcache::cc_ntup, catcache::cc_relname, catcache::cc_reloid, catcache::cc_skey, catcacheheader::ch_ntup, CurrentResourceOwner, DEBUG2, HeapTupleIsValid, IndexScanOK(), IsBootstrapProcessingMode, catctup::refcount, ResourceOwnerEnlargeCatCacheRefs(), ResourceOwnerRememberCatCacheRef(), ScanKeyData::sk_argument, systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), and catctup::tuple.

Referenced by SearchCatCacheInternal().

1320 {
1321  ScanKeyData cur_skey[CATCACHE_MAXKEYS];
1322  Relation relation;
1323  SysScanDesc scandesc;
1324  HeapTuple ntp;
1325  CatCTup *ct;
1327 
1328  /* Initialize local parameter array */
1329  arguments[0] = v1;
1330  arguments[1] = v2;
1331  arguments[2] = v3;
1332  arguments[3] = v4;
1333 
1334  /*
1335  * Ok, need to make a lookup in the relation, copy the scankey and fill
1336  * out any per-call fields.
1337  */
1338  memcpy(cur_skey, cache->cc_skey, sizeof(ScanKeyData) * nkeys);
1339  cur_skey[0].sk_argument = v1;
1340  cur_skey[1].sk_argument = v2;
1341  cur_skey[2].sk_argument = v3;
1342  cur_skey[3].sk_argument = v4;
1343 
1344  /*
1345  * Tuple was not found in cache, so we have to try to retrieve it directly
1346  * from the relation. If found, we will add it to the cache; if not
1347  * found, we will add a negative cache entry instead.
1348  *
1349  * NOTE: it is possible for recursive cache lookups to occur while reading
1350  * the relation --- for example, due to shared-cache-inval messages being
1351  * processed during table_open(). This is OK. It's even possible for one
1352  * of those lookups to find and enter the very same tuple we are trying to
1353  * fetch here. If that happens, we will enter a second copy of the tuple
1354  * into the cache. The first copy will never be referenced again, and
1355  * will eventually age out of the cache, so there's no functional problem.
1356  * This case is rare enough that it's not worth expending extra cycles to
1357  * detect.
1358  */
1359  relation = table_open(cache->cc_reloid, AccessShareLock);
1360 
1361  scandesc = systable_beginscan(relation,
1362  cache->cc_indexoid,
1363  IndexScanOK(cache, cur_skey),
1364  NULL,
1365  nkeys,
1366  cur_skey);
1367 
1368  ct = NULL;
1369 
1370  while (HeapTupleIsValid(ntp = systable_getnext(scandesc)))
1371  {
1372  ct = CatalogCacheCreateEntry(cache, ntp, arguments,
1373  hashValue, hashIndex,
1374  false);
1375  /* immediately set the refcount to 1 */
1377  ct->refcount++;
1379  break; /* assume only one match */
1380  }
1381 
1382  systable_endscan(scandesc);
1383 
1384  table_close(relation, AccessShareLock);
1385 
1386  /*
1387  * If tuple was not found, we need to build a negative cache entry
1388  * containing a fake tuple. The fake tuple has the correct key columns,
1389  * but nulls everywhere else.
1390  *
1391  * In bootstrap mode, we don't build negative entries, because the cache
1392  * invalidation mechanism isn't alive and can't clear them if the tuple
1393  * gets created later. (Bootstrap doesn't do UPDATEs, so it doesn't need
1394  * cache inval for that.)
1395  */
1396  if (ct == NULL)
1397  {
1399  return NULL;
1400 
1401  ct = CatalogCacheCreateEntry(cache, NULL, arguments,
1402  hashValue, hashIndex,
1403  true);
1404 
1405  CACHE_elog(DEBUG2, "SearchCatCache(%s): Contains %d/%d tuples",
1406  cache->cc_relname, cache->cc_ntup, CacheHdr->ch_ntup);
1407  CACHE_elog(DEBUG2, "SearchCatCache(%s): put neg entry in bucket %d",
1408  cache->cc_relname, hashIndex);
1409 
1410  /*
1411  * We are not returning the negative entry to the caller, so leave its
1412  * refcount zero.
1413  */
1414 
1415  return NULL;
1416  }
1417 
1418  CACHE_elog(DEBUG2, "SearchCatCache(%s): Contains %d/%d tuples",
1419  cache->cc_relname, cache->cc_ntup, CacheHdr->ch_ntup);
1420  CACHE_elog(DEBUG2, "SearchCatCache(%s): put in bucket %d",
1421  cache->cc_relname, hashIndex);
1422 
1423 #ifdef CATCACHE_STATS
1424  cache->cc_newloads++;
1425 #endif
1426 
1427  return &ct->tuple;
1428 }
void ResourceOwnerRememberCatCacheRef(ResourceOwner owner, HeapTuple tuple)
Definition: resowner.c:1046
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
static CatCacheHeader * CacheHdr
Definition: catcache.c:64
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
#define AccessShareLock
Definition: lockdefs.h:36
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
Oid cc_indexoid
Definition: catcache.h:59
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define CATCACHE_MAXKEYS
Definition: catcache.h:35
Oid cc_reloid
Definition: catcache.h:58
static CatCTup * CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp, Datum *arguments, uint32 hashValue, Index hashIndex, bool negative)
Definition: catcache.c:1807
int cc_ntup
Definition: catcache.h:55
#define DEBUG2
Definition: elog.h:24
static bool IndexScanOK(CatCache *cache, ScanKey cur_skey)
Definition: catcache.c:1084
uintptr_t Datum
Definition: postgres.h:411
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
int refcount
Definition: catcache.h:118
#define CACHE_elog(...)
Definition: catcache.c:60
const char * cc_relname
Definition: catcache.h:57
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:406
HeapTupleData tuple
Definition: catcache.h:121
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
ScanKeyData cc_skey[CATCACHE_MAXKEYS]
Definition: catcache.h:62
Datum sk_argument
Definition: skey.h:72
void ResourceOwnerEnlargeCatCacheRefs(ResourceOwner owner)
Definition: resowner.c:1035

◆ texteqfast()

static bool texteqfast ( Datum  a,
Datum  b 
)
static

Definition at line 171 of file catcache.c.

References DatumGetBool, DirectFunctionCall2Coll(), and texteq().

Referenced by GetCCHashEqFuncs().

172 {
173  /*
174  * The use of DEFAULT_COLLATION_OID is fairly arbitrary here. We just
175  * want to take the fast "deterministic" path in texteq().
176  */
177  return DatumGetBool(DirectFunctionCall2Coll(texteq, DEFAULT_COLLATION_OID, a, b));
178 }
Datum texteq(PG_FUNCTION_ARGS)
Definition: varlena.c:1783
#define DatumGetBool(X)
Definition: postgres.h:437
Datum DirectFunctionCall2Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:811

◆ texthashfast()

static uint32 texthashfast ( Datum  datum)
static

Definition at line 181 of file catcache.c.

References DatumGetInt32, DirectFunctionCall1Coll(), and hashtext().

Referenced by GetCCHashEqFuncs().

182 {
183  /* analogously here as in texteqfast() */
184  return DatumGetInt32(DirectFunctionCall1Coll(hashtext, DEFAULT_COLLATION_OID, datum));
185 }
#define DatumGetInt32(X)
Definition: postgres.h:516
Datum hashtext(PG_FUNCTION_ARGS)
Definition: hashfunc.c:245
Datum DirectFunctionCall1Coll(PGFunction func, Oid collation, Datum arg1)
Definition: fmgr.c:791

Variable Documentation

◆ CacheHdr

CatCacheHeader* CacheHdr = NULL
static

Definition at line 64 of file catcache.c.