From 78a437946d5ccc70db98da9cc0fa0ae413afa625 Mon Sep 17 00:00:00 2001
From: "Imseih (AWS)" <simseih@88665a22795f.ant.amazon.com>
Date: Fri, 4 Nov 2022 07:52:02 -0500
Subject: [PATCH v14 2/2] Function to return currently vacuumed ( or cleaned )
 index.

pg_stat_get_vacuum_index takes a PID as an argument and
returns the index relid of the currently vacuumed index.
NULL is returned if the backend is not involved in an index vacuum.
---
 doc/src/sgml/func.sgml                | 13 +++++++
 doc/src/sgml/monitoring.sgml          |  8 +++--
 src/backend/access/heap/vacuumlazy.c  |  9 +++++
 src/backend/commands/vacuumparallel.c | 23 ++++++++++++
 src/backend/utils/adt/pgstatfuncs.c   | 52 +++++++++++++++++++++++++++
 src/include/catalog/pg_proc.dat       |  4 +++
 src/include/commands/progress.h       |  1 +
 src/include/utils/backend_progress.h  |  7 +++-
 8 files changed, 114 insertions(+), 3 deletions(-)
  22.2% doc/src/sgml/
  11.2% src/backend/access/heap/
  16.7% src/backend/commands/
  37.1% src/backend/utils/adt/
   5.7% src/include/catalog/
   5.4% src/include/utils/

diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 6e0425cb3d..39841354de 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -22670,6 +22670,19 @@ SELECT * FROM pg_ls_dir('.') WITH ORDINALITY AS t(ls,n);
         parsing the text version.
        </para></entry>
       </row>
+
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        <indexterm>
+         <primary>pg_stat_get_vacuum_index</primary>
+        </indexterm>
+        <function>pg_stat_get_vacuum_index</function> ( <type>integer</type> )
+        <returnvalue>oid</returnvalue>
+       </para>
+       <para>
+        Returns the relid of an index current being vacuumed or cleaned by the backend.
+       </para></entry>
+      </row>
      </tbody>
     </tgroup>
    </table>
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index c61443f3d5..8d947d8c3a 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -6517,7 +6517,9 @@ FROM pg_stat_get_backend_idset() AS backendid;
        has been completely scanned.  It may happen multiple times per vacuum
        if <xref linkend="guc-maintenance-work-mem"/> (or, in the case of autovacuum,
        <xref linkend="guc-autovacuum-work-mem"/> if set) is insufficient to store
-       the number of dead tuples found.
+       the number of dead tuples found. While in this phase, the function
+       <function>pg_stat_get_vacuum_index()</function> will return the relid
+       of the index being vacuumed.
      </entry>
     </row>
     <row>
@@ -6536,7 +6538,9 @@ FROM pg_stat_get_backend_idset() AS backendid;
      <entry>
        <command>VACUUM</command> is currently cleaning up indexes.  This occurs after
        the heap has been completely scanned and all vacuuming of the indexes
-       and the heap has been completed.
+       and the heap has been completed. While in this phase, the function
+       <function>pg_stat_get_vacuum_index()</function> will return the relid
+       of the index being cleaned.
      </entry>
     </row>
     <row>
diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c
index 120a2b18d7..8cd8e34f88 100644
--- a/src/backend/access/heap/vacuumlazy.c
+++ b/src/backend/access/heap/vacuumlazy.c
@@ -350,6 +350,7 @@ heap_vacuum_rel(Relation rel, VacuumParams *params,
 		}
 	}
 
+	/* start the vacuum progress command and report to progress.h */
 	pgstat_progress_start_command(PROGRESS_COMMAND_VACUUM,
 								  RelationGetRelid(rel));
 
@@ -2341,6 +2342,9 @@ lazy_vacuum_all_indexes(LVRelState *vacrel)
 			Relation	indrel = vacrel->indrels[idx];
 			IndexBulkDeleteResult *istat = vacrel->indstats[idx];
 
+			/* report the index relid being vacuumed */
+			pgstat_progress_update_param(PROGRESS_VACUUM_INDRELID, RelationGetRelid(indrel));
+
 			vacrel->indstats[idx] =
 				lazy_vacuum_one_index(indrel, istat, vacrel->old_live_tuples,
 									  vacrel);
@@ -2350,6 +2354,7 @@ lazy_vacuum_all_indexes(LVRelState *vacrel)
 			 */
 			pgstat_progress_update_param(PROGRESS_VACUUM_INDEX_COMPLETED,
 										 idx + 1);
+			pgstat_progress_update_param(PROGRESS_VACUUM_INDRELID, 0);
 
 			if (lazy_check_wraparound_failsafe(vacrel))
 			{
@@ -2705,6 +2710,9 @@ lazy_cleanup_all_indexes(LVRelState *vacrel)
 			Relation	indrel = vacrel->indrels[idx];
 			IndexBulkDeleteResult *istat = vacrel->indstats[idx];
 
+			/* report the index relid being cleaned */
+			pgstat_progress_update_param(PROGRESS_VACUUM_INDRELID, RelationGetRelid(indrel));
+
 			vacrel->indstats[idx] =
 				lazy_cleanup_one_index(indrel, istat, reltuples,
 									   estimated_count, vacrel);
@@ -2714,6 +2722,7 @@ lazy_cleanup_all_indexes(LVRelState *vacrel)
 			 */
 			pgstat_progress_update_param(PROGRESS_VACUUM_INDEX_COMPLETED,
 										 idx + 1);
+			pgstat_progress_update_param(PROGRESS_VACUUM_INDRELID, 0);
 		}
 	}
 	else
diff --git a/src/backend/commands/vacuumparallel.c b/src/backend/commands/vacuumparallel.c
index 85e2de5d54..f2f51e86eb 100644
--- a/src/backend/commands/vacuumparallel.c
+++ b/src/backend/commands/vacuumparallel.c
@@ -840,6 +840,20 @@ parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation indrel,
 	IndexBulkDeleteResult *istat = NULL;
 	IndexBulkDeleteResult *istat_res;
 	IndexVacuumInfo ivinfo;
+	Oid indrelid = RelationGetRelid(indrel);
+
+	/*
+	 * If we are a parallel worker, start a PROGRESS_COMMAND_VACUUM_PARALLEL
+	 * command for progress reporting and report the index being vacuumed.
+	 */
+	if (IsParallelWorker())
+	{
+		pgstat_progress_start_command(PROGRESS_COMMAND_VACUUM_PARALLEL,
+									  pvs->shared->relid);
+	}
+
+	/* report the index being vacuumed or cleaned up */
+	pgstat_progress_update_param(PROGRESS_VACUUM_INDRELID, indrelid);
 
 	/*
 	 * Update the pointer to the corresponding bulk-deletion result if someone
@@ -911,10 +925,19 @@ parallel_vacuum_process_one_index(ParallelVacuumState *pvs, Relation indrel,
 	pfree(pvs->indname);
 	pvs->indname = NULL;
 
+	/*
+	 * Reset the index relid begin vacuumed/cleaned
+	 */
+	pgstat_progress_update_param(PROGRESS_VACUUM_INDRELID, 0);
+
 	/*
 	 * Update the number of indexes completed.
 	 */
 	pg_atomic_add_fetch_u32(&(pvs->shared->idx_completed_progress), 1);
+
+	/* if we are a parallel worker, end the command */
+	if (IsParallelWorker())
+		pgstat_progress_end_command();
 }
 
 /*
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 96bffc0f2a..82eedae1f0 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -19,6 +19,7 @@
 #include "access/xlogprefetcher.h"
 #include "catalog/pg_authid.h"
 #include "catalog/pg_type.h"
+#include "commands/progress.h"
 #include "common/ip.h"
 #include "funcapi.h"
 #include "miscadmin.h"
@@ -2383,3 +2384,54 @@ pg_stat_have_stats(PG_FUNCTION_ARGS)
 
 	PG_RETURN_BOOL(pgstat_have_entry(kind, dboid, objoid));
 }
+
+/*
+ * For a given PID, return the relid of the index
+ * currently being vacuumed.
+ */
+Datum
+pg_stat_get_vacuum_index(PG_FUNCTION_ARGS)
+{
+	int			pid = PG_GETARG_INT32(0);
+	int			num_backends = pgstat_fetch_stat_numbackends();
+	int			curr_backend;
+	Oid 		indrelid = 0;
+	ProgressCommandType cmdtype_vacuum = PROGRESS_COMMAND_VACUUM;
+	ProgressCommandType cmdtype_vacuum_parallel = PROGRESS_COMMAND_VACUUM_PARALLEL;
+
+	/* 1-based index */
+	for (curr_backend = 1; curr_backend <= num_backends; curr_backend++)
+	{
+		LocalPgBackendStatus *local_beentry;
+		PgBackendStatus *beentry;
+
+		local_beentry = pgstat_fetch_stat_local_beentry(curr_backend);
+		beentry = &local_beentry->backendStatus;
+
+		/*
+		 * If a backend has a VACUUM or VACUUM_PARALLEL progress command type
+		 * and the procpid matches the given PID, return the index relid
+		 * that is current being vacuumed. In some cases, the index relid could
+		 * be a '0' if we got here at the end of a vacuum or when no indexes
+		 * are being vacuumed. In this case return NULL.
+		 */
+		if	(
+				(beentry->st_progress_command == cmdtype_vacuum
+					|| beentry->st_progress_command == cmdtype_vacuum_parallel) &&
+				 beentry->st_procpid == pid
+			)
+			{
+				indrelid = Int64GetDatum(beentry->st_progress_param[PROGRESS_VACUUM_INDRELID]);
+
+				if (indrelid > 0)
+					PG_RETURN_OID(indrelid);
+				else
+					PG_RETURN_NULL();
+			}
+	}
+
+	/*
+	 * No matching PID performing a VACUUM operation, return NULL.
+	 */
+	PG_RETURN_NULL();
+}
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 20f5aa56ea..dd5a32172a 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -11827,5 +11827,9 @@
   proname => 'brin_minmax_multi_summary_send', provolatile => 's',
   prorettype => 'bytea', proargtypes => 'pg_brin_minmax_multi_summary',
   prosrc => 'brin_minmax_multi_summary_send' },
+{ oid => '4642',
+  descr => 'get the relid of the index being vacuumed by a backend',
+  proname => 'pg_stat_get_vacuum_index', provolatile => 'v', prorettype => 'int8',
+  proargtypes => 'int4', prosrc => 'pg_stat_get_vacuum_index' },
 
 ]
diff --git a/src/include/commands/progress.h b/src/include/commands/progress.h
index 0e97c6d4ef..bc2b7d1e95 100644
--- a/src/include/commands/progress.h
+++ b/src/include/commands/progress.h
@@ -27,6 +27,7 @@
 #define PROGRESS_VACUUM_NUM_DEAD_TUPLES			6
 #define PROGRESS_VACUUM_INDEX_TOTAL             7
 #define PROGRESS_VACUUM_INDEX_COMPLETED         8
+#define PROGRESS_VACUUM_INDRELID                9
 
 /* Phases of vacuum (as advertised via PROGRESS_VACUUM_PHASE) */
 #define PROGRESS_VACUUM_PHASE_SCAN_HEAP			1
diff --git a/src/include/utils/backend_progress.h b/src/include/utils/backend_progress.h
index 47bf8029b0..74d9dfb4c7 100644
--- a/src/include/utils/backend_progress.h
+++ b/src/include/utils/backend_progress.h
@@ -17,6 +17,10 @@
 
 /* ----------
  * Command type for progress reporting purposes
+ *
+ * Note: PROGRESS_COMMAND_VACUUM_PARALLEL is not
+ * a command per se, but this type is used to track
+ * parallel vacuum workers progress.
  * ----------
  */
 typedef enum ProgressCommandType
@@ -27,7 +31,8 @@ typedef enum ProgressCommandType
 	PROGRESS_COMMAND_CLUSTER,
 	PROGRESS_COMMAND_CREATE_INDEX,
 	PROGRESS_COMMAND_BASEBACKUP,
-	PROGRESS_COMMAND_COPY
+	PROGRESS_COMMAND_COPY,
+	PROGRESS_COMMAND_VACUUM_PARALLEL
 } ProgressCommandType;
 
 #define PGSTAT_NUM_PROGRESS_PARAM	20
-- 
2.32.1 (Apple Git-133)

