From 2a9bbeb0dd8cab27738e31e20c2c3f4ca735e988 Mon Sep 17 00:00:00 2001 From: Bharath Rupireddy Date: Sat, 20 Nov 2021 06:14:58 +0000 Subject: [PATCH v3] pg_waldump: emit stats while terminating Currently, pg_waldump keeps accumulating the stats with options --follow and --stats, but outputs nothing while terminating/exiting. This patch adds signal handlers for SIGINT, SIGTERM and SIGQUIT to display the stats computed as of the termination. --- doc/src/sgml/ref/pg_waldump.sgml | 9 +++++++++ src/bin/pg_waldump/pg_waldump.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/doc/src/sgml/ref/pg_waldump.sgml b/doc/src/sgml/ref/pg_waldump.sgml index 432254d2d5..cf75d1dd21 100644 --- a/doc/src/sgml/ref/pg_waldump.sgml +++ b/doc/src/sgml/ref/pg_waldump.sgml @@ -261,6 +261,15 @@ PostgreSQL documentation .partial. If those files need to be read, .partial suffix needs to be removed from the file name. + + + When is used with and + the pg_waldump is terminated or interrupted + with signal SIGINT or SIGTERM + or SIGQUIT, the summary statistics computed + as of the termination will be displayed. + + diff --git a/src/bin/pg_waldump/pg_waldump.c b/src/bin/pg_waldump/pg_waldump.c index 1e3894b9c4..a3d80feda0 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 TerminationRequestPending = 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 +SignalHandlerForTermination(int signum) +{ + TerminationRequestPending = 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,10 @@ main(int argc, char **argv) int option; int optindex = 0; + pqsignal(SIGINT, SignalHandlerForTermination); + pqsignal(SIGTERM, SignalHandlerForTermination); + pqsignal(SIGQUIT, SignalHandlerForTermination); + pg_logging_init(argv[0]); set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_waldump")); progname = get_progname(argv[0]); @@ -833,6 +850,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 +1104,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 (TerminationRequestPending) + break; + /* try to read the next record */ record = XLogReadRecord(xlogreader_state, &errormsg); if (!record) @@ -1112,7 +1138,10 @@ main(int argc, char **argv) if (!config.quiet) { if (config.stats == true) + { XLogDumpCountRecord(&config, &stats, xlogreader_state); + stats.endptr = xlogreader_state->currRecPtr; + } else XLogDumpDisplayRecord(&config, xlogreader_state); } @@ -1127,6 +1156,9 @@ main(int argc, char **argv) if (config.stats == true && !config.quiet) XLogDumpDisplayStats(&config, &stats); + if (TerminationRequestPending) + return EXIT_FAILURE; + if (errormsg) fatal_error("error in WAL record at %X/%X: %s", LSN_FORMAT_ARGS(xlogreader_state->ReadRecPtr), -- 2.25.1