aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/nbtree/nbtree.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/nbtree/nbtree.c')
-rw-r--r--src/backend/access/nbtree/nbtree.c63
1 files changed, 57 insertions, 6 deletions
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index c7f23da4c7a..b7a1e7ada1c 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -12,7 +12,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.96 2003/02/22 00:45:04 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.97 2003/02/23 06:17:13 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -710,15 +710,16 @@ Datum
btvacuumcleanup(PG_FUNCTION_ARGS)
{
Relation rel = (Relation) PG_GETARG_POINTER(0);
-#ifdef NOT_USED
IndexVacuumCleanupInfo *info = (IndexVacuumCleanupInfo *) PG_GETARG_POINTER(1);
-#endif
IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(2);
BlockNumber num_pages;
BlockNumber blkno;
PageFreeSpaceInfo *pageSpaces;
int nFreePages,
maxFreePages;
+ BlockNumber pages_deleted = 0;
+ MemoryContext mycontext;
+ MemoryContext oldcontext;
Assert(stats != NULL);
@@ -731,6 +732,13 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
pageSpaces = (PageFreeSpaceInfo *) palloc(maxFreePages * sizeof(PageFreeSpaceInfo));
nFreePages = 0;
+ /* Create a temporary memory context to run _bt_pagedel in */
+ mycontext = AllocSetContextCreate(CurrentMemoryContext,
+ "_bt_pagedel",
+ ALLOCSET_DEFAULT_MINSIZE,
+ ALLOCSET_DEFAULT_INITSIZE,
+ ALLOCSET_DEFAULT_MAXSIZE);
+
/*
* Scan through all pages of index, except metapage. (Any pages added
* after we start the scan will not be examined; this should be fine,
@@ -745,17 +753,53 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
buf = _bt_getbuf(rel, blkno, BT_READ);
page = BufferGetPage(buf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
- if (P_ISDELETED(opaque))
+ if (_bt_page_recyclable(page))
{
- /* XXX if safe-to-reclaim... */
+ /* Okay to recycle this page */
if (nFreePages < maxFreePages)
{
pageSpaces[nFreePages].blkno = blkno;
- /* The avail-space value is bogus, but must be < BLCKSZ */
+ /* claimed avail-space must be < BLCKSZ */
pageSpaces[nFreePages].avail = BLCKSZ-1;
nFreePages++;
}
}
+ else if ((opaque->btpo_flags & BTP_HALF_DEAD) ||
+ P_FIRSTDATAKEY(opaque) > PageGetMaxOffsetNumber(page))
+ {
+ /* Empty, try to delete */
+ int ndel;
+
+ /* Run pagedel in a temp context to avoid memory leakage */
+ MemoryContextReset(mycontext);
+ oldcontext = MemoryContextSwitchTo(mycontext);
+
+ ndel = _bt_pagedel(rel, buf, info->vacuum_full);
+ pages_deleted += ndel;
+
+ /*
+ * During VACUUM FULL it's okay to recycle deleted pages
+ * immediately, since there can be no other transactions
+ * scanning the index. Note that we will only recycle the
+ * current page and not any parent pages that _bt_pagedel
+ * might have recursed to; this seems reasonable in the name
+ * of simplicity. (Trying to do otherwise would mean we'd
+ * have to sort the list of recyclable pages we're building.)
+ */
+ if (ndel && info->vacuum_full)
+ {
+ if (nFreePages < maxFreePages)
+ {
+ pageSpaces[nFreePages].blkno = blkno;
+ /* claimed avail-space must be < BLCKSZ */
+ pageSpaces[nFreePages].avail = BLCKSZ-1;
+ nFreePages++;
+ }
+ }
+
+ MemoryContextSwitchTo(oldcontext);
+ continue; /* pagedel released buffer */
+ }
_bt_relbuf(rel, buf);
}
@@ -768,6 +812,13 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
pfree(pageSpaces);
+ MemoryContextDelete(mycontext);
+
+ if (pages_deleted > 0)
+ elog(info->message_level, "Index %s: %u pages, deleted %u; %u now free",
+ RelationGetRelationName(rel),
+ num_pages, pages_deleted, nFreePages);
+
/* update statistics */
stats->num_pages = num_pages;
stats->pages_free = nFreePages;