Rename and document some invalidation routines to make it clearer that

they don't themselves flush any cache entries, only add to to-do lists
that will be processed later.
This commit is contained in:
Tom Lane 2001-01-05 22:54:37 +00:00
parent 2fb6cc9045
commit 81d08fcffe
3 changed files with 106 additions and 50 deletions

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.73 2000/11/24 04:16:12 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.74 2001/01/05 22:54:37 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1047,17 +1047,36 @@ ReleaseCatCache(HeapTuple tuple)
}
/* --------------------------------
* RelationInvalidateCatalogCacheTuple()
* PrepareToInvalidateCacheTuple()
*
* 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.
* This is part of a rather subtle chain of events, so pay attention:
*
* When a tuple is updated or deleted, it cannot be flushed from the
* catcaches immediately, for reasons explained at the top of inval.c.
* Instead we have to add entry(s) for the tuple to a list of pending tuple
* invalidations that will be done at the end of the command or transaction.
*
* The lists of tuples that need to be flushed are kept by inval.c. This
* routine is a helper routine for inval.c. Given a tuple belonging to
* the specified relation, find all catcaches it could be in, compute the
* correct hashindex for each such catcache, and call the specified function
* to record the cache id, hashindex, and tuple ItemPointer in inval.c's
* lists. CatalogCacheIdInvalidate will be called later, if appropriate,
* using the recorded information.
*
* Note that it is irrelevant whether the given tuple is actually loaded
* into the catcache at the moment. Even if it's not there now, it might
* be by the end of the command, so we have to be prepared to flush it.
*
* Also note that it's not an error if there are no catcaches for the
* specified relation. inval.c doesn't know exactly which rels have
* catcaches --- it will call this routine for any tuple that's in a
* system relation.
* --------------------------------
*/
void
RelationInvalidateCatalogCacheTuple(Relation relation,
HeapTuple tuple,
PrepareToInvalidateCacheTuple(Relation relation,
HeapTuple tuple,
void (*function) (int, Index, ItemPointer))
{
CatCache *ccp;
@ -1069,13 +1088,13 @@ RelationInvalidateCatalogCacheTuple(Relation relation,
Assert(RelationIsValid(relation));
Assert(HeapTupleIsValid(tuple));
Assert(PointerIsValid(function));
CACHE1_elog(DEBUG, "RelationInvalidateCatalogCacheTuple: called");
CACHE1_elog(DEBUG, "PrepareToInvalidateCacheTuple: called");
/* ----------------
* for each cache
* if the cache contains tuples from the specified relation
* call the invalidation function on the tuples
* in the proper hash bucket
* compute the tuple's hash index in this cache,
* and call the passed function to register the information.
* ----------------
*/

View File

@ -3,14 +3,41 @@
* inval.c
* POSTGRES cache invalidation dispatcher code.
*
* This is subtle stuff, so pay attention:
*
* When a tuple is updated or deleted, our time qualification rules consider
* that it is *still valid* so long as we are in the same command, ie,
* until the next CommandCounterIncrement() or transaction commit.
* (See utils/time/tqual.c.) At the command boundary, the old tuple stops
* being valid and the new version, if any, becomes valid. Therefore,
* we cannot simply flush a tuple from the system caches during heap_update()
* or heap_delete(). The tuple is still good at that point; what's more,
* even if we did flush it, it might be reloaded into the caches by a later
* request in the same command. So the correct behavior is to keep a list
* of outdated (updated/deleted) tuples and then do the required cache
* flushes at the next command boundary. Similarly, we need a list of
* inserted tuples (including new versions of updated tuples), which we will
* use to flush those tuples out of the caches if we abort the transaction.
* Notice that the first list lives only till command boundary, whereas the
* second lives till end of transaction. Finally, we need a third list of
* all tuples outdated in the current transaction; if we commit, we send
* those invalidation events to all other backends (via the SI message queue)
* so that they can flush obsolete entries from their caches.
*
* We do not need to register EVERY tuple operation in this way, just those
* on tuples in relations that have associated catcaches. Also, whenever
* we see an operation on a pg_class or pg_attribute tuple, we register
* a relcache flush operation for the relation described by that tuple.
*
*
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/inval.c,v 1.38 2000/11/08 22:10:01 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/cache/inval.c,v 1.39 2001/01/05 22:54:37 tgl Exp $
*
* Note - this code is real crufty...
* Note - this code is real crufty... badly needs a rewrite to improve
* readability and portability. (Shouldn't assume Oid == Index, for example)
*
*-------------------------------------------------------------------------
*/
@ -82,7 +109,8 @@ typedef InvalidationMessageData *InvalidationMessage;
* ----------------
* Invalidation info is divided into three parts.
* 1) shared invalidation to be registered for all backends
* 2) local invalidation for the transaction itself
* 2) local invalidation for the transaction itself (actually, just
* for the current command within the transaction)
* 3) rollback information for the transaction itself (in case we abort)
* ----------------
*/
@ -107,7 +135,9 @@ static LocalInvalid RollbackStack = EmptyLocalInvalid;
static InvalidationEntry InvalidationEntryAllocate(uint16 size);
static void LocalInvalidInvalidate(LocalInvalid invalid, void (*function) (), bool freemember);
static void LocalInvalidInvalidate(LocalInvalid invalid,
void (*function) (InvalidationMessage),
bool freemember);
static LocalInvalid LocalInvalidRegister(LocalInvalid invalid,
InvalidationEntry entry);
static void DiscardInvalidStack(LocalInvalid *invalid);
@ -161,7 +191,7 @@ LocalInvalidRegister(LocalInvalid invalid,
*/
static void
LocalInvalidInvalidate(LocalInvalid invalid,
void (*function) (),
void (*function) (InvalidationMessage),
bool freemember)
{
InvalidationEntryData *entryDataP;
@ -172,7 +202,7 @@ LocalInvalidInvalidate(LocalInvalid invalid,
&((InvalidationUserData *) invalid)->dataP[-1];
if (PointerIsValid(function))
(*function) ((Pointer) &entryDataP->userData);
(*function) ((InvalidationMessage) &entryDataP->userData);
invalid = (Pointer) entryDataP->nextP;
@ -193,7 +223,9 @@ DiscardInvalidStack(LocalInvalid *invalid)
locinv = *invalid;
*invalid = EmptyLocalInvalid;
if (locinv)
LocalInvalidInvalidate(locinv, (void (*) ()) NULL, true);
LocalInvalidInvalidate(locinv,
(void (*) (InvalidationMessage)) NULL,
true);
}
/* ----------------------------------------------------------------
@ -269,7 +301,7 @@ CacheIdRegisterSpecifiedLocalInvalid(LocalInvalid invalid,
* --------------------------------
*/
static void
CacheIdRegisterLocalInvalid(Index cacheId,
CacheIdRegisterLocalInvalid(int cacheId,
Index hashIndex,
ItemPointer pointer)
{
@ -298,7 +330,8 @@ CacheIdRegisterLocalInvalid(Index cacheId,
* --------------------------------
*/
static void
CacheIdRegisterLocalRollback(Index cacheId, Index hashIndex,
CacheIdRegisterLocalRollback(int cacheId,
Index hashIndex,
ItemPointer pointer)
{
@ -477,7 +510,7 @@ CacheIdInvalidate(Index cacheId,
* --------------------------------
*/
static void
ResetSystemCaches()
ResetSystemCaches(void)
{
ResetSystemCache();
RelationCacheInvalidate();
@ -585,13 +618,13 @@ InvalidationMessageCacheInvalidate(InvalidationMessage message)
}
/* --------------------------------
* RelationInvalidateRelationCache
* PrepareToInvalidateRelationCache
* --------------------------------
*/
static void
RelationInvalidateRelationCache(Relation relation,
HeapTuple tuple,
void (*function) ())
PrepareToInvalidateRelationCache(Relation relation,
HeapTuple tuple,
void (*function) (Oid, Oid))
{
Oid relationId;
Oid objectId;
@ -614,7 +647,7 @@ RelationInvalidateRelationCache(Relation relation,
return;
/* ----------------
* can't handle immediate relation descriptor invalidation
* register the relcache-invalidation action in the appropriate list
* ----------------
*/
Assert(PointerIsValid(function));
@ -629,11 +662,9 @@ RelationInvalidateRelationCache(Relation relation,
*
* Note:
* This should be called as the first step in processing a transaction.
* This should be called while waiting for a query from the front end
* when other backends are active.
*/
void
DiscardInvalid()
DiscardInvalid(void)
{
/* ----------------
* debugging stuff
@ -694,7 +725,8 @@ RegisterInvalid(bool send)
* Causes invalidation immediately for the next command of the transaction.
*
* Note:
* This should be called in time of CommandCounterIncrement().
* This should be called during CommandCounterIncrement(),
* after we have advanced the command ID.
*/
void
ImmediateLocalInvalidation(bool send)
@ -735,7 +767,7 @@ ImmediateLocalInvalidation(bool send)
}
/*
* InvokeHeapTupleInvalidation
* PrepareForTupleInvalidation
* Invoke functions for the tuple which register invalidation
* of catalog/relation cache.
* Note:
@ -743,20 +775,21 @@ ImmediateLocalInvalidation(bool send)
* Assumes tuple is valid.
*/
#ifdef INVALIDDEBUG
#define InvokeHeapTupleInvalidation_DEBUG1 \
#define PrepareForTupleInvalidation_DEBUG1 \
elog(DEBUG, "%s(%s, [%d,%d])", \
funcname,\
RelationGetPhysicalRelationName(relation), \
ItemPointerGetBlockNumber(&tuple->t_self), \
ItemPointerGetOffsetNumber(&tuple->t_self))
#else
#define InvokeHeapTupleInvalidation_DEBUG1
#define PrepareForTupleInvalidation_DEBUG1
#endif /* defined(INVALIDDEBUG) */
static void
InvokeHeapTupleInvalidation(Relation relation, HeapTuple tuple,
void (*CacheIdRegisterFunc) (),
void (*RelationIdRegisterFunc) (),
PrepareForTupleInvalidation(Relation relation, HeapTuple tuple,
void (*CacheIdRegisterFunc) (int, Index,
ItemPointer),
void (*RelationIdRegisterFunc) (Oid, Oid),
const char *funcname)
{
/* ----------------
@ -768,8 +801,11 @@ InvokeHeapTupleInvalidation(Relation relation, HeapTuple tuple,
if (IsBootstrapProcessingMode())
return;
/* ----------------
* this only works for system relations now
* We only need to worry about invalidation for tuples that are in
* system relations; user-relation tuples are never in catcaches
* and can't affect the relcache either.
* ----------------
*/
if (!IsSystemRelationName(NameStr(RelationGetForm(relation)->relname)))
@ -779,23 +815,24 @@ InvokeHeapTupleInvalidation(Relation relation, HeapTuple tuple,
* debugging stuff
* ----------------
*/
InvokeHeapTupleInvalidation_DEBUG1;
PrepareForTupleInvalidation_DEBUG1;
RelationInvalidateCatalogCacheTuple(relation, tuple,
CacheIdRegisterFunc);
PrepareToInvalidateCacheTuple(relation, tuple,
CacheIdRegisterFunc);
RelationInvalidateRelationCache(relation, tuple,
RelationIdRegisterFunc);
PrepareToInvalidateRelationCache(relation, tuple,
RelationIdRegisterFunc);
}
/*
* RelationInvalidateHeapTuple
* Causes the given tuple in a relation to be invalidated.
* Register the given tuple for invalidation at end of command
* (ie, current command is outdating this tuple).
*/
void
RelationInvalidateHeapTuple(Relation relation, HeapTuple tuple)
{
InvokeHeapTupleInvalidation(relation, tuple,
PrepareForTupleInvalidation(relation, tuple,
CacheIdRegisterLocalInvalid,
RelationIdRegisterLocalInvalid,
"RelationInvalidateHeapTuple");
@ -803,13 +840,13 @@ RelationInvalidateHeapTuple(Relation relation, HeapTuple tuple)
/*
* RelationMark4RollbackHeapTuple
* keep the given tuple in a relation to be invalidated
* in case of abort.
* Register the given tuple for invalidation in case of abort
* (ie, current command is creating this tuple).
*/
void
RelationMark4RollbackHeapTuple(Relation relation, HeapTuple tuple)
{
InvokeHeapTupleInvalidation(relation, tuple,
PrepareForTupleInvalidation(relation, tuple,
CacheIdRegisterLocalRollback,
RelationIdRegisterLocalRollback,
"RelationMark4RollbackHeapTuple");

View File

@ -13,7 +13,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: catcache.h,v 1.29 2000/11/24 04:16:11 tgl Exp $
* $Id: catcache.h,v 1.30 2001/01/05 22:54:37 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -95,7 +95,7 @@ extern void ResetSystemCache(void);
extern void SystemCacheRelationFlushed(Oid relId);
extern void CatalogCacheIdInvalidate(int cacheId, Index hashIndex,
ItemPointer pointer);
extern void RelationInvalidateCatalogCacheTuple(Relation relation,
extern void PrepareToInvalidateCacheTuple(Relation relation,
HeapTuple tuple,
void (*function) (int, Index, ItemPointer));