From 8679b23153d3b663a3a720060362ad82ffd7b45f Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Sun, 3 Apr 2022 12:57:31 -0700
Subject: [PATCH v68 09/31] pgstat: prepare APIs used by pgstatfuncs for shared
 memory stats.

---
 src/include/pgstat.h                          | 25 ++-----
 src/backend/postmaster/pgstat.c               | 45 +++++++------
 src/backend/utils/activity/pgstat_replslot.c  | 51 +++++++++++---
 src/backend/utils/activity/pgstat_slru.c      |  6 +-
 .../utils/activity/pgstat_subscription.c      | 20 +++++-
 src/backend/utils/adt/pgstatfuncs.c           | 67 +++++++++----------
 src/tools/pgindent/typedefs.list              |  2 -
 7 files changed, 123 insertions(+), 93 deletions(-)

diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 1d03bd97de4..a87b45f368e 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -85,21 +85,6 @@ typedef enum SessionEndType
  */
 typedef int64 PgStat_Counter;
 
-/* Possible targets for resetting cluster-wide shared values */
-typedef enum PgStat_Shared_Reset_Target
-{
-	RESET_ARCHIVER,
-	RESET_BGWRITER,
-	RESET_WAL
-} PgStat_Shared_Reset_Target;
-
-/* Possible object types for resetting single counters */
-typedef enum PgStat_Single_Reset_Type
-{
-	RESET_TABLE,
-	RESET_FUNCTION
-} PgStat_Single_Reset_Type;
-
 
 /* ------------------------------------------------------------
  * Structures kept in backend local memory while accumulating counts
@@ -418,7 +403,7 @@ typedef struct PgStat_MsgResetcounter
 typedef struct PgStat_MsgResetsharedcounter
 {
 	PgStat_MsgHdr m_hdr;
-	PgStat_Shared_Reset_Target m_resettarget;
+	PgStat_Kind m_resettarget;
 } PgStat_MsgResetsharedcounter;
 
 /* ----------
@@ -430,7 +415,7 @@ typedef struct PgStat_MsgResetsinglecounter
 {
 	PgStat_MsgHdr m_hdr;
 	Oid			m_databaseid;
-	PgStat_Single_Reset_Type m_resettype;
+	PgStat_Kind m_resettype;
 	Oid			m_objectid;
 } PgStat_MsgResetsinglecounter;
 
@@ -1009,8 +994,8 @@ extern void pgstat_vacuum_stat(void);
 extern void pgstat_ping(void);
 
 extern void pgstat_reset_counters(void);
-extern void pgstat_reset_single_counter(Oid objectid, PgStat_Single_Reset_Type type);
-extern void pgstat_reset_shared_counters(const char *);
+extern void pgstat_reset_single_counter(PgStat_Kind kind, Oid objectid);
+extern void pgstat_reset_shared_counters(PgStat_Kind kind);
 
 /* stats accessors */
 extern PgStat_ArchiverStats *pgstat_fetch_stat_archiver(void);
@@ -1155,6 +1140,7 @@ extern PgStat_TableStatus *find_tabstat_entry(Oid rel_id);
  * Functions in pgstat_replslot.c
  */
 
+extern void pgstat_reset_replslot_counters(void);
 extern void pgstat_reset_replslot_counter(const char *name);
 extern void pgstat_report_replslot(const PgStat_StatReplSlotEntry *repSlotStat);
 extern void pgstat_report_replslot_create(const char *slotname);
@@ -1181,6 +1167,7 @@ extern int	pgstat_slru_index(const char *name);
  * Functions in pgstat_subscription.c
  */
 
+extern void pgstat_reset_subscription_counters(void);
 extern void pgstat_reset_subscription_counter(Oid subid);
 extern void pgstat_report_subscription_error(Oid subid, bool is_apply_error);
 extern void pgstat_report_subscription_drop(Oid subid);
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index 8cbed1d1bc3..c9714b9f68f 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -1090,7 +1090,7 @@ pgstat_reset_counters(void)
  * GRANT system.
  */
 void
-pgstat_reset_single_counter(Oid objoid, PgStat_Single_Reset_Type type)
+pgstat_reset_single_counter(PgStat_Kind kind, Oid objoid)
 {
 	PgStat_MsgResetsinglecounter msg;
 
@@ -1099,7 +1099,7 @@ pgstat_reset_single_counter(Oid objoid, PgStat_Single_Reset_Type type)
 
 	pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_RESETSINGLECOUNTER);
 	msg.m_databaseid = MyDatabaseId;
-	msg.m_resettype = type;
+	msg.m_resettype = kind;
 	msg.m_objectid = objoid;
 
 	pgstat_send(&msg, sizeof(msg));
@@ -1112,26 +1112,15 @@ pgstat_reset_single_counter(Oid objoid, PgStat_Single_Reset_Type type)
  * GRANT system.
  */
 void
-pgstat_reset_shared_counters(const char *target)
+pgstat_reset_shared_counters(PgStat_Kind kind)
 {
 	PgStat_MsgResetsharedcounter msg;
 
 	if (pgStatSock == PGINVALID_SOCKET)
 		return;
 
-	if (strcmp(target, "archiver") == 0)
-		msg.m_resettarget = RESET_ARCHIVER;
-	else if (strcmp(target, "bgwriter") == 0)
-		msg.m_resettarget = RESET_BGWRITER;
-	else if (strcmp(target, "wal") == 0)
-		msg.m_resettarget = RESET_WAL;
-	else
-		ereport(ERROR,
-				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-				 errmsg("unrecognized reset target: \"%s\"", target),
-				 errhint("Target must be \"archiver\", \"bgwriter\", or \"wal\".")));
-
 	pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_RESETSHAREDCOUNTER);
+	msg.m_resettarget = kind;
 	pgstat_send(&msg, sizeof(msg));
 }
 
@@ -3528,7 +3517,8 @@ pgstat_recv_resetcounter(PgStat_MsgResetcounter *msg, int len)
 static void
 pgstat_recv_resetsharedcounter(PgStat_MsgResetsharedcounter *msg, int len)
 {
-	if (msg->m_resettarget == RESET_BGWRITER)
+	if (msg->m_resettarget == PGSTAT_KIND_BGWRITER ||
+		msg->m_resettarget == PGSTAT_KIND_CHECKPOINTER)
 	{
 		/*
 		 * Reset the global, bgwriter and checkpointer statistics for the
@@ -3537,13 +3527,24 @@ pgstat_recv_resetsharedcounter(PgStat_MsgResetsharedcounter *msg, int len)
 		memset(&globalStats, 0, sizeof(globalStats));
 		globalStats.bgwriter.stat_reset_timestamp = GetCurrentTimestamp();
 	}
-	else if (msg->m_resettarget == RESET_ARCHIVER)
+	else if (msg->m_resettarget == PGSTAT_KIND_ARCHIVER)
 	{
 		/* Reset the archiver statistics for the cluster. */
 		memset(&archiverStats, 0, sizeof(archiverStats));
 		archiverStats.stat_reset_timestamp = GetCurrentTimestamp();
 	}
-	else if (msg->m_resettarget == RESET_WAL)
+	else if (msg->m_resettarget == PGSTAT_KIND_SLRU)
+	{
+		int			i;
+		TimestampTz ts = GetCurrentTimestamp();
+
+		for (i = 0; i < SLRU_NUM_ELEMENTS; i++)
+		{
+			memset(&slruStats[i], 0, sizeof(slruStats[i]));
+			slruStats[i].stat_reset_timestamp = ts;
+		}
+	}
+	else if (msg->m_resettarget == PGSTAT_KIND_WAL)
 	{
 		/* Reset the WAL statistics for the cluster. */
 		memset(&walStats, 0, sizeof(walStats));
@@ -3577,10 +3578,10 @@ pgstat_recv_resetsinglecounter(PgStat_MsgResetsinglecounter *msg, int len)
 	dbentry->stat_reset_timestamp = GetCurrentTimestamp();
 
 	/* Remove object if it exists, ignore it if not */
-	if (msg->m_resettype == RESET_TABLE)
+	if (msg->m_resettype == PGSTAT_KIND_RELATION)
 		(void) hash_search(dbentry->tables, (void *) &(msg->m_objectid),
 						   HASH_REMOVE, NULL);
-	else if (msg->m_resettype == RESET_FUNCTION)
+	else if (msg->m_resettype == PGSTAT_KIND_FUNCTION)
 		(void) hash_search(dbentry->functions, (void *) &(msg->m_objectid),
 						   HASH_REMOVE, NULL);
 }
@@ -3596,8 +3597,8 @@ pgstat_recv_resetslrucounter(PgStat_MsgResetslrucounter *msg, int len)
 
 	for (i = 0; i < SLRU_NUM_ELEMENTS; i++)
 	{
-		/* reset entry with the given index, or all entries (index is -1) */
-		if ((msg->m_index == -1) || (msg->m_index == i))
+		/* reset entry with the given index */
+		if (msg->m_index == i)
 		{
 			memset(&slruStats[i], 0, sizeof(slruStats[i]));
 			slruStats[i].stat_reset_timestamp = ts;
diff --git a/src/backend/utils/activity/pgstat_replslot.c b/src/backend/utils/activity/pgstat_replslot.c
index 35078ad73c8..1c197f79a90 100644
--- a/src/backend/utils/activity/pgstat_replslot.c
+++ b/src/backend/utils/activity/pgstat_replslot.c
@@ -23,8 +23,23 @@
 
 
 /*
- * Reset counters for a single replication slot, or all replication slots
- * (when name is null).
+ * Reset counters for all replication slots.
+ */
+void
+pgstat_reset_replslot_counters(void)
+{
+	PgStat_MsgResetreplslotcounter msg;
+
+	if (pgStatSock == PGINVALID_SOCKET)
+		return;
+
+	pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_RESETREPLSLOTCOUNTER);
+	msg.clearall = true;
+	pgstat_send(&msg, sizeof(msg));
+}
+
+/*
+ * Reset counters for a single replication slot.
  *
  * Permission checking for this function is managed through the normal
  * GRANT system.
@@ -32,21 +47,37 @@
 void
 pgstat_reset_replslot_counter(const char *name)
 {
+	ReplicationSlot *slot;
 	PgStat_MsgResetreplslotcounter msg;
 
+	AssertArg(name != NULL);
+
 	if (pgStatSock == PGINVALID_SOCKET)
 		return;
 
-	if (name)
-	{
-		namestrcpy(&msg.m_slotname, name);
-		msg.clearall = false;
-	}
-	else
-		msg.clearall = true;
+	/*
+	 * Check if the slot exists with the given name. It is possible that by
+	 * the time this message is executed the slot is dropped but at least this
+	 * check will ensure that the given name is for a valid slot.
+	 */
+	slot = SearchNamedReplicationSlot(name, true);
+
+	if (!slot)
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("replication slot \"%s\" does not exist",
+						name)));
+
+	/*
+	 * Nothing to do for physical slots as we collect stats only for logical
+	 * slots.
+	 */
+	if (SlotIsPhysical(slot))
+		return;
 
 	pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_RESETREPLSLOTCOUNTER);
-
+	namestrcpy(&msg.m_slotname, name);
+	msg.clearall = false;
 	pgstat_send(&msg, sizeof(msg));
 }
 
diff --git a/src/backend/utils/activity/pgstat_slru.c b/src/backend/utils/activity/pgstat_slru.c
index 6dae3a5dc66..9cb9aeb890d 100644
--- a/src/backend/utils/activity/pgstat_slru.c
+++ b/src/backend/utils/activity/pgstat_slru.c
@@ -33,7 +33,7 @@ static PgStat_MsgSLRU SLRUStats[SLRU_NUM_ELEMENTS];
 
 
 /*
- * Reset counters for a single SLRU, or all SLRUs (when name is null).
+ * Reset counters for a single SLRU.
  *
  * Permission checking for this function is managed through the normal
  * GRANT system.
@@ -43,11 +43,13 @@ pgstat_reset_slru_counter(const char *name)
 {
 	PgStat_MsgResetslrucounter msg;
 
+	AssertArg(name != NULL);
+
 	if (pgStatSock == PGINVALID_SOCKET)
 		return;
 
 	pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_RESETSLRUCOUNTER);
-	msg.m_index = (name) ? pgstat_slru_index(name) : -1;
+	msg.m_index = pgstat_slru_index(name);
 
 	pgstat_send(&msg, sizeof(msg));
 }
diff --git a/src/backend/utils/activity/pgstat_subscription.c b/src/backend/utils/activity/pgstat_subscription.c
index 2ee23d5ae2c..7e82bb16a19 100644
--- a/src/backend/utils/activity/pgstat_subscription.c
+++ b/src/backend/utils/activity/pgstat_subscription.c
@@ -21,8 +21,23 @@
 
 
 /*
- * Reset counters for a single subscription, or all subscriptions (when subid
- * is InvalidOid).
+ * Reset counters for all subscriptions.
+ */
+void
+pgstat_reset_subscription_counters(void)
+{
+	PgStat_MsgResetsubcounter msg;
+
+	if (pgStatSock == PGINVALID_SOCKET)
+		return;
+
+	msg.m_subid = InvalidOid;
+	pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_RESETSUBCOUNTER);
+	pgstat_send(&msg, sizeof(msg));
+}
+
+/*
+ * Reset counters for a single subscription.
  *
  * Permission checking for this function is managed through the normal
  * GRANT system.
@@ -37,7 +52,6 @@ pgstat_reset_subscription_counter(Oid subid)
 
 	msg.m_subid = subid;
 	pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_RESETSUBCOUNTER);
-
 	pgstat_send(&msg, sizeof(msg));
 }
 
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index fd4276fbc67..02676bf01dc 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -2075,7 +2075,24 @@ pg_stat_reset_shared(PG_FUNCTION_ARGS)
 {
 	char	   *target = text_to_cstring(PG_GETARG_TEXT_PP(0));
 
-	pgstat_reset_shared_counters(target);
+	if (strcmp(target, "archiver") == 0)
+		pgstat_reset_shared_counters(PGSTAT_KIND_ARCHIVER);
+	else if (strcmp(target, "bgwriter") == 0)
+	{
+		/*
+		 * Historically checkpointer was part of bgwriter, continue to reset
+		 * both for now.
+		 */
+		pgstat_reset_shared_counters(PGSTAT_KIND_BGWRITER);
+		pgstat_reset_shared_counters(PGSTAT_KIND_CHECKPOINTER);
+	}
+	else if (strcmp(target, "wal") == 0)
+		pgstat_reset_shared_counters(PGSTAT_KIND_WAL);
+	else
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("unrecognized reset target: \"%s\"", target),
+				 errhint("Target must be \"archiver\", \"bgwriter\", or \"wal\".")));
 
 	PG_RETURN_VOID();
 }
@@ -2086,7 +2103,7 @@ pg_stat_reset_single_table_counters(PG_FUNCTION_ARGS)
 {
 	Oid			taboid = PG_GETARG_OID(0);
 
-	pgstat_reset_single_counter(taboid, RESET_TABLE);
+	pgstat_reset_single_counter(PGSTAT_KIND_RELATION, taboid);
 
 	PG_RETURN_VOID();
 }
@@ -2096,7 +2113,7 @@ pg_stat_reset_single_function_counters(PG_FUNCTION_ARGS)
 {
 	Oid			funcoid = PG_GETARG_OID(0);
 
-	pgstat_reset_single_counter(funcoid, RESET_FUNCTION);
+	pgstat_reset_single_counter(PGSTAT_KIND_FUNCTION, funcoid);
 
 	PG_RETURN_VOID();
 }
@@ -2107,10 +2124,13 @@ pg_stat_reset_slru(PG_FUNCTION_ARGS)
 {
 	char	   *target = NULL;
 
-	if (!PG_ARGISNULL(0))
+	if (PG_ARGISNULL(0))
+		pgstat_reset_shared_counters(PGSTAT_KIND_SLRU);
+	else
+	{
 		target = text_to_cstring(PG_GETARG_TEXT_PP(0));
-
-	pgstat_reset_slru_counter(target);
+		pgstat_reset_slru_counter(target);
+	}
 
 	PG_RETURN_VOID();
 }
@@ -2121,36 +2141,14 @@ pg_stat_reset_replication_slot(PG_FUNCTION_ARGS)
 {
 	char	   *target = NULL;
 
-	if (!PG_ARGISNULL(0))
+	if (PG_ARGISNULL(0))
+		pgstat_reset_replslot_counters();
+	else
 	{
-		ReplicationSlot *slot;
-
 		target = text_to_cstring(PG_GETARG_TEXT_PP(0));
-
-		/*
-		 * Check if the slot exists with the given name. It is possible that
-		 * by the time this message is executed the slot is dropped but at
-		 * least this check will ensure that the given name is for a valid
-		 * slot.
-		 */
-		slot = SearchNamedReplicationSlot(target, true);
-
-		if (!slot)
-			ereport(ERROR,
-					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-					 errmsg("replication slot \"%s\" does not exist",
-							target)));
-
-		/*
-		 * Nothing to do for physical slots as we collect stats only for
-		 * logical slots.
-		 */
-		if (SlotIsPhysical(slot))
-			PG_RETURN_VOID();
+		pgstat_reset_replslot_counter(target);
 	}
 
-	pgstat_reset_replslot_counter(target);
-
 	PG_RETURN_VOID();
 }
 
@@ -2163,7 +2161,7 @@ pg_stat_reset_subscription_stats(PG_FUNCTION_ARGS)
 	if (PG_ARGISNULL(0))
 	{
 		/* Clear all subscription stats */
-		subid = InvalidOid;
+		pgstat_reset_subscription_counters();
 	}
 	else
 	{
@@ -2173,10 +2171,9 @@ pg_stat_reset_subscription_stats(PG_FUNCTION_ARGS)
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 					 errmsg("invalid subscription OID %u", subid)));
+		pgstat_reset_subscription_counter(subid);
 	}
 
-	pgstat_reset_subscription_counter(subid);
-
 	PG_RETURN_VOID();
 }
 
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index a5c15a1d68f..53b73087eb8 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -1966,8 +1966,6 @@ PgStat_MsgTempFile
 PgStat_MsgVacuum
 PgStat_MsgWal
 PgStat_SLRUStats
-PgStat_Shared_Reset_Target
-PgStat_Single_Reset_Type
 PgStat_StatDBEntry
 PgStat_StatFuncEntry
 PgStat_StatReplSlotEntry
-- 
2.35.1.677.gabf474a5dd

