Make sure that FlushRelationBuffers() is invoked by all paths through
authorTom Lane
Tue, 19 Sep 2000 19:30:03 +0000 (19:30 +0000)
committerTom Lane
Tue, 19 Sep 2000 19:30:03 +0000 (19:30 +0000)
vacuum.c.  This is needed to make the world safe for pg_upgrade.

src/backend/commands/vacuum.c

index 7d4005d21d5b5d953cc4a4cacafa547f10fd1591..3bd65fed7658ca8adf0dbeb6d15eab8798eb4abb 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.165 2000/09/12 04:49:07 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.166 2000/09/19 19:30:03 tgl Exp $
  *
 
  *-------------------------------------------------------------------------
@@ -397,12 +397,6 @@ vacuum_rel(Oid relid, bool analyze, bool is_toastrel)
     */
    onerel = heap_open(relid, AccessExclusiveLock);
 
-   /*
-    * Remember the relations TOAST relation for later
-    *
-    */
-   toast_relid = onerel->rd_rel->reltoastrelid;
-
 #ifndef NO_SECURITY
    if (!pg_ownercheck(GetUserId(), RelationGetRelationName(onerel),
                       RELNAME))
@@ -416,6 +410,11 @@ vacuum_rel(Oid relid, bool analyze, bool is_toastrel)
    }
 #endif
 
+   /*
+    * Remember the relation'ss TOAST relation for later
+    */
+   toast_relid = onerel->rd_rel->reltoastrelid;
+
    /*
     * Set up statistics-gathering machinery.
     */
@@ -430,7 +429,8 @@ vacuum_rel(Oid relid, bool analyze, bool is_toastrel)
    reindex = false;
    vacuum_pages.num_pages = fraged_pages.num_pages = 0;
    scan_heap(vacrelstats, onerel, &vacuum_pages, &fraged_pages);
-   if (IsIgnoringSystemIndexes() && IsSystemRelationName(RelationGetRelationName(onerel)))
+   if (IsIgnoringSystemIndexes() &&
+       IsSystemRelationName(RelationGetRelationName(onerel)))
        reindex = true;
 
    /* Now open indices */
@@ -459,30 +459,54 @@ vacuum_rel(Oid relid, bool analyze, bool is_toastrel)
        if (vacuum_pages.num_pages > 0)
        {
            for (i = 0; i < nindices; i++)
-               vacuum_index(&vacuum_pages, Irel[i], vacrelstats->num_tuples, 0);
+               vacuum_index(&vacuum_pages, Irel[i],
+                            vacrelstats->num_tuples, 0);
        }
        else
-       /* just scan indices to update statistic */
        {
+           /* just scan indices to update statistic */
            for (i = 0; i < nindices; i++)
                scan_index(Irel[i], vacrelstats->num_tuples);
        }
    }
 
-   if (fraged_pages.num_pages > 0) /* Try to shrink heap */
-       repair_frag(vacrelstats, onerel, &vacuum_pages, &fraged_pages, nindices, Irel);
+   if (fraged_pages.num_pages > 0)
+   {
+       /* Try to shrink heap */
+       repair_frag(vacrelstats, onerel, &vacuum_pages, &fraged_pages,
+                   nindices, Irel);
+   }
    else
    {
        if (Irel != (Relation *) NULL)
            close_indices(nindices, Irel);
-       if (vacuum_pages.num_pages > 0)     /* Clean pages from
-                                                * vacuum_pages list */
+       if (vacuum_pages.num_pages > 0)
+       {
+           /* Clean pages from vacuum_pages list */
            vacuum_heap(vacrelstats, onerel, &vacuum_pages);
+       }
+       else
+       {
+           /*
+            * Flush dirty pages out to disk.  We must do this even if we
+            * didn't do anything else, because we want to ensure that all
+            * tuples have correct on-row commit status on disk (see
+            * bufmgr.c's comments for FlushRelationBuffers()).
+            */
+           i = FlushRelationBuffers(onerel, vacrelstats->num_pages);
+           if (i < 0)
+               elog(ERROR, "VACUUM (vacuum_rel): FlushRelationBuffers returned %d",
+                    i);
+       }
    }
    if (reindex)
        activate_indexes_of_a_table(relid, true);
 
-   /* ok - free vacuum_pages list of reaped pages */
+   /*
+    * ok - free vacuum_pages list of reaped pages
+    *
+    * Isn't this a waste of code?  Upcoming commit should free memory, no?
+    */
    if (vacuum_pages.num_pages > 0)
    {
        vacpage = vacuum_pages.pagedesc;
@@ -498,12 +522,14 @@ vacuum_rel(Oid relid, bool analyze, bool is_toastrel)
 
    /* update statistics in pg_class */
    update_relstats(vacrelstats->relid, vacrelstats->num_pages,
-           vacrelstats->num_tuples, vacrelstats->hasindex, vacrelstats);
+                   vacrelstats->num_tuples, vacrelstats->hasindex,
+                   vacrelstats);
 
-   /* If the relation has a secondary toast one, vacuum that too
+   /*
+    * If the relation has a secondary toast one, vacuum that too
     * while we still hold the lock on the master table. We don't
     * need to propagate "analyze" to it, because the toaster
-    * allways uses hardcoded index access and statistics are
+    * always uses hardcoded index access and statistics are
     * totally unimportant for toast relations
     */
    if (toast_relid != InvalidOid)
@@ -1820,12 +1846,20 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
        pfree(Nvacpagelist.pagedesc);
    }
 
-   /* truncate relation, after flushing any dirty pages out to disk */
+   /*
+    * Flush dirty pages out to disk.  We do this unconditionally, even if
+    * we don't need to truncate, because we want to ensure that all tuples
+    * have correct on-row commit status on disk (see bufmgr.c's comments
+    * for FlushRelationBuffers()).
+    */
+   i = FlushRelationBuffers(onerel, blkno);
+   if (i < 0)
+       elog(ERROR, "VACUUM (repair_frag): FlushRelationBuffers returned %d",
+            i);
+
+   /* truncate relation, if needed */
    if (blkno < nblocks)
    {
-       i = FlushRelationBuffers(onerel, blkno);
-       if (i < 0)
-           elog(FATAL, "VACUUM (repair_frag): FlushRelationBuffers returned %d", i);
        blkno = smgrtruncate(DEFAULT_SMGR, onerel, blkno);
        Assert(blkno >= 0);
        vacrelstats->num_pages = blkno; /* set new number of blocks */
@@ -1840,7 +1874,6 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
    pfree(vacpage);
    if (vacrelstats->vtlinks != NULL)
        pfree(vacrelstats->vtlinks);
-
 }
 
 /*
@@ -1860,7 +1893,7 @@ vacuum_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages)
 
    nblocks = vacuum_pages->num_pages;
    nblocks -= vacuum_pages->empty_end_pages;       /* nothing to do with
-                                                        * them */
+                                                    * them */
 
    for (i = 0, vacpage = vacuum_pages->pagedesc; i < nblocks; i++, vacpage++)
    {
@@ -1873,33 +1906,30 @@ vacuum_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages)
        }
    }
 
+   /*
+    * Flush dirty pages out to disk.  We do this unconditionally, even if
+    * we don't need to truncate, because we want to ensure that all tuples
+    * have correct on-row commit status on disk (see bufmgr.c's comments
+    * for FlushRelationBuffers()).
+    */
+   Assert(vacrelstats->num_pages >= vacuum_pages->empty_end_pages);
+   nblocks = vacrelstats->num_pages - vacuum_pages->empty_end_pages;
+
+   i = FlushRelationBuffers(onerel, nblocks);
+   if (i < 0)
+       elog(ERROR, "VACUUM (vacuum_heap): FlushRelationBuffers returned %d",
+            i);
+
    /* truncate relation if there are some empty end-pages */
    if (vacuum_pages->empty_end_pages > 0)
    {
-       Assert(vacrelstats->num_pages >= vacuum_pages->empty_end_pages);
-       nblocks = vacrelstats->num_pages - vacuum_pages->empty_end_pages;
        elog(MESSAGE_LEVEL, "Rel %s: Pages: %u --> %u.",
             RelationGetRelationName(onerel),
             vacrelstats->num_pages, nblocks);
-
-       /*
-        * We have to flush "empty" end-pages (if changed, but who knows
-        * it) before truncation
-        *
-        * XXX is FlushBufferPool() still needed here?
-        */
-       FlushBufferPool();
-
-       i = FlushRelationBuffers(onerel, nblocks);
-       if (i < 0)
-           elog(FATAL, "VACUUM (vacuum_heap): FlushRelationBuffers returned %d", i);
-
        nblocks = smgrtruncate(DEFAULT_SMGR, onerel, nblocks);
        Assert(nblocks >= 0);
-       vacrelstats->num_pages = nblocks;       /* set new number of
-                                                * blocks */
+       vacrelstats->num_pages = nblocks; /* set new number of blocks */
    }
-
 }
 
 /*