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 "miscadmin.h"
#include "storage/lmgr.h"
#include "utils/builtins.h"
#include "utils/datum.h"
#include "utils/fmgroids.h"
#include "utils/hashutils.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:52
#define DEBUG2
Definition: elog.h:24
unsigned int uint32
Definition: c.h:358
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:226

◆ 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:712
#define FATAL
Definition: elog.h:52
TupleDesc cc_tupdesc
Definition: catcache.h:48
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:732
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:226

◆ CatalogCacheCreateEntry()

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

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

1808 {
1809  CatCTup *ct;
1810  HeapTuple dtp;
1811  MemoryContext oldcxt;
1812 
1813  /* negative entries have no tuple associated */
1814  if (ntp)
1815  {
1816  int i;
1817 
1818  Assert(!negative);
1819 
1820  /*
1821  * If there are any out-of-line toasted fields in the tuple, expand
1822  * them in-line. This saves cycles during later use of the catcache
1823  * entry, and also protects us against the possibility of the toast
1824  * tuples being freed before we attempt to fetch them, in case of
1825  * something using a slightly stale catcache entry.
1826  */
1827  if (HeapTupleHasExternal(ntp))
1828  dtp = toast_flatten_tuple(ntp, cache->cc_tupdesc);
1829  else
1830  dtp = ntp;
1831 
1832  /* Allocate memory for CatCTup and the cached tuple in one go */
1834 
1835  ct = (CatCTup *) palloc(sizeof(CatCTup) +
1836  MAXIMUM_ALIGNOF + dtp->t_len);
1837  ct->tuple.t_len = dtp->t_len;
1838  ct->tuple.t_self = dtp->t_self;
1839  ct->tuple.t_tableOid = dtp->t_tableOid;
1840  ct->tuple.t_data = (HeapTupleHeader)
1841  MAXALIGN(((char *) ct) + sizeof(CatCTup));
1842  /* copy tuple contents */
1843  memcpy((char *) ct->tuple.t_data,
1844  (const char *) dtp->t_data,
1845  dtp->t_len);
1846  MemoryContextSwitchTo(oldcxt);
1847 
1848  if (dtp != ntp)
1849  heap_freetuple(dtp);
1850 
1851  /* extract keys - they'll point into the tuple if not by-value */
1852  for (i = 0; i < cache->cc_nkeys; i++)
1853  {
1854  Datum atp;
1855  bool isnull;
1856 
1857  atp = heap_getattr(&ct->tuple,
1858  cache->cc_keyno[i],
1859  cache->cc_tupdesc,
1860  &isnull);
1861  Assert(!isnull);
1862  ct->keys[i] = atp;
1863  }
1864  }
1865  else
1866  {
1867  Assert(negative);
1869  ct = (CatCTup *) palloc(sizeof(CatCTup));
1870 
1871  /*
1872  * Store keys - they'll point into separately allocated memory if not
1873  * by-value.
1874  */
1875  CatCacheCopyKeys(cache->cc_tupdesc, cache->cc_nkeys, cache->cc_keyno,
1876  arguments, ct->keys);
1877  MemoryContextSwitchTo(oldcxt);
1878  }
1879 
1880  /*
1881  * Finish initializing the CatCTup header, and add it to the cache's
1882  * linked list and counts.
1883  */
1884  ct->ct_magic = CT_MAGIC;
1885  ct->my_cache = cache;
1886  ct->c_list = NULL;
1887  ct->refcount = 0; /* for the moment */
1888  ct->dead = false;
1889  ct->negative = negative;
1890  ct->hash_value = hashValue;
1891 
1892  dlist_push_head(&cache->cc_bucket[hashIndex], &ct->cache_elem);
1893 
1894  cache->cc_ntup++;
1895  CacheHdr->ch_ntup++;
1896 
1897  /*
1898  * If the hash table has become too full, enlarge the buckets array. Quite
1899  * arbitrarily, we enlarge when fill factor > 2.
1900  */
1901  if (cache->cc_ntup > cache->cc_nbuckets * 2)
1902  RehashCatCache(cache);
1903 
1904  return ct;
1905 }
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:1936
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:343
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:762
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:732
int cc_nbuckets
Definition: catcache.h:47
int refcount
Definition: catcache.h:118
#define MAXALIGN(LEN)
Definition: c.h:685
dlist_node cache_elem
Definition: catcache.h:104
bool negative
Definition: catcache.h:120
#define HeapTupleHasExternal(tuple)
Definition: htup_details.h:673
void * palloc(Size size)
Definition: mcxt.c:949
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:47

◆ CatalogCacheFlushCatalog()

void CatalogCacheFlushCatalog ( Oid  catId)

Definition at line 719 of file catcache.c.

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

Referenced by LocalExecuteInvalidationMessage().

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

◆ 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:133
#define CatalogCacheInitializeCache_DEBUG1
Definition: catcache.c:918
#define RelationGetDescr(relation)
Definition: rel.h:445
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
CCHashFN cc_hashfunc[CATCACHE_MAXKEYS]
Definition: catcache.h:50
#define RelationGetForm(relation)
Definition: rel.h:413
char * pstrdup(const char *in)
Definition: mcxt.c:1186
regproc RegProcedure
Definition: c.h:505
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:52
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:453
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
#define CatalogCacheInitializeCache_DEBUG2
Definition: catcache.c:919
TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc)
Definition: tupdesc.c:150
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:134
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:732
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:226
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:47

◆ CatCacheCopyKeys()

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

Definition at line 1936 of file catcache.c.

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

Referenced by CatalogCacheCreateEntry(), and SearchCatCacheList().

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

◆ CatCacheFreeKeys()

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

Definition at line 1911 of file catcache.c.

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

Referenced by CatCacheRemoveCList(), and CatCacheRemoveCTup().

1912 {
1913  int i;
1914 
1915  for (i = 0; i < nkeys; i++)
1916  {
1917  int attnum = attnos[i];
1918  Form_pg_attribute att;
1919 
1920  /* system attribute are not supported in caches */
1921  Assert(attnum > 0);
1922 
1923  att = TupleDescAttr(tupdesc, attnum - 1);
1924 
1925  if (!att->attbyval)
1926  pfree(DatumGetPointer(keys[i]));
1927  }
1928 }
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
void pfree(void *pointer)
Definition: mcxt.c:1056
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
int16 attnum
Definition: pg_attribute.h:79
#define Assert(condition)
Definition: c.h:732
#define DatumGetPointer(X)
Definition: postgres.h:549
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:524
#define HASH_INDEX(h, sz)
Definition: catcache.c:50
dlist_head * cc_bucket
Definition: catcache.h:49
bool dead
Definition: catcache.h:173
dlist_head cc_lists
Definition: catcache.h:54
struct catclist * c_list
Definition: catcache.h:130
#define dlist_container(type, membername, ptr)
Definition: ilist.h:477
#define DEBUG2
Definition: elog.h:24
static void CatCacheRemoveCList(CatCache *cache, CatCList *cl)
Definition: catcache.c:499
static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
Definition: catcache.c:457
unsigned int Index
Definition: c.h:475
#define Assert(condition)
Definition: c.h:732
int cc_nbuckets
Definition: catcache.h:47
int refcount
Definition: catcache.h:118
#define CACHE_elog(...)
Definition: catcache.c:60
int refcount
Definition: catcache.h:172
bool dead
Definition: catcache.h:119

◆ 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:1056
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:732
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:1911
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:1056
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:732
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:1911
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:409

◆ 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 }
signed int int32
Definition: c.h:346
#define DatumGetChar(X)
Definition: postgres.h:409
static uint32 murmurhash32(uint32 data)
Definition: hashutils.h:60

◆ CreateCacheMemoryContext()

void CreateCacheMemoryContext ( void  )

Definition at line 620 of file catcache.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CacheMemoryContext, and TopMemoryContext.

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

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

◆ GetCatCacheHashValue()

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

Definition at line 1472 of file catcache.c.

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

Referenced by GetSysCacheHashValue().

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

◆ 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:52
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:226
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 1083 of file catcache.c.

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

Referenced by SearchCatCacheList(), and SearchCatCacheMiss().

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

◆ InitCatCache()

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

Definition at line 763 of file catcache.c.

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

Referenced by InitCatalogCache().

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

◆ InitCatCachePhase2()

void InitCatCachePhase2 ( CatCache cache,
bool  touch_index 
)

Definition at line 1032 of file catcache.c.

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

Referenced by InitCatalogCachePhase2(), and SysCacheGetAttr().

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

◆ 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:444

◆ 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 }
signed int int32
Definition: c.h:346
#define DatumGetInt16(X)
Definition: postgres.h:444
static uint32 murmurhash32(uint32 data)
Definition: hashutils.h:60

◆ 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:472

◆ 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:472
signed int int32
Definition: c.h:346
static uint32 murmurhash32(uint32 data)
Definition: hashutils.h:60

◆ 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:585
#define NameStr(name)
Definition: c.h:609

◆ 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 }
Datum hash_any(const unsigned char *k, int keylen)
Definition: hashfn.c:148
#define DatumGetName(X)
Definition: postgres.h:585
#define NameStr(name)
Definition: c.h:609

◆ 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:393
Datum oidvectoreq(PG_FUNCTION_ARGS)
Definition: oid.c:426
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:619

◆ 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:472
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:617
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 2007 of file catcache.c.

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

Referenced by CacheInvalidateHeapTuple().

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

◆ PrintCatCacheLeakWarning()

void PrintCatCacheLeakWarning ( HeapTuple  tuple)

Definition at line 2071 of file catcache.c.

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

Referenced by ResourceOwnerReleaseInternal().

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

◆ PrintCatCacheListLeakWarning()

void PrintCatCacheListLeakWarning ( CatCList list)

Definition at line 2087 of file catcache.c.

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

Referenced by ResourceOwnerReleaseInternal().

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

◆ 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:524
#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:477
void pfree(void *pointer)
Definition: mcxt.c:1056
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:839
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:226
int i
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ ReleaseCatCache()

void ReleaseCatCache ( HeapTuple  tuple)

Definition at line 1440 of file catcache.c.

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

Referenced by ReleaseSysCache(), and ResourceOwnerReleaseInternal().

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

◆ ReleaseCatCacheList()

void ReleaseCatCacheList ( CatCList list)

Definition at line 1782 of file catcache.c.

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

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

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

◆ 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:524
dlist_head * cc_bucket
Definition: catcache.h:49
bool dead
Definition: catcache.h:173
dlist_head cc_lists
Definition: catcache.h:54
struct catclist * c_list
Definition: catcache.h:130
#define dlist_container(type, membername, ptr)
Definition: ilist.h:477
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:732
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:674
slist_head ch_caches
Definition: catcache.h:184
#define CACHE_elog(...)
Definition: catcache.c:60
#define slist_foreach(iter, lhead)
Definition: ilist.h:700

◆ SearchCatCache()

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

Definition at line 1147 of file catcache.c.

References catcache::cc_nkeys, and SearchCatCacheInternal().

Referenced by SearchSysCache().

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

◆ SearchCatCache1()

HeapTuple SearchCatCache1 ( CatCache cache,
Datum  v1 
)

Definition at line 1164 of file catcache.c.

References SearchCatCacheInternal().

Referenced by SearchSysCache1().

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

◆ SearchCatCache2()

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

Definition at line 1172 of file catcache.c.

References SearchCatCacheInternal().

Referenced by SearchSysCache2().

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

◆ SearchCatCache3()

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

Definition at line 1180 of file catcache.c.

References SearchCatCacheInternal().

Referenced by SearchSysCache3().

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

◆ SearchCatCache4()

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

Definition at line 1188 of file catcache.c.

References SearchCatCacheInternal().

Referenced by SearchSysCache4().

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

◆ SearchCatCacheInternal()

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

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

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

◆ SearchCatCacheList()

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

Definition at line 1506 of file catcache.c.

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

Referenced by SearchSysCacheList().

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

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

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

◆ 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:1715
#define DatumGetBool(X)
Definition: postgres.h:393
Datum DirectFunctionCall2Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:813

◆ 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:472
Datum hashtext(PG_FUNCTION_ARGS)
Definition: hashfunc.c:245
Datum DirectFunctionCall1Coll(PGFunction func, Oid collation, Datum arg1)
Definition: fmgr.c:793

Variable Documentation

◆ CacheHdr

CatCacheHeader* CacheHdr = NULL
static

Definition at line 64 of file catcache.c.