agora inbox for pgsql-hackers@postgresql.org
help / color / mirror / Atom feedFrom: Kyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Subject: [PATCH 1/2] Allow switch WAL source midst of record.
Date: Thu, 7 Sep 2017 12:14:55 +0900
The corrent recovery machinary assumes the whole of a record is
avaiable from single source. This prevents a standby from restarting
under a certain condition. This patch allows source switching during
reading a series of continuation records.
---
src/backend/access/transam/xlog.c | 14 ++++++++++++--
src/backend/access/transam/xlogreader.c | 28 ++++++++++++++++++----------
src/include/access/xlogreader.h | 4 ++++
3 files changed, 34 insertions(+), 12 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index dd028a1..0d639ec 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -11647,6 +11647,10 @@ retry:
Assert(reqLen <= readLen);
*readTLI = curFileTLI;
+
+ if (!XLogReaderValidatePageHeader(xlogreader, targetPagePtr, readBuf))
+ goto next_record_is_invalid;
+
return readLen;
next_record_is_invalid:
@@ -11781,12 +11785,18 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
}
else
{
- ptr = tliRecPtr;
+ /*
+ * Trying from the current RecPtr, not from the
+ * beginning of the current record. The record may
+ * be no longer available from the master.
+ */
+ ptr = RecPtr;
tli = tliOfPointInHistory(tliRecPtr, expectedTLEs);
if (curFileTLI > 0 && tli < curFileTLI)
elog(ERROR, "according to history file, WAL location %X/%X belongs to timeline %u, but previous recovered WAL file came from timeline %u",
- (uint32) (ptr >> 32), (uint32) ptr,
+ (uint32) (tliRecPtr >> 32),
+ (uint32) tliRecPtr,
tli, curFileTLI);
}
curFileTLI = tli;
diff --git a/src/backend/access/transam/xlogreader.c b/src/backend/access/transam/xlogreader.c
index b1f9b90..78a721a 100644
--- a/src/backend/access/transam/xlogreader.c
+++ b/src/backend/access/transam/xlogreader.c
@@ -27,8 +27,6 @@
static bool allocate_recordbuf(XLogReaderState *state, uint32 reclength);
-static bool ValidXLogPageHeader(XLogReaderState *state, XLogRecPtr recptr,
- XLogPageHeader hdr);
static bool ValidXLogRecordHeader(XLogReaderState *state, XLogRecPtr RecPtr,
XLogRecPtr PrevRecPtr, XLogRecord *record, bool randAccess);
static bool ValidXLogRecord(XLogReaderState *state, XLogRecord *record,
@@ -533,7 +531,6 @@ ReadPageInternal(XLogReaderState *state, XLogRecPtr pageptr, int reqLen)
*/
if (targetSegNo != state->readSegNo && targetPageOff != 0)
{
- XLogPageHeader hdr;
XLogRecPtr targetSegmentPtr = pageptr - targetPageOff;
readLen = state->read_page(state, targetSegmentPtr, XLOG_BLCKSZ,
@@ -545,9 +542,8 @@ ReadPageInternal(XLogReaderState *state, XLogRecPtr pageptr, int reqLen)
/* we can be sure to have enough WAL available, we scrolled back */
Assert(readLen == XLOG_BLCKSZ);
- hdr = (XLogPageHeader) state->readBuf;
-
- if (!ValidXLogPageHeader(state, targetSegmentPtr, hdr))
+ if (!XLogReaderValidatePageHeader(state, targetSegmentPtr,
+ state->readBuf))
goto err;
}
@@ -584,7 +580,7 @@ ReadPageInternal(XLogReaderState *state, XLogRecPtr pageptr, int reqLen)
/*
* Now that we know we have the full header, validate it.
*/
- if (!ValidXLogPageHeader(state, pageptr, hdr))
+ if (!XLogReaderValidatePageHeader(state, pageptr, (char *) hdr))
goto err;
/* update read state information */
@@ -710,14 +706,26 @@ ValidXLogRecord(XLogReaderState *state, XLogRecord *record, XLogRecPtr recptr)
/*
* Validate a page header
+ *
+ * Check if phdr is valid as the XLog page header of the XLog page of the page
+ * pointed by recptr.
+ *
+ * phdr is read as XLogPageHeaderData and check if it has valid magic, has no
+ * usused flag bits set and belongs to correct page pointed by recptr. The
+ * incorrect page address is detected usually when we read a page in a
+ * recycled segment.
+ *
+ * If it is the first page in a segment or detected rewind of state,
+ * additional checks are performed.
*/
-static bool
-ValidXLogPageHeader(XLogReaderState *state, XLogRecPtr recptr,
- XLogPageHeader hdr)
+bool
+XLogReaderValidatePageHeader(XLogReaderState *state, XLogRecPtr recptr,
+ char *phdr)
{
XLogRecPtr recaddr;
XLogSegNo segno;
int32 offset;
+ XLogPageHeader hdr = (XLogPageHeader) phdr;
Assert((recptr % XLOG_BLCKSZ) == 0);
diff --git a/src/include/access/xlogreader.h b/src/include/access/xlogreader.h
index 3a9ebd4..758d880 100644
--- a/src/include/access/xlogreader.h
+++ b/src/include/access/xlogreader.h
@@ -205,6 +205,10 @@ extern void XLogReaderFree(XLogReaderState *state);
extern struct XLogRecord *XLogReadRecord(XLogReaderState *state,
XLogRecPtr recptr, char **errormsg);
+/* Validate a page */
+extern bool XLogReaderValidatePageHeader(XLogReaderState *state,
+ XLogRecPtr recptr, char *phdr);
+
/* Invalidate read state */
extern void XLogReaderInvalReadState(XLogReaderState *state);
--
2.9.2
----Next_Part(Thu_Oct_26_19_05_51_2017_936)--
Content-Type: text/plain
Content-Disposition: inline
Content-Transfer-Encoding: 8bit
MIME-Version: 1.0
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
----Next_Part(Thu_Oct_26_19_05_51_2017_936)----
view thread (8+ messages) latest in thread
Message-ID: <no-message-id-775200@localhost>
Permalink: ../../no-message-id-775200@localhost/
Also on: postgresql.org/message-id/no-message-id-775200@localhost
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-hackers@postgresql.org
Cc: horiguchi.kyotaro@lab.ntt.co.jp
Subject: Re: [PATCH 1/2] Allow switch WAL source midst of record.
In-Reply-To: <no-message-id-775200@localhost>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox