@@ -32,6 +32,7 @@ typedef struct XLogDumpPrivate
3232 char * inpath ;
3333 XLogRecPtr startptr ;
3434 XLogRecPtr endptr ;
35+ bool endptr_reached ;
3536} XLogDumpPrivate ;
3637
3738typedef struct XLogDumpConfig
@@ -40,6 +41,7 @@ typedef struct XLogDumpConfig
4041 bool bkp_details ;
4142 int stop_after_records ;
4243 int already_displayed_records ;
44+ bool follow ;
4345
4446 /* filter options */
4547 int filter_by_rmgr ;
@@ -308,7 +310,10 @@ XLogDumpReadPage(XLogReaderState *state, XLogRecPtr targetPagePtr, int reqLen,
308310 else if (targetPagePtr + reqLen <= private -> endptr )
309311 count = private -> endptr - targetPagePtr ;
310312 else
313+ {
314+ private -> endptr_reached = true;
311315 return -1 ;
316+ }
312317 }
313318
314319 XLogDumpXLogRead (private -> inpath , private -> timeline , targetPagePtr ,
@@ -386,6 +391,7 @@ usage(void)
386391 printf ("\nOptions:\n" );
387392 printf (" -b, --bkp-details output detailed information about backup blocks\n" );
388393 printf (" -e, --end=RECPTR stop reading at log position RECPTR\n" );
394+ printf (" -f, --follow keep retrying after reaching end of WAL\n" );
389395 printf (" -n, --limit=N number of records to display\n" );
390396 printf (" -p, --path=PATH directory in which to find log segment files\n" );
391397 printf (" (default: ./pg_xlog)\n" );
@@ -414,6 +420,7 @@ main(int argc, char **argv)
414420 static struct option long_options [] = {
415421 {"bkp-details" , no_argument , NULL , 'b' },
416422 {"end" , required_argument , NULL , 'e' },
423+ {"follow" , no_argument , NULL , 'f' },
417424 {"help" , no_argument , NULL , '?' },
418425 {"limit" , required_argument , NULL , 'n' },
419426 {"path" , required_argument , NULL , 'p' },
@@ -436,10 +443,12 @@ main(int argc, char **argv)
436443 private .timeline = 1 ;
437444 private .startptr = InvalidXLogRecPtr ;
438445 private .endptr = InvalidXLogRecPtr ;
446+ private .endptr_reached = false;
439447
440448 config .bkp_details = false;
441449 config .stop_after_records = -1 ;
442450 config .already_displayed_records = 0 ;
451+ config .follow = false;
443452 config .filter_by_rmgr = -1 ;
444453 config .filter_by_xid = InvalidTransactionId ;
445454 config .filter_by_xid_enabled = false;
@@ -450,7 +459,7 @@ main(int argc, char **argv)
450459 goto bad_argument ;
451460 }
452461
453- while ((option = getopt_long (argc , argv , "be:?n :p:r:s:t:Vx:" ,
462+ while ((option = getopt_long (argc , argv , "be:?fn :p:r:s:t:Vx:" ,
454463 long_options , & optindex )) != -1 )
455464 {
456465 switch (option )
@@ -467,6 +476,9 @@ main(int argc, char **argv)
467476 }
468477 private .endptr = (uint64 ) xlogid << 32 | xrecoff ;
469478 break ;
479+ case 'f' :
480+ config .follow = true;
481+ break ;
470482 case '?' :
471483 usage ();
472484 exit (EXIT_SUCCESS );
@@ -683,9 +695,22 @@ main(int argc, char **argv)
683695 (uint32 ) (first_record >> 32 ), (uint32 ) first_record ,
684696 (uint32 ) (first_record - private .startptr ));
685697
686- while (( record = XLogReadRecord ( xlogreader_state , first_record , & errormsg )) )
698+ for (;; )
687699 {
688- /* continue after the last record */
700+ /* try to read the next record */
701+ record = XLogReadRecord (xlogreader_state , first_record , & errormsg );
702+ if (!record )
703+ {
704+ if (!config .follow || private .endptr_reached )
705+ break ;
706+ else
707+ {
708+ sleep (1 );
709+ continue ;
710+ }
711+ }
712+
713+ /* after reading the first record, continue at next one */
689714 first_record = InvalidXLogRecPtr ;
690715 XLogDumpDisplayRecord (& config , xlogreader_state -> ReadRecPtr , record );
691716
0 commit comments