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/sysattr.h"
#include "access/table.h"
#include "access/valid.h"
#include "access/xact.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_type.h"
#include "common/hashfn.h"
#include "miscadmin.h"
#include "port/pg_bitutils.h"
#include "storage/lmgr.h"
#include "utils/builtins.h"
#include "utils/datum.h"
#include "utils/fmgroids.h"
#include "utils/inval.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "utils/resowner_private.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, Datum *arguments, uint32 hashValue, Index hashIndex, bool negative)
 
static void CatCacheFreeKeys (TupleDesc tupdesc, int nkeys, int *attnos, Datum *keys)
 
static void CatCacheCopyKeys (TupleDesc tupdesc, int nkeys, int *attnos, Datum *srckeys, Datum *dstkeys)
 
static bool chareqfast (Datum a, Datum b)
 
static uint32 charhashfast (Datum datum)
 
static bool nameeqfast (Datum a, Datum b)
 
static uint32 namehashfast (Datum datum)
 
static bool int2eqfast (Datum a, Datum b)
 
static uint32 int2hashfast (Datum datum)
 
static bool int4eqfast (Datum a, Datum b)
 
static uint32 int4hashfast (Datum datum)
 
static bool texteqfast (Datum a, Datum b)
 
static uint32 texthashfast (Datum datum)
 
static bool oidvectoreqfast (Datum a, Datum b)
 
static uint32 oidvectorhashfast (Datum datum)
 
static void GetCCHashEqFuncs (Oid keytype, CCHashFN *hashfunc, RegProcedure *eqfunc, CCFastEqualFN *fasteqfunc)
 
void CatCacheInvalidate (CatCache *cache, uint32 hashValue)
 
void CreateCacheMemoryContext (void)
 
static void ResetCatalogCache (CatCache *cache)
 
void ResetCatalogCaches (void)
 
void CatalogCacheFlushCatalog (Oid catId)
 
CatCacheInitCatCache (int id, Oid reloid, Oid indexoid, int nkeys, const int *key, int nbuckets)
 
static void RehashCatCache (CatCache *cp)
 
void InitCatCachePhase2 (CatCache *cache, bool touch_index)
 
static bool IndexScanOK (CatCache *cache, ScanKey cur_skey)
 
HeapTuple SearchCatCache (CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
 
HeapTuple SearchCatCache1 (CatCache *cache, Datum v1)
 
HeapTuple SearchCatCache2 (CatCache *cache, Datum v1, Datum v2)
 
HeapTuple SearchCatCache3 (CatCache *cache, Datum v1, Datum v2, Datum v3)
 
HeapTuple SearchCatCache4 (CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
 
void ReleaseCatCache (HeapTuple tuple)
 
uint32 GetCatCacheHashValue (CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
 
CatCListSearchCatCacheList (CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3)
 
void ReleaseCatCacheList (CatCList *list)
 
void PrepareToInvalidateCacheTuple (Relation relation, HeapTuple tuple, HeapTuple newtuple, void(*function)(int, uint32, Oid))
 
void PrintCatCacheLeakWarning (HeapTuple tuple)
 
void PrintCatCacheListLeakWarning (CatCList *list)
 

Variables

static CatCacheHeaderCacheHdr = NULL
 

Macro Definition Documentation

◆ CACHE_elog

#define CACHE_elog (   ...)

Definition at line 61 of file catcache.c.

◆ CatalogCacheInitializeCache_DEBUG1

#define CatalogCacheInitializeCache_DEBUG1

Definition at line 912 of file catcache.c.

◆ CatalogCacheInitializeCache_DEBUG2

#define CatalogCacheInitializeCache_DEBUG2

Definition at line 913 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 753 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 368 of file catcache.c.

371 {
372  const CCFastEqualFN *cc_fastequal = cache->cc_fastequal;
373  int i;
374 
375  for (i = 0; i < nkeys; i++)
376  {
377  if (!(cc_fastequal[i]) (cachekeys[i], searchkeys[i]))
378  return false;
379  }
380  return true;
381 }
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 271 of file catcache.c.

273 {
274  uint32 hashValue = 0;
275  uint32 oneHash;
276  CCHashFN *cc_hashfunc = cache->cc_hashfunc;
277 
278  CACHE_elog(DEBUG2, "CatalogCacheComputeHashValue %s %d %p",
279  cache->cc_relname, nkeys, cache);
280 
281  switch (nkeys)
282  {
283  case 4:
284  oneHash = (cc_hashfunc[3]) (v4);
285  hashValue ^= pg_rotate_left32(oneHash, 24);
286  /* FALLTHROUGH */
287  case 3:
288  oneHash = (cc_hashfunc[2]) (v3);
289  hashValue ^= pg_rotate_left32(oneHash, 16);
290  /* FALLTHROUGH */
291  case 2:
292  oneHash = (cc_hashfunc[1]) (v2);
293  hashValue ^= pg_rotate_left32(oneHash, 8);
294  /* FALLTHROUGH */
295  case 1:
296  oneHash = (cc_hashfunc[0]) (v1);
297  hashValue ^= oneHash;
298  break;
299  default:
300  elog(FATAL, "wrong number of hash keys: %d", nkeys);
301  break;
302  }
303 
304  return hashValue;
305 }
unsigned int uint32
Definition: c.h:441
#define CACHE_elog(...)
Definition: catcache.c:61
uint32(* CCHashFN)(Datum datum)
Definition: catcache.h:39
#define FATAL
Definition: elog.h:35
#define DEBUG2
Definition: elog.h:23
#define elog(elevel,...)
Definition: elog.h:218
static uint32 pg_rotate_left32(uint32 word, int n)
Definition: pg_bitutils.h:297
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 313 of file catcache.c.

314 {
315  Datum v1 = 0,
316  v2 = 0,
317  v3 = 0,
318  v4 = 0;
319  bool isNull = false;
320  int *cc_keyno = cache->cc_keyno;
321  TupleDesc cc_tupdesc = cache->cc_tupdesc;
322 
323  /* Now extract key fields from tuple, insert into scankey */
324  switch (nkeys)
325  {
326  case 4:
327  v4 = fastgetattr(tuple,
328  cc_keyno[3],
329  cc_tupdesc,
330  &isNull);
331  Assert(!isNull);
332  /* FALLTHROUGH */
333  case 3:
334  v3 = fastgetattr(tuple,
335  cc_keyno[2],
336  cc_tupdesc,
337  &isNull);
338  Assert(!isNull);
339  /* FALLTHROUGH */
340  case 2:
341  v2 = fastgetattr(tuple,
342  cc_keyno[1],
343  cc_tupdesc,
344  &isNull);
345  Assert(!isNull);
346  /* FALLTHROUGH */
347  case 1:
348  v1 = fastgetattr(tuple,
349  cc_keyno[0],
350  cc_tupdesc,
351  &isNull);
352  Assert(!isNull);
353  break;
354  default:
355  elog(FATAL, "wrong number of hash keys: %d", nkeys);
356  break;
357  }
358 
359  return CatalogCacheComputeHashValue(cache, nkeys, v1, v2, v3, v4);
360 }
static uint32 CatalogCacheComputeHashValue(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:271
static Datum fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:745
Assert(fmt[strlen(fmt) - 1] !='\n')
uintptr_t Datum
Definition: postgres.h:411
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,
Datum arguments,
uint32  hashValue,
Index  hashIndex,
bool  negative 
)
static

Definition at line 1800 of file catcache.c.

1803 {
1804  CatCTup *ct;
1805  HeapTuple dtp;
1806  MemoryContext oldcxt;
1807 
1808  /* negative entries have no tuple associated */
1809  if (ntp)
1810  {
1811  int i;
1812 
1813  Assert(!negative);
1814 
1815  /*
1816  * If there are any out-of-line toasted fields in the tuple, expand
1817  * them in-line. This saves cycles during later use of the catcache
1818  * entry, and also protects us against the possibility of the toast
1819  * tuples being freed before we attempt to fetch them, in case of
1820  * something using a slightly stale catcache entry.
1821  */
1822  if (HeapTupleHasExternal(ntp))
1823  dtp = toast_flatten_tuple(ntp, cache->cc_tupdesc);
1824  else
1825  dtp = ntp;
1826 
1827  /* Allocate memory for CatCTup and the cached tuple in one go */
1829 
1830  ct = (CatCTup *) palloc(sizeof(CatCTup) +
1831  MAXIMUM_ALIGNOF + dtp->t_len);
1832  ct->tuple.t_len = dtp->t_len;
1833  ct->tuple.t_self = dtp->t_self;
1834  ct->tuple.t_tableOid = dtp->t_tableOid;
1835  ct->tuple.t_data = (HeapTupleHeader)
1836  MAXALIGN(((char *) ct) + sizeof(CatCTup));
1837  /* copy tuple contents */
1838  memcpy((char *) ct->tuple.t_data,
1839  (const char *) dtp->t_data,
1840  dtp->t_len);
1841  MemoryContextSwitchTo(oldcxt);
1842 
1843  if (dtp != ntp)
1844  heap_freetuple(dtp);
1845 
1846  /* extract keys - they'll point into the tuple if not by-value */
1847  for (i = 0; i < cache->cc_nkeys; i++)
1848  {
1849  Datum atp;
1850  bool isnull;
1851 
1852  atp = heap_getattr(&ct->tuple,
1853  cache->cc_keyno[i],
1854  cache->cc_tupdesc,
1855  &isnull);
1856  Assert(!isnull);
1857  ct->keys[i] = atp;
1858  }
1859  }
1860  else
1861  {
1862  Assert(negative);
1864  ct = (CatCTup *) palloc(sizeof(CatCTup));
1865 
1866  /*
1867  * Store keys - they'll point into separately allocated memory if not
1868  * by-value.
1869  */
1870  CatCacheCopyKeys(cache->cc_tupdesc, cache->cc_nkeys, cache->cc_keyno,
1871  arguments, ct->keys);
1872  MemoryContextSwitchTo(oldcxt);
1873  }
1874 
1875  /*
1876  * Finish initializing the CatCTup header, and add it to the cache's
1877  * linked list and counts.
1878  */
1879  ct->ct_magic = CT_MAGIC;
1880  ct->my_cache = cache;
1881  ct->c_list = NULL;
1882  ct->refcount = 0; /* for the moment */
1883  ct->dead = false;
1884  ct->negative = negative;
1885  ct->hash_value = hashValue;
1886 
1887  dlist_push_head(&cache->cc_bucket[hashIndex], &ct->cache_elem);
1888 
1889  cache->cc_ntup++;
1890  CacheHdr->ch_ntup++;
1891 
1892  /*
1893  * If the hash table has become too full, enlarge the buckets array. Quite
1894  * arbitrarily, we enlarge when fill factor > 2.
1895  */
1896  if (cache->cc_ntup > cache->cc_nbuckets * 2)
1897  RehashCatCache(cache);
1898 
1899  return ct;
1900 }
#define MAXALIGN(LEN)
Definition: c.h:757
static void RehashCatCache(CatCache *cp)
Definition: catcache.c:854
static void CatCacheCopyKeys(TupleDesc tupdesc, int nkeys, int *attnos, Datum *srckeys, Datum *dstkeys)
Definition: catcache.c:1931
static CatCacheHeader * CacheHdr
Definition: catcache.c:65
#define CT_MAGIC
Definition: catcache.h:89
HeapTuple toast_flatten_tuple(HeapTuple tup, TupleDesc tupleDesc)
Definition: heaptoast.c:350
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:788
#define HeapTupleHasExternal(tuple)
Definition: htup_details.h:667
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:300
MemoryContext CacheMemoryContext
Definition: mcxt.c:51
void * palloc(Size size)
Definition: mcxt.c:1068
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
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(), catctup::refcount, RehashCatCache(), HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, toast_flatten_tuple(), and catctup::tuple.

Referenced by SearchCatCacheList(), and SearchCatCacheMiss().

◆ CatalogCacheFlushCatalog()

void CatalogCacheFlushCatalog ( Oid  catId)

Definition at line 713 of file catcache.c.

714 {
715  slist_iter iter;
716 
717  CACHE_elog(DEBUG2, "CatalogCacheFlushCatalog called for %u", catId);
718 
720  {
721  CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
722 
723  /* Does this cache store tuples of the target catalog? */
724  if (cache->cc_reloid == catId)
725  {
726  /* Yes, so flush all its contents */
727  ResetCatalogCache(cache);
728 
729  /* Tell inval.c to call syscache callbacks for this cache */
730  CallSyscacheCallbacks(cache->id, 0);
731  }
732  }
733 
734  CACHE_elog(DEBUG2, "end of CatalogCacheFlushCatalog call");
735 }
static void ResetCatalogCache(CatCache *cache)
Definition: catcache.c:636
#define slist_container(type, membername, ptr)
Definition: ilist.h:693
#define slist_foreach(iter, lhead)
Definition: ilist.h:719
void CallSyscacheCallbacks(int cacheid, uint32 hashvalue)
Definition: inval.c:1580
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:226

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

918 {
919  Relation relation;
920  MemoryContext oldcxt;
921  TupleDesc tupdesc;
922  int i;
923 
925 
926  relation = table_open(cache->cc_reloid, AccessShareLock);
927 
928  /*
929  * switch to the cache context so our allocations do not vanish at the end
930  * of a transaction
931  */
932  Assert(CacheMemoryContext != NULL);
933 
935 
936  /*
937  * copy the relcache's tuple descriptor to permanent cache storage
938  */
939  tupdesc = CreateTupleDescCopyConstr(RelationGetDescr(relation));
940 
941  /*
942  * save the relation's name and relisshared flag, too (cc_relname is used
943  * only for debugging purposes)
944  */
945  cache->cc_relname = pstrdup(RelationGetRelationName(relation));
946  cache->cc_relisshared = RelationGetForm(relation)->relisshared;
947 
948  /*
949  * return to the caller's memory context and close the rel
950  */
951  MemoryContextSwitchTo(oldcxt);
952 
953  table_close(relation, AccessShareLock);
954 
955  CACHE_elog(DEBUG2, "CatalogCacheInitializeCache: %s, %d keys",
956  cache->cc_relname, cache->cc_nkeys);
957 
958  /*
959  * initialize cache's key information
960  */
961  for (i = 0; i < cache->cc_nkeys; ++i)
962  {
963  Oid keytype;
964  RegProcedure eqfunc;
965 
967 
968  if (cache->cc_keyno[i] > 0)
969  {
970  Form_pg_attribute attr = TupleDescAttr(tupdesc,
971  cache->cc_keyno[i] - 1);
972 
973  keytype = attr->atttypid;
974  /* cache key columns should always be NOT NULL */
975  Assert(attr->attnotnull);
976  }
977  else
978  {
979  if (cache->cc_keyno[i] < 0)
980  elog(FATAL, "sys attributes are not supported in caches");
981  keytype = OIDOID;
982  }
983 
984  GetCCHashEqFuncs(keytype,
985  &cache->cc_hashfunc[i],
986  &eqfunc,
987  &cache->cc_fastequal[i]);
988 
989  /*
990  * Do equality-function lookup (we assume this won't need a catalog
991  * lookup for any supported type)
992  */
993  fmgr_info_cxt(eqfunc,
994  &cache->cc_skey[i].sk_func,
996 
997  /* Initialize sk_attno suitably for HeapKeyTest() and heap scans */
998  cache->cc_skey[i].sk_attno = cache->cc_keyno[i];
999 
1000  /* Fill in sk_strategy as well --- always standard equality */
1002  cache->cc_skey[i].sk_subtype = InvalidOid;
1003  /* If a catcache key requires a collation, it must be C collation */
1004  cache->cc_skey[i].sk_collation = C_COLLATION_OID;
1005 
1006  CACHE_elog(DEBUG2, "CatalogCacheInitializeCache %s %d %p",
1007  cache->cc_relname, i, cache);
1008  }
1009 
1010  /*
1011  * mark this cache fully initialized
1012  */
1013  cache->cc_tupdesc = tupdesc;
1014 }
regproc RegProcedure
Definition: c.h:585
#define CatalogCacheInitializeCache_DEBUG1
Definition: catcache.c:912
static void GetCCHashEqFuncs(Oid keytype, CCHashFN *hashfunc, RegProcedure *eqfunc, CCFastEqualFN *fasteqfunc)
Definition: catcache.c:202
#define CatalogCacheInitializeCache_DEBUG2
Definition: catcache.c:913
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:136
#define AccessShareLock
Definition: lockdefs.h:36
char * pstrdup(const char *in)
Definition: mcxt.c:1305
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
#define RelationGetForm(relation)
Definition: rel.h:482
#define RelationGetDescr(relation)
Definition: rel.h:514
#define RelationGetRelationName(relation)
Definition: rel.h:522
#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:167
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc)
Definition: tupdesc.c:151
#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 1931 of file catcache.c.

1933 {
1934  int i;
1935 
1936  /*
1937  * XXX: memory and lookup performance could possibly be improved by
1938  * storing all keys in one allocation.
1939  */
1940 
1941  for (i = 0; i < nkeys; i++)
1942  {
1943  int attnum = attnos[i];
1944  Form_pg_attribute att = TupleDescAttr(tupdesc, attnum - 1);
1945  Datum src = srckeys[i];
1946  NameData srcname;
1947 
1948  /*
1949  * Must be careful in case the caller passed a C string where a NAME
1950  * is wanted: convert the given argument to a correctly padded NAME.
1951  * Otherwise the memcpy() done by datumCopy() could fall off the end
1952  * of memory.
1953  */
1954  if (att->atttypid == NAMEOID)
1955  {
1956  namestrcpy(&srcname, DatumGetCString(src));
1957  src = NameGetDatum(&srcname);
1958  }
1959 
1960  dstkeys[i] = datumCopy(src,
1961  att->attbyval,
1962  att->attlen);
1963  }
1964 }
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:83
#define NameGetDatum(X)
Definition: postgres.h:639
#define DatumGetCString(X)
Definition: postgres.h:610
Definition: c.h:676

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

1907 {
1908  int i;
1909 
1910  for (i = 0; i < nkeys; i++)
1911  {
1912  int attnum = attnos[i];
1913  Form_pg_attribute att;
1914 
1915  /* system attribute are not supported in caches */
1916  Assert(attnum > 0);
1917 
1918  att = TupleDescAttr(tupdesc, attnum - 1);
1919 
1920  if (!att->attbyval)
1921  pfree(DatumGetPointer(keys[i]));
1922  }
1923 }
void pfree(void *pointer)
Definition: mcxt.c:1175
#define DatumGetPointer(X)
Definition: postgres.h:593

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

Referenced by CatCacheRemoveCList(), and CatCacheRemoveCTup().

◆ CatCacheInvalidate()

void CatCacheInvalidate ( CatCache cache,
uint32  hashValue 
)

Definition at line 546 of file catcache.c.

547 {
548  Index hashIndex;
549  dlist_mutable_iter iter;
550 
551  CACHE_elog(DEBUG2, "CatCacheInvalidate: called");
552 
553  /*
554  * We don't bother to check whether the cache has finished initialization
555  * yet; if not, there will be no entries in it so no problem.
556  */
557 
558  /*
559  * Invalidate *all* CatCLists in this cache; it's too hard to tell which
560  * searches might still be correct, so just zap 'em all.
561  */
562  dlist_foreach_modify(iter, &cache->cc_lists)
563  {
564  CatCList *cl = dlist_container(CatCList, cache_elem, iter.cur);
565 
566  if (cl->refcount > 0)
567  cl->dead = true;
568  else
569  CatCacheRemoveCList(cache, cl);
570  }
571 
572  /*
573  * inspect the proper hash bucket for tuple matches
574  */
575  hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
576  dlist_foreach_modify(iter, &cache->cc_bucket[hashIndex])
577  {
578  CatCTup *ct = dlist_container(CatCTup, cache_elem, iter.cur);
579 
580  if (hashValue == ct->hash_value)
581  {
582  if (ct->refcount > 0 ||
583  (ct->c_list && ct->c_list->refcount > 0))
584  {
585  ct->dead = true;
586  /* list, if any, was marked dead above */
587  Assert(ct->c_list == NULL || ct->c_list->dead);
588  }
589  else
590  CatCacheRemoveCTup(cache, ct);
591  CACHE_elog(DEBUG2, "CatCacheInvalidate: invalidated");
592 #ifdef CATCACHE_STATS
593  cache->cc_invals++;
594 #endif
595  /* could be multiple matches, so keep looking! */
596  }
597  }
598 }
unsigned int Index
Definition: c.h:549
static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
Definition: catcache.c:451
static void CatCacheRemoveCList(CatCache *cache, CatCList *cl)
Definition: catcache.c:493
#define HASH_INDEX(h, sz)
Definition: catcache.c:51
#define dlist_foreach_modify(iter, lhead)
Definition: ilist.h:543
#define dlist_container(type, membername, ptr)
Definition: ilist.h:496
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:180

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

494 {
495  int i;
496 
497  Assert(cl->refcount == 0);
498  Assert(cl->my_cache == cache);
499 
500  /* delink from member tuples */
501  for (i = cl->n_members; --i >= 0;)
502  {
503  CatCTup *ct = cl->members[i];
504 
505  Assert(ct->c_list == cl);
506  ct->c_list = NULL;
507  /* if the member is dead and now has no references, remove it */
508  if (
509 #ifndef CATCACHE_FORCE_RELEASE
510  ct->dead &&
511 #endif
512  ct->refcount == 0)
513  CatCacheRemoveCTup(cache, ct);
514  }
515 
516  /* delink from linked list */
517  dlist_delete(&cl->cache_elem);
518 
519  /* free associated column data */
520  CatCacheFreeKeys(cache->cc_tupdesc, cl->nkeys,
521  cache->cc_keyno, cl->keys);
522 
523  pfree(cl);
524 }
static void CatCacheFreeKeys(TupleDesc tupdesc, int nkeys, int *attnos, Datum *keys)
Definition: catcache.c:1906
static void dlist_delete(dlist_node *node)
Definition: ilist.h:358
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(), ReleaseCatCacheList(), and ResetCatalogCache().

◆ CatCacheRemoveCTup()

static void CatCacheRemoveCTup ( CatCache cache,
CatCTup ct 
)
static

Definition at line 451 of file catcache.c.

452 {
453  Assert(ct->refcount == 0);
454  Assert(ct->my_cache == cache);
455 
456  if (ct->c_list)
457  {
458  /*
459  * The cleanest way to handle this is to call CatCacheRemoveCList,
460  * which will recurse back to me, and the recursive call will do the
461  * work. Set the "dead" flag to make sure it does recurse.
462  */
463  ct->dead = true;
464  CatCacheRemoveCList(cache, ct->c_list);
465  return; /* nothing left to do */
466  }
467 
468  /* delink from linked list */
469  dlist_delete(&ct->cache_elem);
470 
471  /*
472  * Free keys when we're dealing with a negative entry, normal entries just
473  * point into tuple, allocated together with the CatCTup.
474  */
475  if (ct->negative)
476  CatCacheFreeKeys(cache->cc_tupdesc, cache->cc_nkeys,
477  cache->cc_keyno, ct->keys);
478 
479  pfree(ct);
480 
481  --cache->cc_ntup;
482  --CacheHdr->ch_ntup;
483 }

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(), ReleaseCatCache(), ResetCatalogCache(), and SearchCatCacheList().

◆ chareqfast()

static bool chareqfast ( Datum  a,
Datum  b 
)
static

Definition at line 119 of file catcache.c.

120 {
121  return DatumGetChar(a) == DatumGetChar(b);
122 }
int b
Definition: isn.c:70
int a
Definition: isn.c:69
#define DatumGetChar(X)
Definition: postgres.h:453

References a, b, and DatumGetChar.

Referenced by GetCCHashEqFuncs().

◆ charhashfast()

static uint32 charhashfast ( Datum  datum)
static

Definition at line 125 of file catcache.c.

126 {
127  return murmurhash32((int32) DatumGetChar(datum));
128 }
signed int int32
Definition: c.h:429
static uint32 murmurhash32(uint32 data)
Definition: hashfn.h:92

References DatumGetChar, and murmurhash32().

Referenced by GetCCHashEqFuncs().

◆ CreateCacheMemoryContext()

void CreateCacheMemoryContext ( void  )

Definition at line 614 of file catcache.c.

615 {
616  /*
617  * Purely for paranoia, check that context doesn't exist; caller probably
618  * did so already.
619  */
620  if (!CacheMemoryContext)
622  "CacheMemoryContext",
624 }
MemoryContext TopMemoryContext
Definition: mcxt.c:48
#define AllocSetContextCreate
Definition: memutils.h:173
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:197

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CacheMemoryContext, and TopMemoryContext.

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

◆ GetCatCacheHashValue()

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

Definition at line 1468 of file catcache.c.

1473 {
1474  /*
1475  * one-time startup overhead for each cache
1476  */
1477  if (cache->cc_tupdesc == NULL)
1479 
1480  /*
1481  * calculate the hash value
1482  */
1483  return CatalogCacheComputeHashValue(cache, cache->cc_nkeys, v1, v2, v3, v4);
1484 }
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:917

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

203 {
204  switch (keytype)
205  {
206  case BOOLOID:
207  *hashfunc = charhashfast;
208  *fasteqfunc = chareqfast;
209  *eqfunc = F_BOOLEQ;
210  break;
211  case CHAROID:
212  *hashfunc = charhashfast;
213  *fasteqfunc = chareqfast;
214  *eqfunc = F_CHAREQ;
215  break;
216  case NAMEOID:
217  *hashfunc = namehashfast;
218  *fasteqfunc = nameeqfast;
219  *eqfunc = F_NAMEEQ;
220  break;
221  case INT2OID:
222  *hashfunc = int2hashfast;
223  *fasteqfunc = int2eqfast;
224  *eqfunc = F_INT2EQ;
225  break;
226  case INT4OID:
227  *hashfunc = int4hashfast;
228  *fasteqfunc = int4eqfast;
229  *eqfunc = F_INT4EQ;
230  break;
231  case TEXTOID:
232  *hashfunc = texthashfast;
233  *fasteqfunc = texteqfast;
234  *eqfunc = F_TEXTEQ;
235  break;
236  case OIDOID:
237  case REGPROCOID:
238  case REGPROCEDUREOID:
239  case REGOPEROID:
240  case REGOPERATOROID:
241  case REGCLASSOID:
242  case REGTYPEOID:
243  case REGCONFIGOID:
244  case REGDICTIONARYOID:
245  case REGROLEOID:
246  case REGNAMESPACEOID:
247  *hashfunc = int4hashfast;
248  *fasteqfunc = int4eqfast;
249  *eqfunc = F_OIDEQ;
250  break;
251  case OIDVECTOROID:
252  *hashfunc = oidvectorhashfast;
253  *fasteqfunc = oidvectoreqfast;
254  *eqfunc = F_OIDVECTOREQ;
255  break;
256  default:
257  elog(FATAL, "type %u not supported as catcache key", keytype);
258  *hashfunc = NULL; /* keep compiler quiet */
259 
260  *eqfunc = InvalidOid;
261  break;
262  }
263 }
static bool chareqfast(Datum a, Datum b)
Definition: catcache.c:119
static bool int4eqfast(Datum a, Datum b)
Definition: catcache.c:160
static bool int2eqfast(Datum a, Datum b)
Definition: catcache.c:148
static uint32 int4hashfast(Datum datum)
Definition: catcache.c:166
static uint32 namehashfast(Datum datum)
Definition: catcache.c:140
static bool nameeqfast(Datum a, Datum b)
Definition: catcache.c:131
static uint32 charhashfast(Datum datum)
Definition: catcache.c:125
static uint32 oidvectorhashfast(Datum datum)
Definition: catcache.c:195
static bool texteqfast(Datum a, Datum b)
Definition: catcache.c:172
static bool oidvectoreqfast(Datum a, Datum b)
Definition: catcache.c:189
static uint32 int2hashfast(Datum datum)
Definition: catcache.c:154
static uint32 texthashfast(Datum datum)
Definition: catcache.c:182

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

1079 {
1080  switch (cache->id)
1081  {
1082  case INDEXRELID:
1083 
1084  /*
1085  * Rather than tracking exactly which indexes have to be loaded
1086  * before we can use indexscans (which changes from time to time),
1087  * just force all pg_index searches to be heap scans until we've
1088  * built the critical relcaches.
1089  */
1091  return false;
1092  break;
1093 
1094  case AMOID:
1095  case AMNAME:
1096 
1097  /*
1098  * Always do heap scans in pg_am, because it's so small there's
1099  * not much point in an indexscan anyway. We *must* do this when
1100  * initially building critical relcache entries, but we might as
1101  * well just always do it.
1102  */
1103  return false;
1104 
1105  case AUTHNAME:
1106  case AUTHOID:
1107  case AUTHMEMMEMROLE:
1108  case DATABASEOID:
1109 
1110  /*
1111  * Protect authentication lookups occurring before relcache has
1112  * collected entries for shared indexes.
1113  */
1115  return false;
1116  break;
1117 
1118  default:
1119  break;
1120  }
1121 
1122  /* Normal case, allow index scan */
1123  return true;
1124 }
bool criticalRelcachesBuilt
Definition: relcache.c:139
bool criticalSharedRelcachesBuilt
Definition: relcache.c:145
@ AMNAME
Definition: syscache.h:35
@ AMOID
Definition: syscache.h:36
@ AUTHOID
Definition: syscache.h:45
@ INDEXRELID
Definition: syscache.h:66
@ AUTHNAME
Definition: syscache.h:44
@ AUTHMEMMEMROLE
Definition: syscache.h:42
@ DATABASEOID
Definition: syscache.h:55

References AMNAME, AMOID, AUTHMEMMEMROLE, AUTHNAME, AUTHOID, criticalRelcachesBuilt, criticalSharedRelcachesBuilt, DATABASEOID, catcache::id, and INDEXRELID.

Referenced by SearchCatCacheList(), and SearchCatCacheMiss().

◆ InitCatCache()

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

Definition at line 757 of file catcache.c.

763 {
764  CatCache *cp;
765  MemoryContext oldcxt;
766  size_t sz;
767  int i;
768 
769  /*
770  * nbuckets is the initial number of hash buckets to use in this catcache.
771  * It will be enlarged later if it becomes too full.
772  *
773  * nbuckets must be a power of two. We check this via Assert rather than
774  * a full runtime check because the values will be coming from constant
775  * tables.
776  *
777  * If you're confused by the power-of-two check, see comments in
778  * bitmapset.c for an explanation.
779  */
780  Assert(nbuckets > 0 && (nbuckets & -nbuckets) == nbuckets);
781 
782  /*
783  * first switch to the cache context so our allocations do not vanish at
784  * the end of a transaction
785  */
786  if (!CacheMemoryContext)
788 
790 
791  /*
792  * if first time through, initialize the cache group header
793  */
794  if (CacheHdr == NULL)
795  {
798  CacheHdr->ch_ntup = 0;
799 #ifdef CATCACHE_STATS
800  /* set up to dump stats at backend exit */
801  on_proc_exit(CatCachePrintStats, 0);
802 #endif
803  }
804 
805  /*
806  * Allocate a new cache structure, aligning to a cacheline boundary
807  *
808  * Note: we rely on zeroing to initialize all the dlist headers correctly
809  */
810  sz = sizeof(CatCache) + PG_CACHE_LINE_SIZE;
811  cp = (CatCache *) CACHELINEALIGN(palloc0(sz));
812  cp->cc_bucket = palloc0(nbuckets * sizeof(dlist_head));
813 
814  /*
815  * initialize the cache's relation information for the relation
816  * corresponding to this cache, and initialize some of the new cache's
817  * other internal fields. But don't open the relation yet.
818  */
819  cp->id = id;
820  cp->cc_relname = "(not known yet)";
821  cp->cc_reloid = reloid;
822  cp->cc_indexoid = indexoid;
823  cp->cc_relisshared = false; /* temporary */
824  cp->cc_tupdesc = (TupleDesc) NULL;
825  cp->cc_ntup = 0;
826  cp->cc_nbuckets = nbuckets;
827  cp->cc_nkeys = nkeys;
828  for (i = 0; i < nkeys; ++i)
829  cp->cc_keyno[i] = key[i];
830 
831  /*
832  * new cache is initialized as far as we can go for now. print some
833  * debugging information, if appropriate.
834  */
836 
837  /*
838  * add completed cache to top of group header's list
839  */
841 
842  /*
843  * back to the old context before we return...
844  */
845  MemoryContextSwitchTo(oldcxt);
846 
847  return cp;
848 }
#define CACHELINEALIGN(LEN)
Definition: c.h:760
void CreateCacheMemoryContext(void)
Definition: catcache.c:614
#define InitCatCache_DEBUG2
Definition: catcache.c:753
struct catcache CatCache
static void slist_init(slist_head *head)
Definition: ilist.h:573
static void slist_push_head(slist_head *head, slist_node *node)
Definition: ilist.h:593
void on_proc_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:305
void * palloc0(Size size)
Definition: mcxt.c:1099
#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(), CacheHdr, CACHELINEALIGN, CacheMemoryContext, catcache::cc_bucket, catcache::cc_indexoid, catcache::cc_keyno, catcache::cc_nbuckets, catcache::cc_next, catcache::cc_nkeys, catcache::cc_ntup, catcache::cc_relisshared, catcache::cc_relname, catcache::cc_reloid, catcache::cc_tupdesc, catcacheheader::ch_caches, catcacheheader::ch_ntup, CreateCacheMemoryContext(), i, catcache::id, InitCatCache_DEBUG2, sort-test::key, MemoryContextSwitchTo(), on_proc_exit(), palloc(), palloc0(), PG_CACHE_LINE_SIZE, slist_init(), and slist_push_head().

Referenced by InitCatalogCache().

◆ InitCatCachePhase2()

void InitCatCachePhase2 ( CatCache cache,
bool  touch_index 
)

Definition at line 1026 of file catcache.c.

1027 {
1028  if (cache->cc_tupdesc == NULL)
1030 
1031  if (touch_index &&
1032  cache->id != AMOID &&
1033  cache->id != AMNAME)
1034  {
1035  Relation idesc;
1036 
1037  /*
1038  * We must lock the underlying catalog before opening the index to
1039  * avoid deadlock, since index_open could possibly result in reading
1040  * this same catalog, and if anyone else is exclusive-locking this
1041  * catalog and index they'll be doing it in that order.
1042  */
1044  idesc = index_open(cache->cc_indexoid, AccessShareLock);
1045 
1046  /*
1047  * While we've got the index open, let's check that it's unique (and
1048  * not just deferrable-unique, thank you very much). This is just to
1049  * catch thinkos in definitions of new catcaches, so we don't worry
1050  * about the pg_am indexes not getting tested.
1051  */
1052  Assert(idesc->rd_index->indisunique &&
1053  idesc->rd_index->indimmediate);
1054 
1055  index_close(idesc, AccessShareLock);
1057  }
1058 }
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:158
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:132
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:228
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:109
Form_pg_index rd_index
Definition: rel.h:187

References AccessShareLock, AMNAME, AMOID, Assert(), CatalogCacheInitializeCache(), catcache::cc_indexoid, catcache::cc_reloid, catcache::cc_tupdesc, catcache::id, index_close(), index_open(), LockRelationOid(), RelationData::rd_index, and UnlockRelationOid().

Referenced by InitCatalogCachePhase2(), and SysCacheGetAttr().

◆ int2eqfast()

static bool int2eqfast ( Datum  a,
Datum  b 
)
static

Definition at line 148 of file catcache.c.

149 {
150  return DatumGetInt16(a) == DatumGetInt16(b);
151 }
#define DatumGetInt16(X)
Definition: postgres.h:488

References a, b, and DatumGetInt16.

Referenced by GetCCHashEqFuncs().

◆ int2hashfast()

static uint32 int2hashfast ( Datum  datum)
static

Definition at line 154 of file catcache.c.

155 {
156  return murmurhash32((int32) DatumGetInt16(datum));
157 }

References DatumGetInt16, and murmurhash32().

Referenced by GetCCHashEqFuncs().

◆ int4eqfast()

static bool int4eqfast ( Datum  a,
Datum  b 
)
static

Definition at line 160 of file catcache.c.

161 {
162  return DatumGetInt32(a) == DatumGetInt32(b);
163 }
#define DatumGetInt32(X)
Definition: postgres.h:516

References a, b, and DatumGetInt32.

Referenced by GetCCHashEqFuncs().

◆ int4hashfast()

static uint32 int4hashfast ( Datum  datum)
static

Definition at line 166 of file catcache.c.

167 {
168  return murmurhash32((int32) DatumGetInt32(datum));
169 }

References DatumGetInt32, and murmurhash32().

Referenced by GetCCHashEqFuncs().

◆ nameeqfast()

static bool nameeqfast ( Datum  a,
Datum  b 
)
static

Definition at line 131 of file catcache.c.

132 {
133  char *ca = NameStr(*DatumGetName(a));
134  char *cb = NameStr(*DatumGetName(b));
135 
136  return strncmp(ca, cb, NAMEDATALEN) == 0;
137 }
#define NameStr(name)
Definition: c.h:681
#define NAMEDATALEN
#define DatumGetName(X)
Definition: postgres.h:629

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

Referenced by GetCCHashEqFuncs().

◆ namehashfast()

static uint32 namehashfast ( Datum  datum)
static

Definition at line 140 of file catcache.c.

141 {
142  char *key = NameStr(*DatumGetName(datum));
143 
144  return hash_any((unsigned char *) key, strlen(key));
145 }
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 189 of file catcache.c.

190 {
192 }
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:633
Datum oidvectoreq(PG_FUNCTION_ARGS)
Definition: oid.c:426
#define DatumGetBool(X)
Definition: postgres.h:437

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

Referenced by GetCCHashEqFuncs().

◆ oidvectorhashfast()

static uint32 oidvectorhashfast ( Datum  datum)
static

Definition at line 195 of file catcache.c.

196 {
198 }
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:631
Datum hashoidvector(PG_FUNCTION_ARGS)
Definition: hashfunc.c:233

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

2005 {
2006  slist_iter iter;
2007  Oid reloid;
2008 
2009  CACHE_elog(DEBUG2, "PrepareToInvalidateCacheTuple: called");
2010 
2011  /*
2012  * sanity checks
2013  */
2014  Assert(RelationIsValid(relation));
2015  Assert(HeapTupleIsValid(tuple));
2016  Assert(PointerIsValid(function));
2017  Assert(CacheHdr != NULL);
2018 
2019  reloid = RelationGetRelid(relation);
2020 
2021  /* ----------------
2022  * for each cache
2023  * if the cache contains tuples from the specified relation
2024  * compute the tuple's hash value(s) in this cache,
2025  * and call the passed function to register the information.
2026  * ----------------
2027  */
2028 
2030  {
2031  CatCache *ccp = slist_container(CatCache, cc_next, iter.cur);
2032  uint32 hashvalue;
2033  Oid dbid;
2034 
2035  if (ccp->cc_reloid != reloid)
2036  continue;
2037 
2038  /* Just in case cache hasn't finished initialization yet... */
2039  if (ccp->cc_tupdesc == NULL)
2041 
2042  hashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, tuple);
2043  dbid = ccp->cc_relisshared ? (Oid) 0 : MyDatabaseId;
2044 
2045  (*function) (ccp->id, hashvalue, dbid);
2046 
2047  if (newtuple)
2048  {
2049  uint32 newhashvalue;
2050 
2051  newhashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, newtuple);
2052 
2053  if (newhashvalue != hashvalue)
2054  (*function) (ccp->id, newhashvalue, dbid);
2055  }
2056  }
2057 }
#define PointerIsValid(pointer)
Definition: c.h:698
static uint32 CatalogCacheComputeTupleHashValue(CatCache *cache, int nkeys, HeapTuple tuple)
Definition: catcache.c:313
Oid MyDatabaseId
Definition: globals.c:89
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define RelationGetRelid(relation)
Definition: rel.h:488
#define RelationIsValid(relation)
Definition: rel.h:461

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

◆ PrintCatCacheLeakWarning()

void PrintCatCacheLeakWarning ( HeapTuple  tuple)

Definition at line 2065 of file catcache.c.

2066 {
2067  CatCTup *ct = (CatCTup *) (((char *) tuple) -
2068  offsetof(CatCTup, tuple));
2069 
2070  /* Safety check to ensure we were handed a cache entry */
2071  Assert(ct->ct_magic == CT_MAGIC);
2072 
2073  elog(WARNING, "cache reference leak: cache %s (%d), tuple %u/%u has count %d",
2074  ct->my_cache->cc_relname, ct->my_cache->id,
2075  ItemPointerGetBlockNumber(&(tuple->t_self)),
2076  ItemPointerGetOffsetNumber(&(tuple->t_self)),
2077  ct->refcount);
2078 }
#define offsetof(type, field)
Definition: c.h:727
#define WARNING
Definition: elog.h:30
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:98
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:117

References Assert(), catcache::cc_relname, catctup::ct_magic, CT_MAGIC, elog, catcache::id, ItemPointerGetBlockNumber, ItemPointerGetOffsetNumber, catctup::my_cache, offsetof, catctup::refcount, HeapTupleData::t_self, and WARNING.

Referenced by ResourceOwnerReleaseInternal().

◆ PrintCatCacheListLeakWarning()

void PrintCatCacheListLeakWarning ( CatCList list)

Definition at line 2081 of file catcache.c.

2082 {
2083  elog(WARNING, "cache reference leak: cache %s (%d), list %p has count %d",
2084  list->my_cache->cc_relname, list->my_cache->id,
2085  list, list->refcount);
2086 }

References elog, sort-test::list, and WARNING.

Referenced by ResourceOwnerReleaseInternal().

◆ RehashCatCache()

static void RehashCatCache ( CatCache cp)
static

Definition at line 854 of file catcache.c.

855 {
856  dlist_head *newbucket;
857  int newnbuckets;
858  int i;
859 
860  elog(DEBUG1, "rehashing catalog cache id %d for %s; %d tups, %d buckets",
861  cp->id, cp->cc_relname, cp->cc_ntup, cp->cc_nbuckets);
862 
863  /* Allocate a new, larger, hash table. */
864  newnbuckets = cp->cc_nbuckets * 2;
865  newbucket = (dlist_head *) MemoryContextAllocZero(CacheMemoryContext, newnbuckets * sizeof(dlist_head));
866 
867  /* Move all entries from old hash table to new. */
868  for (i = 0; i < cp->cc_nbuckets; i++)
869  {
870  dlist_mutable_iter iter;
871 
872  dlist_foreach_modify(iter, &cp->cc_bucket[i])
873  {
874  CatCTup *ct = dlist_container(CatCTup, cache_elem, iter.cur);
875  int hashIndex = HASH_INDEX(ct->hash_value, newnbuckets);
876 
877  dlist_delete(iter.cur);
878  dlist_push_head(&newbucket[hashIndex], &ct->cache_elem);
879  }
880  }
881 
882  /* Switch to the new array. */
883  pfree(cp->cc_bucket);
884  cp->cc_nbuckets = newnbuckets;
885  cp->cc_bucket = newbucket;
886 }
#define DEBUG1
Definition: elog.h:24
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:906

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

1437 {
1438  CatCTup *ct = (CatCTup *) (((char *) tuple) -
1439  offsetof(CatCTup, tuple));
1440 
1441  /* Safety checks to ensure we were handed a cache entry */
1442  Assert(ct->ct_magic == CT_MAGIC);
1443  Assert(ct->refcount > 0);
1444 
1445  ct->refcount--;
1447 
1448  if (
1449 #ifndef CATCACHE_FORCE_RELEASE
1450  ct->dead &&
1451 #endif
1452  ct->refcount == 0 &&
1453  (ct->c_list == NULL || ct->c_list->refcount == 0))
1454  CatCacheRemoveCTup(ct->my_cache, ct);
1455 }
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
void ResourceOwnerForgetCatCacheRef(ResourceOwner owner, HeapTuple tuple)
Definition: resowner.c:1054

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

Referenced by ReleaseSysCache(), and ResourceOwnerReleaseInternal().

◆ ReleaseCatCacheList()

void ReleaseCatCacheList ( CatCList list)

Definition at line 1777 of file catcache.c.

1778 {
1779  /* Safety checks to ensure we were handed a cache entry */
1780  Assert(list->cl_magic == CL_MAGIC);
1781  Assert(list->refcount > 0);
1782  list->refcount--;
1784 
1785  if (
1786 #ifndef CATCACHE_FORCE_RELEASE
1787  list->dead &&
1788 #endif
1789  list->refcount == 0)
1790  CatCacheRemoveCList(list->my_cache, list);
1791 }
#define CL_MAGIC
Definition: catcache.h:160
void ResourceOwnerForgetCatCacheListRef(ResourceOwner owner, CatCList *list)
Definition: resowner.c:1089

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

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

◆ ResetCatalogCache()

static void ResetCatalogCache ( CatCache cache)
static

Definition at line 636 of file catcache.c.

637 {
638  dlist_mutable_iter iter;
639  int i;
640 
641  /* Remove each list in this cache, or at least mark it dead */
642  dlist_foreach_modify(iter, &cache->cc_lists)
643  {
644  CatCList *cl = dlist_container(CatCList, cache_elem, iter.cur);
645 
646  if (cl->refcount > 0)
647  cl->dead = true;
648  else
649  CatCacheRemoveCList(cache, cl);
650  }
651 
652  /* Remove each tuple in this cache, or at least mark it dead */
653  for (i = 0; i < cache->cc_nbuckets; i++)
654  {
655  dlist_head *bucket = &cache->cc_bucket[i];
656 
657  dlist_foreach_modify(iter, bucket)
658  {
659  CatCTup *ct = dlist_container(CatCTup, cache_elem, iter.cur);
660 
661  if (ct->refcount > 0 ||
662  (ct->c_list && ct->c_list->refcount > 0))
663  {
664  ct->dead = true;
665  /* list, if any, was marked dead above */
666  Assert(ct->c_list == NULL || ct->c_list->dead);
667  }
668  else
669  CatCacheRemoveCTup(cache, ct);
670 #ifdef CATCACHE_STATS
671  cache->cc_invals++;
672 #endif
673  }
674  }
675 }

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

684 {
685  slist_iter iter;
686 
687  CACHE_elog(DEBUG2, "ResetCatalogCaches called");
688 
690  {
691  CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
692 
693  ResetCatalogCache(cache);
694  }
695 
696  CACHE_elog(DEBUG2, "end of ResetCatalogCaches call");
697 }

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

Referenced by InvalidateSystemCachesExtended().

◆ SearchCatCache()

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

Definition at line 1143 of file catcache.c.

1148 {
1149  return SearchCatCacheInternal(cache, cache->cc_nkeys, v1, v2, v3, v4);
1150 }
static HeapTuple SearchCatCacheInternal(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1194

References catcache::cc_nkeys, and SearchCatCacheInternal().

Referenced by SearchSysCache().

◆ SearchCatCache1()

HeapTuple SearchCatCache1 ( CatCache cache,
Datum  v1 
)

Definition at line 1160 of file catcache.c.

1162 {
1163  return SearchCatCacheInternal(cache, 1, v1, 0, 0, 0);
1164 }

References SearchCatCacheInternal().

Referenced by SearchSysCache1().

◆ SearchCatCache2()

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

Definition at line 1168 of file catcache.c.

1170 {
1171  return SearchCatCacheInternal(cache, 2, v1, v2, 0, 0);
1172 }

References SearchCatCacheInternal().

Referenced by SearchSysCache2().

◆ SearchCatCache3()

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

Definition at line 1176 of file catcache.c.

1178 {
1179  return SearchCatCacheInternal(cache, 3, v1, v2, v3, 0);
1180 }

References SearchCatCacheInternal().

Referenced by SearchSysCache3().

◆ SearchCatCache4()

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

Definition at line 1184 of file catcache.c.

1186 {
1187  return SearchCatCacheInternal(cache, 4, v1, v2, v3, v4);
1188 }

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

1200 {
1202  uint32 hashValue;
1203  Index hashIndex;
1204  dlist_iter iter;
1205  dlist_head *bucket;
1206  CatCTup *ct;
1207 
1208  /* Make sure we're in an xact, even if this ends up being a cache hit */
1210 
1211  Assert(cache->cc_nkeys == nkeys);
1212 
1213  /*
1214  * one-time startup overhead for each cache
1215  */
1216  if (unlikely(cache->cc_tupdesc == NULL))
1218 
1219 #ifdef CATCACHE_STATS
1220  cache->cc_searches++;
1221 #endif
1222 
1223  /* Initialize local parameter array */
1224  arguments[0] = v1;
1225  arguments[1] = v2;
1226  arguments[2] = v3;
1227  arguments[3] = v4;
1228 
1229  /*
1230  * find the hash bucket in which to look for the tuple
1231  */
1232  hashValue = CatalogCacheComputeHashValue(cache, nkeys, v1, v2, v3, v4);
1233  hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
1234 
1235  /*
1236  * scan the hash bucket until we find a match or exhaust our tuples
1237  *
1238  * Note: it's okay to use dlist_foreach here, even though we modify the
1239  * dlist within the loop, because we don't continue the loop afterwards.
1240  */
1241  bucket = &cache->cc_bucket[hashIndex];
1242  dlist_foreach(iter, bucket)
1243  {
1244  ct = dlist_container(CatCTup, cache_elem, iter.cur);
1245 
1246  if (ct->dead)
1247  continue; /* ignore dead entries */
1248 
1249  if (ct->hash_value != hashValue)
1250  continue; /* quickly skip entry if wrong hash val */
1251 
1252  if (!CatalogCacheCompareTuple(cache, nkeys, ct->keys, arguments))
1253  continue;
1254 
1255  /*
1256  * We found a match in the cache. Move it to the front of the list
1257  * for its hashbucket, in order to speed subsequent searches. (The
1258  * most frequently accessed elements in any hashbucket will tend to be
1259  * near the front of the hashbucket's list.)
1260  */
1261  dlist_move_head(bucket, &ct->cache_elem);
1262 
1263  /*
1264  * If it's a positive entry, bump its refcount and return it. If it's
1265  * negative, we can report failure to the caller.
1266  */
1267  if (!ct->negative)
1268  {
1270  ct->refcount++;
1272 
1273  CACHE_elog(DEBUG2, "SearchCatCache(%s): found in bucket %d",
1274  cache->cc_relname, hashIndex);
1275 
1276 #ifdef CATCACHE_STATS
1277  cache->cc_hits++;
1278 #endif
1279 
1280  return &ct->tuple;
1281  }
1282  else
1283  {
1284  CACHE_elog(DEBUG2, "SearchCatCache(%s): found neg entry in bucket %d",
1285  cache->cc_relname, hashIndex);
1286 
1287 #ifdef CATCACHE_STATS
1288  cache->cc_neg_hits++;
1289 #endif
1290 
1291  return NULL;
1292  }
1293  }
1294 
1295  return SearchCatCacheMiss(cache, nkeys, hashValue, hashIndex, v1, v2, v3, v4);
1296 }
#define unlikely(x)
Definition: c.h:273
static pg_noinline HeapTuple SearchCatCacheMiss(CatCache *cache, int nkeys, uint32 hashValue, Index hashIndex, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1306
static bool CatalogCacheCompareTuple(const CatCache *cache, int nkeys, const Datum *cachekeys, const Datum *searchkeys)
Definition: catcache.c:368
#define CATCACHE_MAXKEYS
Definition: catcache.h:35
#define dlist_foreach(iter, lhead)
Definition: ilist.h:526
static void dlist_move_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:385
void ResourceOwnerRememberCatCacheRef(ResourceOwner owner, HeapTuple tuple)
Definition: resowner.c:1045
void ResourceOwnerEnlargeCatCacheRefs(ResourceOwner owner)
Definition: resowner.c:1034
dlist_node * cur
Definition: ilist.h:161
bool IsTransactionState(void)
Definition: xact.c:374

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, ResourceOwnerEnlargeCatCacheRefs(), 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 1502 of file catcache.c.

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

1314 {
1315  ScanKeyData cur_skey[CATCACHE_MAXKEYS];
1316  Relation relation;
1317  SysScanDesc scandesc;
1318  HeapTuple ntp;
1319  CatCTup *ct;
1321 
1322  /* Initialize local parameter array */
1323  arguments[0] = v1;
1324  arguments[1] = v2;
1325  arguments[2] = v3;
1326  arguments[3] = v4;
1327 
1328  /*
1329  * Ok, need to make a lookup in the relation, copy the scankey and fill
1330  * out any per-call fields.
1331  */
1332  memcpy(cur_skey, cache->cc_skey, sizeof(ScanKeyData) * nkeys);
1333  cur_skey[0].sk_argument = v1;
1334  cur_skey[1].sk_argument = v2;
1335  cur_skey[2].sk_argument = v3;
1336  cur_skey[3].sk_argument = v4;
1337 
1338  /*
1339  * Tuple was not found in cache, so we have to try to retrieve it directly
1340  * from the relation. If found, we will add it to the cache; if not
1341  * found, we will add a negative cache entry instead.
1342  *
1343  * NOTE: it is possible for recursive cache lookups to occur while reading
1344  * the relation --- for example, due to shared-cache-inval messages being
1345  * processed during table_open(). This is OK. It's even possible for one
1346  * of those lookups to find and enter the very same tuple we are trying to
1347  * fetch here. If that happens, we will enter a second copy of the tuple
1348  * into the cache. The first copy will never be referenced again, and
1349  * will eventually age out of the cache, so there's no functional problem.
1350  * This case is rare enough that it's not worth expending extra cycles to
1351  * detect.
1352  */
1353  relation = table_open(cache->cc_reloid, AccessShareLock);
1354 
1355  scandesc = systable_beginscan(relation,
1356  cache->cc_indexoid,
1357  IndexScanOK(cache, cur_skey),
1358  NULL,
1359  nkeys,
1360  cur_skey);
1361 
1362  ct = NULL;
1363 
1364  while (HeapTupleIsValid(ntp = systable_getnext(scandesc)))
1365  {
1366  ct = CatalogCacheCreateEntry(cache, ntp, arguments,
1367  hashValue, hashIndex,
1368  false);
1369  /* immediately set the refcount to 1 */
1371  ct->refcount++;
1373  break; /* assume only one match */
1374  }
1375 
1376  systable_endscan(scandesc);
1377 
1378  table_close(relation, AccessShareLock);
1379 
1380  /*
1381  * If tuple was not found, we need to build a negative cache entry
1382  * containing a fake tuple. The fake tuple has the correct key columns,
1383  * but nulls everywhere else.
1384  *
1385  * In bootstrap mode, we don't build negative entries, because the cache
1386  * invalidation mechanism isn't alive and can't clear them if the tuple
1387  * gets created later. (Bootstrap doesn't do UPDATEs, so it doesn't need
1388  * cache inval for that.)
1389  */
1390  if (ct == NULL)
1391  {
1393  return NULL;
1394 
1395  ct = CatalogCacheCreateEntry(cache, NULL, arguments,
1396  hashValue, hashIndex,
1397  true);
1398 
1399  CACHE_elog(DEBUG2, "SearchCatCache(%s): Contains %d/%d tuples",
1400  cache->cc_relname, cache->cc_ntup, CacheHdr->ch_ntup);
1401  CACHE_elog(DEBUG2, "SearchCatCache(%s): put neg entry in bucket %d",
1402  cache->cc_relname, hashIndex);
1403 
1404  /*
1405  * We are not returning the negative entry to the caller, so leave its
1406  * refcount zero.
1407  */
1408 
1409  return NULL;
1410  }
1411 
1412  CACHE_elog(DEBUG2, "SearchCatCache(%s): Contains %d/%d tuples",
1413  cache->cc_relname, cache->cc_ntup, CacheHdr->ch_ntup);
1414  CACHE_elog(DEBUG2, "SearchCatCache(%s): put in bucket %d",
1415  cache->cc_relname, hashIndex);
1416 
1417 #ifdef CATCACHE_STATS
1418  cache->cc_newloads++;
1419 #endif
1420 
1421  return &ct->tuple;
1422 }
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:406

References AccessShareLock, 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, ResourceOwnerEnlargeCatCacheRefs(), 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 172 of file catcache.c.

173 {
174  /*
175  * The use of DEFAULT_COLLATION_OID is fairly arbitrary here. We just
176  * want to take the fast "deterministic" path in texteq().
177  */
178  return DatumGetBool(DirectFunctionCall2Coll(texteq, DEFAULT_COLLATION_OID, a, b));
179 }
Datum DirectFunctionCall2Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:797
Datum texteq(PG_FUNCTION_ARGS)
Definition: varlena.c:1757

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

Referenced by GetCCHashEqFuncs().

◆ texthashfast()

static uint32 texthashfast ( Datum  datum)
static

Definition at line 182 of file catcache.c.

183 {
184  /* analogously here as in texteqfast() */
185  return DatumGetInt32(DirectFunctionCall1Coll(hashtext, DEFAULT_COLLATION_OID, datum));
186 }
Datum DirectFunctionCall1Coll(PGFunction func, Oid collation, Datum arg1)
Definition: fmgr.c:777
Datum hashtext(PG_FUNCTION_ARGS)
Definition: hashfunc.c:268

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

Referenced by GetCCHashEqFuncs().

Variable Documentation

◆ CacheHdr