8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.121 2000/12/22 23:12:06 tgl Exp $
11
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.122 2001/01/02 04:33:19 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -253,10 +253,10 @@ static void RelationClearRelation(Relation relation, bool rebuildIt);
253
253
#ifdef ENABLE_REINDEX_NAILED_RELATIONS
254
254
static void RelationReloadClassinfo (Relation relation );
255
255
#endif /* ENABLE_REINDEX_NAILED_RELATIONS */
256
- static void RelationFlushRelation (Relation * relationPtr ,
257
- int skipLocalRelations );
256
+ static void RelationFlushRelation (Relation relation );
258
257
static Relation RelationNameCacheGetRelation (const char * relationName );
259
- static void RelationCacheAbortWalker (Relation * relationPtr , int dummy );
258
+ static void RelationCacheInvalidateWalker (Relation * relationPtr , Datum listp );
259
+ static void RelationCacheAbortWalker (Relation * relationPtr , Datum dummy );
260
260
static void init_irels (void );
261
261
static void write_irels (void );
262
262
@@ -1639,14 +1639,12 @@ RelationClearRelation(Relation relation, bool rebuildIt)
1639
1639
* we'd be unable to recover.
1640
1640
*/
1641
1641
if (relation -> rd_isnailed )
1642
- #ifdef ENABLE_REINDEX_NAILED_RELATIONS
1643
1642
{
1643
+ #ifdef ENABLE_REINDEX_NAILED_RELATIONS
1644
1644
RelationReloadClassinfo (relation );
1645
1645
#endif /* ENABLE_REINDEX_NAILED_RELATIONS */
1646
1646
return ;
1647
- #ifdef ENABLE_REINDEX_NAILED_RELATIONS
1648
1647
}
1649
- #endif /* ENABLE_REINDEX_NAILED_RELATIONS */
1650
1648
1651
1649
/*
1652
1650
* Remove relation from hash tables
@@ -1774,26 +1772,15 @@ RelationClearRelation(Relation relation, bool rebuildIt)
1774
1772
* RelationFlushRelation
1775
1773
*
1776
1774
* Rebuild the relation if it is open (refcount > 0), else blow it away.
1777
- * If skipLocalRelations is TRUE, xact-local relations are ignored
1778
- * (which is useful when processing SI cache reset, since xact-local
1779
- * relations could not be targets of notifications from other backends).
1780
- *
1781
- * The peculiar calling convention (pointer to pointer to relation)
1782
- * is needed so that we can use this routine as a hash table walker.
1783
1775
* --------------------------------
1784
1776
*/
1785
1777
static void
1786
- RelationFlushRelation (Relation * relationPtr ,
1787
- int skipLocalRelations )
1778
+ RelationFlushRelation (Relation relation )
1788
1779
{
1789
- Relation relation = * relationPtr ;
1790
1780
bool rebuildIt ;
1791
1781
1792
1782
if (relation -> rd_myxactonly )
1793
1783
{
1794
- if (skipLocalRelations )
1795
- return ; /* don't touch local rels if so commanded */
1796
-
1797
1784
/*
1798
1785
* Local rels should always be rebuilt, not flushed; the relcache
1799
1786
* entry must live until RelationPurgeLocalRelation().
@@ -1878,7 +1865,7 @@ RelationIdInvalidateRelationCacheByRelationId(Oid relationId)
1878
1865
RelationIdCacheLookup (relationId , relation );
1879
1866
1880
1867
if (PointerIsValid (relation ))
1881
- RelationFlushRelation (& relation , false );
1868
+ RelationFlushRelation (relation );
1882
1869
}
1883
1870
1884
1871
#if NOT_USED
@@ -1900,35 +1887,12 @@ RelationFlushIndexes(Relation *r,
1900
1887
if (relation -> rd_rel -> relkind == RELKIND_INDEX && /* XXX style */
1901
1888
(!OidIsValid (accessMethodId ) ||
1902
1889
relation -> rd_rel -> relam == accessMethodId ))
1903
- RelationFlushRelation (& relation , false );
1890
+ RelationFlushRelation (relation );
1904
1891
}
1905
1892
1906
1893
#endif
1907
1894
1908
1895
1909
- #if NOT_USED
1910
- void
1911
- RelationIdInvalidateRelationCacheByAccessMethodId (Oid accessMethodId )
1912
- {
1913
-
1914
- /*
1915
- * 25 aug 1992: mao commented out the ht walk below. it should be
1916
- * doing the right thing, in theory, but flushing reldescs for index
1917
- * relations apparently doesn't work. we want to cut 4.0.1, and i
1918
- * don't want to introduce new bugs. this code never executed before,
1919
- * so i'm turning it off for now. after the release is cut, i'll fix
1920
- * this up.
1921
- *
1922
- * 20 nov 1999: this code has still never done anything, so I'm cutting
1923
- * the routine out of the system entirely. tgl
1924
- */
1925
-
1926
- HashTableWalk (RelationNameCache , (HashtFunc ) RelationFlushIndexes ,
1927
- accessMethodId );
1928
- }
1929
-
1930
- #endif
1931
-
1932
1896
/*
1933
1897
* RelationCacheInvalidate
1934
1898
* Blow away cached relation descriptors that have zero reference counts,
@@ -1938,12 +1902,59 @@ RelationIdInvalidateRelationCacheByAccessMethodId(Oid accessMethodId)
1938
1902
* so we do not touch transaction-local relations; they cannot be targets
1939
1903
* of cross-backend SI updates (and our own updates now go through a
1940
1904
* separate linked list that isn't limited by the SI message buffer size).
1905
+ *
1906
+ * We do this in two phases: the first pass deletes deletable items, and
1907
+ * the second one rebuilds the rebuildable items. This is essential for
1908
+ * safety, because HashTableWalk only copes with concurrent deletion of
1909
+ * the element it is currently visiting. If a second SI overflow were to
1910
+ * occur while we are walking the table, resulting in recursive entry to
1911
+ * this routine, we could crash because the inner invocation blows away
1912
+ * the entry next to be visited by the outer scan. But this way is OK,
1913
+ * because (a) during the first pass we won't process any more SI messages,
1914
+ * so HashTableWalk will complete safely; (b) during the second pass we
1915
+ * only hold onto pointers to nondeletable entries.
1941
1916
*/
1942
1917
void
1943
1918
RelationCacheInvalidate (void )
1944
1919
{
1945
- HashTableWalk (RelationNameCache , (HashtFunc ) RelationFlushRelation ,
1946
- (int ) true);
1920
+ List * rebuildList = NIL ;
1921
+ List * l ;
1922
+
1923
+ /* Phase 1 */
1924
+ HashTableWalk (RelationNameCache ,
1925
+ (HashtFunc ) RelationCacheInvalidateWalker ,
1926
+ PointerGetDatum (& rebuildList ));
1927
+
1928
+ /* Phase 2: rebuild the items found to need rebuild in phase 1 */
1929
+ foreach (l , rebuildList )
1930
+ {
1931
+ Relation relation = (Relation ) lfirst (l );
1932
+
1933
+ RelationClearRelation (relation , true);
1934
+ }
1935
+ freeList (rebuildList );
1936
+ }
1937
+
1938
+ static void
1939
+ RelationCacheInvalidateWalker (Relation * relationPtr , Datum listp )
1940
+ {
1941
+ Relation relation = * relationPtr ;
1942
+ List * * rebuildList = (List * * ) DatumGetPointer (listp );
1943
+
1944
+ /* We can ignore xact-local relations, since they are never SI targets */
1945
+ if (relation -> rd_myxactonly )
1946
+ return ;
1947
+
1948
+ if (RelationHasReferenceCountZero (relation ))
1949
+ {
1950
+ /* Delete this entry immediately */
1951
+ RelationClearRelation (relation , false);
1952
+ }
1953
+ else
1954
+ {
1955
+ /* Add entry to list of stuff to rebuild in second pass */
1956
+ * rebuildList = lcons (relation , * rebuildList );
1957
+ }
1947
1958
}
1948
1959
1949
1960
/*
@@ -1962,12 +1973,13 @@ RelationCacheInvalidate(void)
1962
1973
void
1963
1974
RelationCacheAbort (void )
1964
1975
{
1965
- HashTableWalk (RelationNameCache , (HashtFunc ) RelationCacheAbortWalker ,
1976
+ HashTableWalk (RelationNameCache ,
1977
+ (HashtFunc ) RelationCacheAbortWalker ,
1966
1978
0 );
1967
1979
}
1968
1980
1969
1981
static void
1970
- RelationCacheAbortWalker (Relation * relationPtr , int dummy )
1982
+ RelationCacheAbortWalker (Relation * relationPtr , Datum dummy )
1971
1983
{
1972
1984
Relation relation = * relationPtr ;
1973
1985
0 commit comments