]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Improve cache invalidation handling. Eespecially
authorHiroshi Inoue <inoue@tpf.co.jp>
Mon, 10 Jan 2000 06:30:56 +0000 (06:30 +0000)
committerHiroshi Inoue <inoue@tpf.co.jp>
Mon, 10 Jan 2000 06:30:56 +0000 (06:30 +0000)
this would fix TODO
* elog() flushes cache, try invalidating just entries from
  current xact, perhaps using invalidation cache

src/backend/access/heap/heapam.c
src/backend/access/transam/xact.c
src/backend/storage/smgr/md.c
src/backend/utils/cache/inval.c
src/include/utils/inval.h

index 9ff1525b88cf9da390476ff721102e60e2f684fe..4b7c4096222974b251b99e05bd154748609d0cdc 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.62 1999/12/21 00:06:40 wieck Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.63 2000/01/10 06:30:50 inoue Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -1262,7 +1262,7 @@ heap_insert(Relation relation, HeapTuple tup)
        RelationPutHeapTupleAtEnd(relation, tup);
 
        if (IsSystemRelationName(RelationGetRelationName(relation)))
-               RelationInvalidateHeapTuple(relation, tup);
+               RelationMark4RollbackHeapTuple(relation, tup);
 
        return tup->t_data->t_oid;
 }
@@ -1473,6 +1473,8 @@ l2:
                RelationPutHeapTupleAtEnd(relation, newtup);
                LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
        }
+       /* mark for rollback caches */
+       RelationMark4RollbackHeapTuple(relation, newtup);
 
        /*
         * New item in place, now record address of new tuple in t_ctid of old
index d3a81e647bf9e4b9bb7ed0c2079719eee362a056..483a52d441ec8325b2f3d790c34006accba89f84 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.57 2000/01/05 18:23:44 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.58 2000/01/10 06:30:50 inoue Exp $
  *
  * NOTES
  *             Transaction aborts can now occur two ways:
@@ -165,6 +165,7 @@ static void AtAbort_Cache(void);
 static void AtAbort_Locks(void);
 static void AtAbort_Memory(void);
 static void AtCommit_Cache(void);
+static void AtCommit_LocalCache(void);
 static void AtCommit_Locks(void);
 static void AtCommit_Memory(void);
 static void AtStart_Cache(void);
@@ -512,8 +513,11 @@ CommandCounterIncrement()
 
        CurrentTransactionStateData.scanCommandId = CurrentTransactionStateData.commandId;
 
-       /* make cache changes visible to me */
-       AtCommit_Cache();
+       /*
+        * make cache changes visible to me.  AtCommit_LocalCache()
+        * instead of AtCommit_Cache() is called here.
+        */
+       AtCommit_LocalCache();
        AtStart_Cache();
 
 }
@@ -663,15 +667,26 @@ static void
 AtCommit_Cache()
 {
        /* ----------------
-        * Make catalog changes visible to me for the next command.
-        * Other backends will not process my invalidation messages until
-        * after I commit and free my locks--though they will do
-        * unnecessary work if I abort.
+        * Make catalog changes visible to all backend.
         * ----------------
         */
        RegisterInvalid(true);
 }
 
+/* --------------------------------
+ *             AtCommit_LocalCache
+ * --------------------------------
+ */
+static void
+AtCommit_LocalCache()
+{
+       /* ----------------
+        * Make catalog changes visible to me for the next command.
+        * ----------------
+        */
+       ImmediateLocalInvalidation(true);
+}
+
 /* --------------------------------
  *             AtCommit_Locks
  * --------------------------------
index 0cf2893d79c4aad5d73616c242bf2f22ca4ace9b..af887c95ca7aaee3b0598ba74cb37df8d5b47780 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.60 1999/11/16 04:13:56 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.61 2000/01/10 06:30:51 inoue Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,6 +20,7 @@
 #include "catalog/catalog.h"
 #include "miscadmin.h"
 #include "storage/smgr.h"
+#include "utils/inval.h"       /* ImmediateSharedRelationCacheInvalidate() */
 
 #undef DIAGNOSTIC
 
@@ -203,6 +204,15 @@ mdunlink(Relation reln)
         */
        if (reln->rd_unlinked && reln->rd_fd < 0)
                return SM_SUCCESS;
+       /*
+        * This call isn't good for independency of md stuff,but 
+        * mdunlink() unlinks the base file immediately and couldn't
+        * be rollbacked in case of abort. We must guarantee all
+        * backends' relation cache invalidation here.
+        * This would be unnecessary if unlinking is postponed
+        * till end of transaction.
+        */
+       ImmediateSharedRelationCacheInvalidate(reln);
        /*
         * Force all segments of the relation to be opened, so that we
         * won't miss deleting any of them.
@@ -779,6 +789,7 @@ mdtruncate(Relation reln, int nblocks)
 #ifndef LET_OS_MANAGE_FILESIZE
        MemoryContext oldcxt;
        int                     priorblocks;
+       bool    invalregistered = false;
 #endif
 
        /* NOTE: mdnblocks makes sure we have opened all existing segments,
@@ -810,6 +821,20 @@ mdtruncate(Relation reln, int nblocks)
                         * a big file...
                         */
                        FileTruncate(v->mdfd_vfd, 0);
+                       /*
+                        * To call ImmediateSharedRelationCacheInvalidate() here
+                        * isn't good for independency of md stuff,but smgrunlink()
+                        * removes the base file immediately and couldn't be
+                        * rollbacked in case of abort. We must guarantee
+                        * all backends' relation cache invalidation here.
+                        * This would be unnecessary if the truncation is postponed
+                        * till end of transaction.
+                        */
+                       if (!invalregistered)
+                       {
+                               ImmediateSharedRelationCacheInvalidate(reln);
+                               invalregistered = true;
+                       }
                        FileUnlink(v->mdfd_vfd);
                        v = v->mdfd_chain;
                        Assert(ov != &Md_fdvec[fd]); /* we never drop the 1st segment */
index d89a1f678a48afcfea20b6ca5769f16736ce4fb6..a0224f516782cb4d84c244957e17710c3661365e 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/cache/inval.c,v 1.30 1999/11/21 01:58:22 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/cache/inval.c,v 1.31 2000/01/10 06:30:53 inoue Exp $
  *
  * Note - this code is real crufty...
  *
@@ -79,13 +79,39 @@ typedef InvalidationMessageData *InvalidationMessage;
  *             variables and macros
  * ----------------
  */
-static LocalInvalid Invalid = EmptyLocalInvalid;       /* head of linked list */
+
+/*
+ * ----------------
+ *     Invalidation info was devided into three parts.
+ *     1) shared invalidation to be registerd for all backends
+ *     2) local invalidation for the transaction itself
+ *     3) rollback information for the transaction itself
+ * ----------------
+ */
+
+/*
+ * head of invalidation linked list for all backends
+ * eaten by AtCommit_Cache() in CommitTransaction()
+ */
+static LocalInvalid InvalidForall = EmptyLocalInvalid;
+/*
+ * head of invalidation linked list for the backend itself
+ * eaten by AtCommit_LocalCache() in CommandCounterIncrement()
+ */
+static LocalInvalid InvalidLocal = EmptyLocalInvalid;
+/*
+ * head of rollback linked list for the backend itself
+ * eaten by AtAbort_Cache() in AbortTransaction()
+ */
+static LocalInvalid RollbackStack = EmptyLocalInvalid;
 
 
 static InvalidationEntry InvalidationEntryAllocate(uint16 size);
-static void LocalInvalidInvalidate(LocalInvalid invalid, void (*function) ());
+static void LocalInvalidInvalidate(LocalInvalid invalid, void (*function) (), bool freemember);
 static LocalInvalid LocalInvalidRegister(LocalInvalid invalid,
                                                                                 InvalidationEntry entry);
+static void DiscardInvalidStack(LocalInvalid *invalid);
+static void InvalidationMessageRegisterSharedInvalid(InvalidationMessage message);
 
 
 /* ----------------------------------------------------------------
@@ -130,11 +156,11 @@ LocalInvalidRegister(LocalInvalid invalid,
 /* --------------------------------
  *             LocalInvalidInvalidate
  *                             Processes, then frees all entries in a local cache
- *                             invalidation list.
+ *                             invalidation list unless freemember parameter is false.
  * --------------------------------
  */
 static void
-LocalInvalidInvalidate(LocalInvalid invalid, void (*function) ())
+LocalInvalidInvalidate(LocalInvalid invalid, void (*function) (), bool freemember)
 {
        InvalidationEntryData *entryDataP;
 
@@ -148,6 +174,8 @@ LocalInvalidInvalidate(LocalInvalid invalid, void (*function) ())
 
                invalid = (Pointer) entryDataP->nextP;
 
+               if (!freemember)
+                       continue;
                /* help catch errors */
                entryDataP->nextP = (InvalidationUserData *) NULL;
 
@@ -155,27 +183,147 @@ LocalInvalidInvalidate(LocalInvalid invalid, void (*function) ())
        }
 }
 
+static void
+DiscardInvalidStack(LocalInvalid *invalid)
+{
+       LocalInvalid    locinv;
+
+       locinv = *invalid;
+       *invalid = EmptyLocalInvalid;
+       if (locinv)
+               LocalInvalidInvalidate(locinv, (void (*)()) NULL, true);
+}
+
 /* ----------------------------------------------------------------
  *                                       private support functions
  * ----------------------------------------------------------------
  */
 /* --------------------------------
- *             CacheIdRegisterLocalInvalid
+ *             CacheIdRegister.......
+ *             RelationIdRegister....
  * --------------------------------
  */
 #ifdef INVALIDDEBUG
+#define CacheIdRegisterSpecifiedLocalInvalid_DEBUG1 \
+elog(DEBUG, "CacheIdRegisterSpecifiedLocalInvalid(%d, %d, [%d, %d])", \
+        cacheId, hashIndex, ItemPointerGetBlockNumber(pointer), \
+        ItemPointerGetOffsetNumber(pointer))
 #define CacheIdRegisterLocalInvalid_DEBUG1 \
 elog(DEBUG, "CacheIdRegisterLocalInvalid(%d, %d, [%d, %d])", \
         cacheId, hashIndex, ItemPointerGetBlockNumber(pointer), \
         ItemPointerGetOffsetNumber(pointer))
+#define CacheIdRegisterLocalRollback_DEBUG1 \
+elog(DEBUG, "CacheIdRegisterLocalRollback(%d, %d, [%d, %d])", \
+        cacheId, hashIndex, ItemPointerGetBlockNumber(pointer), \
+        ItemPointerGetOffsetNumber(pointer))
+#define CacheIdImmediateRegisterSharedInvalid_DEBUG1 \
+elog(DEBUG, "CacheIdImmediateRegisterSharedInvalid(%d, %d, [%d, %d])", \
+        cacheId, hashIndex, ItemPointerGetBlockNumber(pointer), \
+        ItemPointerGetOffsetNumber(pointer))
 #else
+#define CacheIdRegisterSpecifiedLocalInvalid_DEBUG1
 #define CacheIdRegisterLocalInvalid_DEBUG1
+#define CacheIdRegisterLocalRollback_DEBUG1
+#define CacheIdImmediateRegisterSharedInvalid_DEBUG1
 #endif  /* INVALIDDEBUG */
 
+/* --------------------------------
+ *             CacheIdRegisterSpecifiedLocalInvalid
+ * --------------------------------
+ */
+static LocalInvalid
+CacheIdRegisterSpecifiedLocalInvalid(LocalInvalid invalid,
+               Index cacheId, Index hashIndex, ItemPointer pointer)
+{
+       InvalidationMessage message;
+
+       /* ----------------
+        *      debugging stuff
+        * ----------------
+        */
+       CacheIdRegisterSpecifiedLocalInvalid_DEBUG1;
+
+       /* ----------------
+        *      create a message describing the system catalog tuple
+        *      we wish to invalidate.
+        * ----------------
+        */
+       message = (InvalidationMessage)
+               InvalidationEntryAllocate(sizeof(InvalidationMessageData));
+
+       message->kind = 'c';
+       message->any.catalog.cacheId = cacheId;
+       message->any.catalog.hashIndex = hashIndex;
+
+       ItemPointerCopy(pointer, &message->any.catalog.pointerData);
+
+       /* ----------------
+        *      Add message to linked list of unprocessed messages.
+        * ----------------
+        */
+       invalid = LocalInvalidRegister(invalid, (InvalidationEntry) message);
+       return invalid;
+}
+
+/* --------------------------------
+ *             CacheIdRegisterLocalInvalid
+ * --------------------------------
+ */
 static void
 CacheIdRegisterLocalInvalid(Index cacheId,
                                                        Index hashIndex,
                                                        ItemPointer pointer)
+{
+       /* ----------------
+        *      debugging stuff
+        * ----------------
+        */
+       CacheIdRegisterLocalInvalid_DEBUG1;
+
+       /* ----------------
+        *      Add message to InvalidForall linked list.
+        * ----------------
+        */
+       InvalidForall = CacheIdRegisterSpecifiedLocalInvalid(InvalidForall,
+                               cacheId, hashIndex, pointer);
+       /* ----------------
+        *      Add message to InvalidLocal linked list.
+        * ----------------
+        */
+       InvalidLocal = CacheIdRegisterSpecifiedLocalInvalid(InvalidLocal,
+                               cacheId, hashIndex, pointer);
+}
+
+/* --------------------------------
+ *             CacheIdRegisterLocalRollback
+ * --------------------------------
+ */
+static void
+CacheIdRegisterLocalRollback(Index cacheId, Index hashIndex,
+                                       ItemPointer pointer)
+{
+
+       /* ----------------
+        *      debugging stuff
+        * ----------------
+        */
+       CacheIdRegisterLocalRollback_DEBUG1;
+
+       /* ----------------
+        *      Add message to RollbackStack linked list.
+        * ----------------
+        */
+       RollbackStack = CacheIdRegisterSpecifiedLocalInvalid(
+               RollbackStack, cacheId, hashIndex, pointer);
+}
+
+/* --------------------------------
+ *             CacheIdImmediateRegisterSharedInvalid
+ * --------------------------------
+ */
+static void
+CacheIdImmediateRegisterSharedInvalid(Index cacheId, Index hashIndex,
+                                       ItemPointer pointer)
 {
        InvalidationMessage message;
 
@@ -183,7 +331,7 @@ CacheIdRegisterLocalInvalid(Index cacheId,
         *      debugging stuff
         * ----------------
         */
-       CacheIdRegisterLocalInvalid_DEBUG1;
+       CacheIdImmediateRegisterSharedInvalid_DEBUG1;
 
        /* ----------------
         *      create a message describing the system catalog tuple
@@ -198,12 +346,51 @@ CacheIdRegisterLocalInvalid(Index cacheId,
        message->any.catalog.hashIndex = hashIndex;
 
        ItemPointerCopy(pointer, &message->any.catalog.pointerData);
+       /* ----------------
+        *      Register a shared catalog cache invalidation.
+        * ----------------
+        */
+       InvalidationMessageRegisterSharedInvalid(message);
+       free((Pointer) &((InvalidationUserData *) message)->dataP[-1]);
+}
+
+/* --------------------------------
+ *             RelationIdRegisterSpecifiedLocalInvalid
+ * --------------------------------
+ */
+static LocalInvalid
+RelationIdRegisterSpecifiedLocalInvalid(LocalInvalid invalid,
+                       Oid relationId, Oid objectId)
+{
+       InvalidationMessage message;
+
+       /* ----------------
+        *      debugging stuff
+        * ----------------
+        */
+#ifdef INVALIDDEBUG
+       elog(DEBUG, "RelationRegisterSpecifiedLocalInvalid(%u, %u)", relationId,
+                objectId);
+#endif  /* defined(INVALIDDEBUG) */
+
+       /* ----------------
+        *      create a message describing the relation descriptor
+        *      we wish to invalidate.
+        * ----------------
+        */
+       message = (InvalidationMessage)
+               InvalidationEntryAllocate(sizeof(InvalidationMessageData));
+
+       message->kind = 'r';
+       message->any.relation.relationId = relationId;
+       message->any.relation.objectId = objectId;
 
        /* ----------------
         *      Add message to linked list of unprocessed messages.
         * ----------------
         */
-       Invalid = LocalInvalidRegister(Invalid, (InvalidationEntry) message);
+       invalid = LocalInvalidRegister(invalid, (InvalidationEntry) message);
+       return invalid;
 }
 
 /* --------------------------------
@@ -212,6 +399,61 @@ CacheIdRegisterLocalInvalid(Index cacheId,
  */
 static void
 RelationIdRegisterLocalInvalid(Oid relationId, Oid objectId)
+{
+       /* ----------------
+        *      debugging stuff
+        * ----------------
+        */
+#ifdef INVALIDDEBUG
+       elog(DEBUG, "RelationRegisterLocalInvalid(%u, %u)", relationId,
+                objectId);
+#endif  /* defined(INVALIDDEBUG) */
+
+       /* ----------------
+        *      Add message to InvalidForall linked list.
+        * ----------------
+        */
+       InvalidForall = RelationIdRegisterSpecifiedLocalInvalid(InvalidForall,
+                               relationId, objectId);
+       /* ----------------
+        *      Add message to InvalidLocal linked list.
+        * ----------------
+        */
+       InvalidLocal = RelationIdRegisterSpecifiedLocalInvalid(InvalidLocal,
+                               relationId, objectId);
+}
+
+/* --------------------------------
+ *             RelationIdRegisterLocalRollback
+ * --------------------------------
+ */
+static void
+RelationIdRegisterLocalRollback(Oid relationId, Oid objectId)
+{
+
+       /* ----------------
+        *      debugging stuff
+        * ----------------
+        */
+#ifdef INVALIDDEBUG
+       elog(DEBUG, "RelationRegisterLocalRollback(%u, %u)", relationId,
+                objectId);
+#endif  /* defined(INVALIDDEBUG) */
+
+       /* ----------------
+        *      Add message to RollbackStack linked list.
+        * ----------------
+        */
+       RollbackStack = RelationIdRegisterSpecifiedLocalInvalid(
+                       RollbackStack, relationId, objectId);
+}
+
+/* --------------------------------
+ *             RelationIdImmediateRegisterSharedInvalid
+ * --------------------------------
+ */
+static void
+RelationIdImmediateRegisterSharedInvalid(Oid relationId, Oid objectId)
 {
        InvalidationMessage message;
 
@@ -220,7 +462,7 @@ RelationIdRegisterLocalInvalid(Oid relationId, Oid objectId)
         * ----------------
         */
 #ifdef INVALIDDEBUG
-       elog(DEBUG, "RelationRegisterLocalInvalid(%u, %u)", relationId,
+       elog(DEBUG, "RelationImmediateRegisterSharedInvalid(%u, %u)", relationId,
                 objectId);
 #endif  /* defined(INVALIDDEBUG) */
 
@@ -237,10 +479,11 @@ RelationIdRegisterLocalInvalid(Oid relationId, Oid objectId)
        message->any.relation.objectId = objectId;
 
        /* ----------------
-        *      Add message to linked list of unprocessed messages.
+        *      Register a shared catalog cache invalidation.
         * ----------------
         */
-       Invalid = LocalInvalidRegister(Invalid, (InvalidationEntry) message);
+       InvalidationMessageRegisterSharedInvalid(message);
+       free((Pointer) &((InvalidationUserData *) message)->dataP[-1]);
 }
 
 /* --------------------------------
@@ -397,7 +640,7 @@ InvalidationMessageCacheInvalidate(InvalidationMessage message)
                case 'c':                               /* cached system catalog tuple */
                        InvalidationMessageCacheInvalidate_DEBUG1;
 
-                       CatalogCacheIdInvalidate(message->any.catalog.cacheId,
+                       CacheIdInvalidate(message->any.catalog.cacheId,
                                                                         message->any.catalog.hashIndex,
                                                                         &message->any.catalog.pointerData);
                        break;
@@ -405,7 +648,9 @@ InvalidationMessageCacheInvalidate(InvalidationMessage message)
                case 'r':                               /* cached relation descriptor */
                        InvalidationMessageCacheInvalidate_DEBUG2;
 
-                       /* XXX ignore this--is this correct ??? */
+                       CacheIdInvalidate(message->any.relation.relationId,
+                                               message->any.relation.objectId,
+                                               (ItemPointer) NULL);
                        break;
 
                default:
@@ -500,38 +745,93 @@ RegisterInvalid(bool send)
         *      Process and free the current list of inval messages.
         * ----------------
         */
-       invalid = Invalid;
-       Invalid = EmptyLocalInvalid; /* anything added now is part of a new list */
 
+       DiscardInvalidStack(&InvalidLocal);
        if (send)
-               LocalInvalidInvalidate(invalid,
-                                                          InvalidationMessageRegisterSharedInvalid);
+       {
+               DiscardInvalidStack(&RollbackStack);
+               invalid = InvalidForall;
+               InvalidForall = EmptyLocalInvalid; /* clear InvalidForall */
+               LocalInvalidInvalidate(invalid, InvalidationMessageRegisterSharedInvalid, true);
+       }
        else
-               LocalInvalidInvalidate(invalid,
-                                                          InvalidationMessageCacheInvalidate);
+       {
+               DiscardInvalidStack(&InvalidForall);
+               invalid = RollbackStack;
+               RollbackStack = EmptyLocalInvalid; /* clear RollbackStack */
+               LocalInvalidInvalidate(invalid, InvalidationMessageCacheInvalidate, true);
+       }
 
 }
 
 /*
- * RelationIdInvalidateHeapTuple
- *             Causes the given tuple in a relation to be invalidated.
+ * ImmediateLocalInvalidation
+ *             Causes invalidation immediately for the next command of the transaction.
  *
  * Note:
+ *             This should be called in time of CommandCounterIncrement().
+ */
+void
+ImmediateLocalInvalidation(bool send)
+{
+       LocalInvalid invalid;
+
+       /* ----------------
+        *      debugging stuff
+        * ----------------
+        */
+#ifdef INVALIDDEBUG
+       elog(DEBUG, "ImmediateLocalInvalidation(%d) called", send);
+#endif  /* defined(INVALIDDEBUG) */
+
+       /* ----------------
+        *      Process and free the local list of inval messages.
+        * ----------------
+        */
+
+       if (send)
+       {
+               invalid = InvalidLocal;
+               InvalidLocal = EmptyLocalInvalid; /* clear InvalidLocal */
+               LocalInvalidInvalidate(invalid, InvalidationMessageCacheInvalidate, true);
+       }
+       else
+       {
+               /*
+                * This may be used for rollback to a savepoint.
+                * Don't clear InvalidForall and RollbackStack here.
+                */
+               DiscardInvalidStack(&InvalidLocal);
+               invalid = RollbackStack;
+               LocalInvalidInvalidate(invalid, InvalidationMessageCacheInvalidate, false);
+       }
+
+}
+
+/*
+ * InvokeHeapTupleInvalidation
+ *             Invoke functions for the tuple which register invalidation
+ *             of catalog/relation cache.  
+ *  Note:
  *             Assumes object id is valid.
  *             Assumes tuple is valid.
  */
 #ifdef INVALIDDEBUG
-#define RelationInvalidateHeapTuple_DEBUG1 \
-elog(DEBUG, "RelationInvalidateHeapTuple(%s, [%d,%d])", \
+#define InvokeHeapTupleInvalidation_DEBUG1 \
+elog(DEBUG, "%s(%s, [%d,%d])", \
+        funcname,\
         RelationGetPhysicalRelationName(relation), \
-        ItemPointerGetBlockNumber(&tuple->t_ctid), \
-        ItemPointerGetOffsetNumber(&tuple->t_ctid))
+        ItemPointerGetBlockNumber(&tuple->t_self), \
+        ItemPointerGetOffsetNumber(&tuple->t_self))
 #else
-#define RelationInvalidateHeapTuple_DEBUG1
+#define InvokeHeapTupleInvalidation_DEBUG1
 #endif  /* defined(INVALIDDEBUG) */
 
-void
-RelationInvalidateHeapTuple(Relation relation, HeapTuple tuple)
+static void
+InvokeHeapTupleInvalidation(Relation relation, HeapTuple tuple,
+               void (*CacheIdRegisterFunc)(),
+               void (*RelationIdRegisterFunc)(),
+               const char *funcname)
 {
        /* ----------------
         *      sanity checks
@@ -553,13 +853,88 @@ RelationInvalidateHeapTuple(Relation relation, HeapTuple tuple)
         *      debugging stuff
         * ----------------
         */
-       RelationInvalidateHeapTuple_DEBUG1;
+       InvokeHeapTupleInvalidation_DEBUG1;
+
+       RelationInvalidateCatalogCacheTuple(relation, tuple, 
+               CacheIdRegisterFunc);
 
-       RelationInvalidateCatalogCacheTuple(relation,
-                                                                               tuple,
-                                                                               CacheIdRegisterLocalInvalid);
+       RelationInvalidateRelationCache(relation, tuple,
+               RelationIdRegisterFunc);
+}
+/*
+ * RelationInvalidateHeapTuple
+ *             Causes the given tuple in a relation to be invalidated.
+ */
+void
+RelationInvalidateHeapTuple(Relation relation, HeapTuple tuple)
+{
+       InvokeHeapTupleInvalidation(relation, tuple, 
+               CacheIdRegisterLocalInvalid,
+               RelationIdRegisterLocalInvalid,
+               "RelationInvalidateHeapTuple");
+}
+
+/*
+ * RelationMark4RollbackHeapTuple
+ *             keep the given tuple in a relation to be invalidated
+ *             in case of abort.
+ */
+void
+RelationMark4RollbackHeapTuple(Relation relation, HeapTuple tuple)
+{
+       InvokeHeapTupleInvalidation(relation, tuple,
+               CacheIdRegisterLocalRollback,
+               RelationIdRegisterLocalRollback,
+               "RelationMark4RollbackHeapTuple");
+}
+
+/*
+ * ImmediateInvalidateSharedHeapTuple
+ *             Different from RelationInvalidateHeapTuple()
+ *             this function queues shared invalidation info immediately.
+ */
+void
+ImmediateInvalidateSharedHeapTuple(Relation relation, HeapTuple tuple)
+{
+       InvokeHeapTupleInvalidation(relation, tuple,
+               CacheIdImmediateRegisterSharedInvalid,
+               RelationIdImmediateRegisterSharedInvalid,
+               "ImmediateInvalidateSharedHeapTuple");
+}
+
+/*
+ * ImmediateSharedRelationCacheInvalidate
+ *     Register shared relation cache invalidation immediately
+ *
+ *     This is needed for smgrunlink()/smgrtruncate().
+ *     Those functions unlink/truncate the base file immediately
+ *     and couldn't be rollbacked in case of abort/crash.
+ *     So relation cache invalidation must be registerd immediately. 
+ *  Note:
+ *             Assumes Relation is valid.
+ */
+void
+ImmediateSharedRelationCacheInvalidate(Relation relation)
+{
+       /* ----------------
+        *      sanity checks
+        * ----------------
+        */
+       Assert(RelationIsValid(relation));
+
+       if (IsBootstrapProcessingMode())
+               return;
+
+       /* ----------------
+        *      debugging stuff
+        * ----------------
+        */
+#ifdef INVALIDDEBUG
+elog(DEBUG, "ImmediateSharedRelationCacheInvalidate(%s)", \
+        RelationGetPhysicalRelationName(relation));
+#endif  /* defined(INVALIDDEBUG) */
 
-       RelationInvalidateRelationCache(relation,
-                                                                       tuple,
-                                                                       RelationIdRegisterLocalInvalid);
+       RelationIdImmediateRegisterSharedInvalid(
+               RelOid_pg_class, RelationGetRelid(relation));
 }
index a559c4374dc0be63515bc2d946c700e535cd2698..fb1adbc0c974ea47fbb5ff4a2309840d20fcfce8 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: inval.h,v 1.14 1999/11/21 01:58:20 tgl Exp $
+ * $Id: inval.h,v 1.15 2000/01/10 06:30:56 inoue Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,6 +19,14 @@ extern void DiscardInvalid(void);
 
 extern void RegisterInvalid(bool send);
 
+extern void ImmediateLocalInvalidation(bool send);
+
 extern void RelationInvalidateHeapTuple(Relation relation, HeapTuple tuple);
 
+extern void RelationMark4RollbackHeapTuple(Relation relation, HeapTuple tuple);
+
+extern void ImmediateInvalidateSharedHeapTuple(Relation relation, HeapTuple tuple);
+
+extern void ImmediateSharedRelationCacheInvalidate(Relation relation);
+
 #endif  /* INVAL_H */