summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/access/transam/xlog.c37
-rw-r--r--src/include/access/xlog_internal.h12
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)