You've already forked pg_probackup
mirror of
https://github.com/postgrespro/pg_probackup.git
synced 2025-07-16 07:14:15 +02:00
Fix history file parsing when fetched from archive
History file format has changed from 9.2 to 9.3 to indicate the WAL record when timeline branched off. In 9.2, the complete WAL file name was used while in 9.3 the WAL record is used (like 1/4000090). pg_rman contains a copy of a function of postgres core code to parse the history file that was not anymore compatible, leading to errors related to timelines.
This commit is contained in:
@ -306,7 +306,6 @@ extern int pgFileCompareMtimeDesc(const void *f1, const void *f2);
|
||||
|
||||
/* in xlog.c */
|
||||
extern bool xlog_is_complete_wal(const pgFile *file, int server_version);
|
||||
extern bool xlog_logfname2lsn(const char *logfname, XLogRecPtr *lsn);
|
||||
extern void xlog_fname(char *fname, size_t len, TimeLineID tli, XLogRecPtr *lsn);
|
||||
|
||||
/* in data.c */
|
||||
|
42
restore.c
42
restore.c
@ -768,27 +768,40 @@ readTimeLineHistory(TimeLineID targetTLI)
|
||||
*/
|
||||
while (fd && fgets(fline, sizeof(fline), fd) != NULL)
|
||||
{
|
||||
/* skip leading whitespaces and check for # comment */
|
||||
char *ptr;
|
||||
char *endptr;
|
||||
TimeLineID tli;
|
||||
uint32 switchpoint_hi;
|
||||
uint32 switchpoint_lo;
|
||||
int nfields;
|
||||
|
||||
for (ptr = fline; *ptr; ptr++)
|
||||
{
|
||||
if (!IsSpace(*ptr))
|
||||
if (!isspace((unsigned char) *ptr))
|
||||
break;
|
||||
}
|
||||
if (*ptr == '\0' || *ptr == '#')
|
||||
continue;
|
||||
|
||||
/* Parse one entry... */
|
||||
nfields = sscanf(fline, "%u\t%X/%X", &tli, &switchpoint_hi, &switchpoint_lo);
|
||||
|
||||
timeline = pgut_new(pgTimeLine);
|
||||
timeline->tli = 0;
|
||||
timeline->end = 0;
|
||||
|
||||
/* expect a numeric timeline ID as first field of line */
|
||||
timeline->tli = (TimeLineID) strtoul(ptr, &endptr, 0);
|
||||
if (endptr == ptr)
|
||||
timeline->tli = tli;
|
||||
|
||||
if (nfields < 1)
|
||||
{
|
||||
/* expect a numeric timeline ID as first field of line */
|
||||
elog(ERROR_CORRUPTED,
|
||||
_("syntax error(timeline ID) in history file: %s"),
|
||||
_("syntax error in history file: %s. Expected a numeric timeline ID."),
|
||||
fline);
|
||||
}
|
||||
if (nfields != 3)
|
||||
elog(ERROR_CORRUPTED,
|
||||
_("syntax error in history file: %s. Expected a transaction log switchpoint location."),
|
||||
fline);
|
||||
|
||||
if (last_timeline && timeline->tli <= last_timeline->tli)
|
||||
@ -799,20 +812,9 @@ readTimeLineHistory(TimeLineID targetTLI)
|
||||
parray_insert(result, 0, timeline);
|
||||
last_timeline = timeline;
|
||||
|
||||
/* parse end point(logfname, xid) in the timeline */
|
||||
for (ptr = endptr; *ptr; ptr++)
|
||||
{
|
||||
if (!IsSpace(*ptr))
|
||||
break;
|
||||
}
|
||||
if (*ptr == '\0' || *ptr == '#')
|
||||
elog(ERROR_CORRUPTED,
|
||||
_("End logfile must follow Timeline ID."));
|
||||
|
||||
if (!xlog_logfname2lsn(ptr, &timeline->end))
|
||||
elog(ERROR_CORRUPTED,
|
||||
_("syntax error(endfname) in history file: %s"), fline);
|
||||
/* we ignore the remainder of each line */
|
||||
/* Calculate the end lsn finally */
|
||||
timeline->end = (XLogRecPtr)
|
||||
((uint64) switchpoint_hi << 32) | switchpoint_lo;
|
||||
}
|
||||
|
||||
if (fd)
|
||||
|
18
xlog.c
18
xlog.c
@ -109,24 +109,6 @@ xlog_is_complete_wal(const pgFile *file, int server_version)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
xlog_logfname2lsn(const char *logfname, XLogRecPtr *lsn)
|
||||
{
|
||||
uint32 tli;
|
||||
uint32 xlogid;
|
||||
uint32 xrecoff;
|
||||
|
||||
if (sscanf(logfname, "%08X%08X%08X",
|
||||
&tli, &xlogid, &xrecoff) != 3)
|
||||
return false;
|
||||
|
||||
xrecoff *= XLogSegSize;
|
||||
|
||||
/* Finish calculation of LSN */
|
||||
*lsn = (XLogRecPtr) ((uint64) xlogid << 32) | xrecoff;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* based on XLogFileName() in xlog_internal.h
|
||||
*/
|
||||
|
Reference in New Issue
Block a user