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)
 
static pg_attribute_always_inline void ConditionalCatalogCacheInitializeCache (CatCache *cache)
 
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 1110 of file catcache.c.

◆ CatalogCacheInitializeCache_DEBUG2

#define CatalogCacheInitializeCache_DEBUG2

Definition at line 1111 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:225
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 2133 of file catcache.c.

2135{
2136 CatCTup *ct;
2137 MemoryContext oldcxt;
2138
2139 if (ntp)
2140 {
2141 int i;
2142 HeapTuple dtp = NULL;
2143
2144 /*
2145 * The invalidation of the in-progress entry essentially never happens
2146 * during our regression tests, and there's no easy way to force it to
2147 * fail for testing purposes. To ensure we have test coverage for the
2148 * retry paths in our callers, make debug builds randomly fail about
2149 * 0.1% of the times through this code path, even when there's no
2150 * toasted fields.
2151 */
2152#ifdef USE_ASSERT_CHECKING
2154 return NULL;
2155#endif
2156
2157 /*
2158 * If there are any out-of-line toasted fields in the tuple, expand
2159 * them in-line. This saves cycles during later use of the catcache
2160 * entry, and also protects us against the possibility of the toast
2161 * tuples being freed before we attempt to fetch them, in case of
2162 * something using a slightly stale catcache entry.
2163 */
2164 if (HeapTupleHasExternal(ntp))
2165 {
2166 CatCInProgress *save_in_progress;
2167 CatCInProgress in_progress_ent;
2168
2169 /*
2170 * The tuple could become stale while we are doing toast table
2171 * access (since AcceptInvalidationMessages can run then). The
2172 * invalidation will mark our in-progress entry as dead.
2173 */
2174 save_in_progress = catcache_in_progress_stack;
2175 in_progress_ent.next = catcache_in_progress_stack;
2176 in_progress_ent.cache = cache;
2177 in_progress_ent.hash_value = hashValue;
2178 in_progress_ent.list = false;
2179 in_progress_ent.dead = false;
2180 catcache_in_progress_stack = &in_progress_ent;
2181
2182 PG_TRY();
2183 {
2184 dtp = toast_flatten_tuple(ntp, cache->cc_tupdesc);
2185 }
2186 PG_FINALLY();
2187 {
2188 Assert(catcache_in_progress_stack == &in_progress_ent);
2189 catcache_in_progress_stack = save_in_progress;
2190 }
2191 PG_END_TRY();
2192
2193 if (in_progress_ent.dead)
2194 {
2195 heap_freetuple(dtp);
2196 return NULL;
2197 }
2198 }
2199 else
2200 dtp = ntp;
2201
2202 /* Allocate memory for CatCTup and the cached tuple in one go */
2204
2205 ct = (CatCTup *) palloc(sizeof(CatCTup) +
2206 MAXIMUM_ALIGNOF + dtp->t_len);
2207 ct->tuple.t_len = dtp->t_len;
2208 ct->tuple.t_self = dtp->t_self;
2209 ct->tuple.t_tableOid = dtp->t_tableOid;
2211 MAXALIGN(((char *) ct) + sizeof(CatCTup));
2212 /* copy tuple contents */
2213 memcpy((char *) ct->tuple.t_data,
2214 (const char *) dtp->t_data,
2215 dtp->t_len);
2216 MemoryContextSwitchTo(oldcxt);
2217
2218 if (dtp != ntp)
2219 heap_freetuple(dtp);
2220
2221 /* extract keys - they'll point into the tuple if not by-value */
2222 for (i = 0; i < cache->cc_nkeys; i++)
2223 {
2224 Datum atp;
2225 bool isnull;
2226
2227 atp = heap_getattr(&ct->tuple,
2228 cache->cc_keyno[i],
2229 cache->cc_tupdesc,
2230 &isnull);
2231 Assert(!isnull);
2232 ct->keys[i] = atp;
2233 }
2234 }
2235 else
2236 {
2237 /* Set up keys for a negative cache entry */
2239 ct = (CatCTup *) palloc(sizeof(CatCTup));
2240
2241 /*
2242 * Store keys - they'll point into separately allocated memory if not
2243 * by-value.
2244 */
2245 CatCacheCopyKeys(cache->cc_tupdesc, cache->cc_nkeys, cache->cc_keyno,
2246 arguments, ct->keys);
2247 MemoryContextSwitchTo(oldcxt);
2248 }
2249
2250 /*
2251 * Finish initializing the CatCTup header, and add it to the cache's
2252 * linked list and counts.
2253 */
2254 ct->ct_magic = CT_MAGIC;
2255 ct->my_cache = cache;
2256 ct->c_list = NULL;
2257 ct->refcount = 0; /* for the moment */
2258 ct->dead = false;
2259 ct->negative = (ntp == NULL);
2260 ct->hash_value = hashValue;
2261
2262 dlist_push_head(&cache->cc_bucket[hashIndex], &ct->cache_elem);
2263
2264 cache->cc_ntup++;
2265 CacheHdr->ch_ntup++;
2266
2267 /*
2268 * If the hash table has become too full, enlarge the buckets array. Quite
2269 * arbitrarily, we enlarge when fill factor > 2.
2270 */
2271 if (cache->cc_ntup > cache->cc_nbuckets * 2)
2272 RehashCatCache(cache);
2273
2274 return ct;
2275}
#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:2306
static CatCacheHeader * CacheHdr
Definition: catcache.c:84
#define CT_MAGIC
Definition: catcache.h:91
#define PG_TRY(...)
Definition: elog.h:371
#define PG_END_TRY(...)
Definition: elog.h:396
#define PG_FINALLY(...)
Definition: elog.h:388
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:1321
MemoryContext CacheMemoryContext
Definition: mcxt.c:152
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:1894
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 1115 of file catcache.c.

1116{
1117 Relation relation;
1118 MemoryContext oldcxt;
1119 TupleDesc tupdesc;
1120 int i;
1121
1123
1124 relation = table_open(cache->cc_reloid, AccessShareLock);
1125
1126 /*
1127 * switch to the cache context so our allocations do not vanish at the end
1128 * of a transaction
1129 */
1130 Assert(CacheMemoryContext != NULL);
1131
1133
1134 /*
1135 * copy the relcache's tuple descriptor to permanent cache storage
1136 */
1137 tupdesc = CreateTupleDescCopyConstr(RelationGetDescr(relation));
1138
1139 /*
1140 * save the relation's name and relisshared flag, too (cc_relname is used
1141 * only for debugging purposes)
1142 */
1143 cache->cc_relname = pstrdup(RelationGetRelationName(relation));
1144 cache->cc_relisshared = RelationGetForm(relation)->relisshared;
1145
1146 /*
1147 * return to the caller's memory context and close the rel
1148 */
1149 MemoryContextSwitchTo(oldcxt);
1150
1151 table_close(relation, AccessShareLock);
1152
1153 CACHE_elog(DEBUG2, "CatalogCacheInitializeCache: %s, %d keys",
1154 cache->cc_relname, cache->cc_nkeys);
1155
1156 /*
1157 * initialize cache's key information
1158 */
1159 for (i = 0; i < cache->cc_nkeys; ++i)
1160 {
1161 Oid keytype;
1162 RegProcedure eqfunc;
1163
1165
1166 if (cache->cc_keyno[i] > 0)
1167 {
1168 Form_pg_attribute attr = TupleDescAttr(tupdesc,
1169 cache->cc_keyno[i] - 1);
1170
1171 keytype = attr->atttypid;
1172 /* cache key columns should always be NOT NULL */
1173 Assert(attr->attnotnull);
1174 }
1175 else
1176 {
1177 if (cache->cc_keyno[i] < 0)
1178 elog(FATAL, "sys attributes are not supported in caches");
1179 keytype = OIDOID;
1180 }
1181
1182 GetCCHashEqFuncs(keytype,
1183 &cache->cc_hashfunc[i],
1184 &eqfunc,
1185 &cache->cc_fastequal[i]);
1186
1187 /*
1188 * Do equality-function lookup (we assume this won't need a catalog
1189 * lookup for any supported type)
1190 */
1191 fmgr_info_cxt(eqfunc,
1192 &cache->cc_skey[i].sk_func,
1194
1195 /* Initialize sk_attno suitably for HeapKeyTest() and heap scans */
1196 cache->cc_skey[i].sk_attno = cache->cc_keyno[i];
1197
1198 /* Fill in sk_strategy as well --- always standard equality */
1200 cache->cc_skey[i].sk_subtype = InvalidOid;
1201 /* If a catcache key requires a collation, it must be C collation */
1202 cache->cc_skey[i].sk_collation = C_COLLATION_OID;
1203
1204 CACHE_elog(DEBUG2, "CatalogCacheInitializeCache %s %d %p",
1205 cache->cc_relname, i, cache);
1206 }
1207
1208 /*
1209 * mark this cache fully initialized
1210 */
1211 cache->cc_tupdesc = tupdesc;
1212}
regproc RegProcedure
Definition: c.h:621
#define CatalogCacheInitializeCache_DEBUG1
Definition: catcache.c:1110
static void GetCCHashEqFuncs(Oid keytype, CCHashFN *hashfunc, RegProcedure *eqfunc, CCFastEqualFN *fasteqfunc)
Definition: catcache.c:274
#define CatalogCacheInitializeCache_DEBUG2
Definition: catcache.c:1111
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:1703
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 ConditionalCatalogCacheInitializeCache().

◆ CatCacheCopyKeys()

static void CatCacheCopyKeys ( TupleDesc  tupdesc,
int  nkeys,
int *  attnos,
Datum srckeys,
Datum dstkeys 
)
static

Definition at line 2306 of file catcache.c.

2308{
2309 int i;
2310
2311 /*
2312 * XXX: memory and lookup performance could possibly be improved by
2313 * storing all keys in one allocation.
2314 */
2315
2316 for (i = 0; i < nkeys; i++)
2317 {
2318 int attnum = attnos[i];
2319 Form_pg_attribute att = TupleDescAttr(tupdesc, attnum - 1);
2320 Datum src = srckeys[i];
2321 NameData srcname;
2322
2323 /*
2324 * Must be careful in case the caller passed a C string where a NAME
2325 * is wanted: convert the given argument to a correctly padded NAME.
2326 * Otherwise the memcpy() done by datumCopy() could fall off the end
2327 * of memory.
2328 */
2329 if (att->atttypid == NAMEOID)
2330 {
2331 namestrcpy(&srcname, DatumGetCString(src));
2332 src = NameGetDatum(&srcname);
2333 }
2334
2335 dstkeys[i] = datumCopy(src,
2336 att->attbyval,
2337 att->attlen);
2338 }
2339}
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 2281 of file catcache.c.

2282{
2283 int i;
2284
2285 for (i = 0; i < nkeys; i++)
2286 {
2287 int attnum = attnos[i];
2289
2290 /* system attribute are not supported in caches */
2291 Assert(attnum > 0);
2292
2293 att = TupleDescAttr(tupdesc, attnum - 1);
2294
2295 if (!att->attbyval)
2296 pfree(DatumGetPointer(keys[i]));
2297 }
2298}
void pfree(void *pointer)
Definition: mcxt.c:1528
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:2281
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().

◆ ConditionalCatalogCacheInitializeCache()

static pg_attribute_always_inline void ConditionalCatalogCacheInitializeCache ( CatCache cache)
static

Definition at line 1064 of file catcache.c.

1065{
1066#ifdef USE_ASSERT_CHECKING
1067 /*
1068 * TypeCacheRelCallback() runs outside transactions and relies on TYPEOID
1069 * for hashing. This isn't ideal. Since lookup_type_cache() both
1070 * registers the callback and searches TYPEOID, reaching trouble likely
1071 * requires OOM at an unlucky moment.
1072 *
1073 * InvalidateAttoptCacheCallback() runs outside transactions and likewise
1074 * relies on ATTNUM. InitPostgres() initializes ATTNUM, so it's reliable.
1075 */
1076 if (!(cache->id == TYPEOID || cache->id == ATTNUM) ||
1079 else
1080 Assert(cache->cc_tupdesc != NULL);
1081#endif
1082
1083 if (unlikely(cache->cc_tupdesc == NULL))
1085}
#define unlikely(x)
Definition: c.h:347
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:1115
static void AssertCouldGetRelation(void)
Definition: relcache.h:44
bool IsTransactionState(void)
Definition: xact.c:387

References Assert(), AssertCouldGetRelation(), CatCInProgress::cache, CatalogCacheInitializeCache(), catcache::cc_tupdesc, catcache::id, IsTransactionState(), and unlikely.

Referenced by GetCatCacheHashValue(), InitCatCachePhase2(), PrepareToInvalidateCacheTuple(), SearchCatCacheInternal(), and SearchCatCacheList().

◆ 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:149
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CacheMemoryContext, and TopMemoryContext.

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

◆ GetCatCacheHashValue()

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

Definition at line 1686 of file catcache.c.

1691{
1692 /*
1693 * one-time startup overhead for each cache
1694 */
1696
1697 /*
1698 * calculate the hash value
1699 */
1700 return CatalogCacheComputeHashValue(cache, cache->cc_nkeys, v1, v2, v3, v4);
1701}
static pg_attribute_always_inline void ConditionalCatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:1064

References CatCInProgress::cache, CatalogCacheComputeHashValue(), catcache::cc_nkeys, and ConditionalCatalogCacheInitializeCache().

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

1276{
1277 switch (cache->id)
1278 {
1279 case INDEXRELID:
1280
1281 /*
1282 * Rather than tracking exactly which indexes have to be loaded
1283 * before we can use indexscans (which changes from time to time),
1284 * just force all pg_index searches to be heap scans until we've
1285 * built the critical relcaches.
1286 */
1288 return false;
1289 break;
1290
1291 case AMOID:
1292 case AMNAME:
1293
1294 /*
1295 * Always do heap scans in pg_am, because it's so small there's
1296 * not much point in an indexscan anyway. We *must* do this when
1297 * initially building critical relcache entries, but we might as
1298 * well just always do it.
1299 */
1300 return false;
1301
1302 case AUTHNAME:
1303 case AUTHOID:
1304 case AUTHMEMMEMROLE:
1305 case DATABASEOID:
1306
1307 /*
1308 * Protect authentication lookups occurring before relcache has
1309 * collected entries for shared indexes.
1310 */
1312 return false;
1313 break;
1314
1315 default:
1316 break;
1317 }
1318
1319 /* Normal case, allow index scan */
1320 return true;
1321}
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:1351
void * palloc_aligned(Size size, Size alignto, int flags)
Definition: mcxt.c:1518
#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 1224 of file catcache.c.

1225{
1227
1228 if (touch_index &&
1229 cache->id != AMOID &&
1230 cache->id != AMNAME)
1231 {
1232 Relation idesc;
1233
1234 /*
1235 * We must lock the underlying catalog before opening the index to
1236 * avoid deadlock, since index_open could possibly result in reading
1237 * this same catalog, and if anyone else is exclusive-locking this
1238 * catalog and index they'll be doing it in that order.
1239 */
1241 idesc = index_open(cache->cc_indexoid, AccessShareLock);
1242
1243 /*
1244 * While we've got the index open, let's check that it's unique (and
1245 * not just deferrable-unique, thank you very much). This is just to
1246 * catch thinkos in definitions of new catcaches, so we don't worry
1247 * about the pg_am indexes not getting tested.
1248 */
1249 Assert(idesc->rd_index->indisunique &&
1250 idesc->rd_index->indimmediate);
1251
1254 }
1255}
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, catcache::cc_indexoid, catcache::cc_reloid, ConditionalCatalogCacheInitializeCache(), 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 2376 of file catcache.c.

2381{
2382 slist_iter iter;
2383 Oid reloid;
2384
2385 CACHE_elog(DEBUG2, "PrepareToInvalidateCacheTuple: called");
2386
2387 /*
2388 * sanity checks
2389 */
2390 Assert(RelationIsValid(relation));
2391 Assert(HeapTupleIsValid(tuple));
2393 Assert(CacheHdr != NULL);
2394
2395 reloid = RelationGetRelid(relation);
2396
2397 /* ----------------
2398 * for each cache
2399 * if the cache contains tuples from the specified relation
2400 * compute the tuple's hash value(s) in this cache,
2401 * and call the passed function to register the information.
2402 * ----------------
2403 */
2404
2406 {
2407 CatCache *ccp = slist_container(CatCache, cc_next, iter.cur);
2408 uint32 hashvalue;
2409 Oid dbid;
2410
2411 if (ccp->cc_reloid != reloid)
2412 continue;
2413
2414 /* Just in case cache hasn't finished initialization yet... */
2416
2417 hashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, tuple);
2418 dbid = ccp->cc_relisshared ? (Oid) 0 : MyDatabaseId;
2419
2420 (*function) (ccp->id, hashvalue, dbid, context);
2421
2422 if (newtuple)
2423 {
2424 uint32 newhashvalue;
2425
2426 newhashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, newtuple);
2427
2428 if (newhashvalue != hashvalue)
2429 (*function) (ccp->id, newhashvalue, dbid, context);
2430 }
2431 }
2432}
#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:94
#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(), catcache::cc_nkeys, catcache::cc_relisshared, catcache::cc_reloid, catcacheheader::ch_caches, ConditionalCatalogCacheInitializeCache(), 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:1219

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

1648{
1650}
static void ReleaseCatCacheWithOwner(HeapTuple tuple, ResourceOwner resowner)
Definition: catcache.c:1653
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 2099 of file catcache.c.

2100{
2101 /* Safety checks to ensure we were handed a cache entry */
2102 Assert(list->cl_magic == CL_MAGIC);
2103 Assert(list->refcount > 0);
2104 list->refcount--;
2105 if (resowner)
2107
2108 if (
2109#ifndef CATCACHE_FORCE_RELEASE
2110 list->dead &&
2111#endif
2112 list->refcount == 0)
2113 CatCacheRemoveCList(list->my_cache, list);
2114}
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 1653 of file catcache.c.

1654{
1655 CatCTup *ct = (CatCTup *) (((char *) tuple) -
1656 offsetof(CatCTup, tuple));
1657
1658 /* Safety checks to ensure we were handed a cache entry */
1659 Assert(ct->ct_magic == CT_MAGIC);
1660 Assert(ct->refcount > 0);
1661
1662 ct->refcount--;
1663 if (resowner)
1665
1666 if (
1667#ifndef CATCACHE_FORCE_RELEASE
1668 ct->dead &&
1669#endif
1670 ct->refcount == 0 &&
1671 (ct->c_list == NULL || ct->c_list->refcount == 0))
1673}
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 2443 of file catcache.c.

2444{
2445 HeapTuple tuple = (HeapTuple) DatumGetPointer(res);
2446 CatCTup *ct = (CatCTup *) (((char *) tuple) -
2447 offsetof(CatCTup, tuple));
2448
2449 /* Safety check to ensure we were handed a cache entry */
2450 Assert(ct->ct_magic == CT_MAGIC);
2451
2452 return psprintf("cache %s (%d), tuple %u/%u has count %d",
2453 ct->my_cache->cc_relname, ct->my_cache->id,
2456 ct->refcount);
2457}
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 2466 of file catcache.c.

2467{
2469
2470 return psprintf("cache %s (%d), list %p has count %d",
2471 list->my_cache->cc_relname, list->my_cache->id,
2472 list, list->refcount);
2473}

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

◆ ResOwnerReleaseCatCache()

static void ResOwnerReleaseCatCache ( Datum  res)
static

Definition at line 2437 of file catcache.c.

2438{
2440}

References DatumGetPointer(), and ReleaseCatCacheWithOwner().

◆ ResOwnerReleaseCatCacheList()

static void ResOwnerReleaseCatCacheList ( Datum  res)
static

Definition at line 2460 of file catcache.c.

2461{
2463}

References DatumGetPointer(), and ReleaseCatCacheListWithOwner().

◆ SearchCatCache()

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

Definition at line 1340 of file catcache.c.

1345{
1346 return SearchCatCacheInternal(cache, cache->cc_nkeys, v1, v2, v3, v4);
1347}
static HeapTuple SearchCatCacheInternal(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1391

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

Referenced by SearchSysCache().

◆ SearchCatCache1()

HeapTuple SearchCatCache1 ( CatCache cache,
Datum  v1 
)

Definition at line 1357 of file catcache.c.

1359{
1360 return SearchCatCacheInternal(cache, 1, v1, 0, 0, 0);
1361}

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache1().

◆ SearchCatCache2()

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

Definition at line 1365 of file catcache.c.

1367{
1368 return SearchCatCacheInternal(cache, 2, v1, v2, 0, 0);
1369}

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache2().

◆ SearchCatCache3()

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

Definition at line 1373 of file catcache.c.

1375{
1376 return SearchCatCacheInternal(cache, 3, v1, v2, v3, 0);
1377}

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache3().

◆ SearchCatCache4()

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

Definition at line 1381 of file catcache.c.

1383{
1384 return SearchCatCacheInternal(cache, 4, v1, v2, v3, v4);
1385}

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

1397{
1399 uint32 hashValue;
1400 Index hashIndex;
1401 dlist_iter iter;
1402 dlist_head *bucket;
1403 CatCTup *ct;
1404
1405 Assert(cache->cc_nkeys == nkeys);
1406
1407 /*
1408 * one-time startup overhead for each cache
1409 */
1411
1412#ifdef CATCACHE_STATS
1413 cache->cc_searches++;
1414#endif
1415
1416 /* Initialize local parameter array */
1417 arguments[0] = v1;
1418 arguments[1] = v2;
1419 arguments[2] = v3;
1420 arguments[3] = v4;
1421
1422 /*
1423 * find the hash bucket in which to look for the tuple
1424 */
1425 hashValue = CatalogCacheComputeHashValue(cache, nkeys, v1, v2, v3, v4);
1426 hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
1427
1428 /*
1429 * scan the hash bucket until we find a match or exhaust our tuples
1430 *
1431 * Note: it's okay to use dlist_foreach here, even though we modify the
1432 * dlist within the loop, because we don't continue the loop afterwards.
1433 */
1434 bucket = &cache->cc_bucket[hashIndex];
1435 dlist_foreach(iter, bucket)
1436 {
1437 ct = dlist_container(CatCTup, cache_elem, iter.cur);
1438
1439 if (ct->dead)
1440 continue; /* ignore dead entries */
1441
1442 if (ct->hash_value != hashValue)
1443 continue; /* quickly skip entry if wrong hash val */
1444
1445 if (!CatalogCacheCompareTuple(cache, nkeys, ct->keys, arguments))
1446 continue;
1447
1448 /*
1449 * We found a match in the cache. Move it to the front of the list
1450 * for its hashbucket, in order to speed subsequent searches. (The
1451 * most frequently accessed elements in any hashbucket will tend to be
1452 * near the front of the hashbucket's list.)
1453 */
1454 dlist_move_head(bucket, &ct->cache_elem);
1455
1456 /*
1457 * If it's a positive entry, bump its refcount and return it. If it's
1458 * negative, we can report failure to the caller.
1459 */
1460 if (!ct->negative)
1461 {
1463 ct->refcount++;
1465
1466 CACHE_elog(DEBUG2, "SearchCatCache(%s): found in bucket %d",
1467 cache->cc_relname, hashIndex);
1468
1469#ifdef CATCACHE_STATS
1470 cache->cc_hits++;
1471#endif
1472
1473 return &ct->tuple;
1474 }
1475 else
1476 {
1477 CACHE_elog(DEBUG2, "SearchCatCache(%s): found neg entry in bucket %d",
1478 cache->cc_relname, hashIndex);
1479
1480#ifdef CATCACHE_STATS
1481 cache->cc_neg_hits++;
1482#endif
1483
1484 return NULL;
1485 }
1486 }
1487
1488 return SearchCatCacheMiss(cache, nkeys, hashValue, hashIndex, v1, v2, v3, v4);
1489}
static pg_noinline HeapTuple SearchCatCacheMiss(CatCache *cache, int nkeys, uint32 hashValue, Index hashIndex, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1499
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

References Assert(), CatCInProgress::cache, catctup::cache_elem, CACHE_elog, CatalogCacheCompareTuple(), CatalogCacheComputeHashValue(), CATCACHE_MAXKEYS, catcache::cc_bucket, catcache::cc_nbuckets, catcache::cc_nkeys, catcache::cc_relname, ConditionalCatalogCacheInitializeCache(), dlist_iter::cur, CurrentResourceOwner, catctup::dead, DEBUG2, dlist_container, dlist_foreach, dlist_move_head(), HASH_INDEX, catctup::hash_value, catctup::keys, catctup::negative, catctup::refcount, ResourceOwnerEnlarge(), ResourceOwnerRememberCatCacheRef(), SearchCatCacheMiss(), and catctup::tuple.

Referenced by SearchCatCache(), SearchCatCache1(), SearchCatCache2(), SearchCatCache3(), and SearchCatCache4().

◆ SearchCatCacheList()

CatCList * SearchCatCacheList ( CatCache cache,
int  nkeys,
Datum  v1,
Datum  v2,
Datum  v3 
)

Definition at line 1719 of file catcache.c.

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

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

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:2437
static char * ResOwnerPrintCatCache(Datum res)
Definition: catcache.c:2443
@ 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:2460
static char * ResOwnerPrintCatCacheList(Datum res)
Definition: catcache.c:2466
#define RELEASE_PRIO_CATCACHE_LIST_REFS
Definition: resowner.h:72

Definition at line 147 of file catcache.c.

Referenced by ResourceOwnerForgetCatCacheListRef(), and ResourceOwnerRememberCatCacheListRef().