Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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

+64-27
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)