diff options
Diffstat (limited to 'src/backend/utils/cache/catcache.c')
-rw-r--r-- | src/backend/utils/cache/catcache.c | 1786 |
1 files changed, 922 insertions, 864 deletions
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index aee835943e3..3edddd3c1aa 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -1,18 +1,18 @@ /*------------------------------------------------------------------------- * * catcache.c-- - * System catalog cache for tuples matching a key. + * System catalog cache for tuples matching a key. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.10 1997/08/26 19:24:36 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.11 1997/09/07 04:52:56 momjian Exp $ * * Notes: - * XXX This needs to use exception.h to handle recovery when - * an abort occurs during DisableCache. - * + * XXX This needs to use exception.h to handle recovery when + * an abort occurs during DisableCache. + * *------------------------------------------------------------------------- */ #include <string.h> @@ -26,7 +26,7 @@ #include "miscadmin.h" #include "utils/portal.h" #include "utils/catcache.h" -#include "fmgr.h" /* for F_BOOLEQ, etc. DANGER */ +#include "fmgr.h" /* for F_BOOLEQ, etc. DANGER */ #include "utils/elog.h" #include "utils/palloc.h" #include "utils/mcxt.h" @@ -34,29 +34,31 @@ #include "catalog/pg_type.h" /* for OID of int28 type */ #include "lib/dllist.h" -static void CatCacheRemoveCTup(CatCache *cache, Dlelem *e); -static Index CatalogCacheComputeHashIndex(struct catcache *cacheInP); -static Index CatalogCacheComputeTupleHashIndex(struct catcache *cacheInOutP, - Relation relation, HeapTuple tuple); -static void CatalogCacheInitializeCache(struct catcache *cache, - Relation relation); -static long comphash(long l, char *v); +static void CatCacheRemoveCTup(CatCache * cache, Dlelem * e); +static Index CatalogCacheComputeHashIndex(struct catcache * cacheInP); +static Index +CatalogCacheComputeTupleHashIndex(struct catcache * cacheInOutP, + Relation relation, HeapTuple tuple); +static void +CatalogCacheInitializeCache(struct catcache * cache, + Relation relation); +static long comphash(long l, char *v); /* ---------------- - * variables, macros and other stuff + * variables, macros and other stuff * - * note CCSIZE allocates 51 buckets .. one was already allocated in - * the catcache structure. + * note CCSIZE allocates 51 buckets .. one was already allocated in + * the catcache structure. * ---------------- */ #ifdef CACHEDEBUG -#define CACHE1_elog(a,b) elog(a,b) -#define CACHE2_elog(a,b,c) elog(a,b,c) -#define CACHE3_elog(a,b,c,d) elog(a,b,c,d) -#define CACHE4_elog(a,b,c,d,e) elog(a,b,c,d,e) -#define CACHE5_elog(a,b,c,d,e,f) elog(a,b,c,d,e,f) -#define CACHE6_elog(a,b,c,d,e,f,g) elog(a,b,c,d,e,f,g) +#define CACHE1_elog(a,b) elog(a,b) +#define CACHE2_elog(a,b,c) elog(a,b,c) +#define CACHE3_elog(a,b,c,d) elog(a,b,c,d) +#define CACHE4_elog(a,b,c,d,e) elog(a,b,c,d,e) +#define CACHE5_elog(a,b,c,d,e,f) elog(a,b,c,d,e,f) +#define CACHE6_elog(a,b,c,d,e,f,g) elog(a,b,c,d,e,f,g) #else #define CACHE1_elog(a,b) #define CACHE2_elog(a,b,c) @@ -66,209 +68,217 @@ static long comphash(long l, char *v); #define CACHE6_elog(a,b,c,d,e,f,g) #endif -CatCache *Caches = NULL; +CatCache *Caches = NULL; GlobalMemory CacheCxt; -static int DisableCache; +static int DisableCache; /* ---------------- - * EQPROC is used in CatalogCacheInitializeCache - * XXX this should be replaced by catalog lookups soon + * EQPROC is used in CatalogCacheInitializeCache + * XXX this should be replaced by catalog lookups soon * ---------------- */ -static long eqproc[] = { - F_BOOLEQ, 0l, F_CHAREQ, F_CHAR16EQ, 0l, - F_INT2EQ, F_KEYFIRSTEQ, F_INT4EQ, 0l, F_TEXTEQ, - F_OIDEQ, 0l, 0l, 0l, F_OID8EQ +static long eqproc[] = { + F_BOOLEQ, 0l, F_CHAREQ, F_CHAR16EQ, 0l, + F_INT2EQ, F_KEYFIRSTEQ, F_INT4EQ, 0l, F_TEXTEQ, + F_OIDEQ, 0l, 0l, 0l, F_OID8EQ }; -#define EQPROC(SYSTEMTYPEOID) eqproc[(SYSTEMTYPEOID)-16] +#define EQPROC(SYSTEMTYPEOID) eqproc[(SYSTEMTYPEOID)-16] /* ---------------------------------------------------------------- - * internal support functions + * internal support functions * ---------------------------------------------------------------- */ /* -------------------------------- - * CatalogCacheInitializeCache + * CatalogCacheInitializeCache * -------------------------------- */ #ifdef CACHEDEBUG #define CatalogCacheInitializeCache_DEBUG1 \ - elog(DEBUG, "CatalogCacheInitializeCache: cache @%08lx", cache); \ - if (relation) \ - elog(DEBUG, "CatalogCacheInitializeCache: called w/relation(inval)"); \ - else \ - elog(DEBUG, "CatalogCacheInitializeCache: called w/relname %s", \ - cache->cc_relname) + elog(DEBUG, "CatalogCacheInitializeCache: cache @%08lx", cache); \ + if (relation) \ + elog(DEBUG, "CatalogCacheInitializeCache: called w/relation(inval)"); \ + else \ + elog(DEBUG, "CatalogCacheInitializeCache: called w/relname %s", \ + cache->cc_relname) #define CatalogCacheInitializeCache_DEBUG2 \ - if (cache->cc_key[i] > 0) { \ - elog(DEBUG, "CatalogCacheInitializeCache: load %d/%d w/%d, %d", \ - i+1, cache->cc_nkeys, cache->cc_key[i], \ - relation->rd_att->attrs[cache->cc_key[i] - 1]->attlen); \ - } else { \ - elog(DEBUG, "CatalogCacheInitializeCache: load %d/%d w/%d", \ - i+1, cache->cc_nkeys, cache->cc_key[i]); \ - } + if (cache->cc_key[i] > 0) { \ + elog(DEBUG, "CatalogCacheInitializeCache: load %d/%d w/%d, %d", \ + i+1, cache->cc_nkeys, cache->cc_key[i], \ + relation->rd_att->attrs[cache->cc_key[i] - 1]->attlen); \ + } else { \ + elog(DEBUG, "CatalogCacheInitializeCache: load %d/%d w/%d", \ + i+1, cache->cc_nkeys, cache->cc_key[i]); \ + } #else #define CatalogCacheInitializeCache_DEBUG1 #define CatalogCacheInitializeCache_DEBUG2 #endif static void -CatalogCacheInitializeCache(struct catcache *cache, - Relation relation) +CatalogCacheInitializeCache(struct catcache * cache, + Relation relation) { - MemoryContext oldcxt; - short didopen = 0; - short i; - TupleDesc tupdesc; - - CatalogCacheInitializeCache_DEBUG1; - - /* ---------------- - * first switch to the cache context so our allocations - * do not vanish at the end of a transaction - * ---------------- - */ - if (!CacheCxt) - CacheCxt = CreateGlobalMemory("Cache"); - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - /* ---------------- - * If no relation was passed we must open it to get access to - * its fields. If one of the other caches has already opened - * it we use heap_open() instead of heap_openr() - * ---------------- - */ - if (! RelationIsValid(relation)) { - struct catcache *cp; + MemoryContext oldcxt; + short didopen = 0; + short i; + TupleDesc tupdesc; + + CatalogCacheInitializeCache_DEBUG1; + /* ---------------- - * scan the caches to see if any other cache has opened the relation + * first switch to the cache context so our allocations + * do not vanish at the end of a transaction * ---------------- */ - for (cp = Caches; cp; cp = cp->cc_next) { - if (strncmp(cp->cc_relname, cache->cc_relname, NAMEDATALEN) == 0) { - if (cp->relationId != InvalidOid) - break; - } + if (!CacheCxt) + CacheCxt = CreateGlobalMemory("Cache"); + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + /* ---------------- + * If no relation was passed we must open it to get access to + * its fields. If one of the other caches has already opened + * it we use heap_open() instead of heap_openr() + * ---------------- + */ + if (!RelationIsValid(relation)) + { + struct catcache *cp; + + /* ---------------- + * scan the caches to see if any other cache has opened the relation + * ---------------- + */ + for (cp = Caches; cp; cp = cp->cc_next) + { + if (strncmp(cp->cc_relname, cache->cc_relname, NAMEDATALEN) == 0) + { + if (cp->relationId != InvalidOid) + break; + } + } + + /* ---------------- + * open the relation by name or by id + * ---------------- + */ + if (cp) + relation = heap_open(cp->relationId); + else + { + relation = heap_openr(cache->cc_relname); + } + + didopen = 1; } - + /* ---------------- - * open the relation by name or by id + * initialize the cache's relation id * ---------------- */ - if (cp) - relation = heap_open(cp->relationId); - else - { - relation = heap_openr(cache->cc_relname); - } - - didopen = 1; - } - - /* ---------------- - * initialize the cache's relation id - * ---------------- - */ - Assert(RelationIsValid(relation)); - cache->relationId = RelationGetRelationId(relation); - tupdesc = cache->cc_tupdesc = RelationGetTupleDescriptor(relation); - - CACHE3_elog(DEBUG, "CatalogCacheInitializeCache: relid %d, %d keys", - cache->relationId, cache->cc_nkeys); - - /* ---------------- - * initialize cache's key information - * ---------------- - */ - for (i = 0; i < cache->cc_nkeys; ++i) { - CatalogCacheInitializeCache_DEBUG2; - - if (cache->cc_key[i] > 0) { - - /* - * Yoiks. The implementation of the hashing code and the - * implementation of int28's are at loggerheads. The right - * thing to do is to throw out the implementation of int28's - * altogether; until that happens, we do the right thing here - * to guarantee that the hash key generator doesn't try to - * dereference an int2 by mistake. - */ - - if (tupdesc->attrs[cache->cc_key[i]-1]->atttypid == INT28OID) - cache->cc_klen[i] = sizeof (short); - else - cache->cc_klen[i] = tupdesc->attrs[cache->cc_key[i]-1]->attlen; - - cache->cc_skey[i].sk_procedure = - EQPROC(tupdesc->attrs[cache->cc_key[i]-1]->atttypid); - - fmgr_info(cache->cc_skey[i].sk_procedure, - (func_ptr *) &cache->cc_skey[i].sk_func, - (int *) &cache->cc_skey[i].sk_nargs); - - CACHE5_elog(DEBUG, "CatalogCacheInit %16s %d %d %x", - &relation->rd_rel->relname, - i, - tupdesc->attrs[ cache->cc_key[i]-1 ]->attlen, - cache); + Assert(RelationIsValid(relation)); + cache->relationId = RelationGetRelationId(relation); + tupdesc = cache->cc_tupdesc = RelationGetTupleDescriptor(relation); + + CACHE3_elog(DEBUG, "CatalogCacheInitializeCache: relid %d, %d keys", + cache->relationId, cache->cc_nkeys); + + /* ---------------- + * initialize cache's key information + * ---------------- + */ + for (i = 0; i < cache->cc_nkeys; ++i) + { + CatalogCacheInitializeCache_DEBUG2; + + if (cache->cc_key[i] > 0) + { + + /* + * Yoiks. The implementation of the hashing code and the + * implementation of int28's are at loggerheads. The right + * thing to do is to throw out the implementation of int28's + * altogether; until that happens, we do the right thing here + * to guarantee that the hash key generator doesn't try to + * dereference an int2 by mistake. + */ + + if (tupdesc->attrs[cache->cc_key[i] - 1]->atttypid == INT28OID) + cache->cc_klen[i] = sizeof(short); + else + cache->cc_klen[i] = tupdesc->attrs[cache->cc_key[i] - 1]->attlen; + + cache->cc_skey[i].sk_procedure = + EQPROC(tupdesc->attrs[cache->cc_key[i] - 1]->atttypid); + + fmgr_info(cache->cc_skey[i].sk_procedure, + (func_ptr *) & cache->cc_skey[i].sk_func, + (int *) &cache->cc_skey[i].sk_nargs); + + CACHE5_elog(DEBUG, "CatalogCacheInit %16s %d %d %x", + &relation->rd_rel->relname, + i, + tupdesc->attrs[cache->cc_key[i] - 1]->attlen, + cache); + } } - } - - /* ---------------- - * close the relation if we opened it - * ---------------- - */ - if (didopen) - heap_close(relation); - - /* ---------------- - * initialize index information for the cache. this - * should only be done once per cache. - * ---------------- - */ - if (cache->cc_indname != NULL && cache->indexId == InvalidOid) + + /* ---------------- + * close the relation if we opened it + * ---------------- + */ + if (didopen) + heap_close(relation); + + /* ---------------- + * initialize index information for the cache. this + * should only be done once per cache. + * ---------------- + */ + if (cache->cc_indname != NULL && cache->indexId == InvalidOid) { - if (RelationGetRelationTupleForm(relation)->relhasindex) + if (RelationGetRelationTupleForm(relation)->relhasindex) { - /* - * If the index doesn't exist we are in trouble. - */ - relation = index_openr( cache->cc_indname); - Assert(relation); - cache->indexId = RelationGetRelationId(relation); - index_close(relation); + + /* + * If the index doesn't exist we are in trouble. + */ + relation = index_openr(cache->cc_indname); + Assert(relation); + cache->indexId = RelationGetRelationId(relation); + index_close(relation); } - else - cache->cc_indname = NULL; + else + cache->cc_indname = NULL; } - - /* ---------------- - * return to the proper memory context - * ---------------- - */ - MemoryContextSwitchTo(oldcxt); + + /* ---------------- + * return to the proper memory context + * ---------------- + */ + MemoryContextSwitchTo(oldcxt); } /* -------------------------------- - * CatalogCacheSetId + * CatalogCacheSetId * - * XXX temporary function + * XXX temporary function * -------------------------------- */ #ifdef NOT_USED void -CatalogCacheSetId(CatCache *cacheInOutP, int id) +CatalogCacheSetId(CatCache * cacheInOutP, int id) { - Assert(id == InvalidCatalogCacheId || id >= 0); - cacheInOutP->id = id; + Assert(id == InvalidCatalogCacheId || id >= 0); + cacheInOutP->id = id; } + #endif /* ---------------- * comphash -- - * Compute a hash value, somehow. + * Compute a hash value, somehow. * * XXX explain algorithm here. * @@ -279,798 +289,846 @@ CatalogCacheSetId(CatCache *cacheInOutP, int id) static long comphash(long l, register char *v) { - long i; - NameData n; - - CACHE3_elog(DEBUG, "comphash (%d,%x)", l, v); - - switch (l) { - case 1: - case 2: - case 4: - return((long) v); - } - - if (l == NAMEDATALEN) { - /* if it's a name, make sure that the values - are null-padded. - - Note that this other fixed-length types can also have - the same typelen so this may break them - XXX - */ - namestrcpy(&n,v); - v = n.data; - } else - if (l < 0) - l = VARSIZE(v); - - i = 0; - while (l--) { - i += *v++; - } - return(i); + long i; + NameData n; + + CACHE3_elog(DEBUG, "comphash (%d,%x)", l, v); + + switch (l) + { + case 1: + case 2: + case 4: + return ((long) v); + } + + if (l == NAMEDATALEN) + { + + /* + * if it's a name, make sure that the values are null-padded. + * + * Note that this other fixed-length types can also have the same + * typelen so this may break them - XXX + */ + namestrcpy(&n, v); + v = n.data; + } + else if (l < 0) + l = VARSIZE(v); + + i = 0; + while (l--) + { + i += *v++; + } + return (i); } /* -------------------------------- - * CatalogCacheComputeHashIndex + * CatalogCacheComputeHashIndex * -------------------------------- */ -static Index -CatalogCacheComputeHashIndex(struct catcache *cacheInP) +static Index +CatalogCacheComputeHashIndex(struct catcache * cacheInP) { - Index hashIndex; - hashIndex = 0x0; - CACHE6_elog(DEBUG,"CatalogCacheComputeHashIndex %s %d %d %d %x", - cacheInP->cc_relname, - cacheInP->cc_nkeys, - cacheInP->cc_klen[0], - cacheInP->cc_klen[1], - cacheInP); - - switch (cacheInP->cc_nkeys) { - case 4: - hashIndex ^= comphash(cacheInP->cc_klen[3], - (char*)cacheInP->cc_skey[3].sk_argument) << 9; - /* FALLTHROUGH */ - case 3: - hashIndex ^= comphash(cacheInP->cc_klen[2], - (char*)cacheInP->cc_skey[2].sk_argument) << 6; - /* FALLTHROUGH */ - case 2: - hashIndex ^= comphash(cacheInP->cc_klen[1], - (char*)cacheInP->cc_skey[1].sk_argument) << 3; - /* FALLTHROUGH */ - case 1: - hashIndex ^= comphash(cacheInP->cc_klen[0], - (char*)cacheInP->cc_skey[0].sk_argument); - break; - default: - elog(FATAL, "CCComputeHashIndex: %d cc_nkeys", cacheInP->cc_nkeys); - break; - } - hashIndex %= cacheInP->cc_size; - return (hashIndex); + Index hashIndex; + + hashIndex = 0x0; + CACHE6_elog(DEBUG, "CatalogCacheComputeHashIndex %s %d %d %d %x", + cacheInP->cc_relname, + cacheInP->cc_nkeys, + cacheInP->cc_klen[0], + cacheInP->cc_klen[1], + cacheInP); + + switch (cacheInP->cc_nkeys) + { + case 4: + hashIndex ^= comphash(cacheInP->cc_klen[3], + (char *) cacheInP->cc_skey[3].sk_argument) << 9; + /* FALLTHROUGH */ + case 3: + hashIndex ^= comphash(cacheInP->cc_klen[2], + (char *) cacheInP->cc_skey[2].sk_argument) << 6; + /* FALLTHROUGH */ + case 2: + hashIndex ^= comphash(cacheInP->cc_klen[1], + (char *) cacheInP->cc_skey[1].sk_argument) << 3; + /* FALLTHROUGH */ + case 1: + hashIndex ^= comphash(cacheInP->cc_klen[0], + (char *) cacheInP->cc_skey[0].sk_argument); + break; + default: + elog(FATAL, "CCComputeHashIndex: %d cc_nkeys", cacheInP->cc_nkeys); + break; + } + hashIndex %= cacheInP->cc_size; + return (hashIndex); } /* -------------------------------- - * CatalogCacheComputeTupleHashIndex + * CatalogCacheComputeTupleHashIndex * -------------------------------- */ -static Index -CatalogCacheComputeTupleHashIndex(struct catcache *cacheInOutP, - Relation relation, - HeapTuple tuple) +static Index +CatalogCacheComputeTupleHashIndex(struct catcache * cacheInOutP, + Relation relation, + HeapTuple tuple) { - bool isNull = '\0'; - if (cacheInOutP->relationId == InvalidOid) - CatalogCacheInitializeCache(cacheInOutP, relation); - switch (cacheInOutP->cc_nkeys) { - case 4: - cacheInOutP->cc_skey[3].sk_argument = - (cacheInOutP->cc_key[3] == ObjectIdAttributeNumber) - ? (Datum)tuple->t_oid - : (Datum)fastgetattr(tuple, - cacheInOutP->cc_key[3], - RelationGetTupleDescriptor(relation), - &isNull); - Assert(!isNull); - /* FALLTHROUGH */ - case 3: - cacheInOutP->cc_skey[2].sk_argument = - (cacheInOutP->cc_key[2] == ObjectIdAttributeNumber) - ? (Datum)tuple->t_oid - : (Datum)fastgetattr(tuple, - cacheInOutP->cc_key[2], - RelationGetTupleDescriptor(relation), - &isNull); - Assert(!isNull); - /* FALLTHROUGH */ - case 2: - cacheInOutP->cc_skey[1].sk_argument = - (cacheInOutP->cc_key[1] == ObjectIdAttributeNumber) - ? (Datum)tuple->t_oid - : (Datum)fastgetattr(tuple, - cacheInOutP->cc_key[1], - RelationGetTupleDescriptor(relation), - &isNull); - Assert(!isNull); - /* FALLTHROUGH */ - case 1: - cacheInOutP->cc_skey[0].sk_argument = - (cacheInOutP->cc_key[0] == ObjectIdAttributeNumber) - ? (Datum)tuple->t_oid - : (Datum)fastgetattr(tuple, - cacheInOutP->cc_key[0], - RelationGetTupleDescriptor(relation), - &isNull); - Assert(!isNull); - break; - default: - elog(FATAL, "CCComputeTupleHashIndex: %d cc_nkeys", - cacheInOutP->cc_nkeys - ); - break; - } - - return - CatalogCacheComputeHashIndex(cacheInOutP); + bool isNull = '\0'; + + if (cacheInOutP->relationId == InvalidOid) + CatalogCacheInitializeCache(cacheInOutP, relation); + switch (cacheInOutP->cc_nkeys) + { + case 4: + cacheInOutP->cc_skey[3].sk_argument = + (cacheInOutP->cc_key[3] == ObjectIdAttributeNumber) + ? (Datum) tuple->t_oid + : (Datum) fastgetattr(tuple, + cacheInOutP->cc_key[3], + RelationGetTupleDescriptor(relation), + &isNull); + Assert(!isNull); + /* FALLTHROUGH */ + case 3: + cacheInOutP->cc_skey[2].sk_argument = + (cacheInOutP->cc_key[2] == ObjectIdAttributeNumber) + ? (Datum) tuple->t_oid + : (Datum) fastgetattr(tuple, + cacheInOutP->cc_key[2], + RelationGetTupleDescriptor(relation), + &isNull); + Assert(!isNull); + /* FALLTHROUGH */ + case 2: + cacheInOutP->cc_skey[1].sk_argument = + (cacheInOutP->cc_key[1] == ObjectIdAttributeNumber) + ? (Datum) tuple->t_oid + : (Datum) fastgetattr(tuple, + cacheInOutP->cc_key[1], + RelationGetTupleDescriptor(relation), + &isNull); + Assert(!isNull); + /* FALLTHROUGH */ + case 1: + cacheInOutP->cc_skey[0].sk_argument = + (cacheInOutP->cc_key[0] == ObjectIdAttributeNumber) + ? (Datum) tuple->t_oid + : (Datum) fastgetattr(tuple, + cacheInOutP->cc_key[0], + RelationGetTupleDescriptor(relation), + &isNull); + Assert(!isNull); + break; + default: + elog(FATAL, "CCComputeTupleHashIndex: %d cc_nkeys", + cacheInOutP->cc_nkeys + ); + break; + } + + return + CatalogCacheComputeHashIndex(cacheInOutP); } /* -------------------------------- - * CatCacheRemoveCTup + * CatCacheRemoveCTup * -------------------------------- */ static void -CatCacheRemoveCTup(CatCache *cache, Dlelem *elt) +CatCacheRemoveCTup(CatCache * cache, Dlelem * elt) { - CatCTup *ct; - CatCTup *other_ct; - Dlelem *other_elt; - - if (elt) - ct = (CatCTup*) DLE_VAL(elt); - else - return; - - other_elt = ct->ct_node; - other_ct = (CatCTup*)DLE_VAL(other_elt); - DLRemove(other_elt); - DLFreeElem(other_elt); - free(other_ct); - DLRemove(elt); - DLFreeElem(elt); - free(ct); - --cache->cc_ntup; + CatCTup *ct; + CatCTup *other_ct; + Dlelem *other_elt; + + if (elt) + ct = (CatCTup *) DLE_VAL(elt); + else + return; + + other_elt = ct->ct_node; + other_ct = (CatCTup *) DLE_VAL(other_elt); + DLRemove(other_elt); + DLFreeElem(other_elt); + free(other_ct); + DLRemove(elt); + DLFreeElem(elt); + free(ct); + --cache->cc_ntup; } /* -------------------------------- - * CatalogCacheIdInvalidate() + * CatalogCacheIdInvalidate() * - * Invalidate a tuple given a cache id. In this case the id should always - * 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 - * no problem. + * Invalidate a tuple given a cache id. In this case the id should always + * 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 + * no problem. * -------------------------------- */ void -CatalogCacheIdInvalidate(int cacheId, /* XXX */ - Index hashIndex, - ItemPointer pointer) +CatalogCacheIdInvalidate(int cacheId, /* XXX */ + Index hashIndex, + ItemPointer pointer) { - CatCache *ccp; - CatCTup *ct; - Dlelem *elt; - MemoryContext oldcxt; - - /* ---------------- - * sanity checks - * ---------------- - */ - Assert(hashIndex < NCCBUCK); - Assert(ItemPointerIsValid(pointer)); - CACHE1_elog(DEBUG, "CatalogCacheIdInvalidate: called"); - - /* ---------------- - * switch to the cache context for our memory allocations - * ---------------- - */ - if (!CacheCxt) - CacheCxt = CreateGlobalMemory("Cache"); - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - /* ---------------- - * inspect every cache that could contain the tuple - * ---------------- - */ - for (ccp = Caches; ccp; ccp = ccp->cc_next) { - if (cacheId != ccp->id) - continue; + CatCache *ccp; + CatCTup *ct; + Dlelem *elt; + MemoryContext oldcxt; + /* ---------------- - * inspect the hash bucket until we find a match or exhaust + * sanity checks * ---------------- */ - for (elt = DLGetHead(ccp->cc_cache[hashIndex]); - elt; - elt = DLGetSucc(elt)) - { - ct = (CatCTup*) DLE_VAL(elt); - if (ItemPointerEquals(pointer, &ct->ct_tup->t_ctid)) - break; - } - + Assert(hashIndex < NCCBUCK); + Assert(ItemPointerIsValid(pointer)); + CACHE1_elog(DEBUG, "CatalogCacheIdInvalidate: called"); + /* ---------------- - * if we found a matching tuple, invalidate it. + * switch to the cache context for our memory allocations * ---------------- */ + if (!CacheCxt) + CacheCxt = CreateGlobalMemory("Cache"); + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + /* ---------------- + * inspect every cache that could contain the tuple + * ---------------- + */ + for (ccp = Caches; ccp; ccp = ccp->cc_next) + { + if (cacheId != ccp->id) + continue; + /* ---------------- + * inspect the hash bucket until we find a match or exhaust + * ---------------- + */ + for (elt = DLGetHead(ccp->cc_cache[hashIndex]); + elt; + elt = DLGetSucc(elt)) + { + ct = (CatCTup *) DLE_VAL(elt); + if (ItemPointerEquals(pointer, &ct->ct_tup->t_ctid)) + break; + } - if (elt) { - CatCacheRemoveCTup(ccp, elt); + /* ---------------- + * if we found a matching tuple, invalidate it. + * ---------------- + */ - CACHE1_elog(DEBUG, "CatalogCacheIdInvalidate: invalidated"); + if (elt) + { + CatCacheRemoveCTup(ccp, elt); + + CACHE1_elog(DEBUG, "CatalogCacheIdInvalidate: invalidated"); + } + + if (cacheId != InvalidCatalogCacheId) + break; } - - if (cacheId != InvalidCatalogCacheId) - break; - } - - /* ---------------- - * return to the proper memory context - * ---------------- - */ - MemoryContextSwitchTo(oldcxt); - /* sendpm('I', "Invalidated tuple"); */ + + /* ---------------- + * return to the proper memory context + * ---------------- + */ + MemoryContextSwitchTo(oldcxt); + /* sendpm('I', "Invalidated tuple"); */ } /* ---------------------------------------------------------------- - * public functions + * public functions * - * ResetSystemCache - * InitIndexedSysCache - * InitSysCache - * SearchSysCache - * RelationInvalidateCatalogCacheTuple + * ResetSystemCache + * InitIndexedSysCache + * InitSysCache + * SearchSysCache + * RelationInvalidateCatalogCacheTuple * ---------------------------------------------------------------- */ /* -------------------------------- - * ResetSystemCache + * ResetSystemCache * -------------------------------- */ void ResetSystemCache() { - MemoryContext oldcxt; - struct catcache *cache; - - /* ---------------- - * sanity checks - * ---------------- - */ - CACHE1_elog(DEBUG, "ResetSystemCache called"); - if (DisableCache) { - elog(WARN, "ResetSystemCache: Called while cache disabled"); - return; - } - - /* ---------------- - * first switch to the cache context so our allocations - * do not vanish at the end of a transaction - * ---------------- - */ - if (!CacheCxt) - CacheCxt = CreateGlobalMemory("Cache"); - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - /* ---------------- - * here we purge the contents of all the caches - * - * for each system cache - * for each hash bucket - * for each tuple in hash bucket - * remove the tuple - * ---------------- - */ - for (cache = Caches; PointerIsValid(cache); cache = cache->cc_next) { - int hash; - for (hash = 0; hash < NCCBUCK; hash += 1) { - Dlelem *elt, *nextelt; - for (elt = DLGetHead(cache->cc_cache[hash]); elt; elt = nextelt) { - nextelt = DLGetSucc(elt); - CatCacheRemoveCTup(cache, elt); - if (cache->cc_ntup == -1) - elog(WARN, "ResetSystemCache: cc_ntup<0 (software error)"); - } + MemoryContext oldcxt; + struct catcache *cache; + + /* ---------------- + * sanity checks + * ---------------- + */ + CACHE1_elog(DEBUG, "ResetSystemCache called"); + if (DisableCache) + { + elog(WARN, "ResetSystemCache: Called while cache disabled"); + return; + } + + /* ---------------- + * first switch to the cache context so our allocations + * do not vanish at the end of a transaction + * ---------------- + */ + if (!CacheCxt) + CacheCxt = CreateGlobalMemory("Cache"); + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + /* ---------------- + * here we purge the contents of all the caches + * + * for each system cache + * for each hash bucket + * for each tuple in hash bucket + * remove the tuple + * ---------------- + */ + for (cache = Caches; PointerIsValid(cache); cache = cache->cc_next) + { + int hash; + + for (hash = 0; hash < NCCBUCK; hash += 1) + { + Dlelem *elt, + *nextelt; + + for (elt = DLGetHead(cache->cc_cache[hash]); elt; elt = nextelt) + { + nextelt = DLGetSucc(elt); + CatCacheRemoveCTup(cache, elt); + if (cache->cc_ntup == -1) + elog(WARN, "ResetSystemCache: cc_ntup<0 (software error)"); + } + } + cache->cc_ntup = 0; /* in case of WARN error above */ } - cache->cc_ntup = 0; /* in case of WARN error above */ - } - - CACHE1_elog(DEBUG, "end of ResetSystemCache call"); - - /* ---------------- - * back to the old context before we return... - * ---------------- - */ - MemoryContextSwitchTo(oldcxt); + + CACHE1_elog(DEBUG, "end of ResetSystemCache call"); + + /* ---------------- + * back to the old context before we return... + * ---------------- + */ + MemoryContextSwitchTo(oldcxt); } /* -------------------------------- - * InitIndexedSysCache + * InitIndexedSysCache * - * This allocates and initializes a cache for a system catalog relation. - * Actually, the cache is only partially initialized to avoid opening the - * relation. The relation will be opened and the rest of the cache - * structure initialized on the first access. + * This allocates and initializes a cache for a system catalog relation. + * Actually, the cache is only partially initialized to avoid opening the + * relation. The relation will be opened and the rest of the cache + * structure initialized on the first access. * -------------------------------- */ #ifdef CACHEDEBUG #define InitSysCache_DEBUG1 \ elog(DEBUG, "InitSysCache: rid=%d id=%d nkeys=%d size=%d\n", \ - cp->relationId, cp->id, cp->cc_nkeys, cp->cc_size); \ - for (i = 0; i < nkeys; i += 1) { \ - elog(DEBUG, "InitSysCache: key=%d len=%d skey=[%d %d %d %d]\n", \ - cp->cc_key[i], cp->cc_klen[i], \ - cp->cc_skey[i].sk_flags, \ - cp->cc_skey[i].sk_attno, \ - cp->cc_skey[i].sk_procedure, \ - cp->cc_skey[i].sk_argument); \ - } + cp->relationId, cp->id, cp->cc_nkeys, cp->cc_size); \ + for (i = 0; i < nkeys; i += 1) { \ + elog(DEBUG, "InitSysCache: key=%d len=%d skey=[%d %d %d %d]\n", \ + cp->cc_key[i], cp->cc_klen[i], \ + cp->cc_skey[i].sk_flags, \ + cp->cc_skey[i].sk_attno, \ + cp->cc_skey[i].sk_procedure, \ + cp->cc_skey[i].sk_argument); \ + } #else #define InitSysCache_DEBUG1 #endif -CatCache* +CatCache * InitSysCache(char *relname, - char *iname, - int id, - int nkeys, - int key[], - HeapTuple (*iScanfuncP)()) + char *iname, + int id, + int nkeys, + int key[], + HeapTuple(*iScanfuncP) ()) { - CatCache *cp; - register int i; - MemoryContext oldcxt; - - char *indname; - - indname = (iname) ? iname : NULL; - - /* ---------------- - * first switch to the cache context so our allocations - * do not vanish at the end of a transaction - * ---------------- - */ - if (!CacheCxt) - CacheCxt = CreateGlobalMemory("Cache"); - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - /* ---------------- - * allocate a new cache structure - * ---------------- - */ - cp = (CatCache *)palloc(sizeof(CatCache)); - memset((char*)cp, 0, sizeof(CatCache)); - - /* ---------------- - * initialize the cache buckets (each bucket is a list header) - * and the LRU tuple list - * ---------------- - */ - { - /* - * We can only do this optimization because the number of hash - * buckets never changes. Without it, we call malloc() too much. - * We could move this to dllist.c, but the way we do this is not - * dynamic/portabl, so why allow other routines to use it. - */ - Dllist *cache_begin = malloc((NCCBUCK+1)*sizeof(Dllist)); - for (i = 0; i <= NCCBUCK; ++i) { - cp->cc_cache[i] = &cache_begin[i]; - cp->cc_cache[i]->dll_head = 0; - cp->cc_cache[i]->dll_tail = 0; - } - } - - cp->cc_lrulist = DLNewList(); - - /* ---------------- - * 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 - * corresponding to this cache and initialize some of the the new - * cache's other internal fields. - * ---------------- - */ - cp->relationId = InvalidOid; - cp->indexId = InvalidOid; - cp->cc_relname = relname; - cp->cc_indname = indname; - cp->cc_tupdesc = (TupleDesc) NULL; - cp->id = id; - cp->cc_maxtup = MAXTUP; - cp->cc_size = NCCBUCK; - cp->cc_nkeys = nkeys; - cp->cc_iscanfunc = iScanfuncP; - - /* ---------------- - * initialize the cache's key information - * ---------------- - */ - for (i = 0; i < nkeys; ++i) { - cp->cc_key[i] = key[i]; - if (!key[i]) { - elog(FATAL, "InitSysCache: called with 0 key[%d]", i); - } - if (key[i] < 0) { - if (key[i] != ObjectIdAttributeNumber) { - elog(FATAL, "InitSysCache: called with %d key[%d]", key[i], i); - } else { - cp->cc_klen[i] = sizeof(Oid); + CatCache *cp; + register int i; + MemoryContext oldcxt; + + char *indname; + + indname = (iname) ? iname : NULL; + + /* ---------------- + * first switch to the cache context so our allocations + * do not vanish at the end of a transaction + * ---------------- + */ + if (!CacheCxt) + CacheCxt = CreateGlobalMemory("Cache"); + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + /* ---------------- + * allocate a new cache structure + * ---------------- + */ + cp = (CatCache *) palloc(sizeof(CatCache)); + memset((char *) cp, 0, sizeof(CatCache)); + + /* ---------------- + * initialize the cache buckets (each bucket is a list header) + * and the LRU tuple list + * ---------------- + */ + { + /* - * ScanKeyEntryData and struct skey are equivalent. It looks - * like a move was made to obsolete struct skey, but it - * didn't reach this file. Someday we should clean up this - * code and consolidate to ScanKeyEntry - mer 10 Nov 1991 + * We can only do this optimization because the number of hash + * buckets never changes. Without it, we call malloc() too much. + * We could move this to dllist.c, but the way we do this is not + * dynamic/portabl, so why allow other routines to use it. */ - ScanKeyEntryInitialize(&cp->cc_skey[i], - (bits16)0, - (AttrNumber)key[i], - (RegProcedure)F_OIDEQ, - (Datum)0); - continue; - } + Dllist *cache_begin = malloc((NCCBUCK + 1) * sizeof(Dllist)); + + for (i = 0; i <= NCCBUCK; ++i) + { + cp->cc_cache[i] = &cache_begin[i]; + cp->cc_cache[i]->dll_head = 0; + cp->cc_cache[i]->dll_tail = 0; + } + } + + cp->cc_lrulist = DLNewList(); + + /* ---------------- + * 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 + * corresponding to this cache and initialize some of the the new + * cache's other internal fields. + * ---------------- + */ + cp->relationId = InvalidOid; + cp->indexId = InvalidOid; + cp->cc_relname = relname; + cp->cc_indname = indname; + cp->cc_tupdesc = (TupleDesc) NULL; + cp->id = id; + cp->cc_maxtup = MAXTUP; + cp->cc_size = NCCBUCK; + cp->cc_nkeys = nkeys; + cp->cc_iscanfunc = iScanfuncP; + + /* ---------------- + * initialize the cache's key information + * ---------------- + */ + for (i = 0; i < nkeys; ++i) + { + cp->cc_key[i] = key[i]; + if (!key[i]) + { + elog(FATAL, "InitSysCache: called with 0 key[%d]", i); + } + if (key[i] < 0) + { + if (key[i] != ObjectIdAttributeNumber) + { + elog(FATAL, "InitSysCache: called with %d key[%d]", key[i], i); + } + else + { + cp->cc_klen[i] = sizeof(Oid); + + /* + * ScanKeyEntryData and struct skey are equivalent. It + * looks like a move was made to obsolete struct skey, but + * it didn't reach this file. Someday we should clean up + * this code and consolidate to ScanKeyEntry - mer 10 Nov + * 1991 + */ + ScanKeyEntryInitialize(&cp->cc_skey[i], + (bits16) 0, + (AttrNumber) key[i], + (RegProcedure) F_OIDEQ, + (Datum) 0); + continue; + } + } + + cp->cc_skey[i].sk_attno = key[i]; } - - cp->cc_skey[i].sk_attno = key[i]; - } - - /* ---------------- - * all done. new cache is initialized. print some debugging - * information, if appropriate. - * ---------------- - */ - InitSysCache_DEBUG1; - - /* ---------------- - * back to the old context before we return... - * ---------------- - */ - MemoryContextSwitchTo(oldcxt); - return(cp); + + /* ---------------- + * all done. new cache is initialized. print some debugging + * information, if appropriate. + * ---------------- + */ + InitSysCache_DEBUG1; + + /* ---------------- + * back to the old context before we return... + * ---------------- + */ + MemoryContextSwitchTo(oldcxt); + return (cp); } /* -------------------------------- - * SearchSysCache + * SearchSysCache * - * This call searches a system cache for a tuple, opening the relation - * if necessary (the first access to a particular cache). + * This call searches a system cache for a tuple, opening the relation + * if necessary (the first access to a particular cache). * -------------------------------- */ HeapTuple -SearchSysCache(struct catcache *cache, - Datum v1, - Datum v2, - Datum v3, - Datum v4) +SearchSysCache(struct catcache * cache, + Datum v1, + Datum v2, + Datum v3, + Datum v4) { - unsigned hash; - CatCTup *ct = NULL; - CatCTup *nct; - CatCTup *nct2; - Dlelem *elt; - HeapTuple ntp = 0; - Buffer buffer; - - Relation relation; - MemoryContext oldcxt; - - /* ---------------- - * sanity checks - * ---------------- - */ - if (cache->relationId == InvalidOid) - CatalogCacheInitializeCache(cache, NULL); - - /* ---------------- - * initialize the search key information - * ---------------- - */ - cache->cc_skey[0].sk_argument = v1; - cache->cc_skey[1].sk_argument = v2; - cache->cc_skey[2].sk_argument = v3; - cache->cc_skey[3].sk_argument = v4; - - /* ---------------- - * find the hash bucket in which to look for the tuple - * ---------------- - */ - hash = CatalogCacheComputeHashIndex(cache); - - /* ---------------- - * scan the hash bucket until we find a match or exhaust our tuples - * ---------------- - */ - for (elt = DLGetHead(cache->cc_cache[hash]); - elt; - elt = DLGetSucc(elt)) + unsigned hash; + CatCTup *ct = NULL; + CatCTup *nct; + CatCTup *nct2; + Dlelem *elt; + HeapTuple ntp = 0; + Buffer buffer; + + Relation relation; + MemoryContext oldcxt; + + /* ---------------- + * sanity checks + * ---------------- + */ + if (cache->relationId == InvalidOid) + CatalogCacheInitializeCache(cache, NULL); + + /* ---------------- + * initialize the search key information + * ---------------- + */ + cache->cc_skey[0].sk_argument = v1; + cache->cc_skey[1].sk_argument = v2; + cache->cc_skey[2].sk_argument = v3; + cache->cc_skey[3].sk_argument = v4; + + /* ---------------- + * find the hash bucket in which to look for the tuple + * ---------------- + */ + hash = CatalogCacheComputeHashIndex(cache); + + /* ---------------- + * scan the hash bucket until we find a match or exhaust our tuples + * ---------------- + */ + for (elt = DLGetHead(cache->cc_cache[hash]); + elt; + elt = DLGetSucc(elt)) { - ct = (CatCTup*)DLE_VAL(elt); - /* ---------------- - * see if the cached tuple matches our key. - * (should we be worried about time ranges? -cim 10/2/90) - * ---------------- - */ - if (heap_keytest(ct->ct_tup, - cache->cc_tupdesc, - cache->cc_nkeys, - cache->cc_skey)) - break; + ct = (CatCTup *) DLE_VAL(elt); + /* ---------------- + * see if the cached tuple matches our key. + * (should we be worried about time ranges? -cim 10/2/90) + * ---------------- + */ + if (heap_keytest(ct->ct_tup, + cache->cc_tupdesc, + cache->cc_nkeys, + cache->cc_skey)) + break; } - - /* ---------------- - * if we found a tuple in the cache, move it to the top of the - * lru list, and return it. - * ---------------- - */ - if (elt) { - Dlelem* old_lru_elt; - old_lru_elt = ((CatCTup*)DLE_VAL(elt))->ct_node; - DLRemove(old_lru_elt); - DLAddHead(cache->cc_lrulist, old_lru_elt); + + /* ---------------- + * if we found a tuple in the cache, move it to the top of the + * lru list, and return it. + * ---------------- + */ + if (elt) + { + Dlelem *old_lru_elt; + + old_lru_elt = ((CatCTup *) DLE_VAL(elt))->ct_node; + DLRemove(old_lru_elt); + DLAddHead(cache->cc_lrulist, old_lru_elt); #ifdef CACHEDEBUG + relation = heap_open(cache->relationId); + CACHE3_elog(DEBUG, "SearchSysCache(%s): found in bucket %d", + RelationGetRelationName(relation), hash); + heap_close(relation); +#endif /* CACHEDEBUG */ + + return (ct->ct_tup); + } + + /* ---------------- + * Tuple was not found in cache, so we have to try and + * retrieve it directly from the relation. If it's found, + * we add it to the cache. We must avoid recursion here, + * so we disable cache operations. If operations are + * currently disabled and we couldn't find the requested item + * in the cache, then this may be a recursive request, and we + * abort with an error. + * ---------------- + */ + + if (DisableCache) + { + elog(WARN, "SearchSysCache: Called while cache disabled"); + return ((HeapTuple) NULL); + } + + /* ---------------- + * open the relation associated with the cache + * ---------------- + */ relation = heap_open(cache->relationId); - CACHE3_elog(DEBUG, "SearchSysCache(%s): found in bucket %d", - RelationGetRelationName(relation), hash); - heap_close(relation); -#endif /* CACHEDEBUG */ - - return (ct->ct_tup); - } - - /* ---------------- - * Tuple was not found in cache, so we have to try and - * retrieve it directly from the relation. If it's found, - * we add it to the cache. We must avoid recursion here, - * so we disable cache operations. If operations are - * currently disabled and we couldn't find the requested item - * in the cache, then this may be a recursive request, and we - * abort with an error. - * ---------------- - */ - - if (DisableCache) { - elog(WARN, "SearchSysCache: Called while cache disabled"); - return((HeapTuple) NULL); - } - - /* ---------------- - * open the relation associated with the cache - * ---------------- - */ - relation = heap_open(cache->relationId); - CACHE2_elog(DEBUG, "SearchSysCache(%s)", - RelationGetRelationName(relation)); - - /* ---------------- - * DisableCache and then switch to the cache memory context. - * ---------------- - */ - DisableCache = 1; - - if (!CacheCxt) - CacheCxt = CreateGlobalMemory("Cache"); - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - /* ---------------- - * Scan the relation to find the tuple. If there's an index, and - * if this isn't bootstrap (initdb) time, use the index. - * ---------------- - */ - CACHE2_elog(DEBUG, "SearchSysCache: performing scan (override==%d)", - heapisoverride()); - - if ((RelationGetRelationTupleForm(relation))->relhasindex - && !IsBootstrapProcessingMode()) + CACHE2_elog(DEBUG, "SearchSysCache(%s)", + RelationGetRelationName(relation)); + + /* ---------------- + * DisableCache and then switch to the cache memory context. + * ---------------- + */ + DisableCache = 1; + + if (!CacheCxt) + CacheCxt = CreateGlobalMemory("Cache"); + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + /* ---------------- + * Scan the relation to find the tuple. If there's an index, and + * if this isn't bootstrap (initdb) time, use the index. + * ---------------- + */ + CACHE2_elog(DEBUG, "SearchSysCache: performing scan (override==%d)", + heapisoverride()); + + if ((RelationGetRelationTupleForm(relation))->relhasindex + && !IsBootstrapProcessingMode()) { - /* ---------- - * Switch back to old memory context so memory not freed - * in the scan function will go away at transaction end. - * wieck - 10/18/1996 - * ---------- - */ - MemoryContextSwitchTo(oldcxt); - Assert(cache->cc_iscanfunc); - switch(cache->cc_nkeys) + /* ---------- + * Switch back to old memory context so memory not freed + * in the scan function will go away at transaction end. + * wieck - 10/18/1996 + * ---------- + */ + MemoryContextSwitchTo(oldcxt); + Assert(cache->cc_iscanfunc); + switch (cache->cc_nkeys) + { + case 4: + ntp = cache->cc_iscanfunc(relation, v1, v2, v3, v4); + break; + case 3: + ntp = cache->cc_iscanfunc(relation, v1, v2, v3); + break; + case 2: + ntp = cache->cc_iscanfunc(relation, v1, v2); + break; + case 1: + ntp = cache->cc_iscanfunc(relation, v1); + break; + } + /* ---------- + * Back to Cache context. If we got a tuple copy it + * into our context. + * wieck - 10/18/1996 + * ---------- + */ + MemoryContextSwitchTo((MemoryContext) CacheCxt); + if (HeapTupleIsValid(ntp)) { - case 4: ntp = cache->cc_iscanfunc(relation,v1,v2,v3,v4); break; - case 3: ntp = cache->cc_iscanfunc(relation,v1,v2,v3); break; - case 2: ntp = cache->cc_iscanfunc(relation,v1,v2); break; - case 1: ntp = cache->cc_iscanfunc(relation,v1); break; + ntp = heap_copytuple(ntp); } - /* ---------- - * Back to Cache context. If we got a tuple copy it - * into our context. - * wieck - 10/18/1996 - * ---------- - */ - MemoryContextSwitchTo((MemoryContext)CacheCxt); - if(HeapTupleIsValid(ntp)) { - ntp = heap_copytuple(ntp); - } } - else + else { - HeapScanDesc sd; - - /* ---------- - * As above do the lookup in the callers memory - * context. - * wieck - 10/18/1996 - * ---------- - */ - MemoryContextSwitchTo(oldcxt); - - sd = heap_beginscan(relation, 0, NowTimeQual, - cache->cc_nkeys, cache->cc_skey); - - /* should this buffer be ReleaseBuffer'd? --djm 8/20/96 */ - ntp = heap_getnext(sd, 0, &buffer); - - MemoryContextSwitchTo((MemoryContext)CacheCxt); - - if (HeapTupleIsValid(ntp)) { - CACHE1_elog(DEBUG, "SearchSysCache: found tuple"); - ntp = heap_copytuple(ntp); - } - - MemoryContextSwitchTo(oldcxt); - - heap_endscan(sd); - - MemoryContextSwitchTo((MemoryContext)CacheCxt); + HeapScanDesc sd; + + /* ---------- + * As above do the lookup in the callers memory + * context. + * wieck - 10/18/1996 + * ---------- + */ + MemoryContextSwitchTo(oldcxt); + + sd = heap_beginscan(relation, 0, NowTimeQual, + cache->cc_nkeys, cache->cc_skey); + + /* should this buffer be ReleaseBuffer'd? --djm 8/20/96 */ + ntp = heap_getnext(sd, 0, &buffer); + + MemoryContextSwitchTo((MemoryContext) CacheCxt); + + if (HeapTupleIsValid(ntp)) + { + CACHE1_elog(DEBUG, "SearchSysCache: found tuple"); + ntp = heap_copytuple(ntp); + } + + MemoryContextSwitchTo(oldcxt); + + heap_endscan(sd); + + MemoryContextSwitchTo((MemoryContext) CacheCxt); } - - DisableCache = 0; - - /* ---------------- - * scan is complete. if tup is valid, we copy it and add the copy to - * the cache. - * ---------------- - */ - if (HeapTupleIsValid(ntp)) { + + DisableCache = 0; + /* ---------------- - * allocate a new cache tuple holder, store the pointer - * to the heap tuple there and initialize the list pointers. + * scan is complete. if tup is valid, we copy it and add the copy to + * the cache. * ---------------- */ - Dlelem *lru_elt; - - /* this is a little cumbersome here because we want the Dlelem's - in both doubly linked lists to point to one another. - That makes it easier to remove something from both the cache bucket - and the lru list at the same time */ - nct = (CatCTup*) malloc(sizeof(CatCTup)); - nct->ct_tup = ntp; - elt = DLNewElem(nct); - nct2 = (CatCTup*) malloc(sizeof(CatCTup)); - nct2->ct_tup = ntp; - lru_elt = DLNewElem(nct2); - nct2->ct_node = elt; - nct->ct_node = lru_elt; - - DLAddHead(cache->cc_lrulist, lru_elt); - DLAddHead(cache->cc_cache[hash], elt); + if (HeapTupleIsValid(ntp)) + { + /* ---------------- + * allocate a new cache tuple holder, store the pointer + * to the heap tuple there and initialize the list pointers. + * ---------------- + */ + Dlelem *lru_elt; + + /* + * this is a little cumbersome here because we want the Dlelem's + * in both doubly linked lists to point to one another. That makes + * it easier to remove something from both the cache bucket and + * the lru list at the same time + */ + nct = (CatCTup *) malloc(sizeof(CatCTup)); + nct->ct_tup = ntp; + elt = DLNewElem(nct); + nct2 = (CatCTup *) malloc(sizeof(CatCTup)); + nct2->ct_tup = ntp; + lru_elt = DLNewElem(nct2); + nct2->ct_node = elt; + nct->ct_node = lru_elt; + + DLAddHead(cache->cc_lrulist, lru_elt); + DLAddHead(cache->cc_cache[hash], elt); + + /* ---------------- + * deal with hash bucket overflow + * ---------------- + */ + if (++cache->cc_ntup > cache->cc_maxtup) + { + CatCTup *ct; + + elt = DLGetTail(cache->cc_lrulist); + ct = (CatCTup *) DLE_VAL(elt); + + if (ct != nct) + { + CACHE2_elog(DEBUG, "SearchSysCache(%s): Overflow, LRU removal", + RelationGetRelationName(relation)); + + CatCacheRemoveCTup(cache, elt); + + } + } + + CACHE4_elog(DEBUG, "SearchSysCache(%s): Contains %d/%d tuples", + RelationGetRelationName(relation), + cache->cc_ntup, cache->cc_maxtup); + CACHE3_elog(DEBUG, "SearchSysCache(%s): put in bucket %d", + RelationGetRelationName(relation), hash); + } /* ---------------- - * deal with hash bucket overflow + * close the relation, switch back to the original memory context + * and return the tuple we found (or NULL) * ---------------- */ - if (++cache->cc_ntup > cache->cc_maxtup) { - CatCTup *ct; - elt = DLGetTail(cache->cc_lrulist); - ct = (CatCTup *) DLE_VAL(elt); - - if (ct != nct) { - CACHE2_elog(DEBUG, "SearchSysCache(%s): Overflow, LRU removal", - RelationGetRelationName(relation)); - - CatCacheRemoveCTup(cache, elt); - - } - } - - CACHE4_elog(DEBUG, "SearchSysCache(%s): Contains %d/%d tuples", - RelationGetRelationName(relation), - cache->cc_ntup, cache->cc_maxtup); - CACHE3_elog(DEBUG, "SearchSysCache(%s): put in bucket %d", - RelationGetRelationName(relation), hash); - } - - /* ---------------- - * close the relation, switch back to the original memory context - * and return the tuple we found (or NULL) - * ---------------- - */ - heap_close(relation); - - MemoryContextSwitchTo(oldcxt); - return ntp; + heap_close(relation); + + MemoryContextSwitchTo(oldcxt); + return ntp; } /* -------------------------------- - * RelationInvalidateCatalogCacheTuple() + * RelationInvalidateCatalogCacheTuple() * - * Invalidate a tuple from a specific relation. This call determines the - * cache in question and calls CatalogCacheIdInvalidate(). It is -ok- - * if the relation cannot be found, it simply means this backend has yet - * to open it. + * Invalidate a tuple from a specific relation. This call determines the + * cache in question and calls CatalogCacheIdInvalidate(). It is -ok- + * if the relation cannot be found, it simply means this backend has yet + * to open it. * -------------------------------- */ void RelationInvalidateCatalogCacheTuple(Relation relation, - HeapTuple tuple, - void (*function)(int, Index, ItemPointer)) + HeapTuple tuple, + void (*function) (int, Index, ItemPointer)) { - struct catcache *ccp; - MemoryContext oldcxt; - Oid relationId; - - /* ---------------- - * sanity checks - * ---------------- - */ - Assert(RelationIsValid(relation)); - Assert(HeapTupleIsValid(tuple)); - CACHE1_elog(DEBUG, "RelationInvalidateCatalogCacheTuple: called"); - - /* ---------------- - * switch to the cache memory context - * ---------------- - */ - if (!CacheCxt) - CacheCxt = CreateGlobalMemory("Cache"); - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - /* ---------------- - * for each cache - * if the cache contains tuples from the specified relation - * call the invalidation function on the tuples - * in the proper hash bucket - * ---------------- - */ - relationId = RelationGetRelationId(relation); - - for (ccp = Caches; ccp; ccp = ccp->cc_next) { - if (relationId != ccp->relationId) - continue; - - /* OPT inline simplification of CatalogCacheIdInvalidate */ - if (!PointerIsValid(function)) { - function = CatalogCacheIdInvalidate; + struct catcache *ccp; + MemoryContext oldcxt; + Oid relationId; + + /* ---------------- + * sanity checks + * ---------------- + */ + Assert(RelationIsValid(relation)); + Assert(HeapTupleIsValid(tuple)); + CACHE1_elog(DEBUG, "RelationInvalidateCatalogCacheTuple: called"); + + /* ---------------- + * switch to the cache memory context + * ---------------- + */ + if (!CacheCxt) + CacheCxt = CreateGlobalMemory("Cache"); + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + /* ---------------- + * for each cache + * if the cache contains tuples from the specified relation + * call the invalidation function on the tuples + * in the proper hash bucket + * ---------------- + */ + relationId = RelationGetRelationId(relation); + + for (ccp = Caches; ccp; ccp = ccp->cc_next) + { + if (relationId != ccp->relationId) + continue; + + /* OPT inline simplification of CatalogCacheIdInvalidate */ + if (!PointerIsValid(function)) + { + function = CatalogCacheIdInvalidate; + } + + (*function) (ccp->id, + CatalogCacheComputeTupleHashIndex(ccp, relation, tuple), + &tuple->t_ctid); + + heap_close(relation); } - - (*function)(ccp->id, - CatalogCacheComputeTupleHashIndex(ccp, relation, tuple), - &tuple->t_ctid); - - heap_close(relation); - } - - /* ---------------- - * return to the proper memory context - * ---------------- - */ - MemoryContextSwitchTo(oldcxt); - - /* sendpm('I', "Invalidated tuple"); */ -} + /* ---------------- + * return to the proper memory context + * ---------------- + */ + MemoryContextSwitchTo(oldcxt); + + /* sendpm('I', "Invalidated tuple"); */ +} |