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 CatalogCacheIdInvalidate (int cacheId, 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 548 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().

549 {
550 #ifdef USE_ASSERT_CHECKING
551  slist_iter cache_iter;
552 
553  slist_foreach(cache_iter, &CacheHdr->ch_caches)
554  {
555  CatCache *ccp = slist_container(CatCache, cc_next, cache_iter.cur);
556  dlist_iter iter;
557  int i;
558 
559  /* Check CatCLists */
560  dlist_foreach(iter, &ccp->cc_lists)
561  {
562  CatCList *cl;
563 
564  cl = dlist_container(CatCList, cache_elem, iter.cur);
565  Assert(cl->cl_magic == CL_MAGIC);
566  Assert(cl->refcount == 0);
567  Assert(!cl->dead);
568  }
569 
570  /* Check individual tuples */
571  for (i = 0; i < ccp->cc_nbuckets; i++)
572  {
573  dlist_head *bucket = &ccp->cc_bucket[i];
574 
575  dlist_foreach(iter, bucket)
576  {
577  CatCTup *ct;
578 
579  ct = dlist_container(CatCTup, cache_elem, iter.cur);
580  Assert(ct->ct_magic == CT_MAGIC);
581  Assert(ct->refcount == 0);
582  Assert(!ct->dead);
583  }
584  }
585  }
586 #endif
587 }
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:670
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 675 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().

676 {
677  slist_iter iter;
678 
679  CACHE2_elog(DEBUG2, "CatalogCacheFlushCatalog called for %u", catId);
680 
682  {
683  CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
684 
685  /* Does this cache store tuples of the target catalog? */
686  if (cache->cc_reloid == catId)
687  {
688  /* Yes, so flush all its contents */
689  ResetCatalogCache(cache);
690 
691  /* Tell inval.c to call syscache callbacks for this cache */
692  CallSyscacheCallbacks(cache->id, 0);
693  }
694  }
695 
696  CACHE1_elog(DEBUG2, "end of CatalogCacheFlushCatalog call");
697 }
static void ResetCatalogCache(CatCache *cache)
Definition: catcache.c:598
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:1422
#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 CatalogCacheIdInvalidate ( int  cacheId,
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, catcacheheader::ch_caches, dlist_mutable_iter::cur, slist_iter::cur, catctup::dead, catclist::dead, DEBUG2, dlist_container, dlist_foreach_modify, HASH_INDEX, catctup::hash_value, catcache::id, NULL, catctup::refcount, catclist::refcount, slist_container, and slist_foreach.

Referenced by LocalExecuteInvalidationMessage().

444 {
445  slist_iter cache_iter;
446 
447  CACHE1_elog(DEBUG2, "CatalogCacheIdInvalidate: called");
448 
449  /*
450  * inspect caches to find the proper cache
451  */
452  slist_foreach(cache_iter, &CacheHdr->ch_caches)
453  {
454  CatCache *ccp = slist_container(CatCache, cc_next, cache_iter.cur);
455  Index hashIndex;
456  dlist_mutable_iter iter;
457 
458  if (cacheId != ccp->id)
459  continue;
460 
461  /*
462  * We don't bother to check whether the cache has finished
463  * initialization yet; if not, there will be no entries in it so no
464  * problem.
465  */
466 
467  /*
468  * Invalidate *all* CatCLists in this cache; it's too hard to tell
469  * which searches might still be correct, so just zap 'em all.
470  */
471  dlist_foreach_modify(iter, &ccp->cc_lists)
472  {
473  CatCList *cl = dlist_container(CatCList, cache_elem, iter.cur);
474 
475  if (cl->refcount > 0)
476  cl->dead = true;
477  else
478  CatCacheRemoveCList(ccp, cl);
479  }
480 
481  /*
482  * inspect the proper hash bucket for tuple matches
483  */
484  hashIndex = HASH_INDEX(hashValue, ccp->cc_nbuckets);
485  dlist_foreach_modify(iter, &ccp->cc_bucket[hashIndex])
486  {
487  CatCTup *ct = dlist_container(CatCTup, cache_elem, iter.cur);
488 
489  if (hashValue == ct->hash_value)
490  {
491  if (ct->refcount > 0 ||
492  (ct->c_list && ct->c_list->refcount > 0))
493  {
494  ct->dead = true;
495  /* list, if any, was marked dead above */
496  Assert(ct->c_list == NULL || ct->c_list->dead);
497  }
498  else
499  CatCacheRemoveCTup(ccp, ct);
500  CACHE1_elog(DEBUG2, "CatalogCacheIdInvalidate: invalidated");
501 #ifdef CATCACHE_STATS
502  ccp->cc_invals++;
503 #endif
504  /* could be multiple matches, so keep looking! */
505  }
506  }
507  break; /* need only search this one cache */
508  }
509 }
dlist_node * cur
Definition: ilist.h:180
uint32 hash_value
Definition: catcache.h:115
#define dlist_foreach_modify(iter, lhead)
Definition: ilist.h:524
static CatCacheHeader * CacheHdr
Definition: catcache.c:73
#define HASH_INDEX(h, sz)
Definition: catcache.c:49
slist_node * cur
Definition: ilist.h:226
dlist_head * cc_bucket
Definition: catcache.h:55
int id
Definition: catcache.h:39
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
#define slist_container(type, membername, ptr)
Definition: ilist.h:674
unsigned int Index
Definition: c.h:361
#define CACHE1_elog(a, b)
Definition: catcache.c:64
slist_head ch_caches
Definition: catcache.h:161
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
int cc_nbuckets
Definition: catcache.h:47
int refcount
Definition: catcache.h:112
#define slist_foreach(iter, lhead)
Definition: ilist.h:700
int refcount
Definition: catcache.h:148
bool dead
Definition: catcache.h:113
void CreateCacheMemoryContext ( void  )

Definition at line 525 of file catcache.c.

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

Referenced by ApplyWorkerMain(), 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().

526 {
527  /*
528  * Purely for paranoia, check that context doesn't exist; caller probably
529  * did so already.
530  */
531  if (!CacheMemoryContext)
533  "CacheMemoryContext",
535 }
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:145
MemoryContext TopMemoryContext
Definition: mcxt.c:43
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:440
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
uint32 GetCatCacheHashValue ( CatCache cache,
Datum  v1,
Datum  v2,
Datum  v3,
Datum  v4 
)

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

1354 {
1355  ScanKeyData cur_skey[CATCACHE_MAXKEYS];
1356 
1357  /*
1358  * one-time startup overhead for each cache
1359  */
1360  if (cache->cc_tupdesc == NULL)
1362 
1363  /*
1364  * initialize the search key information
1365  */
1366  memcpy(cur_skey, cache->cc_skey, sizeof(cur_skey));
1367  cur_skey[0].sk_argument = v1;
1368  cur_skey[1].sk_argument = v2;
1369  cur_skey[2].sk_argument = v3;
1370  cur_skey[3].sk_argument = v4;
1371 
1372  /*
1373  * calculate the hash value
1374  */
1375  return CatalogCacheComputeHashValue(cache, cache->cc_nkeys, cur_skey);
1376 }
static void CatalogCacheInitializeCache(CatCache *cache)
Definition: catcache.c:877
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:226
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 719 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().

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

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

989 {
990  if (cache->cc_tupdesc == NULL)
992 
993  if (touch_index &&
994  cache->id != AMOID &&
995  cache->id != AMNAME)
996  {
997  Relation idesc;
998 
999  /*
1000  * We must lock the underlying catalog before opening the index to
1001  * avoid deadlock, since index_open could possibly result in reading
1002  * this same catalog, and if anyone else is exclusive-locking this
1003  * catalog and index they'll be doing it in that order.
1004  */
1006  idesc = index_open(cache->cc_indexoid, AccessShareLock);
1007 
1008  /*
1009  * While we've got the index open, let's check that it's unique (and
1010  * not just deferrable-unique, thank you very much). This is just to
1011  * catch thinkos in definitions of new catcaches, so we don't worry
1012  * about the pg_am indexes not getting tested.
1013  */
1014  Assert(idesc->rd_index->indisunique &&
1015  idesc->rd_index->indimmediate);
1016 
1017  index_close(idesc, AccessShareLock);
1019  }
1020 }
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:877
Oid cc_indexoid
Definition: catcache.h:43
Form_pg_index rd_index
Definition: rel.h:155
Oid cc_reloid
Definition: catcache.h:42
TupleDesc cc_tupdesc
Definition: catcache.h:45
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
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 1846 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().

1850 {
1851  slist_iter iter;
1852  Oid reloid;
1853 
1854  CACHE1_elog(DEBUG2, "PrepareToInvalidateCacheTuple: called");
1855 
1856  /*
1857  * sanity checks
1858  */
1859  Assert(RelationIsValid(relation));
1860  Assert(HeapTupleIsValid(tuple));
1861  Assert(PointerIsValid(function));
1862  Assert(CacheHdr != NULL);
1863 
1864  reloid = RelationGetRelid(relation);
1865 
1866  /* ----------------
1867  * for each cache
1868  * if the cache contains tuples from the specified relation
1869  * compute the tuple's hash value(s) in this cache,
1870  * and call the passed function to register the information.
1871  * ----------------
1872  */
1873 
1875  {
1876  CatCache *ccp = slist_container(CatCache, cc_next, iter.cur);
1877  uint32 hashvalue;
1878  Oid dbid;
1879 
1880  if (ccp->cc_reloid != reloid)
1881  continue;
1882 
1883  /* Just in case cache hasn't finished initialization yet... */
1884  if (ccp->cc_tupdesc == NULL)
1886 
1887  hashvalue = CatalogCacheComputeTupleHashValue(ccp, tuple);
1888  dbid = ccp->cc_relisshared ? (Oid) 0 : MyDatabaseId;
1889 
1890  (*function) (ccp->id, hashvalue, dbid);
1891 
1892  if (newtuple)
1893  {
1894  uint32 newhashvalue;
1895 
1896  newhashvalue = CatalogCacheComputeTupleHashValue(ccp, newtuple);
1897 
1898  if (newhashvalue != hashvalue)
1899  (*function) (ccp->id, newhashvalue, dbid);
1900  }
1901  }
1902 }
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:877
bool cc_relisshared
Definition: catcache.h:44
Oid cc_reloid
Definition: catcache.h:42
#define RelationIsValid(relation)
Definition: rel.h:386
TupleDesc cc_tupdesc
Definition: catcache.h:45
#define DEBUG2
Definition: elog.h:24
unsigned int uint32
Definition: c.h:265
#define slist_container(type, membername, ptr)
Definition: ilist.h:674
Oid MyDatabaseId
Definition: globals.c:76
#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:226
#define Assert(condition)
Definition: c.h:670
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:521
#define RelationGetRelid(relation)
Definition: rel.h:413
void PrintCatCacheLeakWarning ( HeapTuple  tuple)

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

1911 {
1912  CatCTup *ct = (CatCTup *) (((char *) tuple) -
1913  offsetof(CatCTup, tuple));
1914 
1915  /* Safety check to ensure we were handed a cache entry */
1916  Assert(ct->ct_magic == CT_MAGIC);
1917 
1918  elog(WARNING, "cache reference leak: cache %s (%d), tuple %u/%u has count %d",
1919  ct->my_cache->cc_relname, ct->my_cache->id,
1920  ItemPointerGetBlockNumber(&(tuple->t_self)),
1922  ct->refcount);
1923 }
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:670
int refcount
Definition: catcache.h:112
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:76
const char * cc_relname
Definition: catcache.h:41
#define elog
Definition: elog.h:219
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:66
#define offsetof(type, field)
Definition: c.h:550
int ct_magic
Definition: catcache.h:80
void PrintCatCacheListLeakWarning ( CatCList list)

Definition at line 1926 of file catcache.c.

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

Referenced by ResourceOwnerReleaseInternal().

1927 {
1928  elog(WARNING, "cache reference leak: cache %s (%d), list %p has count %d",
1929  list->my_cache->cc_relname, list->my_cache->id,
1930  list, list->refcount);
1931 }
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 1317 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().

1318 {
1319  CatCTup *ct = (CatCTup *) (((char *) tuple) -
1320  offsetof(CatCTup, tuple));
1321 
1322  /* Safety checks to ensure we were handed a cache entry */
1323  Assert(ct->ct_magic == CT_MAGIC);
1324  Assert(ct->refcount > 0);
1325 
1326  ct->refcount--;
1328 
1329  if (
1330 #ifndef CATCACHE_FORCE_RELEASE
1331  ct->dead &&
1332 #endif
1333  ct->refcount == 0 &&
1334  (ct->c_list == NULL || ct->c_list->refcount == 0))
1335  CatCacheRemoveCTup(ct->my_cache, ct);
1336 }
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:226
#define Assert(condition)
Definition: c.h:670
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:550
int ct_magic
Definition: catcache.h:80
bool dead
Definition: catcache.h:113
void ReleaseCatCacheList ( CatCList list)

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

1666 {
1667  /* Safety checks to ensure we were handed a cache entry */
1668  Assert(list->cl_magic == CL_MAGIC);
1669  Assert(list->refcount > 0);
1670  list->refcount--;
1672 
1673  if (
1674 #ifndef CATCACHE_FORCE_RELEASE
1675  list->dead &&
1676 #endif
1677  list->refcount == 0)
1678  CatCacheRemoveCList(list->my_cache, list);
1679 }
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:670
int refcount
Definition: catcache.h:148
void ResetCatalogCaches ( void  )

Definition at line 645 of file catcache.c.

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

Referenced by InvalidateSystemCaches().

646 {
647  slist_iter iter;
648 
649  CACHE1_elog(DEBUG2, "ResetCatalogCaches called");
650 
652  {
653  CatCache *cache = slist_container(CatCache, cc_next, iter.cur);
654 
655  ResetCatalogCache(cache);
656  }
657 
658  CACHE1_elog(DEBUG2, "end of ResetCatalogCaches call");
659 }
static void ResetCatalogCache(CatCache *cache)
Definition: catcache.c:598
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 1103 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().

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

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