@@ -32,6 +32,7 @@ typedef struct XLogDumpPrivate
32
32
char * inpath ;
33
33
XLogRecPtr startptr ;
34
34
XLogRecPtr endptr ;
35
+ bool endptr_reached ;
35
36
} XLogDumpPrivate ;
36
37
37
38
typedef struct XLogDumpConfig
@@ -40,6 +41,7 @@ typedef struct XLogDumpConfig
40
41
bool bkp_details ;
41
42
int stop_after_records ;
42
43
int already_displayed_records ;
44
+ bool follow ;
43
45
44
46
/* filter options */
45
47
int filter_by_rmgr ;
@@ -308,7 +310,10 @@ XLogDumpReadPage(XLogReaderState *state, XLogRecPtr targetPagePtr, int reqLen,
308
310
else if (targetPagePtr + reqLen <= private -> endptr )
309
311
count = private -> endptr - targetPagePtr ;
310
312
else
313
+ {
314
+ private -> endptr_reached = true;
311
315
return -1 ;
316
+ }
312
317
}
313
318
314
319
XLogDumpXLogRead (private -> inpath , private -> timeline , targetPagePtr ,
@@ -386,6 +391,7 @@ usage(void)
386
391
printf ("\nOptions:\n" );
387
392
printf (" -b, --bkp-details output detailed information about backup blocks\n" );
388
393
printf (" -e, --end=RECPTR stop reading at log position RECPTR\n" );
394
+ printf (" -f, --follow keep retrying after reaching end of WAL\n" );
389
395
printf (" -n, --limit=N number of records to display\n" );
390
396
printf (" -p, --path=PATH directory in which to find log segment files\n" );
391
397
printf (" (default: ./pg_xlog)\n" );
@@ -414,6 +420,7 @@ main(int argc, char **argv)
414
420
static struct option long_options [] = {
415
421
{"bkp-details" , no_argument , NULL , 'b' },
416
422
{"end" , required_argument , NULL , 'e' },
423
+ {"follow" , no_argument , NULL , 'f' },
417
424
{"help" , no_argument , NULL , '?' },
418
425
{"limit" , required_argument , NULL , 'n' },
419
426
{"path" , required_argument , NULL , 'p' },
@@ -436,10 +443,12 @@ main(int argc, char **argv)
436
443
private .timeline = 1 ;
437
444
private .startptr = InvalidXLogRecPtr ;
438
445
private .endptr = InvalidXLogRecPtr ;
446
+ private .endptr_reached = false;
439
447
440
448
config .bkp_details = false;
441
449
config .stop_after_records = -1 ;
442
450
config .already_displayed_records = 0 ;
451
+ config .follow = false;
443
452
config .filter_by_rmgr = -1 ;
444
453
config .filter_by_xid = InvalidTransactionId ;
445
454
config .filter_by_xid_enabled = false;
@@ -450,7 +459,7 @@ main(int argc, char **argv)
450
459
goto bad_argument ;
451
460
}
452
461
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:" ,
454
463
long_options , & optindex )) != -1 )
455
464
{
456
465
switch (option )
@@ -467,6 +476,9 @@ main(int argc, char **argv)
467
476
}
468
477
private .endptr = (uint64 ) xlogid << 32 | xrecoff ;
469
478
break ;
479
+ case 'f' :
480
+ config .follow = true;
481
+ break ;
470
482
case '?' :
471
483
usage ();
472
484
exit (EXIT_SUCCESS );
@@ -683,9 +695,22 @@ main(int argc, char **argv)
683
695
(uint32 ) (first_record >> 32 ), (uint32 ) first_record ,
684
696
(uint32 ) (first_record - private .startptr ));
685
697
686
- while (( record = XLogReadRecord ( xlogreader_state , first_record , & errormsg )) )
698
+ for (;; )
687
699
{
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 */
689
714
first_record = InvalidXLogRecPtr ;
690
715
XLogDumpDisplayRecord (& config , xlogreader_state -> ReadRecPtr , record );
691
716
0 commit comments