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, 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)
 
static bool equalTuple (HeapTuple a, HeapTuple b)
 
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 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: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 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 }
unsigned int uint32
Definition: c.h:506
#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: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 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:858
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 2044 of file catcache.c.

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

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

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

180 {
181  return murmurhash32((int32) DatumGetChar(datum));
182 }
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 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 2016 of file catcache.c.

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

References a, and b.

Referenced by CatalogCacheCreateEntry().

◆ GetCatCacheHashValue()

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

Definition at line 1613 of file catcache.c.

1618 {
1619  /*
1620  * one-time startup overhead for each cache
1621  */
1622  if (cache->cc_tupdesc == NULL)
1624 
1625  /*
1626  * calculate the hash value
1627  */
1628  return CatalogCacheComputeHashValue(cache, cache->cc_nkeys, v1, v2, v3, v4);
1629 }
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,
ScanKey  cur_skey 
)
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: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: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: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 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: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 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: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 249 of file catcache.c.

250 {
252 }
#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 2288 of file catcache.c.

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

1575 {
1577 }
static void ReleaseCatCacheWithOwner(HeapTuple tuple, ResourceOwner resowner)
Definition: catcache.c:1580
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 1993 of file catcache.c.

1994 {
1995  /* Safety checks to ensure we were handed a cache entry */
1996  Assert(list->cl_magic == CL_MAGIC);
1997  Assert(list->refcount > 0);
1998  list->refcount--;
1999  if (resowner)
2001 
2002  if (
2003 #ifndef CATCACHE_FORCE_RELEASE
2004  list->dead &&
2005 #endif
2006  list->refcount == 0)
2007  CatCacheRemoveCList(list->my_cache, list);
2008 }
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 1580 of file catcache.c.

1581 {
1582  CatCTup *ct = (CatCTup *) (((char *) tuple) -
1583  offsetof(CatCTup, tuple));
1584 
1585  /* Safety checks to ensure we were handed a cache entry */
1586  Assert(ct->ct_magic == CT_MAGIC);
1587  Assert(ct->refcount > 0);
1588 
1589  ct->refcount--;
1590  if (resowner)
1592 
1593  if (
1594 #ifndef CATCACHE_FORCE_RELEASE
1595  ct->dead &&
1596 #endif
1597  ct->refcount == 0 &&
1598  (ct->c_list == NULL || ct->c_list->refcount == 0))
1599  CatCacheRemoveCTup(ct->my_cache, ct);
1600 }
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 2355 of file catcache.c.

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

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

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

◆ ResOwnerReleaseCatCache()

static void ResOwnerReleaseCatCache ( Datum  res)
static

Definition at line 2349 of file catcache.c.

2350 {
2352 }

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

◆ ResOwnerReleaseCatCacheList()

static void ResOwnerReleaseCatCacheList ( Datum  res)
static

Definition at line 2372 of file catcache.c.

2373 {
2375 }

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: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: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:385

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

1652 {
1653  Datum v4 = 0; /* dummy last-column value */
1655  uint32 lHashValue;
1656  Index lHashIndex;
1657  dlist_iter iter;
1658  dlist_head *lbucket;
1659  CatCList *cl;
1660  CatCTup *ct;
1661  List *volatile ctlist;
1662  ListCell *ctlist_item;
1663  int nmembers;
1664  bool ordered;
1665  HeapTuple ntp;
1666  MemoryContext oldcxt;
1667  int i;
1668 
1669  /*
1670  * one-time startup overhead for each cache
1671  */
1672  if (unlikely(cache->cc_tupdesc == NULL))
1674 
1675  Assert(nkeys > 0 && nkeys < cache->cc_nkeys);
1676 
1677 #ifdef CATCACHE_STATS
1678  cache->cc_lsearches++;
1679 #endif
1680 
1681  /* Initialize local parameter array */
1682  arguments[0] = v1;
1683  arguments[1] = v2;
1684  arguments[2] = v3;
1685  arguments[3] = v4;
1686 
1687  /*
1688  * If we haven't previously done a list search in this cache, create the
1689  * bucket header array; otherwise, consider whether it's time to enlarge
1690  * it.
1691  */
1692  if (cache->cc_lbucket == NULL)
1693  {
1694  /* Arbitrary initial size --- must be a power of 2 */
1695  int nbuckets = 16;
1696 
1697  cache->cc_lbucket = (dlist_head *)
1699  nbuckets * sizeof(dlist_head));
1700  /* Don't set cc_nlbuckets if we get OOM allocating cc_lbucket */
1701  cache->cc_nlbuckets = nbuckets;
1702  }
1703  else
1704  {
1705  /*
1706  * If the hash table has become too full, enlarge the buckets array.
1707  * Quite arbitrarily, we enlarge when fill factor > 2.
1708  */
1709  if (cache->cc_nlist > cache->cc_nlbuckets * 2)
1710  RehashCatCacheLists(cache);
1711  }
1712 
1713  /*
1714  * Find the hash bucket in which to look for the CatCList.
1715  */
1716  lHashValue = CatalogCacheComputeHashValue(cache, nkeys, v1, v2, v3, v4);
1717  lHashIndex = HASH_INDEX(lHashValue, cache->cc_nlbuckets);
1718 
1719  /*
1720  * scan the items until we find a match or exhaust our list
1721  *
1722  * Note: it's okay to use dlist_foreach here, even though we modify the
1723  * dlist within the loop, because we don't continue the loop afterwards.
1724  */
1725  lbucket = &cache->cc_lbucket[lHashIndex];
1726  dlist_foreach(iter, lbucket)
1727  {
1728  cl = dlist_container(CatCList, cache_elem, iter.cur);
1729 
1730  if (cl->dead)
1731  continue; /* ignore dead entries */
1732 
1733  if (cl->hash_value != lHashValue)
1734  continue; /* quickly skip entry if wrong hash val */
1735 
1736  /*
1737  * see if the cached list matches our key.
1738  */
1739  if (cl->nkeys != nkeys)
1740  continue;
1741 
1742  if (!CatalogCacheCompareTuple(cache, nkeys, cl->keys, arguments))
1743  continue;
1744 
1745  /*
1746  * We found a matching list. Move the list to the front of the list
1747  * for its hashbucket, so as to speed subsequent searches. (We do not
1748  * move the members to the fronts of their hashbucket lists, however,
1749  * since there's no point in that unless they are searched for
1750  * individually.)
1751  */
1752  dlist_move_head(lbucket, &cl->cache_elem);
1753 
1754  /* Bump the list's refcount and return it */
1756  cl->refcount++;
1758 
1759  CACHE_elog(DEBUG2, "SearchCatCacheList(%s): found list",
1760  cache->cc_relname);
1761 
1762 #ifdef CATCACHE_STATS
1763  cache->cc_lhits++;
1764 #endif
1765 
1766  return cl;
1767  }
1768 
1769  /*
1770  * List was not found in cache, so we have to build it by reading the
1771  * relation. For each matching tuple found in the relation, use an
1772  * existing cache entry if possible, else build a new one.
1773  *
1774  * We have to bump the member refcounts temporarily to ensure they won't
1775  * get dropped from the cache while loading other members. We use a PG_TRY
1776  * block to ensure we can undo those refcounts if we get an error before
1777  * we finish constructing the CatCList. ctlist must be valid throughout
1778  * the PG_TRY block.
1779  */
1780  ctlist = NIL;
1781 
1782  PG_TRY();
1783  {
1784  ScanKeyData cur_skey[CATCACHE_MAXKEYS];
1785  Relation relation;
1786  SysScanDesc scandesc;
1787  bool stale;
1788 
1789  relation = table_open(cache->cc_reloid, AccessShareLock);
1790 
1791  do
1792  {
1793  /*
1794  * Ok, need to make a lookup in the relation, copy the scankey and
1795  * fill out any per-call fields. (We must re-do this when
1796  * retrying, because systable_beginscan scribbles on the scankey.)
1797  */
1798  memcpy(cur_skey, cache->cc_skey, sizeof(ScanKeyData) * cache->cc_nkeys);
1799  cur_skey[0].sk_argument = v1;
1800  cur_skey[1].sk_argument = v2;
1801  cur_skey[2].sk_argument = v3;
1802  cur_skey[3].sk_argument = v4;
1803 
1804  scandesc = systable_beginscan(relation,
1805  cache->cc_indexoid,
1806  IndexScanOK(cache, cur_skey),
1807  NULL,
1808  nkeys,
1809  cur_skey);
1810 
1811  /* The list will be ordered iff we are doing an index scan */
1812  ordered = (scandesc->irel != NULL);
1813 
1814  stale = false;
1815 
1816  while (HeapTupleIsValid(ntp = systable_getnext(scandesc)))
1817  {
1818  uint32 hashValue;
1819  Index hashIndex;
1820  bool found = false;
1821  dlist_head *bucket;
1822 
1823  /*
1824  * See if there's an entry for this tuple already.
1825  */
1826  ct = NULL;
1827  hashValue = CatalogCacheComputeTupleHashValue(cache, cache->cc_nkeys, ntp);
1828  hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
1829 
1830  bucket = &cache->cc_bucket[hashIndex];
1831  dlist_foreach(iter, bucket)
1832  {
1833  ct = dlist_container(CatCTup, cache_elem, iter.cur);
1834 
1835  if (ct->dead || ct->negative)
1836  continue; /* ignore dead and negative entries */
1837 
1838  if (ct->hash_value != hashValue)
1839  continue; /* quickly skip entry if wrong hash val */
1840 
1841  if (!ItemPointerEquals(&(ct->tuple.t_self), &(ntp->t_self)))
1842  continue; /* not same tuple */
1843 
1844  /*
1845  * Found a match, but can't use it if it belongs to
1846  * another list already
1847  */
1848  if (ct->c_list)
1849  continue;
1850 
1851  found = true;
1852  break; /* A-OK */
1853  }
1854 
1855  if (!found)
1856  {
1857  /* We didn't find a usable entry, so make a new one */
1858  ct = CatalogCacheCreateEntry(cache, ntp, scandesc, NULL,
1859  hashValue, hashIndex);
1860  /* upon failure, we must start the scan over */
1861  if (ct == NULL)
1862  {
1863  /*
1864  * Release refcounts on any items we already had. We
1865  * dare not try to free them if they're now
1866  * unreferenced, since an error while doing that would
1867  * result in the PG_CATCH below doing extra refcount
1868  * decrements. Besides, we'll likely re-adopt those
1869  * items in the next iteration, so it's not worth
1870  * complicating matters to try to get rid of them.
1871  */
1872  foreach(ctlist_item, ctlist)
1873  {
1874  ct = (CatCTup *) lfirst(ctlist_item);
1875  Assert(ct->c_list == NULL);
1876  Assert(ct->refcount > 0);
1877  ct->refcount--;
1878  }
1879  /* Reset ctlist in preparation for new try */
1880  ctlist = NIL;
1881  stale = true;
1882  break;
1883  }
1884  }
1885 
1886  /* Careful here: add entry to ctlist, then bump its refcount */
1887  /* This way leaves state correct if lappend runs out of memory */
1888  ctlist = lappend(ctlist, ct);
1889  ct->refcount++;
1890  }
1891 
1892  systable_endscan(scandesc);
1893  } while (stale);
1894 
1895  table_close(relation, AccessShareLock);
1896 
1897  /* Make sure the resource owner has room to remember this entry. */
1899 
1900  /* Now we can build the CatCList entry. */
1902  nmembers = list_length(ctlist);
1903  cl = (CatCList *)
1904  palloc(offsetof(CatCList, members) + nmembers * sizeof(CatCTup *));
1905 
1906  /* Extract key values */
1907  CatCacheCopyKeys(cache->cc_tupdesc, nkeys, cache->cc_keyno,
1908  arguments, cl->keys);
1909  MemoryContextSwitchTo(oldcxt);
1910 
1911  /*
1912  * We are now past the last thing that could trigger an elog before we
1913  * have finished building the CatCList and remembering it in the
1914  * resource owner. So it's OK to fall out of the PG_TRY, and indeed
1915  * we'd better do so before we start marking the members as belonging
1916  * to the list.
1917  */
1918  }
1919  PG_CATCH();
1920  {
1921  foreach(ctlist_item, ctlist)
1922  {
1923  ct = (CatCTup *) lfirst(ctlist_item);
1924  Assert(ct->c_list == NULL);
1925  Assert(ct->refcount > 0);
1926  ct->refcount--;
1927  if (
1928 #ifndef CATCACHE_FORCE_RELEASE
1929  ct->dead &&
1930 #endif
1931  ct->refcount == 0 &&
1932  (ct->c_list == NULL || ct->c_list->refcount == 0))
1933  CatCacheRemoveCTup(cache, ct);
1934  }
1935 
1936  PG_RE_THROW();
1937  }
1938  PG_END_TRY();
1939 
1940  cl->cl_magic = CL_MAGIC;
1941  cl->my_cache = cache;
1942  cl->refcount = 0; /* for the moment */
1943  cl->dead = false;
1944  cl->ordered = ordered;
1945  cl->nkeys = nkeys;
1946  cl->hash_value = lHashValue;
1947  cl->n_members = nmembers;
1948 
1949  i = 0;
1950  foreach(ctlist_item, ctlist)
1951  {
1952  cl->members[i++] = ct = (CatCTup *) lfirst(ctlist_item);
1953  Assert(ct->c_list == NULL);
1954  ct->c_list = cl;
1955  /* release the temporary refcount on the member */
1956  Assert(ct->refcount > 0);
1957  ct->refcount--;
1958  /* mark list dead if any members already dead */
1959  if (ct->dead)
1960  cl->dead = true;
1961  }
1962  Assert(i == nmembers);
1963 
1964  /*
1965  * Add the CatCList to the appropriate bucket, and count it.
1966  */
1967  dlist_push_head(lbucket, &cl->cache_elem);
1968 
1969  cache->cc_nlist++;
1970 
1971  /* Finally, bump the list's refcount and return it */
1972  cl->refcount++;
1974 
1975  CACHE_elog(DEBUG2, "SearchCatCacheList(%s): made list of %d members",
1976  cache->cc_relname, nmembers);
1977 
1978  return cl;
1979 }
static CatCTup * CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp, SysScanDesc scandesc, Datum *arguments, uint32 hashValue, Index hashIndex)
Definition: catcache.c:2044
static void RehashCatCacheLists(CatCache *cp)
Definition: catcache.c:973
static void ResourceOwnerRememberCatCacheListRef(ResourceOwner owner, CatCList *list)
Definition: catcache.c:151
static bool IndexScanOK(CatCache *cache, ScanKey cur_skey)
Definition: catcache.c:1197
#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 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  do
1472  {
1473  /*
1474  * Ok, need to make a lookup in the relation, copy the scankey and
1475  * fill out any per-call fields. (We must re-do this when retrying,
1476  * because systable_beginscan scribbles on the scankey.)
1477  */
1478  memcpy(cur_skey, cache->cc_skey, sizeof(ScanKeyData) * nkeys);
1479  cur_skey[0].sk_argument = v1;
1480  cur_skey[1].sk_argument = v2;
1481  cur_skey[2].sk_argument = v3;
1482  cur_skey[3].sk_argument = v4;
1483 
1484  scandesc = systable_beginscan(relation,
1485  cache->cc_indexoid,
1486  IndexScanOK(cache, cur_skey),
1487  NULL,
1488  nkeys,
1489  cur_skey);
1490 
1491  ct = NULL;
1492  stale = false;
1493 
1494  while (HeapTupleIsValid(ntp = systable_getnext(scandesc)))
1495  {
1496  ct = CatalogCacheCreateEntry(cache, ntp, scandesc, NULL,
1497  hashValue, hashIndex);
1498  /* upon failure, we must start the scan over */
1499  if (ct == NULL)
1500  {
1501  stale = true;
1502  break;
1503  }
1504  /* immediately set the refcount to 1 */
1506  ct->refcount++;
1508  break; /* assume only one match */
1509  }
1510 
1511  systable_endscan(scandesc);
1512  } while (stale);
1513 
1514  table_close(relation, AccessShareLock);
1515 
1516  /*
1517  * If tuple was not found, we need to build a negative cache entry
1518  * containing a fake tuple. The fake tuple has the correct key columns,
1519  * but nulls everywhere else.
1520  *
1521  * In bootstrap mode, we don't build negative entries, because the cache
1522  * invalidation mechanism isn't alive and can't clear them if the tuple
1523  * gets created later. (Bootstrap doesn't do UPDATEs, so it doesn't need
1524  * cache inval for that.)
1525  */
1526  if (ct == NULL)
1527  {
1529  return NULL;
1530 
1531  ct = CatalogCacheCreateEntry(cache, NULL, NULL, arguments,
1532  hashValue, hashIndex);
1533 
1534  /* Creating a negative cache entry shouldn't fail */
1535  Assert(ct != NULL);
1536 
1537  CACHE_elog(DEBUG2, "SearchCatCache(%s): Contains %d/%d tuples",
1538  cache->cc_relname, cache->cc_ntup, CacheHdr->ch_ntup);
1539  CACHE_elog(DEBUG2, "SearchCatCache(%s): put neg entry in bucket %d",
1540  cache->cc_relname, hashIndex);
1541 
1542  /*
1543  * We are not returning the negative entry to the caller, so leave its
1544  * refcount zero.
1545  */
1546 
1547  return NULL;
1548  }
1549 
1550  CACHE_elog(DEBUG2, "SearchCatCache(%s): Contains %d/%d tuples",
1551  cache->cc_relname, cache->cc_ntup, CacheHdr->ch_ntup);
1552  CACHE_elog(DEBUG2, "SearchCatCache(%s): put in bucket %d",
1553  cache->cc_relname, hashIndex);
1554 
1555 #ifdef CATCACHE_STATS
1556  cache->cc_newloads++;
1557 #endif
1558 
1559  return &ct->tuple;
1560 }
#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:1619

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:2349
static char * ResOwnerPrintCatCache(Datum res)
Definition: catcache.c:2355
@ 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:2372
static char * ResOwnerPrintCatCacheList(Datum res)
Definition: catcache.c:2378
#define RELEASE_PRIO_CATCACHE_LIST_REFS
Definition: resowner.h:72

Definition at line 129 of file catcache.c.

Referenced by ResourceOwnerForgetCatCacheListRef(), and ResourceOwnerRememberCatCacheListRef().