From: Andres Freund <andres@anarazel.de>
Date: Fri, 15 Apr 2022 00:40:25 +0000 (-0700)
Subject: pgstat: set timestamps of fixed-numbered stats after a crash.
X-Git-Tag: REL_15_BETA1~157
X-Git-Url: http://git.postgresql.org/gitweb/?a=commitdiff_plain;h=5cd1c40b3ce9600f129fd1fea9850e1affaf31d5;p=postgresql.git

pgstat: set timestamps of fixed-numbered stats after a crash.

When not loading stats at startup (i.e. pgstat_discard_stats() getting
called), reset timestamps of fixed numbered stats would be left at
0. Oversight in 5891c7a8ed8.

Instead use pgstat_reset_after_failure() and add tests verifying that
fixed-numbered reset timestamps are set appropriately.

Reported-By: "David G. Johnston" <david.g.johnston@gmail.com>
Discussion: https://postgr.es/m/CAKFQuwamFuaQHKdhcMt4Gbw5+Hca2UE741B8gOOXoA=TtAd2Yw@mail.gmail.com
---

diff --git a/src/backend/utils/activity/pgstat.c b/src/backend/utils/activity/pgstat.c
index ea1cb8d1e3f..f658f8f1989 100644
--- a/src/backend/utils/activity/pgstat.c
+++ b/src/backend/utils/activity/pgstat.c
@@ -166,7 +166,7 @@ typedef struct PgStat_SnapshotEntry
 static void pgstat_write_statsfile(void);
 static void pgstat_read_statsfile(void);
 
-static void pgstat_reset_after_failure(TimestampTz ts);
+static void pgstat_reset_after_failure(void);
 
 static bool pgstat_flush_pending_entries(bool nowait);
 
@@ -427,6 +427,12 @@ pgstat_discard_stats(void)
 				 errmsg("unlinked permanent statistics file \"%s\"",
 						PGSTAT_STAT_PERMANENT_FILENAME)));
 	}
+
+	/*
+	 * Reset stats contents. This will set reset timestamps of fixed-numbered
+	 * stats to the current time (no variable stats exist).
+	 */
+	pgstat_reset_after_failure();
 }
 
 /*
@@ -1422,7 +1428,6 @@ pgstat_read_statsfile(void)
 	bool		found;
 	const char *statfile = PGSTAT_STAT_PERMANENT_FILENAME;
 	PgStat_ShmemControl *shmem = pgStatLocal.shmem;
-	TimestampTz ts = GetCurrentTimestamp();
 
 	/* shouldn't be called from postmaster */
 	Assert(IsUnderPostmaster || !IsPostmasterEnvironment);
@@ -1445,7 +1450,7 @@ pgstat_read_statsfile(void)
 					(errcode_for_file_access(),
 					 errmsg("could not open statistics file \"%s\": %m",
 							statfile)));
-		pgstat_reset_after_failure(ts);
+		pgstat_reset_after_failure();
 		return;
 	}
 
@@ -1597,19 +1602,20 @@ error:
 	ereport(LOG,
 			(errmsg("corrupted statistics file \"%s\"", statfile)));
 
-	/* Set the current timestamp as reset timestamp */
-	pgstat_reset_after_failure(ts);
+	pgstat_reset_after_failure();
 
 	goto done;
 }
 
 /*
- * Helper to reset / drop stats after restoring stats from disk failed,
- * potentially after already loading parts.
+ * Helper to reset / drop stats after a crash or after restoring stats from
+ * disk failed, potentially after already loading parts.
  */
 static void
-pgstat_reset_after_failure(TimestampTz ts)
+pgstat_reset_after_failure(void)
 {
+	TimestampTz ts = GetCurrentTimestamp();
+
 	/* reset fixed-numbered stats */
 	for (int kind = PGSTAT_KIND_FIRST_VALID; kind <= PGSTAT_KIND_LAST; kind++)
 	{
diff --git a/src/test/recovery/t/029_stats_restart.pl b/src/test/recovery/t/029_stats_restart.pl
index d3108127ef5..e0478f8af8d 100644
--- a/src/test/recovery/t/029_stats_restart.pl
+++ b/src/test/recovery/t/029_stats_restart.pl
@@ -250,6 +250,16 @@ cmp_ok(
 	$wal_restart2->{reset},
 	"$sect: newer stats_reset");
 
+$node->stop('immediate');
+$node->start;
+
+$sect = "post immediate restart";
+my $wal_restart_immediate = wal_stats();
+
+cmp_ok(
+	$wal_reset_restart->{reset}, 'lt',
+	$wal_restart_immediate->{reset},
+	"$sect: reset timestamp is new");
 
 $node->stop;
 done_testing();