@@ -32,6 +32,7 @@ typedef struct XLogDumpPrivate
3232char * inpath ;
3333XLogRecPtr startptr ;
3434XLogRecPtr endptr ;
35+ bool endptr_reached ;
3536}XLogDumpPrivate ;
3637
3738typedef struct XLogDumpConfig
@@ -40,6 +41,7 @@ typedef struct XLogDumpConfig
4041bool bkp_details ;
4142int stop_after_records ;
4243int already_displayed_records ;
44+ bool follow ;
4345
4446/* filter options */
4547int filter_by_rmgr ;
@@ -308,7 +310,10 @@ XLogDumpReadPage(XLogReaderState *state, XLogRecPtr targetPagePtr, int reqLen,
308310else if (targetPagePtr + reqLen <=private -> endptr )
309311count = private -> endptr - targetPagePtr ;
310312else
313+ {
314+ private -> endptr_reached = true;
311315return -1 ;
316+ }
312317}
313318
314319XLogDumpXLogRead (private -> inpath ,private -> timeline ,targetPagePtr ,
@@ -386,6 +391,7 @@ usage(void)
386391printf ("\nOptions:\n" );
387392printf (" -b, --bkp-details output detailed information about backup blocks\n" );
388393printf (" -e, --end=RECPTR stop reading at log position RECPTR\n" );
394+ printf (" -f, --follow keep retrying after reaching end of WAL\n" );
389395printf (" -n, --limit=N number of records to display\n" );
390396printf (" -p, --path=PATH directory in which to find log segment files\n" );
391397printf (" (default: ./pg_xlog)\n" );
@@ -414,6 +420,7 @@ main(int argc, char **argv)
414420static 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)
436443private .timeline = 1 ;
437444private .startptr = InvalidXLogRecPtr ;
438445private .endptr = InvalidXLogRecPtr ;
446+ private .endptr_reached = false;
439447
440448config .bkp_details = false;
441449config .stop_after_records = -1 ;
442450config .already_displayed_records = 0 ;
451+ config .follow = false;
443452config .filter_by_rmgr = -1 ;
444453config .filter_by_xid = InvalidTransactionId ;
445454config .filter_by_xid_enabled = false;
@@ -450,7 +459,7 @@ main(int argc, char **argv)
450459gotobad_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:" ,
454463long_options ,& optindex ))!= -1 )
455464{
456465switch (option )
@@ -467,6 +476,9 @@ main(int argc, char **argv)
467476}
468477private .endptr = (uint64 )xlogid <<32 |xrecoff ;
469478break ;
479+ case 'f' :
480+ config .follow = true;
481+ break ;
470482case '?' :
471483usage ();
472484exit (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 */
689714first_record = InvalidXLogRecPtr ;
690715XLogDumpDisplayRecord (& config ,xlogreader_state -> ReadRecPtr ,record );
691716