Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 88228e6

Browse files
committed
When xlogreader asks the callback function to read a page, make sure we
get a large enough part of the page to include the beginning of the next record we're interested in. The XLogPageRead callback uses the requested length to decide which timeline to stream WAL from, and if the first call is short, and the page contains a timeline switch, we'll repeatedly try to stream that page from the old timeline, and never get across the timeline switch.
1 parent 3684a53 commit 88228e6

File tree

1 file changed

+12
-18
lines changed

1 file changed

+12
-18
lines changed

src/backend/access/transam/xlogreader.c

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ allocate_recordbuf(XLogReaderState *state, uint32 reclength)
164164
* If RecPtr is not NULL, try to read a record at that position. Otherwise
165165
* try to read a record just after the last one previously read.
166166
*
167-
* If the page_read callback fails to read the requested data, NULL is
167+
* If the read_page callback fails to read the requested data, NULL is
168168
* returned. The callback is expected to have reported the error; errormsg
169169
* is set to NULL.
170170
*
@@ -217,10 +217,16 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
217217
}
218218

219219
targetPagePtr = RecPtr - (RecPtr % XLOG_BLCKSZ);
220+
targetRecOff = RecPtr % XLOG_BLCKSZ;
220221

221-
/* Read the page containing the record into state->readBuf */
222-
readOff = ReadPageInternal(state, targetPagePtr, SizeOfXLogRecord);
223-
222+
/*
223+
* Read the page containing the record into state->readBuf. Request
224+
* enough byte to cover the whole record header, or at least the part of
225+
* it that fits on the same page.
226+
*/
227+
readOff = ReadPageInternal(state,
228+
targetPagePtr,
229+
Min(targetRecOff + SizeOfXLogRecord, XLOG_BLCKSZ));
224230
if (readOff < 0)
225231
goto err;
226232

@@ -229,7 +235,6 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
229235
* examine it now.
230236
*/
231237
pageHeaderSize = XLogPageHeaderSize((XLogPageHeader) state->readBuf);
232-
targetRecOff = RecPtr % XLOG_BLCKSZ;
233238
if (targetRecOff == 0)
234239
{
235240
/*
@@ -256,16 +261,6 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
256261
/* ReadPageInternal has verified the page header */
257262
Assert(pageHeaderSize <= readOff);
258263

259-
/*
260-
* Ensure the whole record header or at least the part on this page is
261-
* read.
262-
*/
263-
readOff = ReadPageInternal(state,
264-
targetPagePtr,
265-
Min(targetRecOff + SizeOfXLogRecord, XLOG_BLCKSZ));
266-
if (readOff < 0)
267-
goto err;
268-
269264
/*
270265
* Read the record length.
271266
*
@@ -463,7 +458,7 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
463458
}
464459

465460
/*
466-
* Read a single xlog page including at least [pagestart, RecPtr] of valid data
461+
* Read a single xlog page including at least [pageptr, reqLen] of valid data
467462
* via the read_page() callback.
468463
*
469464
* Returns -1 if the required page cannot be read for some reason; errormsg_buf
@@ -502,8 +497,7 @@ ReadPageInternal(XLogReaderState *state, XLogRecPtr pageptr, int reqLen)
502497
* record is. This is so that we can check the additional identification
503498
* info that is present in the first page's "long" header.
504499
*/
505-
if (targetSegNo != state->readSegNo &&
506-
targetPageOff != 0)
500+
if (targetSegNo != state->readSegNo && targetPageOff != 0)
507501
{
508502
XLogPageHeader hdr;
509503
XLogRecPtr targetSegmentPtr = pageptr - targetPageOff;

0 commit comments

Comments
 (0)