PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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 struct catcache CatCache
 
typedef struct catctup CatCTup
 
typedef struct catclist CatCList
 
typedef struct catcacheheader CatCacheHeader
 

Functions

void CreateCacheMemoryContext (void)
 
void AtEOXact_CatCache (bool isCommit)
 
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)
 
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 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))
 
void PrintCatCacheLeakWarning (HeapTuple tuple)
 
void PrintCatCacheListLeakWarning (CatCList *list)
 

Variables

PGDLLIMPORT MemoryContext CacheMemoryContext
 

Macro Definition Documentation

#define CATCACHE_MAXKEYS   4
#define CL_MAGIC   0x52765103

Definition at line 123 of file catcache.h.

Referenced by AtEOXact_CatCache(), ReleaseCatCacheList(), and SearchCatCacheList().

#define CT_MAGIC   0x57261502

Typedef Documentation

Function Documentation

void AtEOXact_CatCache ( bool  isCommit)

Definition at line 534 of file catcache.c.

References Assert, catcache::cc_bucket, catcache::cc_lists, catcache::cc_nbuckets, catcacheheader::ch_caches, catclist::cl_magic, CL_MAGIC, catctup::ct_magic, CT_MAGIC, dlist_iter::cur, slist_iter::cur, catctup::dead, catclist::dead, dlist_container, dlist_foreach, i, catctup::refcount, catclist::refcount, slist_container, and slist_foreach.

Referenced by AbortTransaction(), CommitTransaction(), and PrepareTransaction().

535 {
536 #ifdef USE_ASSERT_CHECKING
537  slist_iter cache_iter;
538 
539  slist_foreach(cache_iter, &CacheHdr->ch_caches)
540  {
541  CatCache *ccp = slist_container(CatCache, cc_next, cache_iter.cur);
542  dlist_iter iter;
543  int i;
544 
545  /* Check CatCLists */
546  dlist_foreach(iter, &ccp->cc_lists)
547  {
548  CatCList *cl;
549 
550  cl = dlist_container(CatCList, cache_elem, iter.cur);
551  Assert(cl->cl_magic == CL_MAGIC);
552  Assert(cl->refcount == 0);
553  Assert(!cl->dead);
554  }
555 
556  /* Check individual tuples */
557  for (i = 0; i < ccp->cc_nbuckets; i++)
558  {
559  dlist_head *bucket = &ccp->cc_bucket[i];
560 
561  dlist_foreach(iter, bucket)
562  {
563  CatCTup *ct;
564 
565  ct = dlist_container(CatCTup, cache_elem, iter.cur);
566  Assert(ct->ct_magic == CT_MAGIC);
567  Assert(ct->refcount == 0);
568  Assert(!ct->dead);
569  }
570  }
571  }
572 #endif
573 }
static CatCacheHeader * CacheHdr
Definition: catcache.c:73
slist_node * cur
Definition: ilist.h:226
#define CT_MAGIC
Definition: catcache.h:81
#define dlist_foreach(iter, lhead)
Definition: ilist.h:507
dlist_head * cc_bucket
Definition: catcache.h:55
int cl_magic
Definition: catcache.h:122
bool dead
Definition: catcache.h:149
dlist_head cc_lists
Definition: catcache.h:54
#define dlist_container(type, membername, ptr)
Definition: ilist.h:477
#define CL_MAGIC
Definition: catcache.h:123
#define slist_container(type, membername, ptr)
Definition: ilist.h:674
dlist_node * cur
Definition: ilist.h:161
slist_head ch_caches
Definition: catcache.h:161
#define Assert(condition)
Definition: c.h:675
int cc_nbuckets
Definition: catcache.h:47
int refcount
Definition: catcache.h:112
#define slist_foreach(iter, lhead)
Definition: ilist.h:700
int i
int refcount
Definition: catcache.h:148
int ct_magic
Definition: catcache.h:80
bool dead
Definition: catcache.h:113
void CatalogCacheFlushCatalog ( Oid  catId)

Definition at line 661 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().

662 {
663  slist_iter iter;
664 
665  CACHE2_elog(DEBUG2, "CatalogCacheFlushCatalog called for %u", catId);
666 
668  {
669  CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
670 
671  /* Does this cache store tuples of the target catalog? */
672  if (cache->cc_reloid == catId)
673  {
674  /* Yes, so flush all its contents */
675  ResetCatalogCache(cache);
676 
677  /* Tell inval.c to call syscache callbacks for this cache */
678  CallSyscacheCallbacks(cache->id, 0);
679  }
680  }
681 
682  CACHE1_elog(DEBUG2, "end of CatalogCacheFlushCatalog call");
683 }
static void ResetCatalogCache(CatCache *cache)
Definition: catcache.c:584
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
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, NULL, 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:365
#define CACHE1_elog(a, b)
Definition: catcache.c:64
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
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
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 1335 of file catcache.c.

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

Referenced by GetSysCacheHashValue().

1340 {
1341  ScanKeyData cur_skey[CATCACHE_MAXKEYS];
1342 
1343  /*
1344  * one-time startup overhead for each cache
1345  */
1346  if (cache->cc_tupdesc == NULL)
1348 
1349  /*
1350  * initialize the search key information
1351  */
1352  memcpy(cur_skey, cache->cc_skey, sizeof(cur_skey));
1353  cur_skey[0].sk_argument = v1;
1354  cur_skey[1].sk_argument = v2;
1355  cur_skey[2].sk_argument = v3;
1356  cur_skey[3].sk_argument = v4;
1357 
1358  /*
1359  * calculate the hash value
1360  */
1361  return CatalogCacheComputeHashValue(cache, cache->cc_nkeys, cur_skey);
1362 }
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:863
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
#define NULL
Definition: c.h:229
ScanKeyData cc_skey[CATCACHE_MAXKEYS]
Definition: catcache.h:51
Datum sk_argument
Definition: skey.h:72
CatCache* InitCatCache ( int  id,
Oid  reloid,
Oid  indexoid,
int  nkeys,
const int *  key,
int  nbuckets 
)

Definition at line 705 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(), NULL, on_proc_exit(), palloc(), palloc0(), slist_init(), and slist_push_head().

Referenced by InitCatalogCache().

711 {
712  CatCache *cp;
713  MemoryContext oldcxt;
714  int i;
715 
716  /*
717  * nbuckets is the initial number of hash buckets to use in this catcache.
718  * It will be enlarged later if it becomes too full.
719  *
720  * nbuckets must be a power of two. We check this via Assert rather than
721  * a full runtime check because the values will be coming from constant
722  * tables.
723  *
724  * If you're confused by the power-of-two check, see comments in
725  * bitmapset.c for an explanation.
726  */
727  Assert(nbuckets > 0 && (nbuckets & -nbuckets) == nbuckets);
728 
729  /*
730  * first switch to the cache context so our allocations do not vanish at
731  * the end of a transaction
732  */
733  if (!CacheMemoryContext)
735 
737 
738  /*
739  * if first time through, initialize the cache group header
740  */
741  if (CacheHdr == NULL)
742  {
745  CacheHdr->ch_ntup = 0;
746 #ifdef CATCACHE_STATS
747  /* set up to dump stats at backend exit */
748  on_proc_exit(CatCachePrintStats, 0);
749 #endif
750  }
751 
752  /*
753  * allocate a new cache structure
754  *
755  * Note: we rely on zeroing to initialize all the dlist headers correctly
756  */
757  cp = (CatCache *) palloc0(sizeof(CatCache));
758  cp->cc_bucket = palloc0(nbuckets * sizeof(dlist_head));
759 
760  /*
761  * initialize the cache's relation information for the relation
762  * corresponding to this cache, and initialize some of the new cache's
763  * other internal fields. But don't open the relation yet.
764  */
765  cp->id = id;
766  cp->cc_relname = "(not known yet)";
767  cp->cc_reloid = reloid;
768  cp->cc_indexoid = indexoid;
769  cp->cc_relisshared = false; /* temporary */
770  cp->cc_tupdesc = (TupleDesc) NULL;
771  cp->cc_ntup = 0;
772  cp->cc_nbuckets = nbuckets;
773  cp->cc_nkeys = nkeys;
774  for (i = 0; i < nkeys; ++i)
775  cp->cc_key[i] = key[i];
776 
777  /*
778  * new cache is initialized as far as we can go for now. print some
779  * debugging information, if appropriate.
780  */
782 
783  /*
784  * add completed cache to top of group header's list
785  */
787 
788  /*
789  * back to the old context before we return...
790  */
791  MemoryContextSwitchTo(oldcxt);
792 
793  return cp;
794 }
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:878
struct tupleDesc * TupleDesc
slist_head ch_caches
Definition: catcache.h:161
#define InitCatCache_DEBUG2
Definition: catcache.c:701
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
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:849
int i
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void InitCatCachePhase2 ( CatCache cache,
bool  touch_index 
)

Definition at line 974 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(), NULL, RelationData::rd_index, and UnlockRelationOid().

Referenced by InitCatalogCachePhase2(), and SysCacheGetAttr().

975 {
976  if (cache->cc_tupdesc == NULL)
978 
979  if (touch_index &&
980  cache->id != AMOID &&
981  cache->id != AMNAME)
982  {
983  Relation idesc;
984 
985  /*
986  * We must lock the underlying catalog before opening the index to
987  * avoid deadlock, since index_open could possibly result in reading
988  * this same catalog, and if anyone else is exclusive-locking this
989  * catalog and index they'll be doing it in that order.
990  */
992  idesc = index_open(cache->cc_indexoid, AccessShareLock);
993 
994  /*
995  * While we've got the index open, let's check that it's unique (and
996  * not just deferrable-unique, thank you very much). This is just to
997  * catch thinkos in definitions of new catcaches, so we don't worry
998  * about the pg_am indexes not getting tested.
999  */
1000  Assert(idesc->rd_index->indisunique &&
1001  idesc->rd_index->indimmediate);
1002 
1003  index_close(idesc, AccessShareLock);
1005  }
1006 }
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:863
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 NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
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 1832 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, NULL, PointerIsValid, RelationGetRelid, RelationIsValid, slist_container, and slist_foreach.

Referenced by CacheInvalidateHeapTuple().

1836 {
1837  slist_iter iter;
1838  Oid reloid;
1839 
1840  CACHE1_elog(DEBUG2, "PrepareToInvalidateCacheTuple: called");
1841 
1842  /*
1843  * sanity checks
1844  */
1845  Assert(RelationIsValid(relation));
1846  Assert(HeapTupleIsValid(tuple));
1847  Assert(PointerIsValid(function));
1848  Assert(CacheHdr != NULL);
1849 
1850  reloid = RelationGetRelid(relation);
1851 
1852  /* ----------------
1853  * for each cache
1854  * if the cache contains tuples from the specified relation
1855  * compute the tuple's hash value(s) in this cache,
1856  * and call the passed function to register the information.
1857  * ----------------
1858  */
1859 
1861  {
1862  CatCache *ccp = slist_container(CatCache, cc_next, iter.cur);
1863  uint32 hashvalue;
1864  Oid dbid;
1865 
1866  if (ccp->cc_reloid != reloid)
1867  continue;
1868 
1869  /* Just in case cache hasn't finished initialization yet... */
1870  if (ccp->cc_tupdesc == NULL)
1872 
1873  hashvalue = CatalogCacheComputeTupleHashValue(ccp, tuple);
1874  dbid = ccp->cc_relisshared ? (Oid) 0 : MyDatabaseId;
1875 
1876  (*function) (ccp->id, hashvalue, dbid);
1877 
1878  if (newtuple)
1879  {
1880  uint32 newhashvalue;
1881 
1882  newhashvalue = CatalogCacheComputeTupleHashValue(ccp, newtuple);
1883 
1884  if (newhashvalue != hashvalue)
1885  (*function) (ccp->id, newhashvalue, dbid);
1886  }
1887  }
1888 }
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:863
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:268
#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 NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
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:526
#define RelationGetRelid(relation)
Definition: rel.h:416
void PrintCatCacheLeakWarning ( HeapTuple  tuple)

Definition at line 1896 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().

1897 {
1898  CatCTup *ct = (CatCTup *) (((char *) tuple) -
1899  offsetof(CatCTup, tuple));
1900 
1901  /* Safety check to ensure we were handed a cache entry */
1902  Assert(ct->ct_magic == CT_MAGIC);
1903 
1904  elog(WARNING, "cache reference leak: cache %s (%d), tuple %u/%u has count %d",
1905  ct->my_cache->cc_relname, ct->my_cache->id,
1906  ItemPointerGetBlockNumber(&(tuple->t_self)),
1908  ct->refcount);
1909 }
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:675
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:555
int ct_magic
Definition: catcache.h:80
void PrintCatCacheListLeakWarning ( CatCList list)

Definition at line 1912 of file catcache.c.

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

Referenced by ResourceOwnerReleaseInternal().

1913 {
1914  elog(WARNING, "cache reference leak: cache %s (%d), list %p has count %d",
1915  list->my_cache->cc_relname, list->my_cache->id,
1916  list, list->refcount);
1917 }
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
void ReleaseCatCache ( HeapTuple  tuple)

Definition at line 1303 of file catcache.c.

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

Referenced by ReleaseSysCache(), and ResourceOwnerReleaseInternal().

1304 {
1305  CatCTup *ct = (CatCTup *) (((char *) tuple) -
1306  offsetof(CatCTup, tuple));
1307 
1308  /* Safety checks to ensure we were handed a cache entry */
1309  Assert(ct->ct_magic == CT_MAGIC);
1310  Assert(ct->refcount > 0);
1311 
1312  ct->refcount--;
1314 
1315  if (
1316 #ifndef CATCACHE_FORCE_RELEASE
1317  ct->dead &&
1318 #endif
1319  ct->refcount == 0 &&
1320  (ct->c_list == NULL || ct->c_list->refcount == 0))
1321  CatCacheRemoveCTup(ct->my_cache, ct);
1322 }
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 NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
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:555
int ct_magic
Definition: catcache.h:80
bool dead
Definition: catcache.h:113
void ReleaseCatCacheList ( CatCList list)

Definition at line 1651 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().

1652 {
1653  /* Safety checks to ensure we were handed a cache entry */
1654  Assert(list->cl_magic == CL_MAGIC);
1655  Assert(list->refcount > 0);
1656  list->refcount--;
1658 
1659  if (
1660 #ifndef CATCACHE_FORCE_RELEASE
1661  list->dead &&
1662 #endif
1663  list->refcount == 0)
1664  CatCacheRemoveCList(list->my_cache, list);
1665 }
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:675
int refcount
Definition: catcache.h:148
void ResetCatalogCaches ( void  )

Definition at line 631 of file catcache.c.

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

Referenced by InvalidateSystemCaches().

632 {
633  slist_iter iter;
634 
635  CACHE1_elog(DEBUG2, "ResetCatalogCaches called");
636 
638  {
639  CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
640 
641  ResetCatalogCache(cache);
642  }
643 
644  CACHE1_elog(DEBUG2, "end of ResetCatalogCaches call");
645 }
static void ResetCatalogCache(CatCache *cache)
Definition: catcache.c:584
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 1089 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, NULL, catctup::refcount, ResourceOwnerEnlargeCatCacheRefs(), ResourceOwnerRememberCatCacheRef(), ScanKeyData::sk_argument, systable_beginscan(), systable_endscan(), systable_getnext(), and catctup::tuple.

Referenced by SearchSysCache().

1094 {
1095  ScanKeyData cur_skey[CATCACHE_MAXKEYS];
1096  uint32 hashValue;
1097  Index hashIndex;
1098  dlist_iter iter;
1099  dlist_head *bucket;
1100  CatCTup *ct;
1101  Relation relation;
1102  SysScanDesc scandesc;
1103  HeapTuple ntp;
1104 
1105  /* Make sure we're in an xact, even if this ends up being a cache hit */
1107 
1108  /*
1109  * one-time startup overhead for each cache
1110  */
1111  if (cache->cc_tupdesc == NULL)
1113 
1114 #ifdef CATCACHE_STATS
1115  cache->cc_searches++;
1116 #endif
1117 
1118  /*
1119  * initialize the search key information
1120  */
1121  memcpy(cur_skey, cache->cc_skey, sizeof(cur_skey));
1122  cur_skey[0].sk_argument = v1;
1123  cur_skey[1].sk_argument = v2;
1124  cur_skey[2].sk_argument = v3;
1125  cur_skey[3].sk_argument = v4;
1126 
1127  /*
1128  * find the hash bucket in which to look for the tuple
1129  */
1130  hashValue = CatalogCacheComputeHashValue(cache, cache->cc_nkeys, cur_skey);
1131  hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
1132 
1133  /*
1134  * scan the hash bucket until we find a match or exhaust our tuples
1135  *
1136  * Note: it's okay to use dlist_foreach here, even though we modify the
1137  * dlist within the loop, because we don't continue the loop afterwards.
1138  */
1139  bucket = &cache->cc_bucket[hashIndex];
1140  dlist_foreach(iter, bucket)
1141  {
1142  bool res;
1143 
1144  ct = dlist_container(CatCTup, cache_elem, iter.cur);
1145 
1146  if (ct->dead)
1147  continue; /* ignore dead entries */
1148 
1149  if (ct->hash_value != hashValue)
1150  continue; /* quickly skip entry if wrong hash val */
1151 
1152  /*
1153  * see if the cached tuple matches our key.
1154  */
1155  HeapKeyTest(&ct->tuple,
1156  cache->cc_tupdesc,
1157  cache->cc_nkeys,
1158  cur_skey,
1159  res);
1160  if (!res)
1161  continue;
1162 
1163  /*
1164  * We found a match in the cache. Move it to the front of the list
1165  * for its hashbucket, in order to speed subsequent searches. (The
1166  * most frequently accessed elements in any hashbucket will tend to be
1167  * near the front of the hashbucket's list.)
1168  */
1169  dlist_move_head(bucket, &ct->cache_elem);
1170 
1171  /*
1172  * If it's a positive entry, bump its refcount and return it. If it's
1173  * negative, we can report failure to the caller.
1174  */
1175  if (!ct->negative)
1176  {
1178  ct->refcount++;
1180 
1181  CACHE3_elog(DEBUG2, "SearchCatCache(%s): found in bucket %d",
1182  cache->cc_relname, hashIndex);
1183 
1184 #ifdef CATCACHE_STATS
1185  cache->cc_hits++;
1186 #endif
1187 
1188  return &ct->tuple;
1189  }
1190  else
1191  {
1192  CACHE3_elog(DEBUG2, "SearchCatCache(%s): found neg entry in bucket %d",
1193  cache->cc_relname, hashIndex);
1194 
1195 #ifdef CATCACHE_STATS
1196  cache->cc_neg_hits++;
1197 #endif
1198 
1199  return NULL;
1200  }
1201  }
1202 
1203  /*
1204  * Tuple was not found in cache, so we have to try to retrieve it directly
1205  * from the relation. If found, we will add it to the cache; if not
1206  * found, we will add a negative cache entry instead.
1207  *
1208  * NOTE: it is possible for recursive cache lookups to occur while reading
1209  * the relation --- for example, due to shared-cache-inval messages being
1210  * processed during heap_open(). This is OK. It's even possible for one
1211  * of those lookups to find and enter the very same tuple we are trying to
1212  * fetch here. If that happens, we will enter a second copy of the tuple
1213  * into the cache. The first copy will never be referenced again, and
1214  * will eventually age out of the cache, so there's no functional problem.
1215  * This case is rare enough that it's not worth expending extra cycles to
1216  * detect.
1217  */
1218  relation = heap_open(cache->cc_reloid, AccessShareLock);
1219 
1220  scandesc = systable_beginscan(relation,
1221  cache->cc_indexoid,
1222  IndexScanOK(cache, cur_skey),
1223  NULL,
1224  cache->cc_nkeys,
1225  cur_skey);
1226 
1227  ct = NULL;
1228 
1229  while (HeapTupleIsValid(ntp = systable_getnext(scandesc)))
1230  {
1231  ct = CatalogCacheCreateEntry(cache, ntp,
1232  hashValue, hashIndex,
1233  false);
1234  /* immediately set the refcount to 1 */
1236  ct->refcount++;
1238  break; /* assume only one match */
1239  }
1240 
1241  systable_endscan(scandesc);
1242 
1243  heap_close(relation, AccessShareLock);
1244 
1245  /*
1246  * If tuple was not found, we need to build a negative cache entry
1247  * containing a fake tuple. The fake tuple has the correct key columns,
1248  * but nulls everywhere else.
1249  *
1250  * In bootstrap mode, we don't build negative entries, because the cache
1251  * invalidation mechanism isn't alive and can't clear them if the tuple
1252  * gets created later. (Bootstrap doesn't do UPDATEs, so it doesn't need
1253  * cache inval for that.)
1254  */
1255  if (ct == NULL)
1256  {
1258  return NULL;
1259 
1260  ntp = build_dummy_tuple(cache, cache->cc_nkeys, cur_skey);
1261  ct = CatalogCacheCreateEntry(cache, ntp,
1262  hashValue, hashIndex,
1263  true);
1264  heap_freetuple(ntp);
1265 
1266  CACHE4_elog(DEBUG2, "SearchCatCache(%s): Contains %d/%d tuples",
1267  cache->cc_relname, cache->cc_ntup, CacheHdr->ch_ntup);
1268  CACHE3_elog(DEBUG2, "SearchCatCache(%s): put neg entry in bucket %d",
1269  cache->cc_relname, hashIndex);
1270 
1271  /*
1272  * We are not returning the negative entry to the caller, so leave its
1273  * refcount zero.
1274  */
1275 
1276  return NULL;
1277  }
1278 
1279  CACHE4_elog(DEBUG2, "SearchCatCache(%s): Contains %d/%d tuples",
1280  cache->cc_relname, cache->cc_ntup, CacheHdr->ch_ntup);
1281  CACHE3_elog(DEBUG2, "SearchCatCache(%s): put in bucket %d",
1282  cache->cc_relname, hashIndex);
1283 
1284 #ifdef CATCACHE_STATS
1285  cache->cc_newloads++;
1286 #endif
1287 
1288  return &ct->tuple;
1289 }
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:1674
#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:1372
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:863
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:268
#define CACHE4_elog(a, b, c, d, e)
Definition: catcache.c:67
static bool IndexScanOK(CatCache *cache, ScanKey cur_skey)
Definition: catcache.c:1025
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
dlist_node * cur
Definition: ilist.h:161
unsigned int Index
Definition: c.h:365
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
static HeapTuple build_dummy_tuple(CatCache *cache, int nkeys, ScanKey skeys)
Definition: catcache.c:1740
int cc_nbuckets
Definition: catcache.h:47
int refcount
Definition: catcache.h:112
bool IsTransactionState(void)
Definition: xact.c:350
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 1375 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, NULL, 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().

1381 {
1382  ScanKeyData cur_skey[CATCACHE_MAXKEYS];
1383  uint32 lHashValue;
1384  dlist_iter iter;
1385  CatCList *cl;
1386  CatCTup *ct;
1387  List *volatile ctlist;
1388  ListCell *ctlist_item;
1389  int nmembers;
1390  bool ordered;
1391  HeapTuple ntp;
1392  MemoryContext oldcxt;
1393  int i;
1394 
1395  /*
1396  * one-time startup overhead for each cache
1397  */
1398  if (cache->cc_tupdesc == NULL)
1400 
1401  Assert(nkeys > 0 && nkeys < cache->cc_nkeys);
1402 
1403 #ifdef CATCACHE_STATS
1404  cache->cc_lsearches++;
1405 #endif
1406 
1407  /*
1408  * initialize the search key information
1409  */
1410  memcpy(cur_skey, cache->cc_skey, sizeof(cur_skey));
1411  cur_skey[0].sk_argument = v1;
1412  cur_skey[1].sk_argument = v2;
1413  cur_skey[2].sk_argument = v3;
1414  cur_skey[3].sk_argument = v4;
1415 
1416  /*
1417  * compute a hash value of the given keys for faster search. We don't
1418  * presently divide the CatCList items into buckets, but this still lets
1419  * us skip non-matching items quickly most of the time.
1420  */
1421  lHashValue = CatalogCacheComputeHashValue(cache, nkeys, cur_skey);
1422 
1423  /*
1424  * scan the items until we find a match or exhaust our list
1425  *
1426  * Note: it's okay to use dlist_foreach here, even though we modify the
1427  * dlist within the loop, because we don't continue the loop afterwards.
1428  */
1429  dlist_foreach(iter, &cache->cc_lists)
1430  {
1431  bool res;
1432 
1433  cl = dlist_container(CatCList, cache_elem, iter.cur);
1434 
1435  if (cl->dead)
1436  continue; /* ignore dead entries */
1437 
1438  if (cl->hash_value != lHashValue)
1439  continue; /* quickly skip entry if wrong hash val */
1440 
1441  /*
1442  * see if the cached list matches our key.
1443  */
1444  if (cl->nkeys != nkeys)
1445  continue;
1446  HeapKeyTest(&cl->tuple,
1447  cache->cc_tupdesc,
1448  nkeys,
1449  cur_skey,
1450  res);
1451  if (!res)
1452  continue;
1453 
1454  /*
1455  * We found a matching list. Move the list to the front of the
1456  * cache's list-of-lists, to speed subsequent searches. (We do not
1457  * move the members to the fronts of their hashbucket lists, however,
1458  * since there's no point in that unless they are searched for
1459  * individually.)
1460  */
1461  dlist_move_head(&cache->cc_lists, &cl->cache_elem);
1462 
1463  /* Bump the list's refcount and return it */
1465  cl->refcount++;
1467 
1468  CACHE2_elog(DEBUG2, "SearchCatCacheList(%s): found list",
1469  cache->cc_relname);
1470 
1471 #ifdef CATCACHE_STATS
1472  cache->cc_lhits++;
1473 #endif
1474 
1475  return cl;
1476  }
1477 
1478  /*
1479  * List was not found in cache, so we have to build it by reading the
1480  * relation. For each matching tuple found in the relation, use an
1481  * existing cache entry if possible, else build a new one.
1482  *
1483  * We have to bump the member refcounts temporarily to ensure they won't
1484  * get dropped from the cache while loading other members. We use a PG_TRY
1485  * block to ensure we can undo those refcounts if we get an error before
1486  * we finish constructing the CatCList.
1487  */
1489 
1490  ctlist = NIL;
1491 
1492  PG_TRY();
1493  {
1494  Relation relation;
1495  SysScanDesc scandesc;
1496 
1497  relation = heap_open(cache->cc_reloid, AccessShareLock);
1498 
1499  scandesc = systable_beginscan(relation,
1500  cache->cc_indexoid,
1501  IndexScanOK(cache, cur_skey),
1502  NULL,
1503  nkeys,
1504  cur_skey);
1505 
1506  /* The list will be ordered iff we are doing an index scan */
1507  ordered = (scandesc->irel != NULL);
1508 
1509  while (HeapTupleIsValid(ntp = systable_getnext(scandesc)))
1510  {
1511  uint32 hashValue;
1512  Index hashIndex;
1513  bool found = false;
1514  dlist_head *bucket;
1515 
1516  /*
1517  * See if there's an entry for this tuple already.
1518  */
1519  ct = NULL;
1520  hashValue = CatalogCacheComputeTupleHashValue(cache, ntp);
1521  hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
1522 
1523  bucket = &cache->cc_bucket[hashIndex];
1524  dlist_foreach(iter, bucket)
1525  {
1526  ct = dlist_container(CatCTup, cache_elem, iter.cur);
1527 
1528  if (ct->dead || ct->negative)
1529  continue; /* ignore dead and negative entries */
1530 
1531  if (ct->hash_value != hashValue)
1532  continue; /* quickly skip entry if wrong hash val */
1533 
1534  if (!ItemPointerEquals(&(ct->tuple.t_self), &(ntp->t_self)))
1535  continue; /* not same tuple */
1536 
1537  /*
1538  * Found a match, but can't use it if it belongs to another
1539  * list already
1540  */
1541  if (ct->c_list)
1542  continue;
1543 
1544  found = true;
1545  break; /* A-OK */
1546  }
1547 
1548  if (!found)
1549  {
1550  /* We didn't find a usable entry, so make a new one */
1551  ct = CatalogCacheCreateEntry(cache, ntp,
1552  hashValue, hashIndex,
1553  false);
1554  }
1555 
1556  /* Careful here: add entry to ctlist, then bump its refcount */
1557  /* This way leaves state correct if lappend runs out of memory */
1558  ctlist = lappend(ctlist, ct);
1559  ct->refcount++;
1560  }
1561 
1562  systable_endscan(scandesc);
1563 
1564  heap_close(relation, AccessShareLock);
1565 
1566  /*
1567  * Now we can build the CatCList entry. First we need a dummy tuple
1568  * containing the key values...
1569  */
1570  ntp = build_dummy_tuple(cache, nkeys, cur_skey);
1572  nmembers = list_length(ctlist);
1573  cl = (CatCList *)
1574  palloc(offsetof(CatCList, members) + nmembers * sizeof(CatCTup *));
1575  heap_copytuple_with_tuple(ntp, &cl->tuple);
1576  MemoryContextSwitchTo(oldcxt);
1577  heap_freetuple(ntp);
1578 
1579  /*
1580  * We are now past the last thing that could trigger an elog before we
1581  * have finished building the CatCList and remembering it in the
1582  * resource owner. So it's OK to fall out of the PG_TRY, and indeed
1583  * we'd better do so before we start marking the members as belonging
1584  * to the list.
1585  */
1586 
1587  }
1588  PG_CATCH();
1589  {
1590  foreach(ctlist_item, ctlist)
1591  {
1592  ct = (CatCTup *) lfirst(ctlist_item);
1593  Assert(ct->c_list == NULL);
1594  Assert(ct->refcount > 0);
1595  ct->refcount--;
1596  if (
1597 #ifndef CATCACHE_FORCE_RELEASE
1598  ct->dead &&
1599 #endif
1600  ct->refcount == 0 &&
1601  (ct->c_list == NULL || ct->c_list->refcount == 0))
1602  CatCacheRemoveCTup(cache, ct);
1603  }
1604 
1605  PG_RE_THROW();
1606  }
1607  PG_END_TRY();
1608 
1609  cl->cl_magic = CL_MAGIC;
1610  cl->my_cache = cache;
1611  cl->refcount = 0; /* for the moment */
1612  cl->dead = false;
1613  cl->ordered = ordered;
1614  cl->nkeys = nkeys;
1615  cl->hash_value = lHashValue;
1616  cl->n_members = nmembers;
1617 
1618  i = 0;
1619  foreach(ctlist_item, ctlist)
1620  {
1621  cl->members[i++] = ct = (CatCTup *) lfirst(ctlist_item);
1622  Assert(ct->c_list == NULL);
1623  ct->c_list = cl;
1624  /* release the temporary refcount on the member */
1625  Assert(ct->refcount > 0);
1626  ct->refcount--;
1627  /* mark list dead if any members already dead */
1628  if (ct->dead)
1629  cl->dead = true;
1630  }
1631  Assert(i == nmembers);
1632 
1633  dlist_push_head(&cache->cc_lists, &cl->cache_elem);
1634 
1635  /* Finally, bump the list's refcount and return it */
1636  cl->refcount++;
1638 
1639  CACHE3_elog(DEBUG2, "SearchCatCacheList(%s): made list of %d members",
1640  cache->cc_relname, nmembers);
1641 
1642  return cl;
1643 }
#define NIL
Definition: pg_list.h:69
Relation irel
Definition: relscan.h:155
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:1674
#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:1372
dlist_head cc_lists
Definition: catcache.h:54
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:863
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:268
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:1025
void heap_copytuple_with_tuple(HeapTuple src, HeapTuple dest)
Definition: heaptuple.c:634
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
CatCache * my_cache
Definition: catcache.h:124
dlist_node * cur
Definition: ilist.h:161
unsigned int Index
Definition: c.h:365
#define PG_CATCH()
Definition: elog.h:293
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
static HeapTuple build_dummy_tuple(CatCache *cache, int nkeys, ScanKey skeys)
Definition: catcache.c:1740
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:849
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:555
bool dead
Definition: catcache.h:113
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void ResourceOwnerRememberCatCacheListRef(ResourceOwner owner, CatCList *list)
Definition: resowner.c:984

Variable Documentation

PGDLLIMPORT MemoryContext CacheMemoryContext

Definition at line 46 of file mcxt.c.