PostgreSQL Source Code git master
catcache.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/heaptoast.h"
#include "access/relscan.h"
#include "access/table.h"
#include "access/xact.h"
#include "catalog/catalog.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_type.h"
#include "common/hashfn.h"
#include "common/pg_prng.h"
#include "miscadmin.h"
#include "port/pg_bitutils.h"
#include "storage/lmgr.h"
#include "utils/builtins.h"
#include "utils/catcache.h"
#include "utils/datum.h"
#include "utils/fmgroids.h"
#include "utils/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, const int *attnos, const Datum *keys)
 
static void CatCacheCopyKeys (TupleDesc tupdesc, int nkeys, const int *attnos, const 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 1117 of file catcache.c.

◆ CatalogCacheInitializeCache_DEBUG2

#define CatalogCacheInitializeCache_DEBUG2

Definition at line 1118 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 881 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 442 of file catcache.c.

445{
446 const CCFastEqualFN *cc_fastequal = cache->cc_fastequal;
447 int i;
448
449 for (i = 0; i < nkeys; i++)
450 {
451 if (!(cc_fastequal[i]) (cachekeys[i], searchkeys[i]))
452 return false;
453 }
454 return true;
455}
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 345 of file catcache.c.

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

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

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

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

842{
843 slist_iter iter;
844
845 CACHE_elog(DEBUG2, "CatalogCacheFlushCatalog called for %u", catId);
846
848 {
849 CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
850
851 /* Does this cache store tuples of the target catalog? */
852 if (cache->cc_reloid == catId)
853 {
854 /* Yes, so flush all its contents */
855 ResetCatalogCache(cache, false);
856
857 /* Tell inval.c to call syscache callbacks for this cache */
858 CallSyscacheCallbacks(cache->id, 0);
859 }
860 }
861
862 CACHE_elog(DEBUG2, "end of CatalogCacheFlushCatalog call");
863}
static void ResetCatalogCache(CatCache *cache, bool debug_discard)
Definition: catcache.c:743
#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:191
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 1122 of file catcache.c.

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

Definition at line 2310 of file catcache.c.

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

References attnum, datumCopy(), DatumGetCString(), i, NameGetDatum(), namestrcpy(), and TupleDescAttr().

Referenced by CatalogCacheCreateEntry(), and SearchCatCacheList().

◆ CatCacheFreeKeys()

static void CatCacheFreeKeys ( TupleDesc  tupdesc,
int  nkeys,
const int *  attnos,
const Datum keys 
)
static

Definition at line 2288 of file catcache.c.

2289{
2290 int i;
2291
2292 for (i = 0; i < nkeys; i++)
2293 {
2294 int attnum = attnos[i];
2295
2296 /* system attribute are not supported in caches */
2297 Assert(attnum > 0);
2298
2299 if (!TupleDescCompactAttr(tupdesc, attnum - 1)->attbyval)
2300 pfree(DatumGetPointer(keys[i]));
2301 }
2302}
void pfree(void *pointer)
Definition: mcxt.c:1594
bool attbyval
Definition: pg_attribute.h:94
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:322
static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)
Definition: tupdesc.h:175

References Assert(), attbyval, attnum, DatumGetPointer(), i, pfree(), and TupleDescCompactAttr().

Referenced by CatCacheRemoveCList(), and CatCacheRemoveCTup().

◆ CatCacheInvalidate()

void CatCacheInvalidate ( CatCache cache,
uint32  hashValue 
)

Definition at line 632 of file catcache.c.

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

578{
579 int i;
580
581 Assert(cl->refcount == 0);
582 Assert(cl->my_cache == cache);
583
584 /* delink from member tuples */
585 for (i = cl->n_members; --i >= 0;)
586 {
587 CatCTup *ct = cl->members[i];
588
589 Assert(ct->c_list == cl);
590 ct->c_list = NULL;
591 /* if the member is dead and now has no references, remove it */
592 if (
593#ifndef CATCACHE_FORCE_RELEASE
594 ct->dead &&
595#endif
596 ct->refcount == 0)
597 CatCacheRemoveCTup(cache, ct);
598 }
599
600 /* delink from linked list */
602
603 /* free associated column data */
605 cache->cc_keyno, cl->keys);
606
607 pfree(cl);
608
609 --cache->cc_nlist;
610}
static void CatCacheFreeKeys(TupleDesc tupdesc, int nkeys, const int *attnos, const Datum *keys)
Definition: catcache.c:2288
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:184
short nkeys
Definition: catcache.h:182
Datum keys[CATCACHE_MAXKEYS]
Definition: catcache.h:177
CatCTup * members[FLEXIBLE_ARRAY_MEMBER]
Definition: catcache.h:185
int n_members
Definition: catcache.h:183

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

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

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

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:537
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 1071 of file catcache.c.

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

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

716{
717 /*
718 * Purely for paranoia, check that context doesn't exist; caller probably
719 * did so already.
720 */
723 "CacheMemoryContext",
725}
MemoryContext TopMemoryContext
Definition: mcxt.c:166
#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 1693 of file catcache.c.

1698{
1699 /*
1700 * one-time startup overhead for each cache
1701 */
1703
1704 /*
1705 * calculate the hash value
1706 */
1707 return CatalogCacheComputeHashValue(cache, cache->cc_nkeys, v1, v2, v3, v4);
1708}
static pg_attribute_always_inline void ConditionalCatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:1071

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 case REGDATABASEOID:
321 *hashfunc = int4hashfast;
322 *fasteqfunc = int4eqfast;
323 *eqfunc = F_OIDEQ;
324 break;
325 case OIDVECTOROID:
326 *hashfunc = oidvectorhashfast;
327 *fasteqfunc = oidvectoreqfast;
328 *eqfunc = F_OIDVECTOREQ;
329 break;
330 default:
331 elog(FATAL, "type %u not supported as catcache key", keytype);
332 *hashfunc = NULL; /* keep compiler quiet */
333
334 *eqfunc = InvalidOid;
335 break;
336 }
337}
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 1282 of file catcache.c.

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

891{
892 CatCache *cp;
893 MemoryContext oldcxt;
894 int i;
895
896 /*
897 * nbuckets is the initial number of hash buckets to use in this catcache.
898 * It will be enlarged later if it becomes too full.
899 *
900 * nbuckets must be a power of two. We check this via Assert rather than
901 * a full runtime check because the values will be coming from constant
902 * tables.
903 *
904 * If you're confused by the power-of-two check, see comments in
905 * bitmapset.c for an explanation.
906 */
907 Assert(nbuckets > 0 && (nbuckets & -nbuckets) == nbuckets);
908
909 /*
910 * first switch to the cache context so our allocations do not vanish at
911 * the end of a transaction
912 */
915
917
918 /*
919 * if first time through, initialize the cache group header
920 */
921 if (CacheHdr == NULL)
922 {
925 CacheHdr->ch_ntup = 0;
926#ifdef CATCACHE_STATS
927 /* set up to dump stats at backend exit */
928 on_proc_exit(CatCachePrintStats, 0);
929#endif
930 }
931
932 /*
933 * Allocate a new cache structure, aligning to a cacheline boundary
934 *
935 * Note: we rely on zeroing to initialize all the dlist headers correctly
936 */
939 cp->cc_bucket = palloc0(nbuckets * sizeof(dlist_head));
940
941 /*
942 * Many catcaches never receive any list searches. Therefore, we don't
943 * allocate the cc_lbuckets till we get a list search.
944 */
945 cp->cc_lbucket = NULL;
946
947 /*
948 * initialize the cache's relation information for the relation
949 * corresponding to this cache, and initialize some of the new cache's
950 * other internal fields. But don't open the relation yet.
951 */
952 cp->id = id;
953 cp->cc_relname = "(not known yet)";
954 cp->cc_reloid = reloid;
955 cp->cc_indexoid = indexoid;
956 cp->cc_relisshared = false; /* temporary */
957 cp->cc_tupdesc = (TupleDesc) NULL;
958 cp->cc_ntup = 0;
959 cp->cc_nlist = 0;
960 cp->cc_nbuckets = nbuckets;
961 cp->cc_nlbuckets = 0;
962 cp->cc_nkeys = nkeys;
963 for (i = 0; i < nkeys; ++i)
964 {
966 cp->cc_keyno[i] = key[i];
967 }
968
969 /*
970 * new cache is initialized as far as we can go for now. print some
971 * debugging information, if appropriate.
972 */
974
975 /*
976 * add completed cache to top of group header's list
977 */
979
980 /*
981 * back to the old context before we return...
982 */
983 MemoryContextSwitchTo(oldcxt);
984
985 return cp;
986}
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
void CreateCacheMemoryContext(void)
Definition: catcache.c:715
#define InitCatCache_DEBUG2
Definition: catcache.c:881
#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:1395
void * palloc_aligned(Size size, Size alignto, int flags)
Definition: mcxt.c:1584
#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 1231 of file catcache.c.

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

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

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:754
#define NAMEDATALEN
static Name DatumGetName(Datum X)
Definition: postgres.h:370

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_bytes((unsigned char *) key, strlen(key));
217}
uint32 hash_bytes(const unsigned char *k, int keylen)
Definition: hashfn.c:146

References DatumGetName(), hash_bytes(), 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:100

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

2385{
2386 slist_iter iter;
2387 Oid reloid;
2388
2389 CACHE_elog(DEBUG2, "PrepareToInvalidateCacheTuple: called");
2390
2391 /*
2392 * sanity checks
2393 */
2394 Assert(RelationIsValid(relation));
2395 Assert(HeapTupleIsValid(tuple));
2397 Assert(CacheHdr != NULL);
2398
2399 reloid = RelationGetRelid(relation);
2400
2401 /* ----------------
2402 * for each cache
2403 * if the cache contains tuples from the specified relation
2404 * compute the tuple's hash value(s) in this cache,
2405 * and call the passed function to register the information.
2406 * ----------------
2407 */
2408
2410 {
2411 CatCache *ccp = slist_container(CatCache, cc_next, iter.cur);
2412 uint32 hashvalue;
2413 Oid dbid;
2414
2415 if (ccp->cc_reloid != reloid)
2416 continue;
2417
2418 /* Just in case cache hasn't finished initialization yet... */
2420
2421 hashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, tuple);
2422 dbid = ccp->cc_relisshared ? (Oid) 0 : MyDatabaseId;
2423
2424 (*function) (ccp->id, hashvalue, dbid, context);
2425
2426 if (newtuple)
2427 {
2428 uint32 newhashvalue;
2429
2430 newhashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, newtuple);
2431
2432 if (newhashvalue != hashvalue)
2433 (*function) (ccp->id, newhashvalue, dbid, context);
2434 }
2435 }
2436}
static uint32 CatalogCacheComputeTupleHashValue(CatCache *cache, int nkeys, HeapTuple tuple)
Definition: catcache.c:387
Oid MyDatabaseId
Definition: globals.c:94
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
on_exit_nicely_callback function
#define RelationGetRelid(relation)
Definition: rel.h:515
#define RelationIsValid(relation)
Definition: rel.h:490

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, RelationGetRelid, RelationIsValid, slist_container, and slist_foreach.

Referenced by CacheInvalidateHeapTupleCommon().

◆ RehashCatCache()

static void RehashCatCache ( CatCache cp)
static

Definition at line 992 of file catcache.c.

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

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

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

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

1655{
1657}
static void ReleaseCatCacheWithOwner(HeapTuple tuple, ResourceOwner resowner)
Definition: catcache.c:1660
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 2106 of file catcache.c.

2107{
2108 /* Safety checks to ensure we were handed a cache entry */
2109 Assert(list->cl_magic == CL_MAGIC);
2110 Assert(list->refcount > 0);
2111 list->refcount--;
2112 if (resowner)
2114
2115 if (
2116#ifndef CATCACHE_FORCE_RELEASE
2117 list->dead &&
2118#endif
2119 list->refcount == 0)
2120 CatCacheRemoveCList(list->my_cache, list);
2121}
static void ResourceOwnerForgetCatCacheListRef(ResourceOwner owner, CatCList *list)
Definition: catcache.c:174
#define CL_MAGIC
Definition: catcache.h:169

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

1661{
1662 CatCTup *ct = (CatCTup *) (((char *) tuple) -
1663 offsetof(CatCTup, tuple));
1664
1665 /* Safety checks to ensure we were handed a cache entry */
1666 Assert(ct->ct_magic == CT_MAGIC);
1667 Assert(ct->refcount > 0);
1668
1669 ct->refcount--;
1670 if (resowner)
1672
1673 if (
1674#ifndef CATCACHE_FORCE_RELEASE
1675 ct->dead &&
1676#endif
1677 ct->refcount == 0 &&
1678 (ct->c_list == NULL || ct->c_list->refcount == 0))
1680}
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 743 of file catcache.c.

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

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

806{
808}
void ResetCatalogCachesExt(bool debug_discard)
Definition: catcache.c:811

References ResetCatalogCachesExt().

◆ ResetCatalogCachesExt()

void ResetCatalogCachesExt ( bool  debug_discard)

Definition at line 811 of file catcache.c.

812{
813 slist_iter iter;
814
815 CACHE_elog(DEBUG2, "ResetCatalogCaches called");
816
818 {
819 CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
820
821 ResetCatalogCache(cache, debug_discard);
822 }
823
824 CACHE_elog(DEBUG2, "end of ResetCatalogCaches call");
825}

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:332
void ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:561

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

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

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

2471{
2473
2474 return psprintf("cache %s (%d), list %p has count %d",
2475 list->my_cache->cc_relname, list->my_cache->id,
2476 list, list->refcount);
2477}

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

◆ ResOwnerReleaseCatCache()

static void ResOwnerReleaseCatCache ( Datum  res)
static

Definition at line 2441 of file catcache.c.

2442{
2444}

References DatumGetPointer(), and ReleaseCatCacheWithOwner().

◆ ResOwnerReleaseCatCacheList()

static void ResOwnerReleaseCatCacheList ( Datum  res)
static

Definition at line 2464 of file catcache.c.

2465{
2467}

References DatumGetPointer(), and ReleaseCatCacheListWithOwner().

◆ SearchCatCache()

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

Definition at line 1347 of file catcache.c.

1352{
1353 return SearchCatCacheInternal(cache, cache->cc_nkeys, v1, v2, v3, v4);
1354}
static HeapTuple SearchCatCacheInternal(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1398

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

Referenced by SearchSysCache().

◆ SearchCatCache1()

HeapTuple SearchCatCache1 ( CatCache cache,
Datum  v1 
)

Definition at line 1364 of file catcache.c.

1366{
1367 return SearchCatCacheInternal(cache, 1, v1, 0, 0, 0);
1368}

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache1().

◆ SearchCatCache2()

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

Definition at line 1372 of file catcache.c.

1374{
1375 return SearchCatCacheInternal(cache, 2, v1, v2, 0, 0);
1376}

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache2().

◆ SearchCatCache3()

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

Definition at line 1380 of file catcache.c.

1382{
1383 return SearchCatCacheInternal(cache, 3, v1, v2, v3, 0);
1384}

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache3().

◆ SearchCatCache4()

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

Definition at line 1388 of file catcache.c.

1390{
1391 return SearchCatCacheInternal(cache, 4, v1, v2, v3, v4);
1392}

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

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

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

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

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

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:793
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:2441
static char * ResOwnerPrintCatCache(Datum res)
Definition: catcache.c:2447
@ 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:2464
static char * ResOwnerPrintCatCacheList(Datum res)
Definition: catcache.c:2470
#define RELEASE_PRIO_CATCACHE_LIST_REFS
Definition: resowner.h:72

Definition at line 147 of file catcache.c.

Referenced by ResourceOwnerForgetCatCacheListRef(), and ResourceOwnerRememberCatCacheListRef().