Thanks to visit codestin.com
Credit goes to doxygen.postgresql.org

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

◆ CatalogCacheInitializeCache_DEBUG2

#define CatalogCacheInitializeCache_DEBUG2

Definition at line 1112 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 875 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:539
#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 2134 of file catcache.c.

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

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

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

Definition at line 2307 of file catcache.c.

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

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

2283{
2284 int i;
2285
2286 for (i = 0; i < nkeys; i++)
2287 {
2288 int attnum = attnos[i];
2290
2291 /* system attribute are not supported in caches */
2292 Assert(attnum > 0);
2293
2294 att = TupleDescAttr(tupdesc, attnum - 1);
2295
2296 if (!att->attbyval)
2297 pfree(DatumGetPointer(keys[i]));
2298 }
2299}
void pfree(void *pointer)
Definition: mcxt.c:1594
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:322

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

Referenced by CatCacheRemoveCList(), and CatCacheRemoveCTup().

◆ CatCacheInvalidate()

void CatCacheInvalidate ( CatCache cache,
uint32  hashValue 
)

Definition at line 626 of file catcache.c.

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

572{
573 int i;
574
575 Assert(cl->refcount == 0);
576 Assert(cl->my_cache == cache);
577
578 /* delink from member tuples */
579 for (i = cl->n_members; --i >= 0;)
580 {
581 CatCTup *ct = cl->members[i];
582
583 Assert(ct->c_list == cl);
584 ct->c_list = NULL;
585 /* if the member is dead and now has no references, remove it */
586 if (
587#ifndef CATCACHE_FORCE_RELEASE
588 ct->dead &&
589#endif
590 ct->refcount == 0)
591 CatCacheRemoveCTup(cache, ct);
592 }
593
594 /* delink from linked list */
596
597 /* free associated column data */
599 cache->cc_keyno, cl->keys);
600
601 pfree(cl);
602
603 --cache->cc_nlist;
604}
static void CatCacheFreeKeys(TupleDesc tupdesc, int nkeys, int *attnos, Datum *keys)
Definition: catcache.c:2282
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 529 of file catcache.c.

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

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

1066{
1067#ifdef USE_ASSERT_CHECKING
1068 /*
1069 * TypeCacheRelCallback() runs outside transactions and relies on TYPEOID
1070 * for hashing. This isn't ideal. Since lookup_type_cache() both
1071 * registers the callback and searches TYPEOID, reaching trouble likely
1072 * requires OOM at an unlucky moment.
1073 *
1074 * InvalidateAttoptCacheCallback() runs outside transactions and likewise
1075 * relies on ATTNUM. InitPostgres() initializes ATTNUM, so it's reliable.
1076 */
1077 if (!(cache->id == TYPEOID || cache->id == ATTNUM) ||
1080 else
1081 Assert(cache->cc_tupdesc != NULL);
1082#endif
1083
1084 if (unlikely(cache->cc_tupdesc == NULL))
1086}
#define unlikely(x)
Definition: c.h:403
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:1116
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 709 of file catcache.c.

710{
711 /*
712 * Purely for paranoia, check that context doesn't exist; caller probably
713 * did so already.
714 */
717 "CacheMemoryContext",
719}
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 1687 of file catcache.c.

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

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

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

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

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

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

Referenced by CacheInvalidateHeapTupleCommon().

◆ RehashCatCache()

static void RehashCatCache ( CatCache cp)
static

Definition at line 986 of file catcache.c.

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

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

1649{
1651}
static void ReleaseCatCacheWithOwner(HeapTuple tuple, ResourceOwner resowner)
Definition: catcache.c:1654
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 2100 of file catcache.c.

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

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

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

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

800{
802}
void ResetCatalogCachesExt(bool debug_discard)
Definition: catcache.c:805

References ResetCatalogCachesExt().

◆ ResetCatalogCachesExt()

void ResetCatalogCachesExt ( bool  debug_discard)

Definition at line 805 of file catcache.c.

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

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

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

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

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

◆ ResOwnerReleaseCatCache()

static void ResOwnerReleaseCatCache ( Datum  res)
static

Definition at line 2438 of file catcache.c.

2439{
2441}

References DatumGetPointer(), and ReleaseCatCacheWithOwner().

◆ ResOwnerReleaseCatCacheList()

static void ResOwnerReleaseCatCacheList ( Datum  res)
static

Definition at line 2461 of file catcache.c.

2462{
2464}

References DatumGetPointer(), and ReleaseCatCacheListWithOwner().

◆ SearchCatCache()

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

Definition at line 1341 of file catcache.c.

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

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

Referenced by SearchSysCache().

◆ SearchCatCache1()

HeapTuple SearchCatCache1 ( CatCache cache,
Datum  v1 
)

Definition at line 1358 of file catcache.c.

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

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache1().

◆ SearchCatCache2()

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

Definition at line 1366 of file catcache.c.

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

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache2().

◆ SearchCatCache3()

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

Definition at line 1374 of file catcache.c.

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

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache3().

◆ SearchCatCache4()

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

Definition at line 1382 of file catcache.c.

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

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

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

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

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

Definition at line 147 of file catcache.c.

Referenced by ResourceOwnerForgetCatCacheListRef(), and ResourceOwnerRememberCatCacheListRef().