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:1894
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}
unsigned int Index
Definition: c.h:585
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
Assert(PointerIsAligned(start, uint64))
#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:77
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:165
MemoryContext CacheMemoryContext
Definition: mcxt.c:168
#define AllocSetContextCreate
Definition: memutils.h:149
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:180

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

1691{
1692 /*
1693 * one-time startup overhead for each cache
1694 */
1696
1697 /*
1698 * calculate the hash value
1699 */
1700 return CatalogCacheComputeHashValue(cache, cache->cc_nkeys, v1, v2, v3, v4);
1701}
static pg_attribute_always_inline void ConditionalCatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:1064
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

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

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:1973
void * palloc(Size size)
Definition: mcxt.c:1943
void * palloc_aligned(Size size, Size alignto, int flags)
Definition: mcxt.c:2140
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
TupleDesc cc_tupdesc
Definition: catcache.h:48
struct TupleDescData * TupleDesc
Definition: tupdesc.h:145

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

Referenced by InitCatalogCache().

◆ InitCatCachePhase2()

void InitCatCachePhase2 ( CatCache cache,
bool  touch_index 
)

Definition at line 1224 of file catcache.c.

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

◆ PrepareToInvalidateCacheTuple()

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

Definition at line 2376 of file catcache.c.

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

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

Referenced by CacheInvalidateHeapTupleCommon().

◆ ReleaseCatCache()

void ReleaseCatCache ( HeapTuple  tuple)

Definition at line 1647 of file catcache.c.

1648{
1650}
static void ReleaseCatCacheWithOwner(HeapTuple tuple, ResourceOwner resowner)
Definition: catcache.c:1653
ResourceOwner CurrentResourceOwner
Definition: resowner.c:173

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

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

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

Referenced by SearchSysCache().

◆ SearchCatCache1()

HeapTuple SearchCatCache1 ( CatCache cache,
Datum  v1 
)

Definition at line 1357 of file catcache.c.

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

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache1().

◆ SearchCatCache2()

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

Definition at line 1365 of file catcache.c.

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

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache2().

◆ SearchCatCache3()

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

Definition at line 1373 of file catcache.c.

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

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache3().

◆ SearchCatCache4()

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

Definition at line 1381 of file catcache.c.

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

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache4().

◆ SearchCatCacheList()

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

Definition at line 1719 of file catcache.c.

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

Variable Documentation

◆ CacheMemoryContext

PGDLLIMPORT MemoryContext CacheMemoryContext
extern

Definition at line 168 of file mcxt.c.