PostgreSQL Source Code  git master
catcache.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/hash.h"
#include "access/heapam.h"
#include "access/relscan.h"
#include "access/sysattr.h"
#include "access/tuptoaster.h"
#include "access/valid.h"
#include "access/xact.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 "utils/tqual.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 CACHE1_elog(a, b)
 
#define CACHE2_elog(a, b, c)
 
#define CACHE3_elog(a, b, c, d)
 
#define CACHE4_elog(a, b, c, d, e)
 
#define CACHE5_elog(a, b, c, d, e, f)
 
#define CACHE6_elog(a, b, c, d, e, f, g)
 
#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, Datum v4)
 
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

◆ CACHE1_elog

#define CACHE1_elog (   a,
 
)

◆ CACHE2_elog

#define CACHE2_elog (   a,
  b,
  c 
)

Definition at line 67 of file catcache.c.

Referenced by CatalogCacheFlushCatalog(), and SearchCatCacheList().

◆ CACHE3_elog

#define CACHE3_elog (   a,
  b,
  c,
 
)

◆ CACHE4_elog

#define CACHE4_elog (   a,
  b,
  c,
  d,
  e 
)

◆ CACHE5_elog

#define CACHE5_elog (   a,
  b,
  c,
  d,
  e,
 
)

Definition at line 70 of file catcache.c.

◆ CACHE6_elog

#define CACHE6_elog (   a,
  b,
  c,
  d,
  e,
  f,
 
)

Definition at line 71 of file catcache.c.

◆ CatalogCacheInitializeCache_DEBUG1

#define CatalogCacheInitializeCache_DEBUG1

Definition at line 934 of file catcache.c.

Referenced by CatalogCacheInitializeCache().

◆ CatalogCacheInitializeCache_DEBUG2

#define CatalogCacheInitializeCache_DEBUG2

Definition at line 935 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 775 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 390 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().

393 {
394  const CCFastEqualFN *cc_fastequal = cache->cc_fastequal;
395  int i;
396 
397  for (i = 0; i < nkeys; i++)
398  {
399  if (!(cc_fastequal[i]) (cachekeys[i], searchkeys[i]))
400  return false;
401  }
402  return true;
403 }
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 276 of file catcache.c.

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

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

278 {
279  uint32 hashValue = 0;
280  uint32 oneHash;
281  CCHashFN *cc_hashfunc = cache->cc_hashfunc;
282 
283  CACHE4_elog(DEBUG2, "CatalogCacheComputeHashValue %s %d %p",
284  cache->cc_relname,
285  nkeys,
286  cache);
287 
288  switch (nkeys)
289  {
290  case 4:
291  oneHash = (cc_hashfunc[3]) (v4);
292 
293  hashValue ^= oneHash << 24;
294  hashValue ^= oneHash >> 8;
295  /* FALLTHROUGH */
296  case 3:
297  oneHash = (cc_hashfunc[2]) (v3);
298 
299  hashValue ^= oneHash << 16;
300  hashValue ^= oneHash >> 16;
301  /* FALLTHROUGH */
302  case 2:
303  oneHash = (cc_hashfunc[1]) (v2);
304 
305  hashValue ^= oneHash << 8;
306  hashValue ^= oneHash >> 24;
307  /* FALLTHROUGH */
308  case 1:
309  oneHash = (cc_hashfunc[0]) (v1);
310 
311  hashValue ^= oneHash;
312  break;
313  default:
314  elog(FATAL, "wrong number of hash keys: %d", nkeys);
315  break;
316  }
317 
318  return hashValue;
319 }
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:296
#define CACHE4_elog(a, b, c, d, e)
Definition: catcache.c:69
uint32(* CCHashFN)(Datum datum)
Definition: catcache.h:39
const char * cc_relname
Definition: catcache.h:57
#define elog
Definition: elog.h:219

◆ CatalogCacheComputeTupleHashValue()

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

Definition at line 327 of file catcache.c.

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

Referenced by PrepareToInvalidateCacheTuple(), and SearchCatCacheList().

328 {
329  Datum v1 = 0,
330  v2 = 0,
331  v3 = 0,
332  v4 = 0;
333  bool isNull = false;
334  int *cc_keyno = cache->cc_keyno;
335  TupleDesc cc_tupdesc = cache->cc_tupdesc;
336 
337  /* Now extract key fields from tuple, insert into scankey */
338  switch (nkeys)
339  {
340  case 4:
341  v4 = (cc_keyno[3] == ObjectIdAttributeNumber)
343  : fastgetattr(tuple,
344  cc_keyno[3],
345  cc_tupdesc,
346  &isNull);
347  Assert(!isNull);
348  /* FALLTHROUGH */
349  case 3:
350  v3 = (cc_keyno[2] == ObjectIdAttributeNumber)
352  : fastgetattr(tuple,
353  cc_keyno[2],
354  cc_tupdesc,
355  &isNull);
356  Assert(!isNull);
357  /* FALLTHROUGH */
358  case 2:
359  v2 = (cc_keyno[1] == ObjectIdAttributeNumber)
361  : fastgetattr(tuple,
362  cc_keyno[1],
363  cc_tupdesc,
364  &isNull);
365  Assert(!isNull);
366  /* FALLTHROUGH */
367  case 1:
368  v1 = (cc_keyno[0] == ObjectIdAttributeNumber)
370  : fastgetattr(tuple,
371  cc_keyno[0],
372  cc_tupdesc,
373  &isNull);
374  Assert(!isNull);
375  break;
376  default:
377  elog(FATAL, "wrong number of hash keys: %d", nkeys);
378  break;
379  }
380 
381  return CatalogCacheComputeHashValue(cache, nkeys, v1, v2, v3, v4);
382 }
int cc_keyno[CATCACHE_MAXKEYS]
Definition: catcache.h:53
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:724
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define FATAL
Definition: elog.h:52
TupleDesc cc_tupdesc
Definition: catcache.h:48
uintptr_t Datum
Definition: postgres.h:372
#define Assert(condition)
Definition: c.h:670
static uint32 CatalogCacheComputeHashValue(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:276
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700

◆ CatalogCacheCreateEntry()

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

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

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

◆ CatalogCacheFlushCatalog()

void CatalogCacheFlushCatalog ( Oid  catId)

Definition at line 735 of file catcache.c.

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

Referenced by LocalExecuteInvalidationMessage().

736 {
737  slist_iter iter;
738 
739  CACHE2_elog(DEBUG2, "CatalogCacheFlushCatalog called for %u", catId);
740 
742  {
743  CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
744 
745  /* Does this cache store tuples of the target catalog? */
746  if (cache->cc_reloid == catId)
747  {
748  /* Yes, so flush all its contents */
749  ResetCatalogCache(cache);
750 
751  /* Tell inval.c to call syscache callbacks for this cache */
752  CallSyscacheCallbacks(cache->id, 0);
753  }
754  }
755 
756  CACHE1_elog(DEBUG2, "end of CatalogCacheFlushCatalog call");
757 }
static void ResetCatalogCache(CatCache *cache)
Definition: catcache.c:658
static CatCacheHeader * CacheHdr
Definition: catcache.c:75
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:1450
#define CACHE1_elog(a, b)
Definition: catcache.c:66
slist_head ch_caches
Definition: catcache.h:184
#define slist_foreach(iter, lhead)
Definition: ilist.h:700
#define CACHE2_elog(a, b, c)
Definition: catcache.c:67

◆ CatalogCacheInitializeCache()

static void CatalogCacheInitializeCache ( CatCache cache)
static

Definition at line 939 of file catcache.c.

References AccessShareLock, Assert, BTEqualStrategyNumber, CACHE3_elog, CACHE4_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(), heap_close, heap_open(), i, InvalidOid, MemoryContextSwitchTo(), ObjectIdAttributeNumber, OIDOID, pstrdup(), RelationGetDescr, RelationGetForm, RelationGetRelationName, ScanKeyData::sk_attno, ScanKeyData::sk_collation, ScanKeyData::sk_func, ScanKeyData::sk_strategy, ScanKeyData::sk_subtype, and TupleDescAttr.

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

940 {
941  Relation relation;
942  MemoryContext oldcxt;
943  TupleDesc tupdesc;
944  int i;
945 
947 
948  relation = heap_open(cache->cc_reloid, AccessShareLock);
949 
950  /*
951  * switch to the cache context so our allocations do not vanish at the end
952  * of a transaction
953  */
954  Assert(CacheMemoryContext != NULL);
955 
957 
958  /*
959  * copy the relcache's tuple descriptor to permanent cache storage
960  */
961  tupdesc = CreateTupleDescCopyConstr(RelationGetDescr(relation));
962 
963  /*
964  * save the relation's name and relisshared flag, too (cc_relname is used
965  * only for debugging purposes)
966  */
967  cache->cc_relname = pstrdup(RelationGetRelationName(relation));
968  cache->cc_relisshared = RelationGetForm(relation)->relisshared;
969 
970  /*
971  * return to the caller's memory context and close the rel
972  */
973  MemoryContextSwitchTo(oldcxt);
974 
975  heap_close(relation, AccessShareLock);
976 
977  CACHE3_elog(DEBUG2, "CatalogCacheInitializeCache: %s, %d keys",
978  cache->cc_relname, cache->cc_nkeys);
979 
980  /*
981  * initialize cache's key information
982  */
983  for (i = 0; i < cache->cc_nkeys; ++i)
984  {
985  Oid keytype;
986  RegProcedure eqfunc;
987 
989 
990  if (cache->cc_keyno[i] > 0)
991  {
992  Form_pg_attribute attr = TupleDescAttr(tupdesc,
993  cache->cc_keyno[i] - 1);
994 
995  keytype = attr->atttypid;
996  /* cache key columns should always be NOT NULL */
997  Assert(attr->attnotnull);
998  }
999  else
1000  {
1001  if (cache->cc_keyno[i] != ObjectIdAttributeNumber)
1002  elog(FATAL, "only sys attr supported in caches is OID");
1003  keytype = OIDOID;
1004  }
1005 
1006  GetCCHashEqFuncs(keytype,
1007  &cache->cc_hashfunc[i],
1008  &eqfunc,
1009  &cache->cc_fastequal[i]);
1010 
1011  /*
1012  * Do equality-function lookup (we assume this won't need a catalog
1013  * lookup for any supported type)
1014  */
1015  fmgr_info_cxt(eqfunc,
1016  &cache->cc_skey[i].sk_func,
1018 
1019  /* Initialize sk_attno suitably for HeapKeyTest() and heap scans */
1020  cache->cc_skey[i].sk_attno = cache->cc_keyno[i];
1021 
1022  /* Fill in sk_strategy as well --- always standard equality */
1024  cache->cc_skey[i].sk_subtype = InvalidOid;
1025  /* Currently, there are no catcaches on collation-aware data types */
1026  cache->cc_skey[i].sk_collation = InvalidOid;
1027 
1028  CACHE4_elog(DEBUG2, "CatalogCacheInitializeCache %s %d %p",
1029  cache->cc_relname,
1030  i,
1031  cache);
1032  }
1033 
1034  /*
1035  * mark this cache fully initialized
1036  */
1037  cache->cc_tupdesc = tupdesc;
1038 }
int cc_keyno[CATCACHE_MAXKEYS]
Definition: catcache.h:53
Oid sk_subtype
Definition: skey.h:69
#define CatalogCacheInitializeCache_DEBUG1
Definition: catcache.c:934
#define CACHE3_elog(a, b, c, d)
Definition: catcache.c:68
#define RelationGetDescr(relation)
Definition: rel.h:437
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
#define OIDOID
Definition: pg_type.h:328
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
CCHashFN cc_hashfunc[CATCACHE_MAXKEYS]
Definition: catcache.h:50
#define RelationGetForm(relation)
Definition: rel.h:419
char * pstrdup(const char *in)
Definition: mcxt.c:1076
regproc RegProcedure
Definition: c.h:443
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
#define heap_close(r, l)
Definition: heapam.h:97
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:445
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define CatalogCacheInitializeCache_DEBUG2
Definition: catcache.c:935
TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc)
Definition: tupdesc.c:131
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:132
static void GetCCHashEqFuncs(Oid keytype, CCHashFN *hashfunc, RegProcedure *eqfunc, CCFastEqualFN *fasteqfunc)
Definition: catcache.c:207
#define CACHE4_elog(a, b, c, d, e)
Definition: catcache.c:69
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:670
CCFastEqualFN cc_fastequal[CATCACHE_MAXKEYS]
Definition: catcache.h:51
const char * cc_relname
Definition: catcache.h:57
Oid sk_collation
Definition: skey.h:70
int i
#define elog
Definition: elog.h:219
ScanKeyData cc_skey[CATCACHE_MAXKEYS]
Definition: catcache.h:62
#define BTEqualStrategyNumber
Definition: stratnum.h:31
AttrNumber sk_attno
Definition: skey.h:67
MemoryContext CacheMemoryContext
Definition: mcxt.c:46

◆ CatCacheCopyKeys()

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

Definition at line 1951 of file catcache.c.

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

Referenced by CatalogCacheCreateEntry(), and SearchCatCacheList().

1953 {
1954  int i;
1955 
1956  /*
1957  * XXX: memory and lookup performance could possibly be improved by
1958  * storing all keys in one allocation.
1959  */
1960 
1961  for (i = 0; i < nkeys; i++)
1962  {
1963  int attnum = attnos[i];
1964 
1965  if (attnum == ObjectIdAttributeNumber)
1966  {
1967  dstkeys[i] = srckeys[i];
1968  }
1969  else
1970  {
1971  Form_pg_attribute att = TupleDescAttr(tupdesc, attnum - 1);
1972  Datum src = srckeys[i];
1973  NameData srcname;
1974 
1975  /*
1976  * Must be careful in case the caller passed a C string where a
1977  * NAME is wanted: convert the given argument to a correctly
1978  * padded NAME. Otherwise the memcpy() done by datumCopy() could
1979  * fall off the end of memory.
1980  */
1981  if (att->atttypid == NAMEOID)
1982  {
1983  namestrcpy(&srcname, DatumGetCString(src));
1984  src = NameGetDatum(&srcname);
1985  }
1986 
1987  dstkeys[i] = datumCopy(src,
1988  att->attbyval,
1989  att->attlen);
1990  }
1991  }
1992 
1993 }
#define NameGetDatum(X)
Definition: postgres.h:601
#define NAMEOID
Definition: pg_type.h:300
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
int namestrcpy(Name name, const char *str)
Definition: name.c:216
#define DatumGetCString(X)
Definition: postgres.h:572
Definition: c.h:541
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:128
uintptr_t Datum
Definition: postgres.h:372
int i

◆ CatCacheFreeKeys()

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

Definition at line 1924 of file catcache.c.

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

Referenced by CatCacheRemoveCList(), and CatCacheRemoveCTup().

1925 {
1926  int i;
1927 
1928  for (i = 0; i < nkeys; i++)
1929  {
1930  int attnum = attnos[i];
1931  Form_pg_attribute att;
1932 
1933  /* only valid system attribute is the oid, which is by value */
1934  if (attnum == ObjectIdAttributeNumber)
1935  continue;
1936  Assert(attnum > 0);
1937 
1938  att = TupleDescAttr(tupdesc, attnum - 1);
1939 
1940  if (!att->attbyval)
1941  pfree(DatumGetPointer(keys[i]));
1942  }
1943 }
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
void pfree(void *pointer)
Definition: mcxt.c:949
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define Assert(condition)
Definition: c.h:670
#define DatumGetPointer(X)
Definition: postgres.h:555
int i

◆ CatCacheInvalidate()

void CatCacheInvalidate ( CatCache cache,
uint32  hashValue 
)

Definition at line 568 of file catcache.c.

References Assert, catctup::c_list, CACHE1_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().

569 {
570  Index hashIndex;
571  dlist_mutable_iter iter;
572 
573  CACHE1_elog(DEBUG2, "CatCacheInvalidate: called");
574 
575  /*
576  * We don't bother to check whether the cache has finished initialization
577  * yet; if not, there will be no entries in it so no problem.
578  */
579 
580  /*
581  * Invalidate *all* CatCLists in this cache; it's too hard to tell which
582  * searches might still be correct, so just zap 'em all.
583  */
584  dlist_foreach_modify(iter, &cache->cc_lists)
585  {
586  CatCList *cl = dlist_container(CatCList, cache_elem, iter.cur);
587 
588  if (cl->refcount > 0)
589  cl->dead = true;
590  else
591  CatCacheRemoveCList(cache, cl);
592  }
593 
594  /*
595  * inspect the proper hash bucket for tuple matches
596  */
597  hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
598  dlist_foreach_modify(iter, &cache->cc_bucket[hashIndex])
599  {
600  CatCTup *ct = dlist_container(CatCTup, cache_elem, iter.cur);
601 
602  if (hashValue == ct->hash_value)
603  {
604  if (ct->refcount > 0 ||
605  (ct->c_list && ct->c_list->refcount > 0))
606  {
607  ct->dead = true;
608  /* list, if any, was marked dead above */
609  Assert(ct->c_list == NULL || ct->c_list->dead);
610  }
611  else
612  CatCacheRemoveCTup(cache, ct);
613  CACHE1_elog(DEBUG2, "CatCacheInvalidate: invalidated");
614 #ifdef CATCACHE_STATS
615  cache->cc_invals++;
616 #endif
617  /* could be multiple matches, so keep looking! */
618  }
619  }
620 }
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:51
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:515
static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
Definition: catcache.c:473
unsigned int Index
Definition: c.h:413
#define CACHE1_elog(a, b)
Definition: catcache.c:66
#define Assert(condition)
Definition: c.h:670
int cc_nbuckets
Definition: catcache.h:47
int refcount
Definition: catcache.h:118
int refcount
Definition: catcache.h:172
bool dead
Definition: catcache.h:119

◆ CatCacheRemoveCList()

static void CatCacheRemoveCList ( CatCache cache,
CatCList cl 
)
static

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

516 {
517  int i;
518 
519  Assert(cl->refcount == 0);
520  Assert(cl->my_cache == cache);
521 
522  /* delink from member tuples */
523  for (i = cl->n_members; --i >= 0;)
524  {
525  CatCTup *ct = cl->members[i];
526 
527  Assert(ct->c_list == cl);
528  ct->c_list = NULL;
529  /* if the member is dead and now has no references, remove it */
530  if (
531 #ifndef CATCACHE_FORCE_RELEASE
532  ct->dead &&
533 #endif
534  ct->refcount == 0)
535  CatCacheRemoveCTup(cache, ct);
536  }
537 
538  /* delink from linked list */
539  dlist_delete(&cl->cache_elem);
540 
541  /* free associated column data */
542  CatCacheFreeKeys(cache->cc_tupdesc, cl->nkeys,
543  cache->cc_keyno, cl->keys);
544 
545  pfree(cl);
546 }
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:949
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:473
CatCache * my_cache
Definition: catcache.h:177
#define Assert(condition)
Definition: c.h:670
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:1924
bool dead
Definition: catcache.h:119

◆ CatCacheRemoveCTup()

static void CatCacheRemoveCTup ( CatCache cache,
CatCTup ct 
)
static

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

474 {
475  Assert(ct->refcount == 0);
476  Assert(ct->my_cache == cache);
477 
478  if (ct->c_list)
479  {
480  /*
481  * The cleanest way to handle this is to call CatCacheRemoveCList,
482  * which will recurse back to me, and the recursive call will do the
483  * work. Set the "dead" flag to make sure it does recurse.
484  */
485  ct->dead = true;
486  CatCacheRemoveCList(cache, ct->c_list);
487  return; /* nothing left to do */
488  }
489 
490  /* delink from linked list */
491  dlist_delete(&ct->cache_elem);
492 
493  /*
494  * Free keys when we're dealing with a negative entry, normal entries just
495  * point into tuple, allocated together with the CatCTup.
496  */
497  if (ct->negative)
498  CatCacheFreeKeys(cache->cc_tupdesc, cache->cc_nkeys,
499  cache->cc_keyno, ct->keys);
500 
501  pfree(ct);
502 
503  --cache->cc_ntup;
504  --CacheHdr->ch_ntup;
505 }
int cc_keyno[CATCACHE_MAXKEYS]
Definition: catcache.h:53
CatCache * my_cache
Definition: catcache.h:132
static CatCacheHeader * CacheHdr
Definition: catcache.c:75
Datum keys[CATCACHE_MAXKEYS]
Definition: catcache.h:97
struct catclist * c_list
Definition: catcache.h:130
void pfree(void *pointer)
Definition: mcxt.c:949
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:515
#define Assert(condition)
Definition: c.h:670
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:1924
bool dead
Definition: catcache.h:119

◆ chareqfast()

static bool chareqfast ( Datum  a,
Datum  b 
)
static

Definition at line 129 of file catcache.c.

References DatumGetChar.

Referenced by GetCCHashEqFuncs().

130 {
131  return DatumGetChar(a) == DatumGetChar(b);
132 }
#define DatumGetChar(X)
Definition: postgres.h:415

◆ charhashfast()

static uint32 charhashfast ( Datum  datum)
static

Definition at line 135 of file catcache.c.

References DatumGetChar, and murmurhash32().

Referenced by GetCCHashEqFuncs().

136 {
137  return murmurhash32((int32) DatumGetChar(datum));
138 }
signed int int32
Definition: c.h:284
#define DatumGetChar(X)
Definition: postgres.h:415
static uint32 murmurhash32(uint32 data)
Definition: hashutils.h:41

◆ CreateCacheMemoryContext()

void CreateCacheMemoryContext ( void  )

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

637 {
638  /*
639  * Purely for paranoia, check that context doesn't exist; caller probably
640  * did so already.
641  */
642  if (!CacheMemoryContext)
644  "CacheMemoryContext",
646 }
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
MemoryContext TopMemoryContext
Definition: mcxt.c:43
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
MemoryContext CacheMemoryContext
Definition: mcxt.c:46

◆ GetCatCacheHashValue()

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

Definition at line 1490 of file catcache.c.

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

Referenced by GetSysCacheHashValue().

1495 {
1496  /*
1497  * one-time startup overhead for each cache
1498  */
1499  if (cache->cc_tupdesc == NULL)
1501 
1502  /*
1503  * calculate the hash value
1504  */
1505  return CatalogCacheComputeHashValue(cache, cache->cc_nkeys, v1, v2, v3, v4);
1506 }
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:939
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:276

◆ GetCCHashEqFuncs()

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

Definition at line 207 of file catcache.c.

References BOOLOID, chareqfast(), charhashfast(), CHAROID, elog, FATAL, int2eqfast(), int2hashfast(), INT2OID, int4eqfast(), int4hashfast(), INT4OID, InvalidOid, nameeqfast(), namehashfast(), NAMEOID, OIDOID, oidvectoreqfast(), oidvectorhashfast(), OIDVECTOROID, REGCLASSOID, REGCONFIGOID, REGDICTIONARYOID, REGNAMESPACEOID, REGOPERATOROID, REGOPEROID, REGPROCEDUREOID, REGPROCOID, REGROLEOID, REGTYPEOID, texteqfast(), texthashfast(), and TEXTOID.

Referenced by CatalogCacheInitializeCache().

208 {
209  switch (keytype)
210  {
211  case BOOLOID:
212  *hashfunc = charhashfast;
213  *fasteqfunc = chareqfast;
214  *eqfunc = F_BOOLEQ;
215  break;
216  case CHAROID:
217  *hashfunc = charhashfast;
218  *fasteqfunc = chareqfast;
219  *eqfunc = F_CHAREQ;
220  break;
221  case NAMEOID:
222  *hashfunc = namehashfast;
223  *fasteqfunc = nameeqfast;
224  *eqfunc = F_NAMEEQ;
225  break;
226  case INT2OID:
227  *hashfunc = int2hashfast;
228  *fasteqfunc = int2eqfast;
229  *eqfunc = F_INT2EQ;
230  break;
231  case INT4OID:
232  *hashfunc = int4hashfast;
233  *fasteqfunc = int4eqfast;
234  *eqfunc = F_INT4EQ;
235  break;
236  case TEXTOID:
237  *hashfunc = texthashfast;
238  *fasteqfunc = texteqfast;
239  *eqfunc = F_TEXTEQ;
240  break;
241  case OIDOID:
242  case REGPROCOID:
243  case REGPROCEDUREOID:
244  case REGOPEROID:
245  case REGOPERATOROID:
246  case REGCLASSOID:
247  case REGTYPEOID:
248  case REGCONFIGOID:
249  case REGDICTIONARYOID:
250  case REGROLEOID:
251  case REGNAMESPACEOID:
252  *hashfunc = int4hashfast;
253  *fasteqfunc = int4eqfast;
254  *eqfunc = F_OIDEQ;
255  break;
256  case OIDVECTOROID:
257  *hashfunc = oidvectorhashfast;
258  *fasteqfunc = oidvectoreqfast;
259  *eqfunc = F_OIDVECTOREQ;
260  break;
261  default:
262  elog(FATAL, "type %u not supported as catcache key", keytype);
263  *hashfunc = NULL; /* keep compiler quiet */
264 
265  *eqfunc = InvalidOid;
266  break;
267  }
268 }
#define REGCLASSOID
Definition: pg_type.h:577
#define NAMEOID
Definition: pg_type.h:300
#define REGROLEOID
Definition: pg_type.h:585
#define OIDOID
Definition: pg_type.h:328
#define TEXTOID
Definition: pg_type.h:324
static uint32 namehashfast(Datum datum)
Definition: catcache.c:150
#define INT4OID
Definition: pg_type.h:316
static bool texteqfast(Datum a, Datum b)
Definition: catcache.c:182
#define REGTYPEOID
Definition: pg_type.h:581
#define REGOPEROID
Definition: pg_type.h:569
#define OIDVECTOROID
Definition: pg_type.h:344
static bool nameeqfast(Datum a, Datum b)
Definition: catcache.c:141
#define FATAL
Definition: elog.h:52
#define INT2OID
Definition: pg_type.h:308
#define REGDICTIONARYOID
Definition: pg_type.h:627
static uint32 int2hashfast(Datum datum)
Definition: catcache.c:164
static bool oidvectoreqfast(Datum a, Datum b)
Definition: catcache.c:194
static bool chareqfast(Datum a, Datum b)
Definition: catcache.c:129
static uint32 charhashfast(Datum datum)
Definition: catcache.c:135
#define CHAROID
Definition: pg_type.h:296
#define InvalidOid
Definition: postgres_ext.h:36
static bool int2eqfast(Datum a, Datum b)
Definition: catcache.c:158
#define BOOLOID
Definition: pg_type.h:288
#define REGCONFIGOID
Definition: pg_type.h:624
static bool int4eqfast(Datum a, Datum b)
Definition: catcache.c:170
static uint32 texthashfast(Datum datum)
Definition: catcache.c:188
#define elog
Definition: elog.h:219
#define REGPROCEDUREOID
Definition: pg_type.h:565
static uint32 int4hashfast(Datum datum)
Definition: catcache.c:176
#define REGNAMESPACEOID
Definition: pg_type.h:589
#define REGOPERATOROID
Definition: pg_type.h:573
#define REGPROCOID
Definition: pg_type.h:320
static uint32 oidvectorhashfast(Datum datum)
Definition: catcache.c:200

◆ IndexScanOK()

static bool IndexScanOK ( CatCache cache,
ScanKey  cur_skey 
)
static

Definition at line 1101 of file catcache.c.

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

Referenced by SearchCatCacheList(), and SearchCatCacheMiss().

1102 {
1103  switch (cache->id)
1104  {
1105  case INDEXRELID:
1106 
1107  /*
1108  * Rather than tracking exactly which indexes have to be loaded
1109  * before we can use indexscans (which changes from time to time),
1110  * just force all pg_index searches to be heap scans until we've
1111  * built the critical relcaches.
1112  */
1114  return false;
1115  break;
1116 
1117  case AMOID:
1118  case AMNAME:
1119 
1120  /*
1121  * Always do heap scans in pg_am, because it's so small there's
1122  * not much point in an indexscan anyway. We *must* do this when
1123  * initially building critical relcache entries, but we might as
1124  * well just always do it.
1125  */
1126  return false;
1127 
1128  case AUTHNAME:
1129  case AUTHOID:
1130  case AUTHMEMMEMROLE:
1131 
1132  /*
1133  * Protect authentication lookups occurring before relcache has
1134  * collected entries for shared indexes.
1135  */
1137  return false;
1138  break;
1139 
1140  default:
1141  break;
1142  }
1143 
1144  /* Normal case, allow index scan */
1145  return true;
1146 }
Definition: syscache.h:36
int id
Definition: catcache.h:46
bool criticalSharedRelcachesBuilt
Definition: relcache.c:131
bool criticalRelcachesBuilt
Definition: relcache.c:125

◆ InitCatCache()

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

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

785 {
786  CatCache *cp;
787  MemoryContext oldcxt;
788  size_t sz;
789  int i;
790 
791  /*
792  * nbuckets is the initial number of hash buckets to use in this catcache.
793  * It will be enlarged later if it becomes too full.
794  *
795  * nbuckets must be a power of two. We check this via Assert rather than
796  * a full runtime check because the values will be coming from constant
797  * tables.
798  *
799  * If you're confused by the power-of-two check, see comments in
800  * bitmapset.c for an explanation.
801  */
802  Assert(nbuckets > 0 && (nbuckets & -nbuckets) == nbuckets);
803 
804  /*
805  * first switch to the cache context so our allocations do not vanish at
806  * the end of a transaction
807  */
808  if (!CacheMemoryContext)
810 
812 
813  /*
814  * if first time through, initialize the cache group header
815  */
816  if (CacheHdr == NULL)
817  {
820  CacheHdr->ch_ntup = 0;
821 #ifdef CATCACHE_STATS
822  /* set up to dump stats at backend exit */
823  on_proc_exit(CatCachePrintStats, 0);
824 #endif
825  }
826 
827  /*
828  * Allocate a new cache structure, aligning to a cacheline boundary
829  *
830  * Note: we rely on zeroing to initialize all the dlist headers correctly
831  */
832  sz = sizeof(CatCache) + PG_CACHE_LINE_SIZE;
833  cp = (CatCache *) CACHELINEALIGN(palloc0(sz));
834  cp->cc_bucket = palloc0(nbuckets * sizeof(dlist_head));
835 
836  /*
837  * initialize the cache's relation information for the relation
838  * corresponding to this cache, and initialize some of the new cache's
839  * other internal fields. But don't open the relation yet.
840  */
841  cp->id = id;
842  cp->cc_relname = "(not known yet)";
843  cp->cc_reloid = reloid;
844  cp->cc_indexoid = indexoid;
845  cp->cc_relisshared = false; /* temporary */
846  cp->cc_tupdesc = (TupleDesc) NULL;
847  cp->cc_ntup = 0;
848  cp->cc_nbuckets = nbuckets;
849  cp->cc_nkeys = nkeys;
850  for (i = 0; i < nkeys; ++i)
851  cp->cc_keyno[i] = key[i];
852 
853  /*
854  * new cache is initialized as far as we can go for now. print some
855  * debugging information, if appropriate.
856  */
858 
859  /*
860  * add completed cache to top of group header's list
861  */
863 
864  /*
865  * back to the old context before we return...
866  */
867  MemoryContextSwitchTo(oldcxt);
868 
869  return cp;
870 }
#define PG_CACHE_LINE_SIZE
int cc_keyno[CATCACHE_MAXKEYS]
Definition: catcache.h:53
static CatCacheHeader * CacheHdr
Definition: catcache.c:75
void on_proc_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:292
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:877
struct tupleDesc * TupleDesc
slist_head ch_caches
Definition: catcache.h:184
#define InitCatCache_DEBUG2
Definition: catcache.c:775
#define Assert(condition)
Definition: c.h:670
int cc_nbuckets
Definition: catcache.h:47
#define CACHELINEALIGN(LEN)
Definition: c.h:626
void CreateCacheMemoryContext(void)
Definition: catcache.c:636
const char * cc_relname
Definition: catcache.h:57
void * palloc(Size size)
Definition: mcxt.c:848
int i
MemoryContext CacheMemoryContext
Definition: mcxt.c:46

◆ InitCatCachePhase2()

void InitCatCachePhase2 ( CatCache cache,
bool  touch_index 
)

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

1051 {
1052  if (cache->cc_tupdesc == NULL)
1054 
1055  if (touch_index &&
1056  cache->id != AMOID &&
1057  cache->id != AMNAME)
1058  {
1059  Relation idesc;
1060 
1061  /*
1062  * We must lock the underlying catalog before opening the index to
1063  * avoid deadlock, since index_open could possibly result in reading
1064  * this same catalog, and if anyone else is exclusive-locking this
1065  * catalog and index they'll be doing it in that order.
1066  */
1068  idesc = index_open(cache->cc_indexoid, AccessShareLock);
1069 
1070  /*
1071  * While we've got the index open, let's check that it's unique (and
1072  * not just deferrable-unique, thank you very much). This is just to
1073  * catch thinkos in definitions of new catcaches, so we don't worry
1074  * about the pg_am indexes not getting tested.
1075  */
1076  Assert(idesc->rd_index->indisunique &&
1077  idesc->rd_index->indimmediate);
1078 
1079  index_close(idesc, AccessShareLock);
1081  }
1082 }
Definition: syscache.h:36
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:182
#define AccessShareLock
Definition: lockdefs.h:36
int id
Definition: catcache.h:46
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:939
Oid cc_indexoid
Definition: catcache.h:59
Form_pg_index rd_index
Definition: rel.h:159
Oid cc_reloid
Definition: catcache.h:58
TupleDesc cc_tupdesc
Definition: catcache.h:48
#define Assert(condition)
Definition: c.h:670
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:176
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:105
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:151

◆ int2eqfast()

static bool int2eqfast ( Datum  a,
Datum  b 
)
static

Definition at line 158 of file catcache.c.

References DatumGetInt16.

Referenced by GetCCHashEqFuncs().

159 {
160  return DatumGetInt16(a) == DatumGetInt16(b);
161 }
#define DatumGetInt16(X)
Definition: postgres.h:450

◆ int2hashfast()

static uint32 int2hashfast ( Datum  datum)
static

Definition at line 164 of file catcache.c.

References DatumGetInt16, and murmurhash32().

Referenced by GetCCHashEqFuncs().

165 {
166  return murmurhash32((int32) DatumGetInt16(datum));
167 }
signed int int32
Definition: c.h:284
#define DatumGetInt16(X)
Definition: postgres.h:450
static uint32 murmurhash32(uint32 data)
Definition: hashutils.h:41

◆ int4eqfast()

static bool int4eqfast ( Datum  a,
Datum  b 
)
static

Definition at line 170 of file catcache.c.

References DatumGetInt32.

Referenced by GetCCHashEqFuncs().

171 {
172  return DatumGetInt32(a) == DatumGetInt32(b);
173 }
#define DatumGetInt32(X)
Definition: postgres.h:478

◆ int4hashfast()

static uint32 int4hashfast ( Datum  datum)
static

Definition at line 176 of file catcache.c.

References DatumGetInt32, and murmurhash32().

Referenced by GetCCHashEqFuncs().

177 {
178  return murmurhash32((int32) DatumGetInt32(datum));
179 }
#define DatumGetInt32(X)
Definition: postgres.h:478
signed int int32
Definition: c.h:284
static uint32 murmurhash32(uint32 data)
Definition: hashutils.h:41

◆ nameeqfast()

static bool nameeqfast ( Datum  a,
Datum  b 
)
static

Definition at line 141 of file catcache.c.

References DatumGetName, NAMEDATALEN, and NameStr.

Referenced by GetCCHashEqFuncs().

142 {
143  char *ca = NameStr(*DatumGetName(a));
144  char *cb = NameStr(*DatumGetName(b));
145 
146  return strncmp(ca, cb, NAMEDATALEN) == 0;
147 }
#define NAMEDATALEN
#define DatumGetName(X)
Definition: postgres.h:591
#define NameStr(name)
Definition: c.h:547

◆ namehashfast()

static uint32 namehashfast ( Datum  datum)
static

Definition at line 150 of file catcache.c.

References DatumGetName, hash_any(), and NameStr.

Referenced by GetCCHashEqFuncs().

151 {
152  char *key = NameStr(*DatumGetName(datum));
153 
154  return hash_any((unsigned char *) key, strlen(key));
155 }
#define DatumGetName(X)
Definition: postgres.h:591
Datum hash_any(register const unsigned char *k, register int keylen)
Definition: hashfunc.c:428
#define NameStr(name)
Definition: c.h:547

◆ oidvectoreqfast()

static bool oidvectoreqfast ( Datum  a,
Datum  b 
)
static

Definition at line 194 of file catcache.c.

References DatumGetBool, DirectFunctionCall2, and oidvectoreq().

Referenced by GetCCHashEqFuncs().

195 {
197 }
#define DatumGetBool(X)
Definition: postgres.h:399
Datum oidvectoreq(PG_FUNCTION_ARGS)
Definition: oid.c:426
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:587

◆ oidvectorhashfast()

static uint32 oidvectorhashfast ( Datum  datum)
static

Definition at line 200 of file catcache.c.

References DatumGetInt32, DirectFunctionCall1, and hashoidvector().

Referenced by GetCCHashEqFuncs().

201 {
203 }
#define DatumGetInt32(X)
Definition: postgres.h:478
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
Datum hashoidvector(PG_FUNCTION_ARGS)
Definition: hashfunc.c:207

◆ PrepareToInvalidateCacheTuple()

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

Definition at line 2030 of file catcache.c.

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

2034 {
2035  slist_iter iter;
2036  Oid reloid;
2037 
2038  CACHE1_elog(DEBUG2, "PrepareToInvalidateCacheTuple: called");
2039 
2040  /*
2041  * sanity checks
2042  */
2043  Assert(RelationIsValid(relation));
2044  Assert(HeapTupleIsValid(tuple));
2045  Assert(PointerIsValid(function));
2046  Assert(CacheHdr != NULL);
2047 
2048  reloid = RelationGetRelid(relation);
2049 
2050  /* ----------------
2051  * for each cache
2052  * if the cache contains tuples from the specified relation
2053  * compute the tuple's hash value(s) in this cache,
2054  * and call the passed function to register the information.
2055  * ----------------
2056  */
2057 
2059  {
2060  CatCache *ccp = slist_container(CatCache, cc_next, iter.cur);
2061  uint32 hashvalue;
2062  Oid dbid;
2063 
2064  if (ccp->cc_reloid != reloid)
2065  continue;
2066 
2067  /* Just in case cache hasn't finished initialization yet... */
2068  if (ccp->cc_tupdesc == NULL)
2070 
2071  hashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, tuple);
2072  dbid = ccp->cc_relisshared ? (Oid) 0 : MyDatabaseId;
2073 
2074  (*function) (ccp->id, hashvalue, dbid);
2075 
2076  if (newtuple)
2077  {
2078  uint32 newhashvalue;
2079 
2080  newhashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, newtuple);
2081 
2082  if (newhashvalue != hashvalue)
2083  (*function) (ccp->id, newhashvalue, dbid);
2084  }
2085  }
2086 }
static CatCacheHeader * CacheHdr
Definition: catcache.c:75
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:939
bool cc_relisshared
Definition: catcache.h:60
static uint32 CatalogCacheComputeTupleHashValue(CatCache *cache, int nkeys, HeapTuple tuple)
Definition: catcache.c:327
Oid cc_reloid
Definition: catcache.h:58
int cc_nkeys
Definition: catcache.h:56
#define RelationIsValid(relation)
Definition: rel.h:398
TupleDesc cc_tupdesc
Definition: catcache.h:48
#define DEBUG2
Definition: elog.h:24
unsigned int uint32
Definition: c.h:296
#define slist_container(type, membername, ptr)
Definition: ilist.h:674
Oid MyDatabaseId
Definition: globals.c:77
#define CACHE1_elog(a, b)
Definition: catcache.c:66
slist_head ch_caches
Definition: catcache.h:184
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:670
#define slist_foreach(iter, lhead)
Definition: ilist.h:700
#define PointerIsValid(pointer)
Definition: c.h:564
#define RelationGetRelid(relation)
Definition: rel.h:425

◆ PrintCatCacheLeakWarning()

void PrintCatCacheLeakWarning ( HeapTuple  tuple)

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

2095 {
2096  CatCTup *ct = (CatCTup *) (((char *) tuple) -
2097  offsetof(CatCTup, tuple));
2098 
2099  /* Safety check to ensure we were handed a cache entry */
2100  Assert(ct->ct_magic == CT_MAGIC);
2101 
2102  elog(WARNING, "cache reference leak: cache %s (%d), tuple %u/%u has count %d",
2103  ct->my_cache->cc_relname, ct->my_cache->id,
2104  ItemPointerGetBlockNumber(&(tuple->t_self)),
2105  ItemPointerGetOffsetNumber(&(tuple->t_self)),
2106  ct->refcount);
2107 }
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:670
int refcount
Definition: catcache.h:118
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:95
const char * cc_relname
Definition: catcache.h:57
#define elog
Definition: elog.h:219
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:76
#define offsetof(type, field)
Definition: c.h:593
int ct_magic
Definition: catcache.h:88

◆ PrintCatCacheListLeakWarning()

void PrintCatCacheListLeakWarning ( CatCList list)

Definition at line 2110 of file catcache.c.

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

Referenced by ResourceOwnerReleaseInternal().

2111 {
2112  elog(WARNING, "cache reference leak: cache %s (%d), list %p has count %d",
2113  list->my_cache->cc_relname, list->my_cache->id,
2114  list, list->refcount);
2115 }
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
Definition: elog.h:219
int refcount
Definition: catcache.h:172

◆ RehashCatCache()

static void RehashCatCache ( CatCache cp)
static

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

877 {
878  dlist_head *newbucket;
879  int newnbuckets;
880  int i;
881 
882  elog(DEBUG1, "rehashing catalog cache id %d for %s; %d tups, %d buckets",
883  cp->id, cp->cc_relname, cp->cc_ntup, cp->cc_nbuckets);
884 
885  /* Allocate a new, larger, hash table. */
886  newnbuckets = cp->cc_nbuckets * 2;
887  newbucket = (dlist_head *) MemoryContextAllocZero(CacheMemoryContext, newnbuckets * sizeof(dlist_head));
888 
889  /* Move all entries from old hash table to new. */
890  for (i = 0; i < cp->cc_nbuckets; i++)
891  {
892  dlist_mutable_iter iter;
893 
894  dlist_foreach_modify(iter, &cp->cc_bucket[i])
895  {
896  CatCTup *ct = dlist_container(CatCTup, cache_elem, iter.cur);
897  int hashIndex = HASH_INDEX(ct->hash_value, newnbuckets);
898 
899  dlist_delete(iter.cur);
900  dlist_push_head(&newbucket[hashIndex], &ct->cache_elem);
901  }
902  }
903 
904  /* Switch to the new array. */
905  pfree(cp->cc_bucket);
906  cp->cc_nbuckets = newnbuckets;
907  cp->cc_bucket = newbucket;
908 }
#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:51
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:949
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:741
int cc_nbuckets
Definition: catcache.h:47
const char * cc_relname
Definition: catcache.h:57
dlist_node cache_elem
Definition: catcache.h:104
int i
#define elog
Definition: elog.h:219
MemoryContext CacheMemoryContext
Definition: mcxt.c:46

◆ ReleaseCatCache()

void ReleaseCatCache ( HeapTuple  tuple)

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

1459 {
1460  CatCTup *ct = (CatCTup *) (((char *) tuple) -
1461  offsetof(CatCTup, tuple));
1462 
1463  /* Safety checks to ensure we were handed a cache entry */
1464  Assert(ct->ct_magic == CT_MAGIC);
1465  Assert(ct->refcount > 0);
1466 
1467  ct->refcount--;
1469 
1470  if (
1471 #ifndef CATCACHE_FORCE_RELEASE
1472  ct->dead &&
1473 #endif
1474  ct->refcount == 0 &&
1475  (ct->c_list == NULL || ct->c_list->refcount == 0))
1476  CatCacheRemoveCTup(ct->my_cache, ct);
1477 }
CatCache * my_cache
Definition: catcache.h:132
#define CT_MAGIC
Definition: catcache.h:89
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
void ResourceOwnerForgetCatCacheRef(ResourceOwner owner, HeapTuple tuple)
Definition: resowner.c:944
struct catclist * c_list
Definition: catcache.h:130
static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
Definition: catcache.c:473
#define Assert(condition)
Definition: c.h:670
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:593
int ct_magic
Definition: catcache.h:88
bool dead
Definition: catcache.h:119

◆ ReleaseCatCacheList()

void ReleaseCatCacheList ( CatCList list)

Definition at line 1795 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(), and spgvalidate().

1796 {
1797  /* Safety checks to ensure we were handed a cache entry */
1798  Assert(list->cl_magic == CL_MAGIC);
1799  Assert(list->refcount > 0);
1800  list->refcount--;
1802 
1803  if (
1804 #ifndef CATCACHE_FORCE_RELEASE
1805  list->dead &&
1806 #endif
1807  list->refcount == 0)
1808  CatCacheRemoveCList(list->my_cache, list);
1809 }
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
int cl_magic
Definition: catcache.h:159
bool dead
Definition: catcache.h:173
static void CatCacheRemoveCList(CatCache *cache, CatCList *cl)
Definition: catcache.c:515
#define CL_MAGIC
Definition: catcache.h:160
CatCache * my_cache
Definition: catcache.h:177
void ResourceOwnerForgetCatCacheListRef(ResourceOwner owner, CatCList *list)
Definition: resowner.c:979
#define Assert(condition)
Definition: c.h:670
int refcount
Definition: catcache.h:172

◆ ResetCatalogCache()

static void ResetCatalogCache ( CatCache cache)
static

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

659 {
660  dlist_mutable_iter iter;
661  int i;
662 
663  /* Remove each list in this cache, or at least mark it dead */
664  dlist_foreach_modify(iter, &cache->cc_lists)
665  {
666  CatCList *cl = dlist_container(CatCList, cache_elem, iter.cur);
667 
668  if (cl->refcount > 0)
669  cl->dead = true;
670  else
671  CatCacheRemoveCList(cache, cl);
672  }
673 
674  /* Remove each tuple in this cache, or at least mark it dead */
675  for (i = 0; i < cache->cc_nbuckets; i++)
676  {
677  dlist_head *bucket = &cache->cc_bucket[i];
678 
679  dlist_foreach_modify(iter, bucket)
680  {
681  CatCTup *ct = dlist_container(CatCTup, cache_elem, iter.cur);
682 
683  if (ct->refcount > 0 ||
684  (ct->c_list && ct->c_list->refcount > 0))
685  {
686  ct->dead = true;
687  /* list, if any, was marked dead above */
688  Assert(ct->c_list == NULL || ct->c_list->dead);
689  }
690  else
691  CatCacheRemoveCTup(cache, ct);
692 #ifdef CATCACHE_STATS
693  cache->cc_invals++;
694 #endif
695  }
696  }
697 }
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:515
static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
Definition: catcache.c:473
#define Assert(condition)
Definition: c.h:670
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 705 of file catcache.c.

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

Referenced by InvalidateSystemCaches().

706 {
707  slist_iter iter;
708 
709  CACHE1_elog(DEBUG2, "ResetCatalogCaches called");
710 
712  {
713  CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
714 
715  ResetCatalogCache(cache);
716  }
717 
718  CACHE1_elog(DEBUG2, "end of ResetCatalogCaches call");
719 }
static void ResetCatalogCache(CatCache *cache)
Definition: catcache.c:658
static CatCacheHeader * CacheHdr
Definition: catcache.c:75
slist_node * cur
Definition: ilist.h:226
#define DEBUG2
Definition: elog.h:24
#define slist_container(type, membername, ptr)
Definition: ilist.h:674
#define CACHE1_elog(a, b)
Definition: catcache.c:66
slist_head ch_caches
Definition: catcache.h:184
#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 1165 of file catcache.c.

References catcache::cc_nkeys, and SearchCatCacheInternal().

Referenced by SearchSysCache().

1170 {
1171  return SearchCatCacheInternal(cache, cache->cc_nkeys, v1, v2, v3, v4);
1172 }
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:1216

◆ SearchCatCache1()

HeapTuple SearchCatCache1 ( CatCache cache,
Datum  v1 
)

Definition at line 1182 of file catcache.c.

References SearchCatCacheInternal().

Referenced by SearchSysCache1().

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

◆ SearchCatCache2()

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

Definition at line 1190 of file catcache.c.

References SearchCatCacheInternal().

Referenced by SearchSysCache2().

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

◆ SearchCatCache3()

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

Definition at line 1198 of file catcache.c.

References SearchCatCacheInternal().

Referenced by SearchSysCache3().

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

◆ SearchCatCache4()

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

Definition at line 1206 of file catcache.c.

References SearchCatCacheInternal().

Referenced by SearchSysCache4().

1208 {
1209  return SearchCatCacheInternal(cache, 4, v1, v2, v3, v4);
1210 }
static HeapTuple SearchCatCacheInternal(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1216

◆ SearchCatCacheInternal()

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

Definition at line 1216 of file catcache.c.

References Assert, CACHE3_elog, catctup::cache_elem, 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().

1222 {
1224  uint32 hashValue;
1225  Index hashIndex;
1226  dlist_iter iter;
1227  dlist_head *bucket;
1228  CatCTup *ct;
1229 
1230  /* Make sure we're in an xact, even if this ends up being a cache hit */
1232 
1233  Assert(cache->cc_nkeys == nkeys);
1234 
1235  /*
1236  * one-time startup overhead for each cache
1237  */
1238  if (unlikely(cache->cc_tupdesc == NULL))
1240 
1241 #ifdef CATCACHE_STATS
1242  cache->cc_searches++;
1243 #endif
1244 
1245  /* Initialize local parameter array */
1246  arguments[0] = v1;
1247  arguments[1] = v2;
1248  arguments[2] = v3;
1249  arguments[3] = v4;
1250 
1251  /*
1252  * find the hash bucket in which to look for the tuple
1253  */
1254  hashValue = CatalogCacheComputeHashValue(cache, nkeys, v1, v2, v3, v4);
1255  hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
1256 
1257  /*
1258  * scan the hash bucket until we find a match or exhaust our tuples
1259  *
1260  * Note: it's okay to use dlist_foreach here, even though we modify the
1261  * dlist within the loop, because we don't continue the loop afterwards.
1262  */
1263  bucket = &cache->cc_bucket[hashIndex];
1264  dlist_foreach(iter, bucket)
1265  {
1266  ct = dlist_container(CatCTup, cache_elem, iter.cur);
1267 
1268  if (ct->dead)
1269  continue; /* ignore dead entries */
1270 
1271  if (ct->hash_value != hashValue)
1272  continue; /* quickly skip entry if wrong hash val */
1273 
1274  if (!CatalogCacheCompareTuple(cache, nkeys, ct->keys, arguments))
1275  continue;
1276 
1277  /*
1278  * We found a match in the cache. Move it to the front of the list
1279  * for its hashbucket, in order to speed subsequent searches. (The
1280  * most frequently accessed elements in any hashbucket will tend to be
1281  * near the front of the hashbucket's list.)
1282  */
1283  dlist_move_head(bucket, &ct->cache_elem);
1284 
1285  /*
1286  * If it's a positive entry, bump its refcount and return it. If it's
1287  * negative, we can report failure to the caller.
1288  */
1289  if (!ct->negative)
1290  {
1292  ct->refcount++;
1294 
1295  CACHE3_elog(DEBUG2, "SearchCatCache(%s): found in bucket %d",
1296  cache->cc_relname, hashIndex);
1297 
1298 #ifdef CATCACHE_STATS
1299  cache->cc_hits++;
1300 #endif
1301 
1302  return &ct->tuple;
1303  }
1304  else
1305  {
1306  CACHE3_elog(DEBUG2, "SearchCatCache(%s): found neg entry in bucket %d",
1307  cache->cc_relname, hashIndex);
1308 
1309 #ifdef CATCACHE_STATS
1310  cache->cc_neg_hits++;
1311 #endif
1312 
1313  return NULL;
1314  }
1315  }
1316 
1317  return SearchCatCacheMiss(cache, nkeys, hashValue, hashIndex, v1, v2, v3, v4);
1318 }
void ResourceOwnerRememberCatCacheRef(ResourceOwner owner, HeapTuple tuple)
Definition: resowner.c:935
uint32 hash_value
Definition: catcache.h:91
#define CACHE3_elog(a, b, c, d)
Definition: catcache.c:68
#define HASH_INDEX(h, sz)
Definition: catcache.c:51
#define dlist_foreach(iter, lhead)
Definition: ilist.h:507
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
static pg_noinline HeapTuple SearchCatCacheMiss(CatCache *cache, int nkeys, uint32 hashValue, Index hashIndex, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1328
dlist_head * cc_bucket
Definition: catcache.h:49
Datum keys[CATCACHE_MAXKEYS]
Definition: catcache.h:97
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:939
#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:296
static bool CatalogCacheCompareTuple(const CatCache *cache, int nkeys, const Datum *cachekeys, const Datum *searchkeys)
Definition: catcache.c:390
uintptr_t Datum
Definition: postgres.h:372
dlist_node * cur
Definition: ilist.h:161
unsigned int Index
Definition: c.h:413
#define Assert(condition)
Definition: c.h:670
int cc_nbuckets
Definition: catcache.h:47
int refcount
Definition: catcache.h:118
bool IsTransactionState(void)
Definition: xact.c:351
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:276
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:190
HeapTupleData tuple
Definition: catcache.h:121
void ResourceOwnerEnlargeCatCacheRefs(ResourceOwner owner)
Definition: resowner.c:924
bool dead
Definition: catcache.h:119

◆ SearchCatCacheList()

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

Definition at line 1519 of file catcache.c.

References AccessShareLock, Assert, catctup::c_list, CACHE2_elog, CACHE3_elog, catclist::cache_elem, 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, heap_close, heap_open(), 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, and catctup::tuple.

Referenced by SearchSysCacheList().

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

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

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

Referenced by SearchCatCacheInternal().

1336 {
1337  ScanKeyData cur_skey[CATCACHE_MAXKEYS];
1338  Relation relation;
1339  SysScanDesc scandesc;
1340  HeapTuple ntp;
1341  CatCTup *ct;
1343 
1344  /* Initialize local parameter array */
1345  arguments[0] = v1;
1346  arguments[1] = v2;
1347  arguments[2] = v3;
1348  arguments[3] = v4;
1349 
1350  /*
1351  * Ok, need to make a lookup in the relation, copy the scankey and fill
1352  * out any per-call fields.
1353  */
1354  memcpy(cur_skey, cache->cc_skey, sizeof(ScanKeyData) * nkeys);
1355  cur_skey[0].sk_argument = v1;
1356  cur_skey[1].sk_argument = v2;
1357  cur_skey[2].sk_argument = v3;
1358  cur_skey[3].sk_argument = v4;
1359 
1360  /*
1361  * Tuple was not found in cache, so we have to try to retrieve it directly
1362  * from the relation. If found, we will add it to the cache; if not
1363  * found, we will add a negative cache entry instead.
1364  *
1365  * NOTE: it is possible for recursive cache lookups to occur while reading
1366  * the relation --- for example, due to shared-cache-inval messages being
1367  * processed during heap_open(). This is OK. It's even possible for one
1368  * of those lookups to find and enter the very same tuple we are trying to
1369  * fetch here. If that happens, we will enter a second copy of the tuple
1370  * into the cache. The first copy will never be referenced again, and
1371  * will eventually age out of the cache, so there's no functional problem.
1372  * This case is rare enough that it's not worth expending extra cycles to
1373  * detect.
1374  */
1375  relation = heap_open(cache->cc_reloid, AccessShareLock);
1376 
1377  scandesc = systable_beginscan(relation,
1378  cache->cc_indexoid,
1379  IndexScanOK(cache, cur_skey),
1380  NULL,
1381  nkeys,
1382  cur_skey);
1383 
1384  ct = NULL;
1385 
1386  while (HeapTupleIsValid(ntp = systable_getnext(scandesc)))
1387  {
1388  ct = CatalogCacheCreateEntry(cache, ntp, arguments,
1389  hashValue, hashIndex,
1390  false);
1391  /* immediately set the refcount to 1 */
1393  ct->refcount++;
1395  break; /* assume only one match */
1396  }
1397 
1398  systable_endscan(scandesc);
1399 
1400  heap_close(relation, AccessShareLock);
1401 
1402  /*
1403  * If tuple was not found, we need to build a negative cache entry
1404  * containing a fake tuple. The fake tuple has the correct key columns,
1405  * but nulls everywhere else.
1406  *
1407  * In bootstrap mode, we don't build negative entries, because the cache
1408  * invalidation mechanism isn't alive and can't clear them if the tuple
1409  * gets created later. (Bootstrap doesn't do UPDATEs, so it doesn't need
1410  * cache inval for that.)
1411  */
1412  if (ct == NULL)
1413  {
1415  return NULL;
1416 
1417  ct = CatalogCacheCreateEntry(cache, NULL, arguments,
1418  hashValue, hashIndex,
1419  true);
1420 
1421  CACHE4_elog(DEBUG2, "SearchCatCache(%s): Contains %d/%d tuples",
1422  cache->cc_relname, cache->cc_ntup, CacheHdr->ch_ntup);
1423  CACHE3_elog(DEBUG2, "SearchCatCache(%s): put neg entry in bucket %d",
1424  cache->cc_relname, hashIndex);
1425 
1426  /*
1427  * We are not returning the negative entry to the caller, so leave its
1428  * refcount zero.
1429  */
1430 
1431  return NULL;
1432  }
1433 
1434  CACHE4_elog(DEBUG2, "SearchCatCache(%s): Contains %d/%d tuples",
1435  cache->cc_relname, cache->cc_ntup, CacheHdr->ch_ntup);
1436  CACHE3_elog(DEBUG2, "SearchCatCache(%s): put in bucket %d",
1437  cache->cc_relname, hashIndex);
1438 
1439 #ifdef CATCACHE_STATS
1440  cache->cc_newloads++;
1441 #endif
1442 
1443  return &ct->tuple;
1444 }
void ResourceOwnerRememberCatCacheRef(ResourceOwner owner, HeapTuple tuple)
Definition: resowner.c:935
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define CACHE3_elog(a, b, c, d)
Definition: catcache.c:68
static CatCacheHeader * CacheHdr
Definition: catcache.c:75
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
#define AccessShareLock
Definition: lockdefs.h:36
#define heap_close(r, l)
Definition: heapam.h:97
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
Oid cc_indexoid
Definition: catcache.h:59
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#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:1818
int cc_ntup
Definition: catcache.h:55
#define DEBUG2
Definition: elog.h:24
#define CACHE4_elog(a, b, c, d, e)
Definition: catcache.c:69
static bool IndexScanOK(CatCache *cache, ScanKey cur_skey)
Definition: catcache.c:1101
uintptr_t Datum
Definition: postgres.h:372
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
int refcount
Definition: catcache.h:118
const char * cc_relname
Definition: catcache.h:57
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:367
HeapTupleData tuple
Definition: catcache.h:121
ScanKeyData cc_skey[CATCACHE_MAXKEYS]
Definition: catcache.h:62
Datum sk_argument
Definition: skey.h:72
void ResourceOwnerEnlargeCatCacheRefs(ResourceOwner owner)
Definition: resowner.c:924

◆ texteqfast()

static bool texteqfast ( Datum  a,
Datum  b 
)
static

Definition at line 182 of file catcache.c.

References DatumGetBool, DirectFunctionCall2, and texteq().

Referenced by GetCCHashEqFuncs().

183 {
184  return DatumGetBool(DirectFunctionCall2(texteq, a, b));
185 }
Datum texteq(PG_FUNCTION_ARGS)
Definition: varlena.c:1642
#define DatumGetBool(X)
Definition: postgres.h:399
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:587

◆ texthashfast()

static uint32 texthashfast ( Datum  datum)
static

Definition at line 188 of file catcache.c.

References DatumGetInt32, DirectFunctionCall1, and hashtext().

Referenced by GetCCHashEqFuncs().

189 {
191 }
#define DatumGetInt32(X)
Definition: postgres.h:478
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
Datum hashtext(PG_FUNCTION_ARGS)
Definition: hashfunc.c:242

Variable Documentation

◆ CacheHdr

CatCacheHeader* CacheHdr = NULL
static

Definition at line 75 of file catcache.c.