Skip to content

Commit 6ea7c61

Browse files
committed
PGPRO-2180: Retreive stop_lsn from previous WAL segment
1 parent d84d796 commit 6ea7c61

File tree

3 files changed

+142
-9
lines changed

3 files changed

+142
-9
lines changed

src/backup.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1907,7 +1907,28 @@ pg_stop_backup(pgBackup *backup)
19071907
if (!XRecOffIsValid(stop_backup_lsn))
19081908
{
19091909
if (XRecOffIsNull(stop_backup_lsn))
1910-
stop_backup_lsn = stop_backup_lsn + SizeOfXLogLongPHD;
1910+
{
1911+
char *xlog_path,
1912+
stream_xlog_path[MAXPGPATH];
1913+
XLogSegNo segno;
1914+
1915+
if (stream_wal)
1916+
{
1917+
pgBackupGetPath2(backup, stream_xlog_path,
1918+
lengthof(stream_xlog_path),
1919+
DATABASE_DIR, PG_XLOG_DIR);
1920+
xlog_path = stream_xlog_path;
1921+
}
1922+
else
1923+
xlog_path = arclog_path;
1924+
1925+
GetXLogSegNo(stop_backup_lsn, segno, xlog_seg_size);
1926+
/* Retreive stop_lsn from previous segment */
1927+
segno = segno - 1;
1928+
stop_backup_lsn = get_last_wal_lsn(xlog_path, backup->start_lsn,
1929+
segno, backup->tli,
1930+
xlog_seg_size);
1931+
}
19111932
else
19121933
elog(ERROR, "Invalid stop_backup_lsn value %X/%X",
19131934
(uint32) (stop_backup_lsn >> 32), (uint32) (stop_backup_lsn));

src/parsexlog.c

Lines changed: 117 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ static bool getRecordTimestamp(XLogReaderState *record, TimestampTz *recordXtime
8888

8989
typedef struct XLogPageReadPrivate
9090
{
91-
int thread_num;
91+
int thread_num;
9292
const char *archivedir;
9393
TimeLineID tli;
9494
uint32 xlog_seg_size;
@@ -132,8 +132,7 @@ static XLogReaderState *InitXLogPageRead(XLogPageReadPrivate *private_data,
132132
TimeLineID tli, uint32 xlog_seg_size,
133133
bool allocate_reader);
134134
static void CleanupXLogPageRead(XLogReaderState *xlogreader);
135-
static void PrintXLogCorruptionMsg(XLogPageReadPrivate *private_data,
136-
int elevel);
135+
static void PrintXLogCorruptionMsg(XLogPageReadPrivate *private_data, int elevel);
137136

138137
static XLogSegNo nextSegNoToRead = 0;
139138
static pthread_mutex_t wal_segment_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -239,11 +238,17 @@ doExtractPageMap(void *arg)
239238
*/
240239
if (XLogRecPtrIsInvalid(found))
241240
{
242-
elog(WARNING, "Thread [%d]: could not read WAL record at %X/%X. %s",
243-
private_data->thread_num,
244-
(uint32) (extract_arg->startpoint >> 32),
245-
(uint32) (extract_arg->startpoint),
246-
(xlogreader->errormsg_buf[0] != '\0')?xlogreader->errormsg_buf:"");
241+
if (xlogreader->errormsg_buf[0] != '\0')
242+
elog(WARNING, "Thread [%d]: could not read WAL record at %X/%X: %s",
243+
private_data->thread_num,
244+
(uint32) (extract_arg->startpoint >> 32),
245+
(uint32) (extract_arg->startpoint),
246+
xlogreader->errormsg_buf);
247+
else
248+
elog(WARNING, "Thread [%d]: could not read WAL record at %X/%X",
249+
private_data->thread_num,
250+
(uint32) (extract_arg->startpoint >> 32),
251+
(uint32) (extract_arg->startpoint));
247252
PrintXLogCorruptionMsg(private_data, ERROR);
248253
}
249254
extract_arg->startpoint = found;
@@ -766,6 +771,104 @@ wal_contains_lsn(const char *archivedir, XLogRecPtr target_lsn,
766771
return res;
767772
}
768773

774+
/*
775+
* Get last valid LSN within the WAL segment with number 'segno'. If 'start_lsn'
776+
* is in the segment with number 'segno' then start from 'start_lsn', otherwise
777+
* start from offset 0 within the segment.
778+
*/
779+
XLogRecPtr
780+
get_last_wal_lsn(const char *archivedir, XLogRecPtr start_lsn,
781+
XLogSegNo segno, TimeLineID tli, uint32 seg_size)
782+
{
783+
XLogReaderState *xlogreader;
784+
XLogPageReadPrivate private;
785+
XLogRecPtr startpoint;
786+
XLogSegNo start_segno;
787+
XLogRecPtr res = InvalidXLogRecPtr;
788+
789+
if (segno == 0)
790+
elog(ERROR, "Invalid WAL segment number " UINT64_FORMAT, segno);
791+
792+
elog(LOG, "Retreiving last LSN of the segment with number " UINT64_FORMAT,
793+
segno);
794+
795+
xlogreader = InitXLogPageRead(&private, archivedir, tli, seg_size, true);
796+
797+
/*
798+
* Calculate startpoint. Decide: we should use 'start_lsn' or offset 0.
799+
*/
800+
GetXLogSegNo(start_lsn, start_segno, seg_size);
801+
if (start_segno == segno)
802+
startpoint = start_lsn;
803+
else
804+
{
805+
XLogRecPtr found;
806+
807+
GetXLogRecPtr(segno, 0, seg_size, startpoint);
808+
found = XLogFindNextRecord(xlogreader, startpoint);
809+
810+
if (XLogRecPtrIsInvalid(found))
811+
{
812+
if (xlogreader->errormsg_buf[0] != '\0')
813+
elog(WARNING, "Could not read WAL record at %X/%X: %s",
814+
(uint32) (startpoint >> 32), (uint32) (startpoint),
815+
xlogreader->errormsg_buf);
816+
else
817+
elog(WARNING, "Could not read WAL record at %X/%X",
818+
(uint32) (startpoint >> 32), (uint32) (startpoint));
819+
PrintXLogCorruptionMsg(&private, ERROR);
820+
}
821+
startpoint = found;
822+
}
823+
824+
elog(VERBOSE, "Starting LSN is %X/%X",
825+
(uint32) (startpoint >> 32), (uint32) (startpoint));
826+
827+
while (true)
828+
{
829+
XLogRecord *record;
830+
char *errormsg;
831+
XLogSegNo next_segno = 0;
832+
833+
if (interrupted)
834+
elog(ERROR, "Interrupted during WAL reading");
835+
836+
record = XLogReadRecord(xlogreader, startpoint, &errormsg);
837+
if (record == NULL)
838+
{
839+
XLogRecPtr errptr;
840+
841+
errptr = XLogRecPtrIsInvalid(startpoint) ? xlogreader->EndRecPtr :
842+
startpoint;
843+
844+
if (errormsg)
845+
elog(WARNING, "Could not read WAL record at %X/%X: %s",
846+
(uint32) (errptr >> 32), (uint32) (errptr),
847+
errormsg);
848+
else
849+
elog(WARNING, "Could not read WAL record at %X/%X",
850+
(uint32) (errptr >> 32), (uint32) (errptr));
851+
PrintXLogCorruptionMsg(&private, ERROR);
852+
}
853+
854+
res = xlogreader->ReadRecPtr;
855+
856+
/* continue reading at next record */
857+
startpoint = InvalidXLogRecPtr;
858+
859+
GetXLogSegNo(xlogreader->EndRecPtr, next_segno, seg_size);
860+
if (next_segno > segno)
861+
break;
862+
}
863+
864+
CleanupXLogPageRead(xlogreader);
865+
XLogReaderFree(xlogreader);
866+
867+
elog(VERBOSE, "Last LSN is %X/%X", (uint32) (res >> 32), (uint32) (res));
868+
869+
return res;
870+
}
871+
769872
#ifdef HAVE_LIBZ
770873
/*
771874
* Show error during work with compressed file
@@ -1035,6 +1138,12 @@ PrintXLogCorruptionMsg(XLogPageReadPrivate *private_data, int elevel)
10351138
private_data->gz_xlogpath);
10361139
#endif
10371140
}
1141+
else
1142+
{
1143+
/* Cannot tell what happened specifically */
1144+
elog(elevel, "Thread [%d]: An error occured during WAL reading",
1145+
private_data->thread_num);
1146+
}
10381147
}
10391148

10401149
/*

src/pg_probackup.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,9 @@ extern bool read_recovery_info(const char *archivedir, TimeLineID tli,
576576
TransactionId *recovery_xid);
577577
extern bool wal_contains_lsn(const char *archivedir, XLogRecPtr target_lsn,
578578
TimeLineID target_tli, uint32 seg_size);
579+
extern XLogRecPtr get_last_wal_lsn(const char *archivedir, XLogRecPtr start_lsn,
580+
XLogSegNo segno, TimeLineID tli,
581+
uint32 seg_size);
579582

580583
/* in util.c */
581584
extern TimeLineID get_current_timeline(bool safe);

0 commit comments

Comments
 (0)