diff options
Diffstat (limited to 'src/backend/utils/cache/relcache.c')
-rw-r--r-- | src/backend/utils/cache/relcache.c | 108 |
1 files changed, 60 insertions, 48 deletions
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 1b7ce6fe18c..6fc68cca705 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.121 2000/12/22 23:12:06 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.122 2001/01/02 04:33:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -253,10 +253,10 @@ static void RelationClearRelation(Relation relation, bool rebuildIt); #ifdef ENABLE_REINDEX_NAILED_RELATIONS static void RelationReloadClassinfo(Relation relation); #endif /* ENABLE_REINDEX_NAILED_RELATIONS */ -static void RelationFlushRelation(Relation *relationPtr, - int skipLocalRelations); +static void RelationFlushRelation(Relation relation); static Relation RelationNameCacheGetRelation(const char *relationName); -static void RelationCacheAbortWalker(Relation *relationPtr, int dummy); +static void RelationCacheInvalidateWalker(Relation *relationPtr, Datum listp); +static void RelationCacheAbortWalker(Relation *relationPtr, Datum dummy); static void init_irels(void); static void write_irels(void); @@ -1639,14 +1639,12 @@ RelationClearRelation(Relation relation, bool rebuildIt) * we'd be unable to recover. */ if (relation->rd_isnailed) -#ifdef ENABLE_REINDEX_NAILED_RELATIONS { +#ifdef ENABLE_REINDEX_NAILED_RELATIONS RelationReloadClassinfo(relation); #endif /* ENABLE_REINDEX_NAILED_RELATIONS */ return; -#ifdef ENABLE_REINDEX_NAILED_RELATIONS } -#endif /* ENABLE_REINDEX_NAILED_RELATIONS */ /* * Remove relation from hash tables @@ -1774,26 +1772,15 @@ RelationClearRelation(Relation relation, bool rebuildIt) * RelationFlushRelation * * Rebuild the relation if it is open (refcount > 0), else blow it away. - * If skipLocalRelations is TRUE, xact-local relations are ignored - * (which is useful when processing SI cache reset, since xact-local - * relations could not be targets of notifications from other backends). - * - * The peculiar calling convention (pointer to pointer to relation) - * is needed so that we can use this routine as a hash table walker. * -------------------------------- */ static void -RelationFlushRelation(Relation *relationPtr, - int skipLocalRelations) +RelationFlushRelation(Relation relation) { - Relation relation = *relationPtr; bool rebuildIt; if (relation->rd_myxactonly) { - if (skipLocalRelations) - return; /* don't touch local rels if so commanded */ - /* * Local rels should always be rebuilt, not flushed; the relcache * entry must live until RelationPurgeLocalRelation(). @@ -1878,7 +1865,7 @@ RelationIdInvalidateRelationCacheByRelationId(Oid relationId) RelationIdCacheLookup(relationId, relation); if (PointerIsValid(relation)) - RelationFlushRelation(&relation, false); + RelationFlushRelation(relation); } #if NOT_USED @@ -1900,35 +1887,12 @@ RelationFlushIndexes(Relation *r, if (relation->rd_rel->relkind == RELKIND_INDEX && /* XXX style */ (!OidIsValid(accessMethodId) || relation->rd_rel->relam == accessMethodId)) - RelationFlushRelation(&relation, false); + RelationFlushRelation(relation); } #endif -#if NOT_USED -void -RelationIdInvalidateRelationCacheByAccessMethodId(Oid accessMethodId) -{ - - /* - * 25 aug 1992: mao commented out the ht walk below. it should be - * doing the right thing, in theory, but flushing reldescs for index - * relations apparently doesn't work. we want to cut 4.0.1, and i - * 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); -} - -#endif - /* * RelationCacheInvalidate * Blow away cached relation descriptors that have zero reference counts, @@ -1938,12 +1902,59 @@ RelationIdInvalidateRelationCacheByAccessMethodId(Oid accessMethodId) * so we do not touch transaction-local relations; they cannot be targets * of cross-backend SI updates (and our own updates now go through a * separate linked list that isn't limited by the SI message buffer size). + * + * We do this in two phases: the first pass deletes deletable items, and + * the second one rebuilds the rebuildable items. This is essential for + * safety, because HashTableWalk only copes with concurrent deletion of + * the element it is currently visiting. If a second SI overflow were to + * occur while we are walking the table, resulting in recursive entry to + * this routine, we could crash because the inner invocation blows away + * the entry next to be visited by the outer scan. But this way is OK, + * because (a) during the first pass we won't process any more SI messages, + * so HashTableWalk will complete safely; (b) during the second pass we + * only hold onto pointers to nondeletable entries. */ void RelationCacheInvalidate(void) { - HashTableWalk(RelationNameCache, (HashtFunc) RelationFlushRelation, - (int) true); + List *rebuildList = NIL; + List *l; + + /* Phase 1 */ + HashTableWalk(RelationNameCache, + (HashtFunc) RelationCacheInvalidateWalker, + PointerGetDatum(&rebuildList)); + + /* Phase 2: rebuild the items found to need rebuild in phase 1 */ + foreach (l, rebuildList) + { + Relation relation = (Relation) lfirst(l); + + RelationClearRelation(relation, true); + } + freeList(rebuildList); +} + +static void +RelationCacheInvalidateWalker(Relation *relationPtr, Datum listp) +{ + Relation relation = *relationPtr; + List **rebuildList = (List **) DatumGetPointer(listp); + + /* We can ignore xact-local relations, since they are never SI targets */ + if (relation->rd_myxactonly) + return; + + if (RelationHasReferenceCountZero(relation)) + { + /* Delete this entry immediately */ + RelationClearRelation(relation, false); + } + else + { + /* Add entry to list of stuff to rebuild in second pass */ + *rebuildList = lcons(relation, *rebuildList); + } } /* @@ -1962,12 +1973,13 @@ RelationCacheInvalidate(void) void RelationCacheAbort(void) { - HashTableWalk(RelationNameCache, (HashtFunc) RelationCacheAbortWalker, + HashTableWalk(RelationNameCache, + (HashtFunc) RelationCacheAbortWalker, 0); } static void -RelationCacheAbortWalker(Relation *relationPtr, int dummy) +RelationCacheAbortWalker(Relation *relationPtr, Datum dummy) { Relation relation = *relationPtr; |