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

◆ CatalogCacheInitializeCache_DEBUG2

#define CatalogCacheInitializeCache_DEBUG2

Definition at line 1132 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:552
#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 2154 of file catcache.c.

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

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

2326{
2327 int i;
2328
2329 /*
2330 * XXX: memory and lookup performance could possibly be improved by
2331 * storing all keys in one allocation.
2332 */
2333
2334 for (i = 0; i < nkeys; i++)
2335 {
2336 int attnum = attnos[i];
2337 Form_pg_attribute att = TupleDescAttr(tupdesc, attnum - 1);
2338 Datum src = srckeys[i];
2339 NameData srcname;
2340
2341 /*
2342 * Must be careful in case the caller passed a C string where a NAME
2343 * is wanted: convert the given argument to a correctly padded NAME.
2344 * Otherwise the memcpy() done by datumCopy() could fall off the end
2345 * of memory.
2346 */
2347 if (att->atttypid == NAMEOID)
2348 {
2349 namestrcpy(&srcname, DatumGetCString(src));
2350 src = NameGetDatum(&srcname);
2351 }
2352
2353 dstkeys[i] = datumCopy(src,
2354 att->attbyval,
2355 att->attlen);
2356 }
2357}
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:365
static Datum NameGetDatum(const NameData *X)
Definition: postgres.h:403
Definition: c.h:766

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

2303{
2304 int i;
2305
2306 for (i = 0; i < nkeys; i++)
2307 {
2308 int attnum = attnos[i];
2309
2310 /* system attribute are not supported in caches */
2311 Assert(attnum > 0);
2312
2313 if (!TupleDescCompactAttr(tupdesc, attnum - 1)->attbyval)
2314 pfree(DatumGetPointer(keys[i]));
2315 }
2316}
void pfree(void *pointer)
Definition: mcxt.c:1616
bool attbyval
Definition: pg_attribute.h:94
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:342
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:634
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:176
bool dead
Definition: catcache.h:177
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:2302
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:163
CatCache * my_cache
Definition: catcache.h:181
short nkeys
Definition: catcache.h:179
Datum keys[CATCACHE_MAXKEYS]
Definition: catcache.h:174
CatCTup * members[FLEXIBLE_ARRAY_MEMBER]
Definition: catcache.h:182
int n_members
Definition: catcache.h:180

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:548
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 1085 of file catcache.c.

1086{
1087#ifdef USE_ASSERT_CHECKING
1088 /*
1089 * TypeCacheRelCallback() runs outside transactions and relies on TYPEOID
1090 * for hashing. This isn't ideal. Since lookup_type_cache() both
1091 * registers the callback and searches TYPEOID, reaching trouble likely
1092 * requires OOM at an unlucky moment.
1093 *
1094 * InvalidateAttoptCacheCallback() runs outside transactions and likewise
1095 * relies on ATTNUM. InitPostgres() initializes ATTNUM, so it's reliable.
1096 */
1097 if (!(cache->id == TYPEOID || cache->id == ATTNUM) ||
1100 else
1101 Assert(cache->cc_tupdesc != NULL);
1102#endif
1103
1104 if (unlikely(cache->cc_tupdesc == NULL))
1106}
#define unlikely(x)
Definition: c.h:418
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:1136
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 1707 of file catcache.c.

1712{
1713 /*
1714 * one-time startup overhead for each cache
1715 */
1717
1718 /*
1719 * calculate the hash value
1720 */
1721 return CatalogCacheComputeHashValue(cache, cache->cc_nkeys, v1, v2, v3, v4);
1722}
static pg_attribute_always_inline void ConditionalCatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:1085

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

1297{
1298 switch (cache->id)
1299 {
1300 case INDEXRELID:
1301
1302 /*
1303 * Rather than tracking exactly which indexes have to be loaded
1304 * before we can use indexscans (which changes from time to time),
1305 * just force all pg_index searches to be heap scans until we've
1306 * built the critical relcaches.
1307 */
1309 return false;
1310 break;
1311
1312 case AMOID:
1313 case AMNAME:
1314
1315 /*
1316 * Always do heap scans in pg_am, because it's so small there's
1317 * not much point in an indexscan anyway. We *must* do this when
1318 * initially building critical relcache entries, but we might as
1319 * well just always do it.
1320 */
1321 return false;
1322
1323 case AUTHNAME:
1324 case AUTHOID:
1325 case AUTHMEMMEMROLE:
1326 case DATABASEOID:
1327
1328 /*
1329 * Protect authentication lookups occurring before relcache has
1330 * collected entries for shared indexes.
1331 */
1333 return false;
1334 break;
1335
1336 default:
1337 break;
1338 }
1339
1340 /* Normal case, allow index scan */
1341 return true;
1342}
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:1417
void * palloc_aligned(Size size, Size alignto, int flags)
Definition: mcxt.c:1606
#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(), palloc0(), palloc_aligned(), palloc_object, PG_CACHE_LINE_SIZE, slist_init(), and slist_push_head().

Referenced by InitCatalogCache().

◆ InitCatCachePhase2()

void InitCatCachePhase2 ( CatCache cache,
bool  touch_index 
)

Definition at line 1245 of file catcache.c.

1246{
1248
1249 if (touch_index &&
1250 cache->id != AMOID &&
1251 cache->id != AMNAME)
1252 {
1253 Relation idesc;
1254
1255 /*
1256 * We must lock the underlying catalog before opening the index to
1257 * avoid deadlock, since index_open could possibly result in reading
1258 * this same catalog, and if anyone else is exclusive-locking this
1259 * catalog and index they'll be doing it in that order.
1260 */
1262 idesc = index_open(cache->cc_indexoid, AccessShareLock);
1263
1264 /*
1265 * While we've got the index open, let's check that it's unique (and
1266 * not just deferrable-unique, thank you very much). This is just to
1267 * catch thinkos in definitions of new catcaches, so we don't worry
1268 * about the pg_am indexes not getting tested.
1269 */
1270 Assert(idesc->rd_index->indisunique &&
1271 idesc->rd_index->indimmediate);
1272
1275 }
1276}
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:771
#define NAMEDATALEN
static Name DatumGetName(Datum X)
Definition: postgres.h:390

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:686
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:684
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 2394 of file catcache.c.

2399{
2400 slist_iter iter;
2401 Oid reloid;
2402
2403 CACHE_elog(DEBUG2, "PrepareToInvalidateCacheTuple: called");
2404
2405 /*
2406 * sanity checks
2407 */
2408 Assert(RelationIsValid(relation));
2409 Assert(HeapTupleIsValid(tuple));
2411 Assert(CacheHdr != NULL);
2412
2413 reloid = RelationGetRelid(relation);
2414
2415 /* ----------------
2416 * for each cache
2417 * if the cache contains tuples from the specified relation
2418 * compute the tuple's hash value(s) in this cache,
2419 * and call the passed function to register the information.
2420 * ----------------
2421 */
2422
2424 {
2425 CatCache *ccp = slist_container(CatCache, cc_next, iter.cur);
2426 uint32 hashvalue;
2427 Oid dbid;
2428
2429 if (ccp->cc_reloid != reloid)
2430 continue;
2431
2432 /* Just in case cache hasn't finished initialization yet... */
2434
2435 hashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, tuple);
2436 dbid = ccp->cc_relisshared ? (Oid) 0 : MyDatabaseId;
2437
2438 (*function) (ccp->id, hashvalue, dbid, context);
2439
2440 if (newtuple)
2441 {
2442 uint32 newhashvalue;
2443
2444 newhashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, newtuple);
2445
2446 if (newhashvalue != hashvalue)
2447 (*function) (ccp->id, newhashvalue, dbid, context);
2448 }
2449 }
2450}
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
1017 /*
1018 * Note that each item is pushed at the tail of the new bucket,
1019 * not its head. This is consistent with the SearchCatCache*()
1020 * routines, where matching entries are moved at the front of the
1021 * list to speed subsequent searches.
1022 */
1023 dlist_push_tail(&newbucket[hashIndex], &ct->cache_elem);
1024 }
1025 }
1026
1027 /* Switch to the new array. */
1028 pfree(cp->cc_bucket);
1029 cp->cc_nbuckets = newnbuckets;
1030 cp->cc_bucket = newbucket;
1031}
#define DEBUG1
Definition: elog.h:30
static void dlist_push_tail(dlist_head *head, dlist_node *node)
Definition: ilist.h:364
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1266

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

1038{
1039 dlist_head *newbucket;
1040 int newnbuckets;
1041 int i;
1042
1043 elog(DEBUG1, "rehashing catalog cache id %d for %s; %d lists, %d buckets",
1044 cp->id, cp->cc_relname, cp->cc_nlist, cp->cc_nlbuckets);
1045
1046 /* Allocate a new, larger, hash table. */
1047 newnbuckets = cp->cc_nlbuckets * 2;
1048 newbucket = (dlist_head *) MemoryContextAllocZero(CacheMemoryContext, newnbuckets * sizeof(dlist_head));
1049
1050 /* Move all entries from old hash table to new. */
1051 for (i = 0; i < cp->cc_nlbuckets; i++)
1052 {
1053 dlist_mutable_iter iter;
1054
1055 dlist_foreach_modify(iter, &cp->cc_lbucket[i])
1056 {
1057 CatCList *cl = dlist_container(CatCList, cache_elem, iter.cur);
1058 int hashIndex = HASH_INDEX(cl->hash_value, newnbuckets);
1059
1060 dlist_delete(iter.cur);
1061
1062 /*
1063 * Note that each item is pushed at the tail of the new bucket,
1064 * not its head. This is consistent with the SearchCatCache*()
1065 * routines, where matching entries are moved at the front of the
1066 * list to speed subsequent searches.
1067 */
1068 dlist_push_tail(&newbucket[hashIndex], &cl->cache_elem);
1069 }
1070 }
1071
1072 /* Switch to the new array. */
1073 pfree(cp->cc_lbucket);
1074 cp->cc_nlbuckets = newnbuckets;
1075 cp->cc_lbucket = newbucket;
1076}
uint32 hash_value
Definition: catcache.h:168

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_tail(), elog, HASH_INDEX, catclist::hash_value, i, catcache::id, MemoryContextAllocZero(), and pfree().

Referenced by SearchCatCacheList().

◆ ReleaseCatCache()

void ReleaseCatCache ( HeapTuple  tuple)

Definition at line 1668 of file catcache.c.

1669{
1671}
static void ReleaseCatCacheWithOwner(HeapTuple tuple, ResourceOwner resowner)
Definition: catcache.c:1674
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 2120 of file catcache.c.

2121{
2122 /* Safety checks to ensure we were handed a cache entry */
2123 Assert(list->cl_magic == CL_MAGIC);
2124 Assert(list->refcount > 0);
2125 list->refcount--;
2126 if (resowner)
2128
2129 if (
2130#ifndef CATCACHE_FORCE_RELEASE
2131 list->dead &&
2132#endif
2133 list->refcount == 0)
2134 CatCacheRemoveCList(list->my_cache, list);
2135}
static void ResourceOwnerForgetCatCacheListRef(ResourceOwner owner, CatCList *list)
Definition: catcache.c:174
#define CL_MAGIC
Definition: catcache.h:166

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

Referenced by ReleaseCatCacheList(), and ResOwnerReleaseCatCacheList().

◆ ReleaseCatCacheWithOwner()

static void ReleaseCatCacheWithOwner ( HeapTuple  tuple,
ResourceOwner  resowner 
)
static

Definition at line 1674 of file catcache.c.

1675{
1676 CatCTup *ct = (CatCTup *) (((char *) tuple) -
1677 offsetof(CatCTup, tuple));
1678
1679 /* Safety checks to ensure we were handed a cache entry */
1680 Assert(ct->ct_magic == CT_MAGIC);
1681 Assert(ct->refcount > 0);
1682
1683 ct->refcount--;
1684 if (resowner)
1685 ResourceOwnerForgetCatCacheRef(resowner, &ct->tuple);
1686
1687 if (
1688#ifndef CATCACHE_FORCE_RELEASE
1689 ct->dead &&
1690#endif
1691 ct->refcount == 0 &&
1692 (ct->c_list == NULL || ct->c_list->refcount == 0))
1694}
static void ResourceOwnerForgetCatCacheRef(ResourceOwner owner, HeapTuple tuple)
Definition: catcache.c:164

References Assert(), catctup::c_list, CatCacheRemoveCTup(), catctup::ct_magic, CT_MAGIC, 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:352
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 2461 of file catcache.c.

2462{
2463 HeapTuple tuple = (HeapTuple) DatumGetPointer(res);
2464 CatCTup *ct = (CatCTup *) (((char *) tuple) -
2465 offsetof(CatCTup, tuple));
2466
2467 /* Safety check to ensure we were handed a cache entry */
2468 Assert(ct->ct_magic == CT_MAGIC);
2469
2470 return psprintf("cache %s (%d), tuple %u/%u has count %d",
2471 ct->my_cache->cc_relname, ct->my_cache->id,
2474 ct->refcount);
2475}
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 2484 of file catcache.c.

2485{
2487
2488 return psprintf("cache %s (%d), list %p has count %d",
2489 list->my_cache->cc_relname, list->my_cache->id,
2490 list, list->refcount);
2491}

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

◆ ResOwnerReleaseCatCache()

static void ResOwnerReleaseCatCache ( Datum  res)
static

Definition at line 2455 of file catcache.c.

2456{
2458}

References DatumGetPointer(), and ReleaseCatCacheWithOwner().

◆ ResOwnerReleaseCatCacheList()

static void ResOwnerReleaseCatCacheList ( Datum  res)
static

Definition at line 2478 of file catcache.c.

2479{
2481}

References DatumGetPointer(), and ReleaseCatCacheListWithOwner().

◆ SearchCatCache()

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

Definition at line 1361 of file catcache.c.

1366{
1367 return SearchCatCacheInternal(cache, cache->cc_nkeys, v1, v2, v3, v4);
1368}
static HeapTuple SearchCatCacheInternal(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1412

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

Referenced by SearchSysCache().

◆ SearchCatCache1()

HeapTuple SearchCatCache1 ( CatCache cache,
Datum  v1 
)

Definition at line 1378 of file catcache.c.

1380{
1381 return SearchCatCacheInternal(cache, 1, v1, 0, 0, 0);
1382}

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache1().

◆ SearchCatCache2()

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

Definition at line 1386 of file catcache.c.

1388{
1389 return SearchCatCacheInternal(cache, 2, v1, v2, 0, 0);
1390}

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache2().

◆ SearchCatCache3()

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

Definition at line 1394 of file catcache.c.

1396{
1397 return SearchCatCacheInternal(cache, 3, v1, v2, v3, 0);
1398}

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache3().

◆ SearchCatCache4()

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

Definition at line 1402 of file catcache.c.

1404{
1405 return SearchCatCacheInternal(cache, 4, v1, v2, v3, v4);
1406}

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

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

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

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

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

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:2455
static char * ResOwnerPrintCatCache(Datum res)
Definition: catcache.c:2461
@ 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:2478
static char * ResOwnerPrintCatCacheList(Datum res)
Definition: catcache.c:2484
#define RELEASE_PRIO_CATCACHE_LIST_REFS
Definition: resowner.h:72

Definition at line 147 of file catcache.c.

Referenced by ResourceOwnerForgetCatCacheListRef(), and ResourceOwnerRememberCatCacheListRef().