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

Go to the source code of this file.

Macros

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

Functions

static HeapTuple SearchCatCacheInternal (CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
 
static pg_noinline HeapTuple SearchCatCacheMiss (CatCache *cache, int nkeys, uint32 hashValue, Index hashIndex, Datum v1, Datum v2, Datum v3, Datum v4)
 
static uint32 CatalogCacheComputeHashValue (CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
 
static uint32 CatalogCacheComputeTupleHashValue (CatCache *cache, int nkeys, HeapTuple tuple)
 
static bool CatalogCacheCompareTuple (const CatCache *cache, int nkeys, const Datum *cachekeys, const Datum *searchkeys)
 
static void CatCacheRemoveCTup (CatCache *cache, CatCTup *ct)
 
static void CatCacheRemoveCList (CatCache *cache, CatCList *cl)
 
static void RehashCatCache (CatCache *cp)
 
static void RehashCatCacheLists (CatCache *cp)
 
static void CatalogCacheInitializeCache (CatCache *cache)
 
static CatCTupCatalogCacheCreateEntry (CatCache *cache, HeapTuple ntp, SysScanDesc scandesc, Datum *arguments, uint32 hashValue, Index hashIndex)
 
static void ReleaseCatCacheWithOwner (HeapTuple tuple, ResourceOwner resowner)
 
static void ReleaseCatCacheListWithOwner (CatCList *list, ResourceOwner resowner)
 
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 void ResOwnerReleaseCatCache (Datum res)
 
static char * ResOwnerPrintCatCache (Datum res)
 
static void ResOwnerReleaseCatCacheList (Datum res)
 
static char * ResOwnerPrintCatCacheList (Datum res)
 
static void ResourceOwnerRememberCatCacheRef (ResourceOwner owner, HeapTuple tuple)
 
static void ResourceOwnerForgetCatCacheRef (ResourceOwner owner, HeapTuple tuple)
 
static void ResourceOwnerRememberCatCacheListRef (ResourceOwner owner, CatCList *list)
 
static void ResourceOwnerForgetCatCacheListRef (ResourceOwner owner, CatCList *list)
 
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)
 
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))
 

Variables

static CatCacheHeaderCacheHdr = NULL
 
static const ResourceOwnerDesc catcache_resowner_desc
 
static const ResourceOwnerDesc catlistref_resowner_desc
 

Macro Definition Documentation

◆ CACHE_elog

#define CACHE_elog (   ...)

Definition at line 60 of file catcache.c.

◆ CatalogCacheInitializeCache_DEBUG1

#define CatalogCacheInitializeCache_DEBUG1

Definition at line 1030 of file catcache.c.

◆ CatalogCacheInitializeCache_DEBUG2

#define CatalogCacheInitializeCache_DEBUG2

Definition at line 1031 of file catcache.c.

◆ HASH_INDEX

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

Definition at line 50 of file catcache.c.

◆ InitCatCache_DEBUG2

#define InitCatCache_DEBUG2

Definition at line 823 of file catcache.c.

Function Documentation

◆ CatalogCacheCompareTuple()

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

Definition at line 422 of file catcache.c.

425 {
426  const CCFastEqualFN *cc_fastequal = cache->cc_fastequal;
427  int i;
428 
429  for (i = 0; i < nkeys; i++)
430  {
431  if (!(cc_fastequal[i]) (cachekeys[i], searchkeys[i]))
432  return false;
433  }
434  return true;
435 }
bool(* CCFastEqualFN)(Datum a, Datum b)
Definition: catcache.h:42
int i
Definition: isn.c:73
CCFastEqualFN cc_fastequal[CATCACHE_MAXKEYS]
Definition: catcache.h:51

References catcache::cc_fastequal, and i.

Referenced by SearchCatCacheInternal(), and SearchCatCacheList().

◆ CatalogCacheComputeHashValue()

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

Definition at line 325 of file catcache.c.

327 {
328  uint32 hashValue = 0;
329  uint32 oneHash;
330  CCHashFN *cc_hashfunc = cache->cc_hashfunc;
331 
332  CACHE_elog(DEBUG2, "CatalogCacheComputeHashValue %s %d %p",
333  cache->cc_relname, nkeys, cache);
334 
335  switch (nkeys)
336  {
337  case 4:
338  oneHash = (cc_hashfunc[3]) (v4);
339  hashValue ^= pg_rotate_left32(oneHash, 24);
340  /* FALLTHROUGH */
341  case 3:
342  oneHash = (cc_hashfunc[2]) (v3);
343  hashValue ^= pg_rotate_left32(oneHash, 16);
344  /* FALLTHROUGH */
345  case 2:
346  oneHash = (cc_hashfunc[1]) (v2);
347  hashValue ^= pg_rotate_left32(oneHash, 8);
348  /* FALLTHROUGH */
349  case 1:
350  oneHash = (cc_hashfunc[0]) (v1);
351  hashValue ^= oneHash;
352  break;
353  default:
354  elog(FATAL, "wrong number of hash keys: %d", nkeys);
355  break;
356  }
357 
358  return hashValue;
359 }
unsigned int uint32
Definition: c.h:506
#define CACHE_elog(...)
Definition: catcache.c:60
uint32(* CCHashFN)(Datum datum)
Definition: catcache.h:39
#define FATAL
Definition: elog.h:41
#define DEBUG2
Definition: elog.h:29
#define elog(elevel,...)
Definition: elog.h:224
static uint32 pg_rotate_left32(uint32 word, int n)
Definition: pg_bitutils.h:404
const char * cc_relname
Definition: catcache.h:59
CCHashFN cc_hashfunc[CATCACHE_MAXKEYS]
Definition: catcache.h:50

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

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

◆ CatalogCacheComputeTupleHashValue()

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

Definition at line 367 of file catcache.c.

368 {
369  Datum v1 = 0,
370  v2 = 0,
371  v3 = 0,
372  v4 = 0;
373  bool isNull = false;
374  int *cc_keyno = cache->cc_keyno;
375  TupleDesc cc_tupdesc = cache->cc_tupdesc;
376 
377  /* Now extract key fields from tuple, insert into scankey */
378  switch (nkeys)
379  {
380  case 4:
381  v4 = fastgetattr(tuple,
382  cc_keyno[3],
383  cc_tupdesc,
384  &isNull);
385  Assert(!isNull);
386  /* FALLTHROUGH */
387  case 3:
388  v3 = fastgetattr(tuple,
389  cc_keyno[2],
390  cc_tupdesc,
391  &isNull);
392  Assert(!isNull);
393  /* FALLTHROUGH */
394  case 2:
395  v2 = fastgetattr(tuple,
396  cc_keyno[1],
397  cc_tupdesc,
398  &isNull);
399  Assert(!isNull);
400  /* FALLTHROUGH */
401  case 1:
402  v1 = fastgetattr(tuple,
403  cc_keyno[0],
404  cc_tupdesc,
405  &isNull);
406  Assert(!isNull);
407  break;
408  default:
409  elog(FATAL, "wrong number of hash keys: %d", nkeys);
410  break;
411  }
412 
413  return CatalogCacheComputeHashValue(cache, nkeys, v1, v2, v3, v4);
414 }
#define Assert(condition)
Definition: c.h:858
static uint32 CatalogCacheComputeHashValue(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:325
static Datum fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:749
uintptr_t Datum
Definition: postgres.h:64
int cc_keyno[CATCACHE_MAXKEYS]
Definition: catcache.h:53
TupleDesc cc_tupdesc
Definition: catcache.h:48

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

Referenced by PrepareToInvalidateCacheTuple(), and SearchCatCacheList().

◆ CatalogCacheCreateEntry()

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

Definition at line 2026 of file catcache.c.

2029 {
2030  CatCTup *ct;
2031  HeapTuple dtp;
2032  MemoryContext oldcxt;
2033 
2034  if (ntp)
2035  {
2036  int i;
2037 
2038  /*
2039  * The visibility recheck below essentially never fails during our
2040  * regression tests, and there's no easy way to force it to fail for
2041  * testing purposes. To ensure we have test coverage for the retry
2042  * paths in our callers, make debug builds randomly fail about 0.1% of
2043  * the times through this code path, even when there's no toasted
2044  * fields.
2045  */
2046 #ifdef USE_ASSERT_CHECKING
2048  return NULL;
2049 #endif
2050 
2051  /*
2052  * If there are any out-of-line toasted fields in the tuple, expand
2053  * them in-line. This saves cycles during later use of the catcache
2054  * entry, and also protects us against the possibility of the toast
2055  * tuples being freed before we attempt to fetch them, in case of
2056  * something using a slightly stale catcache entry.
2057  */
2058  if (HeapTupleHasExternal(ntp))
2059  {
2060  dtp = toast_flatten_tuple(ntp, cache->cc_tupdesc);
2061 
2062  /*
2063  * The tuple could become stale while we are doing toast table
2064  * access (since AcceptInvalidationMessages can run then), so we
2065  * must recheck its visibility afterwards.
2066  */
2067  if (!systable_recheck_tuple(scandesc, ntp))
2068  {
2069  heap_freetuple(dtp);
2070  return NULL;
2071  }
2072  }
2073  else
2074  dtp = ntp;
2075 
2076  /* Allocate memory for CatCTup and the cached tuple in one go */
2078 
2079  ct = (CatCTup *) palloc(sizeof(CatCTup) +
2080  MAXIMUM_ALIGNOF + dtp->t_len);
2081  ct->tuple.t_len = dtp->t_len;
2082  ct->tuple.t_self = dtp->t_self;
2083  ct->tuple.t_tableOid = dtp->t_tableOid;
2084  ct->tuple.t_data = (HeapTupleHeader)
2085  MAXALIGN(((char *) ct) + sizeof(CatCTup));
2086  /* copy tuple contents */
2087  memcpy((char *) ct->tuple.t_data,
2088  (const char *) dtp->t_data,
2089  dtp->t_len);
2090  MemoryContextSwitchTo(oldcxt);
2091 
2092  if (dtp != ntp)
2093  heap_freetuple(dtp);
2094 
2095  /* extract keys - they'll point into the tuple if not by-value */
2096  for (i = 0; i < cache->cc_nkeys; i++)
2097  {
2098  Datum atp;
2099  bool isnull;
2100 
2101  atp = heap_getattr(&ct->tuple,
2102  cache->cc_keyno[i],
2103  cache->cc_tupdesc,
2104  &isnull);
2105  Assert(!isnull);
2106  ct->keys[i] = atp;
2107  }
2108  }
2109  else
2110  {
2111  /* Set up keys for a negative cache entry */
2113  ct = (CatCTup *) palloc(sizeof(CatCTup));
2114 
2115  /*
2116  * Store keys - they'll point into separately allocated memory if not
2117  * by-value.
2118  */
2119  CatCacheCopyKeys(cache->cc_tupdesc, cache->cc_nkeys, cache->cc_keyno,
2120  arguments, ct->keys);
2121  MemoryContextSwitchTo(oldcxt);
2122  }
2123 
2124  /*
2125  * Finish initializing the CatCTup header, and add it to the cache's
2126  * linked list and counts.
2127  */
2128  ct->ct_magic = CT_MAGIC;
2129  ct->my_cache = cache;
2130  ct->c_list = NULL;
2131  ct->refcount = 0; /* for the moment */
2132  ct->dead = false;
2133  ct->negative = (ntp == NULL);
2134  ct->hash_value = hashValue;
2135 
2136  dlist_push_head(&cache->cc_bucket[hashIndex], &ct->cache_elem);
2137 
2138  cache->cc_ntup++;
2139  CacheHdr->ch_ntup++;
2140 
2141  /*
2142  * If the hash table has become too full, enlarge the buckets array. Quite
2143  * arbitrarily, we enlarge when fill factor > 2.
2144  */
2145  if (cache->cc_ntup > cache->cc_nbuckets * 2)
2146  RehashCatCache(cache);
2147 
2148  return ct;
2149 }
#define MAXALIGN(LEN)
Definition: c.h:811
#define PG_UINT32_MAX
Definition: c.h:590
static void RehashCatCache(CatCache *cp)
Definition: catcache.c:934
static void CatCacheCopyKeys(TupleDesc tupdesc, int nkeys, int *attnos, Datum *srckeys, Datum *dstkeys)
Definition: catcache.c:2180
static CatCacheHeader * CacheHdr
Definition: catcache.c:64
#define CT_MAGIC
Definition: catcache.h:91
bool systable_recheck_tuple(SysScanDesc sysscan, HeapTuple tup)
Definition: genam.c:562
HeapTuple toast_flatten_tuple(HeapTuple tup, TupleDesc tupleDesc)
Definition: heaptoast.c:350
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1434
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:792
#define HeapTupleHasExternal(tuple)
Definition: htup_details.h:671
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:347
MemoryContext CacheMemoryContext
Definition: mcxt.c:152
void * palloc(Size size)
Definition: mcxt.c:1316
uint32 pg_prng_uint32(pg_prng_state *state)
Definition: pg_prng.c:227
pg_prng_state pg_global_prng_state
Definition: pg_prng.c:34
MemoryContextSwitchTo(old_ctx)
ItemPointerData t_self
Definition: htup.h:65
uint32 t_len
Definition: htup.h:64
HeapTupleHeader t_data
Definition: htup.h:68
Oid t_tableOid
Definition: htup.h:66
dlist_head * cc_bucket
Definition: catcache.h:49
int cc_nkeys
Definition: catcache.h:54
int cc_nbuckets
Definition: catcache.h:47
int cc_ntup
Definition: catcache.h:55
int ct_magic
Definition: catcache.h:90
int refcount
Definition: catcache.h:120
bool negative
Definition: catcache.h:122
dlist_node cache_elem
Definition: catcache.h:106
HeapTupleData tuple
Definition: catcache.h:123
CatCache * my_cache
Definition: catcache.h:134
struct catclist * c_list
Definition: catcache.h:132
Datum keys[CATCACHE_MAXKEYS]
Definition: catcache.h:99
bool dead
Definition: catcache.h:121
uint32 hash_value
Definition: catcache.h:93

References Assert, catctup::c_list, catctup::cache_elem, CacheHdr, 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(), pg_global_prng_state, pg_prng_uint32(), PG_UINT32_MAX, catctup::refcount, RehashCatCache(), systable_recheck_tuple(), HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, toast_flatten_tuple(), and catctup::tuple.

Referenced by SearchCatCacheList(), and SearchCatCacheMiss().

◆ CatalogCacheFlushCatalog()

void CatalogCacheFlushCatalog ( Oid  catId)

Definition at line 783 of file catcache.c.

784 {
785  slist_iter iter;
786 
787  CACHE_elog(DEBUG2, "CatalogCacheFlushCatalog called for %u", catId);
788 
790  {
791  CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
792 
793  /* Does this cache store tuples of the target catalog? */
794  if (cache->cc_reloid == catId)
795  {
796  /* Yes, so flush all its contents */
797  ResetCatalogCache(cache);
798 
799  /* Tell inval.c to call syscache callbacks for this cache */
800  CallSyscacheCallbacks(cache->id, 0);
801  }
802  }
803 
804  CACHE_elog(DEBUG2, "end of CatalogCacheFlushCatalog call");
805 }
static void ResetCatalogCache(CatCache *cache)
Definition: catcache.c:701
#define slist_container(type, membername, ptr)
Definition: ilist.h:1106
#define slist_foreach(iter, lhead)
Definition: ilist.h:1132
void CallSyscacheCallbacks(int cacheid, uint32 hashvalue)
Definition: inval.c:1577
Oid cc_reloid
Definition: catcache.h:60
int id
Definition: catcache.h:46
slist_head ch_caches
Definition: catcache.h:186
slist_node * cur
Definition: ilist.h:259

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

Referenced by LocalExecuteInvalidationMessage().

◆ CatalogCacheInitializeCache()

static void CatalogCacheInitializeCache ( CatCache cache)
static

Definition at line 1035 of file catcache.c.

1036 {
1037  Relation relation;
1038  MemoryContext oldcxt;
1039  TupleDesc tupdesc;
1040  int i;
1041 
1043 
1044  relation = table_open(cache->cc_reloid, AccessShareLock);
1045 
1046  /*
1047  * switch to the cache context so our allocations do not vanish at the end
1048  * of a transaction
1049  */
1050  Assert(CacheMemoryContext != NULL);
1051 
1053 
1054  /*
1055  * copy the relcache's tuple descriptor to permanent cache storage
1056  */
1057  tupdesc = CreateTupleDescCopyConstr(RelationGetDescr(relation));
1058 
1059  /*
1060  * save the relation's name and relisshared flag, too (cc_relname is used
1061  * only for debugging purposes)
1062  */
1063  cache->cc_relname = pstrdup(RelationGetRelationName(relation));
1064  cache->cc_relisshared = RelationGetForm(relation)->relisshared;
1065 
1066  /*
1067  * return to the caller's memory context and close the rel
1068  */
1069  MemoryContextSwitchTo(oldcxt);
1070 
1071  table_close(relation, AccessShareLock);
1072 
1073  CACHE_elog(DEBUG2, "CatalogCacheInitializeCache: %s, %d keys",
1074  cache->cc_relname, cache->cc_nkeys);
1075 
1076  /*
1077  * initialize cache's key information
1078  */
1079  for (i = 0; i < cache->cc_nkeys; ++i)
1080  {
1081  Oid keytype;
1082  RegProcedure eqfunc;
1083 
1085 
1086  if (cache->cc_keyno[i] > 0)
1087  {
1088  Form_pg_attribute attr = TupleDescAttr(tupdesc,
1089  cache->cc_keyno[i] - 1);
1090 
1091  keytype = attr->atttypid;
1092  /* cache key columns should always be NOT NULL */
1093  Assert(attr->attnotnull);
1094  }
1095  else
1096  {
1097  if (cache->cc_keyno[i] < 0)
1098  elog(FATAL, "sys attributes are not supported in caches");
1099  keytype = OIDOID;
1100  }
1101 
1102  GetCCHashEqFuncs(keytype,
1103  &cache->cc_hashfunc[i],
1104  &eqfunc,
1105  &cache->cc_fastequal[i]);
1106 
1107  /*
1108  * Do equality-function lookup (we assume this won't need a catalog
1109  * lookup for any supported type)
1110  */
1111  fmgr_info_cxt(eqfunc,
1112  &cache->cc_skey[i].sk_func,
1114 
1115  /* Initialize sk_attno suitably for HeapKeyTest() and heap scans */
1116  cache->cc_skey[i].sk_attno = cache->cc_keyno[i];
1117 
1118  /* Fill in sk_strategy as well --- always standard equality */
1120  cache->cc_skey[i].sk_subtype = InvalidOid;
1121  /* If a catcache key requires a collation, it must be C collation */
1122  cache->cc_skey[i].sk_collation = C_COLLATION_OID;
1123 
1124  CACHE_elog(DEBUG2, "CatalogCacheInitializeCache %s %d %p",
1125  cache->cc_relname, i, cache);
1126  }
1127 
1128  /*
1129  * mark this cache fully initialized
1130  */
1131  cache->cc_tupdesc = tupdesc;
1132 }
regproc RegProcedure
Definition: c.h:650
#define CatalogCacheInitializeCache_DEBUG1
Definition: catcache.c:1030
static void GetCCHashEqFuncs(Oid keytype, CCHashFN *hashfunc, RegProcedure *eqfunc, CCFastEqualFN *fasteqfunc)
Definition: catcache.c:255
#define CatalogCacheInitializeCache_DEBUG2
Definition: catcache.c:1031
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:137
#define AccessShareLock
Definition: lockdefs.h:36
char * pstrdup(const char *in)
Definition: mcxt.c:1695
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
#define RelationGetForm(relation)
Definition: rel.h:499
#define RelationGetDescr(relation)
Definition: rel.h:531
#define RelationGetRelationName(relation)
Definition: rel.h:539
#define BTEqualStrategyNumber
Definition: stratnum.h:31
FmgrInfo sk_func
Definition: skey.h:71
Oid sk_subtype
Definition: skey.h:69
Oid sk_collation
Definition: skey.h:70
StrategyNumber sk_strategy
Definition: skey.h:68
AttrNumber sk_attno
Definition: skey.h:67
bool cc_relisshared
Definition: catcache.h:62
ScanKeyData cc_skey[CATCACHE_MAXKEYS]
Definition: catcache.h:64
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc)
Definition: tupdesc.c:173
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92

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

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

◆ CatCacheCopyKeys()

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

Definition at line 2180 of file catcache.c.

2182 {
2183  int i;
2184 
2185  /*
2186  * XXX: memory and lookup performance could possibly be improved by
2187  * storing all keys in one allocation.
2188  */
2189 
2190  for (i = 0; i < nkeys; i++)
2191  {
2192  int attnum = attnos[i];
2193  Form_pg_attribute att = TupleDescAttr(tupdesc, attnum - 1);
2194  Datum src = srckeys[i];
2195  NameData srcname;
2196 
2197  /*
2198  * Must be careful in case the caller passed a C string where a NAME
2199  * is wanted: convert the given argument to a correctly padded NAME.
2200  * Otherwise the memcpy() done by datumCopy() could fall off the end
2201  * of memory.
2202  */
2203  if (att->atttypid == NAMEOID)
2204  {
2205  namestrcpy(&srcname, DatumGetCString(src));
2206  src = NameGetDatum(&srcname);
2207  }
2208 
2209  dstkeys[i] = datumCopy(src,
2210  att->attbyval,
2211  att->attlen);
2212  }
2213 }
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:132
void namestrcpy(Name name, const char *str)
Definition: name.c:233
int16 attnum
Definition: pg_attribute.h:74
static char * DatumGetCString(Datum X)
Definition: postgres.h:335
static Datum NameGetDatum(const NameData *X)
Definition: postgres.h:373
Definition: c.h:741

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

Referenced by CatalogCacheCreateEntry(), and SearchCatCacheList().

◆ CatCacheFreeKeys()

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

Definition at line 2155 of file catcache.c.

2156 {
2157  int i;
2158 
2159  for (i = 0; i < nkeys; i++)
2160  {
2161  int attnum = attnos[i];
2162  Form_pg_attribute att;
2163 
2164  /* system attribute are not supported in caches */
2165  Assert(attnum > 0);
2166 
2167  att = TupleDescAttr(tupdesc, attnum - 1);
2168 
2169  if (!att->attbyval)
2170  pfree(DatumGetPointer(keys[i]));
2171  }
2172 }
void pfree(void *pointer)
Definition: mcxt.c:1520
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312

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

Referenced by CatCacheRemoveCList(), and CatCacheRemoveCTup().

◆ CatCacheInvalidate()

void CatCacheInvalidate ( CatCache cache,
uint32  hashValue 
)

Definition at line 606 of file catcache.c.

607 {
608  Index hashIndex;
609  dlist_mutable_iter iter;
610 
611  CACHE_elog(DEBUG2, "CatCacheInvalidate: called");
612 
613  /*
614  * We don't bother to check whether the cache has finished initialization
615  * yet; if not, there will be no entries in it so no problem.
616  */
617 
618  /*
619  * Invalidate *all* CatCLists in this cache; it's too hard to tell which
620  * searches might still be correct, so just zap 'em all.
621  */
622  for (int i = 0; i < cache->cc_nlbuckets; i++)
623  {
624  dlist_head *bucket = &cache->cc_lbucket[i];
625 
626  dlist_foreach_modify(iter, bucket)
627  {
628  CatCList *cl = dlist_container(CatCList, cache_elem, iter.cur);
629 
630  if (cl->refcount > 0)
631  cl->dead = true;
632  else
633  CatCacheRemoveCList(cache, cl);
634  }
635  }
636 
637  /*
638  * inspect the proper hash bucket for tuple matches
639  */
640  hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
641  dlist_foreach_modify(iter, &cache->cc_bucket[hashIndex])
642  {
643  CatCTup *ct = dlist_container(CatCTup, cache_elem, iter.cur);
644 
645  if (hashValue == ct->hash_value)
646  {
647  if (ct->refcount > 0 ||
648  (ct->c_list && ct->c_list->refcount > 0))
649  {
650  ct->dead = true;
651  /* list, if any, was marked dead above */
652  Assert(ct->c_list == NULL || ct->c_list->dead);
653  }
654  else
655  CatCacheRemoveCTup(cache, ct);
656  CACHE_elog(DEBUG2, "CatCacheInvalidate: invalidated");
657 #ifdef CATCACHE_STATS
658  cache->cc_invals++;
659 #endif
660  /* could be multiple matches, so keep looking! */
661  }
662  }
663 }
unsigned int Index
Definition: c.h:614
static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
Definition: catcache.c:509
static void CatCacheRemoveCList(CatCache *cache, CatCList *cl)
Definition: catcache.c:551
#define HASH_INDEX(h, sz)
Definition: catcache.c:50
#define dlist_foreach_modify(iter, lhead)
Definition: ilist.h:640
#define dlist_container(type, membername, ptr)
Definition: ilist.h:593
int cc_nlbuckets
Definition: catcache.h:57
dlist_head * cc_lbucket
Definition: catcache.h:58
int refcount
Definition: catcache.h:174
bool dead
Definition: catcache.h:175
dlist_node * cur
Definition: ilist.h:200

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

Referenced by SysCacheInvalidate().

◆ CatCacheRemoveCList()

static void CatCacheRemoveCList ( CatCache cache,
CatCList cl 
)
static

Definition at line 551 of file catcache.c.

552 {
553  int i;
554 
555  Assert(cl->refcount == 0);
556  Assert(cl->my_cache == cache);
557 
558  /* delink from member tuples */
559  for (i = cl->n_members; --i >= 0;)
560  {
561  CatCTup *ct = cl->members[i];
562 
563  Assert(ct->c_list == cl);
564  ct->c_list = NULL;
565  /* if the member is dead and now has no references, remove it */
566  if (
567 #ifndef CATCACHE_FORCE_RELEASE
568  ct->dead &&
569 #endif
570  ct->refcount == 0)
571  CatCacheRemoveCTup(cache, ct);
572  }
573 
574  /* delink from linked list */
575  dlist_delete(&cl->cache_elem);
576 
577  /* free associated column data */
578  CatCacheFreeKeys(cache->cc_tupdesc, cl->nkeys,
579  cache->cc_keyno, cl->keys);
580 
581  pfree(cl);
582 
583  --cache->cc_nlist;
584 }
static void CatCacheFreeKeys(TupleDesc tupdesc, int nkeys, int *attnos, Datum *keys)
Definition: catcache.c:2155
static void dlist_delete(dlist_node *node)
Definition: ilist.h:405
int cc_nlist
Definition: catcache.h:56
dlist_node cache_elem
Definition: catcache.h:166
CatCache * my_cache
Definition: catcache.h:179
short nkeys
Definition: catcache.h:177
Datum keys[CATCACHE_MAXKEYS]
Definition: catcache.h:172
CatCTup * members[FLEXIBLE_ARRAY_MEMBER]
Definition: catcache.h:180
int n_members
Definition: catcache.h:178

References Assert, catctup::c_list, catclist::cache_elem, CatCacheFreeKeys(), CatCacheRemoveCTup(), catcache::cc_keyno, catcache::cc_nlist, 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(), ReleaseCatCacheListWithOwner(), and ResetCatalogCache().

◆ CatCacheRemoveCTup()

static void CatCacheRemoveCTup ( CatCache cache,
CatCTup ct 
)
static

Definition at line 509 of file catcache.c.

510 {
511  Assert(ct->refcount == 0);
512  Assert(ct->my_cache == cache);
513 
514  if (ct->c_list)
515  {
516  /*
517  * The cleanest way to handle this is to call CatCacheRemoveCList,
518  * which will recurse back to me, and the recursive call will do the
519  * work. Set the "dead" flag to make sure it does recurse.
520  */
521  ct->dead = true;
522  CatCacheRemoveCList(cache, ct->c_list);
523  return; /* nothing left to do */
524  }
525 
526  /* delink from linked list */
527  dlist_delete(&ct->cache_elem);
528 
529  /*
530  * Free keys when we're dealing with a negative entry, normal entries just
531  * point into tuple, allocated together with the CatCTup.
532  */
533  if (ct->negative)
534  CatCacheFreeKeys(cache->cc_tupdesc, cache->cc_nkeys,
535  cache->cc_keyno, ct->keys);
536 
537  pfree(ct);
538 
539  --cache->cc_ntup;
540  --CacheHdr->ch_ntup;
541 }

References Assert, catctup::c_list, catctup::cache_elem, CacheHdr, 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(), ReleaseCatCacheWithOwner(), ResetCatalogCache(), and SearchCatCacheList().

◆ chareqfast()

static bool chareqfast ( Datum  a,
Datum  b 
)
static

Definition at line 172 of file catcache.c.

173 {
174  return DatumGetChar(a) == DatumGetChar(b);
175 }
int b
Definition: isn.c:70
int a
Definition: isn.c:69
static char DatumGetChar(Datum X)
Definition: postgres.h:112

References a, b, and DatumGetChar().

Referenced by GetCCHashEqFuncs().

◆ charhashfast()

static uint32 charhashfast ( Datum  datum)
static

Definition at line 178 of file catcache.c.

179 {
180  return murmurhash32((int32) DatumGetChar(datum));
181 }
signed int int32
Definition: c.h:494
static uint32 murmurhash32(uint32 data)
Definition: hashfn.h:92

References DatumGetChar(), and murmurhash32().

Referenced by GetCCHashEqFuncs().

◆ CreateCacheMemoryContext()

void CreateCacheMemoryContext ( void  )

Definition at line 679 of file catcache.c.

680 {
681  /*
682  * Purely for paranoia, check that context doesn't exist; caller probably
683  * did so already.
684  */
685  if (!CacheMemoryContext)
687  "CacheMemoryContext",
689 }
MemoryContext TopMemoryContext
Definition: mcxt.c:149
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CacheMemoryContext, and TopMemoryContext.

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

◆ GetCatCacheHashValue()

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

Definition at line 1612 of file catcache.c.

1617 {
1618  /*
1619  * one-time startup overhead for each cache
1620  */
1621  if (cache->cc_tupdesc == NULL)
1623 
1624  /*
1625  * calculate the hash value
1626  */
1627  return CatalogCacheComputeHashValue(cache, cache->cc_nkeys, v1, v2, v3, v4);
1628 }
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:1035

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

Referenced by GetSysCacheHashValue().

◆ GetCCHashEqFuncs()

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

Definition at line 255 of file catcache.c.

256 {
257  switch (keytype)
258  {
259  case BOOLOID:
260  *hashfunc = charhashfast;
261  *fasteqfunc = chareqfast;
262  *eqfunc = F_BOOLEQ;
263  break;
264  case CHAROID:
265  *hashfunc = charhashfast;
266  *fasteqfunc = chareqfast;
267  *eqfunc = F_CHAREQ;
268  break;
269  case NAMEOID:
270  *hashfunc = namehashfast;
271  *fasteqfunc = nameeqfast;
272  *eqfunc = F_NAMEEQ;
273  break;
274  case INT2OID:
275  *hashfunc = int2hashfast;
276  *fasteqfunc = int2eqfast;
277  *eqfunc = F_INT2EQ;
278  break;
279  case INT4OID:
280  *hashfunc = int4hashfast;
281  *fasteqfunc = int4eqfast;
282  *eqfunc = F_INT4EQ;
283  break;
284  case TEXTOID:
285  *hashfunc = texthashfast;
286  *fasteqfunc = texteqfast;
287  *eqfunc = F_TEXTEQ;
288  break;
289  case OIDOID:
290  case REGPROCOID:
291  case REGPROCEDUREOID:
292  case REGOPEROID:
293  case REGOPERATOROID:
294  case REGCLASSOID:
295  case REGTYPEOID:
296  case REGCOLLATIONOID:
297  case REGCONFIGOID:
298  case REGDICTIONARYOID:
299  case REGROLEOID:
300  case REGNAMESPACEOID:
301  *hashfunc = int4hashfast;
302  *fasteqfunc = int4eqfast;
303  *eqfunc = F_OIDEQ;
304  break;
305  case OIDVECTOROID:
306  *hashfunc = oidvectorhashfast;
307  *fasteqfunc = oidvectoreqfast;
308  *eqfunc = F_OIDVECTOREQ;
309  break;
310  default:
311  elog(FATAL, "type %u not supported as catcache key", keytype);
312  *hashfunc = NULL; /* keep compiler quiet */
313 
314  *eqfunc = InvalidOid;
315  break;
316  }
317 }
static bool chareqfast(Datum a, Datum b)
Definition: catcache.c:172
static bool int4eqfast(Datum a, Datum b)
Definition: catcache.c:213
static bool int2eqfast(Datum a, Datum b)
Definition: catcache.c:201
static uint32 int4hashfast(Datum datum)
Definition: catcache.c:219
static uint32 namehashfast(Datum datum)
Definition: catcache.c:193
static bool nameeqfast(Datum a, Datum b)
Definition: catcache.c:184
static uint32 charhashfast(Datum datum)
Definition: catcache.c:178
static uint32 oidvectorhashfast(Datum datum)
Definition: catcache.c:248
static bool texteqfast(Datum a, Datum b)
Definition: catcache.c:225
static bool oidvectoreqfast(Datum a, Datum b)
Definition: catcache.c:242
static uint32 int2hashfast(Datum datum)
Definition: catcache.c:207
static uint32 texthashfast(Datum datum)
Definition: catcache.c:235

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

Referenced by CatalogCacheInitializeCache().

◆ IndexScanOK()

static bool IndexScanOK ( CatCache cache,
ScanKey  cur_skey 
)
static

Definition at line 1196 of file catcache.c.

1197 {
1198  switch (cache->id)
1199  {
1200  case INDEXRELID:
1201 
1202  /*
1203  * Rather than tracking exactly which indexes have to be loaded
1204  * before we can use indexscans (which changes from time to time),
1205  * just force all pg_index searches to be heap scans until we've
1206  * built the critical relcaches.
1207  */
1209  return false;
1210  break;
1211 
1212  case AMOID:
1213  case AMNAME:
1214 
1215  /*
1216  * Always do heap scans in pg_am, because it's so small there's
1217  * not much point in an indexscan anyway. We *must* do this when
1218  * initially building critical relcache entries, but we might as
1219  * well just always do it.
1220  */
1221  return false;
1222 
1223  case AUTHNAME:
1224  case AUTHOID:
1225  case AUTHMEMMEMROLE:
1226  case DATABASEOID:
1227 
1228  /*
1229  * Protect authentication lookups occurring before relcache has
1230  * collected entries for shared indexes.
1231  */
1233  return false;
1234  break;
1235 
1236  default:
1237  break;
1238  }
1239 
1240  /* Normal case, allow index scan */
1241  return true;
1242 }
bool criticalRelcachesBuilt
Definition: relcache.c:140
bool criticalSharedRelcachesBuilt
Definition: relcache.c:146

References criticalRelcachesBuilt, criticalSharedRelcachesBuilt, and catcache::id.

Referenced by SearchCatCacheList(), and SearchCatCacheMiss().

◆ InitCatCache()

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

Definition at line 827 of file catcache.c.

833 {
834  CatCache *cp;
835  MemoryContext oldcxt;
836  int i;
837 
838  /*
839  * nbuckets is the initial number of hash buckets to use in this catcache.
840  * It will be enlarged later if it becomes too full.
841  *
842  * nbuckets must be a power of two. We check this via Assert rather than
843  * a full runtime check because the values will be coming from constant
844  * tables.
845  *
846  * If you're confused by the power-of-two check, see comments in
847  * bitmapset.c for an explanation.
848  */
849  Assert(nbuckets > 0 && (nbuckets & -nbuckets) == nbuckets);
850 
851  /*
852  * first switch to the cache context so our allocations do not vanish at
853  * the end of a transaction
854  */
855  if (!CacheMemoryContext)
857 
859 
860  /*
861  * if first time through, initialize the cache group header
862  */
863  if (CacheHdr == NULL)
864  {
867  CacheHdr->ch_ntup = 0;
868 #ifdef CATCACHE_STATS
869  /* set up to dump stats at backend exit */
870  on_proc_exit(CatCachePrintStats, 0);
871 #endif
872  }
873 
874  /*
875  * Allocate a new cache structure, aligning to a cacheline boundary
876  *
877  * Note: we rely on zeroing to initialize all the dlist headers correctly
878  */
881  cp->cc_bucket = palloc0(nbuckets * sizeof(dlist_head));
882 
883  /*
884  * Many catcaches never receive any list searches. Therefore, we don't
885  * allocate the cc_lbuckets till we get a list search.
886  */
887  cp->cc_lbucket = NULL;
888 
889  /*
890  * initialize the cache's relation information for the relation
891  * corresponding to this cache, and initialize some of the new cache's
892  * other internal fields. But don't open the relation yet.
893  */
894  cp->id = id;
895  cp->cc_relname = "(not known yet)";
896  cp->cc_reloid = reloid;
897  cp->cc_indexoid = indexoid;
898  cp->cc_relisshared = false; /* temporary */
899  cp->cc_tupdesc = (TupleDesc) NULL;
900  cp->cc_ntup = 0;
901  cp->cc_nlist = 0;
902  cp->cc_nbuckets = nbuckets;
903  cp->cc_nlbuckets = 0;
904  cp->cc_nkeys = nkeys;
905  for (i = 0; i < nkeys; ++i)
906  {
908  cp->cc_keyno[i] = key[i];
909  }
910 
911  /*
912  * new cache is initialized as far as we can go for now. print some
913  * debugging information, if appropriate.
914  */
916 
917  /*
918  * add completed cache to top of group header's list
919  */
921 
922  /*
923  * back to the old context before we return...
924  */
925  MemoryContextSwitchTo(oldcxt);
926 
927  return cp;
928 }
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
void CreateCacheMemoryContext(void)
Definition: catcache.c:679
#define InitCatCache_DEBUG2
Definition: catcache.c:823
#define MCXT_ALLOC_ZERO
Definition: fe_memutils.h:18
static void slist_init(slist_head *head)
Definition: ilist.h:986
static void slist_push_head(slist_head *head, slist_node *node)
Definition: ilist.h:1006
void on_proc_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:309
void * palloc0(Size size)
Definition: mcxt.c:1346
void * palloc_aligned(Size size, Size alignto, int flags)
Definition: mcxt.c:1510
#define PG_CACHE_LINE_SIZE
slist_node cc_next
Definition: catcache.h:63
Oid cc_indexoid
Definition: catcache.h:61
struct TupleDescData * TupleDesc
Definition: tupdesc.h:89

References Assert, AttributeNumberIsValid, CacheHdr, CacheMemoryContext, catcache::cc_bucket, catcache::cc_indexoid, catcache::cc_keyno, catcache::cc_lbucket, catcache::cc_nbuckets, catcache::cc_next, catcache::cc_nkeys, catcache::cc_nlbuckets, catcache::cc_nlist, catcache::cc_ntup, catcache::cc_relisshared, catcache::cc_relname, catcache::cc_reloid, catcache::cc_tupdesc, catcacheheader::ch_caches, catcacheheader::ch_ntup, CreateCacheMemoryContext(), i, catcache::id, InitCatCache_DEBUG2, sort-test::key, MCXT_ALLOC_ZERO, MemoryContextSwitchTo(), on_proc_exit(), palloc(), palloc0(), palloc_aligned(), PG_CACHE_LINE_SIZE, slist_init(), and slist_push_head().

Referenced by InitCatalogCache().

◆ InitCatCachePhase2()

void InitCatCachePhase2 ( CatCache cache,
bool  touch_index 
)

Definition at line 1144 of file catcache.c.

1145 {
1146  if (cache->cc_tupdesc == NULL)
1148 
1149  if (touch_index &&
1150  cache->id != AMOID &&
1151  cache->id != AMNAME)
1152  {
1153  Relation idesc;
1154 
1155  /*
1156  * We must lock the underlying catalog before opening the index to
1157  * avoid deadlock, since index_open could possibly result in reading
1158  * this same catalog, and if anyone else is exclusive-locking this
1159  * catalog and index they'll be doing it in that order.
1160  */
1162  idesc = index_open(cache->cc_indexoid, AccessShareLock);
1163 
1164  /*
1165  * While we've got the index open, let's check that it's unique (and
1166  * not just deferrable-unique, thank you very much). This is just to
1167  * catch thinkos in definitions of new catcaches, so we don't worry
1168  * about the pg_am indexes not getting tested.
1169  */
1170  Assert(idesc->rd_index->indisunique &&
1171  idesc->rd_index->indimmediate);
1172 
1173  index_close(idesc, AccessShareLock);
1175  }
1176 }
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:177
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:133
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:227
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:108
Form_pg_index rd_index
Definition: rel.h:192

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

◆ int2eqfast()

static bool int2eqfast ( Datum  a,
Datum  b 
)
static

Definition at line 201 of file catcache.c.

202 {
203  return DatumGetInt16(a) == DatumGetInt16(b);
204 }
static int16 DatumGetInt16(Datum X)
Definition: postgres.h:162

References a, b, and DatumGetInt16().

Referenced by GetCCHashEqFuncs().

◆ int2hashfast()

static uint32 int2hashfast ( Datum  datum)
static

Definition at line 207 of file catcache.c.

208 {
209  return murmurhash32((int32) DatumGetInt16(datum));
210 }

References DatumGetInt16(), and murmurhash32().

Referenced by GetCCHashEqFuncs().

◆ int4eqfast()

static bool int4eqfast ( Datum  a,
Datum  b 
)
static

Definition at line 213 of file catcache.c.

214 {
215  return DatumGetInt32(a) == DatumGetInt32(b);
216 }
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:202

References a, b, and DatumGetInt32().

Referenced by GetCCHashEqFuncs().

◆ int4hashfast()

static uint32 int4hashfast ( Datum  datum)
static

Definition at line 219 of file catcache.c.

220 {
221  return murmurhash32((int32) DatumGetInt32(datum));
222 }

References DatumGetInt32(), and murmurhash32().

Referenced by GetCCHashEqFuncs().

◆ nameeqfast()

static bool nameeqfast ( Datum  a,
Datum  b 
)
static

Definition at line 184 of file catcache.c.

185 {
186  char *ca = NameStr(*DatumGetName(a));
187  char *cb = NameStr(*DatumGetName(b));
188 
189  return strncmp(ca, cb, NAMEDATALEN) == 0;
190 }
#define NameStr(name)
Definition: c.h:746
#define NAMEDATALEN
static Name DatumGetName(Datum X)
Definition: postgres.h:360

References a, b, DatumGetName(), NAMEDATALEN, and NameStr.

Referenced by GetCCHashEqFuncs().

◆ namehashfast()

static uint32 namehashfast ( Datum  datum)
static

Definition at line 193 of file catcache.c.

194 {
195  char *key = NameStr(*DatumGetName(datum));
196 
197  return hash_any((unsigned char *) key, strlen(key));
198 }
static Datum hash_any(const unsigned char *k, int keylen)
Definition: hashfn.h:31

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

Referenced by GetCCHashEqFuncs().

◆ oidvectoreqfast()

static bool oidvectoreqfast ( Datum  a,
Datum  b 
)
static

Definition at line 242 of file catcache.c.

243 {
245 }
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:644
Datum oidvectoreq(PG_FUNCTION_ARGS)
Definition: oid.c:344
static bool DatumGetBool(Datum X)
Definition: postgres.h:90

References a, b, DatumGetBool(), DirectFunctionCall2, and oidvectoreq().

Referenced by GetCCHashEqFuncs().

◆ oidvectorhashfast()

static uint32 oidvectorhashfast ( Datum  datum)
static

Definition at line 248 of file catcache.c.

249 {
251 }
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:642
Datum hashoidvector(PG_FUNCTION_ARGS)
Definition: hashfunc.c:232

References DatumGetInt32(), DirectFunctionCall1, and hashoidvector().

Referenced by GetCCHashEqFuncs().

◆ PrepareToInvalidateCacheTuple()

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

Definition at line 2250 of file catcache.c.

2254 {
2255  slist_iter iter;
2256  Oid reloid;
2257 
2258  CACHE_elog(DEBUG2, "PrepareToInvalidateCacheTuple: called");
2259 
2260  /*
2261  * sanity checks
2262  */
2263  Assert(RelationIsValid(relation));
2264  Assert(HeapTupleIsValid(tuple));
2265  Assert(PointerIsValid(function));
2266  Assert(CacheHdr != NULL);
2267 
2268  reloid = RelationGetRelid(relation);
2269 
2270  /* ----------------
2271  * for each cache
2272  * if the cache contains tuples from the specified relation
2273  * compute the tuple's hash value(s) in this cache,
2274  * and call the passed function to register the information.
2275  * ----------------
2276  */
2277 
2279  {
2280  CatCache *ccp = slist_container(CatCache, cc_next, iter.cur);
2281  uint32 hashvalue;
2282  Oid dbid;
2283 
2284  if (ccp->cc_reloid != reloid)
2285  continue;
2286 
2287  /* Just in case cache hasn't finished initialization yet... */
2288  if (ccp->cc_tupdesc == NULL)
2290 
2291  hashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, tuple);
2292  dbid = ccp->cc_relisshared ? (Oid) 0 : MyDatabaseId;
2293 
2294  (*function) (ccp->id, hashvalue, dbid);
2295 
2296  if (newtuple)
2297  {
2298  uint32 newhashvalue;
2299 
2300  newhashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, newtuple);
2301 
2302  if (newhashvalue != hashvalue)
2303  (*function) (ccp->id, newhashvalue, dbid);
2304  }
2305  }
2306 }
#define PointerIsValid(pointer)
Definition: c.h:763
static uint32 CatalogCacheComputeTupleHashValue(CatCache *cache, int nkeys, HeapTuple tuple)
Definition: catcache.c:367
Oid MyDatabaseId
Definition: globals.c:91
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define RelationGetRelid(relation)
Definition: rel.h:505
#define RelationIsValid(relation)
Definition: rel.h:478

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

Referenced by CacheInvalidateHeapTuple().

◆ RehashCatCache()

static void RehashCatCache ( CatCache cp)
static

Definition at line 934 of file catcache.c.

935 {
936  dlist_head *newbucket;
937  int newnbuckets;
938  int i;
939 
940  elog(DEBUG1, "rehashing catalog cache id %d for %s; %d tups, %d buckets",
941  cp->id, cp->cc_relname, cp->cc_ntup, cp->cc_nbuckets);
942 
943  /* Allocate a new, larger, hash table. */
944  newnbuckets = cp->cc_nbuckets * 2;
945  newbucket = (dlist_head *) MemoryContextAllocZero(CacheMemoryContext, newnbuckets * sizeof(dlist_head));
946 
947  /* Move all entries from old hash table to new. */
948  for (i = 0; i < cp->cc_nbuckets; i++)
949  {
950  dlist_mutable_iter iter;
951 
952  dlist_foreach_modify(iter, &cp->cc_bucket[i])
953  {
954  CatCTup *ct = dlist_container(CatCTup, cache_elem, iter.cur);
955  int hashIndex = HASH_INDEX(ct->hash_value, newnbuckets);
956 
957  dlist_delete(iter.cur);
958  dlist_push_head(&newbucket[hashIndex], &ct->cache_elem);
959  }
960  }
961 
962  /* Switch to the new array. */
963  pfree(cp->cc_bucket);
964  cp->cc_nbuckets = newnbuckets;
965  cp->cc_bucket = newbucket;
966 }
#define DEBUG1
Definition: elog.h:30
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1214

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

◆ RehashCatCacheLists()

static void RehashCatCacheLists ( CatCache cp)
static

Definition at line 972 of file catcache.c.

973 {
974  dlist_head *newbucket;
975  int newnbuckets;
976  int i;
977 
978  elog(DEBUG1, "rehashing catalog cache id %d for %s; %d lists, %d buckets",
979  cp->id, cp->cc_relname, cp->cc_nlist, cp->cc_nlbuckets);
980 
981  /* Allocate a new, larger, hash table. */
982  newnbuckets = cp->cc_nlbuckets * 2;
983  newbucket = (dlist_head *) MemoryContextAllocZero(CacheMemoryContext, newnbuckets * sizeof(dlist_head));
984 
985  /* Move all entries from old hash table to new. */
986  for (i = 0; i < cp->cc_nlbuckets; i++)
987  {
988  dlist_mutable_iter iter;
989 
990  dlist_foreach_modify(iter, &cp->cc_lbucket[i])
991  {
992  CatCList *cl = dlist_container(CatCList, cache_elem, iter.cur);
993  int hashIndex = HASH_INDEX(cl->hash_value, newnbuckets);
994 
995  dlist_delete(iter.cur);
996  dlist_push_head(&newbucket[hashIndex], &cl->cache_elem);
997  }
998  }
999 
1000  /* Switch to the new array. */
1001  pfree(cp->cc_lbucket);
1002  cp->cc_nlbuckets = newnbuckets;
1003  cp->cc_lbucket = newbucket;
1004 }
uint32 hash_value
Definition: catcache.h:164

References catclist::cache_elem, CacheMemoryContext, catcache::cc_lbucket, catcache::cc_nlbuckets, catcache::cc_nlist, catcache::cc_relname, dlist_mutable_iter::cur, DEBUG1, dlist_container, dlist_delete(), dlist_foreach_modify, dlist_push_head(), elog, HASH_INDEX, catclist::hash_value, i, catcache::id, MemoryContextAllocZero(), and pfree().

Referenced by SearchCatCacheList().

◆ ReleaseCatCache()

void ReleaseCatCache ( HeapTuple  tuple)

Definition at line 1573 of file catcache.c.

1574 {
1576 }
static void ReleaseCatCacheWithOwner(HeapTuple tuple, ResourceOwner resowner)
Definition: catcache.c:1579
ResourceOwner CurrentResourceOwner
Definition: resowner.c:165

References CurrentResourceOwner, and ReleaseCatCacheWithOwner().

Referenced by ReleaseSysCache().

◆ ReleaseCatCacheList()

◆ ReleaseCatCacheListWithOwner()

static void ReleaseCatCacheListWithOwner ( CatCList list,
ResourceOwner  resowner 
)
static

Definition at line 1992 of file catcache.c.

1993 {
1994  /* Safety checks to ensure we were handed a cache entry */
1995  Assert(list->cl_magic == CL_MAGIC);
1996  Assert(list->refcount > 0);
1997  list->refcount--;
1998  if (resowner)
2000 
2001  if (
2002 #ifndef CATCACHE_FORCE_RELEASE
2003  list->dead &&
2004 #endif
2005  list->refcount == 0)
2006  CatCacheRemoveCList(list->my_cache, list);
2007 }
static void ResourceOwnerForgetCatCacheListRef(ResourceOwner owner, CatCList *list)
Definition: catcache.c:155
#define CL_MAGIC
Definition: catcache.h:162

References Assert, CatCacheRemoveCList(), CL_MAGIC, CurrentResourceOwner, sort-test::list, and ResourceOwnerForgetCatCacheListRef().

Referenced by ReleaseCatCacheList(), and ResOwnerReleaseCatCacheList().

◆ ReleaseCatCacheWithOwner()

static void ReleaseCatCacheWithOwner ( HeapTuple  tuple,
ResourceOwner  resowner 
)
static

Definition at line 1579 of file catcache.c.

1580 {
1581  CatCTup *ct = (CatCTup *) (((char *) tuple) -
1582  offsetof(CatCTup, tuple));
1583 
1584  /* Safety checks to ensure we were handed a cache entry */
1585  Assert(ct->ct_magic == CT_MAGIC);
1586  Assert(ct->refcount > 0);
1587 
1588  ct->refcount--;
1589  if (resowner)
1591 
1592  if (
1593 #ifndef CATCACHE_FORCE_RELEASE
1594  ct->dead &&
1595 #endif
1596  ct->refcount == 0 &&
1597  (ct->c_list == NULL || ct->c_list->refcount == 0))
1598  CatCacheRemoveCTup(ct->my_cache, ct);
1599 }
static void ResourceOwnerForgetCatCacheRef(ResourceOwner owner, HeapTuple tuple)
Definition: catcache.c:145

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

Referenced by ReleaseCatCache(), and ResOwnerReleaseCatCache().

◆ ResetCatalogCache()

static void ResetCatalogCache ( CatCache cache)
static

Definition at line 701 of file catcache.c.

702 {
703  dlist_mutable_iter iter;
704  int i;
705 
706  /* Remove each list in this cache, or at least mark it dead */
707  for (i = 0; i < cache->cc_nlbuckets; i++)
708  {
709  dlist_head *bucket = &cache->cc_lbucket[i];
710 
711  dlist_foreach_modify(iter, bucket)
712  {
713  CatCList *cl = dlist_container(CatCList, cache_elem, iter.cur);
714 
715  if (cl->refcount > 0)
716  cl->dead = true;
717  else
718  CatCacheRemoveCList(cache, cl);
719  }
720  }
721 
722  /* Remove each tuple in this cache, or at least mark it dead */
723  for (i = 0; i < cache->cc_nbuckets; i++)
724  {
725  dlist_head *bucket = &cache->cc_bucket[i];
726 
727  dlist_foreach_modify(iter, bucket)
728  {
729  CatCTup *ct = dlist_container(CatCTup, cache_elem, iter.cur);
730 
731  if (ct->refcount > 0 ||
732  (ct->c_list && ct->c_list->refcount > 0))
733  {
734  ct->dead = true;
735  /* list, if any, was marked dead above */
736  Assert(ct->c_list == NULL || ct->c_list->dead);
737  }
738  else
739  CatCacheRemoveCTup(cache, ct);
740 #ifdef CATCACHE_STATS
741  cache->cc_invals++;
742 #endif
743  }
744  }
745 }

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

Referenced by CatalogCacheFlushCatalog(), and ResetCatalogCaches().

◆ ResetCatalogCaches()

void ResetCatalogCaches ( void  )

Definition at line 753 of file catcache.c.

754 {
755  slist_iter iter;
756 
757  CACHE_elog(DEBUG2, "ResetCatalogCaches called");
758 
760  {
761  CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
762 
763  ResetCatalogCache(cache);
764  }
765 
766  CACHE_elog(DEBUG2, "end of ResetCatalogCaches call");
767 }

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

Referenced by InvalidateSystemCachesExtended().

◆ ResourceOwnerForgetCatCacheListRef()

static void ResourceOwnerForgetCatCacheListRef ( ResourceOwner  owner,
CatCList list 
)
inlinestatic

Definition at line 155 of file catcache.c.

156 {
158 }
static const ResourceOwnerDesc catlistref_resowner_desc
Definition: catcache.c:128
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
void ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:554

References catlistref_resowner_desc, sort-test::list, PointerGetDatum(), and ResourceOwnerForget().

Referenced by ReleaseCatCacheListWithOwner().

◆ ResourceOwnerForgetCatCacheRef()

static void ResourceOwnerForgetCatCacheRef ( ResourceOwner  owner,
HeapTuple  tuple 
)
inlinestatic

Definition at line 145 of file catcache.c.

146 {
148 }
static const ResourceOwnerDesc catcache_resowner_desc
Definition: catcache.c:118

References catcache_resowner_desc, PointerGetDatum(), and ResourceOwnerForget().

Referenced by ReleaseCatCacheWithOwner().

◆ ResourceOwnerRememberCatCacheListRef()

static void ResourceOwnerRememberCatCacheListRef ( ResourceOwner  owner,
CatCList list 
)
inlinestatic

Definition at line 150 of file catcache.c.

151 {
153 }
void ResourceOwnerRemember(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:514

References catlistref_resowner_desc, sort-test::list, PointerGetDatum(), and ResourceOwnerRemember().

Referenced by SearchCatCacheList().

◆ ResourceOwnerRememberCatCacheRef()

static void ResourceOwnerRememberCatCacheRef ( ResourceOwner  owner,
HeapTuple  tuple 
)
inlinestatic

◆ ResOwnerPrintCatCache()

static char * ResOwnerPrintCatCache ( Datum  res)
static

Definition at line 2317 of file catcache.c.

2318 {
2320  CatCTup *ct = (CatCTup *) (((char *) tuple) -
2321  offsetof(CatCTup, tuple));
2322 
2323  /* Safety check to ensure we were handed a cache entry */
2324  Assert(ct->ct_magic == CT_MAGIC);
2325 
2326  return psprintf("cache %s (%d), tuple %u/%u has count %d",
2327  ct->my_cache->cc_relname, ct->my_cache->id,
2328  ItemPointerGetBlockNumber(&(tuple->t_self)),
2330  ct->refcount);
2331 }
HeapTupleData * HeapTuple
Definition: htup.h:71
static OffsetNumber ItemPointerGetOffsetNumber(const ItemPointerData *pointer)
Definition: itemptr.h:124
static BlockNumber ItemPointerGetBlockNumber(const ItemPointerData *pointer)
Definition: itemptr.h:103
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46

References Assert, catcache::cc_relname, catctup::ct_magic, CT_MAGIC, DatumGetPointer(), catcache::id, ItemPointerGetBlockNumber(), ItemPointerGetOffsetNumber(), catctup::my_cache, psprintf(), catctup::refcount, res, and HeapTupleData::t_self.

◆ ResOwnerPrintCatCacheList()

static char * ResOwnerPrintCatCacheList ( Datum  res)
static

Definition at line 2340 of file catcache.c.

2341 {
2343 
2344  return psprintf("cache %s (%d), list %p has count %d",
2345  list->my_cache->cc_relname, list->my_cache->id,
2346  list, list->refcount);
2347 }

References DatumGetPointer(), sort-test::list, psprintf(), and res.

◆ ResOwnerReleaseCatCache()

static void ResOwnerReleaseCatCache ( Datum  res)
static

Definition at line 2311 of file catcache.c.

2312 {
2314 }

References DatumGetPointer(), ReleaseCatCacheWithOwner(), and res.

◆ ResOwnerReleaseCatCacheList()

static void ResOwnerReleaseCatCacheList ( Datum  res)
static

Definition at line 2334 of file catcache.c.

2335 {
2337 }

References DatumGetPointer(), ReleaseCatCacheListWithOwner(), and res.

◆ SearchCatCache()

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

Definition at line 1261 of file catcache.c.

1266 {
1267  return SearchCatCacheInternal(cache, cache->cc_nkeys, v1, v2, v3, v4);
1268 }
static HeapTuple SearchCatCacheInternal(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1312

References catcache::cc_nkeys, and SearchCatCacheInternal().

Referenced by SearchSysCache().

◆ SearchCatCache1()

HeapTuple SearchCatCache1 ( CatCache cache,
Datum  v1 
)

Definition at line 1278 of file catcache.c.

1280 {
1281  return SearchCatCacheInternal(cache, 1, v1, 0, 0, 0);
1282 }

References SearchCatCacheInternal().

Referenced by SearchSysCache1().

◆ SearchCatCache2()

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

Definition at line 1286 of file catcache.c.

1288 {
1289  return SearchCatCacheInternal(cache, 2, v1, v2, 0, 0);
1290 }

References SearchCatCacheInternal().

Referenced by SearchSysCache2().

◆ SearchCatCache3()

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

Definition at line 1294 of file catcache.c.

1296 {
1297  return SearchCatCacheInternal(cache, 3, v1, v2, v3, 0);
1298 }

References SearchCatCacheInternal().

Referenced by SearchSysCache3().

◆ SearchCatCache4()

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

Definition at line 1302 of file catcache.c.

1304 {
1305  return SearchCatCacheInternal(cache, 4, v1, v2, v3, v4);
1306 }

References SearchCatCacheInternal().

Referenced by SearchSysCache4().

◆ SearchCatCacheInternal()

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

Definition at line 1312 of file catcache.c.

1318 {
1320  uint32 hashValue;
1321  Index hashIndex;
1322  dlist_iter iter;
1323  dlist_head *bucket;
1324  CatCTup *ct;
1325 
1326  /* Make sure we're in an xact, even if this ends up being a cache hit */
1328 
1329  Assert(cache->cc_nkeys == nkeys);
1330 
1331  /*
1332  * one-time startup overhead for each cache
1333  */
1334  if (unlikely(cache->cc_tupdesc == NULL))
1336 
1337 #ifdef CATCACHE_STATS
1338  cache->cc_searches++;
1339 #endif
1340 
1341  /* Initialize local parameter array */
1342  arguments[0] = v1;
1343  arguments[1] = v2;
1344  arguments[2] = v3;
1345  arguments[3] = v4;
1346 
1347  /*
1348  * find the hash bucket in which to look for the tuple
1349  */
1350  hashValue = CatalogCacheComputeHashValue(cache, nkeys, v1, v2, v3, v4);
1351  hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
1352 
1353  /*
1354  * scan the hash bucket until we find a match or exhaust our tuples
1355  *
1356  * Note: it's okay to use dlist_foreach here, even though we modify the
1357  * dlist within the loop, because we don't continue the loop afterwards.
1358  */
1359  bucket = &cache->cc_bucket[hashIndex];
1360  dlist_foreach(iter, bucket)
1361  {
1362  ct = dlist_container(CatCTup, cache_elem, iter.cur);
1363 
1364  if (ct->dead)
1365  continue; /* ignore dead entries */
1366 
1367  if (ct->hash_value != hashValue)
1368  continue; /* quickly skip entry if wrong hash val */
1369 
1370  if (!CatalogCacheCompareTuple(cache, nkeys, ct->keys, arguments))
1371  continue;
1372 
1373  /*
1374  * We found a match in the cache. Move it to the front of the list
1375  * for its hashbucket, in order to speed subsequent searches. (The
1376  * most frequently accessed elements in any hashbucket will tend to be
1377  * near the front of the hashbucket's list.)
1378  */
1379  dlist_move_head(bucket, &ct->cache_elem);
1380 
1381  /*
1382  * If it's a positive entry, bump its refcount and return it. If it's
1383  * negative, we can report failure to the caller.
1384  */
1385  if (!ct->negative)
1386  {
1388  ct->refcount++;
1390 
1391  CACHE_elog(DEBUG2, "SearchCatCache(%s): found in bucket %d",
1392  cache->cc_relname, hashIndex);
1393 
1394 #ifdef CATCACHE_STATS
1395  cache->cc_hits++;
1396 #endif
1397 
1398  return &ct->tuple;
1399  }
1400  else
1401  {
1402  CACHE_elog(DEBUG2, "SearchCatCache(%s): found neg entry in bucket %d",
1403  cache->cc_relname, hashIndex);
1404 
1405 #ifdef CATCACHE_STATS
1406  cache->cc_neg_hits++;
1407 #endif
1408 
1409  return NULL;
1410  }
1411  }
1412 
1413  return SearchCatCacheMiss(cache, nkeys, hashValue, hashIndex, v1, v2, v3, v4);
1414 }
#define unlikely(x)
Definition: c.h:311
static pg_noinline HeapTuple SearchCatCacheMiss(CatCache *cache, int nkeys, uint32 hashValue, Index hashIndex, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1424
static void ResourceOwnerRememberCatCacheRef(ResourceOwner owner, HeapTuple tuple)
Definition: catcache.c:140
static bool CatalogCacheCompareTuple(const CatCache *cache, int nkeys, const Datum *cachekeys, const Datum *searchkeys)
Definition: catcache.c:422
#define CATCACHE_MAXKEYS
Definition: catcache.h:35
#define dlist_foreach(iter, lhead)
Definition: ilist.h:623
static void dlist_move_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:467
void ResourceOwnerEnlarge(ResourceOwner owner)
Definition: resowner.c:442
dlist_node * cur
Definition: ilist.h:179
bool IsTransactionState(void)
Definition: xact.c:384

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

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

◆ SearchCatCacheList()

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

Definition at line 1646 of file catcache.c.

1651 {
1652  Datum v4 = 0; /* dummy last-column value */
1654  uint32 lHashValue;
1655  Index lHashIndex;
1656  dlist_iter iter;
1657  dlist_head *lbucket;
1658  CatCList *cl;
1659  CatCTup *ct;
1660  List *volatile ctlist;
1661  ListCell *ctlist_item;
1662  int nmembers;
1663  bool ordered;
1664  HeapTuple ntp;
1665  MemoryContext oldcxt;
1666  int i;
1667 
1668  /*
1669  * one-time startup overhead for each cache
1670  */
1671  if (unlikely(cache->cc_tupdesc == NULL))
1673 
1674  Assert(nkeys > 0 && nkeys < cache->cc_nkeys);
1675 
1676 #ifdef CATCACHE_STATS
1677  cache->cc_lsearches++;
1678 #endif
1679 
1680  /* Initialize local parameter array */
1681  arguments[0] = v1;
1682  arguments[1] = v2;
1683  arguments[2] = v3;
1684  arguments[3] = v4;
1685 
1686  /*
1687  * If we haven't previously done a list search in this cache, create the
1688  * bucket header array; otherwise, consider whether it's time to enlarge
1689  * it.
1690  */
1691  if (cache->cc_lbucket == NULL)
1692  {
1693  /* Arbitrary initial size --- must be a power of 2 */
1694  int nbuckets = 16;
1695 
1696  cache->cc_lbucket = (dlist_head *)
1698  nbuckets * sizeof(dlist_head));
1699  /* Don't set cc_nlbuckets if we get OOM allocating cc_lbucket */
1700  cache->cc_nlbuckets = nbuckets;
1701  }
1702  else
1703  {
1704  /*
1705  * If the hash table has become too full, enlarge the buckets array.
1706  * Quite arbitrarily, we enlarge when fill factor > 2.
1707  */
1708  if (cache->cc_nlist > cache->cc_nlbuckets * 2)
1709  RehashCatCacheLists(cache);
1710  }
1711 
1712  /*
1713  * Find the hash bucket in which to look for the CatCList.
1714  */
1715  lHashValue = CatalogCacheComputeHashValue(cache, nkeys, v1, v2, v3, v4);
1716  lHashIndex = HASH_INDEX(lHashValue, cache->cc_nlbuckets);
1717 
1718  /*
1719  * scan the items until we find a match or exhaust our list
1720  *
1721  * Note: it's okay to use dlist_foreach here, even though we modify the
1722  * dlist within the loop, because we don't continue the loop afterwards.
1723  */
1724  lbucket = &cache->cc_lbucket[lHashIndex];
1725  dlist_foreach(iter, lbucket)
1726  {
1727  cl = dlist_container(CatCList, cache_elem, iter.cur);
1728 
1729  if (cl->dead)
1730  continue; /* ignore dead entries */
1731 
1732  if (cl->hash_value != lHashValue)
1733  continue; /* quickly skip entry if wrong hash val */
1734 
1735  /*
1736  * see if the cached list matches our key.
1737  */
1738  if (cl->nkeys != nkeys)
1739  continue;
1740 
1741  if (!CatalogCacheCompareTuple(cache, nkeys, cl->keys, arguments))
1742  continue;
1743 
1744  /*
1745  * We found a matching list. Move the list to the front of the list
1746  * for its hashbucket, so as to speed subsequent searches. (We do not
1747  * move the members to the fronts of their hashbucket lists, however,
1748  * since there's no point in that unless they are searched for
1749  * individually.)
1750  */
1751  dlist_move_head(lbucket, &cl->cache_elem);
1752 
1753  /* Bump the list's refcount and return it */
1755  cl->refcount++;
1757 
1758  CACHE_elog(DEBUG2, "SearchCatCacheList(%s): found list",
1759  cache->cc_relname);
1760 
1761 #ifdef CATCACHE_STATS
1762  cache->cc_lhits++;
1763 #endif
1764 
1765  return cl;
1766  }
1767 
1768  /*
1769  * List was not found in cache, so we have to build it by reading the
1770  * relation. For each matching tuple found in the relation, use an
1771  * existing cache entry if possible, else build a new one.
1772  *
1773  * We have to bump the member refcounts temporarily to ensure they won't
1774  * get dropped from the cache while loading other members. We use a PG_TRY
1775  * block to ensure we can undo those refcounts if we get an error before
1776  * we finish constructing the CatCList. ctlist must be valid throughout
1777  * the PG_TRY block.
1778  */
1779  ctlist = NIL;
1780 
1781  PG_TRY();
1782  {
1783  ScanKeyData cur_skey[CATCACHE_MAXKEYS];
1784  Relation relation;
1785  SysScanDesc scandesc;
1786  bool stale;
1787 
1788  relation = table_open(cache->cc_reloid, AccessShareLock);
1789 
1790  do
1791  {
1792  /*
1793  * Ok, need to make a lookup in the relation, copy the scankey and
1794  * fill out any per-call fields. (We must re-do this when
1795  * retrying, because systable_beginscan scribbles on the scankey.)
1796  */
1797  memcpy(cur_skey, cache->cc_skey, sizeof(ScanKeyData) * cache->cc_nkeys);
1798  cur_skey[0].sk_argument = v1;
1799  cur_skey[1].sk_argument = v2;
1800  cur_skey[2].sk_argument = v3;
1801  cur_skey[3].sk_argument = v4;
1802 
1803  scandesc = systable_beginscan(relation,
1804  cache->cc_indexoid,
1805  IndexScanOK(cache, cur_skey),
1806  NULL,
1807  nkeys,
1808  cur_skey);
1809 
1810  /* The list will be ordered iff we are doing an index scan */
1811  ordered = (scandesc->irel != NULL);
1812 
1813  stale = false;
1814 
1815  while (HeapTupleIsValid(ntp = systable_getnext(scandesc)))
1816  {
1817  uint32 hashValue;
1818  Index hashIndex;
1819  bool found = false;
1820  dlist_head *bucket;
1821 
1822  /*
1823  * See if there's an entry for this tuple already.
1824  */
1825  ct = NULL;
1826  hashValue = CatalogCacheComputeTupleHashValue(cache, cache->cc_nkeys, ntp);
1827  hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
1828 
1829  bucket = &cache->cc_bucket[hashIndex];
1830  dlist_foreach(iter, bucket)
1831  {
1832  ct = dlist_container(CatCTup, cache_elem, iter.cur);
1833 
1834  if (ct->dead || ct->negative)
1835  continue; /* ignore dead and negative entries */
1836 
1837  if (ct->hash_value != hashValue)
1838  continue; /* quickly skip entry if wrong hash val */
1839 
1840  if (!ItemPointerEquals(&(ct->tuple.t_self), &(ntp->t_self)))
1841  continue; /* not same tuple */
1842 
1843  /*
1844  * Found a match, but can't use it if it belongs to
1845  * another list already
1846  */
1847  if (ct->c_list)
1848  continue;
1849 
1850  found = true;
1851  break; /* A-OK */
1852  }
1853 
1854  if (!found)
1855  {
1856  /* We didn't find a usable entry, so make a new one */
1857  ct = CatalogCacheCreateEntry(cache, ntp, scandesc, NULL,
1858  hashValue, hashIndex);
1859  /* upon failure, we must start the scan over */
1860  if (ct == NULL)
1861  {
1862  /*
1863  * Release refcounts on any items we already had. We
1864  * dare not try to free them if they're now
1865  * unreferenced, since an error while doing that would
1866  * result in the PG_CATCH below doing extra refcount
1867  * decrements. Besides, we'll likely re-adopt those
1868  * items in the next iteration, so it's not worth
1869  * complicating matters to try to get rid of them.
1870  */
1871  foreach(ctlist_item, ctlist)
1872  {
1873  ct = (CatCTup *) lfirst(ctlist_item);
1874  Assert(ct->c_list == NULL);
1875  Assert(ct->refcount > 0);
1876  ct->refcount--;
1877  }
1878  /* Reset ctlist in preparation for new try */
1879  ctlist = NIL;
1880  stale = true;
1881  break;
1882  }
1883  }
1884 
1885  /* Careful here: add entry to ctlist, then bump its refcount */
1886  /* This way leaves state correct if lappend runs out of memory */
1887  ctlist = lappend(ctlist, ct);
1888  ct->refcount++;
1889  }
1890 
1891  systable_endscan(scandesc);
1892  } while (stale);
1893 
1894  table_close(relation, AccessShareLock);
1895 
1896  /* Make sure the resource owner has room to remember this entry. */
1898 
1899  /* Now we can build the CatCList entry. */
1901  nmembers = list_length(ctlist);
1902  cl = (CatCList *)
1903  palloc(offsetof(CatCList, members) + nmembers * sizeof(CatCTup *));
1904 
1905  /* Extract key values */
1906  CatCacheCopyKeys(cache->cc_tupdesc, nkeys, cache->cc_keyno,
1907  arguments, cl->keys);
1908  MemoryContextSwitchTo(oldcxt);
1909 
1910  /*
1911  * We are now past the last thing that could trigger an elog before we
1912  * have finished building the CatCList and remembering it in the
1913  * resource owner. So it's OK to fall out of the PG_TRY, and indeed
1914  * we'd better do so before we start marking the members as belonging
1915  * to the list.
1916  */
1917  }
1918  PG_CATCH();
1919  {
1920  foreach(ctlist_item, ctlist)
1921  {
1922  ct = (CatCTup *) lfirst(ctlist_item);
1923  Assert(ct->c_list == NULL);
1924  Assert(ct->refcount > 0);
1925  ct->refcount--;
1926  if (
1927 #ifndef CATCACHE_FORCE_RELEASE
1928  ct->dead &&
1929 #endif
1930  ct->refcount == 0 &&
1931  (ct->c_list == NULL || ct->c_list->refcount == 0))
1932  CatCacheRemoveCTup(cache, ct);
1933  }
1934 
1935  PG_RE_THROW();
1936  }
1937  PG_END_TRY();
1938 
1939  cl->cl_magic = CL_MAGIC;
1940  cl->my_cache = cache;
1941  cl->refcount = 0; /* for the moment */
1942  cl->dead = false;
1943  cl->ordered = ordered;
1944  cl->nkeys = nkeys;
1945  cl->hash_value = lHashValue;
1946  cl->n_members = nmembers;
1947 
1948  i = 0;
1949  foreach(ctlist_item, ctlist)
1950  {
1951  cl->members[i++] = ct = (CatCTup *) lfirst(ctlist_item);
1952  Assert(ct->c_list == NULL);
1953  ct->c_list = cl;
1954  /* release the temporary refcount on the member */
1955  Assert(ct->refcount > 0);
1956  ct->refcount--;
1957  /* mark list dead if any members already dead */
1958  if (ct->dead)
1959  cl->dead = true;
1960  }
1961  Assert(i == nmembers);
1962 
1963  /*
1964  * Add the CatCList to the appropriate bucket, and count it.
1965  */
1966  dlist_push_head(lbucket, &cl->cache_elem);
1967 
1968  cache->cc_nlist++;
1969 
1970  /* Finally, bump the list's refcount and return it */
1971  cl->refcount++;
1973 
1974  CACHE_elog(DEBUG2, "SearchCatCacheList(%s): made list of %d members",
1975  cache->cc_relname, nmembers);
1976 
1977  return cl;
1978 }
static CatCTup * CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp, SysScanDesc scandesc, Datum *arguments, uint32 hashValue, Index hashIndex)
Definition: catcache.c:2026
static void RehashCatCacheLists(CatCache *cp)
Definition: catcache.c:972
static void ResourceOwnerRememberCatCacheListRef(ResourceOwner owner, CatCList *list)
Definition: catcache.c:150
static bool IndexScanOK(CatCache *cache, ScanKey cur_skey)
Definition: catcache.c:1196
#define PG_RE_THROW()
Definition: elog.h:411
#define PG_TRY(...)
Definition: elog.h:370
#define PG_END_TRY(...)
Definition: elog.h:395
#define PG_CATCH(...)
Definition: elog.h:380
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:596
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:503
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:384
bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)
Definition: itemptr.c:35
List * lappend(List *list, void *datum)
Definition: list.c:339
#define lfirst(lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
Definition: pg_list.h:54
Datum sk_argument
Definition: skey.h:72
Relation irel
Definition: relscan.h:184
int cl_magic
Definition: catcache.h:161
bool ordered
Definition: catcache.h:176

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

Referenced by SearchSysCacheList().

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

1432 {
1433  ScanKeyData cur_skey[CATCACHE_MAXKEYS];
1434  Relation relation;
1435  SysScanDesc scandesc;
1436  HeapTuple ntp;
1437  CatCTup *ct;
1438  bool stale;
1440 
1441  /* Initialize local parameter array */
1442  arguments[0] = v1;
1443  arguments[1] = v2;
1444  arguments[2] = v3;
1445  arguments[3] = v4;
1446 
1447  /*
1448  * Tuple was not found in cache, so we have to try to retrieve it directly
1449  * from the relation. If found, we will add it to the cache; if not
1450  * found, we will add a negative cache entry instead.
1451  *
1452  * NOTE: it is possible for recursive cache lookups to occur while reading
1453  * the relation --- for example, due to shared-cache-inval messages being
1454  * processed during table_open(). This is OK. It's even possible for one
1455  * of those lookups to find and enter the very same tuple we are trying to
1456  * fetch here. If that happens, we will enter a second copy of the tuple
1457  * into the cache. The first copy will never be referenced again, and
1458  * will eventually age out of the cache, so there's no functional problem.
1459  * This case is rare enough that it's not worth expending extra cycles to
1460  * detect.
1461  *
1462  * Another case, which we *must* handle, is that the tuple could become
1463  * outdated during CatalogCacheCreateEntry's attempt to detoast it (since
1464  * AcceptInvalidationMessages can run during TOAST table access). We do
1465  * not want to return already-stale catcache entries, so we loop around
1466  * and do the table scan again if that happens.
1467  */
1468  relation = table_open(cache->cc_reloid, AccessShareLock);
1469 
1470  do
1471  {
1472  /*
1473  * Ok, need to make a lookup in the relation, copy the scankey and
1474  * fill out any per-call fields. (We must re-do this when retrying,
1475  * because systable_beginscan scribbles on the scankey.)
1476  */
1477  memcpy(cur_skey, cache->cc_skey, sizeof(ScanKeyData) * nkeys);
1478  cur_skey[0].sk_argument = v1;
1479  cur_skey[1].sk_argument = v2;
1480  cur_skey[2].sk_argument = v3;
1481  cur_skey[3].sk_argument = v4;
1482 
1483  scandesc = systable_beginscan(relation,
1484  cache->cc_indexoid,
1485  IndexScanOK(cache, cur_skey),
1486  NULL,
1487  nkeys,
1488  cur_skey);
1489 
1490  ct = NULL;
1491  stale = false;
1492 
1493  while (HeapTupleIsValid(ntp = systable_getnext(scandesc)))
1494  {
1495  ct = CatalogCacheCreateEntry(cache, ntp, scandesc, NULL,
1496  hashValue, hashIndex);
1497  /* upon failure, we must start the scan over */
1498  if (ct == NULL)
1499  {
1500  stale = true;
1501  break;
1502  }
1503  /* immediately set the refcount to 1 */
1505  ct->refcount++;
1507  break; /* assume only one match */
1508  }
1509 
1510  systable_endscan(scandesc);
1511  } while (stale);
1512 
1513  table_close(relation, AccessShareLock);
1514 
1515  /*
1516  * If tuple was not found, we need to build a negative cache entry
1517  * containing a fake tuple. The fake tuple has the correct key columns,
1518  * but nulls everywhere else.
1519  *
1520  * In bootstrap mode, we don't build negative entries, because the cache
1521  * invalidation mechanism isn't alive and can't clear them if the tuple
1522  * gets created later. (Bootstrap doesn't do UPDATEs, so it doesn't need
1523  * cache inval for that.)
1524  */
1525  if (ct == NULL)
1526  {
1528  return NULL;
1529 
1530  ct = CatalogCacheCreateEntry(cache, NULL, NULL, arguments,
1531  hashValue, hashIndex);
1532 
1533  /* Creating a negative cache entry shouldn't fail */
1534  Assert(ct != NULL);
1535 
1536  CACHE_elog(DEBUG2, "SearchCatCache(%s): Contains %d/%d tuples",
1537  cache->cc_relname, cache->cc_ntup, CacheHdr->ch_ntup);
1538  CACHE_elog(DEBUG2, "SearchCatCache(%s): put neg entry in bucket %d",
1539  cache->cc_relname, hashIndex);
1540 
1541  /*
1542  * We are not returning the negative entry to the caller, so leave its
1543  * refcount zero.
1544  */
1545 
1546  return NULL;
1547  }
1548 
1549  CACHE_elog(DEBUG2, "SearchCatCache(%s): Contains %d/%d tuples",
1550  cache->cc_relname, cache->cc_ntup, CacheHdr->ch_ntup);
1551  CACHE_elog(DEBUG2, "SearchCatCache(%s): put in bucket %d",
1552  cache->cc_relname, hashIndex);
1553 
1554 #ifdef CATCACHE_STATS
1555  cache->cc_newloads++;
1556 #endif
1557 
1558  return &ct->tuple;
1559 }
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:454

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

Referenced by SearchCatCacheInternal().

◆ texteqfast()

static bool texteqfast ( Datum  a,
Datum  b 
)
static

Definition at line 225 of file catcache.c.

226 {
227  /*
228  * The use of DEFAULT_COLLATION_OID is fairly arbitrary here. We just
229  * want to take the fast "deterministic" path in texteq().
230  */
231  return DatumGetBool(DirectFunctionCall2Coll(texteq, DEFAULT_COLLATION_OID, a, b));
232 }
Datum DirectFunctionCall2Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:812
Datum texteq(PG_FUNCTION_ARGS)
Definition: varlena.c:1619

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

Referenced by GetCCHashEqFuncs().

◆ texthashfast()

static uint32 texthashfast ( Datum  datum)
static

Definition at line 235 of file catcache.c.

236 {
237  /* analogously here as in texteqfast() */
238  return DatumGetInt32(DirectFunctionCall1Coll(hashtext, DEFAULT_COLLATION_OID, datum));
239 }
Datum DirectFunctionCall1Coll(PGFunction func, Oid collation, Datum arg1)
Definition: fmgr.c:792
Datum hashtext(PG_FUNCTION_ARGS)
Definition: hashfunc.c:267

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

Referenced by GetCCHashEqFuncs().

Variable Documentation

◆ CacheHdr

◆ catcache_resowner_desc

const ResourceOwnerDesc catcache_resowner_desc
static
Initial value:
=
{
.name = "catcache reference",
.release_phase = RESOURCE_RELEASE_AFTER_LOCKS,
.release_priority = RELEASE_PRIO_CATCACHE_REFS,
.ReleaseResource = ResOwnerReleaseCatCache,
.DebugPrint = ResOwnerPrintCatCache
}
static void ResOwnerReleaseCatCache(Datum res)
Definition: catcache.c:2311
static char * ResOwnerPrintCatCache(Datum res)
Definition: catcache.c:2317
@ RESOURCE_RELEASE_AFTER_LOCKS
Definition: resowner.h:56
#define RELEASE_PRIO_CATCACHE_REFS
Definition: resowner.h:71

Definition at line 118 of file catcache.c.

Referenced by ResourceOwnerForgetCatCacheRef(), and ResourceOwnerRememberCatCacheRef().

◆ catlistref_resowner_desc

const ResourceOwnerDesc catlistref_resowner_desc
static
Initial value:
=
{
.name = "catcache list reference",
.release_phase = RESOURCE_RELEASE_AFTER_LOCKS,
.release_priority = RELEASE_PRIO_CATCACHE_LIST_REFS,
.ReleaseResource = ResOwnerReleaseCatCacheList,
}
static void ResOwnerReleaseCatCacheList(Datum res)
Definition: catcache.c:2334
static char * ResOwnerPrintCatCacheList(Datum res)
Definition: catcache.c:2340
#define RELEASE_PRIO_CATCACHE_LIST_REFS
Definition: resowner.h:72

Definition at line 128 of file catcache.c.

Referenced by ResourceOwnerForgetCatCacheListRef(), and ResourceOwnerRememberCatCacheListRef().