aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access')
-rw-r--r--src/backend/access/gin/ginvacuum.c33
-rw-r--r--src/backend/access/gist/gistvacuum.c82
-rw-r--r--src/backend/access/hash/hash.c59
-rw-r--r--src/backend/access/index/indexam.c31
-rw-r--r--src/backend/access/nbtree/nbtree.c42
5 files changed, 123 insertions, 124 deletions
diff --git a/src/backend/access/gin/ginvacuum.c b/src/backend/access/gin/ginvacuum.c
index ab1861fdaa9..bc8a3e53efc 100644
--- a/src/backend/access/gin/ginvacuum.c
+++ b/src/backend/access/gin/ginvacuum.c
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/gin/ginvacuum.c,v 1.1 2006/05/02 11:28:54 teodor Exp $
+ * $PostgreSQL: pgsql/src/backend/access/gin/ginvacuum.c,v 1.2 2006/05/02 22:25:10 tgl Exp $
*-------------------------------------------------------------------------
*/
@@ -474,17 +474,25 @@ ginVacuumEntryPage(GinVacuumState *gvs, Buffer buffer, BlockNumber *roots, uint3
Datum
ginbulkdelete(PG_FUNCTION_ARGS) {
- Relation index = (Relation) PG_GETARG_POINTER(0);
- IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(1);
- void *callback_state = (void *) PG_GETARG_POINTER(2);
+ IndexVacuumInfo *info = (IndexVacuumInfo *) PG_GETARG_POINTER(0);
+ IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(1);
+ IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(2);
+ void *callback_state = (void *) PG_GETARG_POINTER(3);
+ Relation index = info->index;
BlockNumber blkno = GIN_ROOT_BLKNO;
GinVacuumState gvs;
Buffer buffer;
BlockNumber rootOfPostingTree[ BLCKSZ/ (sizeof(IndexTupleData)+sizeof(ItemId)) ];
uint32 nRoot;
+ /* first time through? */
+ if (stats == NULL)
+ stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+ /* we'll re-count the tuples each time */
+ stats->num_index_tuples = 0;
+
gvs.index = index;
- gvs.result = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+ gvs.result = stats;
gvs.callback = callback;
gvs.callback_state = callback_state;
initGinState(&gvs.ginstate, index);
@@ -564,9 +572,9 @@ ginbulkdelete(PG_FUNCTION_ARGS) {
Datum
ginvacuumcleanup(PG_FUNCTION_ARGS) {
- Relation index = (Relation) PG_GETARG_POINTER(0);
- IndexVacuumCleanupInfo *info = (IndexVacuumCleanupInfo *) PG_GETARG_POINTER(1);
- IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(2);
+ IndexVacuumInfo *info = (IndexVacuumInfo *) PG_GETARG_POINTER(0);
+ IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(1);
+ Relation index = info->index;
bool needLock = !RELATION_IS_LOCAL(index);
BlockNumber npages,
blkno;
@@ -576,6 +584,15 @@ ginvacuumcleanup(PG_FUNCTION_ARGS) {
BlockNumber lastBlock = GIN_ROOT_BLKNO,
lastFilledBlock = GIN_ROOT_BLKNO;
+ /* Set up all-zero stats if ginbulkdelete wasn't called */
+ if (stats == NULL)
+ stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+ /*
+ * XXX we always report the heap tuple count as the number of index
+ * entries. This is bogus if the index is partial, but it's real hard
+ * to tell how many distinct heap entries are referenced by a GIN index.
+ */
+ stats->num_index_tuples = info->num_heap_tuples;
if (info->vacuum_full) {
LockRelation(index, AccessExclusiveLock);
diff --git a/src/backend/access/gist/gistvacuum.c b/src/backend/access/gist/gistvacuum.c
index 285f1301321..eafd472c5fd 100644
--- a/src/backend/access/gist/gistvacuum.c
+++ b/src/backend/access/gist/gistvacuum.c
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.18 2006/03/31 23:32:05 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.19 2006/05/02 22:25:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -343,9 +343,9 @@ gistVacuumUpdate(GistVacuum *gv, BlockNumber blkno, bool needunion)
Datum
gistvacuumcleanup(PG_FUNCTION_ARGS)
{
- Relation rel = (Relation) PG_GETARG_POINTER(0);
- IndexVacuumCleanupInfo *info = (IndexVacuumCleanupInfo *) PG_GETARG_POINTER(1);
- GistBulkDeleteResult *stats = (GistBulkDeleteResult *) PG_GETARG_POINTER(2);
+ IndexVacuumInfo *info = (IndexVacuumInfo *) PG_GETARG_POINTER(0);
+ GistBulkDeleteResult *stats = (GistBulkDeleteResult *) PG_GETARG_POINTER(1);
+ Relation rel = info->index;
BlockNumber npages,
blkno;
BlockNumber nFreePages,
@@ -355,6 +355,19 @@ gistvacuumcleanup(PG_FUNCTION_ARGS)
lastFilledBlock = GIST_ROOT_BLKNO;
bool needLock;
+ /* Set up all-zero stats if gistbulkdelete wasn't called */
+ if (stats == NULL)
+ {
+ stats = (GistBulkDeleteResult *) palloc0(sizeof(GistBulkDeleteResult));
+ /* use heap's tuple count */
+ Assert(info->num_heap_tuples >= 0);
+ stats->std.num_index_tuples = info->num_heap_tuples;
+ /*
+ * XXX the above is wrong if index is partial. Would it be OK to
+ * just return NULL, or is there work we must do below?
+ */
+ }
+
/* gistVacuumUpdate may cause hard work */
if (info->vacuum_full)
{
@@ -460,13 +473,6 @@ gistvacuumcleanup(PG_FUNCTION_ARGS)
if (info->vacuum_full)
UnlockRelation(rel, AccessExclusiveLock);
- /* if gistbulkdelete skipped the scan, use heap's tuple count */
- if (stats->std.num_index_tuples < 0)
- {
- Assert(info->num_heap_tuples >= 0);
- stats->std.num_index_tuples = info->num_heap_tuples;
- }
-
PG_RETURN_POINTER(stats);
}
@@ -509,36 +515,22 @@ pushStackIfSplited(Page page, GistBDItem *stack)
Datum
gistbulkdelete(PG_FUNCTION_ARGS)
{
- Relation rel = (Relation) PG_GETARG_POINTER(0);
- IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(1);
- void *callback_state = (void *) PG_GETARG_POINTER(2);
- GistBulkDeleteResult *result;
+ IndexVacuumInfo *info = (IndexVacuumInfo *) PG_GETARG_POINTER(0);
+ GistBulkDeleteResult *stats = (GistBulkDeleteResult *) PG_GETARG_POINTER(1);
+ IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(2);
+ void *callback_state = (void *) PG_GETARG_POINTER(3);
+ Relation rel = info->index;
GistBDItem *stack,
*ptr;
- bool needLock;
- result = (GistBulkDeleteResult *) palloc0(sizeof(GistBulkDeleteResult));
+ /* first time through? */
+ if (stats == NULL)
+ stats = (GistBulkDeleteResult *) palloc0(sizeof(GistBulkDeleteResult));
+ /* we'll re-count the tuples each time */
+ stats->std.num_index_tuples = 0;
- /*
- * We can skip the scan entirely if there's nothing to delete (indicated
- * by callback_state == NULL) and the index isn't partial. For a partial
- * index we must scan in order to derive a trustworthy tuple count.
- *
- * XXX as of PG 8.2 this is dead code because GIST indexes are always
- * effectively partial ... but keep it anyway in case our null-handling
- * gets fixed.
- */
- if (callback_state || vac_is_partial_index(rel))
- {
- stack = (GistBDItem *) palloc0(sizeof(GistBDItem));
- stack->blkno = GIST_ROOT_BLKNO;
- }
- else
- {
- /* skip scan and set flag for gistvacuumcleanup */
- stack = NULL;
- result->std.num_index_tuples = -1;
- }
+ stack = (GistBDItem *) palloc0(sizeof(GistBDItem));
+ stack->blkno = GIST_ROOT_BLKNO;
while (stack)
{
@@ -601,11 +593,11 @@ gistbulkdelete(PG_FUNCTION_ARGS)
i--;
maxoff--;
ntodelete++;
- result->std.tuples_removed += 1;
+ stats->std.tuples_removed += 1;
Assert(maxoff == PageGetMaxOffsetNumber(page));
}
else
- result->std.num_index_tuples += 1;
+ stats->std.num_index_tuples += 1;
}
if (ntodelete)
@@ -658,7 +650,7 @@ gistbulkdelete(PG_FUNCTION_ARGS)
stack->next = ptr;
if (GistTupleIsInvalid(idxtuple))
- result->needFullVacuum = true;
+ stats->needFullVacuum = true;
}
}
@@ -671,13 +663,5 @@ gistbulkdelete(PG_FUNCTION_ARGS)
vacuum_delay_point();
}
- needLock = !RELATION_IS_LOCAL(rel);
-
- if (needLock)
- LockRelationForExtension(rel, ExclusiveLock);
- result->std.num_pages = RelationGetNumberOfBlocks(rel);
- if (needLock)
- UnlockRelationForExtension(rel, ExclusiveLock);
-
- PG_RETURN_POINTER(result);
+ PG_RETURN_POINTER(stats);
}
diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c
index 8e232414dc8..ff54052f6de 100644
--- a/src/backend/access/hash/hash.c
+++ b/src/backend/access/hash/hash.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.88 2006/03/24 04:32:12 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.89 2006/05/02 22:25:10 tgl Exp $
*
* NOTES
* This file contains only the public interface routines.
@@ -478,11 +478,11 @@ hashrestrpos(PG_FUNCTION_ARGS)
Datum
hashbulkdelete(PG_FUNCTION_ARGS)
{
- Relation rel = (Relation) PG_GETARG_POINTER(0);
- IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(1);
- void *callback_state = (void *) PG_GETARG_POINTER(2);
- IndexBulkDeleteResult *result;
- BlockNumber num_pages;
+ IndexVacuumInfo *info = (IndexVacuumInfo *) PG_GETARG_POINTER(0);
+ IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(1);
+ IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(2);
+ void *callback_state = (void *) PG_GETARG_POINTER(3);
+ Relation rel = info->index;
double tuples_removed;
double num_index_tuples;
double orig_ntuples;
@@ -517,18 +517,6 @@ hashbulkdelete(PG_FUNCTION_ARGS)
cur_maxbucket = orig_maxbucket;
loop_top:
-
- /*
- * If we don't have anything to delete, skip the scan, and report the
- * number of tuples shown in the metapage. (Unlike btree and gist,
- * we can trust this number even for a partial index.)
- */
- if (!callback_state)
- {
- cur_bucket = cur_maxbucket + 1;
- num_index_tuples = local_metapage.hashm_ntuples;
- }
-
while (cur_bucket <= cur_maxbucket)
{
BlockNumber bucket_blkno;
@@ -657,14 +645,37 @@ loop_top:
_hash_wrtbuf(rel, metabuf);
/* return statistics */
- num_pages = RelationGetNumberOfBlocks(rel);
+ if (stats == NULL)
+ stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+ stats->num_index_tuples = num_index_tuples;
+ stats->tuples_removed += tuples_removed;
+ /* hashvacuumcleanup will fill in num_pages */
+
+ PG_RETURN_POINTER(stats);
+}
- result = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
- result->num_pages = num_pages;
- result->num_index_tuples = num_index_tuples;
- result->tuples_removed = tuples_removed;
+/*
+ * Post-VACUUM cleanup.
+ *
+ * Result: a palloc'd struct containing statistical info for VACUUM displays.
+ */
+Datum
+hashvacuumcleanup(PG_FUNCTION_ARGS)
+{
+ IndexVacuumInfo *info = (IndexVacuumInfo *) PG_GETARG_POINTER(0);
+ IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(1);
+ Relation rel = info->index;
+ BlockNumber num_pages;
+
+ /* If hashbulkdelete wasn't called, return NULL signifying no change */
+ if (stats == NULL)
+ PG_RETURN_POINTER(NULL);
+
+ /* update statistics */
+ num_pages = RelationGetNumberOfBlocks(rel);
+ stats->num_pages = num_pages;
- PG_RETURN_POINTER(result);
+ PG_RETURN_POINTER(stats);
}
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index 8b19d5def26..b54364acb6d 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.91 2006/03/05 15:58:21 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.92 2006/05/02 22:25:10 tgl Exp $
*
* INTERFACE ROUTINES
* index_open - open an index relation by relation OID
@@ -684,19 +684,17 @@ index_getmulti(IndexScanDesc scan,
*
* callback routine tells whether a given main-heap tuple is
* to be deleted
- *
- * if callback_state is NULL then there are no tuples to be deleted;
- * index AM can choose to avoid work in this case, but must still
- * follow the protocol of returning statistical info.
*
* return value is an optional palloc'd struct of statistics
* ----------------
*/
IndexBulkDeleteResult *
-index_bulk_delete(Relation indexRelation,
+index_bulk_delete(IndexVacuumInfo *info,
+ IndexBulkDeleteResult *stats,
IndexBulkDeleteCallback callback,
void *callback_state)
{
+ Relation indexRelation = info->index;
FmgrInfo *procedure;
IndexBulkDeleteResult *result;
@@ -704,8 +702,9 @@ index_bulk_delete(Relation indexRelation,
GET_REL_PROCEDURE(ambulkdelete);
result = (IndexBulkDeleteResult *)
- DatumGetPointer(FunctionCall3(procedure,
- PointerGetDatum(indexRelation),
+ DatumGetPointer(FunctionCall4(procedure,
+ PointerGetDatum(info),
+ PointerGetDatum(stats),
PointerGetDatum((Pointer) callback),
PointerGetDatum(callback_state)));
@@ -719,26 +718,20 @@ index_bulk_delete(Relation indexRelation,
* ----------------
*/
IndexBulkDeleteResult *
-index_vacuum_cleanup(Relation indexRelation,
- IndexVacuumCleanupInfo *info,
+index_vacuum_cleanup(IndexVacuumInfo *info,
IndexBulkDeleteResult *stats)
{
+ Relation indexRelation = info->index;
FmgrInfo *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(amvacuumcleanup);
result = (IndexBulkDeleteResult *)
- DatumGetPointer(FunctionCall3(procedure,
- PointerGetDatum(indexRelation),
- PointerGetDatum((Pointer) info),
- PointerGetDatum((Pointer) stats)));
+ DatumGetPointer(FunctionCall2(procedure,
+ PointerGetDatum(info),
+ PointerGetDatum(stats)));
return result;
}
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index 4f6915e32b4..1eece10398e 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
- * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.145 2006/04/25 22:46:05 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.146 2006/05/02 22:25:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -518,15 +518,15 @@ btrestrpos(PG_FUNCTION_ARGS)
Datum
btbulkdelete(PG_FUNCTION_ARGS)
{
- Relation rel = (Relation) PG_GETARG_POINTER(0);
- IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(1);
- void *callback_state = (void *) PG_GETARG_POINTER(2);
- IndexBulkDeleteResult *result;
+ IndexVacuumInfo *info = (IndexVacuumInfo *) PG_GETARG_POINTER(0);
+ IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(1);
+ IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(2);
+ void *callback_state = (void *) PG_GETARG_POINTER(3);
+ Relation rel = info->index;
double tuples_removed = 0;
OffsetNumber deletable[MaxOffsetNumber];
int ndeletable;
Buffer buf;
- BlockNumber num_pages;
/*
* The outer loop iterates over index leaf pages, the inner over items on
@@ -543,14 +543,8 @@ btbulkdelete(PG_FUNCTION_ARGS)
* further to its right, which the indexscan will have no pin on.) We can
* skip obtaining exclusive lock on empty pages though, since no indexscan
* could be stopped on those.
- *
- * We can skip the scan entirely if there's nothing to delete (indicated
- * by callback_state == NULL).
*/
- if (callback_state)
- buf = _bt_get_endpoint(rel, 0, false);
- else
- buf = InvalidBuffer;
+ buf = _bt_get_endpoint(rel, 0, false);
if (BufferIsValid(buf)) /* check for empty index */
{
@@ -626,14 +620,12 @@ btbulkdelete(PG_FUNCTION_ARGS)
}
/* return statistics */
- num_pages = RelationGetNumberOfBlocks(rel);
-
- result = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
- result->num_pages = num_pages;
- /* btvacuumcleanup will fill in num_index_tuples */
- result->tuples_removed = tuples_removed;
+ if (stats == NULL)
+ stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+ stats->tuples_removed += tuples_removed;
+ /* btvacuumcleanup will fill in num_pages and num_index_tuples */
- PG_RETURN_POINTER(result);
+ PG_RETURN_POINTER(stats);
}
/*
@@ -646,9 +638,9 @@ btbulkdelete(PG_FUNCTION_ARGS)
Datum
btvacuumcleanup(PG_FUNCTION_ARGS)
{
- Relation rel = (Relation) PG_GETARG_POINTER(0);
- IndexVacuumCleanupInfo *info = (IndexVacuumCleanupInfo *) PG_GETARG_POINTER(1);
- IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(2);
+ IndexVacuumInfo *info = (IndexVacuumInfo *) PG_GETARG_POINTER(0);
+ IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(1);
+ Relation rel = info->index;
BlockNumber num_pages;
BlockNumber blkno;
BlockNumber *freePages;
@@ -660,7 +652,9 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
MemoryContext oldcontext;
bool needLock;
- Assert(stats != NULL);
+ /* Set up all-zero stats if btbulkdelete wasn't called */
+ if (stats == NULL)
+ stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
/*
* First find out the number of pages in the index. We must acquire the