On Thu, Mar 17, 2022 at 3:36 AM Andres Freund <and...@anarazel.de> wrote:
>
> The biggest todos are:
> - Address all the remaining AFIXMEs and XXXs

Attached is a patch that addresses three of the existing AFIXMEs.
From 2a975cdb5d10ec365ca2ced39b9f99a9385b6268 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplage...@gmail.com>
Date: Wed, 23 Mar 2022 19:43:12 -0400
Subject: [PATCH] Address 3 AFIXMEs

- reset timestamp callback
- schedule stat internl warn and reset if exists
- pending delete callback
---
 src/backend/utils/activity/pgstat.c           | 117 +++++++++---------
 src/backend/utils/activity/pgstat_database.c  |   7 ++
 src/backend/utils/activity/pgstat_relation.c  |  16 +++
 .../utils/activity/pgstat_subscription.c      |   7 ++
 src/include/utils/pgstat_internal.h           |  16 +++
 5 files changed, 105 insertions(+), 58 deletions(-)

diff --git a/src/backend/utils/activity/pgstat.c b/src/backend/utils/activity/pgstat.c
index 7f86bc29ee..9841447a8b 100644
--- a/src/backend/utils/activity/pgstat.c
+++ b/src/backend/utils/activity/pgstat.c
@@ -154,10 +154,8 @@ static void pgstat_shared_refs_release_all(void);
 static void pgstat_perform_drop(xl_xact_stats_item *drop);
 static bool pgstat_drop_stats_entry(dshash_seq_status *hstat);
 
-static void pgstat_shared_reset_timestamp(PgStatKind kind, PgStatShm_StatEntryHeader *header);
 static void pgstat_reset_all_stats(TimestampTz ts);
 
-static void pgstat_pending_delete(PgStatSharedRef *shared_ref);
 static bool pgstat_pending_flush_stats(bool nowait);
 
 static PgStatKind pgstat_kind_for(char *kind_str);
@@ -281,6 +279,8 @@ static const PgStatKindInfo pgstat_kind_infos[PGSTAT_KIND_LAST + 1] = {
 		.pending_size = sizeof(PgStat_StatDBEntry),
 
 		.flush_pending_cb = pgstat_flush_database,
+		.pending_delete_cb = pgstat_pending_delete,
+		.reset_timestamp_cb = pgstat_database_reset_timestamp,
 	},
 
 	[PGSTAT_KIND_TABLE] = {
@@ -294,6 +294,8 @@ static const PgStatKindInfo pgstat_kind_infos[PGSTAT_KIND_LAST + 1] = {
 		.pending_size = sizeof(PgStat_TableStatus),
 
 		.flush_pending_cb = pgstat_flush_relation,
+		.pending_delete_cb = pgstat_relation_pending_delete,
+		.reset_timestamp_cb = pgstat_shared_reset_timestamp_noop,
 	},
 
 	[PGSTAT_KIND_FUNCTION] = {
@@ -307,6 +309,8 @@ static const PgStatKindInfo pgstat_kind_infos[PGSTAT_KIND_LAST + 1] = {
 		.pending_size = sizeof(PgStat_BackendFunctionEntry),
 
 		.flush_pending_cb = pgstat_flush_function,
+		.pending_delete_cb = pgstat_pending_delete,
+		.reset_timestamp_cb = pgstat_shared_reset_timestamp_noop,
 	},
 
 	[PGSTAT_KIND_SUBSCRIPTION] = {
@@ -322,6 +326,8 @@ static const PgStatKindInfo pgstat_kind_infos[PGSTAT_KIND_LAST + 1] = {
 		.pending_size = sizeof(PgStat_BackendSubEntry),
 
 		.flush_pending_cb = pgstat_flush_subscription,
+		.pending_delete_cb = pgstat_pending_delete,
+		.reset_timestamp_cb = pgstat_subscription_reset_timestamp,
 	},
 
 
@@ -1040,12 +1046,18 @@ pgstat_schedule_stat_internal(PgStatKind kind, Oid dboid, Oid objoid, bool is_cr
 void
 pgstat_schedule_stat_create(PgStatKind kind, Oid dboid, Oid objoid)
 {
-	pgstat_schedule_stat_internal(kind, dboid, objoid, /* create */ true);
+	if (pgstat_shared_ref_get(kind, dboid, objoid, false, NULL))
+	{
+		Oid msg_oid = (kind == PGSTAT_KIND_DB) ? dboid : objoid;
 
-	/*
-	 * AFIXME: It would be a good idea to check if an object with that key
-	 * already exists. WARN if so, and reset the stats to 0.
-	 */
+		ereport(WARNING,
+				errmsg("Resetting existing stats for %s with OID %d.",
+					(pgstat_kind_info_for(kind))->name, msg_oid));
+
+		pgstat_reset_one(kind, dboid, objoid);
+	}
+
+	pgstat_schedule_stat_internal(kind, dboid, objoid, /* create */ true);
 }
 
 /*
@@ -2178,6 +2190,28 @@ pgstat_shared_refs_release_all(void)
  * ------------------------------------------------------------
  */
 
+/*
+ * Delete pending stats for variable number stats in the general case. Some
+ * types of stats require additional steps and have dedicated callbacks.
+ */
+void
+pgstat_pending_delete(PgStatSharedRef *shared_ref)
+{
+	void	   *pending_data = shared_ref->pending;
+	PgStatKind kind = shared_ref->shared_entry->key.kind;
+
+	Assert(pending_data != NULL);
+	Assert(!pgstat_kind_info_for(kind)->fixed_amount);
+
+	/* PGSTAT_KIND_TABLE has its own callback */
+	Assert(kind != PGSTAT_KIND_TABLE);
+
+	pfree(pending_data);
+	shared_ref->pending = NULL;
+
+	dlist_delete(&shared_ref->pending_node);
+}
+
 /*
  * Returns the appropriate PgStatSharedRef, preparing it to receive pending
  * stats if not already done.
@@ -2222,38 +2256,6 @@ pgstat_pending_fetch(PgStatKind kind, Oid dboid, Oid objoid)
 	return shared_ref;
 }
 
-static void
-pgstat_pending_delete(PgStatSharedRef *shared_ref)
-{
-	void	   *pending_data = shared_ref->pending;
-	PgStatKind	kind;
-
-	Assert(pending_data != NULL);
-
-	/* AFIXME: Move into a PgStatKindInfo callback */
-	kind = shared_ref->shared_entry->key.kind;
-	switch (kind)
-	{
-		case PGSTAT_KIND_TABLE:
-			pgstat_relation_unlink(((PgStat_TableStatus *) pending_data)->relation);
-			break;
-		case PGSTAT_KIND_DB:
-		case PGSTAT_KIND_FUNCTION:
-		case PGSTAT_KIND_SUBSCRIPTION:
-			break;
-		default:
-			/* !fixed_amount stats should be handled explicitly */
-			Assert(pgstat_kind_info_for(kind)->fixed_amount);
-			elog(ERROR, "unexpected");
-			break;
-	}
-
-	pfree(pending_data);
-	shared_ref->pending = NULL;
-
-	dlist_delete(&shared_ref->pending_node);
-}
-
 /*
  * Flush out pending stats for database objects (databases, relations,
  * functions).
@@ -2288,6 +2290,7 @@ pgstat_pending_flush_stats(bool nowait)
 
 		Assert(!kind_info->fixed_amount);
 		Assert(kind_info->flush_pending_cb != NULL);
+		Assert(kind_info->pending_delete_cb != NULL);
 
 		/* flush the stats, if possible */
 		remove = kind_info->flush_pending_cb(shared_ref, nowait);
@@ -2302,7 +2305,7 @@ pgstat_pending_flush_stats(bool nowait)
 
 		/* if successfully flushed, remove entry */
 		if (remove)
-			pgstat_pending_delete(shared_ref);
+			kind_info->pending_delete_cb(shared_ref);
 		else
 			have_pending = true;
 
@@ -2438,11 +2441,16 @@ pgstat_perform_drop(xl_xact_stats_item *drop)
 {
 	PgStatShmHashEntry *shent;
 	PgStatHashKey key;
+	const PgStatKindInfo *kind_info;
 
 	key.kind = drop->kind;
 	key.dboid = drop->dboid;
 	key.objoid = drop->objoid;
 
+	kind_info = pgstat_kind_info_for(drop->kind);
+	Assert(!kind_info->fixed_amount);
+	Assert(kind_info->pending_delete_cb != NULL);
+
 	if (pgStatSharedRefHash)
 	{
 		PgStatSharedRefHashEntry *lohashent;
@@ -2452,7 +2460,7 @@ pgstat_perform_drop(xl_xact_stats_item *drop)
 		if (lohashent)
 		{
 			if (lohashent->shared_ref && lohashent->shared_ref->pending)
-				pgstat_pending_delete(lohashent->shared_ref);
+				kind_info->pending_delete_cb(lohashent->shared_ref);
 
 			pgstat_shared_ref_release(lohashent->key, lohashent->shared_ref);
 		}
@@ -2498,9 +2506,12 @@ pgstat_perform_drop(xl_xact_stats_item *drop)
 static void
 pgstat_shared_stat_reset_one(PgStatKind kind, PgStatShm_StatEntryHeader *header)
 {
+	const PgStatKindInfo *kind_info = pgstat_kind_info_for(kind);
+
 	memset(shared_stat_entry_data(kind, header), 0,
 		   shared_stat_entry_len(kind));
-	pgstat_shared_reset_timestamp(kind, header);
+
+	kind_info->reset_timestamp_cb(header);
 }
 
 /*
@@ -2555,26 +2566,16 @@ pgstat_reset_matching(bool (*do_reset) (PgStatShmHashEntry *))
 	dshash_seq_term(&hstat);
 }
 
-static void
-pgstat_shared_reset_timestamp(PgStatKind kind, PgStatShm_StatEntryHeader *header)
+/*
+ * For variable number stats with no stats reset timestamp member
+ */
+void
+pgstat_shared_reset_timestamp_noop(PgStatShm_StatEntryHeader *header)
 {
-	/* AFIXME: Move into a PgStatKindInfo callback */
-	switch (kind)
-	{
-		case PGSTAT_KIND_DB:
-			((PgStatShm_StatDBEntry *) header)->stats.stat_reset_timestamp =
-				GetCurrentTimestamp();
-			break;
-		case PGSTAT_KIND_SUBSCRIPTION:
-			((PgStatShm_StatSubEntry *) header)->stats.stat_reset_timestamp =
-				GetCurrentTimestamp();
-			break;
-		default:
-			return;
-	}
 }
 
 
+
 /* ------------------------------------------------------------
  * Fetching of stats
  * ------------------------------------------------------------
diff --git a/src/backend/utils/activity/pgstat_database.c b/src/backend/utils/activity/pgstat_database.c
index 49037d345a..92ef8f1974 100644
--- a/src/backend/utils/activity/pgstat_database.c
+++ b/src/backend/utils/activity/pgstat_database.c
@@ -319,6 +319,13 @@ pgstat_should_report_connstat(void)
 	return MyBackendType == B_BACKEND;
 }
 
+void
+pgstat_database_reset_timestamp(PgStatShm_StatEntryHeader *header)
+{
+	((PgStatShm_StatDBEntry *) header)->stats.stat_reset_timestamp =
+		GetCurrentTimestamp();
+}
+
 /*
  * pgstat_flush_db - flush out a local database stats entry
  *
diff --git a/src/backend/utils/activity/pgstat_relation.c b/src/backend/utils/activity/pgstat_relation.c
index a96760f5b1..e3eb960659 100644
--- a/src/backend/utils/activity/pgstat_relation.c
+++ b/src/backend/utils/activity/pgstat_relation.c
@@ -885,6 +885,22 @@ pgstat_flush_relation(PgStatSharedRef *shared_ref, bool nowait)
 	return true;
 }
 
+void
+pgstat_relation_pending_delete(PgStatSharedRef *shared_ref)
+{
+	void	   *pending_data = shared_ref->pending;
+
+	Assert(pending_data != NULL);
+
+	pgstat_relation_unlink(((PgStat_TableStatus *) pending_data)->relation);
+
+	pfree(pending_data);
+	shared_ref->pending = NULL;
+
+	dlist_delete(&shared_ref->pending_node);
+}
+
+
 /*
  * Find or create a PgStat_TableStatus entry for rel. New entry is created and
  * initialized if not exists.
diff --git a/src/backend/utils/activity/pgstat_subscription.c b/src/backend/utils/activity/pgstat_subscription.c
index f7f5698c5d..5882016177 100644
--- a/src/backend/utils/activity/pgstat_subscription.c
+++ b/src/backend/utils/activity/pgstat_subscription.c
@@ -43,6 +43,13 @@ pgstat_reset_subscription_counter(Oid subid)
 	pgstat_reset_one(PGSTAT_KIND_SUBSCRIPTION, InvalidOid, subid);
 }
 
+void
+pgstat_subscription_reset_timestamp(PgStatShm_StatEntryHeader *header)
+{
+	((PgStatShm_StatSubEntry *) header)->stats.stat_reset_timestamp =
+		GetCurrentTimestamp();
+}
+
 /* ----------
  * pgstat_report_subscription_error() -
  *
diff --git a/src/include/utils/pgstat_internal.h b/src/include/utils/pgstat_internal.h
index b312993d1f..718e848866 100644
--- a/src/include/utils/pgstat_internal.h
+++ b/src/include/utils/pgstat_internal.h
@@ -193,6 +193,16 @@ typedef struct PgStatKindInfo
 	 */
 	bool		(*flush_pending_cb) (PgStatSharedRef *sr, bool nowait);
 
+	/*
+	 * For variable number stats: delete pending stats.
+	 */
+	void		(*pending_delete_cb) (PgStatSharedRef *sr);
+
+	/*
+	 * For variable number stats: reset the reset timestamp.
+	 */
+	void		(*reset_timestamp_cb) (PgStatShm_StatEntryHeader *header);
+
 	/*
 	 * For global statistics: Reset All.
 	 */
@@ -390,7 +400,9 @@ extern PgStatSharedRef *pgstat_shared_stat_locked(PgStatKind kind,
 												  bool nowait);
 extern void pgstat_reset_one(PgStatKind kind, Oid dboid, Oid objoid);
 extern void pgstat_reset_matching(bool (*do_reset) (PgStatShmHashEntry *));
+extern void pgstat_shared_reset_timestamp_noop(PgStatShm_StatEntryHeader *header);
 
+extern void pgstat_pending_delete(PgStatSharedRef *shared_ref);
 extern PgStatSharedRef *pgstat_pending_prepare(PgStatKind kind, Oid dboid, Oid objoid, bool *created_shared);
 extern PgStatSharedRef *pgstat_pending_fetch(PgStatKind kind, Oid dboid, Oid objoid);
 
@@ -441,6 +453,7 @@ extern void pgstat_checkpointer_snapshot_cb(void);
 extern void pgstat_report_disconnect(Oid dboid);
 extern void pgstat_update_dbstats(TimestampTz now);
 extern void AtEOXact_PgStat_Database(bool isCommit, bool parallel);
+extern void pgstat_database_reset_timestamp(PgStatShm_StatEntryHeader *header);
 extern bool pgstat_flush_database(PgStatSharedRef *shared_ref, bool nowait);
 extern PgStat_StatDBEntry *pgstat_pending_db_prepare(Oid dboid);
 
@@ -460,7 +473,9 @@ extern void AtEOXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isC
 extern void AtEOSubXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit, int nestDepth);
 extern void AtPrepare_PgStat_Relations(PgStat_SubXactStatus *xact_state);
 extern void PostPrepare_PgStat_Relations(PgStat_SubXactStatus *xact_state);
+
 extern bool pgstat_flush_relation(PgStatSharedRef *shared_ref, bool nowait);
+extern void pgstat_relation_pending_delete(PgStatSharedRef *shared_ref);
 
 
 /*
@@ -497,6 +512,7 @@ extern void pgstat_wal_snapshot_cb(void);
  */
 
 extern bool pgstat_flush_subscription(PgStatSharedRef *shared_ref, bool nowait);
+extern void pgstat_subscription_reset_timestamp(PgStatShm_StatEntryHeader *header);
 
 
 /*
-- 
2.30.2

Reply via email to