Commit 81d08fcf authored by Tom Lane's avatar Tom Lane

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.
parent 2fb6cc90
......@@ -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.
* ----------------
*/
......
......@@ -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");
......
......@@ -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));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment