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)
 
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:325
#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:731
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define FATAL
Definition: elog.h:52
TupleDesc cc_tupdesc
Definition: catcache.h:48
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:699
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:707

◆ CatalogCacheCreateEntry()

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

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

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

◆ CatalogCacheFlushCatalog()

void CatalogCacheFlushCatalog ( Oid  catId)

Definition at line 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, 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:433
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:93
CCHashFN cc_hashfunc[CATCACHE_MAXKEYS]
Definition: catcache.h:50
#define RelationGetForm(relation)
Definition: rel.h:401
char * pstrdup(const char *in)
Definition: mcxt.c:1161
regproc RegProcedure
Definition: c.h:472
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:441
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
#define CatalogCacheInitializeCache_DEBUG2
Definition: catcache.c:935
TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc)
Definition: tupdesc.c:151
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:134
static void GetCCHashEqFuncs(Oid keytype, CCHashFN *hashfunc, RegProcedure *eqfunc, CCFastEqualFN *fasteqfunc)
Definition: catcache.c:207
#define CACHE4_elog(a, b, c, d, e)
Definition: catcache.c:69
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:699
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:47

◆ CatCacheCopyKeys()

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

Definition at line 1956 of file catcache.c.

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

Referenced by CatalogCacheCreateEntry(), and SearchCatCacheList().

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

◆ CatCacheFreeKeys()

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

Definition at line 1929 of file catcache.c.

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

Referenced by CatCacheRemoveCList(), and CatCacheRemoveCTup().

1930 {
1931  int i;
1932 
1933  for (i = 0; i < nkeys; i++)
1934  {
1935  int attnum = attnos[i];
1936  Form_pg_attribute att;
1937 
1938  /* only valid system attribute is the oid, which is by value */
1939  if (attnum == ObjectIdAttributeNumber)
1940  continue;
1941  Assert(attnum > 0);
1942 
1943  att = TupleDescAttr(tupdesc, attnum - 1);
1944 
1945  if (!att->attbyval)
1946  pfree(DatumGetPointer(keys[i]));
1947  }
1948 }
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:93
void pfree(void *pointer)
Definition: mcxt.c:1031
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
int16 attnum
Definition: pg_attribute.h:79
#define Assert(condition)
Definition: c.h:699
#define DatumGetPointer(X)
Definition: postgres.h:534
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:442
#define CACHE1_elog(a, b)
Definition: catcache.c:66
#define Assert(condition)
Definition: c.h:699
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:1031
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:699
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:1929
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:1031
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:699
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:1929
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:394

◆ 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:313
#define DatumGetChar(X)
Definition: postgres.h:394
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:192
MemoryContext TopMemoryContext
Definition: mcxt.c:44
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:170
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ 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 chareqfast(), charhashfast(), elog, FATAL, int2eqfast(), int2hashfast(), int4eqfast(), int4hashfast(), InvalidOid, nameeqfast(), namehashfast(), oidvectoreqfast(), oidvectorhashfast(), texteqfast(), and texthashfast().

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 }
static uint32 namehashfast(Datum datum)
Definition: catcache.c:150
static bool texteqfast(Datum a, Datum b)
Definition: catcache.c:182
static bool nameeqfast(Datum a, Datum b)
Definition: catcache.c:141
#define FATAL
Definition: elog.h:52
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 InvalidOid
Definition: postgres_ext.h:36
static bool int2eqfast(Datum a, Datum b)
Definition: catcache.c:158
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
static uint32 int4hashfast(Datum datum)
Definition: catcache.c:176
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:137
bool criticalRelcachesBuilt
Definition: relcache.c:131

◆ 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:303
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:955
struct tupleDesc * TupleDesc
slist_head ch_caches
Definition: catcache.h:184
#define InitCatCache_DEBUG2
Definition: catcache.c:775
#define Assert(condition)
Definition: c.h:699
int cc_nbuckets
Definition: catcache.h:47
#define CACHELINEALIGN(LEN)
Definition: c.h:655
void CreateCacheMemoryContext(void)
Definition: catcache.c:636
const char * cc_relname
Definition: catcache.h:57
void * palloc(Size size)
Definition: mcxt.c:924
int i
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ 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:131
Oid cc_reloid
Definition: catcache.h:58
TupleDesc cc_tupdesc
Definition: catcache.h:48
#define Assert(condition)
Definition: c.h:699
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:150

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

◆ 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:313
#define DatumGetInt16(X)
Definition: postgres.h:429
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:457

◆ 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:457
signed int int32
Definition: c.h:313
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:570
#define NameStr(name)
Definition: c.h:576

◆ 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:570
Datum hash_any(register const unsigned char *k, register int keylen)
Definition: hashfunc.c:428
#define NameStr(name)
Definition: c.h:576

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

◆ 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:457
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
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 2035 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().

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

◆ PrintCatCacheLeakWarning()

void PrintCatCacheLeakWarning ( HeapTuple  tuple)

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

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

◆ PrintCatCacheListLeakWarning()

void PrintCatCacheListLeakWarning ( CatCList list)

Definition at line 2115 of file catcache.c.

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

Referenced by ResourceOwnerReleaseInternal().

2116 {
2117  elog(WARNING, "cache reference leak: cache %s (%d), list %p has count %d",
2118  list->my_cache->cc_relname, list->my_cache->id,
2119  list, list->refcount);
2120 }
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:1031
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:814
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:47

◆ 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:140
void ResourceOwnerForgetCatCacheRef(ResourceOwner owner, HeapTuple tuple)
Definition: resowner.c:957
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:699
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:622
int ct_magic
Definition: catcache.h:88
bool dead
Definition: catcache.h:119

◆ ReleaseCatCacheList()

void ReleaseCatCacheList ( CatCList list)

Definition at line 1800 of file catcache.c.

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

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

1801 {
1802  /* Safety checks to ensure we were handed a cache entry */
1803  Assert(list->cl_magic == CL_MAGIC);
1804  Assert(list->refcount > 0);
1805  list->refcount--;
1807 
1808  if (
1809 #ifndef CATCACHE_FORCE_RELEASE
1810  list->dead &&
1811 #endif
1812  list->refcount == 0)
1813  CatCacheRemoveCList(list->my_cache, list);
1814 }
ResourceOwner CurrentResourceOwner
Definition: resowner.c:140
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:992
#define Assert(condition)
Definition: c.h:699
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:699
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:948
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:140
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:325
static bool CatalogCacheCompareTuple(const CatCache *cache, int nkeys, const Datum *cachekeys, const Datum *searchkeys)
Definition: catcache.c:390
uintptr_t Datum
Definition: postgres.h:367
dlist_node * cur
Definition: ilist.h:161
unsigned int Index
Definition: c.h:442
#define Assert(condition)
Definition: c.h:699
int cc_nbuckets
Definition: catcache.h:47
int refcount
Definition: catcache.h:118
bool IsTransactionState(void)
Definition: xact.c:350
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:208
HeapTupleData tuple
Definition: catcache.h:121
void ResourceOwnerEnlargeCatCacheRefs(ResourceOwner owner)
Definition: resowner.c:937
bool dead
Definition: catcache.h:119

◆ SearchCatCacheList()

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

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

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

◆ 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:948
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:502
#define CACHE3_elog(a, b, c, d)
Definition: catcache.c:68
static CatCacheHeader * CacheHdr
Definition: catcache.c:75
ResourceOwner CurrentResourceOwner
Definition: resowner.c:140
#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:331
Oid cc_indexoid
Definition: catcache.h:59
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:419
#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:1823
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:367
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
int refcount
Definition: catcache.h:118
const char * cc_relname
Definition: catcache.h:57
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:372
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:937

◆ 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:1641
#define DatumGetBool(X)
Definition: postgres.h:378
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:592

◆ 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:457
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
Datum hashtext(PG_FUNCTION_ARGS)
Definition: hashfunc.c:242

Variable Documentation

◆ CacheHdr

CatCacheHeader* CacheHdr = NULL
static

Definition at line 75 of file catcache.c.