Repair problem exposed by Jan's new parallel-regression-test scaffold:
authorTom Lane
Sun, 21 Nov 1999 01:58:22 +0000 (01:58 +0000)
committerTom Lane
Sun, 21 Nov 1999 01:58:22 +0000 (01:58 +0000)
inval.c thought it could safely use the catcache to look up the OIDs of
system relations.  Not good, considering that inval.c could be called
during catcache loading, if a shared-inval message arrives.  Rip out the
lookup logic and instead use the known OIDs from pg_class.h.

src/backend/utils/cache/catcache.c
src/backend/utils/cache/inval.c
src/backend/utils/cache/relcache.c
src/backend/utils/init/postinit.c
src/include/utils/inval.h
src/include/utils/relcache.h

index 423a5d728616ce90c958e01e236b09dc8b874ad5..e5a1684041c709f7b343a7fa68b47879f4a50fe5 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.52 1999/11/19 18:51:48 wieck Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.53 1999/11/21 01:58:22 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -819,7 +819,7 @@ InitSysCache(char *relname,
  * --------------------------------
  */
 static HeapTuple
-SearchSelfReferences(const struct catcache * cache)
+SearchSelfReferences(struct catcache * cache)
 {
    HeapTuple       ntp;
    Relation        rel;
@@ -983,23 +983,11 @@ SearchSysCache(struct catcache * cache,
     * ----------------
     */
 
-   /* ----------
-    * It is definitely insufficient. While modifying the regression
-    * test to run independent tests concurrently it happened, that
-    * this code fails VERY often. ISTM that 'cache' points into
-    * shared memory, but that 'busy' means this backend is loading
-    * a new entry. So when another backend has set busy, this one
-    * think's it detected a recursion.
-    *
-    * Need's a smarter detection mechanism - Jan
-    *
    if (cache->busy)
    {
        elog(ERROR, "SearchSysCache: recursive use of cache %d", cache->id);
    }
    cache->busy = true;
-    * ----------
-    */
 
    /* ----------------
     *  open the relation associated with the cache
index 26f45a1e9b2d0ede5eb7293b78eaf1dc2d524518..d89a1f678a48afcfea20b6ca5769f16736ce4fb6 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/cache/inval.c,v 1.29 1999/11/17 23:51:21 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/cache/inval.c,v 1.30 1999/11/21 01:58:22 tgl Exp $
  *
  * Note - this code is real crufty...
  *
 #include "catalog/catalog.h"
 #include "catalog/catname.h"
 #include "catalog/heap.h"
+#include "catalog/pg_class.h"
 #include "miscadmin.h"
 #include "storage/sinval.h"
 #include "utils/catcache.h"
 #include "utils/inval.h"
 #include "utils/relcache.h"
 
-static InvalidationEntry InvalidationEntryAllocate(uint16 size);
-static void LocalInvalidInvalidate(LocalInvalid invalid, void (*function) ());
-static LocalInvalid LocalInvalidRegister(LocalInvalid invalid,
-                    InvalidationEntry entry);
-static void getmyrelids(void);
-
 
 /* ----------------
  *     private invalidation structures
  * ----------------
  */
+
+typedef struct InvalidationUserData
+{
+   struct InvalidationUserData *dataP[1];      /* VARIABLE LENGTH */
+} InvalidationUserData;            /* VARIABLE LENGTH STRUCTURE */
+
+typedef struct InvalidationEntryData
+{
+   InvalidationUserData *nextP;
+   InvalidationUserData userData;      /* VARIABLE LENGTH ARRAY */
+} InvalidationEntryData;       /* VARIABLE LENGTH STRUCTURE */
+
+typedef Pointer InvalidationEntry;
+
+typedef InvalidationEntry LocalInvalid;
+
+#define EmptyLocalInvalid      NULL
+
 typedef struct CatalogInvalidationData
 {
    Index       cacheId;
@@ -66,15 +79,14 @@ typedef InvalidationMessageData *InvalidationMessage;
  *     variables and macros
  * ----------------
  */
-static LocalInvalid Invalid = EmptyLocalInvalid;       /* XXX global */
+static LocalInvalid Invalid = EmptyLocalInvalid;   /* head of linked list */
 
-Oid            MyRelationRelationId = InvalidOid;
-Oid            MyAttributeRelationId = InvalidOid;
-Oid            MyAMRelationId = InvalidOid;
-Oid            MyAMOPRelationId = InvalidOid;
 
-#define ValidateHacks() \
-   if (!OidIsValid(MyRelationRelationId)) getmyrelids()
+static InvalidationEntry InvalidationEntryAllocate(uint16 size);
+static void LocalInvalidInvalidate(LocalInvalid invalid, void (*function) ());
+static LocalInvalid LocalInvalidRegister(LocalInvalid invalid,
+                                        InvalidationEntry entry);
+
 
 /* ----------------------------------------------------------------
  *             "local" invalidation support functions
@@ -99,7 +111,8 @@ InvalidationEntryAllocate(uint16 size)
 
 /* --------------------------------
  *     LocalInvalidRegister
- *        Returns a new local cache invalidation state containing a new entry.
+ *        Link an invalidation entry into a chain of them.  Really ugly
+ *        coding here.
  * --------------------------------
  */
 static LocalInvalid
@@ -117,7 +130,7 @@ LocalInvalidRegister(LocalInvalid invalid,
 /* --------------------------------
  *     LocalInvalidInvalidate
  *             Processes, then frees all entries in a local cache
- *             invalidation state.
+ *             invalidation list.
  * --------------------------------
  */
 static void
@@ -187,7 +200,7 @@ CacheIdRegisterLocalInvalid(Index cacheId,
    ItemPointerCopy(pointer, &message->any.catalog.pointerData);
 
    /* ----------------
-    *  Note: Invalid is a global variable
+    *  Add message to linked list of unprocessed messages.
     * ----------------
     */
    Invalid = LocalInvalidRegister(Invalid, (InvalidationEntry) message);
@@ -224,32 +237,12 @@ RelationIdRegisterLocalInvalid(Oid relationId, Oid objectId)
    message->any.relation.objectId = objectId;
 
    /* ----------------
-    *  Note: Invalid is a global variable
+    *  Add message to linked list of unprocessed messages.
     * ----------------
     */
    Invalid = LocalInvalidRegister(Invalid, (InvalidationEntry) message);
 }
 
-/* --------------------------------
- *     getmyrelids
- * --------------------------------
- */
-static void
-getmyrelids()
-{
-   MyRelationRelationId = RelnameFindRelid(RelationRelationName);
-   Assert(RelationRelationName != InvalidOid);
-
-   MyAttributeRelationId = RelnameFindRelid(AttributeRelationName);
-   Assert(AttributeRelationName != InvalidOid);
-
-   MyAMRelationId = RelnameFindRelid(AccessMethodRelationName);
-   Assert(MyAMRelationId != InvalidOid);
-
-   MyAMOPRelationId = RelnameFindRelid(AccessMethodOperatorRelationName);
-   Assert(MyAMOPRelationId != InvalidOid);
-}
-
 /* --------------------------------
  *     CacheIdInvalidate
  *
@@ -284,38 +277,23 @@ CacheIdInvalidate(Index cacheId,
 
    CacheIdInvalidate_DEBUG1;
 
-   ValidateHacks();            /* XXX */
-
    /* ----------------
-    *  if the cacheId is the oid of any of the tuples in the
-    *  following system relations, then assume we are invalidating
-    *  a relation descriptor
+    *  if the cacheId is the oid of any of the following system relations,
+    *  then assume we are invalidating a relation descriptor
     * ----------------
     */
-   if (cacheId == MyRelationRelationId)
+   if (cacheId == RelOid_pg_class)
    {
        RelationIdInvalidateRelationCacheByRelationId(hashIndex);
        return;
    }
 
-   if (cacheId == MyAttributeRelationId)
+   if (cacheId == RelOid_pg_attribute)
    {
        RelationIdInvalidateRelationCacheByRelationId(hashIndex);
        return;
    }
 
-   if (cacheId == MyAMRelationId)
-   {
-       RelationIdInvalidateRelationCacheByAccessMethodId(hashIndex);
-       return;
-   }
-
-   if (cacheId == MyAMOPRelationId)
-   {
-       RelationIdInvalidateRelationCacheByAccessMethodId(InvalidOid);
-       return;
-   }
-
    /* ----------------
     *  Yow! the caller asked us to invalidate something else.
     * ----------------
@@ -446,29 +424,22 @@ RelationInvalidateRelationCache(Relation relation,
                                void (*function) ())
 {
    Oid         relationId;
-   Oid         objectId = (Oid) 0;
+   Oid         objectId;
 
    /* ----------------
     *  get the relation object id
     * ----------------
     */
-   ValidateHacks();            /* XXX */
    relationId = RelationGetRelid(relation);
 
    /* ----------------
-    *
+    *  is it one of the ones we need to send an SI message for?
     * ----------------
     */
-   if (relationId == MyRelationRelationId)
+   if (relationId == RelOid_pg_class)
        objectId = tuple->t_data->t_oid;
-   else if (relationId == MyAttributeRelationId)
+   else if (relationId == RelOid_pg_attribute)
        objectId = ((Form_pg_attribute) GETSTRUCT(tuple))->attrelid;
-   else if (relationId == MyAMRelationId)
-       objectId = tuple->t_data->t_oid;
-   else if (relationId == MyAMOPRelationId)
-   {
-       ;                       /* objectId is unused */
-   }
    else
        return;
 
@@ -482,19 +453,6 @@ RelationInvalidateRelationCache(Relation relation,
 }
 
 
-/*
- * InitLocalInvalidateData
- *
- * Setup this before anything could ever get invalid!
- * Called by InitPostgres();
- */
-void
-InitLocalInvalidateData()
-{
-   ValidateHacks();
-}
-
-
 /*
  * DiscardInvalid
  *     Causes the invalidated cache state to be discarded.
@@ -528,6 +486,8 @@ DiscardInvalid()
 void
 RegisterInvalid(bool send)
 {
+   LocalInvalid invalid;
+
    /* ----------------
     *  debugging stuff
     * ----------------
@@ -537,17 +497,19 @@ RegisterInvalid(bool send)
 #endif  /* defined(INVALIDDEBUG) */
 
    /* ----------------
-    *  Note: Invalid is a global variable
+    *  Process and free the current list of inval messages.
     * ----------------
     */
+   invalid = Invalid;
+   Invalid = EmptyLocalInvalid; /* anything added now is part of a new list */
+
    if (send)
-       LocalInvalidInvalidate(Invalid,
+       LocalInvalidInvalidate(invalid,
                               InvalidationMessageRegisterSharedInvalid);
    else
-       LocalInvalidInvalidate(Invalid,
+       LocalInvalidInvalidate(invalid,
                               InvalidationMessageCacheInvalidate);
 
-   Invalid = EmptyLocalInvalid;
 }
 
 /*
index d6d2ee4b4e9e001e2f8188a113aa19f4219f3dbc..b66847441190ea95881a34b029a7ba292c6ff594 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.79 1999/11/18 13:56:28 wieck Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.80 1999/11/21 01:58:22 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -209,11 +209,6 @@ do { \
 static void formrdesc(char *relationName, u_int natts,
          FormData_pg_attribute *att);
 
-#ifdef NOT_USED                    /* See comments at line 1304 */
-static void RelationFlushIndexes(Relation *r, Oid accessMethodId);
-
-#endif
-
 static HeapTuple ScanPgRelation(RelationBuildDescInfo buildinfo);
 static HeapTuple scan_pg_rel_seq(RelationBuildDescInfo buildinfo);
 static HeapTuple scan_pg_rel_ind(RelationBuildDescInfo buildinfo);
@@ -1431,12 +1426,9 @@ RelationIdInvalidateRelationCacheByRelationId(Oid relationId)
    }
 }
 
-#if NOT_USED                   /* See comments at line 1304 */
-/* --------------------------------
- *     RelationIdInvalidateRelationCacheByAccessMethodId
- *
- *     RelationFlushIndexes is needed for use with HashTableWalk..
- * --------------------------------
+#if NOT_USED
+/* only used by RelationIdInvalidateRelationCacheByAccessMethodId,
+ * which is dead code.
  */
 static void
 RelationFlushIndexes(Relation *r,
@@ -1459,11 +1451,10 @@ RelationFlushIndexes(Relation *r,
 #endif
 
 
+#if NOT_USED
 void
 RelationIdInvalidateRelationCacheByAccessMethodId(Oid accessMethodId)
 {
-#ifdef NOT_USED
-
    /*
     * 25 aug 1992:  mao commented out the ht walk below.  it should be
     * doing the right thing, in theory, but flushing reldescs for index
@@ -1471,14 +1462,15 @@ RelationIdInvalidateRelationCacheByAccessMethodId(Oid accessMethodId)
     * don't want to introduce new bugs.  this code never executed before,
     * so i'm turning it off for now.  after the release is cut, i'll fix
     * this up.
+    *
+    * 20 nov 1999:  this code has still never done anything, so I'm
+    * cutting the routine out of the system entirely.  tgl
     */
 
    HashTableWalk(RelationNameCache, (HashtFunc) RelationFlushIndexes,
                  accessMethodId);
-#else
-   return;
-#endif
 }
+#endif
 
 /*
  * RelationCacheInvalidate
index 72c87f161964f141f4277fa5fd5f4b9e63fd1158..c5b3f06b8cbbc49186604a4b894ff9eceec333af 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.52 1999/10/25 03:07:51 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.53 1999/11/21 01:58:21 tgl Exp $
  *
  * NOTES
  *     InitPostgres() is the function called from PostgresMain
@@ -553,12 +553,6 @@ InitPostgres(char *name)       /* database name */
     */
    InitUserid();
 
-   /*
-    * Initialize local data in cache invalidation stuff
-    */
-   if (!bootstrap)
-       InitLocalInvalidateData();
-
    if (lockingOff)
        LockDisable(true);
 
index f63941f39672ec00629d8c3df1a0b7000e72a3bf..a559c4374dc0be63515bc2d946c700e535cd2698 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: inval.h,v 1.13 1999/07/15 23:04:22 momjian Exp $
+ * $Id: inval.h,v 1.14 1999/11/21 01:58:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include "access/htup.h"
 
-extern void InitLocalInvalidateData(void);
-
 extern void DiscardInvalid(void);
 
 extern void RegisterInvalid(bool send);
 
 extern void RelationInvalidateHeapTuple(Relation relation, HeapTuple tuple);
 
-/*
- * POSTGRES local cache invalidation definitions. (originates from linval.h)
- */
-typedef struct InvalidationUserData
-{
-   struct InvalidationUserData *dataP[1];      /* VARIABLE LENGTH */
-} InvalidationUserData;            /* VARIABLE LENGTH STRUCTURE */
-
-typedef struct InvalidationEntryData
-{
-   InvalidationUserData *nextP;
-   InvalidationUserData userData;      /* VARIABLE LENGTH ARRAY */
-} InvalidationEntryData;       /* VARIABLE LENGTH STRUCTURE */
-
-typedef Pointer InvalidationEntry;
-
-typedef InvalidationEntry LocalInvalid;
-
-#define EmptyLocalInvalid      NULL
-
 #endif  /* INVAL_H */
index 95fab3b22aeb89f7f358f0d48327389a700c27ba..2aeec820dff9c42ab1e2d25b3c6b96a6870319a4 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: relcache.h,v 1.15 1999/10/03 23:55:38 tgl Exp $
+ * $Id: relcache.h,v 1.16 1999/11/21 01:58:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -32,8 +32,6 @@ extern void RelationRebuildRelation(Relation relation);
 
 extern void RelationIdInvalidateRelationCacheByRelationId(Oid relationId);
 
-extern void RelationIdInvalidateRelationCacheByAccessMethodId(Oid accessMethodId);
-
 extern void RelationCacheInvalidate(bool onlyFlushReferenceCountZero);
 
 extern void RelationRegisterRelation(Relation relation);