PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
catcache.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/hash.h"
#include "access/heapam.h"
#include "access/relscan.h"
#include "access/sysattr.h"
#include "access/tuptoaster.h"
#include "access/valid.h"
#include "access/xact.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_type.h"
#include "miscadmin.h"
#include "storage/lmgr.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/inval.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "utils/resowner_private.h"
#include "utils/syscache.h"
#include "utils/tqual.h"
Include dependency graph for catcache.c:

Go to the source code of this file.

Macros

#define HASH_INDEX(h, sz)   ((Index) ((h) & ((sz) - 1)))
 
#define CACHE1_elog(a, b)
 
#define CACHE2_elog(a, b, c)
 
#define CACHE3_elog(a, b, c, d)
 
#define CACHE4_elog(a, b, c, d, e)
 
#define CACHE5_elog(a, b, c, d, e, f)
 
#define CACHE6_elog(a, b, c, d, e, f, g)
 
#define InitCatCache_DEBUG2
 
#define CatalogCacheInitializeCache_DEBUG1
 
#define CatalogCacheInitializeCache_DEBUG2
 

Functions

static uint32 CatalogCacheComputeHashValue (CatCache *cache, int nkeys, ScanKey cur_skey)
 
static uint32 CatalogCacheComputeTupleHashValue (CatCache *cache, HeapTuple tuple)
 
static void CatCacheRemoveCTup (CatCache *cache, CatCTup *ct)
 
static void CatCacheRemoveCList (CatCache *cache, CatCList *cl)
 
static void CatalogCacheInitializeCache (CatCache *cache)
 
static CatCTupCatalogCacheCreateEntry (CatCache *cache, HeapTuple ntp, uint32 hashValue, Index hashIndex, bool negative)
 
static HeapTuple build_dummy_tuple (CatCache *cache, int nkeys, ScanKey skeys)
 
static void GetCCHashEqFuncs (Oid keytype, PGFunction *hashfunc, RegProcedure *eqfunc)
 
void CatCacheInvalidate (CatCache *cache, uint32 hashValue)
 
void CreateCacheMemoryContext (void)
 
static void ResetCatalogCache (CatCache *cache)
 
void ResetCatalogCaches (void)
 
void CatalogCacheFlushCatalog (Oid catId)
 
CatCacheInitCatCache (int id, Oid reloid, Oid indexoid, int nkeys, const int *key, int nbuckets)
 
static void RehashCatCache (CatCache *cp)
 
void InitCatCachePhase2 (CatCache *cache, bool touch_index)
 
static bool IndexScanOK (CatCache *cache, ScanKey cur_skey)
 
HeapTuple SearchCatCache (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, Datum v4)
 
void ReleaseCatCacheList (CatCList *list)
 
void PrepareToInvalidateCacheTuple (Relation relation, HeapTuple tuple, HeapTuple newtuple, void(*function)(int, uint32, Oid))
 
void PrintCatCacheLeakWarning (HeapTuple tuple)
 
void PrintCatCacheListLeakWarning (CatCList *list)
 

Variables

static CatCacheHeaderCacheHdr = NULL
 

Macro Definition Documentation

#define CACHE1_elog (   a,
 
)
#define CACHE2_elog (   a,
  b,
  c 
)

Definition at line 65 of file catcache.c.

Referenced by CatalogCacheFlushCatalog(), and SearchCatCacheList().

#define CACHE3_elog (   a,
  b,
  c,
 
)

Definition at line 66 of file catcache.c.

Referenced by CatalogCacheInitializeCache(), SearchCatCache(), and SearchCatCacheList().

#define CACHE4_elog (   a,
  b,
  c,
  d,
  e 
)
#define CACHE5_elog (   a,
  b,
  c,
  d,
  e,
 
)

Definition at line 68 of file catcache.c.

#define CACHE6_elog (   a,
  b,
  c,
  d,
  e,
  f,
 
)

Definition at line 69 of file catcache.c.

#define CatalogCacheInitializeCache_DEBUG1

Definition at line 807 of file catcache.c.

Referenced by CatalogCacheInitializeCache().

#define CatalogCacheInitializeCache_DEBUG2

Definition at line 808 of file catcache.c.

Referenced by CatalogCacheInitializeCache().

#define HASH_INDEX (   h,
  sz 
)    ((Index) ((h) & ((sz) - 1)))

Definition at line 49 of file catcache.c.

Referenced by CatCacheInvalidate(), RehashCatCache(), SearchCatCache(), and SearchCatCacheList().

#define InitCatCache_DEBUG2

Definition at line 650 of file catcache.c.

Referenced by InitCatCache().

Function Documentation

static HeapTuple build_dummy_tuple ( CatCache cache,
int  nkeys,
ScanKey  skeys 
)
static

Definition at line 1690 of file catcache.c.

References Assert, catcache::cc_isname, catcache::cc_key, catcache::cc_tupdesc, DatumGetCString, DatumGetObjectId, heap_form_tuple(), HeapTupleSetOid, i, InvalidOid, NameGetDatum, namestrcpy(), tupleDesc::natts, newval, ObjectIdAttributeNumber, palloc(), pfree(), ScanKeyData::sk_argument, and values.

Referenced by SearchCatCache(), and SearchCatCacheList().

1691 {
1692  HeapTuple ntp;
1693  TupleDesc tupDesc = cache->cc_tupdesc;
1694  Datum *values;
1695  bool *nulls;
1696  Oid tupOid = InvalidOid;
1697  NameData tempNames[4];
1698  int i;
1699 
1700  values = (Datum *) palloc(tupDesc->natts * sizeof(Datum));
1701  nulls = (bool *) palloc(tupDesc->natts * sizeof(bool));
1702 
1703  memset(values, 0, tupDesc->natts * sizeof(Datum));
1704  memset(nulls, true, tupDesc->natts * sizeof(bool));
1705 
1706  for (i = 0; i < nkeys; i++)
1707  {
1708  int attindex = cache->cc_key[i];
1709  Datum keyval = skeys[i].sk_argument;
1710 
1711  if (attindex > 0)
1712  {
1713  /*
1714  * Here we must be careful in case the caller passed a C string
1715  * where a NAME is wanted: convert the given argument to a
1716  * correctly padded NAME. Otherwise the memcpy() done in
1717  * heap_form_tuple could fall off the end of memory.
1718  */
1719  if (cache->cc_isname[i])
1720  {
1721  Name newval = &tempNames[i];
1722 
1723  namestrcpy(newval, DatumGetCString(keyval));
1724  keyval = NameGetDatum(newval);
1725  }
1726  values[attindex - 1] = keyval;
1727  nulls[attindex - 1] = false;
1728  }
1729  else
1730  {
1731  Assert(attindex == ObjectIdAttributeNumber);
1732  tupOid = DatumGetObjectId(keyval);
1733  }
1734  }
1735 
1736  ntp = heap_form_tuple(tupDesc, values, nulls);
1737  if (tupOid != InvalidOid)
1738  HeapTupleSetOid(ntp, tupOid);
1739 
1740  pfree(values);
1741  pfree(nulls);
1742 
1743  return ntp;
1744 }
#define NameGetDatum(X)
Definition: postgres.h:601
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
#define DatumGetObjectId(X)
Definition: postgres.h:506
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
unsigned int Oid
Definition: postgres_ext.h:31
int namestrcpy(Name name, const char *str)
Definition: name.c:216
bool cc_isname[CATCACHE_MAXKEYS]
Definition: catcache.h:53
int natts
Definition: tupdesc.h:73
#define HeapTupleSetOid(tuple, oid)
Definition: htup_details.h:698
void pfree(void *pointer)
Definition: mcxt.c:949
#define DatumGetCString(X)
Definition: postgres.h:572
int cc_key[CATCACHE_MAXKEYS]
Definition: catcache.h:49
TupleDesc cc_tupdesc
Definition: catcache.h:45
Definition: c.h:487
uintptr_t Datum
Definition: postgres.h:372
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:664
#define newval
static Datum values[MAXATTR]
Definition: bootstrap.c:164
void * palloc(Size size)
Definition: mcxt.c:848
int i
Datum sk_argument
Definition: skey.h:72
static uint32 CatalogCacheComputeHashValue ( CatCache cache,
int  nkeys,
ScanKey  cur_skey 
)
static

Definition at line 174 of file catcache.c.

References CACHE4_elog, catcache::cc_hashfunc, catcache::cc_relname, DatumGetUInt32, DEBUG2, DirectFunctionCall1, elog, FATAL, and ScanKeyData::sk_argument.

Referenced by CatalogCacheComputeTupleHashValue(), GetCatCacheHashValue(), SearchCatCache(), and SearchCatCacheList().

175 {
176  uint32 hashValue = 0;
177  uint32 oneHash;
178 
179  CACHE4_elog(DEBUG2, "CatalogCacheComputeHashValue %s %d %p",
180  cache->cc_relname,
181  nkeys,
182  cache);
183 
184  switch (nkeys)
185  {
186  case 4:
187  oneHash =
189  cur_skey[3].sk_argument));
190  hashValue ^= oneHash << 24;
191  hashValue ^= oneHash >> 8;
192  /* FALLTHROUGH */
193  case 3:
194  oneHash =
196  cur_skey[2].sk_argument));
197  hashValue ^= oneHash << 16;
198  hashValue ^= oneHash >> 16;
199  /* FALLTHROUGH */
200  case 2:
201  oneHash =
203  cur_skey[1].sk_argument));
204  hashValue ^= oneHash << 8;
205  hashValue ^= oneHash >> 24;
206  /* FALLTHROUGH */
207  case 1:
208  oneHash =
210  cur_skey[0].sk_argument));
211  hashValue ^= oneHash;
212  break;
213  default:
214  elog(FATAL, "wrong number of hash keys: %d", nkeys);
215  break;
216  }
217 
218  return hashValue;
219 }
#define DatumGetUInt32(X)
Definition: postgres.h:492
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
#define FATAL
Definition: elog.h:52
#define DEBUG2
Definition: elog.h:24
unsigned int uint32
Definition: c.h:258
#define CACHE4_elog(a, b, c, d, e)
Definition: catcache.c:67
const char * cc_relname
Definition: catcache.h:41
#define elog
Definition: elog.h:219
PGFunction cc_hashfunc[CATCACHE_MAXKEYS]
Definition: catcache.h:50
Datum sk_argument
Definition: skey.h:72
static uint32 CatalogCacheComputeTupleHashValue ( CatCache cache,
HeapTuple  tuple 
)
static

Definition at line 227 of file catcache.c.

References Assert, CatalogCacheComputeHashValue(), CATCACHE_MAXKEYS, catcache::cc_key, catcache::cc_nkeys, catcache::cc_skey, catcache::cc_tupdesc, elog, fastgetattr, FATAL, HeapTupleGetOid, ObjectIdAttributeNumber, ObjectIdGetDatum, and ScanKeyData::sk_argument.

Referenced by PrepareToInvalidateCacheTuple(), and SearchCatCacheList().

228 {
229  ScanKeyData cur_skey[CATCACHE_MAXKEYS];
230  bool isNull = false;
231 
232  /* Copy pre-initialized overhead data for scankey */
233  memcpy(cur_skey, cache->cc_skey, sizeof(cur_skey));
234 
235  /* Now extract key fields from tuple, insert into scankey */
236  switch (cache->cc_nkeys)
237  {
238  case 4:
239  cur_skey[3].sk_argument =
240  (cache->cc_key[3] == ObjectIdAttributeNumber)
242  : fastgetattr(tuple,
243  cache->cc_key[3],
244  cache->cc_tupdesc,
245  &isNull);
246  Assert(!isNull);
247  /* FALLTHROUGH */
248  case 3:
249  cur_skey[2].sk_argument =
250  (cache->cc_key[2] == ObjectIdAttributeNumber)
252  : fastgetattr(tuple,
253  cache->cc_key[2],
254  cache->cc_tupdesc,
255  &isNull);
256  Assert(!isNull);
257  /* FALLTHROUGH */
258  case 2:
259  cur_skey[1].sk_argument =
260  (cache->cc_key[1] == ObjectIdAttributeNumber)
262  : fastgetattr(tuple,
263  cache->cc_key[1],
264  cache->cc_tupdesc,
265  &isNull);
266  Assert(!isNull);
267  /* FALLTHROUGH */
268  case 1:
269  cur_skey[0].sk_argument =
270  (cache->cc_key[0] == ObjectIdAttributeNumber)
272  : fastgetattr(tuple,
273  cache->cc_key[0],
274  cache->cc_tupdesc,
275  &isNull);
276  Assert(!isNull);
277  break;
278  default:
279  elog(FATAL, "wrong number of hash keys: %d", cache->cc_nkeys);
280  break;
281  }
282 
283  return CatalogCacheComputeHashValue(cache, cache->cc_nkeys, cur_skey);
284 }
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:719
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
static uint32 CatalogCacheComputeHashValue(CatCache *cache, int nkeys, ScanKey cur_skey)
Definition: catcache.c:174
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define CATCACHE_MAXKEYS
Definition: catcache.h:35
int cc_key[CATCACHE_MAXKEYS]
Definition: catcache.h:49
int cc_nkeys
Definition: catcache.h:48
#define FATAL
Definition: elog.h:52
TupleDesc cc_tupdesc
Definition: catcache.h:45
#define Assert(condition)
Definition: c.h:664
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
ScanKeyData cc_skey[CATCACHE_MAXKEYS]
Definition: catcache.h:51
Datum sk_argument
Definition: skey.h:72
static CatCTup * CatalogCacheCreateEntry ( CatCache cache,
HeapTuple  ntp,
uint32  hashValue,
Index  hashIndex,
bool  negative 
)
static

Definition at line 1624 of file catcache.c.

References catctup::c_list, catctup::cache_elem, CacheMemoryContext, catcache::cc_bucket, catcache::cc_nbuckets, catcache::cc_ntup, catcache::cc_tupdesc, catcacheheader::ch_ntup, catctup::ct_magic, CT_MAGIC, catctup::dead, dlist_push_head(), catctup::hash_value, heap_copytuple_with_tuple(), heap_freetuple(), HeapTupleHasExternal, MemoryContextSwitchTo(), catctup::my_cache, catctup::negative, palloc(), catctup::refcount, RehashCatCache(), toast_flatten_tuple(), and catctup::tuple.

Referenced by SearchCatCache(), and SearchCatCacheList().

1626 {
1627  CatCTup *ct;
1628  HeapTuple dtp;
1629  MemoryContext oldcxt;
1630 
1631  /*
1632  * If there are any out-of-line toasted fields in the tuple, expand them
1633  * in-line. This saves cycles during later use of the catcache entry, and
1634  * also protects us against the possibility of the toast tuples being
1635  * freed before we attempt to fetch them, in case of something using a
1636  * slightly stale catcache entry.
1637  */
1638  if (HeapTupleHasExternal(ntp))
1639  dtp = toast_flatten_tuple(ntp, cache->cc_tupdesc);
1640  else
1641  dtp = ntp;
1642 
1643  /*
1644  * Allocate CatCTup header in cache memory, and copy the tuple there too.
1645  */
1647  ct = (CatCTup *) palloc(sizeof(CatCTup));
1648  heap_copytuple_with_tuple(dtp, &ct->tuple);
1649  MemoryContextSwitchTo(oldcxt);
1650 
1651  if (dtp != ntp)
1652  heap_freetuple(dtp);
1653 
1654  /*
1655  * Finish initializing the CatCTup header, and add it to the cache's
1656  * linked list and counts.
1657  */
1658  ct->ct_magic = CT_MAGIC;
1659  ct->my_cache = cache;
1660  ct->c_list = NULL;
1661  ct->refcount = 0; /* for the moment */
1662  ct->dead = false;
1663  ct->negative = negative;
1664  ct->hash_value = hashValue;
1665 
1666  dlist_push_head(&cache->cc_bucket[hashIndex], &ct->cache_elem);
1667 
1668  cache->cc_ntup++;
1669  CacheHdr->ch_ntup++;
1670 
1671  /*
1672  * If the hash table has become too full, enlarge the buckets array. Quite
1673  * arbitrarily, we enlarge when fill factor > 2.
1674  */
1675  if (cache->cc_ntup > cache->cc_nbuckets * 2)
1676  RehashCatCache(cache);
1677 
1678  return ct;
1679 }
HeapTuple toast_flatten_tuple(HeapTuple tup, TupleDesc tupleDesc)
Definition: tuptoaster.c:1085
uint32 hash_value
Definition: catcache.h:115
CatCache * my_cache
Definition: catcache.h:82
static CatCacheHeader * CacheHdr
Definition: catcache.c:73
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:300
#define CT_MAGIC
Definition: catcache.h:81
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
dlist_head * cc_bucket
Definition: catcache.h:55
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
struct catclist * c_list
Definition: catcache.h:98
static void RehashCatCache(CatCache *cp)
Definition: catcache.c:749
TupleDesc cc_tupdesc
Definition: catcache.h:45
int cc_ntup
Definition: catcache.h:46
void heap_copytuple_with_tuple(HeapTuple src, HeapTuple dest)
Definition: heaptuple.c:637
int cc_nbuckets
Definition: catcache.h:47
int refcount
Definition: catcache.h:112
dlist_node cache_elem
Definition: catcache.h:89
bool negative
Definition: catcache.h:114
#define HeapTupleHasExternal(tuple)
Definition: htup_details.h:674
void * palloc(Size size)
Definition: mcxt.c:848
HeapTupleData tuple
Definition: catcache.h:116
int ct_magic
Definition: catcache.h:80
bool dead
Definition: catcache.h:113
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void CatalogCacheFlushCatalog ( Oid  catId)

Definition at line 610 of file catcache.c.

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

Referenced by LocalExecuteInvalidationMessage().

611 {
612  slist_iter iter;
613 
614  CACHE2_elog(DEBUG2, "CatalogCacheFlushCatalog called for %u", catId);
615 
617  {
618  CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
619 
620  /* Does this cache store tuples of the target catalog? */
621  if (cache->cc_reloid == catId)
622  {
623  /* Yes, so flush all its contents */
624  ResetCatalogCache(cache);
625 
626  /* Tell inval.c to call syscache callbacks for this cache */
627  CallSyscacheCallbacks(cache->id, 0);
628  }
629  }
630 
631  CACHE1_elog(DEBUG2, "end of CatalogCacheFlushCatalog call");
632 }
static void ResetCatalogCache(CatCache *cache)
Definition: catcache.c:533
static CatCacheHeader * CacheHdr
Definition: catcache.c:73
slist_node * cur
Definition: ilist.h:226
int id
Definition: catcache.h:39
Oid cc_reloid
Definition: catcache.h:42
#define DEBUG2
Definition: elog.h:24
#define slist_container(type, membername, ptr)
Definition: ilist.h:674
void CallSyscacheCallbacks(int cacheid, uint32 hashvalue)
Definition: inval.c:1450
#define CACHE1_elog(a, b)
Definition: catcache.c:64
slist_head ch_caches
Definition: catcache.h:161
#define slist_foreach(iter, lhead)
Definition: ilist.h:700
#define CACHE2_elog(a, b, c)
Definition: catcache.c:65
static void CatalogCacheInitializeCache ( CatCache cache)
static

Definition at line 812 of file catcache.c.

References AccessShareLock, Assert, BTEqualStrategyNumber, CACHE3_elog, CACHE4_elog, CacheMemoryContext, CatalogCacheInitializeCache_DEBUG1, CatalogCacheInitializeCache_DEBUG2, catcache::cc_hashfunc, catcache::cc_isname, catcache::cc_key, catcache::cc_nkeys, catcache::cc_relisshared, catcache::cc_relname, catcache::cc_reloid, catcache::cc_skey, catcache::cc_tupdesc, CreateTupleDescCopyConstr(), DEBUG2, elog, FATAL, fmgr_info_cxt(), GetCCHashEqFuncs(), heap_close, heap_open(), i, InvalidOid, MemoryContextSwitchTo(), NAMEOID, ObjectIdAttributeNumber, OIDOID, pstrdup(), RelationGetDescr, RelationGetForm, RelationGetRelationName, ScanKeyData::sk_attno, ScanKeyData::sk_collation, ScanKeyData::sk_func, ScanKeyData::sk_strategy, ScanKeyData::sk_subtype, and TupleDescAttr.

Referenced by GetCatCacheHashValue(), InitCatCachePhase2(), PrepareToInvalidateCacheTuple(), SearchCatCache(), and SearchCatCacheList().

813 {
814  Relation relation;
815  MemoryContext oldcxt;
816  TupleDesc tupdesc;
817  int i;
818 
820 
821  relation = heap_open(cache->cc_reloid, AccessShareLock);
822 
823  /*
824  * switch to the cache context so our allocations do not vanish at the end
825  * of a transaction
826  */
827  Assert(CacheMemoryContext != NULL);
828 
830 
831  /*
832  * copy the relcache's tuple descriptor to permanent cache storage
833  */
834  tupdesc = CreateTupleDescCopyConstr(RelationGetDescr(relation));
835 
836  /*
837  * save the relation's name and relisshared flag, too (cc_relname is used
838  * only for debugging purposes)
839  */
840  cache->cc_relname = pstrdup(RelationGetRelationName(relation));
841  cache->cc_relisshared = RelationGetForm(relation)->relisshared;
842 
843  /*
844  * return to the caller's memory context and close the rel
845  */
846  MemoryContextSwitchTo(oldcxt);
847 
848  heap_close(relation, AccessShareLock);
849 
850  CACHE3_elog(DEBUG2, "CatalogCacheInitializeCache: %s, %d keys",
851  cache->cc_relname, cache->cc_nkeys);
852 
853  /*
854  * initialize cache's key information
855  */
856  for (i = 0; i < cache->cc_nkeys; ++i)
857  {
858  Oid keytype;
859  RegProcedure eqfunc;
860 
862 
863  if (cache->cc_key[i] > 0)
864  {
865  Form_pg_attribute attr = TupleDescAttr(tupdesc,
866  cache->cc_key[i] - 1);
867 
868  keytype = attr->atttypid;
869  /* cache key columns should always be NOT NULL */
870  Assert(attr->attnotnull);
871  }
872  else
873  {
874  if (cache->cc_key[i] != ObjectIdAttributeNumber)
875  elog(FATAL, "only sys attr supported in caches is OID");
876  keytype = OIDOID;
877  }
878 
879  GetCCHashEqFuncs(keytype,
880  &cache->cc_hashfunc[i],
881  &eqfunc);
882 
883  cache->cc_isname[i] = (keytype == NAMEOID);
884 
885  /*
886  * Do equality-function lookup (we assume this won't need a catalog
887  * lookup for any supported type)
888  */
889  fmgr_info_cxt(eqfunc,
890  &cache->cc_skey[i].sk_func,
892 
893  /* Initialize sk_attno suitably for HeapKeyTest() and heap scans */
894  cache->cc_skey[i].sk_attno = cache->cc_key[i];
895 
896  /* Fill in sk_strategy as well --- always standard equality */
898  cache->cc_skey[i].sk_subtype = InvalidOid;
899  /* Currently, there are no catcaches on collation-aware data types */
900  cache->cc_skey[i].sk_collation = InvalidOid;
901 
902  CACHE4_elog(DEBUG2, "CatalogCacheInitializeCache %s %d %p",
903  cache->cc_relname,
904  i,
905  cache);
906  }
907 
908  /*
909  * mark this cache fully initialized
910  */
911  cache->cc_tupdesc = tupdesc;
912 }
Oid sk_subtype
Definition: skey.h:69
#define NAMEOID
Definition: pg_type.h:300
#define CatalogCacheInitializeCache_DEBUG1
Definition: catcache.c:807
#define CACHE3_elog(a, b, c, d)
Definition: catcache.c:66
#define RelationGetDescr(relation)
Definition: rel.h:428
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
#define OIDOID
Definition: pg_type.h:328
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
#define RelationGetForm(relation)
Definition: rel.h:410
char * pstrdup(const char *in)
Definition: mcxt.c:1076
regproc RegProcedure
Definition: c.h:389
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
bool cc_isname[CATCACHE_MAXKEYS]
Definition: catcache.h:53
bool cc_relisshared
Definition: catcache.h:44
Oid cc_reloid
Definition: catcache.h:42
int cc_key[CATCACHE_MAXKEYS]
Definition: catcache.h:49
int cc_nkeys
Definition: catcache.h:48
#define FATAL
Definition: elog.h:52
StrategyNumber sk_strategy
Definition: skey.h:68
TupleDesc cc_tupdesc
Definition: catcache.h:45
#define DEBUG2
Definition: elog.h:24
FmgrInfo sk_func
Definition: skey.h:71
#define RelationGetRelationName(relation)
Definition: rel.h:436
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define CatalogCacheInitializeCache_DEBUG2
Definition: catcache.c:808
TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc)
Definition: tupdesc.c:131
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:137
#define CACHE4_elog(a, b, c, d, e)
Definition: catcache.c:67
static void GetCCHashEqFuncs(Oid keytype, PGFunction *hashfunc, RegProcedure *eqfunc)
Definition: catcache.c:105
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:664
const char * cc_relname
Definition: catcache.h:41
Oid sk_collation
Definition: skey.h:70
int i
#define elog
Definition: elog.h:219
ScanKeyData cc_skey[CATCACHE_MAXKEYS]
Definition: catcache.h:51
PGFunction cc_hashfunc[CATCACHE_MAXKEYS]
Definition: catcache.h:50
#define BTEqualStrategyNumber
Definition: stratnum.h:31
AttrNumber sk_attno
Definition: skey.h:67
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void CatCacheInvalidate ( CatCache cache,
uint32  hashValue 
)

Definition at line 443 of file catcache.c.

References Assert, catctup::c_list, CACHE1_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().

444 {
445  Index hashIndex;
446  dlist_mutable_iter iter;
447 
448  CACHE1_elog(DEBUG2, "CatCacheInvalidate: called");
449 
450  /*
451  * We don't bother to check whether the cache has finished initialization
452  * yet; if not, there will be no entries in it so no problem.
453  */
454 
455  /*
456  * Invalidate *all* CatCLists in this cache; it's too hard to tell which
457  * searches might still be correct, so just zap 'em all.
458  */
459  dlist_foreach_modify(iter, &cache->cc_lists)
460  {
461  CatCList *cl = dlist_container(CatCList, cache_elem, iter.cur);
462 
463  if (cl->refcount > 0)
464  cl->dead = true;
465  else
466  CatCacheRemoveCList(cache, cl);
467  }
468 
469  /*
470  * inspect the proper hash bucket for tuple matches
471  */
472  hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
473  dlist_foreach_modify(iter, &cache->cc_bucket[hashIndex])
474  {
475  CatCTup *ct = dlist_container(CatCTup, cache_elem, iter.cur);
476 
477  if (hashValue == ct->hash_value)
478  {
479  if (ct->refcount > 0 ||
480  (ct->c_list && ct->c_list->refcount > 0))
481  {
482  ct->dead = true;
483  /* list, if any, was marked dead above */
484  Assert(ct->c_list == NULL || ct->c_list->dead);
485  }
486  else
487  CatCacheRemoveCTup(cache, ct);
488  CACHE1_elog(DEBUG2, "CatCacheInvalidate: invalidated");
489 #ifdef CATCACHE_STATS
490  cache->cc_invals++;
491 #endif
492  /* could be multiple matches, so keep looking! */
493  }
494  }
495 }
dlist_node * cur
Definition: ilist.h:180
uint32 hash_value
Definition: catcache.h:115
#define dlist_foreach_modify(iter, lhead)
Definition: ilist.h:524
#define HASH_INDEX(h, sz)
Definition: catcache.c:49
dlist_head * cc_bucket
Definition: catcache.h:55
bool dead
Definition: catcache.h:149
dlist_head cc_lists
Definition: catcache.h:54
struct catclist * c_list
Definition: catcache.h:98
#define dlist_container(type, membername, ptr)
Definition: ilist.h:477
#define DEBUG2
Definition: elog.h:24
static void CatCacheRemoveCList(CatCache *cache, CatCList *cl)
Definition: catcache.c:391
static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
Definition: catcache.c:354
unsigned int Index
Definition: c.h:359
#define CACHE1_elog(a, b)
Definition: catcache.c:64
#define Assert(condition)
Definition: c.h:664
int cc_nbuckets
Definition: catcache.h:47
int refcount
Definition: catcache.h:112
int refcount
Definition: catcache.h:148
bool dead
Definition: catcache.h:113
static void CatCacheRemoveCList ( CatCache cache,
CatCList cl 
)
static

Definition at line 391 of file catcache.c.

References Assert, catctup::c_list, catclist::cache_elem, CatCacheRemoveCTup(), catctup::dead, dlist_delete(), i, catclist::members, catclist::my_cache, catclist::n_members, pfree(), catctup::refcount, catclist::refcount, HeapTupleData::t_data, and catclist::tuple.

Referenced by CatCacheInvalidate(), CatCacheRemoveCTup(), ReleaseCatCacheList(), and ResetCatalogCache().

392 {
393  int i;
394 
395  Assert(cl->refcount == 0);
396  Assert(cl->my_cache == cache);
397 
398  /* delink from member tuples */
399  for (i = cl->n_members; --i >= 0;)
400  {
401  CatCTup *ct = cl->members[i];
402 
403  Assert(ct->c_list == cl);
404  ct->c_list = NULL;
405  /* if the member is dead and now has no references, remove it */
406  if (
407 #ifndef CATCACHE_FORCE_RELEASE
408  ct->dead &&
409 #endif
410  ct->refcount == 0)
411  CatCacheRemoveCTup(cache, ct);
412  }
413 
414  /* delink from linked list */
415  dlist_delete(&cl->cache_elem);
416 
417  /* free associated tuple data */
418  if (cl->tuple.t_data != NULL)
419  pfree(cl->tuple.t_data);
420  pfree(cl);
421 }
int n_members
Definition: catcache.h:154
struct catclist * c_list
Definition: catcache.h:98
HeapTupleHeader t_data
Definition: htup.h:67
CatCTup * members[FLEXIBLE_ARRAY_MEMBER]
Definition: catcache.h:155
void pfree(void *pointer)
Definition: mcxt.c:949
static void dlist_delete(dlist_node *node)
Definition: ilist.h:358
dlist_node cache_elem
Definition: catcache.h:147
static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
Definition: catcache.c:354
CatCache * my_cache
Definition: catcache.h:124
#define Assert(condition)
Definition: c.h:664
HeapTupleData tuple
Definition: catcache.h:153
int refcount
Definition: catcache.h:112
int i
int refcount
Definition: catcache.h:148
bool dead
Definition: catcache.h:113
static void CatCacheRemoveCTup ( CatCache cache,
CatCTup ct 
)
static

Definition at line 354 of file catcache.c.

References Assert, catctup::c_list, catctup::cache_elem, CatCacheRemoveCList(), catcache::cc_ntup, catcacheheader::ch_ntup, catctup::dead, dlist_delete(), catctup::my_cache, pfree(), catctup::refcount, HeapTupleData::t_data, and catctup::tuple.

Referenced by CatCacheInvalidate(), CatCacheRemoveCList(), ReleaseCatCache(), ResetCatalogCache(), and SearchCatCacheList().

355 {
356  Assert(ct->refcount == 0);
357  Assert(ct->my_cache == cache);
358 
359  if (ct->c_list)
360  {
361  /*
362  * The cleanest way to handle this is to call CatCacheRemoveCList,
363  * which will recurse back to me, and the recursive call will do the
364  * work. Set the "dead" flag to make sure it does recurse.
365  */
366  ct->dead = true;
367  CatCacheRemoveCList(cache, ct->c_list);
368  return; /* nothing left to do */
369  }
370 
371  /* delink from linked list */
372  dlist_delete(&ct->cache_elem);
373 
374  /* free associated tuple data */
375  if (ct->tuple.t_data != NULL)
376  pfree(ct->tuple.t_data);
377  pfree(ct);
378 
379  --cache->cc_ntup;
380  --CacheHdr->ch_ntup;
381 }
CatCache * my_cache
Definition: catcache.h:82
static CatCacheHeader * CacheHdr
Definition: catcache.c:73
struct catclist * c_list
Definition: catcache.h:98
HeapTupleHeader t_data
Definition: htup.h:67
void pfree(void *pointer)
Definition: mcxt.c:949
int cc_ntup
Definition: catcache.h:46
static void dlist_delete(dlist_node *node)
Definition: ilist.h:358
static void CatCacheRemoveCList(CatCache *cache, CatCList *cl)
Definition: catcache.c:391
#define Assert(condition)
Definition: c.h:664
int refcount
Definition: catcache.h:112
dlist_node cache_elem
Definition: catcache.h:89
HeapTupleData tuple
Definition: catcache.h:116
bool dead
Definition: catcache.h:113
void CreateCacheMemoryContext ( void  )

Definition at line 511 of file catcache.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), CacheMemoryContext, and TopMemoryContext.

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

512 {
513  /*
514  * Purely for paranoia, check that context doesn't exist; caller probably
515  * did so already.
516  */
517  if (!CacheMemoryContext)
519  "CacheMemoryContext",
521 }
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
MemoryContext TopMemoryContext
Definition: mcxt.c:43
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
uint32 GetCatCacheHashValue ( CatCache cache,
Datum  v1,
Datum  v2,
Datum  v3,
Datum  v4 
)

Definition at line 1285 of file catcache.c.

References CatalogCacheComputeHashValue(), CatalogCacheInitializeCache(), CATCACHE_MAXKEYS, catcache::cc_nkeys, catcache::cc_skey, catcache::cc_tupdesc, and ScanKeyData::sk_argument.

Referenced by GetSysCacheHashValue().

1290 {
1291  ScanKeyData cur_skey[CATCACHE_MAXKEYS];
1292 
1293  /*
1294  * one-time startup overhead for each cache
1295  */
1296  if (cache->cc_tupdesc == NULL)
1298 
1299  /*
1300  * initialize the search key information
1301  */
1302  memcpy(cur_skey, cache->cc_skey, sizeof(cur_skey));
1303  cur_skey[0].sk_argument = v1;
1304  cur_skey[1].sk_argument = v2;
1305  cur_skey[2].sk_argument = v3;
1306  cur_skey[3].sk_argument = v4;
1307 
1308  /*
1309  * calculate the hash value
1310  */
1311  return CatalogCacheComputeHashValue(cache, cache->cc_nkeys, cur_skey);
1312 }
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:812
static uint32 CatalogCacheComputeHashValue(CatCache *cache, int nkeys, ScanKey cur_skey)
Definition: catcache.c:174
#define CATCACHE_MAXKEYS
Definition: catcache.h:35
int cc_nkeys
Definition: catcache.h:48
TupleDesc cc_tupdesc
Definition: catcache.h:45
ScanKeyData cc_skey[CATCACHE_MAXKEYS]
Definition: catcache.h:51
Datum sk_argument
Definition: skey.h:72
static void GetCCHashEqFuncs ( Oid  keytype,
PGFunction hashfunc,
RegProcedure eqfunc 
)
static

Definition at line 105 of file catcache.c.

References BOOLOID, CHAROID, elog, FATAL, hashchar(), hashint2(), hashint4(), hashname(), hashoid(), hashoidvector(), hashtext(), INT2OID, INT4OID, InvalidOid, NAMEOID, OIDOID, OIDVECTOROID, REGCLASSOID, REGCONFIGOID, REGDICTIONARYOID, REGNAMESPACEOID, REGOPERATOROID, REGOPEROID, REGPROCEDUREOID, REGPROCOID, REGROLEOID, REGTYPEOID, and TEXTOID.

Referenced by CatalogCacheInitializeCache().

106 {
107  switch (keytype)
108  {
109  case BOOLOID:
110  *hashfunc = hashchar;
111 
112  *eqfunc = F_BOOLEQ;
113  break;
114  case CHAROID:
115  *hashfunc = hashchar;
116 
117  *eqfunc = F_CHAREQ;
118  break;
119  case NAMEOID:
120  *hashfunc = hashname;
121 
122  *eqfunc = F_NAMEEQ;
123  break;
124  case INT2OID:
125  *hashfunc = hashint2;
126 
127  *eqfunc = F_INT2EQ;
128  break;
129  case INT4OID:
130  *hashfunc = hashint4;
131 
132  *eqfunc = F_INT4EQ;
133  break;
134  case TEXTOID:
135  *hashfunc = hashtext;
136 
137  *eqfunc = F_TEXTEQ;
138  break;
139  case OIDOID:
140  case REGPROCOID:
141  case REGPROCEDUREOID:
142  case REGOPEROID:
143  case REGOPERATOROID:
144  case REGCLASSOID:
145  case REGTYPEOID:
146  case REGCONFIGOID:
147  case REGDICTIONARYOID:
148  case REGROLEOID:
149  case REGNAMESPACEOID:
150  *hashfunc = hashoid;
151 
152  *eqfunc = F_OIDEQ;
153  break;
154  case OIDVECTOROID:
155  *hashfunc = hashoidvector;
156 
157  *eqfunc = F_OIDVECTOREQ;
158  break;
159  default:
160  elog(FATAL, "type %u not supported as catcache key", keytype);
161  *hashfunc = NULL; /* keep compiler quiet */
162 
163  *eqfunc = InvalidOid;
164  break;
165  }
166 }
#define REGCLASSOID
Definition: pg_type.h:577
Datum hashoid(PG_FUNCTION_ARGS)
Definition: hashfunc.c:113
#define NAMEOID
Definition: pg_type.h:300
Datum hashname(PG_FUNCTION_ARGS)
Definition: hashfunc.c:225
#define REGROLEOID
Definition: pg_type.h:585
#define OIDOID
Definition: pg_type.h:328
#define TEXTOID
Definition: pg_type.h:324
#define INT4OID
Definition: pg_type.h:316
#define REGTYPEOID
Definition: pg_type.h:581
#define REGOPEROID
Definition: pg_type.h:569
Datum hashchar(PG_FUNCTION_ARGS)
Definition: hashfunc.c:44
#define OIDVECTOROID
Definition: pg_type.h:344
#define FATAL
Definition: elog.h:52
Datum hashtext(PG_FUNCTION_ARGS)
Definition: hashfunc.c:242
#define INT2OID
Definition: pg_type.h:308
#define REGDICTIONARYOID
Definition: pg_type.h:627
Datum hashint4(PG_FUNCTION_ARGS)
Definition: hashfunc.c:68
#define CHAROID
Definition: pg_type.h:296
#define InvalidOid
Definition: postgres_ext.h:36
#define BOOLOID
Definition: pg_type.h:288
#define REGCONFIGOID
Definition: pg_type.h:624
Datum hashint2(PG_FUNCTION_ARGS)
Definition: hashfunc.c:56
Datum hashoidvector(PG_FUNCTION_ARGS)
Definition: hashfunc.c:207
#define elog
Definition: elog.h:219
#define REGPROCEDUREOID
Definition: pg_type.h:565
#define REGNAMESPACEOID
Definition: pg_type.h:589
#define REGOPERATOROID
Definition: pg_type.h:573
#define REGPROCOID
Definition: pg_type.h:320
static bool IndexScanOK ( CatCache cache,
ScanKey  cur_skey 
)
static

Definition at line 975 of file catcache.c.

References AMNAME, AMOID, AUTHMEMMEMROLE, AUTHNAME, AUTHOID, criticalRelcachesBuilt, criticalSharedRelcachesBuilt, catcache::id, and INDEXRELID.

Referenced by SearchCatCache(), and SearchCatCacheList().

976 {
977  switch (cache->id)
978  {
979  case INDEXRELID:
980 
981  /*
982  * Rather than tracking exactly which indexes have to be loaded
983  * before we can use indexscans (which changes from time to time),
984  * just force all pg_index searches to be heap scans until we've
985  * built the critical relcaches.
986  */
988  return false;
989  break;
990 
991  case AMOID:
992  case AMNAME:
993 
994  /*
995  * Always do heap scans in pg_am, because it's so small there's
996  * not much point in an indexscan anyway. We *must* do this when
997  * initially building critical relcache entries, but we might as
998  * well just always do it.
999  */
1000  return false;
1001 
1002  case AUTHNAME:
1003  case AUTHOID:
1004  case AUTHMEMMEMROLE:
1005 
1006  /*
1007  * Protect authentication lookups occurring before relcache has
1008  * collected entries for shared indexes.
1009  */
1011  return false;
1012  break;
1013 
1014  default:
1015  break;
1016  }
1017 
1018  /* Normal case, allow index scan */
1019  return true;
1020 }
Definition: syscache.h:36
int id
Definition: catcache.h:39
bool criticalSharedRelcachesBuilt
Definition: relcache.c:135
bool criticalRelcachesBuilt
Definition: relcache.c:129
CatCache* InitCatCache ( int  id,
Oid  reloid,
Oid  indexoid,
int  nkeys,
const int *  key,
int  nbuckets 
)

Definition at line 654 of file catcache.c.

References Assert, CacheMemoryContext, catcache::cc_bucket, catcache::cc_indexoid, catcache::cc_key, 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, MemoryContextSwitchTo(), on_proc_exit(), palloc(), palloc0(), slist_init(), and slist_push_head().

Referenced by InitCatalogCache().

660 {
661  CatCache *cp;
662  MemoryContext oldcxt;
663  int i;
664 
665  /*
666  * nbuckets is the initial number of hash buckets to use in this catcache.
667  * It will be enlarged later if it becomes too full.
668  *
669  * nbuckets must be a power of two. We check this via Assert rather than
670  * a full runtime check because the values will be coming from constant
671  * tables.
672  *
673  * If you're confused by the power-of-two check, see comments in
674  * bitmapset.c for an explanation.
675  */
676  Assert(nbuckets > 0 && (nbuckets & -nbuckets) == nbuckets);
677 
678  /*
679  * first switch to the cache context so our allocations do not vanish at
680  * the end of a transaction
681  */
682  if (!CacheMemoryContext)
684 
686 
687  /*
688  * if first time through, initialize the cache group header
689  */
690  if (CacheHdr == NULL)
691  {
694  CacheHdr->ch_ntup = 0;
695 #ifdef CATCACHE_STATS
696  /* set up to dump stats at backend exit */
697  on_proc_exit(CatCachePrintStats, 0);
698 #endif
699  }
700 
701  /*
702  * allocate a new cache structure
703  *
704  * Note: we rely on zeroing to initialize all the dlist headers correctly
705  */
706  cp = (CatCache *) palloc0(sizeof(CatCache));
707  cp->cc_bucket = palloc0(nbuckets * sizeof(dlist_head));
708 
709  /*
710  * initialize the cache's relation information for the relation
711  * corresponding to this cache, and initialize some of the new cache's
712  * other internal fields. But don't open the relation yet.
713  */
714  cp->id = id;
715  cp->cc_relname = "(not known yet)";
716  cp->cc_reloid = reloid;
717  cp->cc_indexoid = indexoid;
718  cp->cc_relisshared = false; /* temporary */
719  cp->cc_tupdesc = (TupleDesc) NULL;
720  cp->cc_ntup = 0;
721  cp->cc_nbuckets = nbuckets;
722  cp->cc_nkeys = nkeys;
723  for (i = 0; i < nkeys; ++i)
724  cp->cc_key[i] = key[i];
725 
726  /*
727  * new cache is initialized as far as we can go for now. print some
728  * debugging information, if appropriate.
729  */
731 
732  /*
733  * add completed cache to top of group header's list
734  */
736 
737  /*
738  * back to the old context before we return...
739  */
740  MemoryContextSwitchTo(oldcxt);
741 
742  return cp;
743 }
static CatCacheHeader * CacheHdr
Definition: catcache.c:73
void on_proc_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:292
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
dlist_head * cc_bucket
Definition: catcache.h:55
static void slist_push_head(slist_head *head, slist_node *node)
Definition: ilist.h:574
slist_node cc_next
Definition: catcache.h:40
int id
Definition: catcache.h:39
bool cc_relisshared
Definition: catcache.h:44
Oid cc_indexoid
Definition: catcache.h:43
static void slist_init(slist_head *head)
Definition: ilist.h:554
Oid cc_reloid
Definition: catcache.h:42
int cc_key[CATCACHE_MAXKEYS]
Definition: catcache.h:49
int cc_nkeys
Definition: catcache.h:48
TupleDesc cc_tupdesc
Definition: catcache.h:45
int cc_ntup
Definition: catcache.h:46
void * palloc0(Size size)
Definition: mcxt.c:877
struct tupleDesc * TupleDesc
slist_head ch_caches
Definition: catcache.h:161
#define InitCatCache_DEBUG2
Definition: catcache.c:650
#define Assert(condition)
Definition: c.h:664
int cc_nbuckets
Definition: catcache.h:47
void CreateCacheMemoryContext(void)
Definition: catcache.c:511
const char * cc_relname
Definition: catcache.h:41
void * palloc(Size size)
Definition: mcxt.c:848
int i
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void InitCatCachePhase2 ( CatCache cache,
bool  touch_index 
)

Definition at line 924 of file catcache.c.

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().

925 {
926  if (cache->cc_tupdesc == NULL)
928 
929  if (touch_index &&
930  cache->id != AMOID &&
931  cache->id != AMNAME)
932  {
933  Relation idesc;
934 
935  /*
936  * We must lock the underlying catalog before opening the index to
937  * avoid deadlock, since index_open could possibly result in reading
938  * this same catalog, and if anyone else is exclusive-locking this
939  * catalog and index they'll be doing it in that order.
940  */
942  idesc = index_open(cache->cc_indexoid, AccessShareLock);
943 
944  /*
945  * While we've got the index open, let's check that it's unique (and
946  * not just deferrable-unique, thank you very much). This is just to
947  * catch thinkos in definitions of new catcaches, so we don't worry
948  * about the pg_am indexes not getting tested.
949  */
950  Assert(idesc->rd_index->indisunique &&
951  idesc->rd_index->indimmediate);
952 
955  }
956 }
Definition: syscache.h:36
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:182
#define AccessShareLock
Definition: lockdefs.h:36
int id
Definition: catcache.h:39
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:812
Oid cc_indexoid
Definition: catcache.h:43
Form_pg_index rd_index
Definition: rel.h:159
Oid cc_reloid
Definition: catcache.h:42
TupleDesc cc_tupdesc
Definition: catcache.h:45
#define Assert(condition)
Definition: c.h:664
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:176
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:105
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:151
void PrepareToInvalidateCacheTuple ( Relation  relation,
HeapTuple  tuple,
HeapTuple  newtuple,
void(*)(int, uint32, Oid function 
)

Definition at line 1782 of file catcache.c.

References Assert, CACHE1_elog, CatalogCacheComputeTupleHashValue(), CatalogCacheInitializeCache(), 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().

1786 {
1787  slist_iter iter;
1788  Oid reloid;
1789 
1790  CACHE1_elog(DEBUG2, "PrepareToInvalidateCacheTuple: called");
1791 
1792  /*
1793  * sanity checks
1794  */
1795  Assert(RelationIsValid(relation));
1796  Assert(HeapTupleIsValid(tuple));
1797  Assert(PointerIsValid(function));
1798  Assert(CacheHdr != NULL);
1799 
1800  reloid = RelationGetRelid(relation);
1801 
1802  /* ----------------
1803  * for each cache
1804  * if the cache contains tuples from the specified relation
1805  * compute the tuple's hash value(s) in this cache,
1806  * and call the passed function to register the information.
1807  * ----------------
1808  */
1809 
1811  {
1812  CatCache *ccp = slist_container(CatCache, cc_next, iter.cur);
1813  uint32 hashvalue;
1814  Oid dbid;
1815 
1816  if (ccp->cc_reloid != reloid)
1817  continue;
1818 
1819  /* Just in case cache hasn't finished initialization yet... */
1820  if (ccp->cc_tupdesc == NULL)
1822 
1823  hashvalue = CatalogCacheComputeTupleHashValue(ccp, tuple);
1824  dbid = ccp->cc_relisshared ? (Oid) 0 : MyDatabaseId;
1825 
1826  (*function) (ccp->id, hashvalue, dbid);
1827 
1828  if (newtuple)
1829  {
1830  uint32 newhashvalue;
1831 
1832  newhashvalue = CatalogCacheComputeTupleHashValue(ccp, newtuple);
1833 
1834  if (newhashvalue != hashvalue)
1835  (*function) (ccp->id, newhashvalue, dbid);
1836  }
1837  }
1838 }
static CatCacheHeader * CacheHdr
Definition: catcache.c:73
slist_node * cur
Definition: ilist.h:226
int id
Definition: catcache.h:39
unsigned int Oid
Definition: postgres_ext.h:31
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:812
bool cc_relisshared
Definition: catcache.h:44
Oid cc_reloid
Definition: catcache.h:42
#define RelationIsValid(relation)
Definition: rel.h:389
TupleDesc cc_tupdesc
Definition: catcache.h:45
#define DEBUG2
Definition: elog.h:24
unsigned int uint32
Definition: c.h:258
#define slist_container(type, membername, ptr)
Definition: ilist.h:674
Oid MyDatabaseId
Definition: globals.c:77
#define CACHE1_elog(a, b)
Definition: catcache.c:64
slist_head ch_caches
Definition: catcache.h:161
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:664
static uint32 CatalogCacheComputeTupleHashValue(CatCache *cache, HeapTuple tuple)
Definition: catcache.c:227
#define slist_foreach(iter, lhead)
Definition: ilist.h:700
#define PointerIsValid(pointer)
Definition: c.h:520
#define RelationGetRelid(relation)
Definition: rel.h:416
void PrintCatCacheLeakWarning ( HeapTuple  tuple)

Definition at line 1846 of file catcache.c.

References Assert, catcache::cc_relname, catctup::ct_magic, CT_MAGIC, elog, catcache::id, ItemPointerGetBlockNumber, ItemPointerGetOffsetNumber, catctup::my_cache, offsetof, catctup::refcount, HeapTupleData::t_self, and WARNING.

Referenced by ResourceOwnerReleaseInternal().

1847 {
1848  CatCTup *ct = (CatCTup *) (((char *) tuple) -
1849  offsetof(CatCTup, tuple));
1850 
1851  /* Safety check to ensure we were handed a cache entry */
1852  Assert(ct->ct_magic == CT_MAGIC);
1853 
1854  elog(WARNING, "cache reference leak: cache %s (%d), tuple %u/%u has count %d",
1855  ct->my_cache->cc_relname, ct->my_cache->id,
1856  ItemPointerGetBlockNumber(&(tuple->t_self)),
1858  ct->refcount);
1859 }
CatCache * my_cache
Definition: catcache.h:82
#define CT_MAGIC
Definition: catcache.h:81
int id
Definition: catcache.h:39
ItemPointerData t_self
Definition: htup.h:65
#define WARNING
Definition: elog.h:40
#define Assert(condition)
Definition: c.h:664
int refcount
Definition: catcache.h:112
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:95
const char * cc_relname
Definition: catcache.h:41
#define elog
Definition: elog.h:219
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:76
#define offsetof(type, field)
Definition: c.h:549
int ct_magic
Definition: catcache.h:80
void PrintCatCacheListLeakWarning ( CatCList list)

Definition at line 1862 of file catcache.c.

References catcache::cc_relname, elog, catcache::id, catclist::my_cache, catclist::refcount, and WARNING.

Referenced by ResourceOwnerReleaseInternal().

1863 {
1864  elog(WARNING, "cache reference leak: cache %s (%d), list %p has count %d",
1865  list->my_cache->cc_relname, list->my_cache->id,
1866  list, list->refcount);
1867 }
int id
Definition: catcache.h:39
#define WARNING
Definition: elog.h:40
CatCache * my_cache
Definition: catcache.h:124
const char * cc_relname
Definition: catcache.h:41
#define elog
Definition: elog.h:219
int refcount
Definition: catcache.h:148
static void RehashCatCache ( CatCache cp)
static

Definition at line 749 of file catcache.c.

References catctup::cache_elem, CacheMemoryContext, catcache::cc_bucket, catcache::cc_nbuckets, catcache::cc_ntup, catcache::cc_relname, dlist_mutable_iter::cur, DEBUG1, dlist_container, dlist_delete(), dlist_foreach_modify, dlist_push_head(), elog, HASH_INDEX, catctup::hash_value, i, catcache::id, MemoryContextAllocZero(), and pfree().

Referenced by CatalogCacheCreateEntry().

750 {
751  dlist_head *newbucket;
752  int newnbuckets;
753  int i;
754 
755  elog(DEBUG1, "rehashing catalog cache id %d for %s; %d tups, %d buckets",
756  cp->id, cp->cc_relname, cp->cc_ntup, cp->cc_nbuckets);
757 
758  /* Allocate a new, larger, hash table. */
759  newnbuckets = cp->cc_nbuckets * 2;
760  newbucket = (dlist_head *) MemoryContextAllocZero(CacheMemoryContext, newnbuckets * sizeof(dlist_head));
761 
762  /* Move all entries from old hash table to new. */
763  for (i = 0; i < cp->cc_nbuckets; i++)
764  {
765  dlist_mutable_iter iter;
766 
767  dlist_foreach_modify(iter, &cp->cc_bucket[i])
768  {
769  CatCTup *ct = dlist_container(CatCTup, cache_elem, iter.cur);
770  int hashIndex = HASH_INDEX(ct->hash_value, newnbuckets);
771 
772  dlist_delete(iter.cur);
773  dlist_push_head(&newbucket[hashIndex], &ct->cache_elem);
774  }
775  }
776 
777  /* Switch to the new array. */
778  pfree(cp->cc_bucket);
779  cp->cc_nbuckets = newnbuckets;
780  cp->cc_bucket = newbucket;
781 }
#define DEBUG1
Definition: elog.h:25
dlist_node * cur
Definition: ilist.h:180
uint32 hash_value
Definition: catcache.h:115
#define dlist_foreach_modify(iter, lhead)
Definition: ilist.h:524
#define HASH_INDEX(h, sz)
Definition: catcache.c:49
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:300
dlist_head * cc_bucket
Definition: catcache.h:55
int id
Definition: catcache.h:39
#define dlist_container(type, membername, ptr)
Definition: ilist.h:477
void pfree(void *pointer)
Definition: mcxt.c:949
int cc_ntup
Definition: catcache.h:46
static void dlist_delete(dlist_node *node)
Definition: ilist.h:358
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:741
int cc_nbuckets
Definition: catcache.h:47
const char * cc_relname
Definition: catcache.h:41
dlist_node cache_elem
Definition: catcache.h:89
int i
#define elog
Definition: elog.h:219
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void ReleaseCatCache ( HeapTuple  tuple)

Definition at line 1253 of file catcache.c.

References Assert, catctup::c_list, CatCacheRemoveCTup(), catctup::ct_magic, CT_MAGIC, CurrentResourceOwner, catctup::dead, catctup::my_cache, offsetof, catctup::refcount, catclist::refcount, ResourceOwnerForgetCatCacheRef(), and catctup::tuple.

Referenced by ReleaseSysCache(), and ResourceOwnerReleaseInternal().

1254 {
1255  CatCTup *ct = (CatCTup *) (((char *) tuple) -
1256  offsetof(CatCTup, tuple));
1257 
1258  /* Safety checks to ensure we were handed a cache entry */
1259  Assert(ct->ct_magic == CT_MAGIC);
1260  Assert(ct->refcount > 0);
1261 
1262  ct->refcount--;
1264 
1265  if (
1266 #ifndef CATCACHE_FORCE_RELEASE
1267  ct->dead &&
1268 #endif
1269  ct->refcount == 0 &&
1270  (ct->c_list == NULL || ct->c_list->refcount == 0))
1271  CatCacheRemoveCTup(ct->my_cache, ct);
1272 }
CatCache * my_cache
Definition: catcache.h:82
#define CT_MAGIC
Definition: catcache.h:81
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
void ResourceOwnerForgetCatCacheRef(ResourceOwner owner, HeapTuple tuple)
Definition: resowner.c:958
struct catclist * c_list
Definition: catcache.h:98
static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
Definition: catcache.c:354
#define Assert(condition)
Definition: c.h:664
int refcount
Definition: catcache.h:112
HeapTupleData tuple
Definition: catcache.h:116
int refcount
Definition: catcache.h:148
#define offsetof(type, field)
Definition: c.h:549
int ct_magic
Definition: catcache.h:80
bool dead
Definition: catcache.h:113
void ReleaseCatCacheList ( CatCList list)

Definition at line 1601 of file catcache.c.

References Assert, CatCacheRemoveCList(), catclist::cl_magic, CL_MAGIC, CurrentResourceOwner, catclist::dead, catclist::my_cache, catclist::refcount, and ResourceOwnerForgetCatCacheListRef().

Referenced by AddEnumLabel(), blvalidate(), brinvalidate(), btvalidate(), ginvalidate(), gistvalidate(), hashvalidate(), opfamily_can_sort_type(), RenameEnumLabel(), ResourceOwnerReleaseInternal(), sepgsql_relation_drop(), and spgvalidate().

1602 {
1603  /* Safety checks to ensure we were handed a cache entry */
1604  Assert(list->cl_magic == CL_MAGIC);
1605  Assert(list->refcount > 0);
1606  list->refcount--;
1608 
1609  if (
1610 #ifndef CATCACHE_FORCE_RELEASE
1611  list->dead &&
1612 #endif
1613  list->refcount == 0)
1614  CatCacheRemoveCList(list->my_cache, list);
1615 }
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
int cl_magic
Definition: catcache.h:122
bool dead
Definition: catcache.h:149
static void CatCacheRemoveCList(CatCache *cache, CatCList *cl)
Definition: catcache.c:391
#define CL_MAGIC
Definition: catcache.h:123
CatCache * my_cache
Definition: catcache.h:124
void ResourceOwnerForgetCatCacheListRef(ResourceOwner owner, CatCList *list)
Definition: resowner.c:993
#define Assert(condition)
Definition: c.h:664
int refcount
Definition: catcache.h:148
static void ResetCatalogCache ( CatCache cache)
static

Definition at line 533 of file catcache.c.

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

Referenced by CatalogCacheFlushCatalog(), and ResetCatalogCaches().

534 {
535  dlist_mutable_iter iter;
536  int i;
537 
538  /* Remove each list in this cache, or at least mark it dead */
539  dlist_foreach_modify(iter, &cache->cc_lists)
540  {
541  CatCList *cl = dlist_container(CatCList, cache_elem, iter.cur);
542 
543  if (cl->refcount > 0)
544  cl->dead = true;
545  else
546  CatCacheRemoveCList(cache, cl);
547  }
548 
549  /* Remove each tuple in this cache, or at least mark it dead */
550  for (i = 0; i < cache->cc_nbuckets; i++)
551  {
552  dlist_head *bucket = &cache->cc_bucket[i];
553 
554  dlist_foreach_modify(iter, bucket)
555  {
556  CatCTup *ct = dlist_container(CatCTup, cache_elem, iter.cur);
557 
558  if (ct->refcount > 0 ||
559  (ct->c_list && ct->c_list->refcount > 0))
560  {
561  ct->dead = true;
562  /* list, if any, was marked dead above */
563  Assert(ct->c_list == NULL || ct->c_list->dead);
564  }
565  else
566  CatCacheRemoveCTup(cache, ct);
567 #ifdef CATCACHE_STATS
568  cache->cc_invals++;
569 #endif
570  }
571  }
572 }
dlist_node * cur
Definition: ilist.h:180
#define dlist_foreach_modify(iter, lhead)
Definition: ilist.h:524
dlist_head * cc_bucket
Definition: catcache.h:55
bool dead
Definition: catcache.h:149
dlist_head cc_lists
Definition: catcache.h:54
struct catclist * c_list
Definition: catcache.h:98
#define dlist_container(type, membername, ptr)
Definition: ilist.h:477
static void CatCacheRemoveCList(CatCache *cache, CatCList *cl)
Definition: catcache.c:391
static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
Definition: catcache.c:354
#define Assert(condition)
Definition: c.h:664
int cc_nbuckets
Definition: catcache.h:47
int refcount
Definition: catcache.h:112
int i
int refcount
Definition: catcache.h:148
bool dead
Definition: catcache.h:113
void ResetCatalogCaches ( void  )

Definition at line 580 of file catcache.c.

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

Referenced by InvalidateSystemCaches().

581 {
582  slist_iter iter;
583 
584  CACHE1_elog(DEBUG2, "ResetCatalogCaches called");
585 
587  {
588  CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
589 
590  ResetCatalogCache(cache);
591  }
592 
593  CACHE1_elog(DEBUG2, "end of ResetCatalogCaches call");
594 }
static void ResetCatalogCache(CatCache *cache)
Definition: catcache.c:533
static CatCacheHeader * CacheHdr
Definition: catcache.c:73
slist_node * cur
Definition: ilist.h:226
#define DEBUG2
Definition: elog.h:24
#define slist_container(type, membername, ptr)
Definition: ilist.h:674
#define CACHE1_elog(a, b)
Definition: catcache.c:64
slist_head ch_caches
Definition: catcache.h:161
#define slist_foreach(iter, lhead)
Definition: ilist.h:700
HeapTuple SearchCatCache ( CatCache cache,
Datum  v1,
Datum  v2,
Datum  v3,
Datum  v4 
)

Definition at line 1039 of file catcache.c.

References AccessShareLock, Assert, build_dummy_tuple(), CACHE3_elog, CACHE4_elog, catctup::cache_elem, CatalogCacheComputeHashValue(), CatalogCacheCreateEntry(), CatalogCacheInitializeCache(), CATCACHE_MAXKEYS, catcache::cc_bucket, catcache::cc_indexoid, catcache::cc_nbuckets, catcache::cc_nkeys, catcache::cc_ntup, catcache::cc_relname, catcache::cc_reloid, catcache::cc_skey, catcache::cc_tupdesc, catcacheheader::ch_ntup, dlist_iter::cur, CurrentResourceOwner, catctup::dead, DEBUG2, dlist_container, dlist_foreach, dlist_move_head(), HASH_INDEX, catctup::hash_value, heap_close, heap_freetuple(), heap_open(), HeapKeyTest, HeapTupleIsValid, IndexScanOK(), IsBootstrapProcessingMode, IsTransactionState(), catctup::negative, catctup::refcount, ResourceOwnerEnlargeCatCacheRefs(), ResourceOwnerRememberCatCacheRef(), ScanKeyData::sk_argument, systable_beginscan(), systable_endscan(), systable_getnext(), and catctup::tuple.

Referenced by SearchSysCache().

1044 {
1045  ScanKeyData cur_skey[CATCACHE_MAXKEYS];
1046  uint32 hashValue;
1047  Index hashIndex;
1048  dlist_iter iter;
1049  dlist_head *bucket;
1050  CatCTup *ct;
1051  Relation relation;
1052  SysScanDesc scandesc;
1053  HeapTuple ntp;
1054 
1055  /* Make sure we're in an xact, even if this ends up being a cache hit */
1057 
1058  /*
1059  * one-time startup overhead for each cache
1060  */
1061  if (cache->cc_tupdesc == NULL)
1063 
1064 #ifdef CATCACHE_STATS
1065  cache->cc_searches++;
1066 #endif
1067 
1068  /*
1069  * initialize the search key information
1070  */
1071  memcpy(cur_skey, cache->cc_skey, sizeof(cur_skey));
1072  cur_skey[0].sk_argument = v1;
1073  cur_skey[1].sk_argument = v2;
1074  cur_skey[2].sk_argument = v3;
1075  cur_skey[3].sk_argument = v4;
1076 
1077  /*
1078  * find the hash bucket in which to look for the tuple
1079  */
1080  hashValue = CatalogCacheComputeHashValue(cache, cache->cc_nkeys, cur_skey);
1081  hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
1082 
1083  /*
1084  * scan the hash bucket until we find a match or exhaust our tuples
1085  *
1086  * Note: it's okay to use dlist_foreach here, even though we modify the
1087  * dlist within the loop, because we don't continue the loop afterwards.
1088  */
1089  bucket = &cache->cc_bucket[hashIndex];
1090  dlist_foreach(iter, bucket)
1091  {
1092  bool res;
1093 
1094  ct = dlist_container(CatCTup, cache_elem, iter.cur);
1095 
1096  if (ct->dead)
1097  continue; /* ignore dead entries */
1098 
1099  if (ct->hash_value != hashValue)
1100  continue; /* quickly skip entry if wrong hash val */
1101 
1102  /*
1103  * see if the cached tuple matches our key.
1104  */
1105  HeapKeyTest(&ct->tuple,
1106  cache->cc_tupdesc,
1107  cache->cc_nkeys,
1108  cur_skey,
1109  res);
1110  if (!res)
1111  continue;
1112 
1113  /*
1114  * We found a match in the cache. Move it to the front of the list
1115  * for its hashbucket, in order to speed subsequent searches. (The
1116  * most frequently accessed elements in any hashbucket will tend to be
1117  * near the front of the hashbucket's list.)
1118  */
1119  dlist_move_head(bucket, &ct->cache_elem);
1120 
1121  /*
1122  * If it's a positive entry, bump its refcount and return it. If it's
1123  * negative, we can report failure to the caller.
1124  */
1125  if (!ct->negative)
1126  {
1128  ct->refcount++;
1130 
1131  CACHE3_elog(DEBUG2, "SearchCatCache(%s): found in bucket %d",
1132  cache->cc_relname, hashIndex);
1133 
1134 #ifdef CATCACHE_STATS
1135  cache->cc_hits++;
1136 #endif
1137 
1138  return &ct->tuple;
1139  }
1140  else
1141  {
1142  CACHE3_elog(DEBUG2, "SearchCatCache(%s): found neg entry in bucket %d",
1143  cache->cc_relname, hashIndex);
1144 
1145 #ifdef CATCACHE_STATS
1146  cache->cc_neg_hits++;
1147 #endif
1148 
1149  return NULL;
1150  }
1151  }
1152 
1153  /*
1154  * Tuple was not found in cache, so we have to try to retrieve it directly
1155  * from the relation. If found, we will add it to the cache; if not
1156  * found, we will add a negative cache entry instead.
1157  *
1158  * NOTE: it is possible for recursive cache lookups to occur while reading
1159  * the relation --- for example, due to shared-cache-inval messages being
1160  * processed during heap_open(). This is OK. It's even possible for one
1161  * of those lookups to find and enter the very same tuple we are trying to
1162  * fetch here. If that happens, we will enter a second copy of the tuple
1163  * into the cache. The first copy will never be referenced again, and
1164  * will eventually age out of the cache, so there's no functional problem.
1165  * This case is rare enough that it's not worth expending extra cycles to
1166  * detect.
1167  */
1168  relation = heap_open(cache->cc_reloid, AccessShareLock);
1169 
1170  scandesc = systable_beginscan(relation,
1171  cache->cc_indexoid,
1172  IndexScanOK(cache, cur_skey),
1173  NULL,
1174  cache->cc_nkeys,
1175  cur_skey);
1176 
1177  ct = NULL;
1178 
1179  while (HeapTupleIsValid(ntp = systable_getnext(scandesc)))
1180  {
1181  ct = CatalogCacheCreateEntry(cache, ntp,
1182  hashValue, hashIndex,
1183  false);
1184  /* immediately set the refcount to 1 */
1186  ct->refcount++;
1188  break; /* assume only one match */
1189  }
1190 
1191  systable_endscan(scandesc);
1192 
1193  heap_close(relation, AccessShareLock);
1194 
1195  /*
1196  * If tuple was not found, we need to build a negative cache entry
1197  * containing a fake tuple. The fake tuple has the correct key columns,
1198  * but nulls everywhere else.
1199  *
1200  * In bootstrap mode, we don't build negative entries, because the cache
1201  * invalidation mechanism isn't alive and can't clear them if the tuple
1202  * gets created later. (Bootstrap doesn't do UPDATEs, so it doesn't need
1203  * cache inval for that.)
1204  */
1205  if (ct == NULL)
1206  {
1208  return NULL;
1209 
1210  ntp = build_dummy_tuple(cache, cache->cc_nkeys, cur_skey);
1211  ct = CatalogCacheCreateEntry(cache, ntp,
1212  hashValue, hashIndex,
1213  true);
1214  heap_freetuple(ntp);
1215 
1216  CACHE4_elog(DEBUG2, "SearchCatCache(%s): Contains %d/%d tuples",
1217  cache->cc_relname, cache->cc_ntup, CacheHdr->ch_ntup);
1218  CACHE3_elog(DEBUG2, "SearchCatCache(%s): put neg entry in bucket %d",
1219  cache->cc_relname, hashIndex);
1220 
1221  /*
1222  * We are not returning the negative entry to the caller, so leave its
1223  * refcount zero.
1224  */
1225 
1226  return NULL;
1227  }
1228 
1229  CACHE4_elog(DEBUG2, "SearchCatCache(%s): Contains %d/%d tuples",
1230  cache->cc_relname, cache->cc_ntup, CacheHdr->ch_ntup);
1231  CACHE3_elog(DEBUG2, "SearchCatCache(%s): put in bucket %d",
1232  cache->cc_relname, hashIndex);
1233 
1234 #ifdef CATCACHE_STATS
1235  cache->cc_newloads++;
1236 #endif
1237 
1238  return &ct->tuple;
1239 }
void ResourceOwnerRememberCatCacheRef(ResourceOwner owner, HeapTuple tuple)
Definition: resowner.c:949
uint32 hash_value
Definition: catcache.h:115
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define CACHE3_elog(a, b, c, d)
Definition: catcache.c:66
static CatCacheHeader * CacheHdr
Definition: catcache.c:73
#define HASH_INDEX(h, sz)
Definition: catcache.c:49
static CatCTup * CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp, uint32 hashValue, Index hashIndex, bool negative)
Definition: catcache.c:1624
#define dlist_foreach(iter, lhead)
Definition: ilist.h:507
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
dlist_head * cc_bucket
Definition: catcache.h:55
#define AccessShareLock
Definition: lockdefs.h:36
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:812
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
Oid cc_indexoid
Definition: catcache.h:43
#define dlist_container(type, membername, ptr)
Definition: ilist.h:477
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
static uint32 CatalogCacheComputeHashValue(CatCache *cache, int nkeys, ScanKey cur_skey)
Definition: catcache.c:174
#define CATCACHE_MAXKEYS
Definition: catcache.h:35
Oid cc_reloid
Definition: catcache.h:42
int cc_nkeys
Definition: catcache.h:48
TupleDesc cc_tupdesc
Definition: catcache.h:45
int cc_ntup
Definition: catcache.h:46
#define DEBUG2
Definition: elog.h:24
unsigned int uint32
Definition: c.h:258
#define CACHE4_elog(a, b, c, d, e)
Definition: catcache.c:67
static bool IndexScanOK(CatCache *cache, ScanKey cur_skey)
Definition: catcache.c:975
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
dlist_node * cur
Definition: ilist.h:161
unsigned int Index
Definition: c.h:359
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:664
static HeapTuple build_dummy_tuple(CatCache *cache, int nkeys, ScanKey skeys)
Definition: catcache.c:1690
int cc_nbuckets
Definition: catcache.h:47
int refcount
Definition: catcache.h:112
bool IsTransactionState(void)
Definition: xact.c:351
const char * cc_relname
Definition: catcache.h:41
static void dlist_move_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:385
dlist_node cache_elem
Definition: catcache.h:89
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:368
bool negative
Definition: catcache.h:114
HeapTupleData tuple
Definition: catcache.h:116
#define HeapKeyTest(tuple, tupdesc, nkeys, keys, result)
Definition: valid.h:22
ScanKeyData cc_skey[CATCACHE_MAXKEYS]
Definition: catcache.h:51
Datum sk_argument
Definition: skey.h:72
void ResourceOwnerEnlargeCatCacheRefs(ResourceOwner owner)
Definition: resowner.c:938
bool dead
Definition: catcache.h:113
CatCList* SearchCatCacheList ( CatCache cache,
int  nkeys,
Datum  v1,
Datum  v2,
Datum  v3,
Datum  v4 
)

Definition at line 1325 of file catcache.c.

References AccessShareLock, Assert, build_dummy_tuple(), catctup::c_list, CACHE2_elog, CACHE3_elog, catclist::cache_elem, CacheMemoryContext, CatalogCacheComputeHashValue(), CatalogCacheComputeTupleHashValue(), CatalogCacheCreateEntry(), CatalogCacheInitializeCache(), CATCACHE_MAXKEYS, CatCacheRemoveCTup(), catcache::cc_bucket, catcache::cc_indexoid, catcache::cc_lists, catcache::cc_nbuckets, 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, heap_close, heap_copytuple_with_tuple(), heap_freetuple(), heap_open(), HeapKeyTest, HeapTupleIsValid, i, IndexScanOK(), SysScanDescData::irel, ItemPointerEquals(), lappend(), lfirst, list_length(), catclist::members, MemoryContextSwitchTo(), catclist::my_cache, catclist::n_members, catctup::negative, NIL, catclist::nkeys, offsetof, catclist::ordered, palloc(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, catctup::refcount, catclist::refcount, ResourceOwnerEnlargeCatCacheListRefs(), ResourceOwnerRememberCatCacheListRef(), ScanKeyData::sk_argument, systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, catctup::tuple, and catclist::tuple.

Referenced by SearchSysCacheList().

1331 {
1332  ScanKeyData cur_skey[CATCACHE_MAXKEYS];
1333  uint32 lHashValue;
1334  dlist_iter iter;
1335  CatCList *cl;
1336  CatCTup *ct;
1337  List *volatile ctlist;
1338  ListCell *ctlist_item;
1339  int nmembers;
1340  bool ordered;
1341  HeapTuple ntp;
1342  MemoryContext oldcxt;
1343  int i;
1344 
1345  /*
1346  * one-time startup overhead for each cache
1347  */
1348  if (cache->cc_tupdesc == NULL)
1350 
1351  Assert(nkeys > 0 && nkeys < cache->cc_nkeys);
1352 
1353 #ifdef CATCACHE_STATS
1354  cache->cc_lsearches++;
1355 #endif
1356 
1357  /*
1358  * initialize the search key information
1359  */
1360  memcpy(cur_skey, cache->cc_skey, sizeof(cur_skey));
1361  cur_skey[0].sk_argument = v1;
1362  cur_skey[1].sk_argument = v2;
1363  cur_skey[2].sk_argument = v3;
1364  cur_skey[3].sk_argument = v4;
1365 
1366  /*
1367  * compute a hash value of the given keys for faster search. We don't
1368  * presently divide the CatCList items into buckets, but this still lets
1369  * us skip non-matching items quickly most of the time.
1370  */
1371  lHashValue = CatalogCacheComputeHashValue(cache, nkeys, cur_skey);
1372 
1373  /*
1374  * scan the items until we find a match or exhaust our list
1375  *
1376  * Note: it's okay to use dlist_foreach here, even though we modify the
1377  * dlist within the loop, because we don't continue the loop afterwards.
1378  */
1379  dlist_foreach(iter, &cache->cc_lists)
1380  {
1381  bool res;
1382 
1383  cl = dlist_container(CatCList, cache_elem, iter.cur);
1384 
1385  if (cl->dead)
1386  continue; /* ignore dead entries */
1387 
1388  if (cl->hash_value != lHashValue)
1389  continue; /* quickly skip entry if wrong hash val */
1390 
1391  /*
1392  * see if the cached list matches our key.
1393  */
1394  if (cl->nkeys != nkeys)
1395  continue;
1396  HeapKeyTest(&cl->tuple,
1397  cache->cc_tupdesc,
1398  nkeys,
1399  cur_skey,
1400  res);
1401  if (!res)
1402  continue;
1403 
1404  /*
1405  * We found a matching list. Move the list to the front of the
1406  * cache's list-of-lists, to speed subsequent searches. (We do not
1407  * move the members to the fronts of their hashbucket lists, however,
1408  * since there's no point in that unless they are searched for
1409  * individually.)
1410  */
1411  dlist_move_head(&cache->cc_lists, &cl->cache_elem);
1412 
1413  /* Bump the list's refcount and return it */
1415  cl->refcount++;
1417 
1418  CACHE2_elog(DEBUG2, "SearchCatCacheList(%s): found list",
1419  cache->cc_relname);
1420 
1421 #ifdef CATCACHE_STATS
1422  cache->cc_lhits++;
1423 #endif
1424 
1425  return cl;
1426  }
1427 
1428  /*
1429  * List was not found in cache, so we have to build it by reading the
1430  * relation. For each matching tuple found in the relation, use an
1431  * existing cache entry if possible, else build a new one.
1432  *
1433  * We have to bump the member refcounts temporarily to ensure they won't
1434  * get dropped from the cache while loading other members. We use a PG_TRY
1435  * block to ensure we can undo those refcounts if we get an error before
1436  * we finish constructing the CatCList.
1437  */
1439 
1440  ctlist = NIL;
1441 
1442  PG_TRY();
1443  {
1444  Relation relation;
1445  SysScanDesc scandesc;
1446 
1447  relation = heap_open(cache->cc_reloid, AccessShareLock);
1448 
1449  scandesc = systable_beginscan(relation,
1450  cache->cc_indexoid,
1451  IndexScanOK(cache, cur_skey),
1452  NULL,
1453  nkeys,
1454  cur_skey);
1455 
1456  /* The list will be ordered iff we are doing an index scan */
1457  ordered = (scandesc->irel != NULL);
1458 
1459  while (HeapTupleIsValid(ntp = systable_getnext(scandesc)))
1460  {
1461  uint32 hashValue;
1462  Index hashIndex;
1463  bool found = false;
1464  dlist_head *bucket;
1465 
1466  /*
1467  * See if there's an entry for this tuple already.
1468  */
1469  ct = NULL;
1470  hashValue = CatalogCacheComputeTupleHashValue(cache, ntp);
1471  hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
1472 
1473  bucket = &cache->cc_bucket[hashIndex];
1474  dlist_foreach(iter, bucket)
1475  {
1476  ct = dlist_container(CatCTup, cache_elem, iter.cur);
1477 
1478  if (ct->dead || ct->negative)
1479  continue; /* ignore dead and negative entries */
1480 
1481  if (ct->hash_value != hashValue)
1482  continue; /* quickly skip entry if wrong hash val */
1483 
1484  if (!ItemPointerEquals(&(ct->tuple.t_self), &(ntp->t_self)))
1485  continue; /* not same tuple */
1486 
1487  /*
1488  * Found a match, but can't use it if it belongs to another
1489  * list already
1490  */
1491  if (ct->c_list)
1492  continue;
1493 
1494  found = true;
1495  break; /* A-OK */
1496  }
1497 
1498  if (!found)
1499  {
1500  /* We didn't find a usable entry, so make a new one */
1501  ct = CatalogCacheCreateEntry(cache, ntp,
1502  hashValue, hashIndex,
1503  false);
1504  }
1505 
1506  /* Careful here: add entry to ctlist, then bump its refcount */
1507  /* This way leaves state correct if lappend runs out of memory */
1508  ctlist = lappend(ctlist, ct);
1509  ct->refcount++;
1510  }
1511 
1512  systable_endscan(scandesc);
1513 
1514  heap_close(relation, AccessShareLock);
1515 
1516  /*
1517  * Now we can build the CatCList entry. First we need a dummy tuple
1518  * containing the key values...
1519  */
1520  ntp = build_dummy_tuple(cache, nkeys, cur_skey);
1522  nmembers = list_length(ctlist);
1523  cl = (CatCList *)
1524  palloc(offsetof(CatCList, members) + nmembers * sizeof(CatCTup *));
1525  heap_copytuple_with_tuple(ntp, &cl->tuple);
1526  MemoryContextSwitchTo(oldcxt);
1527  heap_freetuple(ntp);
1528 
1529  /*
1530  * We are now past the last thing that could trigger an elog before we
1531  * have finished building the CatCList and remembering it in the
1532  * resource owner. So it's OK to fall out of the PG_TRY, and indeed
1533  * we'd better do so before we start marking the members as belonging
1534  * to the list.
1535  */
1536 
1537  }
1538  PG_CATCH();
1539  {
1540  foreach(ctlist_item, ctlist)
1541  {
1542  ct = (CatCTup *) lfirst(ctlist_item);
1543  Assert(ct->c_list == NULL);
1544  Assert(ct->refcount > 0);
1545  ct->refcount--;
1546  if (
1547 #ifndef CATCACHE_FORCE_RELEASE
1548  ct->dead &&
1549 #endif
1550  ct->refcount == 0 &&
1551  (ct->c_list == NULL || ct->c_list->refcount == 0))
1552  CatCacheRemoveCTup(cache, ct);
1553  }
1554 
1555  PG_RE_THROW();
1556  }
1557  PG_END_TRY();
1558 
1559  cl->cl_magic = CL_MAGIC;
1560  cl->my_cache = cache;
1561  cl->refcount = 0; /* for the moment */
1562  cl->dead = false;
1563  cl->ordered = ordered;
1564  cl->nkeys = nkeys;
1565  cl->hash_value = lHashValue;
1566  cl->n_members = nmembers;
1567 
1568  i = 0;
1569  foreach(ctlist_item, ctlist)
1570  {
1571  cl->members[i++] = ct = (CatCTup *) lfirst(ctlist_item);
1572  Assert(ct->c_list == NULL);
1573  ct->c_list = cl;
1574  /* release the temporary refcount on the member */
1575  Assert(ct->refcount > 0);
1576  ct->refcount--;
1577  /* mark list dead if any members already dead */
1578  if (ct->dead)
1579  cl->dead = true;
1580  }
1581  Assert(i == nmembers);
1582 
1583  dlist_push_head(&cache->cc_lists, &cl->cache_elem);
1584 
1585  /* Finally, bump the list's refcount and return it */
1586  cl->refcount++;
1588 
1589  CACHE3_elog(DEBUG2, "SearchCatCacheList(%s): made list of %d members",
1590  cache->cc_relname, nmembers);
1591 
1592  return cl;
1593 }
#define NIL
Definition: pg_list.h:69
Relation irel
Definition: relscan.h:156
int n_members
Definition: catcache.h:154
uint32 hash_value
Definition: catcache.h:152
uint32 hash_value
Definition: catcache.h:115
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define CACHE3_elog(a, b, c, d)
Definition: catcache.c:66
#define HASH_INDEX(h, sz)
Definition: catcache.c:49
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:300
static CatCTup * CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp, uint32 hashValue, Index hashIndex, bool negative)
Definition: catcache.c:1624
#define dlist_foreach(iter, lhead)
Definition: ilist.h:507
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
dlist_head * cc_bucket
Definition: catcache.h:55
#define AccessShareLock
Definition: lockdefs.h:36
void ResourceOwnerEnlargeCatCacheListRefs(ResourceOwner owner)
Definition: resowner.c:973
int cl_magic
Definition: catcache.h:122
bool dead
Definition: catcache.h:149
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
dlist_head cc_lists
Definition: catcache.h:54
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:812
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
short nkeys
Definition: catcache.h:151
struct catclist * c_list
Definition: catcache.h:98
CatCTup * members[FLEXIBLE_ARRAY_MEMBER]
Definition: catcache.h:155
Oid cc_indexoid
Definition: catcache.h:43
#define dlist_container(type, membername, ptr)
Definition: ilist.h:477
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
static uint32 CatalogCacheComputeHashValue(CatCache *cache, int nkeys, ScanKey cur_skey)
Definition: catcache.c:174
#define CATCACHE_MAXKEYS
Definition: catcache.h:35
Oid cc_reloid
Definition: catcache.h:42
ItemPointerData t_self
Definition: htup.h:65
TupleDesc cc_tupdesc
Definition: catcache.h:45
#define DEBUG2
Definition: elog.h:24
unsigned int uint32
Definition: c.h:258
List * lappend(List *list, void *datum)
Definition: list.c:128
dlist_node cache_elem
Definition: catcache.h:147
#define CL_MAGIC
Definition: catcache.h:123
static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
Definition: catcache.c:354
static bool IndexScanOK(CatCache *cache, ScanKey cur_skey)
Definition: catcache.c:975
void heap_copytuple_with_tuple(HeapTuple src, HeapTuple dest)
Definition: heaptuple.c:637
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
CatCache * my_cache
Definition: catcache.h:124
dlist_node * cur
Definition: ilist.h:161
unsigned int Index
Definition: c.h:359
#define PG_CATCH()
Definition: elog.h:293
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:664
#define lfirst(lc)
Definition: pg_list.h:106
static HeapTuple build_dummy_tuple(CatCache *cache, int nkeys, ScanKey skeys)
Definition: catcache.c:1690
int cc_nbuckets
Definition: catcache.h:47
HeapTupleData tuple
Definition: catcache.h:153
static int list_length(const List *l)
Definition: pg_list.h:89
int refcount
Definition: catcache.h:112
const char * cc_relname
Definition: catcache.h:41
#define PG_RE_THROW()
Definition: elog.h:314
bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)
Definition: itemptr.c:29
static uint32 CatalogCacheComputeTupleHashValue(CatCache *cache, HeapTuple tuple)
Definition: catcache.c:227
static void dlist_move_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:385
bool negative
Definition: catcache.h:114
bool ordered
Definition: catcache.h:150
void * palloc(Size size)
Definition: mcxt.c:848
int i
HeapTupleData tuple
Definition: catcache.h:116
#define CACHE2_elog(a, b, c)
Definition: catcache.c:65
#define HeapKeyTest(tuple, tupdesc, nkeys, keys, result)
Definition: valid.h:22
int refcount
Definition: catcache.h:148
#define PG_TRY()
Definition: elog.h:284
ScanKeyData cc_skey[CATCACHE_MAXKEYS]
Definition: catcache.h:51
Definition: pg_list.h:45
Datum sk_argument
Definition: skey.h:72
#define PG_END_TRY()
Definition: elog.h:300
#define offsetof(type, field)
Definition: c.h:549
bool dead
Definition: catcache.h:113
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void ResourceOwnerRememberCatCacheListRef(ResourceOwner owner, CatCList *list)
Definition: resowner.c:984

Variable Documentation

CatCacheHeader* CacheHdr = NULL
static

Definition at line 73 of file catcache.c.