aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/cache/catcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/cache/catcache.c')
-rw-r--r--src/backend/utils/cache/catcache.c1786
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"); */
+}