detailed error message of pg_waldump - Mailing list pgsql-hackers
From | Kyotaro Horiguchi |
---|---|
Subject | detailed error message of pg_waldump |
Date | |
Msg-id | 20210604.173533.349866689278295774.horikyota.ntt@gmail.com Whole thread Raw |
Responses |
Re: detailed error message of pg_waldump
|
List | pgsql-hackers |
In a very common operation of accidentally specifying a recycled segment, pg_waldump often returns the following obscure message. $ pg_waldump 00000001000000000000002D pg_waldump: fatal: could not find a valid record after 0/2D000000 The more detailed message is generated internally and we can use it. That looks like the following. $ pg_waldump 00000001000000000000002D pg_waldump: fatal: unexpected pageaddr 0/24000000 in log segment 00000001000000000000002D, offset 0 Is it work doing? regards. -- Kyotaro Horiguchi NTT Open Source Software Center diff --git a/src/backend/access/transam/xlogreader.c b/src/backend/access/transam/xlogreader.c index 42738eb940..5a98c523c6 100644 --- a/src/backend/access/transam/xlogreader.c +++ b/src/backend/access/transam/xlogreader.c @@ -932,17 +932,28 @@ XLogReaderValidatePageHeader(XLogReaderState *state, XLogRecPtr recptr, * * This positions the reader, like XLogBeginRead(), so that the next call to * XLogReadRecord() will read the next valid record. + * + * If the page_read callback fails to read the requested data, + * InvalidXLogRecPtr is returned. The callback is expected to have reported + * the error; errormsg is set to NULL. + * + * If the reading fails for some other reason, InvalidXLogRecPtr is also + * returned, and *errormsg is set to a string with details of the failure. + * + * The returned pointer (or *errormsg) points to an internal buffer that's + * valid until the next call to XLogFindNextRecord or XLogReadRecord. */ XLogRecPtr -XLogFindNextRecord(XLogReaderState *state, XLogRecPtr RecPtr) +XLogFindNextRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg) { XLogRecPtr tmpRecPtr; XLogRecPtr found = InvalidXLogRecPtr; XLogPageHeader header; - char *errormsg; Assert(!XLogRecPtrIsInvalid(RecPtr)); + *errormsg = NULL; + /* * skip over potential continuation data, keeping in mind that it may span * multiple pages @@ -1021,7 +1032,7 @@ XLogFindNextRecord(XLogReaderState *state, XLogRecPtr RecPtr) * or we just jumped over the remaining data of a continuation. */ XLogBeginRead(state, tmpRecPtr); - while (XLogReadRecord(state, &errormsg) != NULL) + while (XLogReadRecord(state, errormsg) != NULL) { /* past the record we've found, break out */ if (RecPtr <= state->ReadRecPtr) @@ -1036,6 +1047,9 @@ XLogFindNextRecord(XLogReaderState *state, XLogRecPtr RecPtr) err: XLogReaderInvalReadState(state); + if (state->errormsg_buf[0] != '\0') + *errormsg = state->errormsg_buf; + return InvalidXLogRecPtr; } diff --git a/src/bin/pg_waldump/pg_waldump.c b/src/bin/pg_waldump/pg_waldump.c index f8b8afe4a7..d3dbccf22c 100644 --- a/src/bin/pg_waldump/pg_waldump.c +++ b/src/bin/pg_waldump/pg_waldump.c @@ -1051,11 +1051,17 @@ main(int argc, char **argv) fatal_error("out of memory"); /* first find a valid recptr to start from */ - first_record = XLogFindNextRecord(xlogreader_state, private.startptr); + first_record = XLogFindNextRecord(xlogreader_state, private.startptr, + &errormsg); if (first_record == InvalidXLogRecPtr) - fatal_error("could not find a valid record after %X/%X", - LSN_FORMAT_ARGS(private.startptr)); + { + if (errormsg) + fatal_error("%s", errormsg); + else + fatal_error("could not find a valid record after %X/%X", + LSN_FORMAT_ARGS(private.startptr)); + } /* * Display a message that we're skipping data if `from` wasn't a pointer diff --git a/src/include/access/xlogreader.h b/src/include/access/xlogreader.h index 21d200d3df..0f6d920fed 100644 --- a/src/include/access/xlogreader.h +++ b/src/include/access/xlogreader.h @@ -267,7 +267,8 @@ extern void XLogReaderFree(XLogReaderState *state); /* Position the XLogReader to given record */ extern void XLogBeginRead(XLogReaderState *state, XLogRecPtr RecPtr); #ifdef FRONTEND -extern XLogRecPtr XLogFindNextRecord(XLogReaderState *state, XLogRecPtr RecPtr); +extern XLogRecPtr XLogFindNextRecord(XLogReaderState *state, XLogRecPtr RecPtr, + char **errormsg); #endif /* FRONTEND */ /* Read the next XLog record. Returns NULL on end-of-WAL or failure */
pgsql-hackers by date: