diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2000-11-16 22:30:52 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2000-11-16 22:30:52 +0000 |
commit | a933ee38bbb8dffbc48a3363a94ff6f2a9f7964d (patch) | |
tree | 1c32737389b2530e7152dc2287161b36d9001e8c /src/backend/utils/cache/syscache.c | |
parent | cff23842a4c68301ddf34559c7af383bb5557054 (diff) | |
download | postgresql-a933ee38bbb8dffbc48a3363a94ff6f2a9f7964d.tar.gz postgresql-a933ee38bbb8dffbc48a3363a94ff6f2a9f7964d.zip |
Change SearchSysCache coding conventions so that a reference count is
maintained for each cache entry. A cache entry will not be freed until
the matching ReleaseSysCache call has been executed. This eliminates
worries about cache entries getting dropped while still in use. See
my posting to pg-hackers of even date for more info.
Diffstat (limited to 'src/backend/utils/cache/syscache.c')
-rw-r--r-- | src/backend/utils/cache/syscache.c | 187 |
1 files changed, 90 insertions, 97 deletions
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c index 7f35f192089..bb9a55b869a 100644 --- a/src/backend/utils/cache/syscache.c +++ b/src/backend/utils/cache/syscache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.56 2000/11/10 00:33:10 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.57 2000/11/16 22:30:33 tgl Exp $ * * NOTES * These routines allow the parser/planner/executor to perform @@ -343,7 +343,7 @@ static struct cachedesc cacheinfo[] = { }; static CatCache *SysCache[lengthof(cacheinfo)]; -static int32 SysCacheSize = lengthof(cacheinfo); +static int SysCacheSize = lengthof(cacheinfo); static bool CacheInitialized = false; @@ -355,98 +355,67 @@ IsCacheInitialized(void) /* - * zerocaches + * InitCatalogCache - initialize the caches * - * Make sure the SysCache structure is zero'd. + * Note that no database access is done here; we only allocate memory + * and initialize the cache structure. Interrogation of the database + * to complete initialization of a cache happens only upon first use + * of that cache. */ void -zerocaches() +InitCatalogCache(void) { - MemSet((char *) SysCache, 0, SysCacheSize * sizeof(CatCache *)); -} + int cacheId; + Assert(!CacheInitialized); -/* - * InitCatalogCache - initialize the caches - */ -void -InitCatalogCache() -{ - int cacheId; /* XXX type */ + MemSet((char *) SysCache, 0, sizeof(SysCache)); - if (!AMI_OVERRIDE) + for (cacheId = 0; cacheId < SysCacheSize; cacheId++) { - for (cacheId = 0; cacheId < SysCacheSize; cacheId += 1) - { - Assert(!PointerIsValid(SysCache[cacheId])); - - SysCache[cacheId] = InitSysCache(cacheId, - cacheinfo[cacheId].name, - cacheinfo[cacheId].indname, - cacheinfo[cacheId].nkeys, - cacheinfo[cacheId].key); - if (!PointerIsValid(SysCache[cacheId])) - { - elog(ERROR, - "InitCatalogCache: Can't init cache %s (%d)", - cacheinfo[cacheId].name, - cacheId); - } - - } + SysCache[cacheId] = InitCatCache(cacheId, + cacheinfo[cacheId].name, + cacheinfo[cacheId].indname, + cacheinfo[cacheId].nkeys, + cacheinfo[cacheId].key); + if (!PointerIsValid(SysCache[cacheId])) + elog(ERROR, "InitCatalogCache: Can't init cache %s (%d)", + cacheinfo[cacheId].name, cacheId); } CacheInitialized = true; } /* - * SearchSysCacheTuple + * SearchSysCache * - * A layer on top of SearchSysCache that does the initialization and + * A layer on top of SearchCatCache that does the initialization and * key-setting for you. * * Returns the cache copy of the tuple if one is found, NULL if not. - * The tuple is the 'cache' copy. - * - * CAUTION: The tuple that is returned must NOT be freed by the caller! + * The tuple is the 'cache' copy and must NOT be modified! * - * CAUTION: The returned tuple may be flushed from the cache during - * subsequent cache lookup operations, or by shared cache invalidation. - * Callers should not expect the pointer to remain valid for long. + * When the caller is done using the tuple, call ReleaseSysCache() + * to release the reference count grabbed by SearchSysCache(). If this + * is not done, the tuple will remain locked in cache until end of + * transaction, which is tolerable but not desirable. * - * XXX we ought to have some kind of referencecount mechanism for - * cache entries, to ensure entries aren't deleted while in use. + * CAUTION: The tuple that is returned must NOT be freed by the caller! */ HeapTuple -SearchSysCacheTuple(int cacheId,/* cache selection code */ - Datum key1, - Datum key2, - Datum key3, - Datum key4) +SearchSysCache(int cacheId, + Datum key1, + Datum key2, + Datum key3, + Datum key4) { - HeapTuple tp; - if (cacheId < 0 || cacheId >= SysCacheSize) { - elog(ERROR, "SearchSysCacheTuple: Bad cache id %d", cacheId); + elog(ERROR, "SearchSysCache: Bad cache id %d", cacheId); return (HeapTuple) NULL; } - Assert(AMI_OVERRIDE || PointerIsValid(SysCache[cacheId])); - - if (!PointerIsValid(SysCache[cacheId])) - { - SysCache[cacheId] = InitSysCache(cacheId, - cacheinfo[cacheId].name, - cacheinfo[cacheId].indname, - cacheinfo[cacheId].nkeys, - cacheinfo[cacheId].key); - if (!PointerIsValid(SysCache[cacheId])) - elog(ERROR, - "InitCatalogCache: Can't init cache %s(%d)", - cacheinfo[cacheId].name, - cacheId); - } + Assert(PointerIsValid(SysCache[cacheId])); /* * If someone tries to look up a relname, translate temp relation @@ -464,51 +433,75 @@ SearchSysCacheTuple(int cacheId,/* cache selection code */ key1 = CStringGetDatum(nontemp_relname); } - tp = SearchSysCache(SysCache[cacheId], key1, key2, key3, key4); - if (!HeapTupleIsValid(tp)) - { -#ifdef CACHEDEBUG - elog(DEBUG, - "SearchSysCacheTuple: Search %s(%d) %d %d %d %d failed", - cacheinfo[cacheId].name, - cacheId, key1, key2, key3, key4); -#endif - return (HeapTuple) NULL; - } - return tp; + return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4); } +/* + * ReleaseSysCache + * Release previously grabbed reference count on a tuple + */ +void +ReleaseSysCache(HeapTuple tuple) +{ + ReleaseCatCache(tuple); +} /* - * SearchSysCacheTupleCopy + * SearchSysCacheCopy * - * This is like SearchSysCacheTuple, except it returns a palloc'd copy of - * the tuple. The caller should heap_freetuple() the returned copy when - * done with it. This routine should be used when the caller intends to - * continue to access the tuple for more than a very short period of time. + * A convenience routine that does SearchSysCache and (if successful) + * returns a modifiable copy of the syscache entry. The original + * syscache entry is released before returning. The caller should + * heap_freetuple() the result when done with it. */ HeapTuple -SearchSysCacheTupleCopy(int cacheId, /* cache selection code */ - Datum key1, - Datum key2, - Datum key3, - Datum key4) +SearchSysCacheCopy(int cacheId, + Datum key1, + Datum key2, + Datum key3, + Datum key4) { - HeapTuple cachetup; - - cachetup = SearchSysCacheTuple(cacheId, key1, key2, key3, key4); - if (PointerIsValid(cachetup)) - return heap_copytuple(cachetup); - else - return cachetup; /* NULL */ + HeapTuple tuple, + newtuple; + + tuple = SearchSysCache(cacheId, key1, key2, key3, key4); + if (!HeapTupleIsValid(tuple)) + return tuple; + newtuple = heap_copytuple(tuple); + ReleaseSysCache(tuple); + return newtuple; } +/* + * GetSysCacheOid + * + * A convenience routine that does SearchSysCache and returns the OID + * of the found tuple, or InvalidOid if no tuple could be found. + * No lock is retained on the syscache entry. + */ +Oid +GetSysCacheOid(int cacheId, + Datum key1, + Datum key2, + Datum key3, + Datum key4) +{ + HeapTuple tuple; + Oid result; + + tuple = SearchSysCache(cacheId, key1, key2, key3, key4); + if (!HeapTupleIsValid(tuple)) + return InvalidOid; + result = tuple->t_data->t_oid; + ReleaseSysCache(tuple); + return result; +} /* * SysCacheGetAttr * - * Given a tuple previously fetched by SearchSysCacheTuple() or - * SearchSysCacheTupleCopy(), extract a specific attribute. + * Given a tuple previously fetched by SearchSysCache(), + * extract a specific attribute. * * This is equivalent to using heap_getattr() on a tuple fetched * from a non-cached relation. Usually, this is only used for attributes |