Commit 799bc58d authored by Tom Lane's avatar Tom Lane

More infrastructure for btree compaction project. Tree-traversal code

now knows what to do upon hitting a dead page (in theory anyway, it's
untested...).  Add a post-VACUUM-cleanup entry point for index AMs, to
provide a place for dead-page scavenging to happen.
Also, fix oversight that broke btpo_prev links in temporary indexes.
initdb forced due to additions in pg_am.
parent 4fff132d
<!-- <!--
Documentation of the system catalogs, directed toward PostgreSQL developers Documentation of the system catalogs, directed toward PostgreSQL developers
$Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.65 2003/01/19 00:13:28 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.66 2003/02/22 00:45:03 tgl Exp $
--> -->
<chapter id="catalogs"> <chapter id="catalogs">
...@@ -446,6 +446,13 @@ ...@@ -446,6 +446,13 @@
<entry>bulk-delete function</entry> <entry>bulk-delete function</entry>
</row> </row>
<row>
<entry>amvacuumcleanup</entry>
<entry><type>regproc</type></entry>
<entry>pg_proc.oid</entry>
<entry>post-VACUUM cleanup function</entry>
</row>
<row> <row>
<entry>amcostestimate</entry> <entry>amcostestimate</entry>
<entry><type>regproc</type></entry> <entry><type>regproc</type></entry>
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/gist/gist.c,v 1.99 2002/11/13 00:39:46 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/gist/gist.c,v 1.100 2003/02/22 00:45:03 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1650,8 +1650,9 @@ gistbulkdelete(PG_FUNCTION_ARGS) ...@@ -1650,8 +1650,9 @@ gistbulkdelete(PG_FUNCTION_ARGS)
result = (IndexBulkDeleteResult *) palloc(sizeof(IndexBulkDeleteResult)); result = (IndexBulkDeleteResult *) palloc(sizeof(IndexBulkDeleteResult));
result->num_pages = num_pages; result->num_pages = num_pages;
result->tuples_removed = tuples_removed;
result->num_index_tuples = num_index_tuples; result->num_index_tuples = num_index_tuples;
result->tuples_removed = tuples_removed;
result->pages_free = 0;
PG_RETURN_POINTER(result); PG_RETURN_POINTER(result);
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.60 2002/09/04 20:31:09 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.61 2003/02/22 00:45:03 tgl Exp $
* *
* NOTES * NOTES
* This file contains only the public interface routines. * This file contains only the public interface routines.
...@@ -491,8 +491,9 @@ hashbulkdelete(PG_FUNCTION_ARGS) ...@@ -491,8 +491,9 @@ hashbulkdelete(PG_FUNCTION_ARGS)
result = (IndexBulkDeleteResult *) palloc(sizeof(IndexBulkDeleteResult)); result = (IndexBulkDeleteResult *) palloc(sizeof(IndexBulkDeleteResult));
result->num_pages = num_pages; result->num_pages = num_pages;
result->tuples_removed = tuples_removed;
result->num_index_tuples = num_index_tuples; result->num_index_tuples = num_index_tuples;
result->tuples_removed = tuples_removed;
result->pages_free = 0;
PG_RETURN_POINTER(result); PG_RETURN_POINTER(result);
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.63 2003/01/08 19:41:40 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.64 2003/02/22 00:45:03 tgl Exp $
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
* index_open - open an index relation by relation OID * index_open - open an index relation by relation OID
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
* index_restrpos - restore a scan position * index_restrpos - restore a scan position
* index_getnext - get the next tuple from a scan * index_getnext - get the next tuple from a scan
* index_bulk_delete - bulk deletion of index tuples * index_bulk_delete - bulk deletion of index tuples
* index_vacuum_cleanup - post-deletion cleanup of an index
* index_cost_estimator - fetch amcostestimate procedure OID * index_cost_estimator - fetch amcostestimate procedure OID
* index_getprocid - get a support procedure OID * index_getprocid - get a support procedure OID
* *
...@@ -579,6 +580,37 @@ index_bulk_delete(Relation indexRelation, ...@@ -579,6 +580,37 @@ index_bulk_delete(Relation indexRelation,
return result; return result;
} }
/* ----------------
* index_vacuum_cleanup - do post-deletion cleanup of an index
*
* return value is an optional palloc'd struct of statistics
* ----------------
*/
IndexBulkDeleteResult *
index_vacuum_cleanup(Relation indexRelation,
IndexVacuumCleanupInfo *info,
IndexBulkDeleteResult *stats)
{
RegProcedure procedure;
IndexBulkDeleteResult *result;
RELATION_CHECKS;
/* It's okay for an index AM not to have a vacuumcleanup procedure */
if (!RegProcedureIsValid(indexRelation->rd_am->amvacuumcleanup))
return stats;
GET_REL_PROCEDURE(vacuum_cleanup, amvacuumcleanup);
result = (IndexBulkDeleteResult *)
DatumGetPointer(OidFunctionCall3(procedure,
PointerGetDatum(indexRelation),
PointerGetDatum((Pointer) info),
PointerGetDatum((Pointer) stats)));
return result;
}
/* ---------------- /* ----------------
* index_cost_estimator * index_cost_estimator
* *
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.97 2003/02/21 00:06:21 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.98 2003/02/22 00:45:03 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -280,12 +280,21 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel, ...@@ -280,12 +280,21 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel,
if (!_bt_isequal(itupdesc, page, P_HIKEY, if (!_bt_isequal(itupdesc, page, P_HIKEY,
natts, itup_scankey)) natts, itup_scankey))
break; break;
nblkno = opaque->btpo_next; /* Advance to next non-dead page --- there must be one */
if (nbuf != InvalidBuffer) for (;;)
_bt_relbuf(rel, nbuf); {
nbuf = _bt_getbuf(rel, nblkno, BT_READ); nblkno = opaque->btpo_next;
page = BufferGetPage(nbuf); if (nbuf != InvalidBuffer)
opaque = (BTPageOpaque) PageGetSpecialPointer(page); _bt_relbuf(rel, nbuf);
nbuf = _bt_getbuf(rel, nblkno, BT_READ);
page = BufferGetPage(nbuf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
if (!P_IGNORE(opaque))
break;
if (P_RIGHTMOST(opaque))
elog(ERROR, "_bt_check_unique: fell off the end of %s",
RelationGetRelationName(rel));
}
maxoff = PageGetMaxOffsetNumber(page); maxoff = PageGetMaxOffsetNumber(page);
offset = P_FIRSTDATAKEY(opaque); offset = P_FIRSTDATAKEY(opaque);
} }
...@@ -414,20 +423,34 @@ _bt_insertonpg(Relation rel, ...@@ -414,20 +423,34 @@ _bt_insertonpg(Relation rel,
_bt_compare(rel, keysz, scankey, page, P_HIKEY) == 0 && _bt_compare(rel, keysz, scankey, page, P_HIKEY) == 0 &&
random() > (MAX_RANDOM_VALUE / 100)) random() > (MAX_RANDOM_VALUE / 100))
{ {
/* step right one page */
BlockNumber rblkno = lpageop->btpo_next;
Buffer rbuf;
/* /*
* must write-lock next page before releasing write lock on * step right to next non-dead page
*
* must write-lock that page before releasing write lock on
* current page; else someone else's _bt_check_unique scan * current page; else someone else's _bt_check_unique scan
* could fail to see our insertion. * could fail to see our insertion. write locks on intermediate
* dead pages won't do because we don't know when they will get
* de-linked from the tree.
*/ */
rbuf = _bt_getbuf(rel, rblkno, BT_WRITE); Buffer rbuf = InvalidBuffer;
for (;;)
{
BlockNumber rblkno = lpageop->btpo_next;
if (rbuf != InvalidBuffer)
_bt_relbuf(rel, rbuf);
rbuf = _bt_getbuf(rel, rblkno, BT_WRITE);
page = BufferGetPage(rbuf);
lpageop = (BTPageOpaque) PageGetSpecialPointer(page);
if (!P_IGNORE(lpageop))
break;
if (P_RIGHTMOST(lpageop))
elog(ERROR, "_bt_insertonpg: fell off the end of %s",
RelationGetRelationName(rel));
}
_bt_relbuf(rel, buf); _bt_relbuf(rel, buf);
buf = rbuf; buf = rbuf;
page = BufferGetPage(buf);
lpageop = (BTPageOpaque) PageGetSpecialPointer(page);
movedright = true; movedright = true;
} }
...@@ -633,8 +656,9 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright, ...@@ -633,8 +656,9 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
BTPageOpaque ropaque, BTPageOpaque ropaque,
lopaque, lopaque,
oopaque; oopaque;
Buffer sbuf = 0; Buffer sbuf = InvalidBuffer;
Page spage = 0; Page spage = NULL;
BTPageOpaque sopaque = NULL;
Size itemsz; Size itemsz;
ItemId itemid; ItemId itemid;
BTItem item; BTItem item;
...@@ -792,6 +816,9 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright, ...@@ -792,6 +816,9 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
{ {
sbuf = _bt_getbuf(rel, ropaque->btpo_next, BT_WRITE); sbuf = _bt_getbuf(rel, ropaque->btpo_next, BT_WRITE);
spage = BufferGetPage(sbuf); spage = BufferGetPage(sbuf);
sopaque = (BTPageOpaque) PageGetSpecialPointer(spage);
if (sopaque->btpo_prev != ropaque->btpo_prev)
elog(PANIC, "btree: right sibling's left-link doesn't match");
} }
/* /*
...@@ -802,6 +829,9 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright, ...@@ -802,6 +829,9 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
*/ */
START_CRIT_SECTION(); START_CRIT_SECTION();
if (!P_RIGHTMOST(ropaque))
sopaque->btpo_prev = BufferGetBlockNumber(rbuf);
/* XLOG stuff */ /* XLOG stuff */
if (!rel->rd_istemp) if (!rel->rd_istemp)
{ {
...@@ -847,10 +877,6 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright, ...@@ -847,10 +877,6 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
if (!P_RIGHTMOST(ropaque)) if (!P_RIGHTMOST(ropaque))
{ {
BTPageOpaque sopaque = (BTPageOpaque) PageGetSpecialPointer(spage);
sopaque->btpo_prev = BufferGetBlockNumber(rbuf);
rdata[2].next = &(rdata[3]); rdata[2].next = &(rdata[3]);
rdata[3].buffer = sbuf; rdata[3].buffer = sbuf;
rdata[3].data = NULL; rdata[3].data = NULL;
...@@ -1250,58 +1276,63 @@ _bt_getstackbuf(Relation rel, BTStack stack, int access) ...@@ -1250,58 +1276,63 @@ _bt_getstackbuf(Relation rel, BTStack stack, int access)
Buffer buf; Buffer buf;
Page page; Page page;
BTPageOpaque opaque; BTPageOpaque opaque;
OffsetNumber offnum,
minoff,
maxoff;
ItemId itemid;
BTItem item;
buf = _bt_getbuf(rel, blkno, access); buf = _bt_getbuf(rel, blkno, access);
page = BufferGetPage(buf); page = BufferGetPage(buf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page); opaque = (BTPageOpaque) PageGetSpecialPointer(page);
minoff = P_FIRSTDATAKEY(opaque);
maxoff = PageGetMaxOffsetNumber(page);
/* if (!P_IGNORE(opaque))
* start = InvalidOffsetNumber means "search the whole page".
* We need this test anyway due to possibility that
* page has a high key now when it didn't before.
*/
if (start < minoff)
start = minoff;
/*
* These loops will check every item on the page --- but in an order
* that's attuned to the probability of where it actually is. Scan
* to the right first, then to the left.
*/
for (offnum = start;
offnum <= maxoff;
offnum = OffsetNumberNext(offnum))
{ {
itemid = PageGetItemId(page, offnum); OffsetNumber offnum,
item = (BTItem) PageGetItem(page, itemid); minoff,
if (BTItemSame(item, &stack->bts_btitem)) maxoff;
ItemId itemid;
BTItem item;
minoff = P_FIRSTDATAKEY(opaque);
maxoff = PageGetMaxOffsetNumber(page);
/*
* start = InvalidOffsetNumber means "search the whole page".
* We need this test anyway due to possibility that
* page has a high key now when it didn't before.
*/
if (start < minoff)
start = minoff;
/*
* These loops will check every item on the page --- but in an
* order that's attuned to the probability of where it actually
* is. Scan to the right first, then to the left.
*/
for (offnum = start;
offnum <= maxoff;
offnum = OffsetNumberNext(offnum))
{ {
/* Return accurate pointer to where link is now */ itemid = PageGetItemId(page, offnum);
stack->bts_blkno = blkno; item = (BTItem) PageGetItem(page, itemid);
stack->bts_offset = offnum; if (BTItemSame(item, &stack->bts_btitem))
return buf; {
/* Return accurate pointer to where link is now */
stack->bts_blkno = blkno;
stack->bts_offset = offnum;
return buf;
}
} }
}
for (offnum = OffsetNumberPrev(start); for (offnum = OffsetNumberPrev(start);
offnum >= minoff; offnum >= minoff;
offnum = OffsetNumberPrev(offnum)) offnum = OffsetNumberPrev(offnum))
{
itemid = PageGetItemId(page, offnum);
item = (BTItem) PageGetItem(page, itemid);
if (BTItemSame(item, &stack->bts_btitem))
{ {
/* Return accurate pointer to where link is now */ itemid = PageGetItemId(page, offnum);
stack->bts_blkno = blkno; item = (BTItem) PageGetItem(page, itemid);
stack->bts_offset = offnum; if (BTItemSame(item, &stack->bts_btitem))
return buf; {
/* Return accurate pointer to where link is now */
stack->bts_blkno = blkno;
stack->bts_offset = offnum;
return buf;
}
} }
} }
...@@ -1365,6 +1396,8 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf) ...@@ -1365,6 +1396,8 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
rootbuf = _bt_getbuf(rel, P_NEW, BT_WRITE); rootbuf = _bt_getbuf(rel, P_NEW, BT_WRITE);
rootpage = BufferGetPage(rootbuf); rootpage = BufferGetPage(rootbuf);
rootblknum = BufferGetBlockNumber(rootbuf); rootblknum = BufferGetBlockNumber(rootbuf);
/* acquire lock on the metapage */
metabuf = _bt_getbuf(rel, BTREE_METAPAGE, BT_WRITE); metabuf = _bt_getbuf(rel, BTREE_METAPAGE, BT_WRITE);
metapg = BufferGetPage(metabuf); metapg = BufferGetPage(metabuf);
metad = BTPageGetMeta(metapg); metad = BTPageGetMeta(metapg);
......
This diff is collapsed.
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.95 2003/02/21 00:06:21 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.96 2003/02/22 00:45:04 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "access/nbtree.h" #include "access/nbtree.h"
#include "catalog/index.h" #include "catalog/index.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "storage/freespace.h"
/* Working state for btbuild and its callback */ /* Working state for btbuild and its callback */
...@@ -44,7 +45,6 @@ typedef struct ...@@ -44,7 +45,6 @@ typedef struct
} BTBuildState; } BTBuildState;
bool BuildingBtree = false; /* see comment in btbuild() */
bool FastBuild = true; /* use SORT instead of insertion build */ bool FastBuild = true; /* use SORT instead of insertion build */
/* /*
...@@ -68,13 +68,7 @@ static void btbuildCallback(Relation index, ...@@ -68,13 +68,7 @@ static void btbuildCallback(Relation index,
void void
AtEOXact_nbtree(void) AtEOXact_nbtree(void)
{ {
/* /* nothing to do at the moment */
* Note: these actions should only be necessary during xact abort; but
* they can't hurt during a commit.
*/
/* If we were building a btree, we ain't anymore. */
BuildingBtree = false;
} }
...@@ -95,9 +89,6 @@ btbuild(PG_FUNCTION_ARGS) ...@@ -95,9 +89,6 @@ btbuild(PG_FUNCTION_ARGS)
double reltuples; double reltuples;
BTBuildState buildstate; BTBuildState buildstate;
/* set flag to disable locking */
BuildingBtree = true;
/* /*
* bootstrap processing does something strange, so don't use * bootstrap processing does something strange, so don't use
* sort/build for initial catalog indices. at some point i need to * sort/build for initial catalog indices. at some point i need to
...@@ -172,9 +163,6 @@ btbuild(PG_FUNCTION_ARGS) ...@@ -172,9 +163,6 @@ btbuild(PG_FUNCTION_ARGS)
} }
#endif /* BTREE_BUILD_STATS */ #endif /* BTREE_BUILD_STATS */
/* all done */
BuildingBtree = false;
/* /*
* Since we just counted the tuples in the heap, we update its stats * Since we just counted the tuples in the heap, we update its stats
* in pg_class to guarantee that the planner takes advantage of the * in pg_class to guarantee that the planner takes advantage of the
...@@ -689,10 +677,6 @@ btbulkdelete(PG_FUNCTION_ARGS) ...@@ -689,10 +677,6 @@ btbulkdelete(PG_FUNCTION_ARGS)
* We now need to back up the scan one item, so that the next * We now need to back up the scan one item, so that the next
* cycle will re-examine the same offnum on this page (which * cycle will re-examine the same offnum on this page (which
* now holds the next item). * now holds the next item).
*
* For now, just hack the current-item index. Will need to
* be smarter when deletion includes removal of empty
* index pages.
*/ */
current->ip_posid--; current->ip_posid--;
} }
...@@ -708,12 +692,89 @@ btbulkdelete(PG_FUNCTION_ARGS) ...@@ -708,12 +692,89 @@ btbulkdelete(PG_FUNCTION_ARGS)
result = (IndexBulkDeleteResult *) palloc(sizeof(IndexBulkDeleteResult)); result = (IndexBulkDeleteResult *) palloc(sizeof(IndexBulkDeleteResult));
result->num_pages = num_pages; result->num_pages = num_pages;
result->tuples_removed = tuples_removed;
result->num_index_tuples = num_index_tuples; result->num_index_tuples = num_index_tuples;
result->tuples_removed = tuples_removed;
result->pages_free = 0; /* not computed here */
PG_RETURN_POINTER(result); PG_RETURN_POINTER(result);
} }
/*
* Post-VACUUM cleanup.
*
* Here, we scan looking for pages we can delete or return to the freelist.
*
* Result: a palloc'd struct containing statistical info for VACUUM displays.
*/
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;
Assert(stats != NULL);
num_pages = RelationGetNumberOfBlocks(rel);
/* No point in remembering more than MaxFSMPages pages */
maxFreePages = MaxFSMPages;
if ((BlockNumber) maxFreePages > num_pages)
maxFreePages = (int) num_pages + 1; /* +1 to avoid palloc(0) */
pageSpaces = (PageFreeSpaceInfo *) palloc(maxFreePages * sizeof(PageFreeSpaceInfo));
nFreePages = 0;
/*
* Scan through all pages of index, except metapage. (Any pages added
* after we start the scan will not be examined; this should be fine,
* since they can't possibly be empty.)
*/
for (blkno = BTREE_METAPAGE+1; blkno < num_pages; blkno++)
{
Buffer buf;
Page page;
BTPageOpaque opaque;
buf = _bt_getbuf(rel, blkno, BT_READ);
page = BufferGetPage(buf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
if (P_ISDELETED(opaque))
{
/* XXX if safe-to-reclaim... */
if (nFreePages < maxFreePages)
{
pageSpaces[nFreePages].blkno = blkno;
/* The avail-space value is bogus, but must be < BLCKSZ */
pageSpaces[nFreePages].avail = BLCKSZ-1;
nFreePages++;
}
}
_bt_relbuf(rel, buf);
}
/*
* Update the shared Free Space Map with the info we now have about
* free space in the index, discarding any old info the map may have.
* We do not need to sort the page numbers; they're in order already.
*/
MultiRecordFreeSpace(&rel->rd_node, 0, nFreePages, pageSpaces);
pfree(pageSpaces);
/* update statistics */
stats->num_pages = num_pages;
stats->pages_free = nFreePages;
PG_RETURN_POINTER(stats);
}
/* /*
* Restore scan position when btgettuple is called to continue a scan. * Restore scan position when btgettuple is called to continue a scan.
* *
...@@ -739,7 +800,7 @@ _bt_restscan(IndexScanDesc scan) ...@@ -739,7 +800,7 @@ _bt_restscan(IndexScanDesc scan)
maxoff; maxoff;
BTPageOpaque opaque; BTPageOpaque opaque;
Buffer nextbuf; Buffer nextbuf;
ItemPointerData target = so->curHeapIptr; ItemPointer target = &(so->curHeapIptr);
BTItem item; BTItem item;
BlockNumber blkno; BlockNumber blkno;
...@@ -759,7 +820,7 @@ _bt_restscan(IndexScanDesc scan) ...@@ -759,7 +820,7 @@ _bt_restscan(IndexScanDesc scan)
* current->ip_posid before first index tuple on the current page * current->ip_posid before first index tuple on the current page
* (_bt_step will move it right)... XXX still needed? * (_bt_step will move it right)... XXX still needed?
*/ */
if (!ItemPointerIsValid(&target)) if (!ItemPointerIsValid(target))
{ {
ItemPointerSetOffsetNumber(current, ItemPointerSetOffsetNumber(current,
OffsetNumberPrev(P_FIRSTDATAKEY(opaque))); OffsetNumberPrev(P_FIRSTDATAKEY(opaque)));
...@@ -778,11 +839,7 @@ _bt_restscan(IndexScanDesc scan) ...@@ -778,11 +839,7 @@ _bt_restscan(IndexScanDesc scan)
offnum = OffsetNumberNext(offnum)) offnum = OffsetNumberNext(offnum))
{ {
item = (BTItem) PageGetItem(page, PageGetItemId(page, offnum)); item = (BTItem) PageGetItem(page, PageGetItemId(page, offnum));
if (item->bti_itup.t_tid.ip_blkid.bi_hi == if (BTTidSame(item->bti_itup.t_tid, *target))
target.ip_blkid.bi_hi &&
item->bti_itup.t_tid.ip_blkid.bi_lo ==
target.ip_blkid.bi_lo &&
item->bti_itup.t_tid.ip_posid == target.ip_posid)
{ {
/* Found it */ /* Found it */
current->ip_posid = offnum; current->ip_posid = offnum;
...@@ -793,22 +850,33 @@ _bt_restscan(IndexScanDesc scan) ...@@ -793,22 +850,33 @@ _bt_restscan(IndexScanDesc scan)
/* /*
* The item we're looking for moved right at least one page, so * The item we're looking for moved right at least one page, so
* move right. We are careful here to pin and read-lock the next * move right. We are careful here to pin and read-lock the next
* page before releasing the current one. This ensures that a * non-dead page before releasing the current one. This ensures that
* concurrent btbulkdelete scan cannot pass our position --- if it * a concurrent btbulkdelete scan cannot pass our position --- if it
* did, it might be able to reach and delete our target item before * did, it might be able to reach and delete our target item before
* we can find it again. * we can find it again.
*/ */
if (P_RIGHTMOST(opaque)) if (P_RIGHTMOST(opaque))
elog(FATAL, "_bt_restscan: my bits moved right off the end of the world!" elog(ERROR, "_bt_restscan: my bits moved right off the end of the world!"
"\n\tRecreate index %s.", RelationGetRelationName(rel)); "\n\tRecreate index %s.", RelationGetRelationName(rel));
/* Advance to next non-dead page --- there must be one */
blkno = opaque->btpo_next; nextbuf = InvalidBuffer;
nextbuf = _bt_getbuf(rel, blkno, BT_READ); for (;;)
{
blkno = opaque->btpo_next;
if (nextbuf != InvalidBuffer)
_bt_relbuf(rel, nextbuf);
nextbuf = _bt_getbuf(rel, blkno, BT_READ);
page = BufferGetPage(nextbuf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
if (!P_IGNORE(opaque))
break;
if (P_RIGHTMOST(opaque))
elog(ERROR, "_bt_restscan: fell off the end of %s",
RelationGetRelationName(rel));
}
_bt_relbuf(rel, buf); _bt_relbuf(rel, buf);
so->btso_curbuf = buf = nextbuf; so->btso_curbuf = buf = nextbuf;
page = BufferGetPage(buf);
maxoff = PageGetMaxOffsetNumber(page); maxoff = PageGetMaxOffsetNumber(page);
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
offnum = P_FIRSTDATAKEY(opaque); offnum = P_FIRSTDATAKEY(opaque);
ItemPointerSet(current, blkno, offnum); ItemPointerSet(current, blkno, offnum);
} }
......
This diff is collapsed.
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
*
* nbtsort.c * nbtsort.c
* Build a btree from sorted input by loading leaf pages sequentially. * Build a btree from sorted input by loading leaf pages sequentially.
* *
...@@ -35,7 +36,7 @@ ...@@ -35,7 +36,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsort.c,v 1.71 2003/02/21 00:06:21 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsort.c,v 1.72 2003/02/22 00:45:04 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -164,8 +165,8 @@ _bt_leafbuild(BTSpool *btspool, BTSpool *btspool2) ...@@ -164,8 +165,8 @@ _bt_leafbuild(BTSpool *btspool, BTSpool *btspool2)
ResetUsage(); ResetUsage();
} }
#endif /* BTREE_BUILD_STATS */ #endif /* BTREE_BUILD_STATS */
tuplesort_performsort(btspool->sortstate);
tuplesort_performsort(btspool->sortstate);
if (btspool2) if (btspool2)
tuplesort_performsort(btspool2->sortstate); tuplesort_performsort(btspool2->sortstate);
_bt_load(btspool->index, btspool, btspool2); _bt_load(btspool->index, btspool, btspool2);
...@@ -331,7 +332,7 @@ _bt_sortaddtup(Page page, ...@@ -331,7 +332,7 @@ _bt_sortaddtup(Page page,
if (PageAddItem(page, (Item) btitem, itemsize, itup_off, if (PageAddItem(page, (Item) btitem, itemsize, itup_off,
LP_USED) == InvalidOffsetNumber) LP_USED) == InvalidOffsetNumber)
elog(FATAL, "btree: failed to add item to the page in _bt_sort"); elog(ERROR, "btree: failed to add item to the page in _bt_sort");
} }
/*---------- /*----------
...@@ -470,8 +471,7 @@ _bt_buildadd(Relation index, BTPageState *state, BTItem bti) ...@@ -470,8 +471,7 @@ _bt_buildadd(Relation index, BTPageState *state, BTItem bti)
/* /*
* Write out the old page. We never want to see it again, so we * Write out the old page. We never want to see it again, so we
* can give up our lock (if we had one; most likely BuildingBtree * can give up our lock.
* is set, so we aren't locking).
*/ */
_bt_blwritepage(index, obuf); _bt_blwritepage(index, obuf);
...@@ -534,7 +534,7 @@ _bt_uppershutdown(Relation index, BTPageState *state) ...@@ -534,7 +534,7 @@ _bt_uppershutdown(Relation index, BTPageState *state)
if (s->btps_next == (BTPageState *) NULL) if (s->btps_next == (BTPageState *) NULL)
{ {
opaque->btpo_flags |= BTP_ROOT; opaque->btpo_flags |= BTP_ROOT;
_bt_metaproot(index, blkno, s->btps_level + 1); _bt_metaproot(index, blkno, s->btps_level);
} }
else else
{ {
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.75 2002/09/04 20:31:13 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.76 2003/02/22 00:45:04 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1250,8 +1250,9 @@ rtbulkdelete(PG_FUNCTION_ARGS) ...@@ -1250,8 +1250,9 @@ rtbulkdelete(PG_FUNCTION_ARGS)
result = (IndexBulkDeleteResult *) palloc(sizeof(IndexBulkDeleteResult)); result = (IndexBulkDeleteResult *) palloc(sizeof(IndexBulkDeleteResult));
result->num_pages = num_pages; result->num_pages = num_pages;
result->tuples_removed = tuples_removed;
result->num_index_tuples = num_index_tuples; result->num_index_tuples = num_index_tuples;
result->tuples_removed = tuples_removed;
result->pages_free = 0;
PG_RETURN_POINTER(result); PG_RETURN_POINTER(result);
} }
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.247 2003/02/09 06:56:27 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.248 2003/02/22 00:45:05 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -2603,17 +2603,25 @@ static void ...@@ -2603,17 +2603,25 @@ static void
scan_index(Relation indrel, double num_tuples) scan_index(Relation indrel, double num_tuples)
{ {
IndexBulkDeleteResult *stats; IndexBulkDeleteResult *stats;
IndexVacuumCleanupInfo vcinfo;
VacRUsage ru0; VacRUsage ru0;
vac_init_rusage(&ru0); vac_init_rusage(&ru0);
/* /*
* Even though we're not planning to delete anything, use the * Even though we're not planning to delete anything, we use the
* ambulkdelete call, so that the scan happens within the index AM for * ambulkdelete call, because (a) the scan happens within the index AM
* more speed. * for more speed, and (b) it may want to pass private statistics to
* the amvacuumcleanup call.
*/ */
stats = index_bulk_delete(indrel, dummy_tid_reaped, NULL); stats = index_bulk_delete(indrel, dummy_tid_reaped, NULL);
/* Do post-VACUUM cleanup, even though we deleted nothing */
vcinfo.vacuum_full = true;
vcinfo.message_level = elevel;
stats = index_vacuum_cleanup(indrel, &vcinfo, stats);
if (!stats) if (!stats)
return; return;
...@@ -2622,9 +2630,9 @@ scan_index(Relation indrel, double num_tuples) ...@@ -2622,9 +2630,9 @@ scan_index(Relation indrel, double num_tuples)
stats->num_pages, stats->num_index_tuples, stats->num_pages, stats->num_index_tuples,
false); false);
elog(elevel, "Index %s: Pages %u; Tuples %.0f.\n\t%s", elog(elevel, "Index %s: Pages %u, %u free; Tuples %.0f.\n\t%s",
RelationGetRelationName(indrel), RelationGetRelationName(indrel),
stats->num_pages, stats->num_index_tuples, stats->num_pages, stats->pages_free, stats->num_index_tuples,
vac_show_rusage(&ru0)); vac_show_rusage(&ru0));
/* /*
...@@ -2661,6 +2669,7 @@ vacuum_index(VacPageList vacpagelist, Relation indrel, ...@@ -2661,6 +2669,7 @@ vacuum_index(VacPageList vacpagelist, Relation indrel,
double num_tuples, int keep_tuples) double num_tuples, int keep_tuples)
{ {
IndexBulkDeleteResult *stats; IndexBulkDeleteResult *stats;
IndexVacuumCleanupInfo vcinfo;
VacRUsage ru0; VacRUsage ru0;
vac_init_rusage(&ru0); vac_init_rusage(&ru0);
...@@ -2668,6 +2677,12 @@ vacuum_index(VacPageList vacpagelist, Relation indrel, ...@@ -2668,6 +2677,12 @@ vacuum_index(VacPageList vacpagelist, Relation indrel,
/* Do bulk deletion */ /* Do bulk deletion */
stats = index_bulk_delete(indrel, tid_reaped, (void *) vacpagelist); stats = index_bulk_delete(indrel, tid_reaped, (void *) vacpagelist);
/* Do post-VACUUM cleanup */
vcinfo.vacuum_full = true;
vcinfo.message_level = elevel;
stats = index_vacuum_cleanup(indrel, &vcinfo, stats);
if (!stats) if (!stats)
return; return;
...@@ -2676,8 +2691,9 @@ vacuum_index(VacPageList vacpagelist, Relation indrel, ...@@ -2676,8 +2691,9 @@ vacuum_index(VacPageList vacpagelist, Relation indrel,
stats->num_pages, stats->num_index_tuples, stats->num_pages, stats->num_index_tuples,
false); false);
elog(elevel, "Index %s: Pages %u; Tuples %.0f: Deleted %.0f.\n\t%s", elog(elevel, "Index %s: Pages %u, %u free; Tuples %.0f: Deleted %.0f.\n\t%s",
RelationGetRelationName(indrel), stats->num_pages, RelationGetRelationName(indrel),
stats->num_pages, stats->pages_free,
stats->num_index_tuples - keep_tuples, stats->tuples_removed, stats->num_index_tuples - keep_tuples, stats->tuples_removed,
vac_show_rusage(&ru0)); vac_show_rusage(&ru0));
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.23 2002/11/13 00:39:46 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.24 2003/02/22 00:45:05 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -200,7 +200,6 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats, ...@@ -200,7 +200,6 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
tups_vacuumed, tups_vacuumed,
nkeep, nkeep,
nunused; nunused;
bool did_vacuum_index = false;
int i; int i;
VacRUsage ru0; VacRUsage ru0;
...@@ -244,7 +243,6 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats, ...@@ -244,7 +243,6 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
/* Remove index entries */ /* Remove index entries */
for (i = 0; i < nindexes; i++) for (i = 0; i < nindexes; i++)
lazy_vacuum_index(Irel[i], vacrelstats); lazy_vacuum_index(Irel[i], vacrelstats);
did_vacuum_index = true;
/* Remove tuples from heap */ /* Remove tuples from heap */
lazy_vacuum_heap(onerel, vacrelstats); lazy_vacuum_heap(onerel, vacrelstats);
/* Forget the now-vacuumed tuples, and press on */ /* Forget the now-vacuumed tuples, and press on */
...@@ -415,7 +413,7 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats, ...@@ -415,7 +413,7 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
vacrelstats->rel_tuples = num_tuples; vacrelstats->rel_tuples = num_tuples;
/* If any tuples need to be deleted, perform final vacuum cycle */ /* If any tuples need to be deleted, perform final vacuum cycle */
/* XXX put a threshold on min nuber of tuples here? */ /* XXX put a threshold on min number of tuples here? */
if (vacrelstats->num_dead_tuples > 0) if (vacrelstats->num_dead_tuples > 0)
{ {
/* Remove index entries */ /* Remove index entries */
...@@ -424,9 +422,9 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats, ...@@ -424,9 +422,9 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
/* Remove tuples from heap */ /* Remove tuples from heap */
lazy_vacuum_heap(onerel, vacrelstats); lazy_vacuum_heap(onerel, vacrelstats);
} }
else if (!did_vacuum_index) else
{ {
/* Scan indexes just to update pg_class statistics about them */ /* Must do post-vacuum cleanup and statistics update anyway */
for (i = 0; i < nindexes; i++) for (i = 0; i < nindexes; i++)
lazy_scan_index(Irel[i], vacrelstats); lazy_scan_index(Irel[i], vacrelstats);
} }
...@@ -551,42 +549,36 @@ static void ...@@ -551,42 +549,36 @@ static void
lazy_scan_index(Relation indrel, LVRelStats *vacrelstats) lazy_scan_index(Relation indrel, LVRelStats *vacrelstats)
{ {
IndexBulkDeleteResult *stats; IndexBulkDeleteResult *stats;
IndexVacuumCleanupInfo vcinfo;
VacRUsage ru0; VacRUsage ru0;
vac_init_rusage(&ru0); vac_init_rusage(&ru0);
/* /*
* If the index is not partial, skip the scan, and just assume it has * If index is unsafe for concurrent access, must lock it.
* the same number of tuples as the heap.
*/
if (!vac_is_partial_index(indrel))
{
vac_update_relstats(RelationGetRelid(indrel),
RelationGetNumberOfBlocks(indrel),
vacrelstats->rel_tuples,
false);
return;
}
/*
* If index is unsafe for concurrent access, must lock it; but a
* shared lock should be sufficient.
*/ */
if (!indrel->rd_am->amconcurrent) if (!indrel->rd_am->amconcurrent)
LockRelation(indrel, AccessShareLock); LockRelation(indrel, AccessExclusiveLock);
/* /*
* Even though we're not planning to delete anything, use the * Even though we're not planning to delete anything, we use the
* ambulkdelete call, so that the scan happens within the index AM for * ambulkdelete call, because (a) the scan happens within the index AM
* more speed. * for more speed, and (b) it may want to pass private statistics to
* the amvacuumcleanup call.
*/ */
stats = index_bulk_delete(indrel, dummy_tid_reaped, NULL); stats = index_bulk_delete(indrel, dummy_tid_reaped, NULL);
/* Do post-VACUUM cleanup, even though we deleted nothing */
vcinfo.vacuum_full = false;
vcinfo.message_level = elevel;
stats = index_vacuum_cleanup(indrel, &vcinfo, stats);
/* /*
* Release lock acquired above. * Release lock acquired above.
*/ */
if (!indrel->rd_am->amconcurrent) if (!indrel->rd_am->amconcurrent)
UnlockRelation(indrel, AccessShareLock); UnlockRelation(indrel, AccessExclusiveLock);
if (!stats) if (!stats)
return; return;
...@@ -596,9 +588,9 @@ lazy_scan_index(Relation indrel, LVRelStats *vacrelstats) ...@@ -596,9 +588,9 @@ lazy_scan_index(Relation indrel, LVRelStats *vacrelstats)
stats->num_pages, stats->num_index_tuples, stats->num_pages, stats->num_index_tuples,
false); false);
elog(elevel, "Index %s: Pages %u; Tuples %.0f.\n\t%s", elog(elevel, "Index %s: Pages %u, %u free; Tuples %.0f.\n\t%s",
RelationGetRelationName(indrel), RelationGetRelationName(indrel),
stats->num_pages, stats->num_index_tuples, stats->num_pages, stats->pages_free, stats->num_index_tuples,
vac_show_rusage(&ru0)); vac_show_rusage(&ru0));
pfree(stats); pfree(stats);
...@@ -617,6 +609,7 @@ static void ...@@ -617,6 +609,7 @@ static void
lazy_vacuum_index(Relation indrel, LVRelStats *vacrelstats) lazy_vacuum_index(Relation indrel, LVRelStats *vacrelstats)
{ {
IndexBulkDeleteResult *stats; IndexBulkDeleteResult *stats;
IndexVacuumCleanupInfo vcinfo;
VacRUsage ru0; VacRUsage ru0;
vac_init_rusage(&ru0); vac_init_rusage(&ru0);
...@@ -630,26 +623,33 @@ lazy_vacuum_index(Relation indrel, LVRelStats *vacrelstats) ...@@ -630,26 +623,33 @@ lazy_vacuum_index(Relation indrel, LVRelStats *vacrelstats)
/* Do bulk deletion */ /* Do bulk deletion */
stats = index_bulk_delete(indrel, lazy_tid_reaped, (void *) vacrelstats); stats = index_bulk_delete(indrel, lazy_tid_reaped, (void *) vacrelstats);
/* Do post-VACUUM cleanup */
vcinfo.vacuum_full = false;
vcinfo.message_level = elevel;
stats = index_vacuum_cleanup(indrel, &vcinfo, stats);
/* /*
* Release lock acquired above. * Release lock acquired above.
*/ */
if (!indrel->rd_am->amconcurrent) if (!indrel->rd_am->amconcurrent)
UnlockRelation(indrel, AccessExclusiveLock); UnlockRelation(indrel, AccessExclusiveLock);
if (!stats)
return;
/* now update statistics in pg_class */ /* now update statistics in pg_class */
if (stats) vac_update_relstats(RelationGetRelid(indrel),
{ stats->num_pages, stats->num_index_tuples,
vac_update_relstats(RelationGetRelid(indrel), false);
stats->num_pages, stats->num_index_tuples,
false);
elog(elevel, "Index %s: Pages %u; Tuples %.0f: Deleted %.0f.\n\t%s", elog(elevel, "Index %s: Pages %u, %u free; Tuples %.0f: Deleted %.0f.\n\t%s",
RelationGetRelationName(indrel), stats->num_pages, RelationGetRelationName(indrel),
stats->num_index_tuples, stats->tuples_removed, stats->num_pages, stats->pages_free,
vac_show_rusage(&ru0)); stats->num_index_tuples, stats->tuples_removed,
vac_show_rusage(&ru0));
pfree(stats); pfree(stats);
}
} }
/* /*
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: genam.h,v 1.37 2002/09/04 20:31:36 momjian Exp $ * $Id: genam.h,v 1.38 2003/02/22 00:45:05 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -20,17 +20,32 @@ ...@@ -20,17 +20,32 @@
#include "nodes/primnodes.h" #include "nodes/primnodes.h"
/* Struct for statistics returned by bulk-delete operation */ /*
* Struct for statistics returned by bulk-delete operation
*
* This is now also passed to the index AM's vacuum-cleanup operation,
* if it has one, which can modify the results as needed. Note that
* an index AM could choose to have bulk-delete return a larger struct
* of which this is just the first field; this provides a way for bulk-delete
* to communicate additional private data to vacuum-cleanup.
*/
typedef struct IndexBulkDeleteResult typedef struct IndexBulkDeleteResult
{ {
BlockNumber num_pages; /* pages remaining in index */ BlockNumber num_pages; /* pages remaining in index */
double num_index_tuples; /* tuples remaining */
double tuples_removed; /* # removed by bulk-delete operation */ double tuples_removed; /* # removed by bulk-delete operation */
double num_index_tuples; /* # remaining */ BlockNumber pages_free; /* # unused pages in index */
} IndexBulkDeleteResult; } IndexBulkDeleteResult;
/* Typedef for callback function to determine if a tuple is bulk-deletable */ /* Typedef for callback function to determine if a tuple is bulk-deletable */
typedef bool (*IndexBulkDeleteCallback) (ItemPointer itemptr, void *state); typedef bool (*IndexBulkDeleteCallback) (ItemPointer itemptr, void *state);
/* Struct for additional arguments passed to vacuum-cleanup operation */
typedef struct IndexVacuumCleanupInfo
{
bool vacuum_full; /* VACUUM FULL (we have exclusive lock) */
int message_level; /* elog level for progress messages */
} IndexVacuumCleanupInfo;
/* Struct for heap-or-index scans of system tables */ /* Struct for heap-or-index scans of system tables */
typedef struct SysScanDescData typedef struct SysScanDescData
...@@ -72,6 +87,9 @@ extern bool index_getnext_indexitem(IndexScanDesc scan, ...@@ -72,6 +87,9 @@ extern bool index_getnext_indexitem(IndexScanDesc scan,
extern IndexBulkDeleteResult *index_bulk_delete(Relation indexRelation, extern IndexBulkDeleteResult *index_bulk_delete(Relation indexRelation,
IndexBulkDeleteCallback callback, IndexBulkDeleteCallback callback,
void *callback_state); void *callback_state);
extern IndexBulkDeleteResult *index_vacuum_cleanup(Relation indexRelation,
IndexVacuumCleanupInfo *info,
IndexBulkDeleteResult *stats);
extern RegProcedure index_cost_estimator(Relation indexRelation); extern RegProcedure index_cost_estimator(Relation indexRelation);
extern RegProcedure index_getprocid(Relation irel, AttrNumber attnum, extern RegProcedure index_getprocid(Relation irel, AttrNumber attnum,
uint16 procnum); uint16 procnum);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: nbtree.h,v 1.64 2003/02/21 00:06:22 tgl Exp $ * $Id: nbtree.h,v 1.65 2003/02/22 00:45:05 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -54,6 +54,7 @@ typedef BTPageOpaqueData *BTPageOpaque; ...@@ -54,6 +54,7 @@ typedef BTPageOpaqueData *BTPageOpaque;
#define BTP_ROOT (1 << 1) /* root page (has no parent) */ #define BTP_ROOT (1 << 1) /* root page (has no parent) */
#define BTP_DELETED (1 << 2) /* page has been deleted from tree */ #define BTP_DELETED (1 << 2) /* page has been deleted from tree */
#define BTP_META (1 << 3) /* meta-page */ #define BTP_META (1 << 3) /* meta-page */
#define BTP_HALF_DEAD (1 << 4) /* empty, but still in tree */
/* /*
...@@ -124,12 +125,13 @@ typedef BTItemData *BTItem; ...@@ -124,12 +125,13 @@ typedef BTItemData *BTItem;
#define SizeOfBTItem sizeof(BTItemData) #define SizeOfBTItem sizeof(BTItemData)
/* Test whether items are the "same" per the above notes */ /* Test whether items are the "same" per the above notes */
#define BTItemSame(i1, i2) ( (i1)->bti_itup.t_tid.ip_blkid.bi_hi == \ #define BTTidSame(i1, i2) \
(i2)->bti_itup.t_tid.ip_blkid.bi_hi && \ ( (i1).ip_blkid.bi_hi == (i2).ip_blkid.bi_hi && \
(i1)->bti_itup.t_tid.ip_blkid.bi_lo == \ (i1).ip_blkid.bi_lo == (i2).ip_blkid.bi_lo && \
(i2)->bti_itup.t_tid.ip_blkid.bi_lo && \ (i1).ip_posid == (i2).ip_posid )
(i1)->bti_itup.t_tid.ip_posid == \ #define BTItemSame(i1, i2) \
(i2)->bti_itup.t_tid.ip_posid ) BTTidSame((i1)->bti_itup.t_tid, (i2)->bti_itup.t_tid)
/* /*
* In general, the btree code tries to localize its knowledge about * In general, the btree code tries to localize its knowledge about
...@@ -150,6 +152,7 @@ typedef BTItemData *BTItem; ...@@ -150,6 +152,7 @@ typedef BTItemData *BTItem;
#define P_ISLEAF(opaque) ((opaque)->btpo_flags & BTP_LEAF) #define P_ISLEAF(opaque) ((opaque)->btpo_flags & BTP_LEAF)
#define P_ISROOT(opaque) ((opaque)->btpo_flags & BTP_ROOT) #define P_ISROOT(opaque) ((opaque)->btpo_flags & BTP_ROOT)
#define P_ISDELETED(opaque) ((opaque)->btpo_flags & BTP_DELETED) #define P_ISDELETED(opaque) ((opaque)->btpo_flags & BTP_DELETED)
#define P_IGNORE(opaque) ((opaque)->btpo_flags & (BTP_DELETED|BTP_HALF_DEAD))
/* /*
* Lehman and Yao's algorithm requires a ``high key'' on every non-rightmost * Lehman and Yao's algorithm requires a ``high key'' on every non-rightmost
...@@ -412,8 +415,6 @@ typedef BTScanOpaqueData *BTScanOpaque; ...@@ -412,8 +415,6 @@ typedef BTScanOpaqueData *BTScanOpaque;
/* /*
* prototypes for functions in nbtree.c (external entry points for btree) * prototypes for functions in nbtree.c (external entry points for btree)
*/ */
extern bool BuildingBtree; /* in nbtree.c */
extern void AtEOXact_nbtree(void); extern void AtEOXact_nbtree(void);
extern Datum btbuild(PG_FUNCTION_ARGS); extern Datum btbuild(PG_FUNCTION_ARGS);
...@@ -426,6 +427,7 @@ extern Datum btendscan(PG_FUNCTION_ARGS); ...@@ -426,6 +427,7 @@ extern Datum btendscan(PG_FUNCTION_ARGS);
extern Datum btmarkpos(PG_FUNCTION_ARGS); extern Datum btmarkpos(PG_FUNCTION_ARGS);
extern Datum btrestrpos(PG_FUNCTION_ARGS); extern Datum btrestrpos(PG_FUNCTION_ARGS);
extern Datum btbulkdelete(PG_FUNCTION_ARGS); extern Datum btbulkdelete(PG_FUNCTION_ARGS);
extern Datum btvacuumcleanup(PG_FUNCTION_ARGS);
/* /*
* prototypes for functions in nbtinsert.c * prototypes for functions in nbtinsert.c
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: xlog.h,v 1.41 2003/02/21 00:06:22 tgl Exp $ * $Id: xlog.h,v 1.42 2003/02/22 00:45:05 tgl Exp $
*/ */
#ifndef XLOG_H #ifndef XLOG_H
#define XLOG_H #define XLOG_H
...@@ -56,17 +56,18 @@ typedef struct XLogRecord ...@@ -56,17 +56,18 @@ typedef struct XLogRecord
#define XLR_INFO_MASK 0x0F #define XLR_INFO_MASK 0x0F
/* /*
* We support backup of up to 2 disk blocks per XLOG record (could support * If we backed up any disk blocks with the XLOG record, we use flag bits in
* more if we cared to dedicate more xl_info bits for this purpose; currently * xl_info to signal it. We support backup of up to 3 disk blocks per XLOG
* do not need more than 2 anyway). If we backed up any disk blocks then we * record. (Could support 4 if we cared to dedicate all the xl_info bits for
* use flag bits in xl_info to signal it. * this purpose; currently bit 0 of xl_info is unused and available.)
*/ */
#define XLR_BKP_BLOCK_MASK 0x0C /* all info bits used for bkp #define XLR_BKP_BLOCK_MASK 0x0E /* all info bits used for bkp
* blocks */ * blocks */
#define XLR_MAX_BKP_BLOCKS 2 #define XLR_MAX_BKP_BLOCKS 3
#define XLR_SET_BKP_BLOCK(iblk) (0x08 >> (iblk)) #define XLR_SET_BKP_BLOCK(iblk) (0x08 >> (iblk))
#define XLR_BKP_BLOCK_1 XLR_SET_BKP_BLOCK(0) /* 0x08 */ #define XLR_BKP_BLOCK_1 XLR_SET_BKP_BLOCK(0) /* 0x08 */
#define XLR_BKP_BLOCK_2 XLR_SET_BKP_BLOCK(1) /* 0x04 */ #define XLR_BKP_BLOCK_2 XLR_SET_BKP_BLOCK(1) /* 0x04 */
#define XLR_BKP_BLOCK_3 XLR_SET_BKP_BLOCK(2) /* 0x02 */
/* /*
* Sometimes we log records which are out of transaction control. * Sometimes we log records which are out of transaction control.
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: catversion.h,v 1.178 2003/02/21 00:06:22 tgl Exp $ * $Id: catversion.h,v 1.179 2003/02/22 00:45:05 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200302171 #define CATALOG_VERSION_NO 200302211
#endif #endif
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_am.h,v 1.23 2002/07/29 22:14:11 tgl Exp $ * $Id: pg_am.h,v 1.24 2003/02/22 00:45:05 tgl Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -58,6 +58,7 @@ CATALOG(pg_am) ...@@ -58,6 +58,7 @@ CATALOG(pg_am)
regproc amrestrpos; /* "restore marked scan position" function */ regproc amrestrpos; /* "restore marked scan position" function */
regproc ambuild; /* "build new index" function */ regproc ambuild; /* "build new index" function */
regproc ambulkdelete; /* bulk-delete function */ regproc ambulkdelete; /* bulk-delete function */
regproc amvacuumcleanup; /* post-VACUUM cleanup function */
regproc amcostestimate; /* estimate cost of an indexscan */ regproc amcostestimate; /* estimate cost of an indexscan */
} FormData_pg_am; } FormData_pg_am;
...@@ -72,7 +73,7 @@ typedef FormData_pg_am *Form_pg_am; ...@@ -72,7 +73,7 @@ typedef FormData_pg_am *Form_pg_am;
* compiler constants for pg_am * compiler constants for pg_am
* ---------------- * ----------------
*/ */
#define Natts_pg_am 19 #define Natts_pg_am 20
#define Anum_pg_am_amname 1 #define Anum_pg_am_amname 1
#define Anum_pg_am_amowner 2 #define Anum_pg_am_amowner 2
#define Anum_pg_am_amstrategies 3 #define Anum_pg_am_amstrategies 3
...@@ -91,21 +92,22 @@ typedef FormData_pg_am *Form_pg_am; ...@@ -91,21 +92,22 @@ typedef FormData_pg_am *Form_pg_am;
#define Anum_pg_am_amrestrpos 16 #define Anum_pg_am_amrestrpos 16
#define Anum_pg_am_ambuild 17 #define Anum_pg_am_ambuild 17
#define Anum_pg_am_ambulkdelete 18 #define Anum_pg_am_ambulkdelete 18
#define Anum_pg_am_amcostestimate 19 #define Anum_pg_am_amvacuumcleanup 19
#define Anum_pg_am_amcostestimate 20
/* ---------------- /* ----------------
* initial contents of pg_am * initial contents of pg_am
* ---------------- * ----------------
*/ */
DATA(insert OID = 402 ( rtree PGUID 8 3 0 f f f f rtgettuple rtinsert rtbeginscan rtrescan rtendscan rtmarkpos rtrestrpos rtbuild rtbulkdelete rtcostestimate )); DATA(insert OID = 402 ( rtree PGUID 8 3 0 f f f f rtgettuple rtinsert rtbeginscan rtrescan rtendscan rtmarkpos rtrestrpos rtbuild rtbulkdelete - rtcostestimate ));
DESCR("r-tree index access method"); DESCR("r-tree index access method");
DATA(insert OID = 403 ( btree PGUID 5 1 1 t t t t btgettuple btinsert btbeginscan btrescan btendscan btmarkpos btrestrpos btbuild btbulkdelete btcostestimate )); DATA(insert OID = 403 ( btree PGUID 5 1 1 t t t t btgettuple btinsert btbeginscan btrescan btendscan btmarkpos btrestrpos btbuild btbulkdelete btvacuumcleanup btcostestimate ));
DESCR("b-tree index access method"); DESCR("b-tree index access method");
#define BTREE_AM_OID 403 #define BTREE_AM_OID 403
DATA(insert OID = 405 ( hash PGUID 1 1 0 f f f t hashgettuple hashinsert hashbeginscan hashrescan hashendscan hashmarkpos hashrestrpos hashbuild hashbulkdelete hashcostestimate )); DATA(insert OID = 405 ( hash PGUID 1 1 0 f f f t hashgettuple hashinsert hashbeginscan hashrescan hashendscan hashmarkpos hashrestrpos hashbuild hashbulkdelete - hashcostestimate ));
DESCR("hash index access method"); DESCR("hash index access method");
DATA(insert OID = 783 ( gist PGUID 100 7 0 f t f f gistgettuple gistinsert gistbeginscan gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbulkdelete gistcostestimate )); DATA(insert OID = 783 ( gist PGUID 100 7 0 f t f f gistgettuple gistinsert gistbeginscan gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbulkdelete - gistcostestimate ));
DESCR("GiST index access method"); DESCR("GiST index access method");
#define GIST_AM_OID 783 #define GIST_AM_OID 783
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_proc.h,v 1.283 2003/02/13 05:24:02 momjian Exp $ * $Id: pg_proc.h,v 1.284 2003/02/22 00:45:05 tgl Exp $
* *
* NOTES * NOTES
* The script catalog/genbki.sh reads this file and generates .bki * The script catalog/genbki.sh reads this file and generates .bki
...@@ -710,6 +710,8 @@ DATA(insert OID = 338 ( btbuild PGNSP PGUID 12 f f t f v 3 2278 "2281 2281 ...@@ -710,6 +710,8 @@ DATA(insert OID = 338 ( btbuild PGNSP PGUID 12 f f t f v 3 2278 "2281 2281
DESCR("btree(internal)"); DESCR("btree(internal)");
DATA(insert OID = 332 ( btbulkdelete PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" btbulkdelete - _null_ )); DATA(insert OID = 332 ( btbulkdelete PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" btbulkdelete - _null_ ));
DESCR("btree(internal)"); DESCR("btree(internal)");
DATA(insert OID = 972 ( btvacuumcleanup PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" btvacuumcleanup - _null_ ));
DESCR("btree(internal)");
DATA(insert OID = 1268 ( btcostestimate PGNSP PGUID 12 f f t f v 8 2278 "2281 2281 2281 2281 2281 2281 2281 2281" btcostestimate - _null_ )); DATA(insert OID = 1268 ( btcostestimate PGNSP PGUID 12 f f t f v 8 2278 "2281 2281 2281 2281 2281 2281 2281 2281" btcostestimate - _null_ ));
DESCR("btree(internal)"); DESCR("btree(internal)");
......
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