From 29c3daacd8032e25e671422648cf4afc839a9c76 Mon Sep 17 00:00:00 2001 From: Bharath Rupireddy Date: Sun, 28 Nov 2021 06:27:05 +0000 Subject: [PATCH v5] pg_waldump: emit stats when interrupted with SIGINT Currently, pg_waldump doesn't display WAL statistics if it gets interrupted/terminated with SIGINT before reaching the end of WAL although it accumulates statistics as of termination. This behavior makes --stats with --follow option to appear as blocking or hang even though the statistics are computed in the background by the pg_waldump. This patch traps the SIGINT signal and prints the accumulated statistics as of the termination. --- doc/src/sgml/ref/pg_waldump.sgml | 9 +++++++++ src/bin/pg_waldump/pg_waldump.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/doc/src/sgml/ref/pg_waldump.sgml b/doc/src/sgml/ref/pg_waldump.sgml index 432254d2d5..1a48288041 100644 --- a/doc/src/sgml/ref/pg_waldump.sgml +++ b/doc/src/sgml/ref/pg_waldump.sgml @@ -202,6 +202,15 @@ PostgreSQL documentation full-page images) instead of individual records. Optionally generate statistics per-record instead of per-rmgr. + + + If the pg_waldump is terminated or + interrupted with signal SIGINT while + calculating the statistics, the summary statistics computed as + of the termination will be displayed in non-quiet mode or without + . + + diff --git a/src/bin/pg_waldump/pg_waldump.c b/src/bin/pg_waldump/pg_waldump.c index 4690e0f515..699b7d567b 100644 --- a/src/bin/pg_waldump/pg_waldump.c +++ b/src/bin/pg_waldump/pg_waldump.c @@ -13,6 +13,7 @@ #include "postgres.h" #include +#include #include #include @@ -28,6 +29,7 @@ static const char *progname; static int WalSegSz; +static volatile sig_atomic_t time_to_stop = false; typedef struct XLogDumpPrivate { @@ -67,12 +69,20 @@ typedef struct Stats typedef struct XLogDumpStats { uint64 count; + XLogRecPtr startptr; + XLogRecPtr endptr; Stats rmgr_stats[RM_NEXT_ID]; Stats record_stats[RM_NEXT_ID][MAX_XLINFO_TYPES]; } XLogDumpStats; #define fatal_error(...) do { pg_log_fatal(__VA_ARGS__); exit(EXIT_FAILURE); } while(0) +static void +sigint_handler(int signum) +{ + time_to_stop = true; +} + static void print_rmgr_list(void) { @@ -645,6 +655,9 @@ XLogDumpDisplayStats(XLogDumpConfig *config, XLogDumpStats *stats) } total_len = total_rec_len + total_fpi_len; + printf("Summary of the WAL statistics computed between LSN %X/%X and LSN %X/%X is:\n", + LSN_FORMAT_ARGS(stats->startptr), LSN_FORMAT_ARGS(stats->endptr)); + /* * 27 is strlen("Transaction/COMMIT_PREPARED"), 20 is strlen(2^64), 8 is * strlen("(100.00%)") @@ -794,6 +807,8 @@ main(int argc, char **argv) int option; int optindex = 0; + pqsignal(SIGINT, sigint_handler); + pg_logging_init(argv[0]); set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_waldump")); progname = get_progname(argv[0]); @@ -833,6 +848,9 @@ main(int argc, char **argv) config.stats = false; config.stats_per_record = false; + stats.startptr = InvalidXLogRecPtr; + stats.endptr = InvalidXLogRecPtr; + if (argc <= 1) { pg_log_error("no arguments specified"); @@ -1084,8 +1102,14 @@ main(int argc, char **argv) LSN_FORMAT_ARGS(first_record), (uint32) (first_record - private.startptr)); + if (config.stats == true && !config.quiet) + stats.startptr = first_record; + for (;;) { + if (time_to_stop) + break; + /* try to read the next record */ record = XLogReadRecord(xlogreader_state, &errormsg); if (!record) @@ -1112,7 +1136,10 @@ main(int argc, char **argv) if (!config.quiet) { if (config.stats == true) + { XLogDumpCountRecord(&config, &stats, xlogreader_state); + stats.endptr = xlogreader_state->EndRecPtr; + } else XLogDumpDisplayRecord(&config, xlogreader_state); } @@ -1127,6 +1154,9 @@ main(int argc, char **argv) if (config.stats == true && !config.quiet) XLogDumpDisplayStats(&config, &stats); + if (time_to_stop) + return EXIT_FAILURE; + if (errormsg) fatal_error("error in WAL record at %X/%X: %s", LSN_FORMAT_ARGS(xlogreader_state->ReadRecPtr), -- 2.25.1