PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
catcache.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/heaptoast.h"
#include "access/relscan.h"
#include "access/table.h"
#include "access/xact.h"
#include "catalog/catalog.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_type.h"
#include "common/hashfn.h"
#include "common/pg_prng.h"
#include "miscadmin.h"
#include "port/pg_bitutils.h"
#include "storage/lmgr.h"
#include "utils/builtins.h"
#include "utils/catcache.h"
#include "utils/datum.h"
#include "utils/fmgroids.h"
#include "utils/injection_point.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.

Data Structures

struct  CatCInProgress
 

Macros

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

Typedefs

typedef struct CatCInProgress CatCInProgress
 

Functions

static HeapTuple SearchCatCacheInternal (CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
 
static pg_noinline HeapTuple SearchCatCacheMiss (CatCache *cache, int nkeys, uint32 hashValue, Index hashIndex, Datum v1, Datum v2, Datum v3, Datum v4)
 
static uint32 CatalogCacheComputeHashValue (CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
 
static uint32 CatalogCacheComputeTupleHashValue (CatCache *cache, int nkeys, HeapTuple tuple)
 
static bool CatalogCacheCompareTuple (const CatCache *cache, int nkeys, const Datum *cachekeys, const Datum *searchkeys)
 
static void CatCacheRemoveCTup (CatCache *cache, CatCTup *ct)
 
static void CatCacheRemoveCList (CatCache *cache, CatCList *cl)
 
static void RehashCatCache (CatCache *cp)
 
static void RehashCatCacheLists (CatCache *cp)
 
static void CatalogCacheInitializeCache (CatCache *cache)
 
static CatCTupCatalogCacheCreateEntry (CatCache *cache, HeapTuple ntp, 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, bool debug_discard)
 
void ResetCatalogCaches (void)
 
void ResetCatalogCachesExt (bool debug_discard)
 
void CatalogCacheFlushCatalog (Oid catId)
 
CatCacheInitCatCache (int id, Oid reloid, Oid indexoid, int nkeys, const int *key, int nbuckets)
 
void InitCatCachePhase2 (CatCache *cache, bool touch_index)
 
static bool IndexScanOK (CatCache *cache)
 
HeapTuple SearchCatCache (CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
 
HeapTuple SearchCatCache1 (CatCache *cache, Datum v1)
 
HeapTuple SearchCatCache2 (CatCache *cache, Datum v1, Datum v2)
 
HeapTuple SearchCatCache3 (CatCache *cache, Datum v1, Datum v2, Datum v3)
 
HeapTuple SearchCatCache4 (CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
 
void ReleaseCatCache (HeapTuple tuple)
 
uint32 GetCatCacheHashValue (CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
 
CatCListSearchCatCacheList (CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3)
 
void ReleaseCatCacheList (CatCList *list)
 
void PrepareToInvalidateCacheTuple (Relation relation, HeapTuple tuple, HeapTuple newtuple, void(*function)(int, uint32, Oid, void *), void *context)
 

Variables

static CatCInProgresscatcache_in_progress_stack = NULL
 
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 80 of file catcache.c.

◆ CatalogCacheInitializeCache_DEBUG1

#define CatalogCacheInitializeCache_DEBUG1

Definition at line 1081 of file catcache.c.

◆ CatalogCacheInitializeCache_DEBUG2

#define CatalogCacheInitializeCache_DEBUG2

Definition at line 1082 of file catcache.c.

◆ HASH_INDEX

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

Definition at line 70 of file catcache.c.

◆ InitCatCache_DEBUG2

#define InitCatCache_DEBUG2

Definition at line 874 of file catcache.c.

Typedef Documentation

◆ CatCInProgress

Function Documentation

◆ CatalogCacheCompareTuple()

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

Definition at line 441 of file catcache.c.

444{
445 const CCFastEqualFN *cc_fastequal = cache->cc_fastequal;
446 int i;
447
448 for (i = 0; i < nkeys; i++)
449 {
450 if (!(cc_fastequal[i]) (cachekeys[i], searchkeys[i]))
451 return false;
452 }
453 return true;
454}
bool(* CCFastEqualFN)(Datum a, Datum b)
Definition: catcache.h:42
int i
Definition: isn.c:77
CCFastEqualFN cc_fastequal[CATCACHE_MAXKEYS]
Definition: catcache.h:51

References CatCInProgress::cache, 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 344 of file catcache.c.

346{
347 uint32 hashValue = 0;
348 uint32 oneHash;
349 CCHashFN *cc_hashfunc = cache->cc_hashfunc;
350
351 CACHE_elog(DEBUG2, "CatalogCacheComputeHashValue %s %d %p",
352 cache->cc_relname, nkeys, cache);
353
354 switch (nkeys)
355 {
356 case 4:
357 oneHash = (cc_hashfunc[3]) (v4);
358 hashValue ^= pg_rotate_left32(oneHash, 24);
359 /* FALLTHROUGH */
360 case 3:
361 oneHash = (cc_hashfunc[2]) (v3);
362 hashValue ^= pg_rotate_left32(oneHash, 16);
363 /* FALLTHROUGH */
364 case 2:
365 oneHash = (cc_hashfunc[1]) (v2);
366 hashValue ^= pg_rotate_left32(oneHash, 8);
367 /* FALLTHROUGH */
368 case 1:
369 oneHash = (cc_hashfunc[0]) (v1);
370 hashValue ^= oneHash;
371 break;
372 default:
373 elog(FATAL, "wrong number of hash keys: %d", nkeys);
374 break;
375 }
376
377 return hashValue;
378}
uint32_t uint32
Definition: c.h:502
#define CACHE_elog(...)
Definition: catcache.c:80
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:226
static uint32 pg_rotate_left32(uint32 word, int n)
Definition: pg_bitutils.h:428
const char * cc_relname
Definition: catcache.h:59
CCHashFN cc_hashfunc[CATCACHE_MAXKEYS]
Definition: catcache.h:50

References CatCInProgress::cache, 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 386 of file catcache.c.

387{
388 Datum v1 = 0,
389 v2 = 0,
390 v3 = 0,
391 v4 = 0;
392 bool isNull = false;
393 int *cc_keyno = cache->cc_keyno;
394 TupleDesc cc_tupdesc = cache->cc_tupdesc;
395
396 /* Now extract key fields from tuple, insert into scankey */
397 switch (nkeys)
398 {
399 case 4:
400 v4 = fastgetattr(tuple,
401 cc_keyno[3],
402 cc_tupdesc,
403 &isNull);
404 Assert(!isNull);
405 /* FALLTHROUGH */
406 case 3:
407 v3 = fastgetattr(tuple,
408 cc_keyno[2],
409 cc_tupdesc,
410 &isNull);
411 Assert(!isNull);
412 /* FALLTHROUGH */
413 case 2:
414 v2 = fastgetattr(tuple,
415 cc_keyno[1],
416 cc_tupdesc,
417 &isNull);
418 Assert(!isNull);
419 /* FALLTHROUGH */
420 case 1:
421 v1 = fastgetattr(tuple,
422 cc_keyno[0],
423 cc_tupdesc,
424 &isNull);
425 Assert(!isNull);
426 break;
427 default:
428 elog(FATAL, "wrong number of hash keys: %d", nkeys);
429 break;
430 }
431
432 return CatalogCacheComputeHashValue(cache, nkeys, v1, v2, v3, v4);
433}
static uint32 CatalogCacheComputeHashValue(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:344
Assert(PointerIsAligned(start, uint64))
static Datum fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:861
uintptr_t Datum
Definition: postgres.h:69
int cc_keyno[CATCACHE_MAXKEYS]
Definition: catcache.h:53
TupleDesc cc_tupdesc
Definition: catcache.h:48

References Assert(), CatCInProgress::cache, 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 
)
static

Definition at line 2111 of file catcache.c.

2113{
2114 CatCTup *ct;
2115 MemoryContext oldcxt;
2116
2117 if (ntp)
2118 {
2119 int i;
2120 HeapTuple dtp = NULL;
2121
2122 /*
2123 * The invalidation of the in-progress entry essentially never happens
2124 * during our regression tests, and there's no easy way to force it to
2125 * fail for testing purposes. To ensure we have test coverage for the
2126 * retry paths in our callers, make debug builds randomly fail about
2127 * 0.1% of the times through this code path, even when there's no
2128 * toasted fields.
2129 */
2130#ifdef USE_ASSERT_CHECKING
2132 return NULL;
2133#endif
2134
2135 /*
2136 * If there are any out-of-line toasted fields in the tuple, expand
2137 * them in-line. This saves cycles during later use of the catcache
2138 * entry, and also protects us against the possibility of the toast
2139 * tuples being freed before we attempt to fetch them, in case of
2140 * something using a slightly stale catcache entry.
2141 */
2142 if (HeapTupleHasExternal(ntp))
2143 {
2144 CatCInProgress *save_in_progress;
2145 CatCInProgress in_progress_ent;
2146
2147 /*
2148 * The tuple could become stale while we are doing toast table
2149 * access (since AcceptInvalidationMessages can run then). The
2150 * invalidation will mark our in-progress entry as dead.
2151 */
2152 save_in_progress = catcache_in_progress_stack;
2153 in_progress_ent.next = catcache_in_progress_stack;
2154 in_progress_ent.cache = cache;
2155 in_progress_ent.hash_value = hashValue;
2156 in_progress_ent.list = false;
2157 in_progress_ent.dead = false;
2158 catcache_in_progress_stack = &in_progress_ent;
2159
2160 PG_TRY();
2161 {
2162 dtp = toast_flatten_tuple(ntp, cache->cc_tupdesc);
2163 }
2164 PG_FINALLY();
2165 {
2166 Assert(catcache_in_progress_stack == &in_progress_ent);
2167 catcache_in_progress_stack = save_in_progress;
2168 }
2169 PG_END_TRY();
2170
2171 if (in_progress_ent.dead)
2172 {
2173 heap_freetuple(dtp);
2174 return NULL;
2175 }
2176 }
2177 else
2178 dtp = ntp;
2179
2180 /* Allocate memory for CatCTup and the cached tuple in one go */
2182
2183 ct = (CatCTup *) palloc(sizeof(CatCTup) +
2184 MAXIMUM_ALIGNOF + dtp->t_len);
2185 ct->tuple.t_len = dtp->t_len;
2186 ct->tuple.t_self = dtp->t_self;
2187 ct->tuple.t_tableOid = dtp->t_tableOid;
2189 MAXALIGN(((char *) ct) + sizeof(CatCTup));
2190 /* copy tuple contents */
2191 memcpy((char *) ct->tuple.t_data,
2192 (const char *) dtp->t_data,
2193 dtp->t_len);
2194 MemoryContextSwitchTo(oldcxt);
2195
2196 if (dtp != ntp)
2197 heap_freetuple(dtp);
2198
2199 /* extract keys - they'll point into the tuple if not by-value */
2200 for (i = 0; i < cache->cc_nkeys; i++)
2201 {
2202 Datum atp;
2203 bool isnull;
2204
2205 atp = heap_getattr(&ct->tuple,
2206 cache->cc_keyno[i],
2207 cache->cc_tupdesc,
2208 &isnull);
2209 Assert(!isnull);
2210 ct->keys[i] = atp;
2211 }
2212 }
2213 else
2214 {
2215 /* Set up keys for a negative cache entry */
2217 ct = (CatCTup *) palloc(sizeof(CatCTup));
2218
2219 /*
2220 * Store keys - they'll point into separately allocated memory if not
2221 * by-value.
2222 */
2223 CatCacheCopyKeys(cache->cc_tupdesc, cache->cc_nkeys, cache->cc_keyno,
2224 arguments, ct->keys);
2225 MemoryContextSwitchTo(oldcxt);
2226 }
2227
2228 /*
2229 * Finish initializing the CatCTup header, and add it to the cache's
2230 * linked list and counts.
2231 */
2232 ct->ct_magic = CT_MAGIC;
2233 ct->my_cache = cache;
2234 ct->c_list = NULL;
2235 ct->refcount = 0; /* for the moment */
2236 ct->dead = false;
2237 ct->negative = (ntp == NULL);
2238 ct->hash_value = hashValue;
2239
2240 dlist_push_head(&cache->cc_bucket[hashIndex], &ct->cache_elem);
2241
2242 cache->cc_ntup++;
2243 CacheHdr->ch_ntup++;
2244
2245 /*
2246 * If the hash table has become too full, enlarge the buckets array. Quite
2247 * arbitrarily, we enlarge when fill factor > 2.
2248 */
2249 if (cache->cc_ntup > cache->cc_nbuckets * 2)
2250 RehashCatCache(cache);
2251
2252 return ct;
2253}
#define MAXALIGN(LEN)
Definition: c.h:782
#define PG_UINT32_MAX
Definition: c.h:561
static CatCInProgress * catcache_in_progress_stack
Definition: catcache.c:61
static void RehashCatCache(CatCache *cp)
Definition: catcache.c:985
static void CatCacheCopyKeys(TupleDesc tupdesc, int nkeys, int *attnos, Datum *srckeys, Datum *dstkeys)
Definition: catcache.c:2284
static CatCacheHeader * CacheHdr
Definition: catcache.c:84
#define CT_MAGIC
Definition: catcache.h:91
#define PG_TRY(...)
Definition: elog.h:372
#define PG_END_TRY(...)
Definition: elog.h:397
#define PG_FINALLY(...)
Definition: elog.h:389
HeapTuple toast_flatten_tuple(HeapTuple tup, TupleDesc tupleDesc)
Definition: heaptoast.c:350
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1435
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:904
static bool HeapTupleHasExternal(const HeapTupleData *tuple)
Definition: htup_details.h:762
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:347
void * palloc(Size size)
Definition: mcxt.c:1940
MemoryContext CacheMemoryContext
Definition: mcxt.c:168
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
uint32 pg_prng_uint32(pg_prng_state *state)
Definition: pg_prng.c:227
pg_prng_state pg_global_prng_state
Definition: pg_prng.c:34
uint32 hash_value
Definition: catcache.c:55
struct CatCInProgress * next
Definition: catcache.c:58
CatCache * cache
Definition: catcache.c:54
ItemPointerData t_self
Definition: htup.h:65
uint32 t_len
Definition: htup.h:64
HeapTupleHeader t_data
Definition: htup.h:68
Oid t_tableOid
Definition: htup.h:66
dlist_head * cc_bucket
Definition: catcache.h:49
int cc_nkeys
Definition: catcache.h:54
int cc_nbuckets
Definition: catcache.h:47
int cc_ntup
Definition: catcache.h:55
int ct_magic
Definition: catcache.h:90
int refcount
Definition: catcache.h:120
bool negative
Definition: catcache.h:122
dlist_node cache_elem
Definition: catcache.h:106
HeapTupleData tuple
Definition: catcache.h:123
CatCache * my_cache
Definition: catcache.h:134
struct catclist * c_list
Definition: catcache.h:132
Datum keys[CATCACHE_MAXKEYS]
Definition: catcache.h:99
bool dead
Definition: catcache.h:121
uint32 hash_value
Definition: catcache.h:93

References Assert(), catctup::c_list, CatCInProgress::cache, catctup::cache_elem, CacheHdr, CacheMemoryContext, catcache_in_progress_stack, 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, CatCInProgress::dead, catctup::dead, dlist_push_head(), CatCInProgress::hash_value, catctup::hash_value, heap_freetuple(), heap_getattr(), HeapTupleHasExternal(), i, catctup::keys, CatCInProgress::list, MAXALIGN, MemoryContextSwitchTo(), catctup::my_cache, catctup::negative, CatCInProgress::next, palloc(), PG_END_TRY, PG_FINALLY, pg_global_prng_state, pg_prng_uint32(), PG_TRY, PG_UINT32_MAX, 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 834 of file catcache.c.

835{
836 slist_iter iter;
837
838 CACHE_elog(DEBUG2, "CatalogCacheFlushCatalog called for %u", catId);
839
841 {
842 CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
843
844 /* Does this cache store tuples of the target catalog? */
845 if (cache->cc_reloid == catId)
846 {
847 /* Yes, so flush all its contents */
848 ResetCatalogCache(cache, false);
849
850 /* Tell inval.c to call syscache callbacks for this cache */
851 CallSyscacheCallbacks(cache->id, 0);
852 }
853 }
854
855 CACHE_elog(DEBUG2, "end of CatalogCacheFlushCatalog call");
856}
static void ResetCatalogCache(CatCache *cache, bool debug_discard)
Definition: catcache.c:736
#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:1884
Oid cc_reloid
Definition: catcache.h:60
int id
Definition: catcache.h:46
slist_head ch_caches
Definition: catcache.h:186
slist_node * cur
Definition: ilist.h:259

References CatCInProgress::cache, 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 1086 of file catcache.c.

1087{
1088 Relation relation;
1089 MemoryContext oldcxt;
1090 TupleDesc tupdesc;
1091 int i;
1092
1094
1095 relation = table_open(cache->cc_reloid, AccessShareLock);
1096
1097 /*
1098 * switch to the cache context so our allocations do not vanish at the end
1099 * of a transaction
1100 */
1101 Assert(CacheMemoryContext != NULL);
1102
1104
1105 /*
1106 * copy the relcache's tuple descriptor to permanent cache storage
1107 */
1108 tupdesc = CreateTupleDescCopyConstr(RelationGetDescr(relation));
1109
1110 /*
1111 * save the relation's name and relisshared flag, too (cc_relname is used
1112 * only for debugging purposes)
1113 */
1114 cache->cc_relname = pstrdup(RelationGetRelationName(relation));
1115 cache->cc_relisshared = RelationGetForm(relation)->relisshared;
1116
1117 /*
1118 * return to the caller's memory context and close the rel
1119 */
1120 MemoryContextSwitchTo(oldcxt);
1121
1122 table_close(relation, AccessShareLock);
1123
1124 CACHE_elog(DEBUG2, "CatalogCacheInitializeCache: %s, %d keys",
1125 cache->cc_relname, cache->cc_nkeys);
1126
1127 /*
1128 * initialize cache's key information
1129 */
1130 for (i = 0; i < cache->cc_nkeys; ++i)
1131 {
1132 Oid keytype;
1133 RegProcedure eqfunc;
1134
1136
1137 if (cache->cc_keyno[i] > 0)
1138 {
1139 Form_pg_attribute attr = TupleDescAttr(tupdesc,
1140 cache->cc_keyno[i] - 1);
1141
1142 keytype = attr->atttypid;
1143 /* cache key columns should always be NOT NULL */
1144 Assert(attr->attnotnull);
1145 }
1146 else
1147 {
1148 if (cache->cc_keyno[i] < 0)
1149 elog(FATAL, "sys attributes are not supported in caches");
1150 keytype = OIDOID;
1151 }
1152
1153 GetCCHashEqFuncs(keytype,
1154 &cache->cc_hashfunc[i],
1155 &eqfunc,
1156 &cache->cc_fastequal[i]);
1157
1158 /*
1159 * Do equality-function lookup (we assume this won't need a catalog
1160 * lookup for any supported type)
1161 */
1162 fmgr_info_cxt(eqfunc,
1163 &cache->cc_skey[i].sk_func,
1165
1166 /* Initialize sk_attno suitably for HeapKeyTest() and heap scans */
1167 cache->cc_skey[i].sk_attno = cache->cc_keyno[i];
1168
1169 /* Fill in sk_strategy as well --- always standard equality */
1171 cache->cc_skey[i].sk_subtype = InvalidOid;
1172 /* If a catcache key requires a collation, it must be C collation */
1173 cache->cc_skey[i].sk_collation = C_COLLATION_OID;
1174
1175 CACHE_elog(DEBUG2, "CatalogCacheInitializeCache %s %d %p",
1176 cache->cc_relname, i, cache);
1177 }
1178
1179 /*
1180 * mark this cache fully initialized
1181 */
1182 cache->cc_tupdesc = tupdesc;
1183}
regproc RegProcedure
Definition: c.h:621
#define CatalogCacheInitializeCache_DEBUG1
Definition: catcache.c:1081
static void GetCCHashEqFuncs(Oid keytype, CCHashFN *hashfunc, RegProcedure *eqfunc, CCFastEqualFN *fasteqfunc)
Definition: catcache.c:274
#define CatalogCacheInitializeCache_DEBUG2
Definition: catcache.c:1082
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:2322
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:202
#define InvalidOid
Definition: postgres_ext.h:35
unsigned int Oid
Definition: postgres_ext.h:30
#define RelationGetForm(relation)
Definition: rel.h:510
#define RelationGetDescr(relation)
Definition: rel.h:542
#define RelationGetRelationName(relation)
Definition: rel.h:550
#define BTEqualStrategyNumber
Definition: stratnum.h:31
FmgrInfo sk_func
Definition: skey.h:71
Oid sk_subtype
Definition: skey.h:69
Oid sk_collation
Definition: skey.h:70
StrategyNumber sk_strategy
Definition: skey.h:68
AttrNumber sk_attno
Definition: skey.h:67
bool cc_relisshared
Definition: catcache.h:62
ScanKeyData cc_skey[CATCACHE_MAXKEYS]
Definition: catcache.h:64
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc)
Definition: tupdesc.c:333
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition: tupdesc.h:160

References AccessShareLock, Assert(), BTEqualStrategyNumber, CatCInProgress::cache, 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 2284 of file catcache.c.

2286{
2287 int i;
2288
2289 /*
2290 * XXX: memory and lookup performance could possibly be improved by
2291 * storing all keys in one allocation.
2292 */
2293
2294 for (i = 0; i < nkeys; i++)
2295 {
2296 int attnum = attnos[i];
2297 Form_pg_attribute att = TupleDescAttr(tupdesc, attnum - 1);
2298 Datum src = srckeys[i];
2299 NameData srcname;
2300
2301 /*
2302 * Must be careful in case the caller passed a C string where a NAME
2303 * is wanted: convert the given argument to a correctly padded NAME.
2304 * Otherwise the memcpy() done by datumCopy() could fall off the end
2305 * of memory.
2306 */
2307 if (att->atttypid == NAMEOID)
2308 {
2309 namestrcpy(&srcname, DatumGetCString(src));
2310 src = NameGetDatum(&srcname);
2311 }
2312
2313 dstkeys[i] = datumCopy(src,
2314 att->attbyval,
2315 att->attlen);
2316 }
2317}
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:340
static Datum NameGetDatum(const NameData *X)
Definition: postgres.h:378
Definition: c.h:712

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

2260{
2261 int i;
2262
2263 for (i = 0; i < nkeys; i++)
2264 {
2265 int attnum = attnos[i];
2267
2268 /* system attribute are not supported in caches */
2269 Assert(attnum > 0);
2270
2271 att = TupleDescAttr(tupdesc, attnum - 1);
2272
2273 if (!att->attbyval)
2274 pfree(DatumGetPointer(keys[i]));
2275 }
2276}
void pfree(void *pointer)
Definition: mcxt.c:2147
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:317

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

Referenced by CatCacheRemoveCList(), and CatCacheRemoveCTup().

◆ CatCacheInvalidate()

void CatCacheInvalidate ( CatCache cache,
uint32  hashValue 
)

Definition at line 625 of file catcache.c.

626{
627 Index hashIndex;
629
630 CACHE_elog(DEBUG2, "CatCacheInvalidate: called");
631
632 /*
633 * We don't bother to check whether the cache has finished initialization
634 * yet; if not, there will be no entries in it so no problem.
635 */
636
637 /*
638 * Invalidate *all* CatCLists in this cache; it's too hard to tell which
639 * searches might still be correct, so just zap 'em all.
640 */
641 for (int i = 0; i < cache->cc_nlbuckets; i++)
642 {
643 dlist_head *bucket = &cache->cc_lbucket[i];
644
645 dlist_foreach_modify(iter, bucket)
646 {
647 CatCList *cl = dlist_container(CatCList, cache_elem, iter.cur);
648
649 if (cl->refcount > 0)
650 cl->dead = true;
651 else
652 CatCacheRemoveCList(cache, cl);
653 }
654 }
655
656 /*
657 * inspect the proper hash bucket for tuple matches
658 */
659 hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
660 dlist_foreach_modify(iter, &cache->cc_bucket[hashIndex])
661 {
662 CatCTup *ct = dlist_container(CatCTup, cache_elem, iter.cur);
663
664 if (hashValue == ct->hash_value)
665 {
666 if (ct->refcount > 0 ||
667 (ct->c_list && ct->c_list->refcount > 0))
668 {
669 ct->dead = true;
670 /* list, if any, was marked dead above */
671 Assert(ct->c_list == NULL || ct->c_list->dead);
672 }
673 else
674 CatCacheRemoveCTup(cache, ct);
675 CACHE_elog(DEBUG2, "CatCacheInvalidate: invalidated");
676#ifdef CATCACHE_STATS
677 cache->cc_invals++;
678#endif
679 /* could be multiple matches, so keep looking! */
680 }
681 }
682
683 /* Also invalidate any entries that are being built */
684 for (CatCInProgress *e = catcache_in_progress_stack; e != NULL; e = e->next)
685 {
686 if (e->cache == cache)
687 {
688 if (e->list || e->hash_value == hashValue)
689 e->dead = true;
690 }
691 }
692}
unsigned int Index
Definition: c.h:585
static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
Definition: catcache.c:528
static void CatCacheRemoveCList(CatCache *cache, CatCList *cl)
Definition: catcache.c:570
#define HASH_INDEX(h, sz)
Definition: catcache.c:70
#define dlist_foreach_modify(iter, lhead)
Definition: ilist.h:640
#define dlist_container(type, membername, ptr)
Definition: ilist.h:593
e
Definition: preproc-init.c:82
int cc_nlbuckets
Definition: catcache.h:57
dlist_head * cc_lbucket
Definition: catcache.h:58
int refcount
Definition: catcache.h:174
bool dead
Definition: catcache.h:175
dlist_node * cur
Definition: ilist.h:200

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

Referenced by SysCacheInvalidate().

◆ CatCacheRemoveCList()

static void CatCacheRemoveCList ( CatCache cache,
CatCList cl 
)
static

Definition at line 570 of file catcache.c.

571{
572 int i;
573
574 Assert(cl->refcount == 0);
575 Assert(cl->my_cache == cache);
576
577 /* delink from member tuples */
578 for (i = cl->n_members; --i >= 0;)
579 {
580 CatCTup *ct = cl->members[i];
581
582 Assert(ct->c_list == cl);
583 ct->c_list = NULL;
584 /* if the member is dead and now has no references, remove it */
585 if (
586#ifndef CATCACHE_FORCE_RELEASE
587 ct->dead &&
588#endif
589 ct->refcount == 0)
590 CatCacheRemoveCTup(cache, ct);
591 }
592
593 /* delink from linked list */
595
596 /* free associated column data */
598 cache->cc_keyno, cl->keys);
599
600 pfree(cl);
601
602 --cache->cc_nlist;
603}
static void CatCacheFreeKeys(TupleDesc tupdesc, int nkeys, int *attnos, Datum *keys)
Definition: catcache.c:2259
static void dlist_delete(dlist_node *node)
Definition: ilist.h:405
int cc_nlist
Definition: catcache.h:56
dlist_node cache_elem
Definition: catcache.h:166
CatCache * my_cache
Definition: catcache.h:179
short nkeys
Definition: catcache.h:177
Datum keys[CATCACHE_MAXKEYS]
Definition: catcache.h:172
CatCTup * members[FLEXIBLE_ARRAY_MEMBER]
Definition: catcache.h:180
int n_members
Definition: catcache.h:178

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

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

◆ CatCacheRemoveCTup()

static void CatCacheRemoveCTup ( CatCache cache,
CatCTup ct 
)
static

Definition at line 528 of file catcache.c.

529{
530 Assert(ct->refcount == 0);
531 Assert(ct->my_cache == cache);
532
533 if (ct->c_list)
534 {
535 /*
536 * The cleanest way to handle this is to call CatCacheRemoveCList,
537 * which will recurse back to me, and the recursive call will do the
538 * work. Set the "dead" flag to make sure it does recurse.
539 */
540 ct->dead = true;
541 CatCacheRemoveCList(cache, ct->c_list);
542 return; /* nothing left to do */
543 }
544
545 /* delink from linked list */
547
548 /*
549 * Free keys when we're dealing with a negative entry, normal entries just
550 * point into tuple, allocated together with the CatCTup.
551 */
552 if (ct->negative)
553 CatCacheFreeKeys(cache->cc_tupdesc, cache->cc_nkeys,
554 cache->cc_keyno, ct->keys);
555
556 pfree(ct);
557
558 --cache->cc_ntup;
559 --CacheHdr->ch_ntup;
560}

References Assert(), catctup::c_list, CatCInProgress::cache, 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 191 of file catcache.c.

192{
193 return DatumGetChar(a) == DatumGetChar(b);
194}
int b
Definition: isn.c:74
int a
Definition: isn.c:73
static char DatumGetChar(Datum X)
Definition: postgres.h:117

References a, b, and DatumGetChar().

Referenced by GetCCHashEqFuncs().

◆ charhashfast()

static uint32 charhashfast ( Datum  datum)
static

Definition at line 197 of file catcache.c.

198{
199 return murmurhash32((int32) DatumGetChar(datum));
200}
int32_t int32
Definition: c.h:498
static uint32 murmurhash32(uint32 data)
Definition: hashfn.h:92

References DatumGetChar(), and murmurhash32().

Referenced by GetCCHashEqFuncs().

◆ CreateCacheMemoryContext()

void CreateCacheMemoryContext ( void  )

Definition at line 708 of file catcache.c.

709{
710 /*
711 * Purely for paranoia, check that context doesn't exist; caller probably
712 * did so already.
713 */
716 "CacheMemoryContext",
718}
MemoryContext TopMemoryContext
Definition: mcxt.c:165
#define AllocSetContextCreate
Definition: memutils.h:149
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:180

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

1667{
1668 /*
1669 * one-time startup overhead for each cache
1670 */
1671 if (cache->cc_tupdesc == NULL)
1673
1674 /*
1675 * calculate the hash value
1676 */
1677 return CatalogCacheComputeHashValue(cache, cache->cc_nkeys, v1, v2, v3, v4);
1678}
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:1086

References CatCInProgress::cache, 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 274 of file catcache.c.

275{
276 switch (keytype)
277 {
278 case BOOLOID:
279 *hashfunc = charhashfast;
280 *fasteqfunc = chareqfast;
281 *eqfunc = F_BOOLEQ;
282 break;
283 case CHAROID:
284 *hashfunc = charhashfast;
285 *fasteqfunc = chareqfast;
286 *eqfunc = F_CHAREQ;
287 break;
288 case NAMEOID:
289 *hashfunc = namehashfast;
290 *fasteqfunc = nameeqfast;
291 *eqfunc = F_NAMEEQ;
292 break;
293 case INT2OID:
294 *hashfunc = int2hashfast;
295 *fasteqfunc = int2eqfast;
296 *eqfunc = F_INT2EQ;
297 break;
298 case INT4OID:
299 *hashfunc = int4hashfast;
300 *fasteqfunc = int4eqfast;
301 *eqfunc = F_INT4EQ;
302 break;
303 case TEXTOID:
304 *hashfunc = texthashfast;
305 *fasteqfunc = texteqfast;
306 *eqfunc = F_TEXTEQ;
307 break;
308 case OIDOID:
309 case REGPROCOID:
310 case REGPROCEDUREOID:
311 case REGOPEROID:
312 case REGOPERATOROID:
313 case REGCLASSOID:
314 case REGTYPEOID:
315 case REGCOLLATIONOID:
316 case REGCONFIGOID:
317 case REGDICTIONARYOID:
318 case REGROLEOID:
319 case REGNAMESPACEOID:
320 *hashfunc = int4hashfast;
321 *fasteqfunc = int4eqfast;
322 *eqfunc = F_OIDEQ;
323 break;
324 case OIDVECTOROID:
325 *hashfunc = oidvectorhashfast;
326 *fasteqfunc = oidvectoreqfast;
327 *eqfunc = F_OIDVECTOREQ;
328 break;
329 default:
330 elog(FATAL, "type %u not supported as catcache key", keytype);
331 *hashfunc = NULL; /* keep compiler quiet */
332
333 *eqfunc = InvalidOid;
334 break;
335 }
336}
static bool chareqfast(Datum a, Datum b)
Definition: catcache.c:191
static bool int4eqfast(Datum a, Datum b)
Definition: catcache.c:232
static bool int2eqfast(Datum a, Datum b)
Definition: catcache.c:220
static uint32 int4hashfast(Datum datum)
Definition: catcache.c:238
static uint32 namehashfast(Datum datum)
Definition: catcache.c:212
static bool nameeqfast(Datum a, Datum b)
Definition: catcache.c:203
static uint32 charhashfast(Datum datum)
Definition: catcache.c:197
static uint32 oidvectorhashfast(Datum datum)
Definition: catcache.c:267
static bool texteqfast(Datum a, Datum b)
Definition: catcache.c:244
static bool oidvectoreqfast(Datum a, Datum b)
Definition: catcache.c:261
static uint32 int2hashfast(Datum datum)
Definition: catcache.c:226
static uint32 texthashfast(Datum datum)
Definition: catcache.c:254

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

Referenced by CatalogCacheInitializeCache().

◆ IndexScanOK()

static bool IndexScanOK ( CatCache cache)
static

Definition at line 1247 of file catcache.c.

1248{
1249 switch (cache->id)
1250 {
1251 case INDEXRELID:
1252
1253 /*
1254 * Rather than tracking exactly which indexes have to be loaded
1255 * before we can use indexscans (which changes from time to time),
1256 * just force all pg_index searches to be heap scans until we've
1257 * built the critical relcaches.
1258 */
1260 return false;
1261 break;
1262
1263 case AMOID:
1264 case AMNAME:
1265
1266 /*
1267 * Always do heap scans in pg_am, because it's so small there's
1268 * not much point in an indexscan anyway. We *must* do this when
1269 * initially building critical relcache entries, but we might as
1270 * well just always do it.
1271 */
1272 return false;
1273
1274 case AUTHNAME:
1275 case AUTHOID:
1276 case AUTHMEMMEMROLE:
1277 case DATABASEOID:
1278
1279 /*
1280 * Protect authentication lookups occurring before relcache has
1281 * collected entries for shared indexes.
1282 */
1284 return false;
1285 break;
1286
1287 default:
1288 break;
1289 }
1290
1291 /* Normal case, allow index scan */
1292 return true;
1293}
bool criticalRelcachesBuilt
Definition: relcache.c:140
bool criticalSharedRelcachesBuilt
Definition: relcache.c:146

References CatCInProgress::cache, 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 878 of file catcache.c.

884{
885 CatCache *cp;
886 MemoryContext oldcxt;
887 int i;
888
889 /*
890 * nbuckets is the initial number of hash buckets to use in this catcache.
891 * It will be enlarged later if it becomes too full.
892 *
893 * nbuckets must be a power of two. We check this via Assert rather than
894 * a full runtime check because the values will be coming from constant
895 * tables.
896 *
897 * If you're confused by the power-of-two check, see comments in
898 * bitmapset.c for an explanation.
899 */
900 Assert(nbuckets > 0 && (nbuckets & -nbuckets) == nbuckets);
901
902 /*
903 * first switch to the cache context so our allocations do not vanish at
904 * the end of a transaction
905 */
908
910
911 /*
912 * if first time through, initialize the cache group header
913 */
914 if (CacheHdr == NULL)
915 {
918 CacheHdr->ch_ntup = 0;
919#ifdef CATCACHE_STATS
920 /* set up to dump stats at backend exit */
921 on_proc_exit(CatCachePrintStats, 0);
922#endif
923 }
924
925 /*
926 * Allocate a new cache structure, aligning to a cacheline boundary
927 *
928 * Note: we rely on zeroing to initialize all the dlist headers correctly
929 */
932 cp->cc_bucket = palloc0(nbuckets * sizeof(dlist_head));
933
934 /*
935 * Many catcaches never receive any list searches. Therefore, we don't
936 * allocate the cc_lbuckets till we get a list search.
937 */
938 cp->cc_lbucket = NULL;
939
940 /*
941 * initialize the cache's relation information for the relation
942 * corresponding to this cache, and initialize some of the new cache's
943 * other internal fields. But don't open the relation yet.
944 */
945 cp->id = id;
946 cp->cc_relname = "(not known yet)";
947 cp->cc_reloid = reloid;
948 cp->cc_indexoid = indexoid;
949 cp->cc_relisshared = false; /* temporary */
950 cp->cc_tupdesc = (TupleDesc) NULL;
951 cp->cc_ntup = 0;
952 cp->cc_nlist = 0;
953 cp->cc_nbuckets = nbuckets;
954 cp->cc_nlbuckets = 0;
955 cp->cc_nkeys = nkeys;
956 for (i = 0; i < nkeys; ++i)
957 {
959 cp->cc_keyno[i] = key[i];
960 }
961
962 /*
963 * new cache is initialized as far as we can go for now. print some
964 * debugging information, if appropriate.
965 */
967
968 /*
969 * add completed cache to top of group header's list
970 */
972
973 /*
974 * back to the old context before we return...
975 */
976 MemoryContextSwitchTo(oldcxt);
977
978 return cp;
979}
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
void CreateCacheMemoryContext(void)
Definition: catcache.c:708
#define InitCatCache_DEBUG2
Definition: catcache.c:874
#define MCXT_ALLOC_ZERO
Definition: fe_memutils.h:30
static void slist_init(slist_head *head)
Definition: ilist.h:986
static void slist_push_head(slist_head *head, slist_node *node)
Definition: ilist.h:1006
void on_proc_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:309
void * palloc0(Size size)
Definition: mcxt.c:1970
void * palloc_aligned(Size size, Size alignto, int flags)
Definition: mcxt.c:2137
#define PG_CACHE_LINE_SIZE
slist_node cc_next
Definition: catcache.h:63
Oid cc_indexoid
Definition: catcache.h:61
struct TupleDescData * TupleDesc
Definition: tupdesc.h:145

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

Referenced by InitCatalogCache().

◆ InitCatCachePhase2()

void InitCatCachePhase2 ( CatCache cache,
bool  touch_index 
)

Definition at line 1195 of file catcache.c.

1196{
1197 if (cache->cc_tupdesc == NULL)
1199
1200 if (touch_index &&
1201 cache->id != AMOID &&
1202 cache->id != AMNAME)
1203 {
1204 Relation idesc;
1205
1206 /*
1207 * We must lock the underlying catalog before opening the index to
1208 * avoid deadlock, since index_open could possibly result in reading
1209 * this same catalog, and if anyone else is exclusive-locking this
1210 * catalog and index they'll be doing it in that order.
1211 */
1213 idesc = index_open(cache->cc_indexoid, AccessShareLock);
1214
1215 /*
1216 * While we've got the index open, let's check that it's unique (and
1217 * not just deferrable-unique, thank you very much). This is just to
1218 * catch thinkos in definitions of new catcaches, so we don't worry
1219 * about the pg_am indexes not getting tested.
1220 */
1221 Assert(idesc->rd_index->indisunique &&
1222 idesc->rd_index->indimmediate);
1223
1226 }
1227}
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:229
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:107
Form_pg_index rd_index
Definition: rel.h:192

References AccessShareLock, Assert(), CatCInProgress::cache, 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 220 of file catcache.c.

221{
222 return DatumGetInt16(a) == DatumGetInt16(b);
223}
static int16 DatumGetInt16(Datum X)
Definition: postgres.h:167

References a, b, and DatumGetInt16().

Referenced by GetCCHashEqFuncs().

◆ int2hashfast()

static uint32 int2hashfast ( Datum  datum)
static

Definition at line 226 of file catcache.c.

227{
228 return murmurhash32((int32) DatumGetInt16(datum));
229}

References DatumGetInt16(), and murmurhash32().

Referenced by GetCCHashEqFuncs().

◆ int4eqfast()

static bool int4eqfast ( Datum  a,
Datum  b 
)
static

Definition at line 232 of file catcache.c.

233{
234 return DatumGetInt32(a) == DatumGetInt32(b);
235}
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:207

References a, b, and DatumGetInt32().

Referenced by GetCCHashEqFuncs().

◆ int4hashfast()

static uint32 int4hashfast ( Datum  datum)
static

Definition at line 238 of file catcache.c.

239{
240 return murmurhash32((int32) DatumGetInt32(datum));
241}

References DatumGetInt32(), and murmurhash32().

Referenced by GetCCHashEqFuncs().

◆ nameeqfast()

static bool nameeqfast ( Datum  a,
Datum  b 
)
static

Definition at line 203 of file catcache.c.

204{
205 char *ca = NameStr(*DatumGetName(a));
206 char *cb = NameStr(*DatumGetName(b));
207
208 return strncmp(ca, cb, NAMEDATALEN) == 0;
209}
#define NameStr(name)
Definition: c.h:717
#define NAMEDATALEN
static Name DatumGetName(Datum X)
Definition: postgres.h:365

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

Referenced by GetCCHashEqFuncs().

◆ namehashfast()

static uint32 namehashfast ( Datum  datum)
static

Definition at line 212 of file catcache.c.

213{
214 char *key = NameStr(*DatumGetName(datum));
215
216 return hash_any((unsigned char *) key, strlen(key));
217}
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 261 of file catcache.c.

262{
264}
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:684
Datum oidvectoreq(PG_FUNCTION_ARGS)
Definition: oid.c:344
static bool DatumGetBool(Datum X)
Definition: postgres.h:95

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

Referenced by GetCCHashEqFuncs().

◆ oidvectorhashfast()

static uint32 oidvectorhashfast ( Datum  datum)
static

Definition at line 267 of file catcache.c.

268{
270}
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:682
Datum hashoidvector(PG_FUNCTION_ARGS)
Definition: hashfunc.c:232

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

Referenced by GetCCHashEqFuncs().

◆ PrepareToInvalidateCacheTuple()

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

Definition at line 2354 of file catcache.c.

2359{
2360 slist_iter iter;
2361 Oid reloid;
2362
2363 CACHE_elog(DEBUG2, "PrepareToInvalidateCacheTuple: called");
2364
2365 /*
2366 * sanity checks
2367 */
2368 Assert(RelationIsValid(relation));
2369 Assert(HeapTupleIsValid(tuple));
2371 Assert(CacheHdr != NULL);
2372
2373 reloid = RelationGetRelid(relation);
2374
2375 /* ----------------
2376 * for each cache
2377 * if the cache contains tuples from the specified relation
2378 * compute the tuple's hash value(s) in this cache,
2379 * and call the passed function to register the information.
2380 * ----------------
2381 */
2382
2384 {
2385 CatCache *ccp = slist_container(CatCache, cc_next, iter.cur);
2386 uint32 hashvalue;
2387 Oid dbid;
2388
2389 if (ccp->cc_reloid != reloid)
2390 continue;
2391
2392 /* Just in case cache hasn't finished initialization yet... */
2393 if (ccp->cc_tupdesc == NULL)
2395
2396 hashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, tuple);
2397 dbid = ccp->cc_relisshared ? (Oid) 0 : MyDatabaseId;
2398
2399 (*function) (ccp->id, hashvalue, dbid, context);
2400
2401 if (newtuple)
2402 {
2403 uint32 newhashvalue;
2404
2405 newhashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, newtuple);
2406
2407 if (newhashvalue != hashvalue)
2408 (*function) (ccp->id, newhashvalue, dbid, context);
2409 }
2410 }
2411}
#define PointerIsValid(pointer)
Definition: c.h:734
static uint32 CatalogCacheComputeTupleHashValue(CatCache *cache, int nkeys, HeapTuple tuple)
Definition: catcache.c:386
Oid MyDatabaseId
Definition: globals.c:95
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
on_exit_nicely_callback function
#define RelationGetRelid(relation)
Definition: rel.h:516
#define RelationIsValid(relation)
Definition: rel.h:489

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, function, HeapTupleIsValid, catcache::id, MyDatabaseId, PointerIsValid, RelationGetRelid, RelationIsValid, slist_container, and slist_foreach.

Referenced by CacheInvalidateHeapTupleCommon().

◆ RehashCatCache()

static void RehashCatCache ( CatCache cp)
static

Definition at line 985 of file catcache.c.

986{
987 dlist_head *newbucket;
988 int newnbuckets;
989 int i;
990
991 elog(DEBUG1, "rehashing catalog cache id %d for %s; %d tups, %d buckets",
992 cp->id, cp->cc_relname, cp->cc_ntup, cp->cc_nbuckets);
993
994 /* Allocate a new, larger, hash table. */
995 newnbuckets = cp->cc_nbuckets * 2;
996 newbucket = (dlist_head *) MemoryContextAllocZero(CacheMemoryContext, newnbuckets * sizeof(dlist_head));
997
998 /* Move all entries from old hash table to new. */
999 for (i = 0; i < cp->cc_nbuckets; i++)
1000 {
1001 dlist_mutable_iter iter;
1002
1003 dlist_foreach_modify(iter, &cp->cc_bucket[i])
1004 {
1005 CatCTup *ct = dlist_container(CatCTup, cache_elem, iter.cur);
1006 int hashIndex = HASH_INDEX(ct->hash_value, newnbuckets);
1007
1008 dlist_delete(iter.cur);
1009 dlist_push_head(&newbucket[hashIndex], &ct->cache_elem);
1010 }
1011 }
1012
1013 /* Switch to the new array. */
1014 pfree(cp->cc_bucket);
1015 cp->cc_nbuckets = newnbuckets;
1016 cp->cc_bucket = newbucket;
1017}
#define DEBUG1
Definition: elog.h:30
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1290

References catctup::cache_elem, CacheMemoryContext, catcache::cc_bucket, catcache::cc_nbuckets, catcache::cc_ntup, catcache::cc_relname, dlist_mutable_iter::cur, DEBUG1, dlist_container, dlist_delete(), dlist_foreach_modify, dlist_push_head(), elog, HASH_INDEX, catctup::hash_value, i, catcache::id, MemoryContextAllocZero(), and pfree().

Referenced by CatalogCacheCreateEntry().

◆ RehashCatCacheLists()

static void RehashCatCacheLists ( CatCache cp)
static

Definition at line 1023 of file catcache.c.

1024{
1025 dlist_head *newbucket;
1026 int newnbuckets;
1027 int i;
1028
1029 elog(DEBUG1, "rehashing catalog cache id %d for %s; %d lists, %d buckets",
1030 cp->id, cp->cc_relname, cp->cc_nlist, cp->cc_nlbuckets);
1031
1032 /* Allocate a new, larger, hash table. */
1033 newnbuckets = cp->cc_nlbuckets * 2;
1034 newbucket = (dlist_head *) MemoryContextAllocZero(CacheMemoryContext, newnbuckets * sizeof(dlist_head));
1035
1036 /* Move all entries from old hash table to new. */
1037 for (i = 0; i < cp->cc_nlbuckets; i++)
1038 {
1039 dlist_mutable_iter iter;
1040
1041 dlist_foreach_modify(iter, &cp->cc_lbucket[i])
1042 {
1043 CatCList *cl = dlist_container(CatCList, cache_elem, iter.cur);
1044 int hashIndex = HASH_INDEX(cl->hash_value, newnbuckets);
1045
1046 dlist_delete(iter.cur);
1047 dlist_push_head(&newbucket[hashIndex], &cl->cache_elem);
1048 }
1049 }
1050
1051 /* Switch to the new array. */
1052 pfree(cp->cc_lbucket);
1053 cp->cc_nlbuckets = newnbuckets;
1054 cp->cc_lbucket = newbucket;
1055}
uint32 hash_value
Definition: catcache.h:164

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

Referenced by SearchCatCacheList().

◆ ReleaseCatCache()

void ReleaseCatCache ( HeapTuple  tuple)

Definition at line 1623 of file catcache.c.

1624{
1626}
static void ReleaseCatCacheWithOwner(HeapTuple tuple, ResourceOwner resowner)
Definition: catcache.c:1629
ResourceOwner CurrentResourceOwner
Definition: resowner.c:173

References CurrentResourceOwner, and ReleaseCatCacheWithOwner().

Referenced by ReleaseSysCache().

◆ ReleaseCatCacheList()

◆ ReleaseCatCacheListWithOwner()

static void ReleaseCatCacheListWithOwner ( CatCList list,
ResourceOwner  resowner 
)
static

Definition at line 2077 of file catcache.c.

2078{
2079 /* Safety checks to ensure we were handed a cache entry */
2080 Assert(list->cl_magic == CL_MAGIC);
2081 Assert(list->refcount > 0);
2082 list->refcount--;
2083 if (resowner)
2085
2086 if (
2087#ifndef CATCACHE_FORCE_RELEASE
2088 list->dead &&
2089#endif
2090 list->refcount == 0)
2091 CatCacheRemoveCList(list->my_cache, list);
2092}
static void ResourceOwnerForgetCatCacheListRef(ResourceOwner owner, CatCList *list)
Definition: catcache.c:174
#define CL_MAGIC
Definition: catcache.h:162

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

Referenced by ReleaseCatCacheList(), and ResOwnerReleaseCatCacheList().

◆ ReleaseCatCacheWithOwner()

static void ReleaseCatCacheWithOwner ( HeapTuple  tuple,
ResourceOwner  resowner 
)
static

Definition at line 1629 of file catcache.c.

1630{
1631 CatCTup *ct = (CatCTup *) (((char *) tuple) -
1632 offsetof(CatCTup, tuple));
1633
1634 /* Safety checks to ensure we were handed a cache entry */
1635 Assert(ct->ct_magic == CT_MAGIC);
1636 Assert(ct->refcount > 0);
1637
1638 ct->refcount--;
1639 if (resowner)
1641
1642 if (
1643#ifndef CATCACHE_FORCE_RELEASE
1644 ct->dead &&
1645#endif
1646 ct->refcount == 0 &&
1647 (ct->c_list == NULL || ct->c_list->refcount == 0))
1649}
static void ResourceOwnerForgetCatCacheRef(ResourceOwner owner, HeapTuple tuple)
Definition: catcache.c:164

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,
bool  debug_discard 
)
static

Definition at line 736 of file catcache.c.

737{
739 int i;
740
741 /* Remove each list in this cache, or at least mark it dead */
742 for (i = 0; i < cache->cc_nlbuckets; i++)
743 {
744 dlist_head *bucket = &cache->cc_lbucket[i];
745
746 dlist_foreach_modify(iter, bucket)
747 {
748 CatCList *cl = dlist_container(CatCList, cache_elem, iter.cur);
749
750 if (cl->refcount > 0)
751 cl->dead = true;
752 else
753 CatCacheRemoveCList(cache, cl);
754 }
755 }
756
757 /* Remove each tuple in this cache, or at least mark it dead */
758 for (i = 0; i < cache->cc_nbuckets; i++)
759 {
760 dlist_head *bucket = &cache->cc_bucket[i];
761
762 dlist_foreach_modify(iter, bucket)
763 {
764 CatCTup *ct = dlist_container(CatCTup, cache_elem, iter.cur);
765
766 if (ct->refcount > 0 ||
767 (ct->c_list && ct->c_list->refcount > 0))
768 {
769 ct->dead = true;
770 /* list, if any, was marked dead above */
771 Assert(ct->c_list == NULL || ct->c_list->dead);
772 }
773 else
774 CatCacheRemoveCTup(cache, ct);
775#ifdef CATCACHE_STATS
776 cache->cc_invals++;
777#endif
778 }
779 }
780
781 /* Also invalidate any entries that are being built */
782 if (!debug_discard)
783 {
784 for (CatCInProgress *e = catcache_in_progress_stack; e != NULL; e = e->next)
785 {
786 if (e->cache == cache)
787 e->dead = true;
788 }
789 }
790}

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

Referenced by CatalogCacheFlushCatalog(), and ResetCatalogCachesExt().

◆ ResetCatalogCaches()

void ResetCatalogCaches ( void  )

Definition at line 798 of file catcache.c.

799{
801}
void ResetCatalogCachesExt(bool debug_discard)
Definition: catcache.c:804

References ResetCatalogCachesExt().

◆ ResetCatalogCachesExt()

void ResetCatalogCachesExt ( bool  debug_discard)

Definition at line 804 of file catcache.c.

805{
806 slist_iter iter;
807
808 CACHE_elog(DEBUG2, "ResetCatalogCaches called");
809
811 {
812 CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
813
814 ResetCatalogCache(cache, debug_discard);
815 }
816
817 CACHE_elog(DEBUG2, "end of ResetCatalogCaches call");
818}

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

Referenced by InvalidateSystemCachesExtended(), and ResetCatalogCaches().

◆ ResourceOwnerForgetCatCacheListRef()

static void ResourceOwnerForgetCatCacheListRef ( ResourceOwner  owner,
CatCList list 
)
inlinestatic

Definition at line 174 of file catcache.c.

175{
177}
static const ResourceOwnerDesc catlistref_resowner_desc
Definition: catcache.c:147
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:327
void ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:564

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

165{
167}
static const ResourceOwnerDesc catcache_resowner_desc
Definition: catcache.c:137

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

Referenced by ReleaseCatCacheWithOwner().

◆ ResourceOwnerRememberCatCacheListRef()

static void ResourceOwnerRememberCatCacheListRef ( ResourceOwner  owner,
CatCList list 
)
inlinestatic

Definition at line 169 of file catcache.c.

170{
172}
void ResourceOwnerRemember(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:524

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

2423{
2424 HeapTuple tuple = (HeapTuple) DatumGetPointer(res);
2425 CatCTup *ct = (CatCTup *) (((char *) tuple) -
2426 offsetof(CatCTup, tuple));
2427
2428 /* Safety check to ensure we were handed a cache entry */
2429 Assert(ct->ct_magic == CT_MAGIC);
2430
2431 return psprintf("cache %s (%d), tuple %u/%u has count %d",
2432 ct->my_cache->cc_relname, ct->my_cache->id,
2435 ct->refcount);
2436}
HeapTupleData * HeapTuple
Definition: htup.h:71
static OffsetNumber ItemPointerGetOffsetNumber(const ItemPointerData *pointer)
Definition: itemptr.h:124
static BlockNumber ItemPointerGetBlockNumber(const ItemPointerData *pointer)
Definition: itemptr.h:103
char * psprintf(const char *fmt,...)
Definition: psprintf.c:43

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

◆ ResOwnerPrintCatCacheList()

static char * ResOwnerPrintCatCacheList ( Datum  res)
static

Definition at line 2445 of file catcache.c.

2446{
2448
2449 return psprintf("cache %s (%d), list %p has count %d",
2450 list->my_cache->cc_relname, list->my_cache->id,
2451 list, list->refcount);
2452}

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

◆ ResOwnerReleaseCatCache()

static void ResOwnerReleaseCatCache ( Datum  res)
static

Definition at line 2416 of file catcache.c.

2417{
2419}

References DatumGetPointer(), and ReleaseCatCacheWithOwner().

◆ ResOwnerReleaseCatCacheList()

static void ResOwnerReleaseCatCacheList ( Datum  res)
static

Definition at line 2439 of file catcache.c.

2440{
2442}

References DatumGetPointer(), and ReleaseCatCacheListWithOwner().

◆ SearchCatCache()

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

Definition at line 1312 of file catcache.c.

1317{
1318 return SearchCatCacheInternal(cache, cache->cc_nkeys, v1, v2, v3, v4);
1319}
static HeapTuple SearchCatCacheInternal(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1363

References CatCInProgress::cache, catcache::cc_nkeys, and SearchCatCacheInternal().

Referenced by SearchSysCache().

◆ SearchCatCache1()

HeapTuple SearchCatCache1 ( CatCache cache,
Datum  v1 
)

Definition at line 1329 of file catcache.c.

1331{
1332 return SearchCatCacheInternal(cache, 1, v1, 0, 0, 0);
1333}

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache1().

◆ SearchCatCache2()

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

Definition at line 1337 of file catcache.c.

1339{
1340 return SearchCatCacheInternal(cache, 2, v1, v2, 0, 0);
1341}

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache2().

◆ SearchCatCache3()

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

Definition at line 1345 of file catcache.c.

1347{
1348 return SearchCatCacheInternal(cache, 3, v1, v2, v3, 0);
1349}

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache3().

◆ SearchCatCache4()

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

Definition at line 1353 of file catcache.c.

1355{
1356 return SearchCatCacheInternal(cache, 4, v1, v2, v3, v4);
1357}

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache4().

◆ SearchCatCacheInternal()

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

Definition at line 1363 of file catcache.c.

1369{
1371 uint32 hashValue;
1372 Index hashIndex;
1373 dlist_iter iter;
1374 dlist_head *bucket;
1375 CatCTup *ct;
1376
1377 /* Make sure we're in an xact, even if this ends up being a cache hit */
1379
1380 Assert(cache->cc_nkeys == nkeys);
1381
1382 /*
1383 * one-time startup overhead for each cache
1384 */
1385 if (unlikely(cache->cc_tupdesc == NULL))
1387
1388#ifdef CATCACHE_STATS
1389 cache->cc_searches++;
1390#endif
1391
1392 /* Initialize local parameter array */
1393 arguments[0] = v1;
1394 arguments[1] = v2;
1395 arguments[2] = v3;
1396 arguments[3] = v4;
1397
1398 /*
1399 * find the hash bucket in which to look for the tuple
1400 */
1401 hashValue = CatalogCacheComputeHashValue(cache, nkeys, v1, v2, v3, v4);
1402 hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
1403
1404 /*
1405 * scan the hash bucket until we find a match or exhaust our tuples
1406 *
1407 * Note: it's okay to use dlist_foreach here, even though we modify the
1408 * dlist within the loop, because we don't continue the loop afterwards.
1409 */
1410 bucket = &cache->cc_bucket[hashIndex];
1411 dlist_foreach(iter, bucket)
1412 {
1413 ct = dlist_container(CatCTup, cache_elem, iter.cur);
1414
1415 if (ct->dead)
1416 continue; /* ignore dead entries */
1417
1418 if (ct->hash_value != hashValue)
1419 continue; /* quickly skip entry if wrong hash val */
1420
1421 if (!CatalogCacheCompareTuple(cache, nkeys, ct->keys, arguments))
1422 continue;
1423
1424 /*
1425 * We found a match in the cache. Move it to the front of the list
1426 * for its hashbucket, in order to speed subsequent searches. (The
1427 * most frequently accessed elements in any hashbucket will tend to be
1428 * near the front of the hashbucket's list.)
1429 */
1430 dlist_move_head(bucket, &ct->cache_elem);
1431
1432 /*
1433 * If it's a positive entry, bump its refcount and return it. If it's
1434 * negative, we can report failure to the caller.
1435 */
1436 if (!ct->negative)
1437 {
1439 ct->refcount++;
1441
1442 CACHE_elog(DEBUG2, "SearchCatCache(%s): found in bucket %d",
1443 cache->cc_relname, hashIndex);
1444
1445#ifdef CATCACHE_STATS
1446 cache->cc_hits++;
1447#endif
1448
1449 return &ct->tuple;
1450 }
1451 else
1452 {
1453 CACHE_elog(DEBUG2, "SearchCatCache(%s): found neg entry in bucket %d",
1454 cache->cc_relname, hashIndex);
1455
1456#ifdef CATCACHE_STATS
1457 cache->cc_neg_hits++;
1458#endif
1459
1460 return NULL;
1461 }
1462 }
1463
1464 return SearchCatCacheMiss(cache, nkeys, hashValue, hashIndex, v1, v2, v3, v4);
1465}
#define unlikely(x)
Definition: c.h:347
static pg_noinline HeapTuple SearchCatCacheMiss(CatCache *cache, int nkeys, uint32 hashValue, Index hashIndex, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1475
static void ResourceOwnerRememberCatCacheRef(ResourceOwner owner, HeapTuple tuple)
Definition: catcache.c:159
static bool CatalogCacheCompareTuple(const CatCache *cache, int nkeys, const Datum *cachekeys, const Datum *searchkeys)
Definition: catcache.c:441
#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:452
dlist_node * cur
Definition: ilist.h:179
bool IsTransactionState(void)
Definition: xact.c:387

References Assert(), CatCInProgress::cache, 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 1696 of file catcache.c.

1701{
1702 Datum v4 = 0; /* dummy last-column value */
1704 uint32 lHashValue;
1705 Index lHashIndex;
1706 dlist_iter iter;
1707 dlist_head *lbucket;
1708 CatCList *cl;
1709 CatCTup *ct;
1710 List *volatile ctlist;
1711 ListCell *ctlist_item;
1712 int nmembers;
1713 bool ordered;
1714 HeapTuple ntp;
1715 MemoryContext oldcxt;
1716 int i;
1717 CatCInProgress *save_in_progress;
1718 CatCInProgress in_progress_ent;
1719
1720 /*
1721 * one-time startup overhead for each cache
1722 */
1723 if (unlikely(cache->cc_tupdesc == NULL))
1725
1726 Assert(nkeys > 0 && nkeys < cache->cc_nkeys);
1727
1728#ifdef CATCACHE_STATS
1729 cache->cc_lsearches++;
1730#endif
1731
1732 /* Initialize local parameter array */
1733 arguments[0] = v1;
1734 arguments[1] = v2;
1735 arguments[2] = v3;
1736 arguments[3] = v4;
1737
1738 /*
1739 * If we haven't previously done a list search in this cache, create the
1740 * bucket header array; otherwise, consider whether it's time to enlarge
1741 * it.
1742 */
1743 if (cache->cc_lbucket == NULL)
1744 {
1745 /* Arbitrary initial size --- must be a power of 2 */
1746 int nbuckets = 16;
1747
1748 cache->cc_lbucket = (dlist_head *)
1750 nbuckets * sizeof(dlist_head));
1751 /* Don't set cc_nlbuckets if we get OOM allocating cc_lbucket */
1752 cache->cc_nlbuckets = nbuckets;
1753 }
1754 else
1755 {
1756 /*
1757 * If the hash table has become too full, enlarge the buckets array.
1758 * Quite arbitrarily, we enlarge when fill factor > 2.
1759 */
1760 if (cache->cc_nlist > cache->cc_nlbuckets * 2)
1761 RehashCatCacheLists(cache);
1762 }
1763
1764 /*
1765 * Find the hash bucket in which to look for the CatCList.
1766 */
1767 lHashValue = CatalogCacheComputeHashValue(cache, nkeys, v1, v2, v3, v4);
1768 lHashIndex = HASH_INDEX(lHashValue, cache->cc_nlbuckets);
1769
1770 /*
1771 * scan the items until we find a match or exhaust our list
1772 *
1773 * Note: it's okay to use dlist_foreach here, even though we modify the
1774 * dlist within the loop, because we don't continue the loop afterwards.
1775 */
1776 lbucket = &cache->cc_lbucket[lHashIndex];
1777 dlist_foreach(iter, lbucket)
1778 {
1779 cl = dlist_container(CatCList, cache_elem, iter.cur);
1780
1781 if (cl->dead)
1782 continue; /* ignore dead entries */
1783
1784 if (cl->hash_value != lHashValue)
1785 continue; /* quickly skip entry if wrong hash val */
1786
1787 /*
1788 * see if the cached list matches our key.
1789 */
1790 if (cl->nkeys != nkeys)
1791 continue;
1792
1793 if (!CatalogCacheCompareTuple(cache, nkeys, cl->keys, arguments))
1794 continue;
1795
1796 /*
1797 * We found a matching list. Move the list to the front of the list
1798 * for its hashbucket, so as to speed subsequent searches. (We do not
1799 * move the members to the fronts of their hashbucket lists, however,
1800 * since there's no point in that unless they are searched for
1801 * individually.)
1802 */
1803 dlist_move_head(lbucket, &cl->cache_elem);
1804
1805 /* Bump the list's refcount and return it */
1807 cl->refcount++;
1809
1810 CACHE_elog(DEBUG2, "SearchCatCacheList(%s): found list",
1811 cache->cc_relname);
1812
1813#ifdef CATCACHE_STATS
1814 cache->cc_lhits++;
1815#endif
1816
1817 return cl;
1818 }
1819
1820 /*
1821 * List was not found in cache, so we have to build it by reading the
1822 * relation. For each matching tuple found in the relation, use an
1823 * existing cache entry if possible, else build a new one.
1824 *
1825 * We have to bump the member refcounts temporarily to ensure they won't
1826 * get dropped from the cache while loading other members. We use a PG_TRY
1827 * block to ensure we can undo those refcounts if we get an error before
1828 * we finish constructing the CatCList. ctlist must be valid throughout
1829 * the PG_TRY block.
1830 */
1831 ctlist = NIL;
1832
1833 /*
1834 * Cache invalidation can happen while we're building the list.
1835 * CatalogCacheCreateEntry() handles concurrent invalidation of individual
1836 * tuples, but it's also possible that a new entry is concurrently added
1837 * that should be part of the list we're building. Register an
1838 * "in-progress" entry that will receive the invalidation, until we have
1839 * built the final list entry.
1840 */
1841 save_in_progress = catcache_in_progress_stack;
1842 in_progress_ent.next = catcache_in_progress_stack;
1843 in_progress_ent.cache = cache;
1844 in_progress_ent.hash_value = lHashValue;
1845 in_progress_ent.list = true;
1846 in_progress_ent.dead = false;
1847 catcache_in_progress_stack = &in_progress_ent;
1848
1849 PG_TRY();
1850 {
1851 ScanKeyData cur_skey[CATCACHE_MAXKEYS];
1852 Relation relation;
1853 SysScanDesc scandesc;
1854 bool first_iter = true;
1855
1856 relation = table_open(cache->cc_reloid, AccessShareLock);
1857
1858 /*
1859 * Ok, need to make a lookup in the relation, copy the scankey and
1860 * fill out any per-call fields.
1861 */
1862 memcpy(cur_skey, cache->cc_skey, sizeof(ScanKeyData) * cache->cc_nkeys);
1863 cur_skey[0].sk_argument = v1;
1864 cur_skey[1].sk_argument = v2;
1865 cur_skey[2].sk_argument = v3;
1866 cur_skey[3].sk_argument = v4;
1867
1868 /*
1869 * Scan the table for matching entries. If an invalidation arrives
1870 * mid-build, we will loop back here to retry.
1871 */
1872 do
1873 {
1874 /*
1875 * If we are retrying, release refcounts on any items created on
1876 * the previous iteration. We dare not try to free them if
1877 * they're now unreferenced, since an error while doing that would
1878 * result in the PG_CATCH below doing extra refcount decrements.
1879 * Besides, we'll likely re-adopt those items in the next
1880 * iteration, so it's not worth complicating matters to try to get
1881 * rid of them.
1882 */
1883 foreach(ctlist_item, ctlist)
1884 {
1885 ct = (CatCTup *) lfirst(ctlist_item);
1886 Assert(ct->c_list == NULL);
1887 Assert(ct->refcount > 0);
1888 ct->refcount--;
1889 }
1890 /* Reset ctlist in preparation for new try */
1891 ctlist = NIL;
1892 in_progress_ent.dead = false;
1893
1894 scandesc = systable_beginscan(relation,
1895 cache->cc_indexoid,
1896 IndexScanOK(cache),
1897 NULL,
1898 nkeys,
1899 cur_skey);
1900
1901 /* The list will be ordered iff we are doing an index scan */
1902 ordered = (scandesc->irel != NULL);
1903
1904 /* Injection point to help testing the recursive invalidation case */
1905 if (first_iter)
1906 {
1907 INJECTION_POINT("catcache-list-miss-systable-scan-started");
1908 first_iter = false;
1909 }
1910
1911 while (HeapTupleIsValid(ntp = systable_getnext(scandesc)) &&
1912 !in_progress_ent.dead)
1913 {
1914 uint32 hashValue;
1915 Index hashIndex;
1916 bool found = false;
1917 dlist_head *bucket;
1918
1919 /*
1920 * See if there's an entry for this tuple already.
1921 */
1922 ct = NULL;
1923 hashValue = CatalogCacheComputeTupleHashValue(cache, cache->cc_nkeys, ntp);
1924 hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
1925
1926 bucket = &cache->cc_bucket[hashIndex];
1927 dlist_foreach(iter, bucket)
1928 {
1929 ct = dlist_container(CatCTup, cache_elem, iter.cur);
1930
1931 if (ct->dead || ct->negative)
1932 continue; /* ignore dead and negative entries */
1933
1934 if (ct->hash_value != hashValue)
1935 continue; /* quickly skip entry if wrong hash val */
1936
1937 if (!ItemPointerEquals(&(ct->tuple.t_self), &(ntp->t_self)))
1938 continue; /* not same tuple */
1939
1940 /*
1941 * Found a match, but can't use it if it belongs to
1942 * another list already
1943 */
1944 if (ct->c_list)
1945 continue;
1946
1947 found = true;
1948 break; /* A-OK */
1949 }
1950
1951 if (!found)
1952 {
1953 /* We didn't find a usable entry, so make a new one */
1954 ct = CatalogCacheCreateEntry(cache, ntp, NULL,
1955 hashValue, hashIndex);
1956
1957 /* upon failure, we must start the scan over */
1958 if (ct == NULL)
1959 {
1960 in_progress_ent.dead = true;
1961 break;
1962 }
1963 }
1964
1965 /* Careful here: add entry to ctlist, then bump its refcount */
1966 /* This way leaves state correct if lappend runs out of memory */
1967 ctlist = lappend(ctlist, ct);
1968 ct->refcount++;
1969 }
1970
1971 systable_endscan(scandesc);
1972 } while (in_progress_ent.dead);
1973
1974 table_close(relation, AccessShareLock);
1975
1976 /* Make sure the resource owner has room to remember this entry. */
1978
1979 /* Now we can build the CatCList entry. */
1981 nmembers = list_length(ctlist);
1982 cl = (CatCList *)
1983 palloc(offsetof(CatCList, members) + nmembers * sizeof(CatCTup *));
1984
1985 /* Extract key values */
1986 CatCacheCopyKeys(cache->cc_tupdesc, nkeys, cache->cc_keyno,
1987 arguments, cl->keys);
1988 MemoryContextSwitchTo(oldcxt);
1989
1990 /*
1991 * We are now past the last thing that could trigger an elog before we
1992 * have finished building the CatCList and remembering it in the
1993 * resource owner. So it's OK to fall out of the PG_TRY, and indeed
1994 * we'd better do so before we start marking the members as belonging
1995 * to the list.
1996 */
1997 }
1998 PG_CATCH();
1999 {
2000 Assert(catcache_in_progress_stack == &in_progress_ent);
2001 catcache_in_progress_stack = save_in_progress;
2002
2003 foreach(ctlist_item, ctlist)
2004 {
2005 ct = (CatCTup *) lfirst(ctlist_item);
2006 Assert(ct->c_list == NULL);
2007 Assert(ct->refcount > 0);
2008 ct->refcount--;
2009 if (
2010#ifndef CATCACHE_FORCE_RELEASE
2011 ct->dead &&
2012#endif
2013 ct->refcount == 0 &&
2014 (ct->c_list == NULL || ct->c_list->refcount == 0))
2015 CatCacheRemoveCTup(cache, ct);
2016 }
2017
2018 PG_RE_THROW();
2019 }
2020 PG_END_TRY();
2021 Assert(catcache_in_progress_stack == &in_progress_ent);
2022 catcache_in_progress_stack = save_in_progress;
2023
2024 cl->cl_magic = CL_MAGIC;
2025 cl->my_cache = cache;
2026 cl->refcount = 0; /* for the moment */
2027 cl->dead = false;
2028 cl->ordered = ordered;
2029 cl->nkeys = nkeys;
2030 cl->hash_value = lHashValue;
2031 cl->n_members = nmembers;
2032
2033 i = 0;
2034 foreach(ctlist_item, ctlist)
2035 {
2036 cl->members[i++] = ct = (CatCTup *) lfirst(ctlist_item);
2037 Assert(ct->c_list == NULL);
2038 ct->c_list = cl;
2039 /* release the temporary refcount on the member */
2040 Assert(ct->refcount > 0);
2041 ct->refcount--;
2042 /* mark list dead if any members already dead */
2043 if (ct->dead)
2044 cl->dead = true;
2045 }
2046 Assert(i == nmembers);
2047
2048 /*
2049 * Add the CatCList to the appropriate bucket, and count it.
2050 */
2051 dlist_push_head(lbucket, &cl->cache_elem);
2052
2053 cache->cc_nlist++;
2054
2055 /* Finally, bump the list's refcount and return it */
2056 cl->refcount++;
2058
2059 CACHE_elog(DEBUG2, "SearchCatCacheList(%s): made list of %d members",
2060 cache->cc_relname, nmembers);
2061
2062 return cl;
2063}
static CatCTup * CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp, Datum *arguments, uint32 hashValue, Index hashIndex)
Definition: catcache.c:2111
static bool IndexScanOK(CatCache *cache)
Definition: catcache.c:1247
static void RehashCatCacheLists(CatCache *cp)
Definition: catcache.c:1023
static void ResourceOwnerRememberCatCacheListRef(ResourceOwner owner, CatCList *list)
Definition: catcache.c:169
#define PG_RE_THROW()
Definition: elog.h:405
#define PG_CATCH(...)
Definition: elog.h:382
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:603
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:514
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:388
#define INJECTION_POINT(name)
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:210
int cl_magic
Definition: catcache.h:161
bool ordered
Definition: catcache.h:176

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

Referenced by SearchSysCacheList().

◆ SearchCatCacheMiss()

static pg_noinline HeapTuple SearchCatCacheMiss ( CatCache cache,
int  nkeys,
uint32  hashValue,
Index  hashIndex,
Datum  v1,
Datum  v2,
Datum  v3,
Datum  v4 
)
static

Definition at line 1475 of file catcache.c.

1483{
1484 ScanKeyData cur_skey[CATCACHE_MAXKEYS];
1485 Relation relation;
1486 SysScanDesc scandesc;
1487 HeapTuple ntp;
1488 CatCTup *ct;
1489 bool stale;
1491
1492 /* Initialize local parameter array */
1493 arguments[0] = v1;
1494 arguments[1] = v2;
1495 arguments[2] = v3;
1496 arguments[3] = v4;
1497
1498 /*
1499 * Tuple was not found in cache, so we have to try to retrieve it directly
1500 * from the relation. If found, we will add it to the cache; if not
1501 * found, we will add a negative cache entry instead.
1502 *
1503 * NOTE: it is possible for recursive cache lookups to occur while reading
1504 * the relation --- for example, due to shared-cache-inval messages being
1505 * processed during table_open(). This is OK. It's even possible for one
1506 * of those lookups to find and enter the very same tuple we are trying to
1507 * fetch here. If that happens, we will enter a second copy of the tuple
1508 * into the cache. The first copy will never be referenced again, and
1509 * will eventually age out of the cache, so there's no functional problem.
1510 * This case is rare enough that it's not worth expending extra cycles to
1511 * detect.
1512 *
1513 * Another case, which we *must* handle, is that the tuple could become
1514 * outdated during CatalogCacheCreateEntry's attempt to detoast it (since
1515 * AcceptInvalidationMessages can run during TOAST table access). We do
1516 * not want to return already-stale catcache entries, so we loop around
1517 * and do the table scan again if that happens.
1518 */
1519 relation = table_open(cache->cc_reloid, AccessShareLock);
1520
1521 /*
1522 * Ok, need to make a lookup in the relation, copy the scankey and fill
1523 * out any per-call fields.
1524 */
1525 memcpy(cur_skey, cache->cc_skey, sizeof(ScanKeyData) * nkeys);
1526 cur_skey[0].sk_argument = v1;
1527 cur_skey[1].sk_argument = v2;
1528 cur_skey[2].sk_argument = v3;
1529 cur_skey[3].sk_argument = v4;
1530
1531 do
1532 {
1533 scandesc = systable_beginscan(relation,
1534 cache->cc_indexoid,
1535 IndexScanOK(cache),
1536 NULL,
1537 nkeys,
1538 cur_skey);
1539
1540 ct = NULL;
1541 stale = false;
1542
1543 while (HeapTupleIsValid(ntp = systable_getnext(scandesc)))
1544 {
1545 ct = CatalogCacheCreateEntry(cache, ntp, NULL,
1546 hashValue, hashIndex);
1547 /* upon failure, we must start the scan over */
1548 if (ct == NULL)
1549 {
1550 stale = true;
1551 break;
1552 }
1553 /* immediately set the refcount to 1 */
1555 ct->refcount++;
1557 break; /* assume only one match */
1558 }
1559
1560 systable_endscan(scandesc);
1561 } while (stale);
1562
1563 table_close(relation, AccessShareLock);
1564
1565 /*
1566 * If tuple was not found, we need to build a negative cache entry
1567 * containing a fake tuple. The fake tuple has the correct key columns,
1568 * but nulls everywhere else.
1569 *
1570 * In bootstrap mode, we don't build negative entries, because the cache
1571 * invalidation mechanism isn't alive and can't clear them if the tuple
1572 * gets created later. (Bootstrap doesn't do UPDATEs, so it doesn't need
1573 * cache inval for that.)
1574 */
1575 if (ct == NULL)
1576 {
1578 return NULL;
1579
1580 ct = CatalogCacheCreateEntry(cache, NULL, arguments,
1581 hashValue, hashIndex);
1582
1583 /* Creating a negative cache entry shouldn't fail */
1584 Assert(ct != NULL);
1585
1586 CACHE_elog(DEBUG2, "SearchCatCache(%s): Contains %d/%d tuples",
1587 cache->cc_relname, cache->cc_ntup, CacheHdr->ch_ntup);
1588 CACHE_elog(DEBUG2, "SearchCatCache(%s): put neg entry in bucket %d",
1589 cache->cc_relname, hashIndex);
1590
1591 /*
1592 * We are not returning the negative entry to the caller, so leave its
1593 * refcount zero.
1594 */
1595
1596 return NULL;
1597 }
1598
1599 CACHE_elog(DEBUG2, "SearchCatCache(%s): Contains %d/%d tuples",
1600 cache->cc_relname, cache->cc_ntup, CacheHdr->ch_ntup);
1601 CACHE_elog(DEBUG2, "SearchCatCache(%s): put in bucket %d",
1602 cache->cc_relname, hashIndex);
1603
1604#ifdef CATCACHE_STATS
1605 cache->cc_newloads++;
1606#endif
1607
1608 return &ct->tuple;
1609}
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:477

References AccessShareLock, Assert(), CatCInProgress::cache, 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 244 of file catcache.c.

245{
246 /*
247 * The use of DEFAULT_COLLATION_OID is fairly arbitrary here. We just
248 * want to take the fast "deterministic" path in texteq().
249 */
250 return DatumGetBool(DirectFunctionCall2Coll(texteq, DEFAULT_COLLATION_OID, a, b));
251}
Datum DirectFunctionCall2Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:812
Datum texteq(PG_FUNCTION_ARGS)
Definition: varlena.c:1683

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

Referenced by GetCCHashEqFuncs().

◆ texthashfast()

static uint32 texthashfast ( Datum  datum)
static

Definition at line 254 of file catcache.c.

255{
256 /* analogously here as in texteqfast() */
257 return DatumGetInt32(DirectFunctionCall1Coll(hashtext, DEFAULT_COLLATION_OID, datum));
258}
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_in_progress_stack

CatCInProgress* catcache_in_progress_stack = NULL
static

◆ 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:2416
static char * ResOwnerPrintCatCache(Datum res)
Definition: catcache.c:2422
@ RESOURCE_RELEASE_AFTER_LOCKS
Definition: resowner.h:56
#define RELEASE_PRIO_CATCACHE_REFS
Definition: resowner.h:71

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

Definition at line 147 of file catcache.c.

Referenced by ResourceOwnerForgetCatCacheListRef(), and ResourceOwnerRememberCatCacheListRef().