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/catalog.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)
 
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)
 
static bool equalTuple (HeapTuple a, HeapTuple b)
 
void PrepareToInvalidateCacheTuple (Relation relation, HeapTuple tuple, HeapTuple newtuple, void(*function)(int, uint32, Oid, void *), void *context)
 

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

◆ CatalogCacheInitializeCache_DEBUG1

#define CatalogCacheInitializeCache_DEBUG1

Definition at line 1031 of file catcache.c.

◆ CatalogCacheInitializeCache_DEBUG2

#define CatalogCacheInitializeCache_DEBUG2

Definition at line 1032 of file catcache.c.

◆ HASH_INDEX

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

Definition at line 51 of file catcache.c.

◆ InitCatCache_DEBUG2

#define InitCatCache_DEBUG2

Definition at line 824 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 423 of file catcache.c.

426 {
427  const CCFastEqualFN *cc_fastequal = cache->cc_fastequal;
428  int i;
429 
430  for (i = 0; i < nkeys; i++)
431  {
432  if (!(cc_fastequal[i]) (cachekeys[i], searchkeys[i]))
433  return false;
434  }
435  return true;
436 }
bool(* CCFastEqualFN)(Datum a, Datum b)
Definition: catcache.h:42
int i
Definition: isn.c:72
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 326 of file catcache.c.

328 {
329  uint32 hashValue = 0;
330  uint32 oneHash;
331  CCHashFN *cc_hashfunc = cache->cc_hashfunc;
332 
333  CACHE_elog(DEBUG2, "CatalogCacheComputeHashValue %s %d %p",
334  cache->cc_relname, nkeys, cache);
335 
336  switch (nkeys)
337  {
338  case 4:
339  oneHash = (cc_hashfunc[3]) (v4);
340  hashValue ^= pg_rotate_left32(oneHash, 24);
341  /* FALLTHROUGH */
342  case 3:
343  oneHash = (cc_hashfunc[2]) (v3);
344  hashValue ^= pg_rotate_left32(oneHash, 16);
345  /* FALLTHROUGH */
346  case 2:
347  oneHash = (cc_hashfunc[1]) (v2);
348  hashValue ^= pg_rotate_left32(oneHash, 8);
349  /* FALLTHROUGH */
350  case 1:
351  oneHash = (cc_hashfunc[0]) (v1);
352  hashValue ^= oneHash;
353  break;
354  default:
355  elog(FATAL, "wrong number of hash keys: %d", nkeys);
356  break;
357  }
358 
359  return hashValue;
360 }
uint32_t uint32
Definition: c.h:485
#define CACHE_elog(...)
Definition: catcache.c:61
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:225
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 368 of file catcache.c.

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

2045 {
2046  CatCTup *ct;
2047  HeapTuple dtp;
2048  MemoryContext oldcxt;
2049 
2050  if (ntp)
2051  {
2052  int i;
2053 
2054  /*
2055  * The visibility recheck below essentially never fails during our
2056  * regression tests, and there's no easy way to force it to fail for
2057  * testing purposes. To ensure we have test coverage for the retry
2058  * paths in our callers, make debug builds randomly fail about 0.1% of
2059  * the times through this code path, even when there's no toasted
2060  * fields.
2061  */
2062 #ifdef USE_ASSERT_CHECKING
2064  return NULL;
2065 #endif
2066 
2067  /*
2068  * If there are any out-of-line toasted fields in the tuple, expand
2069  * them in-line. This saves cycles during later use of the catcache
2070  * entry, and also protects us against the possibility of the toast
2071  * tuples being freed before we attempt to fetch them, in case of
2072  * something using a slightly stale catcache entry.
2073  */
2074  if (HeapTupleHasExternal(ntp))
2075  {
2076  bool need_cmp = IsInplaceUpdateOid(cache->cc_reloid);
2077  HeapTuple before = NULL;
2078  bool matches = true;
2079 
2080  if (need_cmp)
2081  before = heap_copytuple(ntp);
2082  dtp = toast_flatten_tuple(ntp, cache->cc_tupdesc);
2083 
2084  /*
2085  * The tuple could become stale while we are doing toast table
2086  * access (since AcceptInvalidationMessages can run then).
2087  * equalTuple() detects staleness from inplace updates, while
2088  * systable_recheck_tuple() detects staleness from normal updates.
2089  *
2090  * While this equalTuple() follows the usual rule of reading with
2091  * a pin and no buffer lock, it warrants suspicion since an
2092  * inplace update could appear at any moment. It's safe because
2093  * the inplace update sends an invalidation that can't reorder
2094  * before the inplace heap change. If the heap change reaches
2095  * this process just after equalTuple() looks, we've not missed
2096  * its inval.
2097  */
2098  if (need_cmp)
2099  {
2100  matches = equalTuple(before, ntp);
2102  }
2103  if (!matches || !systable_recheck_tuple(scandesc, ntp))
2104  {
2105  heap_freetuple(dtp);
2106  return NULL;
2107  }
2108  }
2109  else
2110  dtp = ntp;
2111 
2112  /* Allocate memory for CatCTup and the cached tuple in one go */
2114 
2115  ct = (CatCTup *) palloc(sizeof(CatCTup) +
2116  MAXIMUM_ALIGNOF + dtp->t_len);
2117  ct->tuple.t_len = dtp->t_len;
2118  ct->tuple.t_self = dtp->t_self;
2119  ct->tuple.t_tableOid = dtp->t_tableOid;
2120  ct->tuple.t_data = (HeapTupleHeader)
2121  MAXALIGN(((char *) ct) + sizeof(CatCTup));
2122  /* copy tuple contents */
2123  memcpy((char *) ct->tuple.t_data,
2124  (const char *) dtp->t_data,
2125  dtp->t_len);
2126  MemoryContextSwitchTo(oldcxt);
2127 
2128  if (dtp != ntp)
2129  heap_freetuple(dtp);
2130 
2131  /* extract keys - they'll point into the tuple if not by-value */
2132  for (i = 0; i < cache->cc_nkeys; i++)
2133  {
2134  Datum atp;
2135  bool isnull;
2136 
2137  atp = heap_getattr(&ct->tuple,
2138  cache->cc_keyno[i],
2139  cache->cc_tupdesc,
2140  &isnull);
2141  Assert(!isnull);
2142  ct->keys[i] = atp;
2143  }
2144  }
2145  else
2146  {
2147  /* Set up keys for a negative cache entry */
2149  ct = (CatCTup *) palloc(sizeof(CatCTup));
2150 
2151  /*
2152  * Store keys - they'll point into separately allocated memory if not
2153  * by-value.
2154  */
2155  CatCacheCopyKeys(cache->cc_tupdesc, cache->cc_nkeys, cache->cc_keyno,
2156  arguments, ct->keys);
2157  MemoryContextSwitchTo(oldcxt);
2158  }
2159 
2160  /*
2161  * Finish initializing the CatCTup header, and add it to the cache's
2162  * linked list and counts.
2163  */
2164  ct->ct_magic = CT_MAGIC;
2165  ct->my_cache = cache;
2166  ct->c_list = NULL;
2167  ct->refcount = 0; /* for the moment */
2168  ct->dead = false;
2169  ct->negative = (ntp == NULL);
2170  ct->hash_value = hashValue;
2171 
2172  dlist_push_head(&cache->cc_bucket[hashIndex], &ct->cache_elem);
2173 
2174  cache->cc_ntup++;
2175  CacheHdr->ch_ntup++;
2176 
2177  /*
2178  * If the hash table has become too full, enlarge the buckets array. Quite
2179  * arbitrarily, we enlarge when fill factor > 2.
2180  */
2181  if (cache->cc_ntup > cache->cc_nbuckets * 2)
2182  RehashCatCache(cache);
2183 
2184  return ct;
2185 }
#define MAXALIGN(LEN)
Definition: c.h:765
#define PG_UINT32_MAX
Definition: c.h:544
bool IsInplaceUpdateOid(Oid relid)
Definition: catalog.c:162
static bool equalTuple(HeapTuple a, HeapTuple b)
Definition: catcache.c:2014
static void RehashCatCache(CatCache *cp)
Definition: catcache.c:935
static void CatCacheCopyKeys(TupleDesc tupdesc, int nkeys, int *attnos, Datum *srckeys, Datum *dstkeys)
Definition: catcache.c:2216
static CatCacheHeader * CacheHdr
Definition: catcache.c:65
#define CT_MAGIC
Definition: catcache.h:91
bool systable_recheck_tuple(SysScanDesc sysscan, HeapTuple tup)
Definition: genam.c:572
HeapTuple toast_flatten_tuple(HeapTuple tup, TupleDesc tupleDesc)
Definition: heaptoast.c:350
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:776
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:1317
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)
static int before(chr x, chr y)
Definition: regc_locale.c:488
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
Oid cc_reloid
Definition: catcache.h:60
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, before(), 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_reloid, catcache::cc_tupdesc, catcacheheader::ch_ntup, catctup::ct_magic, CT_MAGIC, catctup::dead, dlist_push_head(), equalTuple(), catctup::hash_value, heap_copytuple(), heap_freetuple(), heap_getattr(), HeapTupleHasExternal, i, IsInplaceUpdateOid(), 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 784 of file catcache.c.

785 {
786  slist_iter iter;
787 
788  CACHE_elog(DEBUG2, "CatalogCacheFlushCatalog called for %u", catId);
789 
791  {
792  CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
793 
794  /* Does this cache store tuples of the target catalog? */
795  if (cache->cc_reloid == catId)
796  {
797  /* Yes, so flush all its contents */
798  ResetCatalogCache(cache);
799 
800  /* Tell inval.c to call syscache callbacks for this cache */
801  CallSyscacheCallbacks(cache->id, 0);
802  }
803  }
804 
805  CACHE_elog(DEBUG2, "end of CatalogCacheFlushCatalog call");
806 }
static void ResetCatalogCache(CatCache *cache)
Definition: catcache.c:702
#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:1765
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 1036 of file catcache.c.

1037 {
1038  Relation relation;
1039  MemoryContext oldcxt;
1040  TupleDesc tupdesc;
1041  int i;
1042 
1044 
1045  relation = table_open(cache->cc_reloid, AccessShareLock);
1046 
1047  /*
1048  * switch to the cache context so our allocations do not vanish at the end
1049  * of a transaction
1050  */
1051  Assert(CacheMemoryContext != NULL);
1052 
1054 
1055  /*
1056  * copy the relcache's tuple descriptor to permanent cache storage
1057  */
1058  tupdesc = CreateTupleDescCopyConstr(RelationGetDescr(relation));
1059 
1060  /*
1061  * save the relation's name and relisshared flag, too (cc_relname is used
1062  * only for debugging purposes)
1063  */
1064  cache->cc_relname = pstrdup(RelationGetRelationName(relation));
1065  cache->cc_relisshared = RelationGetForm(relation)->relisshared;
1066 
1067  /*
1068  * return to the caller's memory context and close the rel
1069  */
1070  MemoryContextSwitchTo(oldcxt);
1071 
1072  table_close(relation, AccessShareLock);
1073 
1074  CACHE_elog(DEBUG2, "CatalogCacheInitializeCache: %s, %d keys",
1075  cache->cc_relname, cache->cc_nkeys);
1076 
1077  /*
1078  * initialize cache's key information
1079  */
1080  for (i = 0; i < cache->cc_nkeys; ++i)
1081  {
1082  Oid keytype;
1083  RegProcedure eqfunc;
1084 
1086 
1087  if (cache->cc_keyno[i] > 0)
1088  {
1089  Form_pg_attribute attr = TupleDescAttr(tupdesc,
1090  cache->cc_keyno[i] - 1);
1091 
1092  keytype = attr->atttypid;
1093  /* cache key columns should always be NOT NULL */
1094  Assert(attr->attnotnull);
1095  }
1096  else
1097  {
1098  if (cache->cc_keyno[i] < 0)
1099  elog(FATAL, "sys attributes are not supported in caches");
1100  keytype = OIDOID;
1101  }
1102 
1103  GetCCHashEqFuncs(keytype,
1104  &cache->cc_hashfunc[i],
1105  &eqfunc,
1106  &cache->cc_fastequal[i]);
1107 
1108  /*
1109  * Do equality-function lookup (we assume this won't need a catalog
1110  * lookup for any supported type)
1111  */
1112  fmgr_info_cxt(eqfunc,
1113  &cache->cc_skey[i].sk_func,
1115 
1116  /* Initialize sk_attno suitably for HeapKeyTest() and heap scans */
1117  cache->cc_skey[i].sk_attno = cache->cc_keyno[i];
1118 
1119  /* Fill in sk_strategy as well --- always standard equality */
1121  cache->cc_skey[i].sk_subtype = InvalidOid;
1122  /* If a catcache key requires a collation, it must be C collation */
1123  cache->cc_skey[i].sk_collation = C_COLLATION_OID;
1124 
1125  CACHE_elog(DEBUG2, "CatalogCacheInitializeCache %s %d %p",
1126  cache->cc_relname, i, cache);
1127  }
1128 
1129  /*
1130  * mark this cache fully initialized
1131  */
1132  cache->cc_tupdesc = tupdesc;
1133 }
regproc RegProcedure
Definition: c.h:604
#define CatalogCacheInitializeCache_DEBUG1
Definition: catcache.c:1031
static void GetCCHashEqFuncs(Oid keytype, CCHashFN *hashfunc, RegProcedure *eqfunc, CCFastEqualFN *fasteqfunc)
Definition: catcache.c:256
#define CatalogCacheInitializeCache_DEBUG2
Definition: catcache.c:1032
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:1696
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 2216 of file catcache.c.

2218 {
2219  int i;
2220 
2221  /*
2222  * XXX: memory and lookup performance could possibly be improved by
2223  * storing all keys in one allocation.
2224  */
2225 
2226  for (i = 0; i < nkeys; i++)
2227  {
2228  int attnum = attnos[i];
2229  Form_pg_attribute att = TupleDescAttr(tupdesc, attnum - 1);
2230  Datum src = srckeys[i];
2231  NameData srcname;
2232 
2233  /*
2234  * Must be careful in case the caller passed a C string where a NAME
2235  * is wanted: convert the given argument to a correctly padded NAME.
2236  * Otherwise the memcpy() done by datumCopy() could fall off the end
2237  * of memory.
2238  */
2239  if (att->atttypid == NAMEOID)
2240  {
2241  namestrcpy(&srcname, DatumGetCString(src));
2242  src = NameGetDatum(&srcname);
2243  }
2244 
2245  dstkeys[i] = datumCopy(src,
2246  att->attbyval,
2247  att->attlen);
2248  }
2249 }
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:695

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

2192 {
2193  int i;
2194 
2195  for (i = 0; i < nkeys; i++)
2196  {
2197  int attnum = attnos[i];
2198  Form_pg_attribute att;
2199 
2200  /* system attribute are not supported in caches */
2201  Assert(attnum > 0);
2202 
2203  att = TupleDescAttr(tupdesc, attnum - 1);
2204 
2205  if (!att->attbyval)
2206  pfree(DatumGetPointer(keys[i]));
2207  }
2208 }
void pfree(void *pointer)
Definition: mcxt.c:1521
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 607 of file catcache.c.

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

553 {
554  int i;
555 
556  Assert(cl->refcount == 0);
557  Assert(cl->my_cache == cache);
558 
559  /* delink from member tuples */
560  for (i = cl->n_members; --i >= 0;)
561  {
562  CatCTup *ct = cl->members[i];
563 
564  Assert(ct->c_list == cl);
565  ct->c_list = NULL;
566  /* if the member is dead and now has no references, remove it */
567  if (
568 #ifndef CATCACHE_FORCE_RELEASE
569  ct->dead &&
570 #endif
571  ct->refcount == 0)
572  CatCacheRemoveCTup(cache, ct);
573  }
574 
575  /* delink from linked list */
576  dlist_delete(&cl->cache_elem);
577 
578  /* free associated column data */
579  CatCacheFreeKeys(cache->cc_tupdesc, cl->nkeys,
580  cache->cc_keyno, cl->keys);
581 
582  pfree(cl);
583 
584  --cache->cc_nlist;
585 }
static void CatCacheFreeKeys(TupleDesc tupdesc, int nkeys, int *attnos, Datum *keys)
Definition: catcache.c:2191
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 510 of file catcache.c.

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

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

174 {
175  return DatumGetChar(a) == DatumGetChar(b);
176 }
int b
Definition: isn.c:69
int a
Definition: isn.c:68
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 179 of file catcache.c.

180 {
181  return murmurhash32((int32) DatumGetChar(datum));
182 }
int32_t int32
Definition: c.h:481
static uint32 murmurhash32(uint32 data)
Definition: hashfn.h:92

References DatumGetChar(), and murmurhash32().

Referenced by GetCCHashEqFuncs().

◆ CreateCacheMemoryContext()

void CreateCacheMemoryContext ( void  )

Definition at line 680 of file catcache.c.

681 {
682  /*
683  * Purely for paranoia, check that context doesn't exist; caller probably
684  * did so already.
685  */
686  if (!CacheMemoryContext)
688  "CacheMemoryContext",
690 }
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().

◆ equalTuple()

static bool equalTuple ( HeapTuple  a,
HeapTuple  b 
)
static

Definition at line 2014 of file catcache.c.

2015 {
2016  uint32 alen;
2017  uint32 blen;
2018 
2019  alen = a->t_len;
2020  blen = b->t_len;
2021  return (alen == blen &&
2022  memcmp((char *) a->t_data,
2023  (char *) b->t_data, blen) == 0);
2024 }

References a, and b.

Referenced by CatalogCacheCreateEntry().

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

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

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

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)
static

Definition at line 1197 of file catcache.c.

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

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

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

203 {
204  return DatumGetInt16(a) == DatumGetInt16(b);
205 }
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 208 of file catcache.c.

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

References DatumGetInt16(), and murmurhash32().

Referenced by GetCCHashEqFuncs().

◆ int4eqfast()

static bool int4eqfast ( Datum  a,
Datum  b 
)
static

Definition at line 214 of file catcache.c.

215 {
216  return DatumGetInt32(a) == DatumGetInt32(b);
217 }
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 220 of file catcache.c.

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

References DatumGetInt32(), and murmurhash32().

Referenced by GetCCHashEqFuncs().

◆ nameeqfast()

static bool nameeqfast ( Datum  a,
Datum  b 
)
static

Definition at line 185 of file catcache.c.

186 {
187  char *ca = NameStr(*DatumGetName(a));
188  char *cb = NameStr(*DatumGetName(b));
189 
190  return strncmp(ca, cb, NAMEDATALEN) == 0;
191 }
#define NameStr(name)
Definition: c.h:700
#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 194 of file catcache.c.

195 {
196  char *key = NameStr(*DatumGetName(datum));
197 
198  return hash_any((unsigned char *) key, strlen(key));
199 }
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 243 of file catcache.c.

244 {
246 }
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:643
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 249 of file catcache.c.

250 {
252 }
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:641
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, void *)  function,
void *  context 
)

Definition at line 2286 of file catcache.c.

2291 {
2292  slist_iter iter;
2293  Oid reloid;
2294 
2295  CACHE_elog(DEBUG2, "PrepareToInvalidateCacheTuple: called");
2296 
2297  /*
2298  * sanity checks
2299  */
2300  Assert(RelationIsValid(relation));
2301  Assert(HeapTupleIsValid(tuple));
2302  Assert(PointerIsValid(function));
2303  Assert(CacheHdr != NULL);
2304 
2305  reloid = RelationGetRelid(relation);
2306 
2307  /* ----------------
2308  * for each cache
2309  * if the cache contains tuples from the specified relation
2310  * compute the tuple's hash value(s) in this cache,
2311  * and call the passed function to register the information.
2312  * ----------------
2313  */
2314 
2316  {
2317  CatCache *ccp = slist_container(CatCache, cc_next, iter.cur);
2318  uint32 hashvalue;
2319  Oid dbid;
2320 
2321  if (ccp->cc_reloid != reloid)
2322  continue;
2323 
2324  /* Just in case cache hasn't finished initialization yet... */
2325  if (ccp->cc_tupdesc == NULL)
2327 
2328  hashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, tuple);
2329  dbid = ccp->cc_relisshared ? (Oid) 0 : MyDatabaseId;
2330 
2331  (*function) (ccp->id, hashvalue, dbid, context);
2332 
2333  if (newtuple)
2334  {
2335  uint32 newhashvalue;
2336 
2337  newhashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, newtuple);
2338 
2339  if (newhashvalue != hashvalue)
2340  (*function) (ccp->id, newhashvalue, dbid, context);
2341  }
2342  }
2343 }
#define PointerIsValid(pointer)
Definition: c.h:717
static uint32 CatalogCacheComputeTupleHashValue(CatCache *cache, int nkeys, HeapTuple tuple)
Definition: catcache.c:368
Oid MyDatabaseId
Definition: globals.c:93
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
tree context
Definition: radixtree.h:1835
#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, context, slist_iter::cur, DEBUG2, HeapTupleIsValid, catcache::id, MyDatabaseId, PointerIsValid, RelationGetRelid, RelationIsValid, slist_container, and slist_foreach.

Referenced by CacheInvalidateHeapTupleCommon().

◆ RehashCatCache()

static void RehashCatCache ( CatCache cp)
static

Definition at line 935 of file catcache.c.

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

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

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

1992 {
1993  /* Safety checks to ensure we were handed a cache entry */
1994  Assert(list->cl_magic == CL_MAGIC);
1995  Assert(list->refcount > 0);
1996  list->refcount--;
1997  if (resowner)
1999 
2000  if (
2001 #ifndef CATCACHE_FORCE_RELEASE
2002  list->dead &&
2003 #endif
2004  list->refcount == 0)
2005  CatCacheRemoveCList(list->my_cache, list);
2006 }
static void ResourceOwnerForgetCatCacheListRef(ResourceOwner owner, CatCList *list)
Definition: catcache.c:156
#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:146

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

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

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

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

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

157 {
159 }
static const ResourceOwnerDesc catlistref_resowner_desc
Definition: catcache.c:129
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 146 of file catcache.c.

147 {
149 }
static const ResourceOwnerDesc catcache_resowner_desc
Definition: catcache.c:119

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

Referenced by ReleaseCatCacheWithOwner().

◆ ResourceOwnerRememberCatCacheListRef()

static void ResourceOwnerRememberCatCacheListRef ( ResourceOwner  owner,
CatCList list 
)
inlinestatic

Definition at line 151 of file catcache.c.

152 {
154 }
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 2354 of file catcache.c.

2355 {
2357  CatCTup *ct = (CatCTup *) (((char *) tuple) -
2358  offsetof(CatCTup, tuple));
2359 
2360  /* Safety check to ensure we were handed a cache entry */
2361  Assert(ct->ct_magic == CT_MAGIC);
2362 
2363  return psprintf("cache %s (%d), tuple %u/%u has count %d",
2364  ct->my_cache->cc_relname, ct->my_cache->id,
2365  ItemPointerGetBlockNumber(&(tuple->t_self)),
2367  ct->refcount);
2368 }
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:43

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

2378 {
2380 
2381  return psprintf("cache %s (%d), list %p has count %d",
2382  list->my_cache->cc_relname, list->my_cache->id,
2383  list, list->refcount);
2384 }

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

◆ ResOwnerReleaseCatCache()

static void ResOwnerReleaseCatCache ( Datum  res)
static

Definition at line 2348 of file catcache.c.

2349 {
2351 }

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

◆ ResOwnerReleaseCatCacheList()

static void ResOwnerReleaseCatCacheList ( Datum  res)
static

Definition at line 2371 of file catcache.c.

2372 {
2374 }

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

◆ SearchCatCache()

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

Definition at line 1262 of file catcache.c.

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

References catcache::cc_nkeys, and SearchCatCacheInternal().

Referenced by SearchSysCache().

◆ SearchCatCache1()

HeapTuple SearchCatCache1 ( CatCache cache,
Datum  v1 
)

Definition at line 1279 of file catcache.c.

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

References SearchCatCacheInternal().

Referenced by SearchSysCache1().

◆ SearchCatCache2()

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

Definition at line 1287 of file catcache.c.

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

References SearchCatCacheInternal().

Referenced by SearchSysCache2().

◆ SearchCatCache3()

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

Definition at line 1295 of file catcache.c.

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

References SearchCatCacheInternal().

Referenced by SearchSysCache3().

◆ SearchCatCache4()

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

Definition at line 1303 of file catcache.c.

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

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

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

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  /*
1791  * Ok, need to make a lookup in the relation, copy the scankey and
1792  * fill out any per-call fields.
1793  */
1794  memcpy(cur_skey, cache->cc_skey, sizeof(ScanKeyData) * cache->cc_nkeys);
1795  cur_skey[0].sk_argument = v1;
1796  cur_skey[1].sk_argument = v2;
1797  cur_skey[2].sk_argument = v3;
1798  cur_skey[3].sk_argument = v4;
1799 
1800  do
1801  {
1802  scandesc = systable_beginscan(relation,
1803  cache->cc_indexoid,
1804  IndexScanOK(cache),
1805  NULL,
1806  nkeys,
1807  cur_skey);
1808 
1809  /* The list will be ordered iff we are doing an index scan */
1810  ordered = (scandesc->irel != NULL);
1811 
1812  stale = false;
1813 
1814  while (HeapTupleIsValid(ntp = systable_getnext(scandesc)))
1815  {
1816  uint32 hashValue;
1817  Index hashIndex;
1818  bool found = false;
1819  dlist_head *bucket;
1820 
1821  /*
1822  * See if there's an entry for this tuple already.
1823  */
1824  ct = NULL;
1825  hashValue = CatalogCacheComputeTupleHashValue(cache, cache->cc_nkeys, ntp);
1826  hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
1827 
1828  bucket = &cache->cc_bucket[hashIndex];
1829  dlist_foreach(iter, bucket)
1830  {
1831  ct = dlist_container(CatCTup, cache_elem, iter.cur);
1832 
1833  if (ct->dead || ct->negative)
1834  continue; /* ignore dead and negative entries */
1835 
1836  if (ct->hash_value != hashValue)
1837  continue; /* quickly skip entry if wrong hash val */
1838 
1839  if (!ItemPointerEquals(&(ct->tuple.t_self), &(ntp->t_self)))
1840  continue; /* not same tuple */
1841 
1842  /*
1843  * Found a match, but can't use it if it belongs to
1844  * another list already
1845  */
1846  if (ct->c_list)
1847  continue;
1848 
1849  found = true;
1850  break; /* A-OK */
1851  }
1852 
1853  if (!found)
1854  {
1855  /* We didn't find a usable entry, so make a new one */
1856  ct = CatalogCacheCreateEntry(cache, ntp, scandesc, NULL,
1857  hashValue, hashIndex);
1858  /* upon failure, we must start the scan over */
1859  if (ct == NULL)
1860  {
1861  /*
1862  * Release refcounts on any items we already had. We
1863  * dare not try to free them if they're now
1864  * unreferenced, since an error while doing that would
1865  * result in the PG_CATCH below doing extra refcount
1866  * decrements. Besides, we'll likely re-adopt those
1867  * items in the next iteration, so it's not worth
1868  * complicating matters to try to get rid of them.
1869  */
1870  foreach(ctlist_item, ctlist)
1871  {
1872  ct = (CatCTup *) lfirst(ctlist_item);
1873  Assert(ct->c_list == NULL);
1874  Assert(ct->refcount > 0);
1875  ct->refcount--;
1876  }
1877  /* Reset ctlist in preparation for new try */
1878  ctlist = NIL;
1879  stale = true;
1880  break;
1881  }
1882  }
1883 
1884  /* Careful here: add entry to ctlist, then bump its refcount */
1885  /* This way leaves state correct if lappend runs out of memory */
1886  ctlist = lappend(ctlist, ct);
1887  ct->refcount++;
1888  }
1889 
1890  systable_endscan(scandesc);
1891  } while (stale);
1892 
1893  table_close(relation, AccessShareLock);
1894 
1895  /* Make sure the resource owner has room to remember this entry. */
1897 
1898  /* Now we can build the CatCList entry. */
1900  nmembers = list_length(ctlist);
1901  cl = (CatCList *)
1902  palloc(offsetof(CatCList, members) + nmembers * sizeof(CatCTup *));
1903 
1904  /* Extract key values */
1905  CatCacheCopyKeys(cache->cc_tupdesc, nkeys, cache->cc_keyno,
1906  arguments, cl->keys);
1907  MemoryContextSwitchTo(oldcxt);
1908 
1909  /*
1910  * We are now past the last thing that could trigger an elog before we
1911  * have finished building the CatCList and remembering it in the
1912  * resource owner. So it's OK to fall out of the PG_TRY, and indeed
1913  * we'd better do so before we start marking the members as belonging
1914  * to the list.
1915  */
1916  }
1917  PG_CATCH();
1918  {
1919  foreach(ctlist_item, ctlist)
1920  {
1921  ct = (CatCTup *) lfirst(ctlist_item);
1922  Assert(ct->c_list == NULL);
1923  Assert(ct->refcount > 0);
1924  ct->refcount--;
1925  if (
1926 #ifndef CATCACHE_FORCE_RELEASE
1927  ct->dead &&
1928 #endif
1929  ct->refcount == 0 &&
1930  (ct->c_list == NULL || ct->c_list->refcount == 0))
1931  CatCacheRemoveCTup(cache, ct);
1932  }
1933 
1934  PG_RE_THROW();
1935  }
1936  PG_END_TRY();
1937 
1938  cl->cl_magic = CL_MAGIC;
1939  cl->my_cache = cache;
1940  cl->refcount = 0; /* for the moment */
1941  cl->dead = false;
1942  cl->ordered = ordered;
1943  cl->nkeys = nkeys;
1944  cl->hash_value = lHashValue;
1945  cl->n_members = nmembers;
1946 
1947  i = 0;
1948  foreach(ctlist_item, ctlist)
1949  {
1950  cl->members[i++] = ct = (CatCTup *) lfirst(ctlist_item);
1951  Assert(ct->c_list == NULL);
1952  ct->c_list = cl;
1953  /* release the temporary refcount on the member */
1954  Assert(ct->refcount > 0);
1955  ct->refcount--;
1956  /* mark list dead if any members already dead */
1957  if (ct->dead)
1958  cl->dead = true;
1959  }
1960  Assert(i == nmembers);
1961 
1962  /*
1963  * Add the CatCList to the appropriate bucket, and count it.
1964  */
1965  dlist_push_head(lbucket, &cl->cache_elem);
1966 
1967  cache->cc_nlist++;
1968 
1969  /* Finally, bump the list's refcount and return it */
1970  cl->refcount++;
1972 
1973  CACHE_elog(DEBUG2, "SearchCatCacheList(%s): made list of %d members",
1974  cache->cc_relname, nmembers);
1975 
1976  return cl;
1977 }
static CatCTup * CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp, SysScanDesc scandesc, Datum *arguments, uint32 hashValue, Index hashIndex)
Definition: catcache.c:2042
static bool IndexScanOK(CatCache *cache)
Definition: catcache.c:1197
static void RehashCatCacheLists(CatCache *cp)
Definition: catcache.c:973
static void ResourceOwnerRememberCatCacheListRef(ResourceOwner owner, CatCList *list)
Definition: catcache.c:151
#define PG_RE_THROW()
Definition: elog.h:412
#define PG_TRY(...)
Definition: elog.h:371
#define PG_END_TRY(...)
Definition: elog.h:396
#define PG_CATCH(...)
Definition: elog.h:381
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:606
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:513
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:387
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:207
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 1425 of file catcache.c.

1433 {
1434  ScanKeyData cur_skey[CATCACHE_MAXKEYS];
1435  Relation relation;
1436  SysScanDesc scandesc;
1437  HeapTuple ntp;
1438  CatCTup *ct;
1439  bool stale;
1441 
1442  /* Initialize local parameter array */
1443  arguments[0] = v1;
1444  arguments[1] = v2;
1445  arguments[2] = v3;
1446  arguments[3] = v4;
1447 
1448  /*
1449  * Tuple was not found in cache, so we have to try to retrieve it directly
1450  * from the relation. If found, we will add it to the cache; if not
1451  * found, we will add a negative cache entry instead.
1452  *
1453  * NOTE: it is possible for recursive cache lookups to occur while reading
1454  * the relation --- for example, due to shared-cache-inval messages being
1455  * processed during table_open(). This is OK. It's even possible for one
1456  * of those lookups to find and enter the very same tuple we are trying to
1457  * fetch here. If that happens, we will enter a second copy of the tuple
1458  * into the cache. The first copy will never be referenced again, and
1459  * will eventually age out of the cache, so there's no functional problem.
1460  * This case is rare enough that it's not worth expending extra cycles to
1461  * detect.
1462  *
1463  * Another case, which we *must* handle, is that the tuple could become
1464  * outdated during CatalogCacheCreateEntry's attempt to detoast it (since
1465  * AcceptInvalidationMessages can run during TOAST table access). We do
1466  * not want to return already-stale catcache entries, so we loop around
1467  * and do the table scan again if that happens.
1468  */
1469  relation = table_open(cache->cc_reloid, AccessShareLock);
1470 
1471  /*
1472  * Ok, need to make a lookup in the relation, copy the scankey and fill
1473  * out any per-call fields.
1474  */
1475  memcpy(cur_skey, cache->cc_skey, sizeof(ScanKeyData) * nkeys);
1476  cur_skey[0].sk_argument = v1;
1477  cur_skey[1].sk_argument = v2;
1478  cur_skey[2].sk_argument = v3;
1479  cur_skey[3].sk_argument = v4;
1480 
1481  do
1482  {
1483  scandesc = systable_beginscan(relation,
1484  cache->cc_indexoid,
1485  IndexScanOK(cache),
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 226 of file catcache.c.

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

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

Referenced by GetCCHashEqFuncs().

◆ texthashfast()

static uint32 texthashfast ( Datum  datum)
static

Definition at line 236 of file catcache.c.

237 {
238  /* analogously here as in texteqfast() */
239  return DatumGetInt32(DirectFunctionCall1Coll(hashtext, DEFAULT_COLLATION_OID, datum));
240 }
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:2348
static char * ResOwnerPrintCatCache(Datum res)
Definition: catcache.c:2354
@ RESOURCE_RELEASE_AFTER_LOCKS
Definition: resowner.h:56
#define RELEASE_PRIO_CATCACHE_REFS
Definition: resowner.h:71

Definition at line 119 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:2371
static char * ResOwnerPrintCatCacheList(Datum res)
Definition: catcache.c:2377
#define RELEASE_PRIO_CATCACHE_LIST_REFS
Definition: resowner.h:72

Definition at line 129 of file catcache.c.

Referenced by ResourceOwnerForgetCatCacheListRef(), and ResourceOwnerRememberCatCacheListRef().