Skip to content

Commit 1c87d61

Browse files
committed
Check target LSN. Archived WAL segment should contain it.
1 parent eaccb46 commit 1c87d61

File tree

4 files changed

+73
-7
lines changed

4 files changed

+73
-7
lines changed

backup.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ do_backup_database(parray *backup_list)
239239

240240
if (ptrack_lsn > prev_backup->stop_lsn)
241241
{
242-
elog(ERROR, "lsn from ptrack_control %lx differs from lsn of previous ptrack backup %lx.\n"
242+
elog(ERROR, "LSN from ptrack_control %lx differs from LSN of previous ptrack backup %lx.\n"
243243
"Create new full backup before an incremental one.",
244244
ptrack_lsn, prev_backup->start_lsn);
245245
}
@@ -714,7 +714,8 @@ pg_ptrack_get_and_clear(Oid tablespace_oid, Oid db_oid, Oid rel_oid,
714714
}
715715

716716
/*
717-
* TODO Add comment
717+
* Wait for target 'lsn' to be archived in archive 'wal' directory with
718+
* WAL segment file.
718719
*/
719720
static void
720721
wait_archive_lsn(XLogRecPtr lsn, bool prev_segno)
@@ -729,7 +730,7 @@ wait_archive_lsn(XLogRecPtr lsn, bool prev_segno)
729730

730731
tli = get_current_timeline(false);
731732

732-
/* Compute the name of the WAL file containig requested lsn */
733+
/* Compute the name of the WAL file containig requested LSN */
733734
XLByteToSeg(lsn, targetSegNo);
734735
if (prev_segno)
735736
targetSegNo--;
@@ -747,14 +748,22 @@ wait_archive_lsn(XLogRecPtr lsn, bool prev_segno)
747748

748749
/* Inform user if WAL segment is absent in first attempt */
749750
if (try_count == 1)
750-
elog(INFO, "wait for lsn %X/%X in archived WAL segment %s",
751+
elog(INFO, "wait for LSN %X/%X in archived WAL segment %s",
751752
(uint32) (lsn >> 32), (uint32) lsn, wal_path);
752753

753754
if (archive_timeout > 0 && try_count > archive_timeout)
754755
elog(ERROR,
755756
"switched WAL segment %s could not be archived in %d seconds",
756757
wal_file, archive_timeout);
757758
}
759+
760+
/*
761+
* WAL segment was archived. Check LSN on it if we waited current WAL
762+
* segment, not previous.
763+
*/
764+
if (!prev_segno && !wal_contains_lsn(arclog_path, lsn, tli))
765+
elog(ERROR, "WAL segment %s doesn't contain target LSN %X/%X",
766+
wal_file, (uint32) (lsn >> 32), (uint32) lsn);
758767
}
759768

760769
/*

parsexlog.c

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ read_recovery_info(const char *archivedir, TimeLineID tli,
303303
XLogRecPtr startpoint = stop_lsn;
304304
XLogReaderState *xlogreader;
305305
XLogPageReadPrivate private;
306+
bool res;
306307

307308
private.archivedir = archivedir;
308309
private.tli = tli;
@@ -342,12 +343,66 @@ read_recovery_info(const char *archivedir, TimeLineID tli,
342343
*recovery_time = timestamptz_to_time_t(last_time);
343344
*recovery_xid = XLogRecGetXid(xlogreader);
344345

345-
return true;
346+
/* Found timestamp in WAL record 'record' */
347+
res = true;
348+
goto cleanup;
346349
}
347350
} while (startpoint >= start_lsn);
348351

349352
/* Didn't find timestamp from WAL records between start_lsn and stop_lsn */
350-
return false;
353+
res = false;
354+
355+
cleanup:
356+
XLogReaderFree(xlogreader);
357+
if (xlogreadfd != -1)
358+
{
359+
close(xlogreadfd);
360+
xlogreadfd = -1;
361+
xlogexists = false;
362+
}
363+
364+
return res;
365+
}
366+
367+
/*
368+
* Check if WAL segment file 'wal_path' contains 'target_lsn'.
369+
*/
370+
bool
371+
wal_contains_lsn(const char *archivedir, XLogRecPtr target_lsn,
372+
TimeLineID target_tli)
373+
{
374+
XLogReaderState *xlogreader;
375+
XLogPageReadPrivate private;
376+
char *errormsg;
377+
bool res;
378+
379+
private.archivedir = archivedir;
380+
private.tli = target_tli;
381+
382+
xlogreader = XLogReaderAllocate(&SimpleXLogPageRead, &private);
383+
if (xlogreader == NULL)
384+
elog(ERROR, "out of memory");
385+
386+
res = XLogReadRecord(xlogreader, target_lsn, &errormsg) != NULL;
387+
if (!res)
388+
{
389+
if (errormsg)
390+
elog(ERROR, "could not read WAL record at %X/%X: %s",
391+
(uint32) (target_lsn >> 32), (uint32) (target_lsn),
392+
errormsg);
393+
394+
/* Didn't find 'target_lsn' and there is no error, return false */
395+
}
396+
397+
XLogReaderFree(xlogreader);
398+
if (xlogreadfd != -1)
399+
{
400+
close(xlogreadfd);
401+
xlogreadfd = -1;
402+
xlogexists = false;
403+
}
404+
405+
return res;
351406
}
352407

353408
/* XLogreader callback function, to read a WAL page */

pg_probackup.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,8 @@ extern bool read_recovery_info(const char *archivedir, TimeLineID tli,
368368
XLogRecPtr start_lsn, XLogRecPtr stop_lsn,
369369
time_t *recovery_time,
370370
TransactionId *recovery_xid);
371+
extern bool wal_contains_lsn(const char *archivedir, XLogRecPtr target_lsn,
372+
TimeLineID target_tli);
371373

372374
/* in util.c */
373375
extern TimeLineID get_current_timeline(bool safe);

restore.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,7 @@ readTimeLineHistory_probackup(TimeLineID targetTLI)
790790
/* append target timeline */
791791
entry = pgut_new(TimeLineHistoryEntry);
792792
entry->tli = targetTLI;
793-
/* lsn in target timeline is valid */
793+
/* LSN in target timeline is valid */
794794
entry->end = (uint32) (-1UL << 32) | -1UL;
795795
parray_insert(result, 0, entry);
796796

0 commit comments

Comments
 (0)