From ce9bb92f8fb8d25cf00ec939797ffdb5930fb792 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Wed, 26 Mar 2014 13:48:20 +0200 Subject: [PATCH] Add -f/--follow option to pg_xlogdump. This is useful for seeing what WAL records are inserted in real-time, by pointing pg_xlogdump to a live server. --- contrib/pg_xlogdump/pg_xlogdump.c | 31 ++++++++++++++++++++++++++++--- doc/src/sgml/pg_xlogdump.sgml | 11 +++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/contrib/pg_xlogdump/pg_xlogdump.c b/contrib/pg_xlogdump/pg_xlogdump.c index 024ab01efa..e947696429 100644 --- a/contrib/pg_xlogdump/pg_xlogdump.c +++ b/contrib/pg_xlogdump/pg_xlogdump.c @@ -32,6 +32,7 @@ typedef struct XLogDumpPrivate char *inpath; XLogRecPtr startptr; XLogRecPtr endptr; + bool endptr_reached; } XLogDumpPrivate; typedef struct XLogDumpConfig @@ -40,6 +41,7 @@ typedef struct XLogDumpConfig bool bkp_details; int stop_after_records; int already_displayed_records; + bool follow; /* filter options */ int filter_by_rmgr; @@ -308,7 +310,10 @@ XLogDumpReadPage(XLogReaderState *state, XLogRecPtr targetPagePtr, int reqLen, else if (targetPagePtr + reqLen <= private->endptr) count = private->endptr - targetPagePtr; else + { + private->endptr_reached = true; return -1; + } } XLogDumpXLogRead(private->inpath, private->timeline, targetPagePtr, @@ -386,6 +391,7 @@ usage(void) printf("\nOptions:\n"); printf(" -b, --bkp-details output detailed information about backup blocks\n"); printf(" -e, --end=RECPTR stop reading at log position RECPTR\n"); + printf(" -f, --follow keep retrying after reaching end of WAL\n"); printf(" -n, --limit=N number of records to display\n"); printf(" -p, --path=PATH directory in which to find log segment files\n"); printf(" (default: ./pg_xlog)\n"); @@ -414,6 +420,7 @@ main(int argc, char **argv) static struct option long_options[] = { {"bkp-details", no_argument, NULL, 'b'}, {"end", required_argument, NULL, 'e'}, + {"follow", no_argument, NULL, 'f'}, {"help", no_argument, NULL, '?'}, {"limit", required_argument, NULL, 'n'}, {"path", required_argument, NULL, 'p'}, @@ -436,10 +443,12 @@ main(int argc, char **argv) private.timeline = 1; private.startptr = InvalidXLogRecPtr; private.endptr = InvalidXLogRecPtr; + private.endptr_reached = false; config.bkp_details = false; config.stop_after_records = -1; config.already_displayed_records = 0; + config.follow = false; config.filter_by_rmgr = -1; config.filter_by_xid = InvalidTransactionId; config.filter_by_xid_enabled = false; @@ -450,7 +459,7 @@ main(int argc, char **argv) goto bad_argument; } - while ((option = getopt_long(argc, argv, "be:?n:p:r:s:t:Vx:", + while ((option = getopt_long(argc, argv, "be:?fn:p:r:s:t:Vx:", long_options, &optindex)) != -1) { switch (option) @@ -467,6 +476,9 @@ main(int argc, char **argv) } private.endptr = (uint64) xlogid << 32 | xrecoff; break; + case 'f': + config.follow = true; + break; case '?': usage(); exit(EXIT_SUCCESS); @@ -683,9 +695,22 @@ main(int argc, char **argv) (uint32) (first_record >> 32), (uint32) first_record, (uint32) (first_record - private.startptr)); - while ((record = XLogReadRecord(xlogreader_state, first_record, &errormsg))) + for (;;) { - /* continue after the last record */ + /* try to read the next record */ + record = XLogReadRecord(xlogreader_state, first_record, &errormsg); + if (!record) + { + if (!config.follow || private.endptr_reached) + break; + else + { + sleep(1); + continue; + } + } + + /* after reading the first record, continue at next one */ first_record = InvalidXLogRecPtr; XLogDumpDisplayRecord(&config, xlogreader_state->ReadRecPtr, record); diff --git a/doc/src/sgml/pg_xlogdump.sgml b/doc/src/sgml/pg_xlogdump.sgml index 1739622119..1d1a2cea87 100644 --- a/doc/src/sgml/pg_xlogdump.sgml +++ b/doc/src/sgml/pg_xlogdump.sgml @@ -91,6 +91,17 @@ PostgreSQL documentation + + + + + + After reaching the end of valid WAL, keep polling once per second for + new WAL to appear. + + + +