>From 5972d8516786615bed3a587b0d2fb78dba2e74ed Mon Sep 17 00:00:00 2001
From: amit <amitlangote09@gmail.com>
Date: Tue, 8 Mar 2016 15:23:38 +0900
Subject: [PATCH 3/3] Add a block number argument to index bulk delete callback.

Currently, index AMs can only pass a ItemPointer (heap tid) and a generic
pointer to caller specified struct.  Add a BlockNumber so that the callback
can use it for something.  For example, lazy_tid_reaped() now uses it to
track the progress of AM's bulk delete scan of an index by comparing it with
the last call's value that it stores in its private state on every change.
The private state being the LVRelStats struct that now has the corresponding
field.  On every change, the count of index blocks vacuumed is incremented
which is also a new field in LVRelStats. The count is reset for every index
vacuum round.

Then a pgstat_progress_update_param call has been added to lazy_tid_reaped,
that pushes the count on every increment.

Currently, only btree AM is changed to pass the block number, others pass
InvalidBlockNumber.
---
 src/backend/access/gin/ginvacuum.c    |    2 +-
 src/backend/access/gist/gistvacuum.c  |    2 +-
 src/backend/access/hash/hash.c        |    2 +-
 src/backend/access/nbtree/nbtree.c    |    2 +-
 src/backend/access/spgist/spgvacuum.c |    6 +++---
 src/backend/catalog/index.c           |    5 +++--
 src/backend/commands/vacuumlazy.c     |   25 ++++++++++++++-----------
 src/include/access/genam.h            |    4 +++-
 8 files changed, 27 insertions(+), 21 deletions(-)

diff --git a/src/backend/access/gin/ginvacuum.c b/src/backend/access/gin/ginvacuum.c
index 6a4b98a..64e69d6 100644
--- a/src/backend/access/gin/ginvacuum.c
+++ b/src/backend/access/gin/ginvacuum.c
@@ -55,7 +55,7 @@ ginVacuumItemPointers(GinVacuumState *gvs, ItemPointerData *items,
 	 */
 	for (i = 0; i < nitem; i++)
 	{
-		if (gvs->callback(items + i, gvs->callback_state))
+		if (gvs->callback(items + i, InvalidBlockNumber, gvs->callback_state))
 		{
 			gvs->result->tuples_removed += 1;
 			if (!tmpitems)
diff --git a/src/backend/access/gist/gistvacuum.c b/src/backend/access/gist/gistvacuum.c
index 7947ff9..96e89c3 100644
--- a/src/backend/access/gist/gistvacuum.c
+++ b/src/backend/access/gist/gistvacuum.c
@@ -202,7 +202,7 @@ gistbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
 				iid = PageGetItemId(page, i);
 				idxtuple = (IndexTuple) PageGetItem(page, iid);
 
-				if (callback(&(idxtuple->t_tid), callback_state))
+				if (callback(&(idxtuple->t_tid), InvalidBlockNumber, callback_state))
 					todelete[ntodelete++] = i;
 				else
 					stats->num_index_tuples += 1;
diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c
index 3d48c4f..1530f0b 100644
--- a/src/backend/access/hash/hash.c
+++ b/src/backend/access/hash/hash.c
@@ -575,7 +575,7 @@ loop_top:
 				itup = (IndexTuple) PageGetItem(page,
 												PageGetItemId(page, offno));
 				htup = &(itup->t_tid);
-				if (callback(htup, callback_state))
+				if (callback(htup, InvalidBlockNumber, callback_state))
 				{
 					/* mark the item for deletion */
 					deletable[ndeletable++] = offno;
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index f2905cb..8c6be30 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -1034,7 +1034,7 @@ restart:
 				 * applies to *any* type of index that marks index tuples as
 				 * killed.
 				 */
-				if (callback(htup, callback_state))
+				if (callback(htup, blkno, callback_state))
 					deletable[ndeletable++] = offnum;
 			}
 		}
diff --git a/src/backend/access/spgist/spgvacuum.c b/src/backend/access/spgist/spgvacuum.c
index 15b867f..6c7265b 100644
--- a/src/backend/access/spgist/spgvacuum.c
+++ b/src/backend/access/spgist/spgvacuum.c
@@ -154,7 +154,7 @@ vacuumLeafPage(spgBulkDeleteState *bds, Relation index, Buffer buffer,
 		{
 			Assert(ItemPointerIsValid(&lt->heapPtr));
 
-			if (bds->callback(&lt->heapPtr, bds->callback_state))
+			if (bds->callback(&lt->heapPtr, InvalidBlockNumber, bds->callback_state))
 			{
 				bds->stats->tuples_removed += 1;
 				deletable[i] = true;
@@ -424,7 +424,7 @@ vacuumLeafRoot(spgBulkDeleteState *bds, Relation index, Buffer buffer)
 		{
 			Assert(ItemPointerIsValid(&lt->heapPtr));
 
-			if (bds->callback(&lt->heapPtr, bds->callback_state))
+			if (bds->callback(&lt->heapPtr, InvalidBlockNumber, bds->callback_state))
 			{
 				bds->stats->tuples_removed += 1;
 				toDelete[xlrec.nDelete] = i;
@@ -902,7 +902,7 @@ spgbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
 
 /* Dummy callback to delete no tuples during spgvacuumcleanup */
 static bool
-dummy_callback(ItemPointer itemptr, void *state)
+dummy_callback(ItemPointer itemptr, BlockNumber index_blkno, void *state)
 {
 	return false;
 }
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 31a1438..d792fdb 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -114,7 +114,8 @@ static void IndexCheckExclusion(Relation heapRelation,
 					IndexInfo *indexInfo);
 static inline int64 itemptr_encode(ItemPointer itemptr);
 static inline void itemptr_decode(ItemPointer itemptr, int64 encoded);
-static bool validate_index_callback(ItemPointer itemptr, void *opaque);
+static bool validate_index_callback(ItemPointer itemptr, BlockNumber index_blkno,
+						void *opaque);
 static void validate_index_heapscan(Relation heapRelation,
 						Relation indexRelation,
 						IndexInfo *indexInfo,
@@ -2913,7 +2914,7 @@ itemptr_decode(ItemPointer itemptr, int64 encoded)
  * validate_index_callback - bulkdelete callback to collect the index TIDs
  */
 static bool
-validate_index_callback(ItemPointer itemptr, void *opaque)
+validate_index_callback(ItemPointer itemptr, BlockNumber index_blkno, void *opaque)
 {
 	v_i_state  *state = (v_i_state *) opaque;
 	int64		encoded = itemptr_encode(itemptr);
diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c
index 60c3b3b..2e28f4b 100644
--- a/src/backend/commands/vacuumlazy.c
+++ b/src/backend/commands/vacuumlazy.c
@@ -143,6 +143,8 @@ typedef struct LVRelStats
 	int			num_index_scans;
 	TransactionId latestRemovedXid;
 	bool		lock_waiter_detected;
+	BlockNumber	last_index_blkno;
+	BlockNumber	index_blks_vacuumed;
 } LVRelStats;
 
 
@@ -176,7 +178,7 @@ static BlockNumber count_nondeletable_pages(Relation onerel,
 static void lazy_space_alloc(LVRelStats *vacrelstats, BlockNumber relblocks);
 static void lazy_record_dead_tuple(LVRelStats *vacrelstats,
 					   ItemPointer itemptr);
-static bool lazy_tid_reaped(ItemPointer itemptr, void *state);
+static bool lazy_tid_reaped(ItemPointer itemptr, BlockNumber index_blkno, void *state);
 static int	vac_cmp_itemptr(const void *left, const void *right);
 static bool heap_page_is_all_visible(Relation rel, Buffer buf,
 						 TransactionId *visibility_cutoff_xid, bool *all_frozen);
@@ -657,16 +659,12 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
 
 			/* Remove index entries */
 			pgstat_progress_update_param(PROG_PAR_VAC_PHASE_ID, LV_PHASE_VACUUM_INDEX);
+			vacrelstats->index_blks_vacuumed = 0;	/* reset for this round */
 			for (i = 0; i < nindexes; i++)
-			{
 				lazy_vacuum_index(Irel[i],
 								  &indstats[i],
 								  vacrelstats);
 
-				pgstat_progress_update_param(PROG_PAR_VAC_IDX_BLKS_DONE,
-											 current_index_blks[i]);
-			}
-
 			pgstat_progress_update_param(PROG_PAR_VAC_N_IDX_SCAN,
 										 vacrelstats->num_index_scans+1);
 
@@ -1222,15 +1220,12 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
 
 		/* Remove index entries */
 		pgstat_progress_update_param(PROG_PAR_VAC_PHASE_ID, LV_PHASE_VACUUM_INDEX);
+		vacrelstats->index_blks_vacuumed = 0;	/* reset for this round */
 		for (i = 0; i < nindexes; i++)
-		{
 			lazy_vacuum_index(Irel[i],
 							  &indstats[i],
 							  vacrelstats);
 
-			pgstat_progress_update_param(PROG_PAR_VAC_IDX_BLKS_DONE,
-										 current_index_blks[i]);
-		}
 		pgstat_progress_update_param(PROG_PAR_VAC_N_IDX_SCAN,
 									 vacrelstats->num_index_scans + 1);
 
@@ -1922,11 +1917,19 @@ lazy_record_dead_tuple(LVRelStats *vacrelstats,
  *		Assumes dead_tuples array is in sorted order.
  */
 static bool
-lazy_tid_reaped(ItemPointer itemptr, void *state)
+lazy_tid_reaped(ItemPointer itemptr, BlockNumber index_blkno, void *state)
 {
 	LVRelStats *vacrelstats = (LVRelStats *) state;
 	ItemPointer res;
 
+	if (index_blkno != vacrelstats->last_index_blkno)
+	{
+		++vacrelstats->index_blks_vacuumed;
+		pgstat_progress_update_param(PROG_PAR_VAC_IDX_BLKS_DONE,
+									 vacrelstats->index_blks_vacuumed);
+		vacrelstats->last_index_blkno = index_blkno;
+	}
+
 	res = (ItemPointer) bsearch((void *) itemptr,
 								(void *) vacrelstats->dead_tuples,
 								vacrelstats->num_dead_tuples,
diff --git a/src/include/access/genam.h b/src/include/access/genam.h
index 81907d5..8d67d1c 100644
--- a/src/include/access/genam.h
+++ b/src/include/access/genam.h
@@ -77,7 +77,9 @@ typedef struct IndexBulkDeleteResult
 } IndexBulkDeleteResult;
 
 /* Typedef for callback function to determine if a tuple is bulk-deletable */
-typedef bool (*IndexBulkDeleteCallback) (ItemPointer itemptr, void *state);
+typedef bool (*IndexBulkDeleteCallback) (ItemPointer itemptr,
+										 BlockNumber index_blkno,
+										 void *state);
 
 /* struct definitions appear in relscan.h */
 typedef struct IndexScanDescData *IndexScanDesc;
-- 
1.7.1

