From bffedfa1e90a3b872e7b7073b29eb8b1b43c5433 Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryzbyj@telsasoft.com>
Date: Thu, 19 Mar 2020 15:21:22 -0500
Subject: [PATCH v27 2/5] Save the values of the callback..

..allowing them to be restored later, rather than setting phase=UNKNOWN.
---
 src/backend/access/heap/vacuumlazy.c | 81 ++++++++++++++++++----------
 1 file changed, 54 insertions(+), 27 deletions(-)

diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c
index 92bac9a24d..d923a40687 100644
--- a/src/backend/access/heap/vacuumlazy.c
+++ b/src/backend/access/heap/vacuumlazy.c
@@ -378,7 +378,8 @@ static LVSharedIndStats *get_indstats(LVShared *lvshared, int n);
 static bool skip_parallel_vacuum_index(Relation indrel, LVShared *lvshared);
 static void vacuum_error_callback(void *arg);
 static void update_vacuum_error_cbarg(LVRelStats *errcbarg, int phase,
-									  BlockNumber blkno, Relation rel);
+									  BlockNumber blkno, char *indname,
+									  LVRelStats *olderrcbarg);
 
 
 /*
@@ -745,6 +746,7 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
 	};
 	int64		initprog_val[3];
 	ErrorContextCallback errcallback;
+	LVRelStats	olderrcbarg;
 
 	pg_rusage_init(&ru0);
 
@@ -892,7 +894,7 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
 
 	/* Setup error traceback support for ereport() */
 	update_vacuum_error_cbarg(vacrelstats, VACUUM_ERRCB_PHASE_SCAN_HEAP,
-			InvalidBlockNumber, NULL);
+			InvalidBlockNumber, NULL, &olderrcbarg);
 	errcallback.callback = vacuum_error_callback;
 	errcallback.arg = vacrelstats;
 	errcallback.previous = error_context_stack;
@@ -924,7 +926,7 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
 		pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, blkno);
 
 		update_vacuum_error_cbarg(vacrelstats, VACUUM_ERRCB_PHASE_SCAN_HEAP,
-								  blkno, NULL);
+								  blkno, NULL, &olderrcbarg);
 
 		if (blkno == next_unskippable_block)
 		{
@@ -1047,7 +1049,10 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
 
 			/* Set the error context while continuing heap scan */
 			update_vacuum_error_cbarg(vacrelstats,
-									  VACUUM_ERRCB_PHASE_SCAN_HEAP, blkno, NULL);
+									  olderrcbarg.phase,
+									  olderrcbarg.blkno,
+									  olderrcbarg.indname,
+									  NULL);
 		}
 
 		/*
@@ -1532,8 +1537,10 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
 
 			/* Set the error context while continuing heap scan */
 			update_vacuum_error_cbarg(vacrelstats,
-				VACUUM_ERRCB_PHASE_SCAN_HEAP, blkno, NULL);
-
+									  olderrcbarg.phase,
+									  olderrcbarg.blkno,
+									  olderrcbarg.indname,
+									  NULL);
 		}
 
 		freespace = PageGetHeapFreeSpace(page);
@@ -1817,6 +1824,7 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats)
 	int			npages;
 	PGRUsage	ru0;
 	Buffer		vmbuffer = InvalidBuffer;
+	LVRelStats	olderrcbarg;
 
 	/* Report that we are now vacuuming the heap */
 	pgstat_progress_update_param(PROGRESS_VACUUM_PHASE,
@@ -1824,7 +1832,7 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats)
 
 	/* Setup error traceback support for ereport() */
 	update_vacuum_error_cbarg(vacrelstats, VACUUM_ERRCB_PHASE_VACUUM_HEAP,
-							  InvalidBlockNumber, NULL);
+							  InvalidBlockNumber, NULL, &olderrcbarg);
 
 	pg_rusage_init(&ru0);
 	npages = 0;
@@ -1875,7 +1883,9 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats)
 
 	/* Clear the error traceback phase */
 	update_vacuum_error_cbarg(vacrelstats,
-							  VACUUM_ERRCB_PHASE_UNKNOWN, InvalidBlockNumber,
+							  olderrcbarg.phase,
+							  olderrcbarg.blkno,
+							  olderrcbarg.indname,
 							  NULL);
 }
 
@@ -1899,12 +1909,13 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
 	int			uncnt = 0;
 	TransactionId visibility_cutoff_xid;
 	bool		all_frozen;
+	LVRelStats	olderrcbarg;
 
 	pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_VACUUMED, blkno);
 
 	/* Setup error traceback support for ereport() */
 	update_vacuum_error_cbarg(vacrelstats, VACUUM_ERRCB_PHASE_VACUUM_HEAP,
-							  blkno, NULL);
+							  blkno, NULL, &olderrcbarg);
 
 	START_CRIT_SECTION();
 
@@ -1984,9 +1995,10 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
 
 	/* Clear the error traceback phase */
 	update_vacuum_error_cbarg(vacrelstats,
-							  VACUUM_ERRCB_PHASE_UNKNOWN, InvalidBlockNumber,
+							  olderrcbarg.phase,
+							  olderrcbarg.blkno,
+							  olderrcbarg.indname,
 							  NULL);
-
 	return tupindex;
 }
 
@@ -2384,6 +2396,7 @@ lazy_vacuum_index(Relation indrel, IndexBulkDeleteResult **stats,
 	IndexVacuumInfo ivinfo;
 	const char *msg;
 	PGRUsage	ru0;
+	LVRelStats	olderrcbarg;
 
 	pg_rusage_init(&ru0);
 
@@ -2397,8 +2410,9 @@ lazy_vacuum_index(Relation indrel, IndexBulkDeleteResult **stats,
 
 	/* Setup error traceback support for ereport() */
 	update_vacuum_error_cbarg(vacrelstats,
-							  VACUUM_ERRCB_PHASE_VACUUM_INDEX, InvalidBlockNumber,
-							  indrel);
+							  VACUUM_ERRCB_PHASE_VACUUM_INDEX,
+							  InvalidBlockNumber,
+							  RelationGetRelationName(indrel), &olderrcbarg);
 
 	/* Do bulk deletion */
 	*stats = index_bulk_delete(&ivinfo, *stats,
@@ -2417,7 +2431,9 @@ lazy_vacuum_index(Relation indrel, IndexBulkDeleteResult **stats,
 
 	/* Clear the error traceback phase */
 	update_vacuum_error_cbarg(vacrelstats,
-							  VACUUM_ERRCB_PHASE_UNKNOWN, InvalidBlockNumber,
+							  olderrcbarg.phase,
+							  olderrcbarg.blkno,
+							  olderrcbarg.indname,
 							  NULL);
 }
 
@@ -2435,6 +2451,7 @@ lazy_cleanup_index(Relation indrel,
 	IndexVacuumInfo ivinfo;
 	const char *msg;
 	PGRUsage	ru0;
+	LVRelStats	olderrcbarg;
 
 	pg_rusage_init(&ru0);
 
@@ -2449,7 +2466,9 @@ lazy_cleanup_index(Relation indrel,
 
 	/* Setup error traceback support for ereport() */
 	update_vacuum_error_cbarg(vacrelstats,
-							  VACUUM_ERRCB_PHASE_INDEX_CLEANUP, InvalidBlockNumber, indrel);
+							  VACUUM_ERRCB_PHASE_INDEX_CLEANUP,
+							  InvalidBlockNumber,
+							  RelationGetRelationName(indrel), &olderrcbarg);
 
 	*stats = index_vacuum_cleanup(&ivinfo, *stats);
 
@@ -2475,7 +2494,9 @@ lazy_cleanup_index(Relation indrel,
 
 	/* Clear the error traceback phase */
 	update_vacuum_error_cbarg(vacrelstats,
-							  VACUUM_ERRCB_PHASE_UNKNOWN, InvalidBlockNumber,
+							  olderrcbarg.phase,
+							  olderrcbarg.blkno,
+							  olderrcbarg.indname,
 							  NULL);
 }
 
@@ -3522,22 +3543,28 @@ vacuum_error_callback(void *arg)
 /* Update vacuum error callback for current phase, block and index */
 static void
 update_vacuum_error_cbarg(LVRelStats *errcbarg, int phase, BlockNumber blkno,
-						  Relation indrel)
+						  char *indname, LVRelStats *olderrcbarg)
 {
-	errcbarg->blkno = blkno;
-	errcbarg->phase = phase;
-
-	/* Free index name from any previous phase */
-	if (errcbarg->indname)
+	/* Save the values to allow resetting later */
+	if (olderrcbarg != NULL)
+		*olderrcbarg = *errcbarg;
+	else if (errcbarg->indname)
 	{
+		/*
+		 * Free index name from any previous phase, but only if we're resetting
+		 * the values to a previous state, and not if the values were saved to
+		 * restore later.  We need to avoid pfreeing a pointer that's
+		 * referenced by olderrcbarg.
+		 */
+		Assert(olderrcbarg == NULL);
 		pfree(errcbarg->indname);
 		errcbarg->indname = NULL;
 	}
 
+	errcbarg->blkno = blkno;
+	errcbarg->phase = phase;
+
 	/* For index phases, save the name of the current index for the callback */
-	if (indrel)
-	{
-		Assert(indrel->rd_rel->relkind == RELKIND_INDEX);
-		errcbarg->indname = pstrdup(RelationGetRelationName(indrel));
-	}
+	if (indname)
+		errcbarg->indname = pstrdup(indname);
 }
-- 
2.17.0

