Commit 95563e7b authored by Tom Lane's avatar Tom Lane

Make sure that FlushRelationBuffers() is invoked by all paths through

vacuum.c.  This is needed to make the world safe for pg_upgrade.
parent ba2ea6e0
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -397,12 +397,6 @@ vacuum_rel(Oid relid, bool analyze, bool is_toastrel)
*/ */
onerel = heap_open(relid, AccessExclusiveLock); onerel = heap_open(relid, AccessExclusiveLock);
/*
* Remember the relations TOAST relation for later
*
*/
toast_relid = onerel->rd_rel->reltoastrelid;
#ifndef NO_SECURITY #ifndef NO_SECURITY
if (!pg_ownercheck(GetUserId(), RelationGetRelationName(onerel), if (!pg_ownercheck(GetUserId(), RelationGetRelationName(onerel),
RELNAME)) RELNAME))
...@@ -416,6 +410,11 @@ vacuum_rel(Oid relid, bool analyze, bool is_toastrel) ...@@ -416,6 +410,11 @@ vacuum_rel(Oid relid, bool analyze, bool is_toastrel)
} }
#endif #endif
/*
* Remember the relation'ss TOAST relation for later
*/
toast_relid = onerel->rd_rel->reltoastrelid;
/* /*
* Set up statistics-gathering machinery. * Set up statistics-gathering machinery.
*/ */
...@@ -430,7 +429,8 @@ vacuum_rel(Oid relid, bool analyze, bool is_toastrel) ...@@ -430,7 +429,8 @@ vacuum_rel(Oid relid, bool analyze, bool is_toastrel)
reindex = false; reindex = false;
vacuum_pages.num_pages = fraged_pages.num_pages = 0; vacuum_pages.num_pages = fraged_pages.num_pages = 0;
scan_heap(vacrelstats, onerel, &vacuum_pages, &fraged_pages); scan_heap(vacrelstats, onerel, &vacuum_pages, &fraged_pages);
if (IsIgnoringSystemIndexes() && IsSystemRelationName(RelationGetRelationName(onerel))) if (IsIgnoringSystemIndexes() &&
IsSystemRelationName(RelationGetRelationName(onerel)))
reindex = true; reindex = true;
/* Now open indices */ /* Now open indices */
...@@ -459,30 +459,54 @@ vacuum_rel(Oid relid, bool analyze, bool is_toastrel) ...@@ -459,30 +459,54 @@ vacuum_rel(Oid relid, bool analyze, bool is_toastrel)
if (vacuum_pages.num_pages > 0) if (vacuum_pages.num_pages > 0)
{ {
for (i = 0; i < nindices; i++) 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 else
/* just scan indices to update statistic */
{ {
/* just scan indices to update statistic */
for (i = 0; i < nindices; i++) for (i = 0; i < nindices; i++)
scan_index(Irel[i], vacrelstats->num_tuples); scan_index(Irel[i], vacrelstats->num_tuples);
} }
} }
if (fraged_pages.num_pages > 0) /* Try to shrink heap */ if (fraged_pages.num_pages > 0)
repair_frag(vacrelstats, onerel, &vacuum_pages, &fraged_pages, nindices, Irel); {
/* Try to shrink heap */
repair_frag(vacrelstats, onerel, &vacuum_pages, &fraged_pages,
nindices, Irel);
}
else else
{ {
if (Irel != (Relation *) NULL) if (Irel != (Relation *) NULL)
close_indices(nindices, Irel); close_indices(nindices, Irel);
if (vacuum_pages.num_pages > 0) /* Clean pages from if (vacuum_pages.num_pages > 0)
* vacuum_pages list */ {
/* Clean pages from vacuum_pages list */
vacuum_heap(vacrelstats, onerel, &vacuum_pages); 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) if (reindex)
activate_indexes_of_a_table(relid, true); 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) if (vacuum_pages.num_pages > 0)
{ {
vacpage = vacuum_pages.pagedesc; vacpage = vacuum_pages.pagedesc;
...@@ -498,12 +522,14 @@ vacuum_rel(Oid relid, bool analyze, bool is_toastrel) ...@@ -498,12 +522,14 @@ vacuum_rel(Oid relid, bool analyze, bool is_toastrel)
/* update statistics in pg_class */ /* update statistics in pg_class */
update_relstats(vacrelstats->relid, vacrelstats->num_pages, 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 * while we still hold the lock on the master table. We don't
* need to propagate "analyze" to it, because the toaster * 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 * totally unimportant for toast relations
*/ */
if (toast_relid != InvalidOid) 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)", ...@@ -1820,12 +1846,20 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
pfree(Nvacpagelist.pagedesc); pfree(Nvacpagelist.pagedesc);
} }
/* truncate relation, after flushing any dirty pages out to disk */ /*
if (blkno < nblocks) * 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); i = FlushRelationBuffers(onerel, blkno);
if (i < 0) if (i < 0)
elog(FATAL, "VACUUM (repair_frag): FlushRelationBuffers returned %d", i); elog(ERROR, "VACUUM (repair_frag): FlushRelationBuffers returned %d",
i);
/* truncate relation, if needed */
if (blkno < nblocks)
{
blkno = smgrtruncate(DEFAULT_SMGR, onerel, blkno); blkno = smgrtruncate(DEFAULT_SMGR, onerel, blkno);
Assert(blkno >= 0); Assert(blkno >= 0);
vacrelstats->num_pages = blkno; /* set new number of blocks */ 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)", ...@@ -1840,7 +1874,6 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
pfree(vacpage); pfree(vacpage);
if (vacrelstats->vtlinks != NULL) if (vacrelstats->vtlinks != NULL)
pfree(vacrelstats->vtlinks); pfree(vacrelstats->vtlinks);
} }
/* /*
...@@ -1873,33 +1906,30 @@ vacuum_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages) ...@@ -1873,33 +1906,30 @@ vacuum_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages)
} }
} }
/* 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 * Flush dirty pages out to disk. We do this unconditionally, even if
* it) before truncation * 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
* XXX is FlushBufferPool() still needed here? * for FlushRelationBuffers()).
*/ */
FlushBufferPool(); Assert(vacrelstats->num_pages >= vacuum_pages->empty_end_pages);
nblocks = vacrelstats->num_pages - vacuum_pages->empty_end_pages;
i = FlushRelationBuffers(onerel, nblocks); i = FlushRelationBuffers(onerel, nblocks);
if (i < 0) if (i < 0)
elog(FATAL, "VACUUM (vacuum_heap): FlushRelationBuffers returned %d", i); 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)
{
elog(MESSAGE_LEVEL, "Rel %s: Pages: %u --> %u.",
RelationGetRelationName(onerel),
vacrelstats->num_pages, nblocks);
nblocks = smgrtruncate(DEFAULT_SMGR, onerel, nblocks); nblocks = smgrtruncate(DEFAULT_SMGR, onerel, nblocks);
Assert(nblocks >= 0); Assert(nblocks >= 0);
vacrelstats->num_pages = nblocks; /* set new number of vacrelstats->num_pages = nblocks; /* set new number of blocks */
* blocks */
} }
} }
/* /*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment