Hi,

On 2020-06-23 00:14:40 -0400, Tom Lane wrote:
> Andres Freund <and...@anarazel.de> writes:
> > I am only suggesting that where you save the old location, as currently
> > done with LVRelStats olderrinfo, you instead use a more specific
> > type. Not that you should pass that anywhere (except for
> > update_vacuum_error_info).
> 
> As things currently stand, I don't think we need another struct
> type at all.  ISTM we should hard-wire the handling of indname
> as I suggested above.  Then there are only two fields to be dealt
> with, and we could just as well save them in simple local variables.

That's fine with me too.


> If there's a clear future path to needing to save/restore more
> fields, then maybe another struct type would be useful ... but
> right now the struct type declaration itself would take more
> lines of code than it would save.

FWIW, I started to be annoyed by this code when I was addding
prefetching support to vacuum, and wanted to change what's tracked
where. The number of places that needed to be touched was
disproportional.


Here's a *draft* for how I thought this roughly could look like. I think
it's nicer to not specify the exact saved state in multiple places, and
I think it's much clearer to use a separate function to restore the
state than to set a "fresh" state.

I've only applied a hacky fix for the way the indname is tracked, I
thought that'd best be discussed separately.

Greetings,

Andres Freund
diff --git i/src/backend/access/heap/vacuumlazy.c w/src/backend/access/heap/vacuumlazy.c
index 3bef0e124ba..afd6128233b 100644
--- i/src/backend/access/heap/vacuumlazy.c
+++ w/src/backend/access/heap/vacuumlazy.c
@@ -319,6 +319,12 @@ typedef struct LVRelStats
 	VacErrPhase phase;
 } LVRelStats;
 
+typedef struct LVSavedPos
+{
+	BlockNumber blkno;
+	VacErrPhase phase;
+} LVSavedPos;
+
 /* A few variables that don't seem worth passing around as parameters */
 static int	elevel = -1;
 
@@ -388,9 +394,9 @@ static void end_parallel_vacuum(Relation *Irel, IndexBulkDeleteResult **stats,
 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_info(LVRelStats *errinfo, int phase,
-									 BlockNumber blkno, char *indname);
-
+static void update_vacuum_error_info(LVRelStats *errinfo, LVSavedPos *oldpos,
+										   int phase, BlockNumber blkno, char *indname);
+static void restore_vacuum_error_info(LVRelStats *errinfo, const LVSavedPos *oldpos);
 
 /*
  *	heap_vacuum_rel() -- perform VACUUM for one heap relation
@@ -538,7 +544,8 @@ heap_vacuum_rel(Relation onerel, VacuumParams *params,
 		 * which we add context information to errors, so we don't need to
 		 * revert to the previous phase.
 		 */
-		update_vacuum_error_info(vacrelstats, VACUUM_ERRCB_PHASE_TRUNCATE,
+		update_vacuum_error_info(vacrelstats, NULL,
+								 VACUUM_ERRCB_PHASE_TRUNCATE,
 								 vacrelstats->nonempty_pages, NULL);
 		lazy_truncate_heap(onerel, vacrelstats);
 	}
@@ -948,8 +955,8 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
 
 		pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, blkno);
 
-		update_vacuum_error_info(vacrelstats, VACUUM_ERRCB_PHASE_SCAN_HEAP,
-								 blkno, NULL);
+		update_vacuum_error_info(vacrelstats, NULL,
+								 VACUUM_ERRCB_PHASE_SCAN_HEAP, blkno, NULL);
 
 		if (blkno == next_unskippable_block)
 		{
@@ -1820,15 +1827,14 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats)
 	int			npages;
 	PGRUsage	ru0;
 	Buffer		vmbuffer = InvalidBuffer;
-	LVRelStats	olderrinfo;
+	LVSavedPos	oldpos;
 
 	/* Report that we are now vacuuming the heap */
 	pgstat_progress_update_param(PROGRESS_VACUUM_PHASE,
 								 PROGRESS_VACUUM_PHASE_VACUUM_HEAP);
 
 	/* Update error traceback information */
-	olderrinfo = *vacrelstats;
-	update_vacuum_error_info(vacrelstats, VACUUM_ERRCB_PHASE_VACUUM_HEAP,
+	update_vacuum_error_info(vacrelstats, &oldpos, VACUUM_ERRCB_PHASE_VACUUM_HEAP,
 							 InvalidBlockNumber, NULL);
 
 	pg_rusage_init(&ru0);
@@ -1879,10 +1885,7 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats)
 			 errdetail_internal("%s", pg_rusage_show(&ru0))));
 
 	/* Revert to the previous phase information for error traceback */
-	update_vacuum_error_info(vacrelstats,
-							 olderrinfo.phase,
-							 olderrinfo.blkno,
-							 olderrinfo.indname);
+	restore_vacuum_error_info(vacrelstats, &oldpos);
 }
 
 /*
@@ -1905,14 +1908,13 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
 	int			uncnt = 0;
 	TransactionId visibility_cutoff_xid;
 	bool		all_frozen;
-	LVRelStats	olderrinfo;
+	LVSavedPos	oldpos;
 
 	pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_VACUUMED, blkno);
 
 	/* Update error traceback information */
-	olderrinfo = *vacrelstats;
-	update_vacuum_error_info(vacrelstats, VACUUM_ERRCB_PHASE_VACUUM_HEAP,
-							 blkno, NULL);
+	update_vacuum_error_info(vacrelstats, &oldpos,
+							 VACUUM_ERRCB_PHASE_VACUUM_HEAP, blkno, NULL);
 
 	START_CRIT_SECTION();
 
@@ -1991,10 +1993,7 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
 	}
 
 	/* Revert to the previous phase information for error traceback */
-	update_vacuum_error_info(vacrelstats,
-							 olderrinfo.phase,
-							 olderrinfo.blkno,
-							 olderrinfo.indname);
+	restore_vacuum_error_info(vacrelstats, &oldpos);
 	return tupindex;
 }
 
@@ -2404,7 +2403,7 @@ lazy_vacuum_index(Relation indrel, IndexBulkDeleteResult **stats,
 	IndexVacuumInfo ivinfo;
 	const char *msg;
 	PGRUsage	ru0;
-	LVRelStats	olderrinfo;
+	LVSavedPos	oldpos;
 
 	pg_rusage_init(&ru0);
 
@@ -2417,8 +2416,7 @@ lazy_vacuum_index(Relation indrel, IndexBulkDeleteResult **stats,
 	ivinfo.strategy = vac_strategy;
 
 	/* Update error traceback information */
-	olderrinfo = *vacrelstats;
-	update_vacuum_error_info(vacrelstats,
+	update_vacuum_error_info(vacrelstats, &oldpos,
 							 VACUUM_ERRCB_PHASE_VACUUM_INDEX,
 							 InvalidBlockNumber,
 							 RelationGetRelationName(indrel));
@@ -2439,10 +2437,7 @@ lazy_vacuum_index(Relation indrel, IndexBulkDeleteResult **stats,
 			 errdetail_internal("%s", pg_rusage_show(&ru0))));
 
 	/* Revert to the previous phase information for error traceback */
-	update_vacuum_error_info(vacrelstats,
-							 olderrinfo.phase,
-							 olderrinfo.blkno,
-							 olderrinfo.indname);
+	restore_vacuum_error_info(vacrelstats, &oldpos);
 }
 
 /*
@@ -2459,7 +2454,7 @@ lazy_cleanup_index(Relation indrel,
 	IndexVacuumInfo ivinfo;
 	const char *msg;
 	PGRUsage	ru0;
-	LVRelStats	olderrcbarg;
+	LVSavedPos	oldpos;
 
 	pg_rusage_init(&ru0);
 
@@ -2473,8 +2468,7 @@ lazy_cleanup_index(Relation indrel,
 	ivinfo.strategy = vac_strategy;
 
 	/* Update error traceback information */
-	olderrcbarg = *vacrelstats;
-	update_vacuum_error_info(vacrelstats,
+	update_vacuum_error_info(vacrelstats, &oldpos,
 							 VACUUM_ERRCB_PHASE_INDEX_CLEANUP,
 							 InvalidBlockNumber,
 							 RelationGetRelationName(indrel));
@@ -2482,10 +2476,8 @@ lazy_cleanup_index(Relation indrel,
 	*stats = index_vacuum_cleanup(&ivinfo, *stats);
 
 	/* Revert back to the old phase information for error traceback */
-	update_vacuum_error_info(vacrelstats,
-							 olderrcbarg.phase,
-							 olderrcbarg.blkno,
-							 olderrcbarg.indname);
+	restore_vacuum_error_info(vacrelstats, &oldpos);
+
 	if (!(*stats))
 		return;
 
@@ -3600,9 +3592,15 @@ vacuum_error_callback(void *arg)
 
 /* Update vacuum error callback for the current phase, block, and index. */
 static void
-update_vacuum_error_info(LVRelStats *errinfo, int phase, BlockNumber blkno,
-						 char *indname)
+update_vacuum_error_info(LVRelStats *errinfo, LVSavedPos *oldpos,
+						 int phase, BlockNumber blkno, char *indname)
 {
+	if (oldpos)
+	{
+		oldpos->blkno = errinfo->blkno;
+		oldpos->phase = errinfo->phase;
+	}
+
 	errinfo->blkno = blkno;
 	errinfo->phase = phase;
 
@@ -3613,3 +3611,17 @@ update_vacuum_error_info(LVRelStats *errinfo, int phase, BlockNumber blkno,
 	/* For index phases, save the name of the current index for the callback */
 	errinfo->indname = indname ? pstrdup(indname) : NULL;
 }
+
+static void
+restore_vacuum_error_info(LVRelStats *errinfo, const LVSavedPos *oldpos)
+{
+	errinfo->blkno = oldpos->blkno;
+	errinfo->phase = oldpos->phase;
+
+	/* FIXME: Imo pretty ugly that we don't restore the name properly */
+	if (errinfo->indname)
+	{
+		pfree(errinfo->indname);
+		errinfo->indname = NULL;
+	}
+}

Reply via email to