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: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:999
unsigned int Index
Definition c.h:754
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 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: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:680
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.