aboutsummaryrefslogtreecommitdiff
path: root/src/bin/pg_rewind/parsexlog.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/pg_rewind/parsexlog.c')
-rw-r--r--src/bin/pg_rewind/parsexlog.c39
1 files changed, 27 insertions, 12 deletions
diff --git a/src/bin/pg_rewind/parsexlog.c b/src/bin/pg_rewind/parsexlog.c
index 2081cf8bd33..d69eafbcf3d 100644
--- a/src/bin/pg_rewind/parsexlog.c
+++ b/src/bin/pg_rewind/parsexlog.c
@@ -45,7 +45,7 @@ static char xlogfpath[MAXPGPATH];
typedef struct XLogPageReadPrivate
{
const char *datadir;
- TimeLineID tli;
+ int tliIndex;
} XLogPageReadPrivate;
static int SimpleXLogPageRead(XLogReaderState *xlogreader,
@@ -55,11 +55,11 @@ static int SimpleXLogPageRead(XLogReaderState *xlogreader,
/*
* Read WAL from the datadir/pg_xlog, starting from 'startpoint' on timeline
- * 'tli', until 'endpoint'. Make note of the data blocks touched by the WAL
- * records, and return them in a page map.
+ * index 'tliIndex' in target timeline history, until 'endpoint'. Make note of
+ * the data blocks touched by the WAL records, and return them in a page map.
*/
void
-extractPageMap(const char *datadir, XLogRecPtr startpoint, TimeLineID tli,
+extractPageMap(const char *datadir, XLogRecPtr startpoint, int tliIndex,
XLogRecPtr endpoint)
{
XLogRecord *record;
@@ -68,7 +68,7 @@ extractPageMap(const char *datadir, XLogRecPtr startpoint, TimeLineID tli,
XLogPageReadPrivate private;
private.datadir = datadir;
- private.tli = tli;
+ private.tliIndex = tliIndex;
xlogreader = XLogReaderAllocate(&SimpleXLogPageRead, &private);
if (xlogreader == NULL)
pg_fatal("out of memory\n");
@@ -112,7 +112,7 @@ extractPageMap(const char *datadir, XLogRecPtr startpoint, TimeLineID tli,
* doing anything with the record itself.
*/
XLogRecPtr
-readOneRecord(const char *datadir, XLogRecPtr ptr, TimeLineID tli)
+readOneRecord(const char *datadir, XLogRecPtr ptr, int tliIndex)
{
XLogRecord *record;
XLogReaderState *xlogreader;
@@ -121,7 +121,7 @@ readOneRecord(const char *datadir, XLogRecPtr ptr, TimeLineID tli)
XLogRecPtr endptr;
private.datadir = datadir;
- private.tli = tli;
+ private.tliIndex = tliIndex;
xlogreader = XLogReaderAllocate(&SimpleXLogPageRead, &private);
if (xlogreader == NULL)
pg_fatal("out of memory\n");
@@ -152,7 +152,7 @@ readOneRecord(const char *datadir, XLogRecPtr ptr, TimeLineID tli)
* Find the previous checkpoint preceding given WAL position.
*/
void
-findLastCheckpoint(const char *datadir, XLogRecPtr forkptr, TimeLineID tli,
+findLastCheckpoint(const char *datadir, XLogRecPtr forkptr, int tliIndex,
XLogRecPtr *lastchkptrec, TimeLineID *lastchkpttli,
XLogRecPtr *lastchkptredo)
{
@@ -173,7 +173,7 @@ findLastCheckpoint(const char *datadir, XLogRecPtr forkptr, TimeLineID tli,
forkptr += (forkptr % XLogSegSize == 0) ? SizeOfXLogLongPHD : SizeOfXLogShortPHD;
private.datadir = datadir;
- private.tli = tli;
+ private.tliIndex = tliIndex;
xlogreader = XLogReaderAllocate(&SimpleXLogPageRead, &private);
if (xlogreader == NULL)
pg_fatal("out of memory\n");
@@ -236,9 +236,11 @@ SimpleXLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr,
{
XLogPageReadPrivate *private = (XLogPageReadPrivate *) xlogreader->private_data;
uint32 targetPageOff;
- XLogSegNo targetSegNo PG_USED_FOR_ASSERTS_ONLY;
+ XLogRecPtr targetSegEnd;
+ XLogSegNo targetSegNo;
XLByteToSeg(targetPagePtr, targetSegNo);
+ XLogSegNoOffsetToRecPtr(targetSegNo + 1, 0, targetSegEnd);
targetPageOff = targetPagePtr % XLogSegSize;
/*
@@ -257,7 +259,20 @@ SimpleXLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr,
{
char xlogfname[MAXFNAMELEN];
- XLogFileName(xlogfname, private->tli, xlogreadsegno);
+ /*
+ * Since incomplete segments are copied into next timelines, switch to
+ * the timeline holding the required segment. Assuming this scan can be
+ * done both forward and backward, consider also switching timeline
+ * accordingly.
+ */
+ while (private->tliIndex < targetNentries - 1 &&
+ targetHistory[private->tliIndex].end < targetSegEnd)
+ private->tliIndex++;
+ while (private->tliIndex > 0 &&
+ targetHistory[private->tliIndex].begin >= targetSegEnd)
+ private->tliIndex--;
+
+ XLogFileName(xlogfname, targetHistory[private->tliIndex].tli, xlogreadsegno);
snprintf(xlogfpath, MAXPGPATH, "%s/" XLOGDIR "/%s", private->datadir, xlogfname);
@@ -293,7 +308,7 @@ SimpleXLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr,
Assert(targetSegNo == xlogreadsegno);
- *pageTLI = private->tli;
+ *pageTLI = targetHistory[private->tliIndex].tli;
return XLOG_BLCKSZ;
}