Thanks to visit codestin.com
Credit goes to doxygen.postgresql.org

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

836{
837 slist_iter iter;
838
839 CACHE_elog(DEBUG2, "CatalogCacheFlushCatalog called for %u", catId);
840
842 {
843 CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
844
845 /* Does this cache store tuples of the target catalog? */
846 if (cache->cc_reloid == catId)
847 {
848 /* Yes, so flush all its contents */
849 ResetCatalogCache(cache, false);
850
851 /* Tell inval.c to call syscache callbacks for this cache */
852 CallSyscacheCallbacks(cache->id, 0);
853 }
854 }
855
856 CACHE_elog(DEBUG2, "end of CatalogCacheFlushCatalog call");
857}
static void ResetCatalogCache(CatCache *cache, bool debug_discard)
Definition: catcache.c:737
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 626 of file catcache.c.

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

710{
711 /*
712 * Purely for paranoia, check that context doesn't exist; caller probably
713 * did so already.
714 */
717 "CacheMemoryContext",
719}
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 1687 of file catcache.c.

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

885{
886 CatCache *cp;
887 MemoryContext oldcxt;
888 int i;
889
890 /*
891 * nbuckets is the initial number of hash buckets to use in this catcache.
892 * It will be enlarged later if it becomes too full.
893 *
894 * nbuckets must be a power of two. We check this via Assert rather than
895 * a full runtime check because the values will be coming from constant
896 * tables.
897 *
898 * If you're confused by the power-of-two check, see comments in
899 * bitmapset.c for an explanation.
900 */
901 Assert(nbuckets > 0 && (nbuckets & -nbuckets) == nbuckets);
902
903 /*
904 * first switch to the cache context so our allocations do not vanish at
905 * the end of a transaction
906 */
909
911
912 /*
913 * if first time through, initialize the cache group header
914 */
915 if (CacheHdr == NULL)
916 {
919 CacheHdr->ch_ntup = 0;
920#ifdef CATCACHE_STATS
921 /* set up to dump stats at backend exit */
922 on_proc_exit(CatCachePrintStats, 0);
923#endif
924 }
925
926 /*
927 * Allocate a new cache structure, aligning to a cacheline boundary
928 *
929 * Note: we rely on zeroing to initialize all the dlist headers correctly
930 */
933 cp->cc_bucket = palloc0(nbuckets * sizeof(dlist_head));
934
935 /*
936 * Many catcaches never receive any list searches. Therefore, we don't
937 * allocate the cc_lbuckets till we get a list search.
938 */
939 cp->cc_lbucket = NULL;
940
941 /*
942 * initialize the cache's relation information for the relation
943 * corresponding to this cache, and initialize some of the new cache's
944 * other internal fields. But don't open the relation yet.
945 */
946 cp->id = id;
947 cp->cc_relname = "(not known yet)";
948 cp->cc_reloid = reloid;
949 cp->cc_indexoid = indexoid;
950 cp->cc_relisshared = false; /* temporary */
951 cp->cc_tupdesc = (TupleDesc) NULL;
952 cp->cc_ntup = 0;
953 cp->cc_nlist = 0;
954 cp->cc_nbuckets = nbuckets;
955 cp->cc_nlbuckets = 0;
956 cp->cc_nkeys = nkeys;
957 for (i = 0; i < nkeys; ++i)
958 {
960 cp->cc_keyno[i] = key[i];
961 }
962
963 /*
964 * new cache is initialized as far as we can go for now. print some
965 * debugging information, if appropriate.
966 */
968
969 /*
970 * add completed cache to top of group header's list
971 */
973
974 /*
975 * back to the old context before we return...
976 */
977 MemoryContextSwitchTo(oldcxt);
978
979 return cp;
980}
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
void CreateCacheMemoryContext(void)
Definition: catcache.c:709
#define InitCatCache_DEBUG2
Definition: catcache.c:875
#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 1225 of file catcache.c.

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

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

Referenced by CacheInvalidateHeapTupleCommon().

◆ ReleaseCatCache()

void ReleaseCatCache ( HeapTuple  tuple)

Definition at line 1648 of file catcache.c.

1649{
1651}
static void ReleaseCatCacheWithOwner(HeapTuple tuple, ResourceOwner resowner)
Definition: catcache.c:1654
ResourceOwner CurrentResourceOwner
Definition: resowner.c:173

References CurrentResourceOwner, and ReleaseCatCacheWithOwner().

Referenced by ReleaseSysCache().

◆ ReleaseCatCacheList()

◆ ResetCatalogCaches()

void ResetCatalogCaches ( void  )

Definition at line 799 of file catcache.c.

800{
802}
void ResetCatalogCachesExt(bool debug_discard)
Definition: catcache.c:805

References ResetCatalogCachesExt().

◆ ResetCatalogCachesExt()

void ResetCatalogCachesExt ( bool  debug_discard)

Definition at line 805 of file catcache.c.

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

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

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

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

Referenced by SearchSysCache().

◆ SearchCatCache1()

HeapTuple SearchCatCache1 ( CatCache cache,
Datum  v1 
)

Definition at line 1358 of file catcache.c.

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

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache1().

◆ SearchCatCache2()

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

Definition at line 1366 of file catcache.c.

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

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache2().

◆ SearchCatCache3()

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

Definition at line 1374 of file catcache.c.

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

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache3().

◆ SearchCatCache4()

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

Definition at line 1382 of file catcache.c.

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

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache4().

◆ SearchCatCacheList()

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

Definition at line 1720 of file catcache.c.

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