Skip to content

Commit bab7823

Browse files
committed
Fix pg_xlogdump so that it handles cross-page XLP_FIRST_IS_CONTRECORD record.
Previously pg_xlogdump failed to dump the contents of the WAL file if the file starts with the continuation WAL record which spans more than one pages. Since pg_xlogdump assumed that the continuation record always fits on a page, it could not find the valid WAL record to start reading from in that case. This patch changes pg_xlogdump so that it can handle a continuation WAL record which crosses a page boundary and find the valid record to start reading from. Back-patch to 9.3 where pg_xlogdump was introduced. Author: Pavan Deolasee Reviewed-By: Michael Paquier and Craig Ringer Discussion: CABOikdPsPByMiG6J01DKq6om2+BNkxHTPkOyqHM2a4oYwGKsqQ@mail.gmail.com
1 parent b899ccb commit bab7823

File tree

1 file changed

+64
-27
lines changed

1 file changed

+64
-27
lines changed

src/backend/access/transam/xlogreader.c

Lines changed: 64 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -866,46 +866,83 @@ XLogRecPtr
866866
XLogFindNextRecord(XLogReaderState *state, XLogRecPtr RecPtr)
867867
{
868868
XLogReaderState saved_state = *state;
869-
XLogRecPtr targetPagePtr;
870869
XLogRecPtr tmpRecPtr;
871-
int targetRecOff;
872870
XLogRecPtr found = InvalidXLogRecPtr;
873-
uint32 pageHeaderSize;
874871
XLogPageHeader header;
875-
int readLen;
876872
char *errormsg;
877873

878874
Assert(!XLogRecPtrIsInvalid(RecPtr));
879875

880-
targetRecOff = RecPtr % XLOG_BLCKSZ;
876+
/*
877+
* skip over potential continuation data, keeping in mind that it may span
878+
* multiple pages
879+
*/
880+
tmpRecPtr = RecPtr;
881+
while (true)
882+
{
883+
XLogRecPtr targetPagePtr;
884+
int targetRecOff;
885+
uint32 pageHeaderSize;
886+
int readLen;
881887

882-
/* scroll back to page boundary */
883-
targetPagePtr = RecPtr - targetRecOff;
888+
/*
889+
* Compute targetRecOff. It should typically be equal or greater than
890+
* short page-header since a valid record can't start anywhere before
891+
* that, except when caller has explicitly specified the offset that
892+
* falls somewhere there or when we are skipping multi-page
893+
* continuation record. It doesn't matter though because
894+
* ReadPageInternal() is prepared to handle that and will read at least
895+
* short page-header worth of data
896+
*/
897+
targetRecOff = tmpRecPtr % XLOG_BLCKSZ;
884898

885-
/* Read the page containing the record */
886-
readLen = ReadPageInternal(state, targetPagePtr, targetRecOff);
887-
if (readLen < 0)
888-
goto err;
899+
/* scroll back to page boundary */
900+
targetPagePtr = tmpRecPtr - targetRecOff;
889901

890-
header = (XLogPageHeader) state->readBuf;
902+
/* Read the page containing the record */
903+
readLen = ReadPageInternal(state, targetPagePtr, targetRecOff);
904+
if (readLen < 0)
905+
goto err;
891906

892-
pageHeaderSize = XLogPageHeaderSize(header);
907+
header = (XLogPageHeader) state->readBuf;
893908

894-
/* make sure we have enough data for the page header */
895-
readLen = ReadPageInternal(state, targetPagePtr, pageHeaderSize);
896-
if (readLen < 0)
897-
goto err;
909+
pageHeaderSize = XLogPageHeaderSize(header);
898910

899-
/* skip over potential continuation data */
900-
if (header->xlp_info & XLP_FIRST_IS_CONTRECORD)
901-
{
902-
/* record headers are MAXALIGN'ed */
903-
tmpRecPtr = targetPagePtr + pageHeaderSize
904-
+ MAXALIGN(header->xlp_rem_len);
905-
}
906-
else
907-
{
908-
tmpRecPtr = targetPagePtr + pageHeaderSize;
911+
/* make sure we have enough data for the page header */
912+
readLen = ReadPageInternal(state, targetPagePtr, pageHeaderSize);
913+
if (readLen < 0)
914+
goto err;
915+
916+
/* skip over potential continuation data */
917+
if (header->xlp_info & XLP_FIRST_IS_CONTRECORD)
918+
{
919+
/*
920+
* If the length of the remaining continuation data is more than
921+
* what can fit in this page, the continuation record crosses over
922+
* this page. Read the next page and try again. xlp_rem_len in the
923+
* next page header will contain the remaining length of the
924+
* continuation data
925+
*
926+
* Note that record headers are MAXALIGN'ed
927+
*/
928+
if (MAXALIGN(header->xlp_rem_len) > (XLOG_BLCKSZ - pageHeaderSize))
929+
tmpRecPtr = targetPagePtr + XLOG_BLCKSZ;
930+
else
931+
{
932+
/*
933+
* The previous continuation record ends in this page. Set
934+
* tmpRecPtr to point to the first valid record
935+
*/
936+
tmpRecPtr = targetPagePtr + pageHeaderSize
937+
+ MAXALIGN(header->xlp_rem_len);
938+
break;
939+
}
940+
}
941+
else
942+
{
943+
tmpRecPtr = targetPagePtr + pageHeaderSize;
944+
break;
945+
}
909946
}
910947

911948
/*

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy