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

vacuum.c.  This is needed to make the world safe for pg_upgrade.
This commit is contained in:
Tom Lane 2000-09-19 19:30:03 +00:00
parent ba2ea6e0f5
commit 95563e7bbf
1 changed files with 72 additions and 42 deletions

View 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 */
}
}
/*