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)
 
CatCache * InitCatCache (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)
 
CatCList * SearchCatCacheList (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:1895
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:1002
unsigned int Index
Definition c.h:757
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:167
MemoryContext CacheMemoryContext
Definition mcxt.c:170
#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 1720 of file catcache.c.

1725{
1726 /*
1727 * one-time startup overhead for each cache
1728 */
1730
1731 /*
1732 * calculate the hash value
1733 */
1734 return CatalogCacheComputeHashValue(cache, cache->cc_nkeys, v1, v2, v3, v4);
1735}
static uint32 CatalogCacheComputeHashValue(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition catcache.c:356
static pg_always_inline void ConditionalCatalogCacheInitializeCache(CatCache *cache)
Definition catcache.c:1096
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:89
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:1420
void * palloc_aligned(Size size, Size alignto, int flags)
Definition mcxt.c:1609
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:138
#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 2405 of file catcache.c.

2410{
2411 slist_iter iter;
2412 Oid reloid;
2413
2414 CACHE_elog(DEBUG2, "PrepareToInvalidateCacheTuple: called");
2415
2416 /*
2417 * sanity checks
2418 */
2419 Assert(RelationIsValid(relation));
2420 Assert(HeapTupleIsValid(tuple));
2422 Assert(CacheHdr != NULL);
2423
2424 reloid = RelationGetRelid(relation);
2425
2426 /* ----------------
2427 * for each cache
2428 * if the cache contains tuples from the specified relation
2429 * compute the tuple's hash value(s) in this cache,
2430 * and call the passed function to register the information.
2431 * ----------------
2432 */
2433
2435 {
2436 CatCache *ccp = slist_container(CatCache, cc_next, iter.cur);
2437 uint32 hashvalue;
2438 Oid dbid;
2439
2440 if (ccp->cc_reloid != reloid)
2441 continue;
2442
2443 /* Just in case cache hasn't finished initialization yet... */
2445
2446 hashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, tuple);
2447 dbid = ccp->cc_relisshared ? (Oid) 0 : MyDatabaseId;
2448
2449 (*function) (ccp->id, hashvalue, dbid, context);
2450
2451 if (newtuple)
2452 {
2454
2455 newhashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, newtuple);
2456
2457 if (newhashvalue != hashvalue)
2458 (*function) (ccp->id, newhashvalue, dbid, context);
2459 }
2460 }
2461}
uint32_t uint32
Definition c.h:683
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 1681 of file catcache.c.

1682{
1684}
static void ReleaseCatCacheWithOwner(HeapTuple tuple, ResourceOwner resowner)
Definition catcache.c:1687
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 1374 of file catcache.c.

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

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

Referenced by SearchSysCache().

◆ SearchCatCache1()

HeapTuple SearchCatCache1 ( CatCache *  cache,
Datum  v1 
)
extern

Definition at line 1391 of file catcache.c.

1393{
1394 return SearchCatCacheInternal(cache, 1, v1, 0, 0, 0);
1395}

References CatCInProgress::cache, and SearchCatCacheInternal().

Referenced by SearchSysCache1().

◆ SearchCatCache2()

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

Definition at line 1399 of file catcache.c.

1401{
1402 return SearchCatCacheInternal(cache, 2, v1, v2, 0, 0);
1403}

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

Referenced by SearchSysCache2().

◆ SearchCatCache3()

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

Definition at line 1407 of file catcache.c.

1409{
1410 return SearchCatCacheInternal(cache, 3, v1, v2, v3, 0);
1411}

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

1417{
1418 return SearchCatCacheInternal(cache, 4, v1, v2, v3, v4);
1419}

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

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