PostgreSQL Source Code  git master
catcache.h File Reference
#include "access/htup.h"
#include "access/skey.h"
#include "lib/ilist.h"
#include "utils/relcache.h"
Include dependency graph for catcache.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  catcache
 
struct  catctup
 
struct  catclist
 
struct  catcacheheader
 

Macros

#define CATCACHE_MAXKEYS   4
 
#define CT_MAGIC   0x57261502
 
#define CL_MAGIC   0x52765103
 

Typedefs

typedef uint32(* CCHashFN) (Datum datum)
 
typedef bool(* CCFastEqualFN) (Datum a, Datum b)
 
typedef struct catcache CatCache
 
typedef struct catctup CatCTup
 
typedef struct catclist CatCList
 
typedef struct catcacheheader CatCacheHeader
 

Functions

void CreateCacheMemoryContext (void)
 
CatCacheInitCatCache (int id, Oid reloid, Oid indexoid, int nkeys, const int *key, int nbuckets)
 
void InitCatCachePhase2 (CatCache *cache, bool touch_index)
 
HeapTuple SearchCatCache (CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
 
HeapTuple SearchCatCache1 (CatCache *cache, Datum v1)
 
HeapTuple SearchCatCache2 (CatCache *cache, Datum v1, Datum v2)
 
HeapTuple SearchCatCache3 (CatCache *cache, Datum v1, Datum v2, Datum v3)
 
HeapTuple SearchCatCache4 (CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
 
void ReleaseCatCache (HeapTuple tuple)
 
uint32 GetCatCacheHashValue (CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
 
CatCListSearchCatCacheList (CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3)
 
void ReleaseCatCacheList (CatCList *list)
 
void ResetCatalogCaches (void)
 
void CatalogCacheFlushCatalog (Oid catId)
 
void CatCacheInvalidate (CatCache *cache, uint32 hashValue)
 
void PrepareToInvalidateCacheTuple (Relation relation, HeapTuple tuple, HeapTuple newtuple, void(*function)(int, uint32, Oid))
 

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

◆ CT_MAGIC

#define CT_MAGIC   0x57261502

Definition at line 89 of file catcache.h.

Typedef Documentation

◆ CatCache

typedef struct catcache CatCache

◆ CatCacheHeader

◆ CatCList

typedef struct catclist CatCList

◆ CatCTup

typedef struct catctup CatCTup

◆ CCFastEqualFN

typedef bool(* CCFastEqualFN) (Datum a, Datum b)

Definition at line 42 of file catcache.h.

◆ CCHashFN

typedef uint32(* CCHashFN) (Datum datum)

Definition at line 39 of file catcache.h.

Function Documentation

◆ CatalogCacheFlushCatalog()

void CatalogCacheFlushCatalog ( Oid  catId)

Definition at line 766 of file catcache.c.

767 {
768  slist_iter iter;
769 
770  CACHE_elog(DEBUG2, "CatalogCacheFlushCatalog called for %u", catId);
771 
773  {
774  CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
775 
776  /* Does this cache store tuples of the target catalog? */
777  if (cache->cc_reloid == catId)
778  {
779  /* Yes, so flush all its contents */
780  ResetCatalogCache(cache);
781 
782  /* Tell inval.c to call syscache callbacks for this cache */
783  CallSyscacheCallbacks(cache->id, 0);
784  }
785  }
786 
787  CACHE_elog(DEBUG2, "end of CatalogCacheFlushCatalog call");
788 }
static CatCacheHeader * CacheHdr
Definition: catcache.c:65
static void ResetCatalogCache(CatCache *cache)
Definition: catcache.c:689
#define CACHE_elog(...)
Definition: catcache.c:61
#define DEBUG2
Definition: elog.h:29
#define slist_container(type, membername, ptr)
Definition: ilist.h:1106
#define slist_foreach(iter, lhead)
Definition: ilist.h:1132
void CallSyscacheCallbacks(int cacheid, uint32 hashvalue)
Definition: inval.c:1579
Oid cc_reloid
Definition: catcache.h:58
int id
Definition: catcache.h:46
slist_head ch_caches
Definition: catcache.h:184
slist_node * cur
Definition: ilist.h:259

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

Referenced by LocalExecuteInvalidationMessage().

◆ CatCacheInvalidate()

void CatCacheInvalidate ( CatCache cache,
uint32  hashValue 
)

Definition at line 599 of file catcache.c.

600 {
601  Index hashIndex;
602  dlist_mutable_iter iter;
603 
604  CACHE_elog(DEBUG2, "CatCacheInvalidate: called");
605 
606  /*
607  * We don't bother to check whether the cache has finished initialization
608  * yet; if not, there will be no entries in it so no problem.
609  */
610 
611  /*
612  * Invalidate *all* CatCLists in this cache; it's too hard to tell which
613  * searches might still be correct, so just zap 'em all.
614  */
615  dlist_foreach_modify(iter, &cache->cc_lists)
616  {
617  CatCList *cl = dlist_container(CatCList, cache_elem, iter.cur);
618 
619  if (cl->refcount > 0)
620  cl->dead = true;
621  else
622  CatCacheRemoveCList(cache, cl);
623  }
624 
625  /*
626  * inspect the proper hash bucket for tuple matches
627  */
628  hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
629  dlist_foreach_modify(iter, &cache->cc_bucket[hashIndex])
630  {
631  CatCTup *ct = dlist_container(CatCTup, cache_elem, iter.cur);
632 
633  if (hashValue == ct->hash_value)
634  {
635  if (ct->refcount > 0 ||
636  (ct->c_list && ct->c_list->refcount > 0))
637  {
638  ct->dead = true;
639  /* list, if any, was marked dead above */
640  Assert(ct->c_list == NULL || ct->c_list->dead);
641  }
642  else
643  CatCacheRemoveCTup(cache, ct);
644  CACHE_elog(DEBUG2, "CatCacheInvalidate: invalidated");
645 #ifdef CATCACHE_STATS
646  cache->cc_invals++;
647 #endif
648  /* could be multiple matches, so keep looking! */
649  }
650  }
651 }
unsigned int Index
Definition: c.h:603
static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
Definition: catcache.c:504
static void CatCacheRemoveCList(CatCache *cache, CatCList *cl)
Definition: catcache.c:546
#define HASH_INDEX(h, sz)
Definition: catcache.c:51
#define dlist_foreach_modify(iter, lhead)
Definition: ilist.h:640
#define dlist_container(type, membername, ptr)
Definition: ilist.h:593
Assert(fmt[strlen(fmt) - 1] !='\n')
dlist_head * cc_bucket
Definition: catcache.h:49
dlist_head cc_lists
Definition: catcache.h:54
int cc_nbuckets
Definition: catcache.h:47
int refcount
Definition: catcache.h:172
bool dead
Definition: catcache.h:173
int refcount
Definition: catcache.h:118
struct catclist * c_list
Definition: catcache.h:130
bool dead
Definition: catcache.h:119
uint32 hash_value
Definition: catcache.h:91
dlist_node * cur
Definition: ilist.h:200

References Assert(), catctup::c_list, CACHE_elog, CatCacheRemoveCList(), CatCacheRemoveCTup(), catcache::cc_bucket, catcache::cc_lists, catcache::cc_nbuckets, dlist_mutable_iter::cur, catctup::dead, catclist::dead, DEBUG2, dlist_container, dlist_foreach_modify, HASH_INDEX, catctup::hash_value, catctup::refcount, and catclist::refcount.

Referenced by SysCacheInvalidate().

◆ CreateCacheMemoryContext()

void CreateCacheMemoryContext ( void  )

Definition at line 667 of file catcache.c.

668 {
669  /*
670  * Purely for paranoia, check that context doesn't exist; caller probably
671  * did so already.
672  */
673  if (!CacheMemoryContext)
675  "CacheMemoryContext",
677 }
MemoryContext TopMemoryContext
Definition: mcxt.c:141
MemoryContext CacheMemoryContext
Definition: mcxt.c:144
#define AllocSetContextCreate
Definition: memutils.h:126
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:150

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CacheMemoryContext, and TopMemoryContext.

Referenced by assign_record_type_typmod(), BuildEventTriggerCache(), init_ts_config_cache(), InitCatCache(), InitializeAttoptCache(), InitializeRelfilenumberMap(), InitializeTableSpaceCache(), lookup_ts_dictionary_cache(), lookup_ts_parser_cache(), lookup_type_cache(), LookupOpclassInfo(), RelationBuildLocalRelation(), and RelationCacheInitialize().

◆ GetCatCacheHashValue()

uint32 GetCatCacheHashValue ( CatCache cache,
Datum  v1,
Datum  v2,
Datum  v3,
Datum  v4 
)

Definition at line 1530 of file catcache.c.

1535 {
1536  /*
1537  * one-time startup overhead for each cache
1538  */
1539  if (cache->cc_tupdesc == NULL)
1541 
1542  /*
1543  * calculate the hash value
1544  */
1545  return CatalogCacheComputeHashValue(cache, cache->cc_nkeys, v1, v2, v3, v4);
1546 }
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:972
static uint32 CatalogCacheComputeHashValue(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:324
int cc_nkeys
Definition: catcache.h:56
TupleDesc cc_tupdesc
Definition: catcache.h:48

References CatalogCacheComputeHashValue(), CatalogCacheInitializeCache(), catcache::cc_nkeys, and catcache::cc_tupdesc.

Referenced by GetSysCacheHashValue().

◆ InitCatCache()

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

Definition at line 810 of file catcache.c.

816 {
817  CatCache *cp;
818  MemoryContext oldcxt;
819  int i;
820 
821  /*
822  * nbuckets is the initial number of hash buckets to use in this catcache.
823  * It will be enlarged later if it becomes too full.
824  *
825  * nbuckets must be a power of two. We check this via Assert rather than
826  * a full runtime check because the values will be coming from constant
827  * tables.
828  *
829  * If you're confused by the power-of-two check, see comments in
830  * bitmapset.c for an explanation.
831  */
832  Assert(nbuckets > 0 && (nbuckets & -nbuckets) == nbuckets);
833 
834  /*
835  * first switch to the cache context so our allocations do not vanish at
836  * the end of a transaction
837  */
838  if (!CacheMemoryContext)
840 
842 
843  /*
844  * if first time through, initialize the cache group header
845  */
846  if (CacheHdr == NULL)
847  {
850  CacheHdr->ch_ntup = 0;
851 #ifdef CATCACHE_STATS
852  /* set up to dump stats at backend exit */
853  on_proc_exit(CatCachePrintStats, 0);
854 #endif
855  }
856 
857  /*
858  * Allocate a new cache structure, aligning to a cacheline boundary
859  *
860  * Note: we rely on zeroing to initialize all the dlist headers correctly
861  */
864  cp->cc_bucket = palloc0(nbuckets * sizeof(dlist_head));
865 
866  /*
867  * initialize the cache's relation information for the relation
868  * corresponding to this cache, and initialize some of the new cache's
869  * other internal fields. But don't open the relation yet.
870  */
871  cp->id = id;
872  cp->cc_relname = "(not known yet)";
873  cp->cc_reloid = reloid;
874  cp->cc_indexoid = indexoid;
875  cp->cc_relisshared = false; /* temporary */
876  cp->cc_tupdesc = (TupleDesc) NULL;
877  cp->cc_ntup = 0;
878  cp->cc_nbuckets = nbuckets;
879  cp->cc_nkeys = nkeys;
880  for (i = 0; i < nkeys; ++i)
881  {
883  cp->cc_keyno[i] = key[i];
884  }
885 
886  /*
887  * new cache is initialized as far as we can go for now. print some
888  * debugging information, if appropriate.
889  */
891 
892  /*
893  * add completed cache to top of group header's list
894  */
896 
897  /*
898  * back to the old context before we return...
899  */
900  MemoryContextSwitchTo(oldcxt);
901 
902  return cp;
903 }
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
void CreateCacheMemoryContext(void)
Definition: catcache.c:667
#define InitCatCache_DEBUG2
Definition: catcache.c:806
#define MCXT_ALLOC_ZERO
Definition: fe_memutils.h:18
static void slist_init(slist_head *head)
Definition: ilist.h:986
static void slist_push_head(slist_head *head, slist_node *node)
Definition: ilist.h:1006
void on_proc_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:309
int i
Definition: isn.c:73
void * palloc0(Size size)
Definition: mcxt.c:1257
void * palloc_aligned(Size size, Size alignto, int flags)
Definition: mcxt.c:1446
void * palloc(Size size)
Definition: mcxt.c:1226
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:138
#define PG_CACHE_LINE_SIZE
const char * cc_relname
Definition: catcache.h:57
slist_node cc_next
Definition: catcache.h:61
int cc_keyno[CATCACHE_MAXKEYS]
Definition: catcache.h:53
Oid cc_indexoid
Definition: catcache.h:59
bool cc_relisshared
Definition: catcache.h:60
int cc_ntup
Definition: catcache.h:55
struct TupleDescData * TupleDesc
Definition: tupdesc.h:89

References Assert(), AttributeNumberIsValid, CacheHdr, CacheMemoryContext, catcache::cc_bucket, catcache::cc_indexoid, catcache::cc_keyno, catcache::cc_nbuckets, catcache::cc_next, catcache::cc_nkeys, catcache::cc_ntup, catcache::cc_relisshared, catcache::cc_relname, catcache::cc_reloid, catcache::cc_tupdesc, catcacheheader::ch_caches, catcacheheader::ch_ntup, CreateCacheMemoryContext(), i, catcache::id, InitCatCache_DEBUG2, sort-test::key, MCXT_ALLOC_ZERO, MemoryContextSwitchTo(), on_proc_exit(), palloc(), palloc0(), palloc_aligned(), PG_CACHE_LINE_SIZE, slist_init(), and slist_push_head().

Referenced by InitCatalogCache().

◆ InitCatCachePhase2()

void InitCatCachePhase2 ( CatCache cache,
bool  touch_index 
)

Definition at line 1081 of file catcache.c.

1082 {
1083  if (cache->cc_tupdesc == NULL)
1085 
1086  if (touch_index &&
1087  cache->id != AMOID &&
1088  cache->id != AMNAME)
1089  {
1090  Relation idesc;
1091 
1092  /*
1093  * We must lock the underlying catalog before opening the index to
1094  * avoid deadlock, since index_open could possibly result in reading
1095  * this same catalog, and if anyone else is exclusive-locking this
1096  * catalog and index they'll be doing it in that order.
1097  */
1099  idesc = index_open(cache->cc_indexoid, AccessShareLock);
1100 
1101  /*
1102  * While we've got the index open, let's check that it's unique (and
1103  * not just deferrable-unique, thank you very much). This is just to
1104  * catch thinkos in definitions of new catcaches, so we don't worry
1105  * about the pg_am indexes not getting tested.
1106  */
1107  Assert(idesc->rd_index->indisunique &&
1108  idesc->rd_index->indimmediate);
1109 
1110  index_close(idesc, AccessShareLock);
1112  }
1113 }
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:158
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:132
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:228
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:109
#define AccessShareLock
Definition: lockdefs.h:36
Form_pg_index rd_index
Definition: rel.h:191
@ AMNAME
Definition: syscache.h:35
@ AMOID
Definition: syscache.h:36

References AccessShareLock, AMNAME, AMOID, Assert(), CatalogCacheInitializeCache(), catcache::cc_indexoid, catcache::cc_reloid, catcache::cc_tupdesc, catcache::id, index_close(), index_open(), LockRelationOid(), RelationData::rd_index, and UnlockRelationOid().

Referenced by InitCatalogCachePhase2(), and SysCacheGetAttr().

◆ PrepareToInvalidateCacheTuple()

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

Definition at line 2071 of file catcache.c.

2075 {
2076  slist_iter iter;
2077  Oid reloid;
2078 
2079  CACHE_elog(DEBUG2, "PrepareToInvalidateCacheTuple: called");
2080 
2081  /*
2082  * sanity checks
2083  */
2084  Assert(RelationIsValid(relation));
2085  Assert(HeapTupleIsValid(tuple));
2086  Assert(PointerIsValid(function));
2087  Assert(CacheHdr != NULL);
2088 
2089  reloid = RelationGetRelid(relation);
2090 
2091  /* ----------------
2092  * for each cache
2093  * if the cache contains tuples from the specified relation
2094  * compute the tuple's hash value(s) in this cache,
2095  * and call the passed function to register the information.
2096  * ----------------
2097  */
2098 
2100  {
2101  CatCache *ccp = slist_container(CatCache, cc_next, iter.cur);
2102  uint32 hashvalue;
2103  Oid dbid;
2104 
2105  if (ccp->cc_reloid != reloid)
2106  continue;
2107 
2108  /* Just in case cache hasn't finished initialization yet... */
2109  if (ccp->cc_tupdesc == NULL)
2111 
2112  hashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, tuple);
2113  dbid = ccp->cc_relisshared ? (Oid) 0 : MyDatabaseId;
2114 
2115  (*function) (ccp->id, hashvalue, dbid);
2116 
2117  if (newtuple)
2118  {
2119  uint32 newhashvalue;
2120 
2121  newhashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, newtuple);
2122 
2123  if (newhashvalue != hashvalue)
2124  (*function) (ccp->id, newhashvalue, dbid);
2125  }
2126  }
2127 }
unsigned int uint32
Definition: c.h:495
#define PointerIsValid(pointer)
Definition: c.h:752
static uint32 CatalogCacheComputeTupleHashValue(CatCache *cache, int nkeys, HeapTuple tuple)
Definition: catcache.c:366
Oid MyDatabaseId
Definition: globals.c:89
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
unsigned int Oid
Definition: postgres_ext.h:31
#define RelationGetRelid(relation)
Definition: rel.h:504
#define RelationIsValid(relation)
Definition: rel.h:477

References Assert(), CACHE_elog, CacheHdr, CatalogCacheComputeTupleHashValue(), CatalogCacheInitializeCache(), catcache::cc_nkeys, catcache::cc_relisshared, catcache::cc_reloid, catcache::cc_tupdesc, catcacheheader::ch_caches, slist_iter::cur, DEBUG2, HeapTupleIsValid, catcache::id, MyDatabaseId, PointerIsValid, RelationGetRelid, RelationIsValid, slist_container, and slist_foreach.

Referenced by CacheInvalidateHeapTuple().

◆ ReleaseCatCache()

void ReleaseCatCache ( HeapTuple  tuple)

Definition at line 1491 of file catcache.c.

1492 {
1494 }
static void ReleaseCatCacheWithOwner(HeapTuple tuple, ResourceOwner resowner)
Definition: catcache.c:1497
ResourceOwner CurrentResourceOwner
Definition: resowner.c:164

References CurrentResourceOwner, and ReleaseCatCacheWithOwner().

Referenced by ReleaseSysCache().

◆ ReleaseCatCacheList()

◆ ResetCatalogCaches()

void ResetCatalogCaches ( void  )

Definition at line 736 of file catcache.c.

737 {
738  slist_iter iter;
739 
740  CACHE_elog(DEBUG2, "ResetCatalogCaches called");
741 
743  {
744  CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
745 
746  ResetCatalogCache(cache);
747  }
748 
749  CACHE_elog(DEBUG2, "end of ResetCatalogCaches call");
750 }

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

Referenced by InvalidateSystemCachesExtended().

◆ SearchCatCache()

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

Definition at line 1198 of file catcache.c.

1203 {
1204  return SearchCatCacheInternal(cache, cache->cc_nkeys, v1, v2, v3, v4);
1205 }
static HeapTuple SearchCatCacheInternal(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1249

References catcache::cc_nkeys, and SearchCatCacheInternal().

Referenced by SearchSysCache().

◆ SearchCatCache1()

HeapTuple SearchCatCache1 ( CatCache cache,
Datum  v1 
)

Definition at line 1215 of file catcache.c.

1217 {
1218  return SearchCatCacheInternal(cache, 1, v1, 0, 0, 0);
1219 }

References SearchCatCacheInternal().

Referenced by SearchSysCache1().

◆ SearchCatCache2()

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

Definition at line 1223 of file catcache.c.

1225 {
1226  return SearchCatCacheInternal(cache, 2, v1, v2, 0, 0);
1227 }

References SearchCatCacheInternal().

Referenced by SearchSysCache2().

◆ SearchCatCache3()

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

Definition at line 1231 of file catcache.c.

1233 {
1234  return SearchCatCacheInternal(cache, 3, v1, v2, v3, 0);
1235 }

References SearchCatCacheInternal().

Referenced by SearchSysCache3().

◆ SearchCatCache4()

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

Definition at line 1239 of file catcache.c.

1241 {
1242  return SearchCatCacheInternal(cache, 4, v1, v2, v3, v4);
1243 }

References SearchCatCacheInternal().

Referenced by SearchSysCache4().

◆ SearchCatCacheList()

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

Definition at line 1564 of file catcache.c.

1569 {
1570  Datum v4 = 0; /* dummy last-column value */
1572  uint32 lHashValue;
1573  dlist_iter iter;
1574  CatCList *cl;
1575  CatCTup *ct;
1576  List *volatile ctlist;
1577  ListCell *ctlist_item;
1578  int nmembers;
1579  bool ordered;
1580  HeapTuple ntp;
1581  MemoryContext oldcxt;
1582  int i;
1583 
1584  /*
1585  * one-time startup overhead for each cache
1586  */
1587  if (cache->cc_tupdesc == NULL)
1589 
1590  Assert(nkeys > 0 && nkeys < cache->cc_nkeys);
1591 
1592 #ifdef CATCACHE_STATS
1593  cache->cc_lsearches++;
1594 #endif
1595 
1596  /* Initialize local parameter array */
1597  arguments[0] = v1;
1598  arguments[1] = v2;
1599  arguments[2] = v3;
1600  arguments[3] = v4;
1601 
1602  /*
1603  * compute a hash value of the given keys for faster search. We don't
1604  * presently divide the CatCList items into buckets, but this still lets
1605  * us skip non-matching items quickly most of the time.
1606  */
1607  lHashValue = CatalogCacheComputeHashValue(cache, nkeys, v1, v2, v3, v4);
1608 
1609  /*
1610  * scan the items until we find a match or exhaust our list
1611  *
1612  * Note: it's okay to use dlist_foreach here, even though we modify the
1613  * dlist within the loop, because we don't continue the loop afterwards.
1614  */
1615  dlist_foreach(iter, &cache->cc_lists)
1616  {
1617  cl = dlist_container(CatCList, cache_elem, iter.cur);
1618 
1619  if (cl->dead)
1620  continue; /* ignore dead entries */
1621 
1622  if (cl->hash_value != lHashValue)
1623  continue; /* quickly skip entry if wrong hash val */
1624 
1625  /*
1626  * see if the cached list matches our key.
1627  */
1628  if (cl->nkeys != nkeys)
1629  continue;
1630 
1631  if (!CatalogCacheCompareTuple(cache, nkeys, cl->keys, arguments))
1632  continue;
1633 
1634  /*
1635  * We found a matching list. Move the list to the front of the
1636  * cache's list-of-lists, to speed subsequent searches. (We do not
1637  * move the members to the fronts of their hashbucket lists, however,
1638  * since there's no point in that unless they are searched for
1639  * individually.)
1640  */
1641  dlist_move_head(&cache->cc_lists, &cl->cache_elem);
1642 
1643  /* Bump the list's refcount and return it */
1645  cl->refcount++;
1647 
1648  CACHE_elog(DEBUG2, "SearchCatCacheList(%s): found list",
1649  cache->cc_relname);
1650 
1651 #ifdef CATCACHE_STATS
1652  cache->cc_lhits++;
1653 #endif
1654 
1655  return cl;
1656  }
1657 
1658  /*
1659  * List was not found in cache, so we have to build it by reading the
1660  * relation. For each matching tuple found in the relation, use an
1661  * existing cache entry if possible, else build a new one.
1662  *
1663  * We have to bump the member refcounts temporarily to ensure they won't
1664  * get dropped from the cache while loading other members. We use a PG_TRY
1665  * block to ensure we can undo those refcounts if we get an error before
1666  * we finish constructing the CatCList.
1667  */
1668  ctlist = NIL;
1669 
1670  PG_TRY();
1671  {
1672  ScanKeyData cur_skey[CATCACHE_MAXKEYS];
1673  Relation relation;
1674  SysScanDesc scandesc;
1675 
1676  /*
1677  * Ok, need to make a lookup in the relation, copy the scankey and
1678  * fill out any per-call fields.
1679  */
1680  memcpy(cur_skey, cache->cc_skey, sizeof(ScanKeyData) * cache->cc_nkeys);
1681  cur_skey[0].sk_argument = v1;
1682  cur_skey[1].sk_argument = v2;
1683  cur_skey[2].sk_argument = v3;
1684  cur_skey[3].sk_argument = v4;
1685 
1686  relation = table_open(cache->cc_reloid, AccessShareLock);
1687 
1688  scandesc = systable_beginscan(relation,
1689  cache->cc_indexoid,
1690  IndexScanOK(cache, cur_skey),
1691  NULL,
1692  nkeys,
1693  cur_skey);
1694 
1695  /* The list will be ordered iff we are doing an index scan */
1696  ordered = (scandesc->irel != NULL);
1697 
1698  while (HeapTupleIsValid(ntp = systable_getnext(scandesc)))
1699  {
1700  uint32 hashValue;
1701  Index hashIndex;
1702  bool found = false;
1703  dlist_head *bucket;
1704 
1705  /*
1706  * See if there's an entry for this tuple already.
1707  */
1708  ct = NULL;
1709  hashValue = CatalogCacheComputeTupleHashValue(cache, cache->cc_nkeys, ntp);
1710  hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
1711 
1712  bucket = &cache->cc_bucket[hashIndex];
1713  dlist_foreach(iter, bucket)
1714  {
1715  ct = dlist_container(CatCTup, cache_elem, iter.cur);
1716 
1717  if (ct->dead || ct->negative)
1718  continue; /* ignore dead and negative entries */
1719 
1720  if (ct->hash_value != hashValue)
1721  continue; /* quickly skip entry if wrong hash val */
1722 
1723  if (!ItemPointerEquals(&(ct->tuple.t_self), &(ntp->t_self)))
1724  continue; /* not same tuple */
1725 
1726  /*
1727  * Found a match, but can't use it if it belongs to another
1728  * list already
1729  */
1730  if (ct->c_list)
1731  continue;
1732 
1733  found = true;
1734  break; /* A-OK */
1735  }
1736 
1737  if (!found)
1738  {
1739  /* We didn't find a usable entry, so make a new one */
1740  ct = CatalogCacheCreateEntry(cache, ntp, arguments,
1741  hashValue, hashIndex,
1742  false);
1743  }
1744 
1745  /* Careful here: add entry to ctlist, then bump its refcount */
1746  /* This way leaves state correct if lappend runs out of memory */
1747  ctlist = lappend(ctlist, ct);
1748  ct->refcount++;
1749  }
1750 
1751  systable_endscan(scandesc);
1752 
1753  table_close(relation, AccessShareLock);
1754 
1755  /* Make sure the resource owner has room to remember this entry. */
1757 
1758  /* Now we can build the CatCList entry. */
1760  nmembers = list_length(ctlist);
1761  cl = (CatCList *)
1762  palloc(offsetof(CatCList, members) + nmembers * sizeof(CatCTup *));
1763 
1764  /* Extract key values */
1765  CatCacheCopyKeys(cache->cc_tupdesc, nkeys, cache->cc_keyno,
1766  arguments, cl->keys);
1767  MemoryContextSwitchTo(oldcxt);
1768 
1769  /*
1770  * We are now past the last thing that could trigger an elog before we
1771  * have finished building the CatCList and remembering it in the
1772  * resource owner. So it's OK to fall out of the PG_TRY, and indeed
1773  * we'd better do so before we start marking the members as belonging
1774  * to the list.
1775  */
1776  }
1777  PG_CATCH();
1778  {
1779  foreach(ctlist_item, ctlist)
1780  {
1781  ct = (CatCTup *) lfirst(ctlist_item);
1782  Assert(ct->c_list == NULL);
1783  Assert(ct->refcount > 0);
1784  ct->refcount--;
1785  if (
1786 #ifndef CATCACHE_FORCE_RELEASE
1787  ct->dead &&
1788 #endif
1789  ct->refcount == 0 &&
1790  (ct->c_list == NULL || ct->c_list->refcount == 0))
1791  CatCacheRemoveCTup(cache, ct);
1792  }
1793 
1794  PG_RE_THROW();
1795  }
1796  PG_END_TRY();
1797 
1798  cl->cl_magic = CL_MAGIC;
1799  cl->my_cache = cache;
1800  cl->refcount = 0; /* for the moment */
1801  cl->dead = false;
1802  cl->ordered = ordered;
1803  cl->nkeys = nkeys;
1804  cl->hash_value = lHashValue;
1805  cl->n_members = nmembers;
1806 
1807  i = 0;
1808  foreach(ctlist_item, ctlist)
1809  {
1810  cl->members[i++] = ct = (CatCTup *) lfirst(ctlist_item);
1811  Assert(ct->c_list == NULL);
1812  ct->c_list = cl;
1813  /* release the temporary refcount on the member */
1814  Assert(ct->refcount > 0);
1815  ct->refcount--;
1816  /* mark list dead if any members already dead */
1817  if (ct->dead)
1818  cl->dead = true;
1819  }
1820  Assert(i == nmembers);
1821 
1822  dlist_push_head(&cache->cc_lists, &cl->cache_elem);
1823 
1824  /* Finally, bump the list's refcount and return it */
1825  cl->refcount++;
1827 
1828  CACHE_elog(DEBUG2, "SearchCatCacheList(%s): made list of %d members",
1829  cache->cc_relname, nmembers);
1830 
1831  return cl;
1832 }
static CatCTup * CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp, Datum *arguments, uint32 hashValue, Index hashIndex, bool negative)
Definition: catcache.c:1870
static void CatCacheCopyKeys(TupleDesc tupdesc, int nkeys, int *attnos, Datum *srckeys, Datum *dstkeys)
Definition: catcache.c:2001
static bool CatalogCacheCompareTuple(const CatCache *cache, int nkeys, const Datum *cachekeys, const Datum *searchkeys)
Definition: catcache.c:421
static void ResourceOwnerRememberCatCacheListRef(ResourceOwner owner, CatCList *list)
Definition: catcache.c:149
static bool IndexScanOK(CatCache *cache, ScanKey cur_skey)
Definition: catcache.c:1133
#define CATCACHE_MAXKEYS
Definition: catcache.h:35
#define CL_MAGIC
Definition: catcache.h:160
#define PG_RE_THROW()
Definition: elog.h:411
#define PG_TRY(...)
Definition: elog.h:370
#define PG_END_TRY(...)
Definition: elog.h:395
#define PG_CATCH(...)
Definition: elog.h:380
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:599
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:506
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:387
#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
bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)
Definition: itemptr.c:35
List * lappend(List *list, void *datum)
Definition: list.c:338
#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
uintptr_t Datum
Definition: postgres.h:64
void ResourceOwnerEnlarge(ResourceOwner owner)
Definition: resowner.c:448
ItemPointerData t_self
Definition: htup.h:65
Definition: pg_list.h:54
Datum sk_argument
Definition: skey.h:72
Relation irel
Definition: relscan.h:184
ScanKeyData cc_skey[CATCACHE_MAXKEYS]
Definition: catcache.h:62
dlist_node cache_elem
Definition: catcache.h:164
CatCache * my_cache
Definition: catcache.h:177
int cl_magic
Definition: catcache.h:159
short nkeys
Definition: catcache.h:175
Datum keys[CATCACHE_MAXKEYS]
Definition: catcache.h:170
bool ordered
Definition: catcache.h:174
CatCTup * members[FLEXIBLE_ARRAY_MEMBER]
Definition: catcache.h:178
uint32 hash_value
Definition: catcache.h:162
int n_members
Definition: catcache.h:176
bool negative
Definition: catcache.h:120
HeapTupleData tuple
Definition: catcache.h:121
dlist_node * cur
Definition: ilist.h:179
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40

References AccessShareLock, Assert(), catctup::c_list, catclist::cache_elem, CACHE_elog, CacheMemoryContext, CatalogCacheCompareTuple(), CatalogCacheComputeHashValue(), CatalogCacheComputeTupleHashValue(), CatalogCacheCreateEntry(), CatalogCacheInitializeCache(), CATCACHE_MAXKEYS, CatCacheCopyKeys(), CatCacheRemoveCTup(), catcache::cc_bucket, catcache::cc_indexoid, catcache::cc_keyno, catcache::cc_lists, catcache::cc_nbuckets, catcache::cc_nkeys, catcache::cc_relname, catcache::cc_reloid, catcache::cc_skey, catcache::cc_tupdesc, catclist::cl_magic, CL_MAGIC, dlist_iter::cur, CurrentResourceOwner, catctup::dead, catclist::dead, DEBUG2, dlist_container, dlist_foreach, dlist_move_head(), dlist_push_head(), HASH_INDEX, catctup::hash_value, catclist::hash_value, HeapTupleIsValid, i, IndexScanOK(), SysScanDescData::irel, ItemPointerEquals(), catclist::keys, lappend(), lfirst, list_length(), catclist::members, MemoryContextSwitchTo(), catclist::my_cache, catclist::n_members, catctup::negative, NIL, catclist::nkeys, catclist::ordered, palloc(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, catctup::refcount, catclist::refcount, ResourceOwnerEnlarge(), ResourceOwnerRememberCatCacheListRef(), ScanKeyData::sk_argument, systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), table_open(), and catctup::tuple.

Referenced by SearchSysCacheList().

Variable Documentation

◆ CacheMemoryContext

PGDLLIMPORT MemoryContext CacheMemoryContext
extern

Definition at line 144 of file mcxt.c.