OSDN Git Service

Rename and document some invalidation routines to make it clearer that
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 5 Jan 2001 22:54:37 +0000 (22:54 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 5 Jan 2001 22:54:37 +0000 (22:54 +0000)
they don't themselves flush any cache entries, only add to to-do lists
that will be processed later.

src/backend/utils/cache/catcache.c
src/backend/utils/cache/inval.c
src/include/utils/catcache.h

index 3e1c428..d8e31f3 100644 (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.
         * ----------------
         */
 
index 8f4fd62..37f2c84 100644 (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");
index 70c988c..a24307b 100644 (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));