PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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 166 of file catcache.h.

◆ CT_MAGIC

#define CT_MAGIC   0x57261502

Definition at line 99 of file catcache.h.

Typedef Documentation

◆ CatCache

◆ CatCacheHeader

◆ CatCList

◆ 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)
extern

Definition at line 852 of file catcache.c.

853{
854 slist_iter iter;
855
856 CACHE_elog(DEBUG2, "CatalogCacheFlushCatalog called for %u", catId);
857
859 {
860 CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
861
862 /* Does this cache store tuples of the target catalog? */
863 if (cache->cc_reloid == catId)
864 {
865 /* Yes, so flush all its contents */
866 ResetCatalogCache(cache, false);
867
868 /* Tell inval.c to call syscache callbacks for this cache */
869 CallSyscacheCallbacks(cache->id, 0);
870 }
871 }
872
873 CACHE_elog(DEBUG2, "end of CatalogCacheFlushCatalog call");
874}
static void ResetCatalogCache(CatCache *cache, bool debug_discard)
Definition catcache.c:754
static CatCacheHeader * CacheHdr
Definition catcache.c:84
#define CACHE_elog(...)
Definition catcache.c:80
#define DEBUG2
Definition elog.h:30
#define slist_container(type, membername, ptr)
Definition ilist.h:1106
#define slist_foreach(iter, lhead)
Definition ilist.h:1132
void CallSyscacheCallbacks(SysCacheIdentifier cacheid, uint32 hashvalue)
Definition inval.c:1898
Oid cc_reloid
Definition catcache.h:60
int id
Definition catcache.h:46
slist_head ch_caches
Definition catcache.h:188
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 
)
extern

Definition at line 643 of file catcache.c.

644{
647
648 CACHE_elog(DEBUG2, "CatCacheInvalidate: called");
649
650 /*
651 * We don't bother to check whether the cache has finished initialization
652 * yet; if not, there will be no entries in it so no problem.
653 */
654
655 /*
656 * Invalidate *all* CatCLists in this cache; it's too hard to tell which
657 * searches might still be correct, so just zap 'em all.
658 */
659 for (int i = 0; i < cache->cc_nlbuckets; i++)
660 {
661 dlist_head *bucket = &cache->cc_lbucket[i];
662
664 {
665 CatCList *cl = dlist_container(CatCList, cache_elem, iter.cur);
666
667 if (cl->refcount > 0)
668 cl->dead = true;
669 else
670 CatCacheRemoveCList(cache, cl);
671 }
672 }
673
674 /*
675 * inspect the proper hash bucket for tuple matches
676 */
677 hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
679 {
680 CatCTup *ct = dlist_container(CatCTup, cache_elem, iter.cur);
681
682 if (hashValue == ct->hash_value)
683 {
684 if (ct->refcount > 0 ||
685 (ct->c_list && ct->c_list->refcount > 0))
686 {
687 ct->dead = true;
688 /* list, if any, was marked dead above */
689 Assert(ct->c_list == NULL || ct->c_list->dead);
690 }
691 else
692 CatCacheRemoveCTup(cache, ct);
693 CACHE_elog(DEBUG2, "CatCacheInvalidate: invalidated");
694#ifdef CATCACHE_STATS
695 cache->cc_invals++;
696#endif
697 /* could be multiple matches, so keep looking! */
698 }
699 }
700
701 /* Also invalidate any entries that are being built */
703 {
704 if (e->cache == cache)
705 {
706 if (e->list || e->hash_value == hashValue)
707 e->dead = true;
708 }
709 }
710}
#define Assert(condition)
Definition c.h:943
unsigned int Index
Definition c.h:698
static CatCInProgress * catcache_in_progress_stack
Definition catcache.c:61
static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
Definition catcache.c:546
static void CatCacheRemoveCList(CatCache *cache, CatCList *cl)
Definition catcache.c:588
#define HASH_INDEX(h, sz)
Definition catcache.c:70
#define dlist_foreach_modify(iter, lhead)
Definition ilist.h:640
#define dlist_container(type, membername, ptr)
Definition ilist.h:593
int i
Definition isn.c:77
e
static int fb(int x)
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
dlist_node * cur
Definition ilist.h:200

References Assert, 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, DEBUG2, dlist_container, dlist_foreach_modify, fb(), HASH_INDEX, i, and CatCInProgress::next.

Referenced by SysCacheInvalidate().

◆ CreateCacheMemoryContext()

void CreateCacheMemoryContext ( void  )
extern

Definition at line 726 of file catcache.c.

727{
728 /*
729 * Purely for paranoia, check that context doesn't exist; caller probably
730 * did so already.
731 */
734 "CacheMemoryContext",
736}
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 
)
extern

Definition at line 1718 of file catcache.c.

1723{
1724 /*
1725 * one-time startup overhead for each cache
1726 */
1728
1729 /*
1730 * calculate the hash value
1731 */
1732 return CatalogCacheComputeHashValue(cache, cache->cc_nkeys, v1, v2, v3, v4);
1733}
static pg_attribute_always_inline void ConditionalCatalogCacheInitializeCache(CatCache *cache)
Definition catcache.c:1096
static uint32 CatalogCacheComputeHashValue(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition catcache.c:356
int cc_nkeys
Definition catcache.h:54

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

Referenced by GetSysCacheHashValue().

◆ InitCatCache()

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

Definition at line 896 of file catcache.c.

902{
903 CatCache *cp;
905 int i;
906
907 /*
908 * nbuckets is the initial number of hash buckets to use in this catcache.
909 * It will be enlarged later if it becomes too full.
910 *
911 * nbuckets must be a power of two. We check this via Assert rather than
912 * a full runtime check because the values will be coming from constant
913 * tables.
914 *
915 * If you're confused by the power-of-two check, see comments in
916 * bitmapset.c for an explanation.
917 */
918 Assert(nbuckets > 0 && (nbuckets & -nbuckets) == nbuckets);
919
920 /*
921 * first switch to the cache context so our allocations do not vanish at
922 * the end of a transaction
923 */
926
928
929 /*
930 * if first time through, initialize the cache group header
931 */
932 if (CacheHdr == NULL)
933 {
936 CacheHdr->ch_ntup = 0;
937#ifdef CATCACHE_STATS
938 /* set up to dump stats at backend exit */
940#endif
941 }
942
943 /*
944 * Allocate a new cache structure, aligning to a cacheline boundary
945 *
946 * Note: we rely on zeroing to initialize all the dlist headers correctly
947 */
950 cp->cc_bucket = palloc0(nbuckets * sizeof(dlist_head));
951
952 /*
953 * Many catcaches never receive any list searches. Therefore, we don't
954 * allocate the cc_lbuckets till we get a list search.
955 */
956 cp->cc_lbucket = NULL;
957
958 /*
959 * initialize the cache's relation information for the relation
960 * corresponding to this cache, and initialize some of the new cache's
961 * other internal fields. But don't open the relation yet.
962 */
963 cp->id = id;
964 cp->cc_relname = "(not known yet)";
965 cp->cc_reloid = reloid;
966 cp->cc_indexoid = indexoid;
967 cp->cc_relisshared = false; /* temporary */
968 cp->cc_tupdesc = (TupleDesc) NULL;
969 cp->cc_ntup = 0;
970 cp->cc_nlist = 0;
971 cp->cc_nbuckets = nbuckets;
972 cp->cc_nlbuckets = 0;
973 cp->cc_nkeys = nkeys;
974 for (i = 0; i < nkeys; ++i)
975 {
977 cp->cc_keyno[i] = key[i];
978 }
979
980 /*
981 * new cache is initialized as far as we can go for now. print some
982 * debugging information, if appropriate.
983 */
985
986 /*
987 * add completed cache to top of group header's list
988 */
989 slist_push_head(&CacheHdr->ch_caches, &cp->cc_next);
990
991 /*
992 * back to the old context before we return...
993 */
995
996 return cp;
997}
#define AttributeNumberIsValid(attributeNumber)
Definition attnum.h:34
void CreateCacheMemoryContext(void)
Definition catcache.c:726
#define InitCatCache_DEBUG2
Definition catcache.c:892
#define MCXT_ALLOC_ZERO
Definition fe_memutils.h:30
#define palloc_object(type)
Definition fe_memutils.h:74
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:316
void * palloc0(Size size)
Definition mcxt.c:1417
void * palloc_aligned(Size size, Size alignto, int flags)
Definition mcxt.c:1606
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
#define PG_CACHE_LINE_SIZE
struct TupleDescData * TupleDesc
Definition tupdesc.h:163

References Assert, AttributeNumberIsValid, CacheHdr, CacheMemoryContext, catcacheheader::ch_caches, catcacheheader::ch_ntup, CreateCacheMemoryContext(), fb(), i, InitCatCache_DEBUG2, MCXT_ALLOC_ZERO, MemoryContextSwitchTo(), on_proc_exit(), palloc0(), palloc_aligned(), palloc_object, PG_CACHE_LINE_SIZE, slist_init(), and slist_push_head().

Referenced by InitCatalogCache().

◆ InitCatCachePhase2()

void InitCatCachePhase2 ( CatCache cache,
bool  touch_index 
)
extern

Definition at line 1256 of file catcache.c.

1257{
1259
1260 if (touch_index &&
1261 cache->id != AMOID &&
1262 cache->id != AMNAME)
1263 {
1265
1266 /*
1267 * We must lock the underlying catalog before opening the index to
1268 * avoid deadlock, since index_open could possibly result in reading
1269 * this same catalog, and if anyone else is exclusive-locking this
1270 * catalog and index they'll be doing it in that order.
1271 */
1274
1275 /*
1276 * While we've got the index open, let's check that it's unique (and
1277 * not just deferrable-unique, thank you very much). This is just to
1278 * catch thinkos in definitions of new catcaches, so we don't worry
1279 * about the pg_am indexes not getting tested.
1280 */
1281 Assert(idesc->rd_index->indisunique &&
1282 idesc->rd_index->indimmediate);
1283
1286 }
1287}
void index_close(Relation relation, LOCKMODE lockmode)
Definition indexam.c:178
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition indexam.c:134
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
Oid cc_indexoid
Definition catcache.h:61

References AccessShareLock, Assert, CatCInProgress::cache, catcache::cc_indexoid, catcache::cc_reloid, ConditionalCatalogCacheInitializeCache(), fb(), catcache::id, index_close(), index_open(), LockRelationOid(), and UnlockRelationOid().

Referenced by InitCatalogCachePhase2(), and SysCacheGetAttr().

◆ PrepareToInvalidateCacheTuple()

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

Definition at line 2403 of file catcache.c.

2408{
2409 slist_iter iter;
2410 Oid reloid;
2411
2412 CACHE_elog(DEBUG2, "PrepareToInvalidateCacheTuple: called");
2413
2414 /*
2415 * sanity checks
2416 */
2417 Assert(RelationIsValid(relation));
2418 Assert(HeapTupleIsValid(tuple));
2420 Assert(CacheHdr != NULL);
2421
2422 reloid = RelationGetRelid(relation);
2423
2424 /* ----------------
2425 * for each cache
2426 * if the cache contains tuples from the specified relation
2427 * compute the tuple's hash value(s) in this cache,
2428 * and call the passed function to register the information.
2429 * ----------------
2430 */
2431
2433 {
2434 CatCache *ccp = slist_container(CatCache, cc_next, iter.cur);
2435 uint32 hashvalue;
2436 Oid dbid;
2437
2438 if (ccp->cc_reloid != reloid)
2439 continue;
2440
2441 /* Just in case cache hasn't finished initialization yet... */
2443
2444 hashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, tuple);
2445 dbid = ccp->cc_relisshared ? (Oid) 0 : MyDatabaseId;
2446
2447 (*function) (ccp->id, hashvalue, dbid, context);
2448
2449 if (newtuple)
2450 {
2452
2453 newhashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, newtuple);
2454
2455 if (newhashvalue != hashvalue)
2456 (*function) (ccp->id, newhashvalue, dbid, context);
2457 }
2458 }
2459}
uint32_t uint32
Definition c.h:624
static uint32 CatalogCacheComputeTupleHashValue(CatCache *cache, int nkeys, HeapTuple tuple)
Definition catcache.c:398
Oid MyDatabaseId
Definition globals.c:96
#define HeapTupleIsValid(tuple)
Definition htup.h:78
on_exit_nicely_callback function
unsigned int Oid
#define RelationGetRelid(relation)
Definition rel.h:516
#define RelationIsValid(relation)
Definition rel.h:491

References Assert, CACHE_elog, CacheHdr, CatalogCacheComputeTupleHashValue(), catcacheheader::ch_caches, ConditionalCatalogCacheInitializeCache(), slist_iter::cur, DEBUG2, fb(), function, HeapTupleIsValid, MyDatabaseId, RelationGetRelid, RelationIsValid, slist_container, and slist_foreach.

Referenced by CacheInvalidateHeapTupleCommon().

◆ ReleaseCatCache()

void ReleaseCatCache ( HeapTuple  tuple)
extern

Definition at line 1679 of file catcache.c.

1680{
1682}
static void ReleaseCatCacheWithOwner(HeapTuple tuple, ResourceOwner resowner)
Definition catcache.c:1685
ResourceOwner CurrentResourceOwner
Definition resowner.c:173

References CurrentResourceOwner, and ReleaseCatCacheWithOwner().

Referenced by ReleaseSysCache().

◆ ReleaseCatCacheList()

◆ ResetCatalogCaches()

void ResetCatalogCaches ( void  )
extern

Definition at line 816 of file catcache.c.

817{
819}
void ResetCatalogCachesExt(bool debug_discard)
Definition catcache.c:822

References ResetCatalogCachesExt().

◆ ResetCatalogCachesExt()

void ResetCatalogCachesExt ( bool  debug_discard)
extern

Definition at line 822 of file catcache.c.

823{
824 slist_iter iter;
825
826 CACHE_elog(DEBUG2, "ResetCatalogCaches called");
827
829 {
830 CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
831
833 }
834
835 CACHE_elog(DEBUG2, "end of ResetCatalogCaches call");
836}

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

Referenced by InvalidateSystemCachesExtended(), and ResetCatalogCaches().

◆ SearchCatCache()

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

Definition at line 1372 of file catcache.c.

1377{
1378 return SearchCatCacheInternal(cache, cache->cc_nkeys, v1, v2, v3, v4);
1379}
static HeapTuple SearchCatCacheInternal(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition catcache.c:1423

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

Referenced by SearchSysCache().

◆ SearchCatCache1()

HeapTuple SearchCatCache1 ( CatCache cache,
Datum  v1 
)
extern

Definition at line 1389 of file catcache.c.

1391{
1392 return SearchCatCacheInternal(cache, 1, v1, 0, 0, 0);
1393}

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache1().

◆ SearchCatCache2()

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

Definition at line 1397 of file catcache.c.

1399{
1400 return SearchCatCacheInternal(cache, 2, v1, v2, 0, 0);
1401}

References CatCInProgress::cache, fb(), and SearchCatCacheInternal().

Referenced by SearchSysCache2().

◆ SearchCatCache3()

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

Definition at line 1405 of file catcache.c.

1407{
1408 return SearchCatCacheInternal(cache, 3, v1, v2, v3, 0);
1409}

References CatCInProgress::cache, fb(), and SearchCatCacheInternal().

Referenced by SearchSysCache3().

◆ SearchCatCache4()

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

Definition at line 1413 of file catcache.c.

1415{
1416 return SearchCatCacheInternal(cache, 4, v1, v2, v3, v4);
1417}

References CatCInProgress::cache, fb(), and SearchCatCacheInternal().

Referenced by SearchSysCache4().

◆ SearchCatCacheList()

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

Definition at line 1751 of file catcache.c.

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

Referenced by SearchSysCacheList().

Variable Documentation

◆ CacheMemoryContext

PGDLLIMPORT MemoryContext CacheMemoryContext
extern

Definition at line 169 of file mcxt.c.