mirror of
https://github.com/postgres/postgres.git
synced 2025-04-29 13:56:47 +03:00
Do some restructuring to improve performance of the catcaches. Teach
CatalogCacheFlushRelation (formerly called SystemCacheRelationFlushed) how to distinguish tuples it should flush from those it needn't; this means a relcache flush event now only removes the catcache entries it ought to, rather than zapping the caches completely as it used to. Testing with the regression tests indicates that this considerably improves the lifespan of catcache entries. Also, rearrange catcache data structures so that the limit on number of cached tuples applies globally across all the catcaches, rather than being per-catcache. It was a little silly to have the same size limit on both, say, pg_attribute caches and pg_am caches (there being only four possible rows in the latter...). Doing LRU removal across all the caches instead of locally in each one should reduce cache reload traffic in the more heavily used caches and improve the efficiency of cache memory use.
This commit is contained in:
parent
41c377f5c6
commit
2c5aa2acb4
301
src/backend/utils/cache/catcache.c
vendored
301
src/backend/utils/cache/catcache.c
vendored
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.78 2001/06/01 02:41:36 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.79 2001/06/18 03:35:07 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -29,17 +29,15 @@
|
|||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
|
|
||||||
|
|
||||||
static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct);
|
/* #define CACHEDEBUG */ /* turns DEBUG elogs on */
|
||||||
static Index CatalogCacheComputeHashIndex(CatCache *cache,
|
|
||||||
ScanKey cur_skey);
|
/* voodoo constants */
|
||||||
static Index CatalogCacheComputeTupleHashIndex(CatCache *cache,
|
#define NCCBUCKETS 257 /* Hash buckets per CatCache (prime!) */
|
||||||
HeapTuple tuple);
|
#define MAXCCTUPLES 5000 /* Maximum # of tuples in all caches */
|
||||||
static void CatalogCacheInitializeCache(CatCache *cache);
|
|
||||||
static Datum cc_hashname(PG_FUNCTION_ARGS);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* variables, macros and other stuff
|
* variables, macros and other stuff
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef CACHEDEBUG
|
#ifdef CACHEDEBUG
|
||||||
@ -58,8 +56,8 @@ static Datum cc_hashname(PG_FUNCTION_ARGS);
|
|||||||
#define CACHE6_elog(a,b,c,d,e,f,g)
|
#define CACHE6_elog(a,b,c,d,e,f,g)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static CatCache *Caches = NULL; /* head of list of caches */
|
/* Cache management header --- pointer is NULL until created */
|
||||||
|
static CatCacheHeader *CacheHdr = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* EQPROC is used in CatalogCacheInitializeCache to find the equality
|
* EQPROC is used in CatalogCacheInitializeCache to find the equality
|
||||||
@ -68,7 +66,6 @@ static CatCache *Caches = NULL; /* head of list of caches */
|
|||||||
*
|
*
|
||||||
* XXX this should be replaced by catalog lookups,
|
* XXX this should be replaced by catalog lookups,
|
||||||
* but that seems to pose considerable risk of circularity...
|
* but that seems to pose considerable risk of circularity...
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
static const Oid eqproc[] = {
|
static const Oid eqproc[] = {
|
||||||
F_BOOLEQ, InvalidOid, F_CHAREQ, F_NAMEEQ, InvalidOid,
|
F_BOOLEQ, InvalidOid, F_CHAREQ, F_NAMEEQ, InvalidOid,
|
||||||
@ -78,9 +75,18 @@ static const Oid eqproc[] = {
|
|||||||
|
|
||||||
#define EQPROC(SYSTEMTYPEOID) eqproc[(SYSTEMTYPEOID)-BOOLOID]
|
#define EQPROC(SYSTEMTYPEOID) eqproc[(SYSTEMTYPEOID)-BOOLOID]
|
||||||
|
|
||||||
|
|
||||||
|
static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct);
|
||||||
|
static Index CatalogCacheComputeHashIndex(CatCache *cache,
|
||||||
|
ScanKey cur_skey);
|
||||||
|
static Index CatalogCacheComputeTupleHashIndex(CatCache *cache,
|
||||||
|
HeapTuple tuple);
|
||||||
|
static void CatalogCacheInitializeCache(CatCache *cache);
|
||||||
|
static Datum cc_hashname(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* internal support functions
|
* internal support functions
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static PGFunction
|
static PGFunction
|
||||||
@ -116,7 +122,6 @@ GetCCHashFunc(Oid keytype)
|
|||||||
static Datum
|
static Datum
|
||||||
cc_hashname(PG_FUNCTION_ARGS)
|
cc_hashname(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We need our own variant of hashname because we want to accept
|
* We need our own variant of hashname because we want to accept
|
||||||
* null-terminated C strings as search values for name fields. So, we
|
* null-terminated C strings as search values for name fields. So, we
|
||||||
@ -141,7 +146,6 @@ cc_hashname(PG_FUNCTION_ARGS)
|
|||||||
void
|
void
|
||||||
CreateCacheMemoryContext(void)
|
CreateCacheMemoryContext(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Purely for paranoia, check that context doesn't exist; caller
|
* Purely for paranoia, check that context doesn't exist; caller
|
||||||
* probably did so already.
|
* probably did so already.
|
||||||
@ -161,7 +165,6 @@ CreateCacheMemoryContext(void)
|
|||||||
* This function does final initialization of a catcache: obtain the tuple
|
* This function does final initialization of a catcache: obtain the tuple
|
||||||
* descriptor and set up the hash and equality function links. We assume
|
* descriptor and set up the hash and equality function links. We assume
|
||||||
* that the relcache entry can be opened at this point!
|
* that the relcache entry can be opened at this point!
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
#ifdef CACHEDEBUG
|
#ifdef CACHEDEBUG
|
||||||
#define CatalogCacheInitializeCache_DEBUG1 \
|
#define CatalogCacheInitializeCache_DEBUG1 \
|
||||||
@ -191,7 +194,7 @@ CatalogCacheInitializeCache(CatCache *cache)
|
|||||||
Relation relation;
|
Relation relation;
|
||||||
MemoryContext oldcxt;
|
MemoryContext oldcxt;
|
||||||
TupleDesc tupdesc;
|
TupleDesc tupdesc;
|
||||||
short i;
|
int i;
|
||||||
|
|
||||||
CatalogCacheInitializeCache_DEBUG1;
|
CatalogCacheInitializeCache_DEBUG1;
|
||||||
|
|
||||||
@ -206,8 +209,7 @@ CatalogCacheInitializeCache(CatCache *cache)
|
|||||||
* switch to the cache context so our allocations do not vanish at the
|
* switch to the cache context so our allocations do not vanish at the
|
||||||
* end of a transaction
|
* end of a transaction
|
||||||
*/
|
*/
|
||||||
if (!CacheMemoryContext)
|
Assert(CacheMemoryContext != NULL);
|
||||||
CreateCacheMemoryContext();
|
|
||||||
|
|
||||||
oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
|
oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
|
||||||
|
|
||||||
@ -286,7 +288,6 @@ CatalogCacheInitializeCache(CatCache *cache)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* CatalogCacheComputeHashIndex
|
* CatalogCacheComputeHashIndex
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
static Index
|
static Index
|
||||||
CatalogCacheComputeHashIndex(CatCache *cache, ScanKey cur_skey)
|
CatalogCacheComputeHashIndex(CatCache *cache, ScanKey cur_skey)
|
||||||
@ -330,7 +331,6 @@ CatalogCacheComputeHashIndex(CatCache *cache, ScanKey cur_skey)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* CatalogCacheComputeTupleHashIndex
|
* CatalogCacheComputeTupleHashIndex
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
static Index
|
static Index
|
||||||
CatalogCacheComputeTupleHashIndex(CatCache *cache,
|
CatalogCacheComputeTupleHashIndex(CatCache *cache,
|
||||||
@ -396,12 +396,12 @@ CatalogCacheComputeTupleHashIndex(CatCache *cache,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* CatCacheRemoveCTup
|
* CatCacheRemoveCTup
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
|
CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
|
||||||
{
|
{
|
||||||
Assert(ct->refcount == 0);
|
Assert(ct->refcount == 0);
|
||||||
|
Assert(ct->my_cache == cache);
|
||||||
|
|
||||||
/* delink from linked lists */
|
/* delink from linked lists */
|
||||||
DLRemove(&ct->lrulist_elem);
|
DLRemove(&ct->lrulist_elem);
|
||||||
@ -413,6 +413,7 @@ CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
|
|||||||
pfree(ct);
|
pfree(ct);
|
||||||
|
|
||||||
--cache->cc_ntup;
|
--cache->cc_ntup;
|
||||||
|
--CacheHdr->ch_ntup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -422,7 +423,6 @@ CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
|
|||||||
* be found (whether the cache has opened its relation or not). Of course,
|
* be found (whether the cache has opened its relation or not). Of course,
|
||||||
* if the cache has yet to open its relation, there will be no tuples so
|
* if the cache has yet to open its relation, there will be no tuples so
|
||||||
* no problem.
|
* no problem.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
CatalogCacheIdInvalidate(int cacheId,
|
CatalogCacheIdInvalidate(int cacheId,
|
||||||
@ -433,17 +433,14 @@ CatalogCacheIdInvalidate(int cacheId,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* sanity checks
|
* sanity checks
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
Assert(hashIndex < NCCBUCK);
|
|
||||||
Assert(ItemPointerIsValid(pointer));
|
Assert(ItemPointerIsValid(pointer));
|
||||||
CACHE1_elog(DEBUG, "CatalogCacheIdInvalidate: called");
|
CACHE1_elog(DEBUG, "CatalogCacheIdInvalidate: called");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* inspect caches to find the proper cache
|
* inspect caches to find the proper cache
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
for (ccp = Caches; ccp; ccp = ccp->cc_next)
|
for (ccp = CacheHdr->ch_caches; ccp; ccp = ccp->cc_next)
|
||||||
{
|
{
|
||||||
Dlelem *elt,
|
Dlelem *elt,
|
||||||
*nextelt;
|
*nextelt;
|
||||||
@ -451,11 +448,12 @@ CatalogCacheIdInvalidate(int cacheId,
|
|||||||
if (cacheId != ccp->id)
|
if (cacheId != ccp->id)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
Assert(hashIndex < ccp->cc_size);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* inspect the hash bucket until we find a match or exhaust
|
* inspect the hash bucket until we find a match or exhaust
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
for (elt = DLGetHead(&ccp->cc_cache[hashIndex]); elt; elt = nextelt)
|
for (elt = DLGetHead(&ccp->cc_bucket[hashIndex]); elt; elt = nextelt)
|
||||||
{
|
{
|
||||||
CatCTup *ct = (CatCTup *) DLE_VAL(elt);
|
CatCTup *ct = (CatCTup *) DLE_VAL(elt);
|
||||||
|
|
||||||
@ -479,7 +477,7 @@ CatalogCacheIdInvalidate(int cacheId,
|
|||||||
* public functions
|
* public functions
|
||||||
*
|
*
|
||||||
* AtEOXact_CatCache
|
* AtEOXact_CatCache
|
||||||
* ResetSystemCache
|
* ResetCatalogCaches
|
||||||
* InitCatCache
|
* InitCatCache
|
||||||
* SearchCatCache
|
* SearchCatCache
|
||||||
* ReleaseCatCache
|
* ReleaseCatCache
|
||||||
@ -497,19 +495,14 @@ CatalogCacheIdInvalidate(int cacheId,
|
|||||||
* necessary in the abort case, since elog() may have interrupted routines.
|
* necessary in the abort case, since elog() may have interrupted routines.
|
||||||
* In the commit case, any nonzero counts indicate failure to call
|
* In the commit case, any nonzero counts indicate failure to call
|
||||||
* ReleaseSysCache, so we put out a notice for debugging purposes.
|
* ReleaseSysCache, so we put out a notice for debugging purposes.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
AtEOXact_CatCache(bool isCommit)
|
AtEOXact_CatCache(bool isCommit)
|
||||||
{
|
{
|
||||||
CatCache *cache;
|
|
||||||
|
|
||||||
for (cache = Caches; cache; cache = cache->cc_next)
|
|
||||||
{
|
|
||||||
Dlelem *elt,
|
Dlelem *elt,
|
||||||
*nextelt;
|
*nextelt;
|
||||||
|
|
||||||
for (elt = DLGetHead(&cache->cc_lrulist); elt; elt = nextelt)
|
for (elt = DLGetHead(&CacheHdr->ch_lrulist); elt; elt = nextelt)
|
||||||
{
|
{
|
||||||
CatCTup *ct = (CatCTup *) DLE_VAL(elt);
|
CatCTup *ct = (CatCTup *) DLE_VAL(elt);
|
||||||
|
|
||||||
@ -519,7 +512,7 @@ AtEOXact_CatCache(bool isCommit)
|
|||||||
{
|
{
|
||||||
if (isCommit)
|
if (isCommit)
|
||||||
elog(NOTICE, "Cache reference leak: cache %s (%d), tuple %u has count %d",
|
elog(NOTICE, "Cache reference leak: cache %s (%d), tuple %u has count %d",
|
||||||
cache->cc_relname, cache->id,
|
ct->my_cache->cc_relname, ct->my_cache->id,
|
||||||
ct->tuple.t_data->t_oid,
|
ct->tuple.t_data->t_oid,
|
||||||
ct->refcount);
|
ct->refcount);
|
||||||
ct->refcount = 0;
|
ct->refcount = 0;
|
||||||
@ -527,38 +520,30 @@ AtEOXact_CatCache(bool isCommit)
|
|||||||
|
|
||||||
/* Clean up any now-deletable dead entries */
|
/* Clean up any now-deletable dead entries */
|
||||||
if (ct->dead)
|
if (ct->dead)
|
||||||
CatCacheRemoveCTup(cache, ct);
|
CatCacheRemoveCTup(ct->my_cache, ct);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ResetSystemCache
|
* ResetCatalogCache
|
||||||
*
|
*
|
||||||
* Reset caches when a shared cache inval event forces it
|
* Reset one catalog cache to empty.
|
||||||
*
|
*
|
||||||
|
* This is not very efficient if the target cache is nearly empty.
|
||||||
|
* However, it shouldn't need to be efficient; we don't invoke it often.
|
||||||
*/
|
*/
|
||||||
void
|
static void
|
||||||
ResetSystemCache(void)
|
ResetCatalogCache(CatCache *cache)
|
||||||
{
|
{
|
||||||
CatCache *cache;
|
int i;
|
||||||
|
|
||||||
CACHE1_elog(DEBUG, "ResetSystemCache called");
|
/* Remove each tuple in this cache, or at least mark it dead */
|
||||||
|
for (i = 0; i < cache->cc_size; i++)
|
||||||
/* ----------------
|
|
||||||
* here we purge the contents of all the caches
|
|
||||||
*
|
|
||||||
* for each system cache
|
|
||||||
* for each tuple
|
|
||||||
* remove the tuple, or at least mark it dead
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
for (cache = Caches; cache; cache = cache->cc_next)
|
|
||||||
{
|
{
|
||||||
Dlelem *elt,
|
Dlelem *elt,
|
||||||
*nextelt;
|
*nextelt;
|
||||||
|
|
||||||
for (elt = DLGetHead(&cache->cc_lrulist); elt; elt = nextelt)
|
for (elt = DLGetHead(&cache->cc_bucket[i]); elt; elt = nextelt)
|
||||||
{
|
{
|
||||||
CatCTup *ct = (CatCTup *) DLE_VAL(elt);
|
CatCTup *ct = (CatCTup *) DLE_VAL(elt);
|
||||||
|
|
||||||
@ -570,12 +555,28 @@ ResetSystemCache(void)
|
|||||||
CatCacheRemoveCTup(cache, ct);
|
CatCacheRemoveCTup(cache, ct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CACHE1_elog(DEBUG, "end of ResetSystemCache call");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SystemCacheRelationFlushed
|
* ResetCatalogCaches
|
||||||
|
*
|
||||||
|
* Reset all caches when a shared cache inval event forces it
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ResetCatalogCaches(void)
|
||||||
|
{
|
||||||
|
CatCache *cache;
|
||||||
|
|
||||||
|
CACHE1_elog(DEBUG, "ResetCatalogCaches called");
|
||||||
|
|
||||||
|
for (cache = CacheHdr->ch_caches; cache; cache = cache->cc_next)
|
||||||
|
ResetCatalogCache(cache);
|
||||||
|
|
||||||
|
CACHE1_elog(DEBUG, "end of ResetCatalogCaches call");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CatalogCacheFlushRelation
|
||||||
*
|
*
|
||||||
* This is called by RelationFlushRelation() to clear out cached information
|
* This is called by RelationFlushRelation() to clear out cached information
|
||||||
* about a relation being dropped. (This could be a DROP TABLE command,
|
* about a relation being dropped. (This could be a DROP TABLE command,
|
||||||
@ -586,26 +587,80 @@ ResetSystemCache(void)
|
|||||||
* A special case occurs when relId is itself one of the cacheable system
|
* A special case occurs when relId is itself one of the cacheable system
|
||||||
* tables --- although those'll never be dropped, they can get flushed from
|
* tables --- although those'll never be dropped, they can get flushed from
|
||||||
* the relcache (VACUUM causes this, for example). In that case we need
|
* the relcache (VACUUM causes this, for example). In that case we need
|
||||||
* to flush all cache entries from that table. The brute-force method
|
* to flush all cache entries that came from that table. (At one point we
|
||||||
* currently used takes care of that quite handily. (At one point we
|
|
||||||
* also tried to force re-execution of CatalogCacheInitializeCache for
|
* also tried to force re-execution of CatalogCacheInitializeCache for
|
||||||
* the cache(s) on that table. This is a bad idea since it leads to all
|
* the cache(s) on that table. This is a bad idea since it leads to all
|
||||||
* kinds of trouble if a cache flush occurs while loading cache entries.
|
* kinds of trouble if a cache flush occurs while loading cache entries.
|
||||||
* We now avoid the need to do it by copying cc_tupdesc out of the relcache,
|
* We now avoid the need to do it by copying cc_tupdesc out of the relcache,
|
||||||
* rather than relying on the relcache to keep a tupdesc for us. Of course
|
* rather than relying on the relcache to keep a tupdesc for us. Of course
|
||||||
* this assumes the tupdesc of a cachable system table will not change...)
|
* this assumes the tupdesc of a cachable system table will not change...)
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
SystemCacheRelationFlushed(Oid relId)
|
CatalogCacheFlushRelation(Oid relId)
|
||||||
{
|
{
|
||||||
|
CatCache *cache;
|
||||||
|
|
||||||
/*
|
CACHE2_elog(DEBUG, "CatalogCacheFlushRelation called for %u", relId);
|
||||||
* XXX Ideally we'd search the caches and just zap entries that
|
|
||||||
* actually refer to or come from the indicated relation. For now, we
|
for (cache = CacheHdr->ch_caches; cache; cache = cache->cc_next)
|
||||||
* take the brute-force approach: just flush the caches entirely.
|
{
|
||||||
*/
|
int i;
|
||||||
ResetSystemCache();
|
|
||||||
|
/* We can ignore uninitialized caches, since they must be empty */
|
||||||
|
if (cache->cc_tupdesc == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Does this cache store tuples of the target relation itself? */
|
||||||
|
if (cache->cc_tupdesc->attrs[0]->attrelid == relId)
|
||||||
|
{
|
||||||
|
/* Yes, so flush all its contents */
|
||||||
|
ResetCatalogCache(cache);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Does this cache store tuples associated with relations at all? */
|
||||||
|
if (cache->cc_reloidattr == 0)
|
||||||
|
continue; /* nope, leave it alone */
|
||||||
|
|
||||||
|
/* Yes, scan the tuples and remove those related to relId */
|
||||||
|
for (i = 0; i < cache->cc_size; i++)
|
||||||
|
{
|
||||||
|
Dlelem *elt,
|
||||||
|
*nextelt;
|
||||||
|
|
||||||
|
for (elt = DLGetHead(&cache->cc_bucket[i]); elt; elt = nextelt)
|
||||||
|
{
|
||||||
|
CatCTup *ct = (CatCTup *) DLE_VAL(elt);
|
||||||
|
Oid tupRelid;
|
||||||
|
|
||||||
|
nextelt = DLGetSucc(elt);
|
||||||
|
|
||||||
|
if (cache->cc_reloidattr == ObjectIdAttributeNumber)
|
||||||
|
tupRelid = ct->tuple.t_data->t_oid;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool isNull;
|
||||||
|
|
||||||
|
tupRelid = DatumGetObjectId(
|
||||||
|
fastgetattr(&ct->tuple,
|
||||||
|
cache->cc_reloidattr,
|
||||||
|
cache->cc_tupdesc,
|
||||||
|
&isNull));
|
||||||
|
Assert(!isNull);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tupRelid == relId)
|
||||||
|
{
|
||||||
|
if (ct->refcount > 0)
|
||||||
|
ct->dead = true;
|
||||||
|
else
|
||||||
|
CatCacheRemoveCTup(cache, ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CACHE1_elog(DEBUG, "end of CatalogCacheFlushRelation call");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -615,7 +670,6 @@ SystemCacheRelationFlushed(Oid relId)
|
|||||||
* Actually, the cache is only partially initialized to avoid opening the
|
* Actually, the cache is only partially initialized to avoid opening the
|
||||||
* relation. The relation will be opened and the rest of the cache
|
* relation. The relation will be opened and the rest of the cache
|
||||||
* structure initialized on the first access.
|
* structure initialized on the first access.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
#ifdef CACHEDEBUG
|
#ifdef CACHEDEBUG
|
||||||
#define InitCatCache_DEBUG1 \
|
#define InitCatCache_DEBUG1 \
|
||||||
@ -632,6 +686,7 @@ CatCache *
|
|||||||
InitCatCache(int id,
|
InitCatCache(int id,
|
||||||
char *relname,
|
char *relname,
|
||||||
char *indname,
|
char *indname,
|
||||||
|
int reloidattr,
|
||||||
int nkeys,
|
int nkeys,
|
||||||
int *key)
|
int *key)
|
||||||
{
|
{
|
||||||
@ -642,63 +697,67 @@ InitCatCache(int id,
|
|||||||
/*
|
/*
|
||||||
* first switch to the cache context so our allocations do not vanish
|
* first switch to the cache context so our allocations do not vanish
|
||||||
* at the end of a transaction
|
* at the end of a transaction
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
if (!CacheMemoryContext)
|
if (!CacheMemoryContext)
|
||||||
CreateCacheMemoryContext();
|
CreateCacheMemoryContext();
|
||||||
|
|
||||||
oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
|
oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if first time through, initialize the cache group header,
|
||||||
|
* including global LRU list header
|
||||||
|
*/
|
||||||
|
if (CacheHdr == NULL)
|
||||||
|
{
|
||||||
|
CacheHdr = (CatCacheHeader *) palloc(sizeof(CatCacheHeader));
|
||||||
|
CacheHdr->ch_caches = NULL;
|
||||||
|
CacheHdr->ch_ntup = 0;
|
||||||
|
CacheHdr->ch_maxtup = MAXCCTUPLES;
|
||||||
|
DLInitList(&CacheHdr->ch_lrulist);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* allocate a new cache structure
|
* allocate a new cache structure
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
cp = (CatCache *) palloc(sizeof(CatCache));
|
cp = (CatCache *) palloc(sizeof(CatCache) + NCCBUCKETS * sizeof(Dllist));
|
||||||
MemSet((char *) cp, 0, sizeof(CatCache));
|
MemSet((char *) cp, 0, sizeof(CatCache) + NCCBUCKETS * sizeof(Dllist));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* initialize the cache buckets (each bucket is a list header) and the
|
* initialize the cache buckets (each bucket is a list header)
|
||||||
* LRU tuple list
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
DLInitList(&cp->cc_lrulist);
|
for (i = 0; i < NCCBUCKETS; ++i)
|
||||||
for (i = 0; i < NCCBUCK; ++i)
|
DLInitList(&cp->cc_bucket[i]);
|
||||||
DLInitList(&cp->cc_cache[i]);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Caches is the pointer to the head of the list of all the system
|
|
||||||
* caches. here we add the new cache to the top of the list.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
cp->cc_next = Caches; /* list of caches (single link) */
|
|
||||||
Caches = cp;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* initialize the cache's relation information for the relation
|
* initialize the cache's relation information for the relation
|
||||||
* corresponding to this cache, and initialize some of the new cache's
|
* corresponding to this cache, and initialize some of the new cache's
|
||||||
* other internal fields. But don't open the relation yet.
|
* other internal fields. But don't open the relation yet.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
cp->id = id;
|
||||||
cp->cc_relname = relname;
|
cp->cc_relname = relname;
|
||||||
cp->cc_indname = indname;
|
cp->cc_indname = indname;
|
||||||
|
cp->cc_reloidattr = reloidattr;
|
||||||
cp->cc_tupdesc = (TupleDesc) NULL;
|
cp->cc_tupdesc = (TupleDesc) NULL;
|
||||||
cp->id = id;
|
cp->cc_ntup = 0;
|
||||||
cp->cc_maxtup = MAXTUP;
|
cp->cc_size = NCCBUCKETS;
|
||||||
cp->cc_size = NCCBUCK;
|
|
||||||
cp->cc_nkeys = nkeys;
|
cp->cc_nkeys = nkeys;
|
||||||
for (i = 0; i < nkeys; ++i)
|
for (i = 0; i < nkeys; ++i)
|
||||||
cp->cc_key[i] = key[i];
|
cp->cc_key[i] = key[i];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* all done. new cache is initialized. print some debugging
|
* new cache is initialized as far as we can go for now.
|
||||||
* information, if appropriate.
|
* print some debugging information, if appropriate.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
InitCatCache_DEBUG1;
|
InitCatCache_DEBUG1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* add completed cache to top of group header's list
|
||||||
|
*/
|
||||||
|
cp->cc_next = CacheHdr->ch_caches;
|
||||||
|
CacheHdr->ch_caches = cp;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* back to the old context before we return...
|
* back to the old context before we return...
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
MemoryContextSwitchTo(oldcxt);
|
MemoryContextSwitchTo(oldcxt);
|
||||||
|
|
||||||
@ -766,7 +825,6 @@ IndexScanOK(CatCache *cache, ScanKey cur_skey)
|
|||||||
*
|
*
|
||||||
* This call searches a system cache for a tuple, opening the relation
|
* This call searches a system cache for a tuple, opening the relation
|
||||||
* if necessary (the first access to a particular cache).
|
* if necessary (the first access to a particular cache).
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
HeapTuple
|
HeapTuple
|
||||||
SearchCatCache(CatCache *cache,
|
SearchCatCache(CatCache *cache,
|
||||||
@ -785,14 +843,12 @@ SearchCatCache(CatCache *cache,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* one-time startup overhead
|
* one-time startup overhead
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
if (cache->cc_tupdesc == NULL)
|
if (cache->cc_tupdesc == NULL)
|
||||||
CatalogCacheInitializeCache(cache);
|
CatalogCacheInitializeCache(cache);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* initialize the search key information
|
* initialize the search key information
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
memcpy(cur_skey, cache->cc_skey, sizeof(cur_skey));
|
memcpy(cur_skey, cache->cc_skey, sizeof(cur_skey));
|
||||||
cur_skey[0].sk_argument = v1;
|
cur_skey[0].sk_argument = v1;
|
||||||
@ -802,15 +858,13 @@ SearchCatCache(CatCache *cache,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* find the hash bucket in which to look for the tuple
|
* find the hash bucket in which to look for the tuple
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
hash = CatalogCacheComputeHashIndex(cache, cur_skey);
|
hash = CatalogCacheComputeHashIndex(cache, cur_skey);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* scan the hash bucket until we find a match or exhaust our tuples
|
* scan the hash bucket until we find a match or exhaust our tuples
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
for (elt = DLGetHead(&cache->cc_cache[hash]);
|
for (elt = DLGetHead(&cache->cc_bucket[hash]);
|
||||||
elt;
|
elt;
|
||||||
elt = DLGetSucc(elt))
|
elt = DLGetSucc(elt))
|
||||||
{
|
{
|
||||||
@ -824,7 +878,6 @@ SearchCatCache(CatCache *cache,
|
|||||||
/*
|
/*
|
||||||
* see if the cached tuple matches our key. (should we be worried
|
* see if the cached tuple matches our key. (should we be worried
|
||||||
* about time ranges? -cim 10/2/90)
|
* about time ranges? -cim 10/2/90)
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
HeapKeyTest(&ct->tuple,
|
HeapKeyTest(&ct->tuple,
|
||||||
cache->cc_tupdesc,
|
cache->cc_tupdesc,
|
||||||
@ -841,7 +894,6 @@ SearchCatCache(CatCache *cache,
|
|||||||
* subsequent searches. (The most frequently accessed elements in
|
* subsequent searches. (The most frequently accessed elements in
|
||||||
* any hashbucket will tend to be near the front of the
|
* any hashbucket will tend to be near the front of the
|
||||||
* hashbucket's list.)
|
* hashbucket's list.)
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
ct->refcount++;
|
ct->refcount++;
|
||||||
|
|
||||||
@ -869,19 +921,16 @@ SearchCatCache(CatCache *cache,
|
|||||||
* will never be referenced again, and will eventually age out of the
|
* will never be referenced again, and will eventually age out of the
|
||||||
* cache, so there's no functional problem. This case is rare enough
|
* cache, so there's no functional problem. This case is rare enough
|
||||||
* that it's not worth expending extra cycles to detect.
|
* that it's not worth expending extra cycles to detect.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* open the relation associated with the cache
|
* open the relation associated with the cache
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
relation = heap_openr(cache->cc_relname, AccessShareLock);
|
relation = heap_openr(cache->cc_relname, AccessShareLock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Scan the relation to find the tuple. If there's an index, and if
|
* Scan the relation to find the tuple. If there's an index, and if
|
||||||
* it's safe to do so, use the index. Else do a heap scan.
|
* it's safe to do so, use the index. Else do a heap scan.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
ct = NULL;
|
ct = NULL;
|
||||||
|
|
||||||
@ -958,13 +1007,11 @@ SearchCatCache(CatCache *cache,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* close the relation
|
* close the relation
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
heap_close(relation, AccessShareLock);
|
heap_close(relation, AccessShareLock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* scan is complete. if tup was found, we can add it to the cache.
|
* scan is complete. if tup was found, we can add it to the cache.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
if (ct == NULL)
|
if (ct == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -972,27 +1019,27 @@ SearchCatCache(CatCache *cache,
|
|||||||
/*
|
/*
|
||||||
* Finish initializing the CatCTup header, and add it to the linked
|
* Finish initializing the CatCTup header, and add it to the linked
|
||||||
* lists.
|
* lists.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
CACHE1_elog(DEBUG, "SearchCatCache: found tuple");
|
CACHE1_elog(DEBUG, "SearchCatCache: found tuple");
|
||||||
|
|
||||||
ct->ct_magic = CT_MAGIC;
|
ct->ct_magic = CT_MAGIC;
|
||||||
|
ct->my_cache = cache;
|
||||||
DLInitElem(&ct->lrulist_elem, (void *) ct);
|
DLInitElem(&ct->lrulist_elem, (void *) ct);
|
||||||
DLInitElem(&ct->cache_elem, (void *) ct);
|
DLInitElem(&ct->cache_elem, (void *) ct);
|
||||||
ct->refcount = 1; /* count this first reference */
|
ct->refcount = 1; /* count this first reference */
|
||||||
ct->dead = false;
|
ct->dead = false;
|
||||||
|
|
||||||
DLAddHead(&cache->cc_lrulist, &ct->lrulist_elem);
|
DLAddHead(&CacheHdr->ch_lrulist, &ct->lrulist_elem);
|
||||||
DLAddHead(&cache->cc_cache[hash], &ct->cache_elem);
|
DLAddHead(&cache->cc_bucket[hash], &ct->cache_elem);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we've exceeded the desired size of this cache, try to throw away
|
* If we've exceeded the desired size of the caches, try to throw away
|
||||||
* the least recently used entry.
|
* the least recently used entry.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
if (++cache->cc_ntup > cache->cc_maxtup)
|
++cache->cc_ntup;
|
||||||
|
if (++CacheHdr->ch_ntup > CacheHdr->ch_maxtup)
|
||||||
{
|
{
|
||||||
for (elt = DLGetTail(&cache->cc_lrulist);
|
for (elt = DLGetTail(&CacheHdr->ch_lrulist);
|
||||||
elt;
|
elt;
|
||||||
elt = DLGetPred(elt))
|
elt = DLGetPred(elt))
|
||||||
{
|
{
|
||||||
@ -1002,14 +1049,14 @@ SearchCatCache(CatCache *cache,
|
|||||||
{
|
{
|
||||||
CACHE2_elog(DEBUG, "SearchCatCache(%s): Overflow, LRU removal",
|
CACHE2_elog(DEBUG, "SearchCatCache(%s): Overflow, LRU removal",
|
||||||
cache->cc_relname);
|
cache->cc_relname);
|
||||||
CatCacheRemoveCTup(cache, oldct);
|
CatCacheRemoveCTup(oldct->my_cache, oldct);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CACHE4_elog(DEBUG, "SearchCatCache(%s): Contains %d/%d tuples",
|
CACHE4_elog(DEBUG, "SearchCatCache(%s): Contains %d/%d tuples",
|
||||||
cache->cc_relname, cache->cc_ntup, cache->cc_maxtup);
|
cache->cc_relname, cache->cc_ntup, CacheHdr->ch_ntup);
|
||||||
CACHE3_elog(DEBUG, "SearchCatCache(%s): put in bucket %d",
|
CACHE3_elog(DEBUG, "SearchCatCache(%s): put in bucket %d",
|
||||||
cache->cc_relname, hash);
|
cache->cc_relname, hash);
|
||||||
|
|
||||||
@ -1026,7 +1073,6 @@ SearchCatCache(CatCache *cache,
|
|||||||
* will be freed as soon as their refcount goes to zero. In combination
|
* will be freed as soon as their refcount goes to zero. In combination
|
||||||
* with aset.c's CLOBBER_FREED_MEMORY option, this provides a good test
|
* with aset.c's CLOBBER_FREED_MEMORY option, this provides a good test
|
||||||
* to catch references to already-released catcache entries.
|
* to catch references to already-released catcache entries.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ReleaseCatCache(HeapTuple tuple)
|
ReleaseCatCache(HeapTuple tuple)
|
||||||
@ -1046,12 +1092,7 @@ ReleaseCatCache(HeapTuple tuple)
|
|||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
/* We can find the associated cache using the dllist pointers */
|
CatCacheRemoveCTup(ct->my_cache, ct);
|
||||||
Dllist *lru = DLGetListHdr(&ct->lrulist_elem);
|
|
||||||
CatCache *cache = (CatCache *) (((char *) lru) -
|
|
||||||
offsetof(CatCache, cc_lrulist));
|
|
||||||
|
|
||||||
CatCacheRemoveCTup(cache, ct);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1061,7 +1102,7 @@ ReleaseCatCache(HeapTuple tuple)
|
|||||||
* This is part of a rather subtle chain of events, so pay attention:
|
* This is part of a rather subtle chain of events, so pay attention:
|
||||||
*
|
*
|
||||||
* When a tuple is updated or deleted, it cannot be flushed from the
|
* When a tuple is updated or deleted, it cannot be flushed from the
|
||||||
* catcaches immediately, for reasons explained at the top of inval.c.
|
* catcaches immediately, for reasons explained at the top of cache/inval.c.
|
||||||
* Instead we have to add entry(s) for the tuple to a list of pending tuple
|
* Instead we have to add entry(s) for the tuple to a list of pending tuple
|
||||||
* invalidations that will be done at the end of the command or transaction.
|
* invalidations that will be done at the end of the command or transaction.
|
||||||
*
|
*
|
||||||
@ -1081,7 +1122,6 @@ ReleaseCatCache(HeapTuple tuple)
|
|||||||
* specified relation. inval.c doesn't know exactly which rels have
|
* specified relation. inval.c doesn't know exactly which rels have
|
||||||
* catcaches --- it will call this routine for any tuple that's in a
|
* catcaches --- it will call this routine for any tuple that's in a
|
||||||
* system relation.
|
* system relation.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
PrepareToInvalidateCacheTuple(Relation relation,
|
PrepareToInvalidateCacheTuple(Relation relation,
|
||||||
@ -1090,14 +1130,15 @@ PrepareToInvalidateCacheTuple(Relation relation,
|
|||||||
{
|
{
|
||||||
CatCache *ccp;
|
CatCache *ccp;
|
||||||
|
|
||||||
|
CACHE1_elog(DEBUG, "PrepareToInvalidateCacheTuple: called");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* sanity checks
|
* sanity checks
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
Assert(RelationIsValid(relation));
|
Assert(RelationIsValid(relation));
|
||||||
Assert(HeapTupleIsValid(tuple));
|
Assert(HeapTupleIsValid(tuple));
|
||||||
Assert(PointerIsValid(function));
|
Assert(PointerIsValid(function));
|
||||||
CACHE1_elog(DEBUG, "PrepareToInvalidateCacheTuple: called");
|
Assert(CacheHdr != NULL);
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* for each cache
|
* for each cache
|
||||||
@ -1107,7 +1148,7 @@ PrepareToInvalidateCacheTuple(Relation relation,
|
|||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (ccp = Caches; ccp; ccp = ccp->cc_next)
|
for (ccp = CacheHdr->ch_caches; ccp; ccp = ccp->cc_next)
|
||||||
{
|
{
|
||||||
if (strcmp(ccp->cc_relname, RelationGetRelationName(relation)) != 0)
|
if (strcmp(ccp->cc_relname, RelationGetRelationName(relation)) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
14
src/backend/utils/cache/inval.c
vendored
14
src/backend/utils/cache/inval.c
vendored
@ -34,7 +34,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/inval.c,v 1.43 2001/06/01 20:23:06 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/cache/inval.c,v 1.44 2001/06/18 03:35:07 tgl Exp $
|
||||||
*
|
*
|
||||||
* Note - this code is real crufty... badly needs a rewrite to improve
|
* Note - this code is real crufty... badly needs a rewrite to improve
|
||||||
* readability and portability. (Shouldn't assume Oid == Index, for example)
|
* readability and portability. (Shouldn't assume Oid == Index, for example)
|
||||||
@ -478,16 +478,20 @@ CacheIdInvalidate(Index cacheId,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ResetSystemCaches
|
* InvalidateSystemCaches
|
||||||
*
|
*
|
||||||
* This blows away all tuples in the system catalog caches and
|
* This blows away all tuples in the system catalog caches and
|
||||||
* all the cached relation descriptors (and closes their files too).
|
* all the cached relation descriptors (and closes their files too).
|
||||||
* Relation descriptors that have positive refcounts are then rebuilt.
|
* Relation descriptors that have positive refcounts are then rebuilt.
|
||||||
|
*
|
||||||
|
* We call this when we see a shared-inval-queue overflow signal,
|
||||||
|
* since that tells us we've lost some shared-inval messages and hence
|
||||||
|
* don't know what needs to be invalidated.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
ResetSystemCaches(void)
|
InvalidateSystemCaches(void)
|
||||||
{
|
{
|
||||||
ResetSystemCache();
|
ResetCatalogCaches();
|
||||||
RelationCacheInvalidate();
|
RelationCacheInvalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -643,7 +647,7 @@ DiscardInvalid(void)
|
|||||||
elog(DEBUG, "DiscardInvalid called");
|
elog(DEBUG, "DiscardInvalid called");
|
||||||
#endif /* defined(INVALIDDEBUG) */
|
#endif /* defined(INVALIDDEBUG) */
|
||||||
|
|
||||||
InvalidateSharedInvalid(CacheIdInvalidate, ResetSystemCaches);
|
InvalidateSharedInvalid(CacheIdInvalidate, InvalidateSystemCaches);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
4
src/backend/utils/cache/relcache.c
vendored
4
src/backend/utils/cache/relcache.c
vendored
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.137 2001/06/12 05:55:49 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.138 2001/06/18 03:35:07 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1657,7 +1657,7 @@ RelationClearRelation(Relation relation, bool rebuildIt)
|
|||||||
MemoryContextSwitchTo(oldcxt);
|
MemoryContextSwitchTo(oldcxt);
|
||||||
|
|
||||||
/* Clear out catcache's entries for this relation */
|
/* Clear out catcache's entries for this relation */
|
||||||
SystemCacheRelationFlushed(RelationGetRelid(relation));
|
CatalogCacheFlushRelation(RelationGetRelid(relation));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Free all the subsidiary data structures of the relcache entry. We
|
* Free all the subsidiary data structures of the relcache entry. We
|
||||||
|
41
src/backend/utils/cache/syscache.c
vendored
41
src/backend/utils/cache/syscache.c
vendored
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.62 2001/06/12 05:55:49 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.63 2001/06/18 03:35:07 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* These routines allow the parser/planner/executor to perform
|
* These routines allow the parser/planner/executor to perform
|
||||||
@ -54,7 +54,12 @@
|
|||||||
|
|
||||||
Add your entry to the cacheinfo[] array below. All cache lists are
|
Add your entry to the cacheinfo[] array below. All cache lists are
|
||||||
alphabetical, so add it in the proper place. Specify the relation
|
alphabetical, so add it in the proper place. Specify the relation
|
||||||
name, index name, number of keys, and key attribute numbers.
|
name, index name, number of keys, and key attribute numbers. If the
|
||||||
|
relation contains tuples that are associated with a particular relation
|
||||||
|
(for example, its attributes, rules, triggers, etc) then specify the
|
||||||
|
attribute number that contains the OID of the associated relation.
|
||||||
|
This is used by CatalogCacheFlushRelation() to remove the correct
|
||||||
|
tuples during a table drop or relcache invalidation event.
|
||||||
|
|
||||||
In include/catalog/indexing.h, add a define for the number of indexes
|
In include/catalog/indexing.h, add a define for the number of indexes
|
||||||
on the relation, add define(s) for the index name(s), add an extern
|
on the relation, add define(s) for the index name(s), add an extern
|
||||||
@ -76,12 +81,12 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* struct cachedesc: information defining a single syscache
|
* struct cachedesc: information defining a single syscache
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
struct cachedesc
|
struct cachedesc
|
||||||
{
|
{
|
||||||
char *name; /* name of the relation being cached */
|
char *name; /* name of the relation being cached */
|
||||||
char *indname; /* name of index relation for this cache */
|
char *indname; /* name of index relation for this cache */
|
||||||
|
int reloidattr; /* attr number of rel OID reference, or 0 */
|
||||||
int nkeys; /* # of keys needed for cache lookup */
|
int nkeys; /* # of keys needed for cache lookup */
|
||||||
int key[4]; /* attribute numbers of key attrs */
|
int key[4]; /* attribute numbers of key attrs */
|
||||||
};
|
};
|
||||||
@ -89,6 +94,7 @@ struct cachedesc
|
|||||||
static struct cachedesc cacheinfo[] = {
|
static struct cachedesc cacheinfo[] = {
|
||||||
{AggregateRelationName, /* AGGNAME */
|
{AggregateRelationName, /* AGGNAME */
|
||||||
AggregateNameTypeIndex,
|
AggregateNameTypeIndex,
|
||||||
|
0,
|
||||||
2,
|
2,
|
||||||
{
|
{
|
||||||
Anum_pg_aggregate_aggname,
|
Anum_pg_aggregate_aggname,
|
||||||
@ -98,6 +104,7 @@ static struct cachedesc cacheinfo[] = {
|
|||||||
}},
|
}},
|
||||||
{AccessMethodRelationName, /* AMNAME */
|
{AccessMethodRelationName, /* AMNAME */
|
||||||
AmNameIndex,
|
AmNameIndex,
|
||||||
|
0,
|
||||||
1,
|
1,
|
||||||
{
|
{
|
||||||
Anum_pg_am_amname,
|
Anum_pg_am_amname,
|
||||||
@ -107,6 +114,7 @@ static struct cachedesc cacheinfo[] = {
|
|||||||
}},
|
}},
|
||||||
{AccessMethodOperatorRelationName, /* AMOPOPID */
|
{AccessMethodOperatorRelationName, /* AMOPOPID */
|
||||||
AccessMethodOpidIndex,
|
AccessMethodOpidIndex,
|
||||||
|
0,
|
||||||
3,
|
3,
|
||||||
{
|
{
|
||||||
Anum_pg_amop_amopclaid,
|
Anum_pg_amop_amopclaid,
|
||||||
@ -116,6 +124,7 @@ static struct cachedesc cacheinfo[] = {
|
|||||||
}},
|
}},
|
||||||
{AccessMethodOperatorRelationName, /* AMOPSTRATEGY */
|
{AccessMethodOperatorRelationName, /* AMOPSTRATEGY */
|
||||||
AccessMethodStrategyIndex,
|
AccessMethodStrategyIndex,
|
||||||
|
0,
|
||||||
3,
|
3,
|
||||||
{
|
{
|
||||||
Anum_pg_amop_amopid,
|
Anum_pg_amop_amopid,
|
||||||
@ -125,6 +134,7 @@ static struct cachedesc cacheinfo[] = {
|
|||||||
}},
|
}},
|
||||||
{AttributeRelationName, /* ATTNAME */
|
{AttributeRelationName, /* ATTNAME */
|
||||||
AttributeRelidNameIndex,
|
AttributeRelidNameIndex,
|
||||||
|
Anum_pg_attribute_attrelid,
|
||||||
2,
|
2,
|
||||||
{
|
{
|
||||||
Anum_pg_attribute_attrelid,
|
Anum_pg_attribute_attrelid,
|
||||||
@ -134,6 +144,7 @@ static struct cachedesc cacheinfo[] = {
|
|||||||
}},
|
}},
|
||||||
{AttributeRelationName, /* ATTNUM */
|
{AttributeRelationName, /* ATTNUM */
|
||||||
AttributeRelidNumIndex,
|
AttributeRelidNumIndex,
|
||||||
|
Anum_pg_attribute_attrelid,
|
||||||
2,
|
2,
|
||||||
{
|
{
|
||||||
Anum_pg_attribute_attrelid,
|
Anum_pg_attribute_attrelid,
|
||||||
@ -143,6 +154,7 @@ static struct cachedesc cacheinfo[] = {
|
|||||||
}},
|
}},
|
||||||
{OperatorClassRelationName, /* CLADEFTYPE */
|
{OperatorClassRelationName, /* CLADEFTYPE */
|
||||||
OpclassDeftypeIndex,
|
OpclassDeftypeIndex,
|
||||||
|
0,
|
||||||
1,
|
1,
|
||||||
{
|
{
|
||||||
Anum_pg_opclass_opcdeftype,
|
Anum_pg_opclass_opcdeftype,
|
||||||
@ -152,6 +164,7 @@ static struct cachedesc cacheinfo[] = {
|
|||||||
}},
|
}},
|
||||||
{OperatorClassRelationName, /* CLANAME */
|
{OperatorClassRelationName, /* CLANAME */
|
||||||
OpclassNameIndex,
|
OpclassNameIndex,
|
||||||
|
0,
|
||||||
1,
|
1,
|
||||||
{
|
{
|
||||||
Anum_pg_opclass_opcname,
|
Anum_pg_opclass_opcname,
|
||||||
@ -161,6 +174,7 @@ static struct cachedesc cacheinfo[] = {
|
|||||||
}},
|
}},
|
||||||
{GroupRelationName, /* GRONAME */
|
{GroupRelationName, /* GRONAME */
|
||||||
GroupNameIndex,
|
GroupNameIndex,
|
||||||
|
0,
|
||||||
1,
|
1,
|
||||||
{
|
{
|
||||||
Anum_pg_group_groname,
|
Anum_pg_group_groname,
|
||||||
@ -170,6 +184,7 @@ static struct cachedesc cacheinfo[] = {
|
|||||||
}},
|
}},
|
||||||
{GroupRelationName, /* GROSYSID */
|
{GroupRelationName, /* GROSYSID */
|
||||||
GroupSysidIndex,
|
GroupSysidIndex,
|
||||||
|
0,
|
||||||
1,
|
1,
|
||||||
{
|
{
|
||||||
Anum_pg_group_grosysid,
|
Anum_pg_group_grosysid,
|
||||||
@ -179,6 +194,7 @@ static struct cachedesc cacheinfo[] = {
|
|||||||
}},
|
}},
|
||||||
{IndexRelationName, /* INDEXRELID */
|
{IndexRelationName, /* INDEXRELID */
|
||||||
IndexRelidIndex,
|
IndexRelidIndex,
|
||||||
|
Anum_pg_index_indrelid,
|
||||||
1,
|
1,
|
||||||
{
|
{
|
||||||
Anum_pg_index_indexrelid,
|
Anum_pg_index_indexrelid,
|
||||||
@ -188,6 +204,7 @@ static struct cachedesc cacheinfo[] = {
|
|||||||
}},
|
}},
|
||||||
{InheritsRelationName, /* INHRELID */
|
{InheritsRelationName, /* INHRELID */
|
||||||
InheritsRelidSeqnoIndex,
|
InheritsRelidSeqnoIndex,
|
||||||
|
Anum_pg_inherits_inhrelid,
|
||||||
2,
|
2,
|
||||||
{
|
{
|
||||||
Anum_pg_inherits_inhrelid,
|
Anum_pg_inherits_inhrelid,
|
||||||
@ -197,6 +214,7 @@ static struct cachedesc cacheinfo[] = {
|
|||||||
}},
|
}},
|
||||||
{LanguageRelationName, /* LANGNAME */
|
{LanguageRelationName, /* LANGNAME */
|
||||||
LanguageNameIndex,
|
LanguageNameIndex,
|
||||||
|
0,
|
||||||
1,
|
1,
|
||||||
{
|
{
|
||||||
Anum_pg_language_lanname,
|
Anum_pg_language_lanname,
|
||||||
@ -206,6 +224,7 @@ static struct cachedesc cacheinfo[] = {
|
|||||||
}},
|
}},
|
||||||
{LanguageRelationName, /* LANGOID */
|
{LanguageRelationName, /* LANGOID */
|
||||||
LanguageOidIndex,
|
LanguageOidIndex,
|
||||||
|
0,
|
||||||
1,
|
1,
|
||||||
{
|
{
|
||||||
ObjectIdAttributeNumber,
|
ObjectIdAttributeNumber,
|
||||||
@ -215,6 +234,7 @@ static struct cachedesc cacheinfo[] = {
|
|||||||
}},
|
}},
|
||||||
{OperatorRelationName, /* OPERNAME */
|
{OperatorRelationName, /* OPERNAME */
|
||||||
OperatorNameIndex,
|
OperatorNameIndex,
|
||||||
|
0,
|
||||||
4,
|
4,
|
||||||
{
|
{
|
||||||
Anum_pg_operator_oprname,
|
Anum_pg_operator_oprname,
|
||||||
@ -224,6 +244,7 @@ static struct cachedesc cacheinfo[] = {
|
|||||||
}},
|
}},
|
||||||
{OperatorRelationName, /* OPEROID */
|
{OperatorRelationName, /* OPEROID */
|
||||||
OperatorOidIndex,
|
OperatorOidIndex,
|
||||||
|
0,
|
||||||
1,
|
1,
|
||||||
{
|
{
|
||||||
ObjectIdAttributeNumber,
|
ObjectIdAttributeNumber,
|
||||||
@ -233,6 +254,7 @@ static struct cachedesc cacheinfo[] = {
|
|||||||
}},
|
}},
|
||||||
{ProcedureRelationName, /* PROCNAME */
|
{ProcedureRelationName, /* PROCNAME */
|
||||||
ProcedureNameIndex,
|
ProcedureNameIndex,
|
||||||
|
0,
|
||||||
3,
|
3,
|
||||||
{
|
{
|
||||||
Anum_pg_proc_proname,
|
Anum_pg_proc_proname,
|
||||||
@ -242,6 +264,7 @@ static struct cachedesc cacheinfo[] = {
|
|||||||
}},
|
}},
|
||||||
{ProcedureRelationName, /* PROCOID */
|
{ProcedureRelationName, /* PROCOID */
|
||||||
ProcedureOidIndex,
|
ProcedureOidIndex,
|
||||||
|
0,
|
||||||
1,
|
1,
|
||||||
{
|
{
|
||||||
ObjectIdAttributeNumber,
|
ObjectIdAttributeNumber,
|
||||||
@ -251,6 +274,7 @@ static struct cachedesc cacheinfo[] = {
|
|||||||
}},
|
}},
|
||||||
{RelationRelationName, /* RELNAME */
|
{RelationRelationName, /* RELNAME */
|
||||||
ClassNameIndex,
|
ClassNameIndex,
|
||||||
|
ObjectIdAttributeNumber,
|
||||||
1,
|
1,
|
||||||
{
|
{
|
||||||
Anum_pg_class_relname,
|
Anum_pg_class_relname,
|
||||||
@ -260,6 +284,7 @@ static struct cachedesc cacheinfo[] = {
|
|||||||
}},
|
}},
|
||||||
{RelationRelationName, /* RELOID */
|
{RelationRelationName, /* RELOID */
|
||||||
ClassOidIndex,
|
ClassOidIndex,
|
||||||
|
ObjectIdAttributeNumber,
|
||||||
1,
|
1,
|
||||||
{
|
{
|
||||||
ObjectIdAttributeNumber,
|
ObjectIdAttributeNumber,
|
||||||
@ -269,6 +294,7 @@ static struct cachedesc cacheinfo[] = {
|
|||||||
}},
|
}},
|
||||||
{RewriteRelationName, /* RULENAME */
|
{RewriteRelationName, /* RULENAME */
|
||||||
RewriteRulenameIndex,
|
RewriteRulenameIndex,
|
||||||
|
Anum_pg_rewrite_ev_class,
|
||||||
1,
|
1,
|
||||||
{
|
{
|
||||||
Anum_pg_rewrite_rulename,
|
Anum_pg_rewrite_rulename,
|
||||||
@ -278,6 +304,7 @@ static struct cachedesc cacheinfo[] = {
|
|||||||
}},
|
}},
|
||||||
{ShadowRelationName, /* SHADOWNAME */
|
{ShadowRelationName, /* SHADOWNAME */
|
||||||
ShadowNameIndex,
|
ShadowNameIndex,
|
||||||
|
0,
|
||||||
1,
|
1,
|
||||||
{
|
{
|
||||||
Anum_pg_shadow_usename,
|
Anum_pg_shadow_usename,
|
||||||
@ -287,6 +314,7 @@ static struct cachedesc cacheinfo[] = {
|
|||||||
}},
|
}},
|
||||||
{ShadowRelationName, /* SHADOWSYSID */
|
{ShadowRelationName, /* SHADOWSYSID */
|
||||||
ShadowSysidIndex,
|
ShadowSysidIndex,
|
||||||
|
0,
|
||||||
1,
|
1,
|
||||||
{
|
{
|
||||||
Anum_pg_shadow_usesysid,
|
Anum_pg_shadow_usesysid,
|
||||||
@ -296,6 +324,7 @@ static struct cachedesc cacheinfo[] = {
|
|||||||
}},
|
}},
|
||||||
{StatisticRelationName, /* STATRELATT */
|
{StatisticRelationName, /* STATRELATT */
|
||||||
StatisticRelidAttnumIndex,
|
StatisticRelidAttnumIndex,
|
||||||
|
Anum_pg_statistic_starelid,
|
||||||
2,
|
2,
|
||||||
{
|
{
|
||||||
Anum_pg_statistic_starelid,
|
Anum_pg_statistic_starelid,
|
||||||
@ -305,6 +334,7 @@ static struct cachedesc cacheinfo[] = {
|
|||||||
}},
|
}},
|
||||||
{TypeRelationName, /* TYPENAME */
|
{TypeRelationName, /* TYPENAME */
|
||||||
TypeNameIndex,
|
TypeNameIndex,
|
||||||
|
Anum_pg_type_typrelid,
|
||||||
1,
|
1,
|
||||||
{
|
{
|
||||||
Anum_pg_type_typname,
|
Anum_pg_type_typname,
|
||||||
@ -314,6 +344,7 @@ static struct cachedesc cacheinfo[] = {
|
|||||||
}},
|
}},
|
||||||
{TypeRelationName, /* TYPEOID */
|
{TypeRelationName, /* TYPEOID */
|
||||||
TypeOidIndex,
|
TypeOidIndex,
|
||||||
|
Anum_pg_type_typrelid,
|
||||||
1,
|
1,
|
||||||
{
|
{
|
||||||
ObjectIdAttributeNumber,
|
ObjectIdAttributeNumber,
|
||||||
@ -323,8 +354,7 @@ static struct cachedesc cacheinfo[] = {
|
|||||||
}}
|
}}
|
||||||
};
|
};
|
||||||
|
|
||||||
static CatCache *SysCache[
|
static CatCache *SysCache[lengthof(cacheinfo)];
|
||||||
lengthof(cacheinfo)];
|
|
||||||
static int SysCacheSize = lengthof(cacheinfo);
|
static int SysCacheSize = lengthof(cacheinfo);
|
||||||
static bool CacheInitialized = false;
|
static bool CacheInitialized = false;
|
||||||
|
|
||||||
@ -358,6 +388,7 @@ InitCatalogCache(void)
|
|||||||
SysCache[cacheId] = InitCatCache(cacheId,
|
SysCache[cacheId] = InitCatCache(cacheId,
|
||||||
cacheinfo[cacheId].name,
|
cacheinfo[cacheId].name,
|
||||||
cacheinfo[cacheId].indname,
|
cacheinfo[cacheId].indname,
|
||||||
|
cacheinfo[cacheId].reloidattr,
|
||||||
cacheinfo[cacheId].nkeys,
|
cacheinfo[cacheId].nkeys,
|
||||||
cacheinfo[cacheId].key);
|
cacheinfo[cacheId].key);
|
||||||
if (!PointerIsValid(SysCache[cacheId]))
|
if (!PointerIsValid(SysCache[cacheId]))
|
||||||
|
@ -13,32 +13,49 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: catcache.h,v 1.32 2001/03/22 04:01:11 momjian Exp $
|
* $Id: catcache.h,v 1.33 2001/06/18 03:35:07 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
#ifndef CATCACHE_H
|
#ifndef CATCACHE_H
|
||||||
#define CATCACHE_H
|
#define CATCACHE_H
|
||||||
|
|
||||||
/* #define CACHEDEBUG *//* turns DEBUG elogs on */
|
|
||||||
|
|
||||||
#include "access/htup.h"
|
#include "access/htup.h"
|
||||||
#include "lib/dllist.h"
|
#include "lib/dllist.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* struct catctup: individual tuple in the cache.
|
* struct catctup: individual tuple in the cache.
|
||||||
* struct catcache: information for managing a cache.
|
* struct catcache: information for managing a cache.
|
||||||
|
* struct catcacheheader: information for managing all the caches.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
typedef struct catcache
|
||||||
|
{
|
||||||
|
int id; /* cache identifier --- see syscache.h */
|
||||||
|
struct catcache *cc_next; /* link to next catcache */
|
||||||
|
char *cc_relname; /* name of relation the tuples come from */
|
||||||
|
char *cc_indname; /* name of index matching cache keys */
|
||||||
|
int cc_reloidattr; /* AttrNumber of relation OID, or 0 */
|
||||||
|
TupleDesc cc_tupdesc; /* tuple descriptor (copied from reldesc) */
|
||||||
|
int cc_ntup; /* # of tuples currently in this cache */
|
||||||
|
int cc_size; /* # of hash buckets in this cache */
|
||||||
|
int cc_nkeys; /* number of keys (1..4) */
|
||||||
|
int cc_key[4]; /* AttrNumber of each key */
|
||||||
|
PGFunction cc_hashfunc[4]; /* hash function to use for each key */
|
||||||
|
ScanKeyData cc_skey[4]; /* precomputed key info for heap scans */
|
||||||
|
Dllist cc_bucket[1]; /* hash buckets --- VARIABLE LENGTH ARRAY */
|
||||||
|
} CatCache; /* VARIABLE LENGTH STRUCT */
|
||||||
|
|
||||||
|
|
||||||
typedef struct catctup
|
typedef struct catctup
|
||||||
{
|
{
|
||||||
int ct_magic; /* for Assert checks */
|
int ct_magic; /* for Assert checks */
|
||||||
#define CT_MAGIC 0x57261502
|
#define CT_MAGIC 0x57261502
|
||||||
|
CatCache *my_cache; /* link to owning catcache */
|
||||||
/*
|
/*
|
||||||
* Each tuple in a cache is a member of two lists: one lists all the
|
* Each tuple in a cache is a member of two lists: one lists all the
|
||||||
* elements in that cache in LRU order, and the other lists just the
|
* elements in all the caches in LRU order, and the other lists just
|
||||||
* elements in one hashbucket, also in LRU order.
|
* the elements in one hashbucket of one cache, also in LRU order.
|
||||||
*
|
*
|
||||||
* A tuple marked "dead" must not be returned by subsequent searches.
|
* A tuple marked "dead" must not be returned by subsequent searches.
|
||||||
* However, it won't be physically deleted from the cache until its
|
* However, it won't be physically deleted from the cache until its
|
||||||
@ -52,30 +69,14 @@ typedef struct catctup
|
|||||||
} CatCTup;
|
} CatCTup;
|
||||||
|
|
||||||
|
|
||||||
/* voodoo constants */
|
typedef struct catcacheheader
|
||||||
#define NCCBUCK 500 /* CatCache buckets */
|
|
||||||
#define MAXTUP 500 /* Maximum # of tuples stored per cache */
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct catcache
|
|
||||||
{
|
{
|
||||||
int id; /* cache identifier --- see syscache.h */
|
CatCache *ch_caches; /* head of list of CatCache structs */
|
||||||
struct catcache *cc_next; /* link to next catcache */
|
int ch_ntup; /* # of tuples in all caches */
|
||||||
char *cc_relname; /* name of relation the tuples come from */
|
int ch_maxtup; /* max # of tuples allowed (LRU) */
|
||||||
char *cc_indname; /* name of index matching cache keys */
|
Dllist ch_lrulist; /* overall LRU list, most recent first */
|
||||||
TupleDesc cc_tupdesc; /* tuple descriptor (copied from reldesc) */
|
} CatCacheHeader;
|
||||||
short cc_ntup; /* # of tuples in this cache */
|
|
||||||
short cc_maxtup; /* max # of tuples allowed (LRU) */
|
|
||||||
short cc_size; /* # of hash buckets in this cache */
|
|
||||||
short cc_nkeys; /* number of keys (1..4) */
|
|
||||||
short cc_key[4]; /* AttrNumber of each key */
|
|
||||||
PGFunction cc_hashfunc[4]; /* hash function to use for each key */
|
|
||||||
ScanKeyData cc_skey[4]; /* precomputed key info for heap scans */
|
|
||||||
Dllist cc_lrulist; /* overall LRU list, most recent first */
|
|
||||||
Dllist cc_cache[NCCBUCK]; /* hash buckets */
|
|
||||||
} CatCache;
|
|
||||||
|
|
||||||
#define InvalidCatalogCacheId (-1)
|
|
||||||
|
|
||||||
/* this extern duplicates utils/memutils.h... */
|
/* this extern duplicates utils/memutils.h... */
|
||||||
extern MemoryContext CacheMemoryContext;
|
extern MemoryContext CacheMemoryContext;
|
||||||
@ -84,6 +85,7 @@ extern void CreateCacheMemoryContext(void);
|
|||||||
extern void AtEOXact_CatCache(bool isCommit);
|
extern void AtEOXact_CatCache(bool isCommit);
|
||||||
|
|
||||||
extern CatCache *InitCatCache(int id, char *relname, char *indname,
|
extern CatCache *InitCatCache(int id, char *relname, char *indname,
|
||||||
|
int reloidattr,
|
||||||
int nkeys, int *key);
|
int nkeys, int *key);
|
||||||
|
|
||||||
extern HeapTuple SearchCatCache(CatCache *cache,
|
extern HeapTuple SearchCatCache(CatCache *cache,
|
||||||
@ -91,8 +93,8 @@ extern HeapTuple SearchCatCache(CatCache *cache,
|
|||||||
Datum v3, Datum v4);
|
Datum v3, Datum v4);
|
||||||
extern void ReleaseCatCache(HeapTuple tuple);
|
extern void ReleaseCatCache(HeapTuple tuple);
|
||||||
|
|
||||||
extern void ResetSystemCache(void);
|
extern void ResetCatalogCaches(void);
|
||||||
extern void SystemCacheRelationFlushed(Oid relId);
|
extern void CatalogCacheFlushRelation(Oid relId);
|
||||||
extern void CatalogCacheIdInvalidate(int cacheId, Index hashIndex,
|
extern void CatalogCacheIdInvalidate(int cacheId, Index hashIndex,
|
||||||
ItemPointer pointer);
|
ItemPointer pointer);
|
||||||
extern void PrepareToInvalidateCacheTuple(Relation relation,
|
extern void PrepareToInvalidateCacheTuple(Relation relation,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user