v2-0002-Add-TAP-test-for-discarding-stats-after-crash.patch

text/x-patch

Filename: v2-0002-Add-TAP-test-for-discarding-stats-after-crash.patch
Type: text/x-patch
Part: 1
Message: Re: shared-memory based stats collector - v66

Patch

Format: format-patch
Series: patch v2-0002
Subject: Add TAP test for discarding stats after crash
File+
src/test/recovery/t/030_stats_cleanup_crash.pl 184 0
From 5761e7436ea0df8ef6f56011a20085fb52c832b1 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sun, 20 Mar 2022 16:33:40 -0400
Subject: [PATCH v2 2/2] Add TAP test for discarding stats after crash

Stats should not be restored if the db crashed. Also, ensure invalid
stats files are handled gracefully.
---
 .../recovery/t/030_stats_cleanup_crash.pl     | 184 ++++++++++++++++++
 1 file changed, 184 insertions(+)
 create mode 100644 src/test/recovery/t/030_stats_cleanup_crash.pl

diff --git a/src/test/recovery/t/030_stats_cleanup_crash.pl b/src/test/recovery/t/030_stats_cleanup_crash.pl
new file mode 100644
index 0000000000..dde3eaf04c
--- /dev/null
+++ b/src/test/recovery/t/030_stats_cleanup_crash.pl
@@ -0,0 +1,184 @@
+# Copyright (c) 2021-2022, PostgreSQL Global Development Group
+
+# Tests that statistics are discarded after a crash and that invalid stats
+# files are handled gracefully.
+
+use strict;
+use warnings;
+use PostgreSQL::Test::Cluster;
+use PostgreSQL::Test::Utils;
+use Test::More;
+use File::Copy;
+
+my $node = PostgreSQL::Test::Cluster->new('primary');
+$node->init(allows_streaming => 1);
+$node->start;
+$node->append_conf('postgresql.conf', "track_functions = 'all'");
+$node->reload;
+
+my $connect_db = 'postgres';
+my $db_under_test = 'test';
+
+$node->safe_psql($connect_db,
+	"CREATE DATABASE $db_under_test");
+
+# Create table in test db
+$node->safe_psql($db_under_test,
+	"CREATE TABLE tab_stats_crash_discard_test1 AS SELECT generate_series(1,100) AS a");
+
+# Create function in test db
+$node->safe_psql($db_under_test,
+	"CREATE FUNCTION func_stats_crash_discard1() RETURNS VOID AS 'select 2;' LANGUAGE SQL IMMUTABLE");
+
+# Get database oid
+my $dboid = $node->safe_psql($db_under_test,
+	"SELECT oid FROM pg_database WHERE datname = '$db_under_test'");
+
+# Get function oid
+my $funcoid = $node->safe_psql($db_under_test,
+	"SELECT 'func_stats_crash_discard1()'::regprocedure::oid");
+
+# Get table oid
+my $tableoid = $node->safe_psql($db_under_test,
+	"SELECT 'tab_stats_crash_discard_test1'::regclass::oid");
+
+# Do scan
+$node->safe_psql($db_under_test,
+	"SELECT * FROM tab_stats_crash_discard_test1");
+
+# Call function
+$node->safe_psql($db_under_test,
+	"SELECT func_stats_crash_discard1()");
+
+# Force flush of stats
+$node->safe_psql($db_under_test,
+	"SELECT pg_stat_force_next_flush()");
+
+is($node->safe_psql($connect_db,
+	"SELECT pg_stat_stats_exist($dboid, $dboid, 'db')"), 't',
+	"Check that db stats exist.");
+
+is($node->safe_psql($connect_db,
+	"SELECT pg_stat_stats_exist($dboid, $funcoid, 'function')"), 't',
+	"Check that function stats exist.");
+
+is($node->safe_psql($connect_db,
+	"SELECT pg_stat_stats_exist($dboid, $tableoid, 'table')"), 't',
+	"Check that table stats exist.");
+
+# Regular shutdown
+$node->stop();
+
+# Backup stats files
+my $statsfile = $PostgreSQL::Test::Utils::tmp_check . '/' . "discard_stats1";
+ok( !-f "$statsfile",
+	"Backup statsfile cannot already exist");
+
+my $datadir = $node->data_dir();
+my $og_stats = $datadir . '/' . "pg_stat" . '/' . "pgstat.stat";
+ok( -f "$og_stats",
+	"Origin stats file must exist");
+copy($og_stats, $statsfile) or die "Copy failed: $!";
+
+# Start the server
+$node->start;
+
+is($node->safe_psql($connect_db,
+	"SELECT pg_stat_stats_exist($dboid, $dboid, 'db')"), 't',
+	"Check that db stats exist.");
+
+is($node->safe_psql($connect_db,
+	"SELECT pg_stat_stats_exist($dboid, $funcoid, 'function')"), 't',
+	"Check that function stats exist.");
+
+is($node->safe_psql($connect_db,
+	"SELECT pg_stat_stats_exist($dboid, $tableoid, 'table')"), 't',
+	"Check that table stats exist.");
+
+# Fast shutdown
+$node->stop('immediate');
+
+ok( !-f "$og_stats",
+	"No stats file should exist after immediate shutdown.");
+
+# Copy the old stats back
+copy($statsfile, $og_stats) or die "Copy failed: $!";
+
+# Start the server
+$node->start;
+
+# Stats should have been discarded
+is($node->safe_psql($connect_db,
+	"SELECT pg_stat_stats_exist($dboid, $dboid, 'db')"), 'f',
+	"Check that db stats do not exist.");
+
+is($node->safe_psql($connect_db,
+	"SELECT pg_stat_stats_exist($dboid, $tableoid, 'table')"), 'f',
+	"Check that table stats do not exist.");
+
+is($node->safe_psql($connect_db,
+	"SELECT pg_stat_stats_exist($dboid, $funcoid, 'function')"), 'f',
+	"Check that function stats do not exist.");
+
+# Get rid of backup statsfile
+unlink $statsfile or die "cannot unlink $statsfile $!";
+
+# Start generating new stats
+
+# Do scan
+$node->safe_psql($db_under_test,
+	"SELECT * FROM tab_stats_crash_discard_test1");
+
+# Call function
+$node->safe_psql($db_under_test,
+	"SELECT func_stats_crash_discard1()");
+
+# Force flush of stats
+$node->safe_psql($db_under_test,
+	"SELECT pg_stat_force_next_flush()");
+
+is($node->safe_psql($connect_db,
+	"SELECT pg_stat_stats_exist($dboid, $dboid, 'db')"), 't',
+	"Check that db stats exist.");
+
+is($node->safe_psql($connect_db,
+	"SELECT pg_stat_stats_exist($dboid, $funcoid, 'function')"), 't',
+	"Check that function stats exist.");
+
+is($node->safe_psql($connect_db,
+	"SELECT pg_stat_stats_exist($dboid, $tableoid, 'table')"), 't',
+	"Check that table stats exist.");
+
+# Regular shutdown
+$node->stop();
+
+sub overwrite_file
+{
+	my $fh;
+	my ($filename, $str) = @_;
+	open my $fh, ">", $filename
+	  or die "could not write \"$filename\": $!";
+	print $fh $str;
+	close $fh;
+	return;
+}
+
+overwrite_file($og_stats,  "ZZZZZZZZZZZZZ");
+
+# Normal startup and no issues despite invalid stats file
+$node->start;
+
+# No stats present due to invalid stats file
+is($node->safe_psql($connect_db,
+	"SELECT pg_stat_stats_exist($dboid, $dboid, 'db')"), 'f',
+	"Check that db stats do not exist.");
+
+is($node->safe_psql($connect_db,
+	"SELECT pg_stat_stats_exist($dboid, $tableoid, 'table')"), 'f',
+	"Check that table stats do not exist.");
+
+is($node->safe_psql($connect_db,
+	"SELECT pg_stat_stats_exist($dboid, $funcoid, 'function')"), 'f',
+	"Check that function stats do not exist.");
+
+done_testing();
-- 
2.30.2