From f0a5cc6ad6cc351adff9302c3e9b2a227a5d9cb4 Mon Sep 17 00:00:00 2001
From: Atsushi Torikoshi <torikoshia@oss.nttdata.com>
Date: Mon, 6 Nov 2023 14:53:19 +0900
Subject: [PATCH v1] [WIP]Add ability to reset all statistics to
 pg_stat_reset_shared()

Currently pg_stat_reset_shared() requires its argument to specify
statistics to be reset, and there is no way to reset all statistics
at the same time.
This patch makes it possible when no argument is specified.

Note this patch is WIP and pg_stat_recovery_prefetch is not reset.
---
 doc/src/sgml/monitoring.sgml        |  4 +-
 src/backend/utils/activity/pgstat.c | 75 +++++++++++++++++++++++++++++
 src/backend/utils/adt/pgstatfuncs.c | 10 ++++
 src/include/catalog/pg_proc.dat     |  4 ++
 src/include/pgstat.h                |  1 +
 5 files changed, 93 insertions(+), 1 deletion(-)

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index e068f7e247..9d1e3bf4db 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -4716,7 +4716,7 @@ description | Waiting for a newly initialized WAL file to reach durable storage
         <returnvalue>void</returnvalue>
        </para>
        <para>
-        Resets some cluster-wide statistics counters to zero, depending on the
+        Resets cluster-wide statistics counters to zero, depending on the
         argument.  The argument can be <literal>bgwriter</literal> to reset
         all the counters shown in
         the <structname>pg_stat_bgwriter</structname> view,
@@ -4730,6 +4730,8 @@ description | Waiting for a newly initialized WAL file to reach durable storage
         <structname>pg_stat_wal</structname> view or
         <literal>recovery_prefetch</literal> to reset all the counters shown
         in the <structname>pg_stat_recovery_prefetch</structname> view.
+        If no argument is specified, reset all these views at once.
+        Note current patch is WIP and pg_stat_recovery_prefetch is not reset.
        </para>
        <para>
         This function is restricted to superusers by default, but other users
diff --git a/src/backend/utils/activity/pgstat.c b/src/backend/utils/activity/pgstat.c
index d743fc0b28..9b9398439f 100644
--- a/src/backend/utils/activity/pgstat.c
+++ b/src/backend/utils/activity/pgstat.c
@@ -767,6 +767,81 @@ pgstat_reset_of_kind(PgStat_Kind kind)
 		pgstat_reset_entries_of_kind(kind, ts);
 }
 
+/* Reset below cluster-wide statistics:
+ * - pg_stat_bgwriter
+ * - pg_stat_checkpointer
+ * - pg_stat_archiver
+ * - pg_stat_io
+ * - pg_stat_wal
+ *
+ * Note recovery_prefetch is not implemented(WIP).
+ */
+void
+pgstat_reset_shared_all(void)
+{
+#define STATS_SHARED_NUM_LWLOCK	4
+	TimestampTz ts = GetCurrentTimestamp();
+
+	PgStatShared_Archiver *stats_archiver = &pgStatLocal.shmem->archiver;
+	PgStatShared_BgWriter *stats_bgwriter = &pgStatLocal.shmem->bgwriter;
+	PgStatShared_Checkpointer *stats_checkpointer = &pgStatLocal.shmem->checkpointer;
+	PgStatShared_Wal *stats_wal = &pgStatLocal.shmem->wal;
+	PgStatShared_IO *stats_io = &pgStatLocal.shmem->io;
+
+	// Acquire LWLocks
+	LWLock *locks[] = {&stats_archiver->lock,  &stats_bgwriter->lock,
+					   &stats_checkpointer->lock, &stats_wal->lock};
+
+	for (int i = 0; i < STATS_SHARED_NUM_LWLOCK; i++)
+		LWLockAcquire(locks[i], LW_EXCLUSIVE);
+
+	for (int i = 0; i < BACKEND_NUM_TYPES; i++)
+	{
+		LWLock	*bktype_lock = &stats_io->locks[i];
+		LWLockAcquire(bktype_lock, LW_EXCLUSIVE);
+	}
+
+	// Reset stats
+	pgstat_copy_changecounted_stats(&stats_archiver->reset_offset,
+									&stats_archiver->stats,
+									sizeof(stats_archiver->stats),
+									&stats_archiver->changecount);
+	stats_archiver->stats.stat_reset_timestamp = ts;
+
+	pgstat_copy_changecounted_stats(&stats_bgwriter->reset_offset,
+									&stats_bgwriter->stats,
+									sizeof(stats_bgwriter->stats),
+									&stats_bgwriter->changecount);
+	stats_bgwriter->stats.stat_reset_timestamp = ts;
+
+	pgstat_copy_changecounted_stats(&stats_checkpointer->reset_offset,
+									&stats_checkpointer->stats,
+									sizeof(stats_checkpointer->stats),
+									&stats_checkpointer->changecount);
+	stats_checkpointer->stats.stat_reset_timestamp = ts;
+
+	memset(&stats_wal->stats, 0, sizeof(stats_wal->stats));
+	stats_wal->stats.stat_reset_timestamp = ts;
+
+	for (int i = 0; i < BACKEND_NUM_TYPES; i++)
+	{
+		PgStat_BktypeIO *bktype_shstats = &stats_io->stats.stats[i];
+		memset(bktype_shstats, 0, sizeof(*bktype_shstats));
+
+		if (i == 0)
+			pgStatLocal.shmem->io.stats.stat_reset_timestamp = ts;
+	}
+
+	// Release LWLocks
+	for (int i = 0; i < STATS_SHARED_NUM_LWLOCK; i++)
+		LWLockRelease(locks[i]);
+
+	for (int i = 0; i < BACKEND_NUM_TYPES; i++)
+	{
+		LWLock     *bktype_lock = &stats_io->locks[i];
+		LWLockRelease(bktype_lock);
+	}
+}
 
 /* ------------------------------------------------------------
  * Fetching of stats
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 1fb8b31863..0d6f375238 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -1676,6 +1676,16 @@ pg_stat_reset(PG_FUNCTION_ARGS)
 	PG_RETURN_VOID();
 }
 
+/*
+ * Reset all shared cluster-wide counters
+ */
+Datum
+pg_stat_reset_shared_all(PG_FUNCTION_ARGS)
+{
+	pgstat_reset_shared_all();
+	PG_RETURN_VOID();
+}
+
 /*
  * Reset some shared cluster-wide counters
  *
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 091f7e343c..afda903f24 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5883,6 +5883,10 @@
   descr => 'statistics: reset collected statistics shared across the cluster',
   proname => 'pg_stat_reset_shared', provolatile => 'v', prorettype => 'void',
   proargtypes => 'text', prosrc => 'pg_stat_reset_shared' },
+{ oid => '8000',
+  descr => 'statistics: reset collected statistics shared across the cluster',
+  proname => 'pg_stat_reset_shared', provolatile => 'v', prorettype => 'void',
+  proargtypes => '', prosrc => 'pg_stat_reset_shared_all' },
 { oid => '3776',
   descr => 'statistics: reset collected statistics for a single table or index in the current database or shared across all databases in the cluster',
   proname => 'pg_stat_reset_single_table_counters', provolatile => 'v',
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index f95d8db0c4..2b238bee78 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -477,6 +477,7 @@ extern void pgstat_force_next_flush(void);
 extern void pgstat_reset_counters(void);
 extern void pgstat_reset(PgStat_Kind kind, Oid dboid, Oid objoid);
 extern void pgstat_reset_of_kind(PgStat_Kind kind);
+extern void pgstat_reset_shared_all(void);
 
 /* stats accessors */
 extern void pgstat_clear_snapshot(void);

base-commit: 2c7c6c417fe655ab3fd4ca7f68ec22c913a2fe80
-- 
2.39.2

