36#include "utils/fmgroids.h"
70#define HASH_INDEX(h, sz) ((Index) ((h) & ((sz) - 1)))
78#define CACHE_elog(...) elog(__VA_ARGS__)
80#define CACHE_elog(...)
103 const Datum *cachekeys,
104 const Datum *searchkeys);
107static void CatCachePrintStats(
int code,
Datum arg);
140 .
name =
"catcache reference",
150 .
name =
"catcache list reference",
310 case REGPROCEDUREOID:
315 case REGCOLLATIONOID:
317 case REGDICTIONARYOID:
319 case REGNAMESPACEOID:
328 *eqfunc = F_OIDVECTOREQ;
331 elog(
FATAL,
"type %u not supported as catcache key", keytype);
358 oneHash = (cc_hashfunc[3]) (v4);
362 oneHash = (cc_hashfunc[2]) (v3);
366 oneHash = (cc_hashfunc[1]) (v2);
370 oneHash = (cc_hashfunc[0]) (v1);
371 hashValue ^= oneHash;
374 elog(
FATAL,
"wrong number of hash keys: %d", nkeys);
429 elog(
FATAL,
"wrong number of hash keys: %d", nkeys);
443 const Datum *cachekeys,
444 const Datum *searchkeys)
449 for (
i = 0;
i < nkeys;
i++)
451 if (!(cc_fastequal[
i]) (cachekeys[
i], searchkeys[
i]))
461CatCachePrintStats(
int code,
Datum arg)
479 elog(
DEBUG2,
"catcache %s/%u: %d tup, %" PRIu64
" srch, %" PRIu64
"+%"
480 PRIu64
"=%" PRIu64
" hits, %" PRIu64
"+%" PRIu64
"=%"
481 PRIu64
" loads, %" PRIu64
" invals, %d lists, %" PRIu64
482 " lsrch, %" PRIu64
" lhits",
497 cc_searches +=
cache->cc_searches;
498 cc_hits +=
cache->cc_hits;
499 cc_neg_hits +=
cache->cc_neg_hits;
500 cc_newloads +=
cache->cc_newloads;
501 cc_invals +=
cache->cc_invals;
503 cc_lsearches +=
cache->cc_lsearches;
504 cc_lhits +=
cache->cc_lhits;
506 elog(
DEBUG2,
"catcache totals: %d tup, %" PRIu64
" srch, %" PRIu64
"+%"
507 PRIu64
"=%" PRIu64
" hits, %" PRIu64
"+%" PRIu64
"=%" PRIu64
508 " loads, %" PRIu64
" invals, %" PRIu64
" lists, %" PRIu64
509 " lsrch, %" PRIu64
" lhits",
514 cc_hits + cc_neg_hits,
516 cc_searches - cc_hits - cc_neg_hits - cc_newloads,
517 cc_searches - cc_hits - cc_neg_hits,
593#ifndef CATCACHE_FORCE_RELEASE
695 if (
e->list ||
e->hash_value == hashValue)
723 "CacheMemoryContext",
874#define InitCatCache_DEBUG2 \
876 elog(DEBUG2, "InitCatCache: rel=%u ind=%u id=%d nkeys=%d size=%d", \
877 cp->cc_reloid, cp->cc_indexoid, cp->id, \
878 cp->cc_nkeys, cp->cc_nbuckets); \
881#define InitCatCache_DEBUG2
907 Assert(nbuckets > 0 && (nbuckets & -nbuckets) == nbuckets);
963 for (
i = 0;
i < nkeys; ++
i)
998 elog(
DEBUG1,
"rehashing catalog cache id %d for %s; %d tups, %d buckets",
1036 elog(
DEBUG1,
"rehashing catalog cache id %d for %s; %d lists, %d buckets",
1073#ifdef USE_ASSERT_CHECKING
1101#define CatalogCacheInitializeCache_DEBUG1 \
1102 elog(DEBUG2, "CatalogCacheInitializeCache: cache @%p rel=%u", cache, \
1105#define CatalogCacheInitializeCache_DEBUG2 \
1107 if (cache->cc_keyno[i] > 0) { \
1108 elog(DEBUG2, "CatalogCacheInitializeCache: load %d/%d w/%d, %u", \
1109 i+1, cache->cc_nkeys, cache->cc_keyno[i], \
1110 TupleDescAttr(tupdesc, cache->cc_keyno[i] - 1)->atttypid); \
1112 elog(DEBUG2, "CatalogCacheInitializeCache: load %d/%d w/%d", \
1113 i+1, cache->cc_nkeys, cache->cc_keyno[i]); \
1117#define CatalogCacheInitializeCache_DEBUG1
1118#define CatalogCacheInitializeCache_DEBUG2
1178 keytype = attr->atttypid;
1180 Assert(attr->attnotnull);
1185 elog(
FATAL,
"sys attributes are not supported in caches");
1311 case AUTHMEMMEMROLE:
1419#ifdef CATCACHE_STATS
1420 cache->cc_searches++;
1476#ifdef CATCACHE_STATS
1487#ifdef CATCACHE_STATS
1488 cache->cc_neg_hits++;
1577 hashValue, hashIndex);
1612 hashValue, hashIndex);
1635#ifdef CATCACHE_STATS
1636 cache->cc_newloads++;
1674#ifndef CATCACHE_FORCE_RELEASE
1740 List *
volatile ctlist;
1755 Assert(nkeys > 0 && nkeys < cache->cc_nkeys);
1757#ifdef CATCACHE_STATS
1758 cache->cc_lsearches++;
1819 if (cl->
nkeys != nkeys)
1842#ifdef CATCACHE_STATS
1874 in_progress_ent.
list =
true;
1875 in_progress_ent.
dead =
false;
1883 bool first_iter =
true;
1912 foreach(ctlist_item, ctlist)
1921 in_progress_ent.
dead =
false;
1931 ordered = (scandesc->
irel != NULL);
1941 !in_progress_ent.
dead)
1984 hashValue, hashIndex);
1989 in_progress_ent.
dead =
true;
2001 }
while (in_progress_ent.
dead);
2032 foreach(ctlist_item, ctlist)
2039#ifndef CATCACHE_FORCE_RELEASE
2063 foreach(ctlist_item, ctlist)
2116#ifndef CATCACHE_FORCE_RELEASE
2119 list->refcount == 0)
2159#ifdef USE_ASSERT_CHECKING
2185 in_progress_ent.
list =
false;
2186 in_progress_ent.
dead =
false;
2200 if (in_progress_ent.
dead)
2213 MAXIMUM_ALIGNOF + dtp->
t_len);
2221 (
const char *) dtp->
t_data,
2292 for (
i = 0;
i < nkeys;
i++)
2320 for (
i = 0;
i < nkeys;
i++)
2333 if (att->atttypid == NAMEOID)
2424 (*function) (ccp->
id, hashvalue, dbid, context);
2432 if (newhashvalue != hashvalue)
2433 (*function) (ccp->
id, newhashvalue, dbid, context);
2456 return psprintf(
"cache %s (%d), tuple %u/%u has count %d",
2474 return psprintf(
"cache %s (%d), list %p has count %d",
2475 list->my_cache->cc_relname,
list->my_cache->id,
#define AttributeNumberIsValid(attributeNumber)
#define pg_attribute_always_inline
struct CatCInProgress CatCInProgress
static bool chareqfast(Datum a, Datum b)
CatCache * InitCatCache(int id, Oid reloid, Oid indexoid, int nkeys, const int *key, int nbuckets)
HeapTuple SearchCatCache2(CatCache *cache, Datum v1, Datum v2)
static bool int4eqfast(Datum a, Datum b)
HeapTuple SearchCatCache3(CatCache *cache, Datum v1, Datum v2, Datum v3)
void ReleaseCatCacheList(CatCList *list)
static void CatalogCacheInitializeCache(CatCache *cache)
static pg_noinline HeapTuple SearchCatCacheMiss(CatCache *cache, int nkeys, uint32 hashValue, Index hashIndex, Datum v1, Datum v2, Datum v3, Datum v4)
static bool int2eqfast(Datum a, Datum b)
static void ReleaseCatCacheWithOwner(HeapTuple tuple, ResourceOwner resowner)
static uint32 int4hashfast(Datum datum)
void InitCatCachePhase2(CatCache *cache, bool touch_index)
void ResetCatalogCaches(void)
CatCList * SearchCatCacheList(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3)
static void ResOwnerReleaseCatCache(Datum res)
uint32 GetCatCacheHashValue(CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
static CatCInProgress * catcache_in_progress_stack
static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
static char * ResOwnerPrintCatCache(Datum res)
static void RehashCatCache(CatCache *cp)
static void ResetCatalogCache(CatCache *cache, bool debug_discard)
static CatCTup * CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp, Datum *arguments, uint32 hashValue, Index hashIndex)
static uint32 CatalogCacheComputeTupleHashValue(CatCache *cache, int nkeys, HeapTuple tuple)
HeapTuple SearchCatCache4(CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
static void ResourceOwnerForgetCatCacheListRef(ResourceOwner owner, CatCList *list)
static void CatCacheFreeKeys(TupleDesc tupdesc, int nkeys, const int *attnos, const Datum *keys)
static const ResourceOwnerDesc catcache_resowner_desc
static void ResOwnerReleaseCatCacheList(Datum res)
static void ResourceOwnerRememberCatCacheRef(ResourceOwner owner, HeapTuple tuple)
void PrepareToInvalidateCacheTuple(Relation relation, HeapTuple tuple, HeapTuple newtuple, void(*function)(int, uint32, Oid, void *), void *context)
#define CatalogCacheInitializeCache_DEBUG1
static HeapTuple SearchCatCacheInternal(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
static pg_attribute_always_inline void ConditionalCatalogCacheInitializeCache(CatCache *cache)
static char * ResOwnerPrintCatCacheList(Datum res)
static void ReleaseCatCacheListWithOwner(CatCList *list, ResourceOwner resowner)
static CatCacheHeader * CacheHdr
static uint32 namehashfast(Datum datum)
void CreateCacheMemoryContext(void)
static const ResourceOwnerDesc catlistref_resowner_desc
static bool IndexScanOK(CatCache *cache)
static void GetCCHashEqFuncs(Oid keytype, CCHashFN *hashfunc, RegProcedure *eqfunc, CCFastEqualFN *fasteqfunc)
static uint32 CatalogCacheComputeHashValue(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
static bool CatalogCacheCompareTuple(const CatCache *cache, int nkeys, const Datum *cachekeys, const Datum *searchkeys)
void CatCacheInvalidate(CatCache *cache, uint32 hashValue)
static void ResourceOwnerForgetCatCacheRef(ResourceOwner owner, HeapTuple tuple)
static bool nameeqfast(Datum a, Datum b)
static uint32 charhashfast(Datum datum)
static void RehashCatCacheLists(CatCache *cp)
HeapTuple SearchCatCache1(CatCache *cache, Datum v1)
static void CatCacheCopyKeys(TupleDesc tupdesc, int nkeys, const int *attnos, const Datum *srckeys, Datum *dstkeys)
#define InitCatCache_DEBUG2
static uint32 oidvectorhashfast(Datum datum)
static void ResourceOwnerRememberCatCacheListRef(ResourceOwner owner, CatCList *list)
static bool texteqfast(Datum a, Datum b)
static bool oidvectoreqfast(Datum a, Datum b)
void CatalogCacheFlushCatalog(Oid catId)
static uint32 int2hashfast(Datum datum)
#define CatalogCacheInitializeCache_DEBUG2
static void CatCacheRemoveCList(CatCache *cache, CatCList *cl)
#define HASH_INDEX(h, sz)
static uint32 texthashfast(Datum datum)
void ReleaseCatCache(HeapTuple tuple)
HeapTuple SearchCatCache(CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
void ResetCatalogCachesExt(bool debug_discard)
uint32(* CCHashFN)(Datum datum)
bool(* CCFastEqualFN)(Datum a, Datum b)
Datum datumCopy(Datum value, bool typByVal, int typLen)
Datum DirectFunctionCall2Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2)
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Datum DirectFunctionCall1Coll(PGFunction func, Oid collation, Datum arg1)
#define DirectFunctionCall2(func, arg1, arg2)
#define DirectFunctionCall1(func, arg1)
void systable_endscan(SysScanDesc sysscan)
HeapTuple systable_getnext(SysScanDesc sysscan)
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
uint32 hash_bytes(const unsigned char *k, int keylen)
static uint32 murmurhash32(uint32 data)
Assert(PointerIsAligned(start, uint64))
Datum hashoidvector(PG_FUNCTION_ARGS)
Datum hashtext(PG_FUNCTION_ARGS)
HeapTuple toast_flatten_tuple(HeapTuple tup, TupleDesc tupleDesc)
void heap_freetuple(HeapTuple htup)
HeapTupleData * HeapTuple
HeapTupleHeaderData * HeapTupleHeader
#define HeapTupleIsValid(tuple)
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
static bool HeapTupleHasExternal(const HeapTupleData *tuple)
static Datum fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
#define dlist_foreach(iter, lhead)
static void dlist_delete(dlist_node *node)
static void slist_init(slist_head *head)
static void dlist_push_head(dlist_head *head, dlist_node *node)
#define dlist_foreach_modify(iter, lhead)
static void slist_push_head(slist_head *head, slist_node *node)
#define slist_container(type, membername, ptr)
static void dlist_move_head(dlist_head *head, dlist_node *node)
#define slist_foreach(iter, lhead)
#define dlist_container(type, membername, ptr)
void index_close(Relation relation, LOCKMODE lockmode)
Relation index_open(Oid relationId, LOCKMODE lockmode)
#define INJECTION_POINT(name, arg)
void CallSyscacheCallbacks(int cacheid, uint32 hashvalue)
void on_proc_exit(pg_on_exit_callback function, Datum arg)
bool ItemPointerEquals(const ItemPointerData *pointer1, const ItemPointerData *pointer2)
static OffsetNumber ItemPointerGetOffsetNumber(const ItemPointerData *pointer)
static BlockNumber ItemPointerGetBlockNumber(const ItemPointerData *pointer)
List * lappend(List *list, void *datum)
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
void LockRelationOid(Oid relid, LOCKMODE lockmode)
void * MemoryContextAllocZero(MemoryContext context, Size size)
char * pstrdup(const char *in)
void pfree(void *pointer)
void * palloc0(Size size)
MemoryContext TopMemoryContext
MemoryContext CacheMemoryContext
void * palloc_aligned(Size size, Size alignto, int flags)
#define AllocSetContextCreate
#define ALLOCSET_DEFAULT_SIZES
#define IsBootstrapProcessingMode()
void namestrcpy(Name name, const char *str)
Datum oidvectoreq(PG_FUNCTION_ARGS)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
FormData_pg_attribute * Form_pg_attribute
on_exit_nicely_callback function
static uint32 pg_rotate_left32(uint32 word, int n)
#define PG_CACHE_LINE_SIZE
static int list_length(const List *l)
uint32 pg_prng_uint32(pg_prng_state *state)
pg_prng_state pg_global_prng_state
static bool DatumGetBool(Datum X)
static Datum PointerGetDatum(const void *X)
static Name DatumGetName(Datum X)
static char * DatumGetCString(Datum X)
static Datum NameGetDatum(const NameData *X)
static Pointer DatumGetPointer(Datum X)
static char DatumGetChar(Datum X)
static int16 DatumGetInt16(Datum X)
static int32 DatumGetInt32(Datum X)
char * psprintf(const char *fmt,...)
#define RelationGetForm(relation)
#define RelationGetRelid(relation)
#define RelationGetDescr(relation)
#define RelationGetRelationName(relation)
#define RelationIsValid(relation)
bool criticalRelcachesBuilt
bool criticalSharedRelcachesBuilt
static void AssertCouldGetRelation(void)
ResourceOwner CurrentResourceOwner
void ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
void ResourceOwnerRemember(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
void ResourceOwnerEnlarge(ResourceOwner owner)
#define RELEASE_PRIO_CATCACHE_LIST_REFS
@ RESOURCE_RELEASE_AFTER_LOCKS
#define RELEASE_PRIO_CATCACHE_REFS
#define BTEqualStrategyNumber
struct CatCInProgress * next
StrategyNumber sk_strategy
CCHashFN cc_hashfunc[CATCACHE_MAXKEYS]
int cc_keyno[CATCACHE_MAXKEYS]
CCFastEqualFN cc_fastequal[CATCACHE_MAXKEYS]
ScanKeyData cc_skey[CATCACHE_MAXKEYS]
Datum keys[CATCACHE_MAXKEYS]
CatCTup * members[FLEXIBLE_ARRAY_MEMBER]
Datum keys[CATCACHE_MAXKEYS]
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)
TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc)
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)
struct TupleDescData * TupleDesc
Datum texteq(PG_FUNCTION_ARGS)
bool IsTransactionState(void)