33 * inval.c
44 * POSTGRES cache invalidation dispatcher code.
55 *
6+ *This is subtle stuff, so pay attention:
7+ *
8+ *When a tuple is updated or deleted, our time qualification rules consider
9+ *that it is *still valid* so long as we are in the same command, ie,
10+ *until the next CommandCounterIncrement() or transaction commit.
11+ *(See utils/time/tqual.c.) At the command boundary, the old tuple stops
12+ *being valid and the new version, if any, becomes valid. Therefore,
13+ *we cannot simply flush a tuple from the system caches during heap_update()
14+ *or heap_delete(). The tuple is still good at that point; what's more,
15+ *even if we did flush it, it might be reloaded into the caches by a later
16+ *request in the same command. So the correct behavior is to keep a list
17+ *of outdated (updated/deleted) tuples and then do the required cache
18+ *flushes at the next command boundary. Similarly, we need a list of
19+ *inserted tuples (including new versions of updated tuples), which we will
20+ *use to flush those tuples out of the caches if we abort the transaction.
21+ *Notice that the first list lives only till command boundary, whereas the
22+ *second lives till end of transaction. Finally, we need a third list of
23+ *all tuples outdated in the current transaction; if we commit, we send
24+ *those invalidation events to all other backends (via the SI message queue)
25+ *so that they can flush obsolete entries from their caches.
26+ *
27+ *We do not need to register EVERY tuple operation in this way, just those
28+ *on tuples in relations that have associated catcaches. Also, whenever
29+ *we see an operation on a pg_class or pg_attribute tuple, we register
30+ *a relcache flush operation for the relation described by that tuple.
31+ *
32+ *
633 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
734 * Portions Copyright (c) 1994, Regents of the University of California
835 *
9- *
1036 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/utils/cache/inval.c,v 1.38 2000/11/08 22:10:01 tgl Exp $
37+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/inval.c,v 1.39 2001/01/05 22:54:37 tgl Exp $
1238 *
13- * Note - this code is real crufty...
39+ * Note - this code is real crufty... badly needs a rewrite to improve
40+ * readability and portability. (Shouldn't assume Oid == Index, for example)
1441 *
1542 *-------------------------------------------------------------------------
1643 */
@@ -82,7 +109,8 @@ typedef InvalidationMessageData *InvalidationMessage;
82109 * ----------------
83110 *Invalidation info is divided into three parts.
84111 *1) shared invalidation to be registered for all backends
85- *2) local invalidation for the transaction itself
112+ *2) local invalidation for the transaction itself (actually, just
113+ * for the current command within the transaction)
86114 *3) rollback information for the transaction itself (in case we abort)
87115 * ----------------
88116 */
@@ -107,7 +135,9 @@ static LocalInvalid RollbackStack = EmptyLocalInvalid;
107135
108136
109137static InvalidationEntry InvalidationEntryAllocate (uint16 size );
110- static void LocalInvalidInvalidate (LocalInvalid invalid ,void (* function ) (),bool freemember );
138+ static void LocalInvalidInvalidate (LocalInvalid invalid ,
139+ void (* function ) (InvalidationMessage ),
140+ bool freemember );
111141static LocalInvalid LocalInvalidRegister (LocalInvalid invalid ,
112142InvalidationEntry entry );
113143static void DiscardInvalidStack (LocalInvalid * invalid );
@@ -161,7 +191,7 @@ LocalInvalidRegister(LocalInvalid invalid,
161191 */
162192static void
163193LocalInvalidInvalidate (LocalInvalid invalid ,
164- void (* function ) (),
194+ void (* function ) (InvalidationMessage ),
165195bool freemember )
166196{
167197InvalidationEntryData * entryDataP ;
@@ -172,7 +202,7 @@ LocalInvalidInvalidate(LocalInvalid invalid,
172202& ((InvalidationUserData * )invalid )-> dataP [-1 ];
173203
174204if (PointerIsValid (function ))
175- (* function ) ((Pointer )& entryDataP -> userData );
205+ (* function ) ((InvalidationMessage )& entryDataP -> userData );
176206
177207invalid = (Pointer )entryDataP -> nextP ;
178208
@@ -193,7 +223,9 @@ DiscardInvalidStack(LocalInvalid *invalid)
193223locinv = * invalid ;
194224* invalid = EmptyLocalInvalid ;
195225if (locinv )
196- LocalInvalidInvalidate (locinv , (void (* ) ())NULL , true);
226+ LocalInvalidInvalidate (locinv ,
227+ (void (* ) (InvalidationMessage ))NULL ,
228+ true);
197229}
198230
199231/* ----------------------------------------------------------------
@@ -269,7 +301,7 @@ CacheIdRegisterSpecifiedLocalInvalid(LocalInvalid invalid,
269301 * --------------------------------
270302 */
271303static void
272- CacheIdRegisterLocalInvalid (Index cacheId ,
304+ CacheIdRegisterLocalInvalid (int cacheId ,
273305Index hashIndex ,
274306ItemPointer pointer )
275307{
@@ -298,7 +330,8 @@ CacheIdRegisterLocalInvalid(Index cacheId,
298330 * --------------------------------
299331 */
300332static void
301- CacheIdRegisterLocalRollback (Index cacheId ,Index hashIndex ,
333+ CacheIdRegisterLocalRollback (int cacheId ,
334+ Index hashIndex ,
302335ItemPointer pointer )
303336{
304337
@@ -477,7 +510,7 @@ CacheIdInvalidate(Index cacheId,
477510 * --------------------------------
478511 */
479512static void
480- ResetSystemCaches ()
513+ ResetSystemCaches (void )
481514{
482515ResetSystemCache ();
483516RelationCacheInvalidate ();
@@ -585,13 +618,13 @@ InvalidationMessageCacheInvalidate(InvalidationMessage message)
585618}
586619
587620/* --------------------------------
588- *RelationInvalidateRelationCache
621+ *PrepareToInvalidateRelationCache
589622 * --------------------------------
590623 */
591624static void
592- RelationInvalidateRelationCache (Relation relation ,
593- HeapTuple tuple ,
594- void (* function ) ())
625+ PrepareToInvalidateRelationCache (Relation relation ,
626+ HeapTuple tuple ,
627+ void (* function ) (Oid , Oid ))
595628{
596629Oid relationId ;
597630Oid objectId ;
@@ -614,7 +647,7 @@ RelationInvalidateRelationCache(Relation relation,
614647return ;
615648
616649/* ----------------
617- * can't handle immediate relation descriptor invalidation
650+ *register the relcache-invalidation action in the appropriate list
618651 * ----------------
619652 */
620653Assert (PointerIsValid (function ));
@@ -629,11 +662,9 @@ RelationInvalidateRelationCache(Relation relation,
629662 *
630663 * Note:
631664 *This should be called as the first step in processing a transaction.
632- *This should be called while waiting for a query from the front end
633- *when other backends are active.
634665 */
635666void
636- DiscardInvalid ()
667+ DiscardInvalid (void )
637668{
638669/* ----------------
639670 *debugging stuff
@@ -694,7 +725,8 @@ RegisterInvalid(bool send)
694725 *Causes invalidation immediately for the next command of the transaction.
695726 *
696727 * Note:
697- *This should be called in time of CommandCounterIncrement().
728+ *This should be called during CommandCounterIncrement(),
729+ *after we have advanced the command ID.
698730 */
699731void
700732ImmediateLocalInvalidation (bool send )
@@ -735,28 +767,29 @@ ImmediateLocalInvalidation(bool send)
735767}
736768
737769/*
738- *InvokeHeapTupleInvalidation
770+ *PrepareForTupleInvalidation
739771 *Invoke functions for the tuple which register invalidation
740772 *of catalog/relation cache.
741773 *Note:
742774 *Assumes object id is valid.
743775 *Assumes tuple is valid.
744776 */
745777#ifdef INVALIDDEBUG
746- #define InvokeHeapTupleInvalidation_DEBUG1 \
778+ #define PrepareForTupleInvalidation_DEBUG1 \
747779elog(DEBUG, "%s(%s, [%d,%d])", \
748780 funcname,\
749781 RelationGetPhysicalRelationName(relation), \
750782 ItemPointerGetBlockNumber(&tuple->t_self), \
751783 ItemPointerGetOffsetNumber(&tuple->t_self))
752784#else
753- #define InvokeHeapTupleInvalidation_DEBUG1
785+ #define PrepareForTupleInvalidation_DEBUG1
754786#endif /* defined(INVALIDDEBUG) */
755787
756788static void
757- InvokeHeapTupleInvalidation (Relation relation ,HeapTuple tuple ,
758- void (* CacheIdRegisterFunc ) (),
759- void (* RelationIdRegisterFunc ) (),
789+ PrepareForTupleInvalidation (Relation relation ,HeapTuple tuple ,
790+ void (* CacheIdRegisterFunc ) (int ,Index ,
791+ ItemPointer ),
792+ void (* RelationIdRegisterFunc ) (Oid ,Oid ),
760793const char * funcname )
761794{
762795/* ----------------
@@ -768,8 +801,11 @@ InvokeHeapTupleInvalidation(Relation relation, HeapTuple tuple,
768801
769802if (IsBootstrapProcessingMode ())
770803return ;
804+
771805/* ----------------
772- *this only works for system relations now
806+ *We only need to worry about invalidation for tuples that are in
807+ *system relations; user-relation tuples are never in catcaches
808+ *and can't affect the relcache either.
773809 * ----------------
774810 */
775811if (!IsSystemRelationName (NameStr (RelationGetForm (relation )-> relname )))
@@ -779,37 +815,38 @@ InvokeHeapTupleInvalidation(Relation relation, HeapTuple tuple,
779815 *debugging stuff
780816 * ----------------
781817 */
782- InvokeHeapTupleInvalidation_DEBUG1 ;
818+ PrepareForTupleInvalidation_DEBUG1 ;
783819
784- RelationInvalidateCatalogCacheTuple (relation ,tuple ,
785- CacheIdRegisterFunc );
820+ PrepareToInvalidateCacheTuple (relation ,tuple ,
821+ CacheIdRegisterFunc );
786822
787- RelationInvalidateRelationCache (relation ,tuple ,
788- RelationIdRegisterFunc );
823+ PrepareToInvalidateRelationCache (relation ,tuple ,
824+ RelationIdRegisterFunc );
789825}
790826
791827/*
792828 * RelationInvalidateHeapTuple
793- *Causes the given tuple in a relation to be invalidated.
829+ *Register the given tuple for invalidation at end of command
830+ *(ie, current command is outdating this tuple).
794831 */
795832void
796833RelationInvalidateHeapTuple (Relation relation ,HeapTuple tuple )
797834{
798- InvokeHeapTupleInvalidation (relation ,tuple ,
835+ PrepareForTupleInvalidation (relation ,tuple ,
799836CacheIdRegisterLocalInvalid ,
800837RelationIdRegisterLocalInvalid ,
801838"RelationInvalidateHeapTuple" );
802839}
803840
804841/*
805842 * RelationMark4RollbackHeapTuple
806- *keep the given tuplein a relation to be invalidated
807- *in case of abort .
843+ *Register the given tuplefor invalidation in case of abort
844+ *(ie, current command is creating this tuple) .
808845 */
809846void
810847RelationMark4RollbackHeapTuple (Relation relation ,HeapTuple tuple )
811848{
812- InvokeHeapTupleInvalidation (relation ,tuple ,
849+ PrepareForTupleInvalidation (relation ,tuple ,
813850CacheIdRegisterLocalRollback ,
814851RelationIdRegisterLocalRollback ,
815852"RelationMark4RollbackHeapTuple" );