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 169 of file catcache.h.

◆ CT_MAGIC

#define CT_MAGIC   0x57261502

Definition at line 99 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 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
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:191
slist_node * cur
Definition: ilist.h:259

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

Referenced by LocalExecuteInvalidationMessage().

◆ 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:622
static CatCInProgress * catcache_in_progress_stack
Definition: catcache.c:61
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
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:179
bool dead
Definition: catcache.h:180
int refcount
Definition: catcache.h:121
struct catclist * c_list
Definition: catcache.h:133
bool dead
Definition: catcache.h:122
uint32 hash_value
Definition: catcache.h:101
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 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
MemoryContext CacheMemoryContext
Definition: mcxt.c:169
#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 1693 of file catcache.c.

1698{
1699 /*
1700 * one-time startup overhead for each cache
1701 */
1703
1704 /*
1705 * calculate the hash value
1706 */
1707 return CatalogCacheComputeHashValue(cache, cache->cc_nkeys, v1, v2, v3, v4);
1708}
static pg_attribute_always_inline void ConditionalCatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:1071
static uint32 CatalogCacheComputeHashValue(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:345
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 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:1395
void * palloc(Size size)
Definition: mcxt.c:1365
void * palloc_aligned(Size size, Size alignto, int flags)
Definition: mcxt.c:1584
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 1231 of file catcache.c.

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

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

◆ ReleaseCatCache()

void ReleaseCatCache ( HeapTuple  tuple)

Definition at line 1654 of file catcache.c.

1655{
1657}
static void ReleaseCatCacheWithOwner(HeapTuple tuple, ResourceOwner resowner)
Definition: catcache.c:1660
ResourceOwner CurrentResourceOwner
Definition: resowner.c:173

References CurrentResourceOwner, and ReleaseCatCacheWithOwner().

Referenced by ReleaseSysCache().

◆ ReleaseCatCacheList()

◆ 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().

◆ SearchCatCache()

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

Definition at line 1347 of file catcache.c.

1352{
1353 return SearchCatCacheInternal(cache, cache->cc_nkeys, v1, v2, v3, v4);
1354}
static HeapTuple SearchCatCacheInternal(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1398

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

Referenced by SearchSysCache().

◆ SearchCatCache1()

HeapTuple SearchCatCache1 ( CatCache cache,
Datum  v1 
)

Definition at line 1364 of file catcache.c.

1366{
1367 return SearchCatCacheInternal(cache, 1, v1, 0, 0, 0);
1368}

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache1().

◆ SearchCatCache2()

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

Definition at line 1372 of file catcache.c.

1374{
1375 return SearchCatCacheInternal(cache, 2, v1, v2, 0, 0);
1376}

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache2().

◆ SearchCatCache3()

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

Definition at line 1380 of file catcache.c.

1382{
1383 return SearchCatCacheInternal(cache, 3, v1, v2, v3, 0);
1384}

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache3().

◆ SearchCatCache4()

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

Definition at line 1388 of file catcache.c.

1390{
1391 return SearchCatCacheInternal(cache, 4, v1, v2, v3, v4);
1392}

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache4().

◆ SearchCatCacheList()

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

Definition at line 1726 of file catcache.c.

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