PostgreSQL Source Code git master
catcache.h File Reference
#include "access/htup.h"
#include "access/skey.h"
#include "lib/ilist.h"
#include "utils/relcache.h"
Include dependency graph for catcache.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  catcache
 
struct  catctup
 
struct  catclist
 
struct  catcacheheader
 

Macros

#define CATCACHE_MAXKEYS   4
 
#define CT_MAGIC   0x57261502
 
#define CL_MAGIC   0x52765103
 

Typedefs

typedef uint32(* CCHashFN) (Datum datum)
 
typedef bool(* CCFastEqualFN) (Datum a, Datum b)
 
typedef struct catcache CatCache
 
typedef struct catctup CatCTup
 
typedef struct catclist CatCList
 
typedef struct catcacheheader CatCacheHeader
 

Functions

void CreateCacheMemoryContext (void)
 
CatCacheInitCatCache (int id, Oid reloid, Oid indexoid, int nkeys, const int *key, int nbuckets)
 
void InitCatCachePhase2 (CatCache *cache, bool touch_index)
 
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 ResetCatalogCaches (void)
 
void ResetCatalogCachesExt (bool debug_discard)
 
void CatalogCacheFlushCatalog (Oid catId)
 
void CatCacheInvalidate (CatCache *cache, uint32 hashValue)
 
void PrepareToInvalidateCacheTuple (Relation relation, HeapTuple tuple, HeapTuple newtuple, void(*function)(int, uint32, Oid, void *), void *context)
 

Variables

PGDLLIMPORT MemoryContext CacheMemoryContext
 

Macro Definition Documentation

◆ CATCACHE_MAXKEYS

#define CATCACHE_MAXKEYS   4

Definition at line 35 of file catcache.h.

◆ CL_MAGIC

#define CL_MAGIC   0x52765103

Definition at line 162 of file catcache.h.

◆ CT_MAGIC

#define CT_MAGIC   0x57261502

Definition at line 91 of file catcache.h.

Typedef Documentation

◆ CatCache

typedef struct catcache CatCache

◆ CatCacheHeader

◆ CatCList

typedef struct catclist CatCList

◆ CatCTup

typedef struct catctup CatCTup

◆ CCFastEqualFN

typedef bool(* CCFastEqualFN) (Datum a, Datum b)

Definition at line 42 of file catcache.h.

◆ CCHashFN

typedef uint32(* CCHashFN) (Datum datum)

Definition at line 39 of file catcache.h.

Function Documentation

◆ CatalogCacheFlushCatalog()

void CatalogCacheFlushCatalog ( Oid  catId)

Definition at line 834 of file catcache.c.

835{
836 slist_iter iter;
837
838 CACHE_elog(DEBUG2, "CatalogCacheFlushCatalog called for %u", catId);
839
841 {
842 CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
843
844 /* Does this cache store tuples of the target catalog? */
845 if (cache->cc_reloid == catId)
846 {
847 /* Yes, so flush all its contents */
848 ResetCatalogCache(cache, false);
849
850 /* Tell inval.c to call syscache callbacks for this cache */
851 CallSyscacheCallbacks(cache->id, 0);
852 }
853 }
854
855 CACHE_elog(DEBUG2, "end of CatalogCacheFlushCatalog call");
856}
static void ResetCatalogCache(CatCache *cache, bool debug_discard)
Definition: catcache.c:736
static CatCacheHeader * CacheHdr
Definition: catcache.c:84
#define CACHE_elog(...)
Definition: catcache.c:80
#define DEBUG2
Definition: elog.h:29
#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:1765
Oid cc_reloid
Definition: catcache.h:60
int id
Definition: catcache.h:46
slist_head ch_caches
Definition: catcache.h:186
slist_node * cur
Definition: ilist.h:259

References CatCInProgress::cache, CACHE_elog, CacheHdr, CallSyscacheCallbacks(), catcache::cc_reloid, catcacheheader::ch_caches, slist_iter::cur, DEBUG2, catcache::id, ResetCatalogCache(), slist_container, and slist_foreach.

Referenced by LocalExecuteInvalidationMessage().

◆ CatCacheInvalidate()

void CatCacheInvalidate ( CatCache cache,
uint32  hashValue 
)

Definition at line 625 of file catcache.c.

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

◆ CreateCacheMemoryContext()

void CreateCacheMemoryContext ( void  )

Definition at line 708 of file catcache.c.

709{
710 /*
711 * Purely for paranoia, check that context doesn't exist; caller probably
712 * did so already.
713 */
716 "CacheMemoryContext",
718}
MemoryContext TopMemoryContext
Definition: mcxt.c:149
MemoryContext CacheMemoryContext
Definition: mcxt.c:152
#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 1662 of file catcache.c.

1667{
1668 /*
1669 * one-time startup overhead for each cache
1670 */
1671 if (cache->cc_tupdesc == NULL)
1673
1674 /*
1675 * calculate the hash value
1676 */
1677 return CatalogCacheComputeHashValue(cache, cache->cc_nkeys, v1, v2, v3, v4);
1678}
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:1086
static uint32 CatalogCacheComputeHashValue(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:344
int cc_nkeys
Definition: catcache.h:54
TupleDesc cc_tupdesc
Definition: catcache.h:48

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

Referenced by GetSysCacheHashValue().

◆ InitCatCache()

CatCache * InitCatCache ( int  id,
Oid  reloid,
Oid  indexoid,
int  nkeys,
const int *  key,
int  nbuckets 
)

Definition at line 878 of file catcache.c.

884{
885 CatCache *cp;
886 MemoryContext oldcxt;
887 int i;
888
889 /*
890 * nbuckets is the initial number of hash buckets to use in this catcache.
891 * It will be enlarged later if it becomes too full.
892 *
893 * nbuckets must be a power of two. We check this via Assert rather than
894 * a full runtime check because the values will be coming from constant
895 * tables.
896 *
897 * If you're confused by the power-of-two check, see comments in
898 * bitmapset.c for an explanation.
899 */
900 Assert(nbuckets > 0 && (nbuckets & -nbuckets) == nbuckets);
901
902 /*
903 * first switch to the cache context so our allocations do not vanish at
904 * the end of a transaction
905 */
908
910
911 /*
912 * if first time through, initialize the cache group header
913 */
914 if (CacheHdr == NULL)
915 {
918 CacheHdr->ch_ntup = 0;
919#ifdef CATCACHE_STATS
920 /* set up to dump stats at backend exit */
921 on_proc_exit(CatCachePrintStats, 0);
922#endif
923 }
924
925 /*
926 * Allocate a new cache structure, aligning to a cacheline boundary
927 *
928 * Note: we rely on zeroing to initialize all the dlist headers correctly
929 */
932 cp->cc_bucket = palloc0(nbuckets * sizeof(dlist_head));
933
934 /*
935 * Many catcaches never receive any list searches. Therefore, we don't
936 * allocate the cc_lbuckets till we get a list search.
937 */
938 cp->cc_lbucket = NULL;
939
940 /*
941 * initialize the cache's relation information for the relation
942 * corresponding to this cache, and initialize some of the new cache's
943 * other internal fields. But don't open the relation yet.
944 */
945 cp->id = id;
946 cp->cc_relname = "(not known yet)";
947 cp->cc_reloid = reloid;
948 cp->cc_indexoid = indexoid;
949 cp->cc_relisshared = false; /* temporary */
950 cp->cc_tupdesc = (TupleDesc) NULL;
951 cp->cc_ntup = 0;
952 cp->cc_nlist = 0;
953 cp->cc_nbuckets = nbuckets;
954 cp->cc_nlbuckets = 0;
955 cp->cc_nkeys = nkeys;
956 for (i = 0; i < nkeys; ++i)
957 {
959 cp->cc_keyno[i] = key[i];
960 }
961
962 /*
963 * new cache is initialized as far as we can go for now. print some
964 * debugging information, if appropriate.
965 */
967
968 /*
969 * add completed cache to top of group header's list
970 */
972
973 /*
974 * back to the old context before we return...
975 */
976 MemoryContextSwitchTo(oldcxt);
977
978 return cp;
979}
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
void CreateCacheMemoryContext(void)
Definition: catcache.c:708
#define InitCatCache_DEBUG2
Definition: catcache.c:874
#define MCXT_ALLOC_ZERO
Definition: fe_memutils.h:30
static void slist_init(slist_head *head)
Definition: ilist.h:986
static void slist_push_head(slist_head *head, slist_node *node)
Definition: ilist.h:1006
void on_proc_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:309
void * palloc0(Size size)
Definition: mcxt.c:1347
void * palloc(Size size)
Definition: mcxt.c:1317
void * palloc_aligned(Size size, Size alignto, int flags)
Definition: mcxt.c:1511
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
#define PG_CACHE_LINE_SIZE
const char * cc_relname
Definition: catcache.h:59
slist_node cc_next
Definition: catcache.h:63
int cc_keyno[CATCACHE_MAXKEYS]
Definition: catcache.h:53
Oid cc_indexoid
Definition: catcache.h:61
bool cc_relisshared
Definition: catcache.h:62
int cc_ntup
Definition: catcache.h:55
int cc_nlist
Definition: catcache.h:56
struct TupleDescData * TupleDesc
Definition: tupdesc.h:138

References Assert, AttributeNumberIsValid, CacheHdr, CacheMemoryContext, catcache::cc_bucket, catcache::cc_indexoid, catcache::cc_keyno, catcache::cc_lbucket, catcache::cc_nbuckets, catcache::cc_next, catcache::cc_nkeys, catcache::cc_nlbuckets, catcache::cc_nlist, catcache::cc_ntup, catcache::cc_relisshared, catcache::cc_relname, catcache::cc_reloid, catcache::cc_tupdesc, catcacheheader::ch_caches, catcacheheader::ch_ntup, CreateCacheMemoryContext(), i, catcache::id, InitCatCache_DEBUG2, sort-test::key, MCXT_ALLOC_ZERO, MemoryContextSwitchTo(), on_proc_exit(), palloc(), palloc0(), palloc_aligned(), PG_CACHE_LINE_SIZE, slist_init(), and slist_push_head().

Referenced by InitCatalogCache().

◆ InitCatCachePhase2()

void InitCatCachePhase2 ( CatCache cache,
bool  touch_index 
)

Definition at line 1195 of file catcache.c.

1196{
1197 if (cache->cc_tupdesc == NULL)
1199
1200 if (touch_index &&
1201 cache->id != AMOID &&
1202 cache->id != AMNAME)
1203 {
1204 Relation idesc;
1205
1206 /*
1207 * We must lock the underlying catalog before opening the index to
1208 * avoid deadlock, since index_open could possibly result in reading
1209 * this same catalog, and if anyone else is exclusive-locking this
1210 * catalog and index they'll be doing it in that order.
1211 */
1213 idesc = index_open(cache->cc_indexoid, AccessShareLock);
1214
1215 /*
1216 * While we've got the index open, let's check that it's unique (and
1217 * not just deferrable-unique, thank you very much). This is just to
1218 * catch thinkos in definitions of new catcaches, so we don't worry
1219 * about the pg_am indexes not getting tested.
1220 */
1221 Assert(idesc->rd_index->indisunique &&
1222 idesc->rd_index->indimmediate);
1223
1226 }
1227}
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:226
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:107
#define AccessShareLock
Definition: lockdefs.h:36
Form_pg_index rd_index
Definition: rel.h:192

References AccessShareLock, Assert, CatCInProgress::cache, CatalogCacheInitializeCache(), catcache::cc_indexoid, catcache::cc_reloid, catcache::cc_tupdesc, catcache::id, index_close(), index_open(), LockRelationOid(), RelationData::rd_index, and UnlockRelationOid().

Referenced by InitCatalogCachePhase2(), and SysCacheGetAttr().

◆ PrepareToInvalidateCacheTuple()

void PrepareToInvalidateCacheTuple ( Relation  relation,
HeapTuple  tuple,
HeapTuple  newtuple,
void(*)(int, uint32, Oid, void *)  function,
void *  context 
)

Definition at line 2354 of file catcache.c.

2359{
2360 slist_iter iter;
2361 Oid reloid;
2362
2363 CACHE_elog(DEBUG2, "PrepareToInvalidateCacheTuple: called");
2364
2365 /*
2366 * sanity checks
2367 */
2368 Assert(RelationIsValid(relation));
2369 Assert(HeapTupleIsValid(tuple));
2371 Assert(CacheHdr != NULL);
2372
2373 reloid = RelationGetRelid(relation);
2374
2375 /* ----------------
2376 * for each cache
2377 * if the cache contains tuples from the specified relation
2378 * compute the tuple's hash value(s) in this cache,
2379 * and call the passed function to register the information.
2380 * ----------------
2381 */
2382
2384 {
2385 CatCache *ccp = slist_container(CatCache, cc_next, iter.cur);
2386 uint32 hashvalue;
2387 Oid dbid;
2388
2389 if (ccp->cc_reloid != reloid)
2390 continue;
2391
2392 /* Just in case cache hasn't finished initialization yet... */
2393 if (ccp->cc_tupdesc == NULL)
2395
2396 hashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, tuple);
2397 dbid = ccp->cc_relisshared ? (Oid) 0 : MyDatabaseId;
2398
2399 (*function) (ccp->id, hashvalue, dbid, context);
2400
2401 if (newtuple)
2402 {
2403 uint32 newhashvalue;
2404
2405 newhashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, newtuple);
2406
2407 if (newhashvalue != hashvalue)
2408 (*function) (ccp->id, newhashvalue, dbid, context);
2409 }
2410 }
2411}
#define PointerIsValid(pointer)
Definition: c.h:720
uint32_t uint32
Definition: c.h:488
static uint32 CatalogCacheComputeTupleHashValue(CatCache *cache, int nkeys, HeapTuple tuple)
Definition: catcache.c:386
Oid MyDatabaseId
Definition: globals.c:93
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
on_exit_nicely_callback function
unsigned int Oid
Definition: postgres_ext.h:32
#define RelationGetRelid(relation)
Definition: rel.h:505
#define RelationIsValid(relation)
Definition: rel.h:478

References Assert, CACHE_elog, CacheHdr, CatalogCacheComputeTupleHashValue(), CatalogCacheInitializeCache(), catcache::cc_nkeys, catcache::cc_relisshared, catcache::cc_reloid, catcache::cc_tupdesc, catcacheheader::ch_caches, slist_iter::cur, DEBUG2, function, HeapTupleIsValid, catcache::id, MyDatabaseId, PointerIsValid, RelationGetRelid, RelationIsValid, slist_container, and slist_foreach.

Referenced by CacheInvalidateHeapTupleCommon().

◆ ReleaseCatCache()

void ReleaseCatCache ( HeapTuple  tuple)

Definition at line 1623 of file catcache.c.

1624{
1626}
static void ReleaseCatCacheWithOwner(HeapTuple tuple, ResourceOwner resowner)
Definition: catcache.c:1629
ResourceOwner CurrentResourceOwner
Definition: resowner.c:165

References CurrentResourceOwner, and ReleaseCatCacheWithOwner().

Referenced by ReleaseSysCache().

◆ ReleaseCatCacheList()

◆ ResetCatalogCaches()

void ResetCatalogCaches ( void  )

Definition at line 798 of file catcache.c.

799{
801}
void ResetCatalogCachesExt(bool debug_discard)
Definition: catcache.c:804

References ResetCatalogCachesExt().

◆ ResetCatalogCachesExt()

void ResetCatalogCachesExt ( bool  debug_discard)

Definition at line 804 of file catcache.c.

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

References CatCInProgress::cache, CACHE_elog, CacheHdr, catcacheheader::ch_caches, slist_iter::cur, DEBUG2, ResetCatalogCache(), slist_container, and slist_foreach.

Referenced by InvalidateSystemCachesExtended(), and ResetCatalogCaches().

◆ SearchCatCache()

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

Definition at line 1312 of file catcache.c.

1317{
1318 return SearchCatCacheInternal(cache, cache->cc_nkeys, v1, v2, v3, v4);
1319}
static HeapTuple SearchCatCacheInternal(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1363

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

Referenced by SearchSysCache().

◆ SearchCatCache1()

HeapTuple SearchCatCache1 ( CatCache cache,
Datum  v1 
)

Definition at line 1329 of file catcache.c.

1331{
1332 return SearchCatCacheInternal(cache, 1, v1, 0, 0, 0);
1333}

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache1().

◆ SearchCatCache2()

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

Definition at line 1337 of file catcache.c.

1339{
1340 return SearchCatCacheInternal(cache, 2, v1, v2, 0, 0);
1341}

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache2().

◆ SearchCatCache3()

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

Definition at line 1345 of file catcache.c.

1347{
1348 return SearchCatCacheInternal(cache, 3, v1, v2, v3, 0);
1349}

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache3().

◆ SearchCatCache4()

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

Definition at line 1353 of file catcache.c.

1355{
1356 return SearchCatCacheInternal(cache, 4, v1, v2, v3, v4);
1357}

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache4().

◆ SearchCatCacheList()

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

Definition at line 1696 of file catcache.c.

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

References AccessShareLock, Assert, catctup::c_list, CatCInProgress::cache, catclist::cache_elem, CACHE_elog, CacheMemoryContext, CatalogCacheCompareTuple(), CatalogCacheComputeHashValue(), CatalogCacheComputeTupleHashValue(), CatalogCacheCreateEntry(), CatalogCacheInitializeCache(), 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, 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(), catctup::tuple, and unlikely.

Referenced by SearchSysCacheList().

Variable Documentation

◆ CacheMemoryContext

PGDLLIMPORT MemoryContext CacheMemoryContext
extern

Definition at line 152 of file mcxt.c.