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

Go to the source code of this file.

Macros

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

Functions

static HeapTuple SearchCatCacheInternal (CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
 
static pg_noinline HeapTuple SearchCatCacheMiss (CatCache *cache, int nkeys, uint32 hashValue, Index hashIndex, Datum v1, Datum v2, Datum v3, Datum v4)
 
static uint32 CatalogCacheComputeHashValue (CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
 
static uint32 CatalogCacheComputeTupleHashValue (CatCache *cache, int nkeys, HeapTuple tuple)
 
static bool CatalogCacheCompareTuple (const CatCache *cache, int nkeys, const Datum *cachekeys, const Datum *searchkeys)
 
static void CatCacheRemoveCTup (CatCache *cache, CatCTup *ct)
 
static void CatCacheRemoveCList (CatCache *cache, CatCList *cl)
 
static void 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)
 
static void RehashCatCache (CatCache *cp)
 
void InitCatCachePhase2 (CatCache *cache, bool touch_index)
 
static bool IndexScanOK (CatCache *cache, ScanKey cur_skey)
 
HeapTuple SearchCatCache (CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
 
HeapTuple SearchCatCache1 (CatCache *cache, Datum v1)
 
HeapTuple SearchCatCache2 (CatCache *cache, Datum v1, Datum v2)
 
HeapTuple SearchCatCache3 (CatCache *cache, Datum v1, Datum v2, Datum v3)
 
HeapTuple SearchCatCache4 (CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
 
void ReleaseCatCache (HeapTuple tuple)
 
uint32 GetCatCacheHashValue (CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
 
CatCListSearchCatCacheList (CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3)
 
void ReleaseCatCacheList (CatCList *list)
 
void PrepareToInvalidateCacheTuple (Relation relation, HeapTuple tuple, HeapTuple newtuple, void(*function)(int, uint32, Oid))
 

Variables

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

Macro Definition Documentation

◆ CACHE_elog

#define CACHE_elog (   ...)

Definition at line 60 of file catcache.c.

◆ CatalogCacheInitializeCache_DEBUG1

#define CatalogCacheInitializeCache_DEBUG1

Definition at line 966 of file catcache.c.

◆ CatalogCacheInitializeCache_DEBUG2

#define CatalogCacheInitializeCache_DEBUG2

Definition at line 967 of file catcache.c.

◆ HASH_INDEX

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

Definition at line 50 of file catcache.c.

◆ InitCatCache_DEBUG2

#define InitCatCache_DEBUG2

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

423 {
424  const CCFastEqualFN *cc_fastequal = cache->cc_fastequal;
425  int i;
426 
427  for (i = 0; i < nkeys; i++)
428  {
429  if (!(cc_fastequal[i]) (cachekeys[i], searchkeys[i]))
430  return false;
431  }
432  return true;
433 }
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 323 of file catcache.c.

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

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

1932 {
1933  CatCTup *ct;
1934  HeapTuple dtp;
1935  MemoryContext oldcxt;
1936 
1937  if (ntp)
1938  {
1939  int i;
1940 
1941  /*
1942  * The visibility recheck below essentially never fails during our
1943  * regression tests, and there's no easy way to force it to fail for
1944  * testing purposes. To ensure we have test coverage for the retry
1945  * paths in our callers, make debug builds randomly fail about 0.1% of
1946  * the times through this code path, even when there's no toasted
1947  * fields.
1948  */
1949 #ifdef USE_ASSERT_CHECKING
1951  return NULL;
1952 #endif
1953 
1954  /*
1955  * If there are any out-of-line toasted fields in the tuple, expand
1956  * them in-line. This saves cycles during later use of the catcache
1957  * entry, and also protects us against the possibility of the toast
1958  * tuples being freed before we attempt to fetch them, in case of
1959  * something using a slightly stale catcache entry.
1960  */
1961  if (HeapTupleHasExternal(ntp))
1962  {
1963  dtp = toast_flatten_tuple(ntp, cache->cc_tupdesc);
1964 
1965  /*
1966  * The tuple could become stale while we are doing toast table
1967  * access (since AcceptInvalidationMessages can run then), so we
1968  * must recheck its visibility afterwards.
1969  */
1970  if (!systable_recheck_tuple(scandesc, ntp))
1971  {
1972  heap_freetuple(dtp);
1973  return NULL;
1974  }
1975  }
1976  else
1977  dtp = ntp;
1978 
1979  /* Allocate memory for CatCTup and the cached tuple in one go */
1981 
1982  ct = (CatCTup *) palloc(sizeof(CatCTup) +
1983  MAXIMUM_ALIGNOF + dtp->t_len);
1984  ct->tuple.t_len = dtp->t_len;
1985  ct->tuple.t_self = dtp->t_self;
1986  ct->tuple.t_tableOid = dtp->t_tableOid;
1987  ct->tuple.t_data = (HeapTupleHeader)
1988  MAXALIGN(((char *) ct) + sizeof(CatCTup));
1989  /* copy tuple contents */
1990  memcpy((char *) ct->tuple.t_data,
1991  (const char *) dtp->t_data,
1992  dtp->t_len);
1993  MemoryContextSwitchTo(oldcxt);
1994 
1995  if (dtp != ntp)
1996  heap_freetuple(dtp);
1997 
1998  /* extract keys - they'll point into the tuple if not by-value */
1999  for (i = 0; i < cache->cc_nkeys; i++)
2000  {
2001  Datum atp;
2002  bool isnull;
2003 
2004  atp = heap_getattr(&ct->tuple,
2005  cache->cc_keyno[i],
2006  cache->cc_tupdesc,
2007  &isnull);
2008  Assert(!isnull);
2009  ct->keys[i] = atp;
2010  }
2011  }
2012  else
2013  {
2014  /* Set up keys for a negative cache entry */
2016  ct = (CatCTup *) palloc(sizeof(CatCTup));
2017 
2018  /*
2019  * Store keys - they'll point into separately allocated memory if not
2020  * by-value.
2021  */
2022  CatCacheCopyKeys(cache->cc_tupdesc, cache->cc_nkeys, cache->cc_keyno,
2023  arguments, ct->keys);
2024  MemoryContextSwitchTo(oldcxt);
2025  }
2026 
2027  /*
2028  * Finish initializing the CatCTup header, and add it to the cache's
2029  * linked list and counts.
2030  */
2031  ct->ct_magic = CT_MAGIC;
2032  ct->my_cache = cache;
2033  ct->c_list = NULL;
2034  ct->refcount = 0; /* for the moment */
2035  ct->dead = false;
2036  ct->negative = (ntp == NULL);
2037  ct->hash_value = hashValue;
2038 
2039  dlist_push_head(&cache->cc_bucket[hashIndex], &ct->cache_elem);
2040 
2041  cache->cc_ntup++;
2042  CacheHdr->ch_ntup++;
2043 
2044  /*
2045  * If the hash table has become too full, enlarge the buckets array. Quite
2046  * arbitrarily, we enlarge when fill factor > 2.
2047  */
2048  if (cache->cc_ntup > cache->cc_nbuckets * 2)
2049  RehashCatCache(cache);
2050 
2051  return ct;
2052 }
#define MAXALIGN(LEN)
Definition: c.h:798
#define PG_UINT32_MAX
Definition: c.h:577
static void RehashCatCache(CatCache *cp)
Definition: catcache.c:908
static void CatCacheCopyKeys(TupleDesc tupdesc, int nkeys, int *attnos, Datum *srckeys, Datum *dstkeys)
Definition: catcache.c:2083
static CatCacheHeader * CacheHdr
Definition: catcache.c:64
#define CT_MAGIC
Definition: catcache.h:89
bool systable_recheck_tuple(SysScanDesc sysscan, HeapTuple tup)
Definition: genam.c:562
HeapTuple toast_flatten_tuple(HeapTuple tup, TupleDesc tupleDesc)
Definition: heaptoast.c:350
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1434
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:792
#define HeapTupleHasExternal(tuple)
Definition: htup_details.h:671
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:347
MemoryContext CacheMemoryContext
Definition: mcxt.c:140
void * palloc(Size size)
Definition: mcxt.c:1304
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
uint32 pg_prng_uint32(pg_prng_state *state)
Definition: pg_prng.c:191
pg_prng_state pg_global_prng_state
Definition: pg_prng.c:34
ItemPointerData t_self
Definition: htup.h:65
uint32 t_len
Definition: htup.h:64
HeapTupleHeader t_data
Definition: htup.h:68
Oid t_tableOid
Definition: htup.h:66
dlist_head * cc_bucket
Definition: catcache.h:49
int cc_nkeys
Definition: catcache.h:56
int cc_nbuckets
Definition: catcache.h:47
int cc_ntup
Definition: catcache.h:55
int ct_magic
Definition: catcache.h:88
int refcount
Definition: catcache.h:118
bool negative
Definition: catcache.h:120
dlist_node cache_elem
Definition: catcache.h:104
HeapTupleData tuple
Definition: catcache.h:121
CatCache * my_cache
Definition: catcache.h:132
struct catclist * c_list
Definition: catcache.h:130
Datum keys[CATCACHE_MAXKEYS]
Definition: catcache.h:97
bool dead
Definition: catcache.h:119
uint32 hash_value
Definition: catcache.h:91

References Assert(), catctup::c_list, catctup::cache_elem, CacheHdr, CacheMemoryContext, CatCacheCopyKeys(), catcache::cc_bucket, catcache::cc_keyno, catcache::cc_nbuckets, catcache::cc_nkeys, catcache::cc_ntup, catcache::cc_tupdesc, catcacheheader::ch_ntup, catctup::ct_magic, CT_MAGIC, catctup::dead, dlist_push_head(), catctup::hash_value, heap_freetuple(), heap_getattr(), HeapTupleHasExternal, i, catctup::keys, MAXALIGN, MemoryContextSwitchTo(), catctup::my_cache, catctup::negative, palloc(), pg_global_prng_state, pg_prng_uint32(), PG_UINT32_MAX, catctup::refcount, RehashCatCache(), systable_recheck_tuple(), HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, toast_flatten_tuple(), and catctup::tuple.

Referenced by SearchCatCacheList(), and SearchCatCacheMiss().

◆ CatalogCacheFlushCatalog()

void CatalogCacheFlushCatalog ( Oid  catId)

Definition at line 765 of file catcache.c.

766 {
767  slist_iter iter;
768 
769  CACHE_elog(DEBUG2, "CatalogCacheFlushCatalog called for %u", catId);
770 
772  {
773  CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
774 
775  /* Does this cache store tuples of the target catalog? */
776  if (cache->cc_reloid == catId)
777  {
778  /* Yes, so flush all its contents */
779  ResetCatalogCache(cache);
780 
781  /* Tell inval.c to call syscache callbacks for this cache */
782  CallSyscacheCallbacks(cache->id, 0);
783  }
784  }
785 
786  CACHE_elog(DEBUG2, "end of CatalogCacheFlushCatalog call");
787 }
static void ResetCatalogCache(CatCache *cache)
Definition: catcache.c:688
#define slist_container(type, membername, ptr)
Definition: ilist.h:1106
#define slist_foreach(iter, lhead)
Definition: ilist.h:1132
void CallSyscacheCallbacks(int cacheid, uint32 hashvalue)
Definition: inval.c:1577
Oid cc_reloid
Definition: catcache.h:58
int id
Definition: catcache.h:46
slist_head ch_caches
Definition: catcache.h:184
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 971 of file catcache.c.

972 {
973  Relation relation;
974  MemoryContext oldcxt;
975  TupleDesc tupdesc;
976  int i;
977 
979 
980  relation = table_open(cache->cc_reloid, AccessShareLock);
981 
982  /*
983  * switch to the cache context so our allocations do not vanish at the end
984  * of a transaction
985  */
986  Assert(CacheMemoryContext != NULL);
987 
989 
990  /*
991  * copy the relcache's tuple descriptor to permanent cache storage
992  */
993  tupdesc = CreateTupleDescCopyConstr(RelationGetDescr(relation));
994 
995  /*
996  * save the relation's name and relisshared flag, too (cc_relname is used
997  * only for debugging purposes)
998  */
999  cache->cc_relname = pstrdup(RelationGetRelationName(relation));
1000  cache->cc_relisshared = RelationGetForm(relation)->relisshared;
1001 
1002  /*
1003  * return to the caller's memory context and close the rel
1004  */
1005  MemoryContextSwitchTo(oldcxt);
1006 
1007  table_close(relation, AccessShareLock);
1008 
1009  CACHE_elog(DEBUG2, "CatalogCacheInitializeCache: %s, %d keys",
1010  cache->cc_relname, cache->cc_nkeys);
1011 
1012  /*
1013  * initialize cache's key information
1014  */
1015  for (i = 0; i < cache->cc_nkeys; ++i)
1016  {
1017  Oid keytype;
1018  RegProcedure eqfunc;
1019 
1021 
1022  if (cache->cc_keyno[i] > 0)
1023  {
1024  Form_pg_attribute attr = TupleDescAttr(tupdesc,
1025  cache->cc_keyno[i] - 1);
1026 
1027  keytype = attr->atttypid;
1028  /* cache key columns should always be NOT NULL */
1029  Assert(attr->attnotnull);
1030  }
1031  else
1032  {
1033  if (cache->cc_keyno[i] < 0)
1034  elog(FATAL, "sys attributes are not supported in caches");
1035  keytype = OIDOID;
1036  }
1037 
1038  GetCCHashEqFuncs(keytype,
1039  &cache->cc_hashfunc[i],
1040  &eqfunc,
1041  &cache->cc_fastequal[i]);
1042 
1043  /*
1044  * Do equality-function lookup (we assume this won't need a catalog
1045  * lookup for any supported type)
1046  */
1047  fmgr_info_cxt(eqfunc,
1048  &cache->cc_skey[i].sk_func,
1050 
1051  /* Initialize sk_attno suitably for HeapKeyTest() and heap scans */
1052  cache->cc_skey[i].sk_attno = cache->cc_keyno[i];
1053 
1054  /* Fill in sk_strategy as well --- always standard equality */
1056  cache->cc_skey[i].sk_subtype = InvalidOid;
1057  /* If a catcache key requires a collation, it must be C collation */
1058  cache->cc_skey[i].sk_collation = C_COLLATION_OID;
1059 
1060  CACHE_elog(DEBUG2, "CatalogCacheInitializeCache %s %d %p",
1061  cache->cc_relname, i, cache);
1062  }
1063 
1064  /*
1065  * mark this cache fully initialized
1066  */
1067  cache->cc_tupdesc = tupdesc;
1068 }
regproc RegProcedure
Definition: c.h:637
#define CatalogCacheInitializeCache_DEBUG1
Definition: catcache.c:966
static void GetCCHashEqFuncs(Oid keytype, CCHashFN *hashfunc, RegProcedure *eqfunc, CCFastEqualFN *fasteqfunc)
Definition: catcache.c:253
#define CatalogCacheInitializeCache_DEBUG2
Definition: catcache.c:967
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:1683
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:60
ScanKeyData cc_skey[CATCACHE_MAXKEYS]
Definition: catcache.h:62
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 2083 of file catcache.c.

2085 {
2086  int i;
2087 
2088  /*
2089  * XXX: memory and lookup performance could possibly be improved by
2090  * storing all keys in one allocation.
2091  */
2092 
2093  for (i = 0; i < nkeys; i++)
2094  {
2095  int attnum = attnos[i];
2096  Form_pg_attribute att = TupleDescAttr(tupdesc, attnum - 1);
2097  Datum src = srckeys[i];
2098  NameData srcname;
2099 
2100  /*
2101  * Must be careful in case the caller passed a C string where a NAME
2102  * is wanted: convert the given argument to a correctly padded NAME.
2103  * Otherwise the memcpy() done by datumCopy() could fall off the end
2104  * of memory.
2105  */
2106  if (att->atttypid == NAMEOID)
2107  {
2108  namestrcpy(&srcname, DatumGetCString(src));
2109  src = NameGetDatum(&srcname);
2110  }
2111 
2112  dstkeys[i] = datumCopy(src,
2113  att->attbyval,
2114  att->attlen);
2115  }
2116 }
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:728

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

2059 {
2060  int i;
2061 
2062  for (i = 0; i < nkeys; i++)
2063  {
2064  int attnum = attnos[i];
2065  Form_pg_attribute att;
2066 
2067  /* system attribute are not supported in caches */
2068  Assert(attnum > 0);
2069 
2070  att = TupleDescAttr(tupdesc, attnum - 1);
2071 
2072  if (!att->attbyval)
2073  pfree(DatumGetPointer(keys[i]));
2074  }
2075 }
void pfree(void *pointer)
Definition: mcxt.c:1508
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 598 of file catcache.c.

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

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

Referenced by SysCacheInvalidate().

◆ CatCacheRemoveCList()

static void CatCacheRemoveCList ( CatCache cache,
CatCList cl 
)
static

Definition at line 545 of file catcache.c.

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

References Assert(), catctup::c_list, catclist::cache_elem, CatCacheFreeKeys(), CatCacheRemoveCTup(), catcache::cc_keyno, catcache::cc_tupdesc, catctup::dead, dlist_delete(), i, catclist::keys, catclist::members, catclist::my_cache, catclist::n_members, catclist::nkeys, pfree(), catctup::refcount, and catclist::refcount.

Referenced by CatCacheInvalidate(), CatCacheRemoveCTup(), ReleaseCatCacheListWithOwner(), and ResetCatalogCache().

◆ CatCacheRemoveCTup()

static void CatCacheRemoveCTup ( CatCache cache,
CatCTup ct 
)
static

Definition at line 503 of file catcache.c.

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

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

171 {
172  return DatumGetChar(a) == DatumGetChar(b);
173 }
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 176 of file catcache.c.

177 {
178  return murmurhash32((int32) DatumGetChar(datum));
179 }
signed int 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 666 of file catcache.c.

667 {
668  /*
669  * Purely for paranoia, check that context doesn't exist; caller probably
670  * did so already.
671  */
672  if (!CacheMemoryContext)
674  "CacheMemoryContext",
676 }
MemoryContext TopMemoryContext
Definition: mcxt.c:137
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:153

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CacheMemoryContext, and TopMemoryContext.

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

◆ GetCatCacheHashValue()

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

Definition at line 1548 of file catcache.c.

1553 {
1554  /*
1555  * one-time startup overhead for each cache
1556  */
1557  if (cache->cc_tupdesc == NULL)
1559 
1560  /*
1561  * calculate the hash value
1562  */
1563  return CatalogCacheComputeHashValue(cache, cache->cc_nkeys, v1, v2, v3, v4);
1564 }
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:971

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

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

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

1133 {
1134  switch (cache->id)
1135  {
1136  case INDEXRELID:
1137 
1138  /*
1139  * Rather than tracking exactly which indexes have to be loaded
1140  * before we can use indexscans (which changes from time to time),
1141  * just force all pg_index searches to be heap scans until we've
1142  * built the critical relcaches.
1143  */
1145  return false;
1146  break;
1147 
1148  case AMOID:
1149  case AMNAME:
1150 
1151  /*
1152  * Always do heap scans in pg_am, because it's so small there's
1153  * not much point in an indexscan anyway. We *must* do this when
1154  * initially building critical relcache entries, but we might as
1155  * well just always do it.
1156  */
1157  return false;
1158 
1159  case AUTHNAME:
1160  case AUTHOID:
1161  case AUTHMEMMEMROLE:
1162  case DATABASEOID:
1163 
1164  /*
1165  * Protect authentication lookups occurring before relcache has
1166  * collected entries for shared indexes.
1167  */
1169  return false;
1170  break;
1171 
1172  default:
1173  break;
1174  }
1175 
1176  /* Normal case, allow index scan */
1177  return true;
1178 }
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 809 of file catcache.c.

815 {
816  CatCache *cp;
817  MemoryContext oldcxt;
818  int i;
819 
820  /*
821  * nbuckets is the initial number of hash buckets to use in this catcache.
822  * It will be enlarged later if it becomes too full.
823  *
824  * nbuckets must be a power of two. We check this via Assert rather than
825  * a full runtime check because the values will be coming from constant
826  * tables.
827  *
828  * If you're confused by the power-of-two check, see comments in
829  * bitmapset.c for an explanation.
830  */
831  Assert(nbuckets > 0 && (nbuckets & -nbuckets) == nbuckets);
832 
833  /*
834  * first switch to the cache context so our allocations do not vanish at
835  * the end of a transaction
836  */
837  if (!CacheMemoryContext)
839 
841 
842  /*
843  * if first time through, initialize the cache group header
844  */
845  if (CacheHdr == NULL)
846  {
849  CacheHdr->ch_ntup = 0;
850 #ifdef CATCACHE_STATS
851  /* set up to dump stats at backend exit */
852  on_proc_exit(CatCachePrintStats, 0);
853 #endif
854  }
855 
856  /*
857  * Allocate a new cache structure, aligning to a cacheline boundary
858  *
859  * Note: we rely on zeroing to initialize all the dlist headers correctly
860  */
863  cp->cc_bucket = palloc0(nbuckets * sizeof(dlist_head));
864 
865  /*
866  * initialize the cache's relation information for the relation
867  * corresponding to this cache, and initialize some of the new cache's
868  * other internal fields. But don't open the relation yet.
869  */
870  cp->id = id;
871  cp->cc_relname = "(not known yet)";
872  cp->cc_reloid = reloid;
873  cp->cc_indexoid = indexoid;
874  cp->cc_relisshared = false; /* temporary */
875  cp->cc_tupdesc = (TupleDesc) NULL;
876  cp->cc_ntup = 0;
877  cp->cc_nbuckets = nbuckets;
878  cp->cc_nkeys = nkeys;
879  for (i = 0; i < nkeys; ++i)
880  {
882  cp->cc_keyno[i] = key[i];
883  }
884 
885  /*
886  * new cache is initialized as far as we can go for now. print some
887  * debugging information, if appropriate.
888  */
890 
891  /*
892  * add completed cache to top of group header's list
893  */
895 
896  /*
897  * back to the old context before we return...
898  */
899  MemoryContextSwitchTo(oldcxt);
900 
901  return cp;
902 }
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
void CreateCacheMemoryContext(void)
Definition: catcache.c:666
#define InitCatCache_DEBUG2
Definition: catcache.c:805
#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:1334
void * palloc_aligned(Size size, Size alignto, int flags)
Definition: mcxt.c:1498
#define PG_CACHE_LINE_SIZE
slist_node cc_next
Definition: catcache.h:61
Oid cc_indexoid
Definition: catcache.h:59
struct TupleDescData * TupleDesc
Definition: tupdesc.h:89

References Assert(), AttributeNumberIsValid, CacheHdr, CacheMemoryContext, catcache::cc_bucket, catcache::cc_indexoid, catcache::cc_keyno, catcache::cc_nbuckets, catcache::cc_next, catcache::cc_nkeys, catcache::cc_ntup, catcache::cc_relisshared, catcache::cc_relname, catcache::cc_reloid, catcache::cc_tupdesc, catcacheheader::ch_caches, catcacheheader::ch_ntup, CreateCacheMemoryContext(), i, catcache::id, InitCatCache_DEBUG2, 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 1080 of file catcache.c.

1081 {
1082  if (cache->cc_tupdesc == NULL)
1084 
1085  if (touch_index &&
1086  cache->id != AMOID &&
1087  cache->id != AMNAME)
1088  {
1089  Relation idesc;
1090 
1091  /*
1092  * We must lock the underlying catalog before opening the index to
1093  * avoid deadlock, since index_open could possibly result in reading
1094  * this same catalog, and if anyone else is exclusive-locking this
1095  * catalog and index they'll be doing it in that order.
1096  */
1098  idesc = index_open(cache->cc_indexoid, AccessShareLock);
1099 
1100  /*
1101  * While we've got the index open, let's check that it's unique (and
1102  * not just deferrable-unique, thank you very much). This is just to
1103  * catch thinkos in definitions of new catcaches, so we don't worry
1104  * about the pg_am indexes not getting tested.
1105  */
1106  Assert(idesc->rd_index->indisunique &&
1107  idesc->rd_index->indimmediate);
1108 
1109  index_close(idesc, AccessShareLock);
1111  }
1112 }
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 199 of file catcache.c.

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

206 {
207  return murmurhash32((int32) DatumGetInt16(datum));
208 }

References DatumGetInt16(), and murmurhash32().

Referenced by GetCCHashEqFuncs().

◆ int4eqfast()

static bool int4eqfast ( Datum  a,
Datum  b 
)
static

Definition at line 211 of file catcache.c.

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

218 {
219  return murmurhash32((int32) DatumGetInt32(datum));
220 }

References DatumGetInt32(), and murmurhash32().

Referenced by GetCCHashEqFuncs().

◆ nameeqfast()

static bool nameeqfast ( Datum  a,
Datum  b 
)
static

Definition at line 182 of file catcache.c.

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

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

241 {
243 }
#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 246 of file catcache.c.

247 {
249 }
#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 2153 of file catcache.c.

2157 {
2158  slist_iter iter;
2159  Oid reloid;
2160 
2161  CACHE_elog(DEBUG2, "PrepareToInvalidateCacheTuple: called");
2162 
2163  /*
2164  * sanity checks
2165  */
2166  Assert(RelationIsValid(relation));
2167  Assert(HeapTupleIsValid(tuple));
2168  Assert(PointerIsValid(function));
2169  Assert(CacheHdr != NULL);
2170 
2171  reloid = RelationGetRelid(relation);
2172 
2173  /* ----------------
2174  * for each cache
2175  * if the cache contains tuples from the specified relation
2176  * compute the tuple's hash value(s) in this cache,
2177  * and call the passed function to register the information.
2178  * ----------------
2179  */
2180 
2182  {
2183  CatCache *ccp = slist_container(CatCache, cc_next, iter.cur);
2184  uint32 hashvalue;
2185  Oid dbid;
2186 
2187  if (ccp->cc_reloid != reloid)
2188  continue;
2189 
2190  /* Just in case cache hasn't finished initialization yet... */
2191  if (ccp->cc_tupdesc == NULL)
2193 
2194  hashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, tuple);
2195  dbid = ccp->cc_relisshared ? (Oid) 0 : MyDatabaseId;
2196 
2197  (*function) (ccp->id, hashvalue, dbid);
2198 
2199  if (newtuple)
2200  {
2201  uint32 newhashvalue;
2202 
2203  newhashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, newtuple);
2204 
2205  if (newhashvalue != hashvalue)
2206  (*function) (ccp->id, newhashvalue, dbid);
2207  }
2208  }
2209 }
#define PointerIsValid(pointer)
Definition: c.h:750
static uint32 CatalogCacheComputeTupleHashValue(CatCache *cache, int nkeys, HeapTuple tuple)
Definition: catcache.c:365
Oid MyDatabaseId
Definition: globals.c:91
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define RelationGetRelid(relation)
Definition: rel.h:505
#define RelationIsValid(relation)
Definition: rel.h:478

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

Referenced by CacheInvalidateHeapTuple().

◆ RehashCatCache()

static void RehashCatCache ( CatCache cp)
static

Definition at line 908 of file catcache.c.

909 {
910  dlist_head *newbucket;
911  int newnbuckets;
912  int i;
913 
914  elog(DEBUG1, "rehashing catalog cache id %d for %s; %d tups, %d buckets",
915  cp->id, cp->cc_relname, cp->cc_ntup, cp->cc_nbuckets);
916 
917  /* Allocate a new, larger, hash table. */
918  newnbuckets = cp->cc_nbuckets * 2;
919  newbucket = (dlist_head *) MemoryContextAllocZero(CacheMemoryContext, newnbuckets * sizeof(dlist_head));
920 
921  /* Move all entries from old hash table to new. */
922  for (i = 0; i < cp->cc_nbuckets; i++)
923  {
924  dlist_mutable_iter iter;
925 
926  dlist_foreach_modify(iter, &cp->cc_bucket[i])
927  {
928  CatCTup *ct = dlist_container(CatCTup, cache_elem, iter.cur);
929  int hashIndex = HASH_INDEX(ct->hash_value, newnbuckets);
930 
931  dlist_delete(iter.cur);
932  dlist_push_head(&newbucket[hashIndex], &ct->cache_elem);
933  }
934  }
935 
936  /* Switch to the new array. */
937  pfree(cp->cc_bucket);
938  cp->cc_nbuckets = newnbuckets;
939  cp->cc_bucket = newbucket;
940 }
#define DEBUG1
Definition: elog.h:30
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1202

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

◆ ReleaseCatCache()

void ReleaseCatCache ( HeapTuple  tuple)

Definition at line 1509 of file catcache.c.

1510 {
1512 }
static void ReleaseCatCacheWithOwner(HeapTuple tuple, ResourceOwner resowner)
Definition: catcache.c:1515
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 1895 of file catcache.c.

1896 {
1897  /* Safety checks to ensure we were handed a cache entry */
1898  Assert(list->cl_magic == CL_MAGIC);
1899  Assert(list->refcount > 0);
1900  list->refcount--;
1901  if (resowner)
1903 
1904  if (
1905 #ifndef CATCACHE_FORCE_RELEASE
1906  list->dead &&
1907 #endif
1908  list->refcount == 0)
1909  CatCacheRemoveCList(list->my_cache, list);
1910 }
static void ResourceOwnerForgetCatCacheListRef(ResourceOwner owner, CatCList *list)
Definition: catcache.c:153
#define CL_MAGIC
Definition: catcache.h:160

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

1516 {
1517  CatCTup *ct = (CatCTup *) (((char *) tuple) -
1518  offsetof(CatCTup, tuple));
1519 
1520  /* Safety checks to ensure we were handed a cache entry */
1521  Assert(ct->ct_magic == CT_MAGIC);
1522  Assert(ct->refcount > 0);
1523 
1524  ct->refcount--;
1525  if (resowner)
1527 
1528  if (
1529 #ifndef CATCACHE_FORCE_RELEASE
1530  ct->dead &&
1531 #endif
1532  ct->refcount == 0 &&
1533  (ct->c_list == NULL || ct->c_list->refcount == 0))
1534  CatCacheRemoveCTup(ct->my_cache, ct);
1535 }
static void ResourceOwnerForgetCatCacheRef(ResourceOwner owner, HeapTuple tuple)
Definition: catcache.c:143

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

689 {
690  dlist_mutable_iter iter;
691  int i;
692 
693  /* Remove each list in this cache, or at least mark it dead */
694  dlist_foreach_modify(iter, &cache->cc_lists)
695  {
696  CatCList *cl = dlist_container(CatCList, cache_elem, iter.cur);
697 
698  if (cl->refcount > 0)
699  cl->dead = true;
700  else
701  CatCacheRemoveCList(cache, cl);
702  }
703 
704  /* Remove each tuple in this cache, or at least mark it dead */
705  for (i = 0; i < cache->cc_nbuckets; i++)
706  {
707  dlist_head *bucket = &cache->cc_bucket[i];
708 
709  dlist_foreach_modify(iter, bucket)
710  {
711  CatCTup *ct = dlist_container(CatCTup, cache_elem, iter.cur);
712 
713  if (ct->refcount > 0 ||
714  (ct->c_list && ct->c_list->refcount > 0))
715  {
716  ct->dead = true;
717  /* list, if any, was marked dead above */
718  Assert(ct->c_list == NULL || ct->c_list->dead);
719  }
720  else
721  CatCacheRemoveCTup(cache, ct);
722 #ifdef CATCACHE_STATS
723  cache->cc_invals++;
724 #endif
725  }
726  }
727 }

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

Referenced by CatalogCacheFlushCatalog(), and ResetCatalogCaches().

◆ ResetCatalogCaches()

void ResetCatalogCaches ( void  )

Definition at line 735 of file catcache.c.

736 {
737  slist_iter iter;
738 
739  CACHE_elog(DEBUG2, "ResetCatalogCaches called");
740 
742  {
743  CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
744 
745  ResetCatalogCache(cache);
746  }
747 
748  CACHE_elog(DEBUG2, "end of ResetCatalogCaches call");
749 }

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

154 {
156 }
static const ResourceOwnerDesc catlistref_resowner_desc
Definition: catcache.c:126
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 143 of file catcache.c.

144 {
146 }
static const ResourceOwnerDesc catcache_resowner_desc
Definition: catcache.c:116

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

Referenced by ReleaseCatCacheWithOwner().

◆ ResourceOwnerRememberCatCacheListRef()

static void ResourceOwnerRememberCatCacheListRef ( ResourceOwner  owner,
CatCList list 
)
inlinestatic

Definition at line 148 of file catcache.c.

149 {
151 }
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 2220 of file catcache.c.

2221 {
2223  CatCTup *ct = (CatCTup *) (((char *) tuple) -
2224  offsetof(CatCTup, tuple));
2225 
2226  /* Safety check to ensure we were handed a cache entry */
2227  Assert(ct->ct_magic == CT_MAGIC);
2228 
2229  return psprintf("cache %s (%d), tuple %u/%u has count %d",
2230  ct->my_cache->cc_relname, ct->my_cache->id,
2231  ItemPointerGetBlockNumber(&(tuple->t_self)),
2233  ct->refcount);
2234 }
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 2243 of file catcache.c.

2244 {
2246 
2247  return psprintf("cache %s (%d), list %p has count %d",
2248  list->my_cache->cc_relname, list->my_cache->id,
2249  list, list->refcount);
2250 }

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

◆ ResOwnerReleaseCatCache()

static void ResOwnerReleaseCatCache ( Datum  res)
static

Definition at line 2214 of file catcache.c.

2215 {
2217 }

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

◆ ResOwnerReleaseCatCacheList()

static void ResOwnerReleaseCatCacheList ( Datum  res)
static

Definition at line 2237 of file catcache.c.

2238 {
2240 }

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

◆ SearchCatCache()

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

Definition at line 1197 of file catcache.c.

1202 {
1203  return SearchCatCacheInternal(cache, cache->cc_nkeys, v1, v2, v3, v4);
1204 }
static HeapTuple SearchCatCacheInternal(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1248

References catcache::cc_nkeys, and SearchCatCacheInternal().

Referenced by SearchSysCache().

◆ SearchCatCache1()

HeapTuple SearchCatCache1 ( CatCache cache,
Datum  v1 
)

Definition at line 1214 of file catcache.c.

1216 {
1217  return SearchCatCacheInternal(cache, 1, v1, 0, 0, 0);
1218 }

References SearchCatCacheInternal().

Referenced by SearchSysCache1().

◆ SearchCatCache2()

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

Definition at line 1222 of file catcache.c.

1224 {
1225  return SearchCatCacheInternal(cache, 2, v1, v2, 0, 0);
1226 }

References SearchCatCacheInternal().

Referenced by SearchSysCache2().

◆ SearchCatCache3()

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

Definition at line 1230 of file catcache.c.

1232 {
1233  return SearchCatCacheInternal(cache, 3, v1, v2, v3, 0);
1234 }

References SearchCatCacheInternal().

Referenced by SearchSysCache3().

◆ SearchCatCache4()

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

Definition at line 1238 of file catcache.c.

1240 {
1241  return SearchCatCacheInternal(cache, 4, v1, v2, v3, v4);
1242 }

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

1254 {
1256  uint32 hashValue;
1257  Index hashIndex;
1258  dlist_iter iter;
1259  dlist_head *bucket;
1260  CatCTup *ct;
1261 
1262  /* Make sure we're in an xact, even if this ends up being a cache hit */
1264 
1265  Assert(cache->cc_nkeys == nkeys);
1266 
1267  /*
1268  * one-time startup overhead for each cache
1269  */
1270  if (unlikely(cache->cc_tupdesc == NULL))
1272 
1273 #ifdef CATCACHE_STATS
1274  cache->cc_searches++;
1275 #endif
1276 
1277  /* Initialize local parameter array */
1278  arguments[0] = v1;
1279  arguments[1] = v2;
1280  arguments[2] = v3;
1281  arguments[3] = v4;
1282 
1283  /*
1284  * find the hash bucket in which to look for the tuple
1285  */
1286  hashValue = CatalogCacheComputeHashValue(cache, nkeys, v1, v2, v3, v4);
1287  hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
1288 
1289  /*
1290  * scan the hash bucket until we find a match or exhaust our tuples
1291  *
1292  * Note: it's okay to use dlist_foreach here, even though we modify the
1293  * dlist within the loop, because we don't continue the loop afterwards.
1294  */
1295  bucket = &cache->cc_bucket[hashIndex];
1296  dlist_foreach(iter, bucket)
1297  {
1298  ct = dlist_container(CatCTup, cache_elem, iter.cur);
1299 
1300  if (ct->dead)
1301  continue; /* ignore dead entries */
1302 
1303  if (ct->hash_value != hashValue)
1304  continue; /* quickly skip entry if wrong hash val */
1305 
1306  if (!CatalogCacheCompareTuple(cache, nkeys, ct->keys, arguments))
1307  continue;
1308 
1309  /*
1310  * We found a match in the cache. Move it to the front of the list
1311  * for its hashbucket, in order to speed subsequent searches. (The
1312  * most frequently accessed elements in any hashbucket will tend to be
1313  * near the front of the hashbucket's list.)
1314  */
1315  dlist_move_head(bucket, &ct->cache_elem);
1316 
1317  /*
1318  * If it's a positive entry, bump its refcount and return it. If it's
1319  * negative, we can report failure to the caller.
1320  */
1321  if (!ct->negative)
1322  {
1324  ct->refcount++;
1326 
1327  CACHE_elog(DEBUG2, "SearchCatCache(%s): found in bucket %d",
1328  cache->cc_relname, hashIndex);
1329 
1330 #ifdef CATCACHE_STATS
1331  cache->cc_hits++;
1332 #endif
1333 
1334  return &ct->tuple;
1335  }
1336  else
1337  {
1338  CACHE_elog(DEBUG2, "SearchCatCache(%s): found neg entry in bucket %d",
1339  cache->cc_relname, hashIndex);
1340 
1341 #ifdef CATCACHE_STATS
1342  cache->cc_neg_hits++;
1343 #endif
1344 
1345  return NULL;
1346  }
1347  }
1348 
1349  return SearchCatCacheMiss(cache, nkeys, hashValue, hashIndex, v1, v2, v3, v4);
1350 }
#define unlikely(x)
Definition: c.h:298
static pg_noinline HeapTuple SearchCatCacheMiss(CatCache *cache, int nkeys, uint32 hashValue, Index hashIndex, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1360
static void ResourceOwnerRememberCatCacheRef(ResourceOwner owner, HeapTuple tuple)
Definition: catcache.c:138
static bool CatalogCacheCompareTuple(const CatCache *cache, int nkeys, const Datum *cachekeys, const Datum *searchkeys)
Definition: catcache.c:420
#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:379

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

1587 {
1588  Datum v4 = 0; /* dummy last-column value */
1590  uint32 lHashValue;
1591  dlist_iter iter;
1592  CatCList *cl;
1593  CatCTup *ct;
1594  List *volatile ctlist;
1595  ListCell *ctlist_item;
1596  int nmembers;
1597  bool ordered;
1598  HeapTuple ntp;
1599  MemoryContext oldcxt;
1600  int i;
1601 
1602  /*
1603  * one-time startup overhead for each cache
1604  */
1605  if (cache->cc_tupdesc == NULL)
1607 
1608  Assert(nkeys > 0 && nkeys < cache->cc_nkeys);
1609 
1610 #ifdef CATCACHE_STATS
1611  cache->cc_lsearches++;
1612 #endif
1613 
1614  /* Initialize local parameter array */
1615  arguments[0] = v1;
1616  arguments[1] = v2;
1617  arguments[2] = v3;
1618  arguments[3] = v4;
1619 
1620  /*
1621  * compute a hash value of the given keys for faster search. We don't
1622  * presently divide the CatCList items into buckets, but this still lets
1623  * us skip non-matching items quickly most of the time.
1624  */
1625  lHashValue = CatalogCacheComputeHashValue(cache, nkeys, v1, v2, v3, v4);
1626 
1627  /*
1628  * scan the items until we find a match or exhaust our list
1629  *
1630  * Note: it's okay to use dlist_foreach here, even though we modify the
1631  * dlist within the loop, because we don't continue the loop afterwards.
1632  */
1633  dlist_foreach(iter, &cache->cc_lists)
1634  {
1635  cl = dlist_container(CatCList, cache_elem, iter.cur);
1636 
1637  if (cl->dead)
1638  continue; /* ignore dead entries */
1639 
1640  if (cl->hash_value != lHashValue)
1641  continue; /* quickly skip entry if wrong hash val */
1642 
1643  /*
1644  * see if the cached list matches our key.
1645  */
1646  if (cl->nkeys != nkeys)
1647  continue;
1648 
1649  if (!CatalogCacheCompareTuple(cache, nkeys, cl->keys, arguments))
1650  continue;
1651 
1652  /*
1653  * We found a matching list. Move the list to the front of the
1654  * cache's list-of-lists, to speed subsequent searches. (We do not
1655  * move the members to the fronts of their hashbucket lists, however,
1656  * since there's no point in that unless they are searched for
1657  * individually.)
1658  */
1659  dlist_move_head(&cache->cc_lists, &cl->cache_elem);
1660 
1661  /* Bump the list's refcount and return it */
1663  cl->refcount++;
1665 
1666  CACHE_elog(DEBUG2, "SearchCatCacheList(%s): found list",
1667  cache->cc_relname);
1668 
1669 #ifdef CATCACHE_STATS
1670  cache->cc_lhits++;
1671 #endif
1672 
1673  return cl;
1674  }
1675 
1676  /*
1677  * List was not found in cache, so we have to build it by reading the
1678  * relation. For each matching tuple found in the relation, use an
1679  * existing cache entry if possible, else build a new one.
1680  *
1681  * We have to bump the member refcounts temporarily to ensure they won't
1682  * get dropped from the cache while loading other members. We use a PG_TRY
1683  * block to ensure we can undo those refcounts if we get an error before
1684  * we finish constructing the CatCList. ctlist must be valid throughout
1685  * the PG_TRY block.
1686  */
1687  ctlist = NIL;
1688 
1689  PG_TRY();
1690  {
1691  ScanKeyData cur_skey[CATCACHE_MAXKEYS];
1692  Relation relation;
1693  SysScanDesc scandesc;
1694  bool stale;
1695 
1696  relation = table_open(cache->cc_reloid, AccessShareLock);
1697 
1698  do
1699  {
1700  /*
1701  * Ok, need to make a lookup in the relation, copy the scankey and
1702  * fill out any per-call fields. (We must re-do this when
1703  * retrying, because systable_beginscan scribbles on the scankey.)
1704  */
1705  memcpy(cur_skey, cache->cc_skey, sizeof(ScanKeyData) * cache->cc_nkeys);
1706  cur_skey[0].sk_argument = v1;
1707  cur_skey[1].sk_argument = v2;
1708  cur_skey[2].sk_argument = v3;
1709  cur_skey[3].sk_argument = v4;
1710 
1711  scandesc = systable_beginscan(relation,
1712  cache->cc_indexoid,
1713  IndexScanOK(cache, cur_skey),
1714  NULL,
1715  nkeys,
1716  cur_skey);
1717 
1718  /* The list will be ordered iff we are doing an index scan */
1719  ordered = (scandesc->irel != NULL);
1720 
1721  stale = false;
1722 
1723  while (HeapTupleIsValid(ntp = systable_getnext(scandesc)))
1724  {
1725  uint32 hashValue;
1726  Index hashIndex;
1727  bool found = false;
1728  dlist_head *bucket;
1729 
1730  /*
1731  * See if there's an entry for this tuple already.
1732  */
1733  ct = NULL;
1734  hashValue = CatalogCacheComputeTupleHashValue(cache, cache->cc_nkeys, ntp);
1735  hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
1736 
1737  bucket = &cache->cc_bucket[hashIndex];
1738  dlist_foreach(iter, bucket)
1739  {
1740  ct = dlist_container(CatCTup, cache_elem, iter.cur);
1741 
1742  if (ct->dead || ct->negative)
1743  continue; /* ignore dead and negative entries */
1744 
1745  if (ct->hash_value != hashValue)
1746  continue; /* quickly skip entry if wrong hash val */
1747 
1748  if (!ItemPointerEquals(&(ct->tuple.t_self), &(ntp->t_self)))
1749  continue; /* not same tuple */
1750 
1751  /*
1752  * Found a match, but can't use it if it belongs to
1753  * another list already
1754  */
1755  if (ct->c_list)
1756  continue;
1757 
1758  found = true;
1759  break; /* A-OK */
1760  }
1761 
1762  if (!found)
1763  {
1764  /* We didn't find a usable entry, so make a new one */
1765  ct = CatalogCacheCreateEntry(cache, ntp, scandesc, NULL,
1766  hashValue, hashIndex);
1767  /* upon failure, we must start the scan over */
1768  if (ct == NULL)
1769  {
1770  /*
1771  * Release refcounts on any items we already had. We
1772  * dare not try to free them if they're now
1773  * unreferenced, since an error while doing that would
1774  * result in the PG_CATCH below doing extra refcount
1775  * decrements. Besides, we'll likely re-adopt those
1776  * items in the next iteration, so it's not worth
1777  * complicating matters to try to get rid of them.
1778  */
1779  foreach(ctlist_item, ctlist)
1780  {
1781  ct = (CatCTup *) lfirst(ctlist_item);
1782  Assert(ct->c_list == NULL);
1783  Assert(ct->refcount > 0);
1784  ct->refcount--;
1785  }
1786  /* Reset ctlist in preparation for new try */
1787  ctlist = NIL;
1788  stale = true;
1789  break;
1790  }
1791  }
1792 
1793  /* Careful here: add entry to ctlist, then bump its refcount */
1794  /* This way leaves state correct if lappend runs out of memory */
1795  ctlist = lappend(ctlist, ct);
1796  ct->refcount++;
1797  }
1798 
1799  systable_endscan(scandesc);
1800  } while (stale);
1801 
1802  table_close(relation, AccessShareLock);
1803 
1804  /* Make sure the resource owner has room to remember this entry. */
1806 
1807  /* Now we can build the CatCList entry. */
1809  nmembers = list_length(ctlist);
1810  cl = (CatCList *)
1811  palloc(offsetof(CatCList, members) + nmembers * sizeof(CatCTup *));
1812 
1813  /* Extract key values */
1814  CatCacheCopyKeys(cache->cc_tupdesc, nkeys, cache->cc_keyno,
1815  arguments, cl->keys);
1816  MemoryContextSwitchTo(oldcxt);
1817 
1818  /*
1819  * We are now past the last thing that could trigger an elog before we
1820  * have finished building the CatCList and remembering it in the
1821  * resource owner. So it's OK to fall out of the PG_TRY, and indeed
1822  * we'd better do so before we start marking the members as belonging
1823  * to the list.
1824  */
1825  }
1826  PG_CATCH();
1827  {
1828  foreach(ctlist_item, ctlist)
1829  {
1830  ct = (CatCTup *) lfirst(ctlist_item);
1831  Assert(ct->c_list == NULL);
1832  Assert(ct->refcount > 0);
1833  ct->refcount--;
1834  if (
1835 #ifndef CATCACHE_FORCE_RELEASE
1836  ct->dead &&
1837 #endif
1838  ct->refcount == 0 &&
1839  (ct->c_list == NULL || ct->c_list->refcount == 0))
1840  CatCacheRemoveCTup(cache, ct);
1841  }
1842 
1843  PG_RE_THROW();
1844  }
1845  PG_END_TRY();
1846 
1847  cl->cl_magic = CL_MAGIC;
1848  cl->my_cache = cache;
1849  cl->refcount = 0; /* for the moment */
1850  cl->dead = false;
1851  cl->ordered = ordered;
1852  cl->nkeys = nkeys;
1853  cl->hash_value = lHashValue;
1854  cl->n_members = nmembers;
1855 
1856  i = 0;
1857  foreach(ctlist_item, ctlist)
1858  {
1859  cl->members[i++] = ct = (CatCTup *) lfirst(ctlist_item);
1860  Assert(ct->c_list == NULL);
1861  ct->c_list = cl;
1862  /* release the temporary refcount on the member */
1863  Assert(ct->refcount > 0);
1864  ct->refcount--;
1865  /* mark list dead if any members already dead */
1866  if (ct->dead)
1867  cl->dead = true;
1868  }
1869  Assert(i == nmembers);
1870 
1871  dlist_push_head(&cache->cc_lists, &cl->cache_elem);
1872 
1873  /* Finally, bump the list's refcount and return it */
1874  cl->refcount++;
1876 
1877  CACHE_elog(DEBUG2, "SearchCatCacheList(%s): made list of %d members",
1878  cache->cc_relname, nmembers);
1879 
1880  return cl;
1881 }
static CatCTup * CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp, SysScanDesc scandesc, Datum *arguments, uint32 hashValue, Index hashIndex)
Definition: catcache.c:1929
static void ResourceOwnerRememberCatCacheListRef(ResourceOwner owner, CatCList *list)
Definition: catcache.c:148
static bool IndexScanOK(CatCache *cache, ScanKey cur_skey)
Definition: catcache.c:1132
#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:159
bool ordered
Definition: catcache.h:174
uint32 hash_value
Definition: catcache.h:162

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_lists, catcache::cc_nbuckets, catcache::cc_nkeys, catcache::cc_relname, catcache::cc_reloid, catcache::cc_skey, catcache::cc_tupdesc, catclist::cl_magic, CL_MAGIC, dlist_iter::cur, CurrentResourceOwner, catctup::dead, catclist::dead, DEBUG2, dlist_container, dlist_foreach, dlist_move_head(), dlist_push_head(), HASH_INDEX, catctup::hash_value, catclist::hash_value, HeapTupleIsValid, i, IndexScanOK(), SysScanDescData::irel, ItemPointerEquals(), catclist::keys, lappend(), lfirst, list_length(), catclist::members, MemoryContextSwitchTo(), catclist::my_cache, catclist::n_members, catctup::negative, NIL, catclist::nkeys, catclist::ordered, palloc(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, catctup::refcount, catclist::refcount, ResourceOwnerEnlarge(), ResourceOwnerRememberCatCacheListRef(), ScanKeyData::sk_argument, systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), table_open(), and catctup::tuple.

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

1368 {
1369  ScanKeyData cur_skey[CATCACHE_MAXKEYS];
1370  Relation relation;
1371  SysScanDesc scandesc;
1372  HeapTuple ntp;
1373  CatCTup *ct;
1374  bool stale;
1376 
1377  /* Initialize local parameter array */
1378  arguments[0] = v1;
1379  arguments[1] = v2;
1380  arguments[2] = v3;
1381  arguments[3] = v4;
1382 
1383  /*
1384  * Tuple was not found in cache, so we have to try to retrieve it directly
1385  * from the relation. If found, we will add it to the cache; if not
1386  * found, we will add a negative cache entry instead.
1387  *
1388  * NOTE: it is possible for recursive cache lookups to occur while reading
1389  * the relation --- for example, due to shared-cache-inval messages being
1390  * processed during table_open(). This is OK. It's even possible for one
1391  * of those lookups to find and enter the very same tuple we are trying to
1392  * fetch here. If that happens, we will enter a second copy of the tuple
1393  * into the cache. The first copy will never be referenced again, and
1394  * will eventually age out of the cache, so there's no functional problem.
1395  * This case is rare enough that it's not worth expending extra cycles to
1396  * detect.
1397  *
1398  * Another case, which we *must* handle, is that the tuple could become
1399  * outdated during CatalogCacheCreateEntry's attempt to detoast it (since
1400  * AcceptInvalidationMessages can run during TOAST table access). We do
1401  * not want to return already-stale catcache entries, so we loop around
1402  * and do the table scan again if that happens.
1403  */
1404  relation = table_open(cache->cc_reloid, AccessShareLock);
1405 
1406  do
1407  {
1408  /*
1409  * Ok, need to make a lookup in the relation, copy the scankey and
1410  * fill out any per-call fields. (We must re-do this when retrying,
1411  * because systable_beginscan scribbles on the scankey.)
1412  */
1413  memcpy(cur_skey, cache->cc_skey, sizeof(ScanKeyData) * nkeys);
1414  cur_skey[0].sk_argument = v1;
1415  cur_skey[1].sk_argument = v2;
1416  cur_skey[2].sk_argument = v3;
1417  cur_skey[3].sk_argument = v4;
1418 
1419  scandesc = systable_beginscan(relation,
1420  cache->cc_indexoid,
1421  IndexScanOK(cache, cur_skey),
1422  NULL,
1423  nkeys,
1424  cur_skey);
1425 
1426  ct = NULL;
1427  stale = false;
1428 
1429  while (HeapTupleIsValid(ntp = systable_getnext(scandesc)))
1430  {
1431  ct = CatalogCacheCreateEntry(cache, ntp, scandesc, NULL,
1432  hashValue, hashIndex);
1433  /* upon failure, we must start the scan over */
1434  if (ct == NULL)
1435  {
1436  stale = true;
1437  break;
1438  }
1439  /* immediately set the refcount to 1 */
1441  ct->refcount++;
1443  break; /* assume only one match */
1444  }
1445 
1446  systable_endscan(scandesc);
1447  } while (stale);
1448 
1449  table_close(relation, AccessShareLock);
1450 
1451  /*
1452  * If tuple was not found, we need to build a negative cache entry
1453  * containing a fake tuple. The fake tuple has the correct key columns,
1454  * but nulls everywhere else.
1455  *
1456  * In bootstrap mode, we don't build negative entries, because the cache
1457  * invalidation mechanism isn't alive and can't clear them if the tuple
1458  * gets created later. (Bootstrap doesn't do UPDATEs, so it doesn't need
1459  * cache inval for that.)
1460  */
1461  if (ct == NULL)
1462  {
1464  return NULL;
1465 
1466  ct = CatalogCacheCreateEntry(cache, NULL, NULL, arguments,
1467  hashValue, hashIndex);
1468 
1469  /* Creating a negative cache entry shouldn't fail */
1470  Assert(ct != NULL);
1471 
1472  CACHE_elog(DEBUG2, "SearchCatCache(%s): Contains %d/%d tuples",
1473  cache->cc_relname, cache->cc_ntup, CacheHdr->ch_ntup);
1474  CACHE_elog(DEBUG2, "SearchCatCache(%s): put neg entry in bucket %d",
1475  cache->cc_relname, hashIndex);
1476 
1477  /*
1478  * We are not returning the negative entry to the caller, so leave its
1479  * refcount zero.
1480  */
1481 
1482  return NULL;
1483  }
1484 
1485  CACHE_elog(DEBUG2, "SearchCatCache(%s): Contains %d/%d tuples",
1486  cache->cc_relname, cache->cc_ntup, CacheHdr->ch_ntup);
1487  CACHE_elog(DEBUG2, "SearchCatCache(%s): put in bucket %d",
1488  cache->cc_relname, hashIndex);
1489 
1490 #ifdef CATCACHE_STATS
1491  cache->cc_newloads++;
1492 #endif
1493 
1494  return &ct->tuple;
1495 }
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:451

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

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

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

Referenced by GetCCHashEqFuncs().

◆ texthashfast()

static uint32 texthashfast ( Datum  datum)
static

Definition at line 233 of file catcache.c.

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

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

Definition at line 126 of file catcache.c.

Referenced by ResourceOwnerForgetCatCacheListRef(), and ResourceOwnerRememberCatCacheListRef().