diff options
-rw-r--r-- | src/backend/access/transam/xlog.c | 37 | ||||
-rw-r--r-- | src/include/access/xlog_internal.h | 12 |
2 files changed, 30 insertions, 19 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 5c3ca479fb..aa0b0291ee 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -3728,23 +3728,32 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt) RecPtr = &tmpRecPtr; /* - * Align recptr to next page if no more records can fit on the current - * page. + * RecPtr is pointing to end+1 of the previous WAL record. We must + * advance it if necessary to where the next record starts. First, + * align to next page if no more records can fit on the current page. */ if (XLOG_BLCKSZ - (RecPtr->xrecoff % XLOG_BLCKSZ) < SizeOfXLogRecord) - { - NextLogPage(tmpRecPtr); - /* We will account for page header size below */ - } + NextLogPage(*RecPtr); - if (tmpRecPtr.xrecoff >= XLogFileSize) + /* Check for crossing of xlog segment boundary */ + if (RecPtr->xrecoff >= XLogFileSize) { - (tmpRecPtr.xlogid)++; - tmpRecPtr.xrecoff = 0; + (RecPtr->xlogid)++; + RecPtr->xrecoff = 0; } + + /* + * If at page start, we must skip over the page header. But we can't + * do that until we've read in the page, since the header size is + * variable. + */ } else { + /* + * In this case, the passed-in record pointer should already be + * pointing to a valid record starting position. + */ if (!XRecOffIsValid(RecPtr->xrecoff)) ereport(PANIC, (errmsg("invalid record offset at %X/%X", @@ -3773,11 +3782,13 @@ retry: if (targetRecOff == 0) { /* - * Can only get here in the continuing-from-prev-page case, because - * XRecOffIsValid eliminated the zero-page-offset case otherwise. Need - * to skip over the new page's header. + * At page start, so skip over page header. The Assert checks that + * we're not scribbling on caller's record pointer; it's OK because we + * can only get here in the continuing-from-prev-record case, since + * XRecOffIsValid rejected the zero-page-offset case otherwise. */ - tmpRecPtr.xrecoff += pageHeaderSize; + Assert(RecPtr == &tmpRecPtr); + RecPtr->xrecoff += pageHeaderSize; targetRecOff = pageHeaderSize; } else if (targetRecOff < pageHeaderSize) diff --git a/src/include/access/xlog_internal.h b/src/include/access/xlog_internal.h index eeccdce31d..7e39630c1b 100644 --- a/src/include/access/xlog_internal.h +++ b/src/include/access/xlog_internal.h @@ -154,13 +154,13 @@ typedef XLogLongPageHeaderData *XLogLongPageHeader; /* Align a record pointer to next page */ #define NextLogPage(recptr) \ do { \ - if (recptr.xrecoff % XLOG_BLCKSZ != 0) \ - recptr.xrecoff += \ - (XLOG_BLCKSZ - recptr.xrecoff % XLOG_BLCKSZ); \ - if (recptr.xrecoff >= XLogFileSize) \ + if ((recptr).xrecoff % XLOG_BLCKSZ != 0) \ + (recptr).xrecoff += \ + (XLOG_BLCKSZ - (recptr).xrecoff % XLOG_BLCKSZ); \ + if ((recptr).xrecoff >= XLogFileSize) \ { \ - (recptr.xlogid)++; \ - recptr.xrecoff = 0; \ + ((recptr).xlogid)++; \ + (recptr).xrecoff = 0; \ } \ } while (0) |