@@ -844,46 +844,83 @@ XLogRecPtr
844
844
XLogFindNextRecord (XLogReaderState * state ,XLogRecPtr RecPtr )
845
845
{
846
846
XLogReaderState saved_state = * state ;
847
- XLogRecPtr targetPagePtr ;
848
847
XLogRecPtr tmpRecPtr ;
849
- int targetRecOff ;
850
848
XLogRecPtr found = InvalidXLogRecPtr ;
851
- uint32 pageHeaderSize ;
852
849
XLogPageHeader header ;
853
- int readLen ;
854
850
char * errormsg ;
855
851
856
852
Assert (!XLogRecPtrIsInvalid (RecPtr ));
857
853
858
- targetRecOff = RecPtr %XLOG_BLCKSZ ;
854
+ /*
855
+ * skip over potential continuation data, keeping in mind that it may span
856
+ * multiple pages
857
+ */
858
+ tmpRecPtr = RecPtr ;
859
+ while (true)
860
+ {
861
+ XLogRecPtr targetPagePtr ;
862
+ int targetRecOff ;
863
+ uint32 pageHeaderSize ;
864
+ int readLen ;
859
865
860
- /* scroll back to page boundary */
861
- targetPagePtr = RecPtr - targetRecOff ;
866
+ /*
867
+ * Compute targetRecOff. It should typically be equal or greater than
868
+ * short page-header since a valid record can't start anywhere before
869
+ * that, except when caller has explicitly specified the offset that
870
+ * falls somewhere there or when we are skipping multi-page
871
+ * continuation record. It doesn't matter though because
872
+ * ReadPageInternal() is prepared to handle that and will read at least
873
+ * short page-header worth of data
874
+ */
875
+ targetRecOff = tmpRecPtr %XLOG_BLCKSZ ;
862
876
863
- /* Read the page containing the record */
864
- readLen = ReadPageInternal (state ,targetPagePtr ,targetRecOff );
865
- if (readLen < 0 )
866
- gotoerr ;
877
+ /* scroll back to page boundary */
878
+ targetPagePtr = tmpRecPtr - targetRecOff ;
867
879
868
- header = (XLogPageHeader )state -> readBuf ;
880
+ /* Read the page containing the record */
881
+ readLen = ReadPageInternal (state ,targetPagePtr ,targetRecOff );
882
+ if (readLen < 0 )
883
+ gotoerr ;
869
884
870
- pageHeaderSize = XLogPageHeaderSize ( header ) ;
885
+ header = ( XLogPageHeader ) state -> readBuf ;
871
886
872
- /* make sure we have enough data for the page header */
873
- readLen = ReadPageInternal (state ,targetPagePtr ,pageHeaderSize );
874
- if (readLen < 0 )
875
- gotoerr ;
887
+ pageHeaderSize = XLogPageHeaderSize (header );
876
888
877
- /* skip over potential continuation data */
878
- if (header -> xlp_info & XLP_FIRST_IS_CONTRECORD )
879
- {
880
- /* record headers are MAXALIGN'ed */
881
- tmpRecPtr = targetPagePtr + pageHeaderSize
882
- + MAXALIGN (header -> xlp_rem_len );
883
- }
884
- else
885
- {
886
- tmpRecPtr = targetPagePtr + pageHeaderSize ;
889
+ /* make sure we have enough data for the page header */
890
+ readLen = ReadPageInternal (state ,targetPagePtr ,pageHeaderSize );
891
+ if (readLen < 0 )
892
+ gotoerr ;
893
+
894
+ /* skip over potential continuation data */
895
+ if (header -> xlp_info & XLP_FIRST_IS_CONTRECORD )
896
+ {
897
+ /*
898
+ * If the length of the remaining continuation data is more than
899
+ * what can fit in this page, the continuation record crosses over
900
+ * this page. Read the next page and try again. xlp_rem_len in the
901
+ * next page header will contain the remaining length of the
902
+ * continuation data
903
+ *
904
+ * Note that record headers are MAXALIGN'ed
905
+ */
906
+ if (MAXALIGN (header -> xlp_rem_len )> (XLOG_BLCKSZ - pageHeaderSize ))
907
+ tmpRecPtr = targetPagePtr + XLOG_BLCKSZ ;
908
+ else
909
+ {
910
+ /*
911
+ * The previous continuation record ends in this page. Set
912
+ * tmpRecPtr to point to the first valid record
913
+ */
914
+ tmpRecPtr = targetPagePtr + pageHeaderSize
915
+ + MAXALIGN (header -> xlp_rem_len );
916
+ break ;
917
+ }
918
+ }
919
+ else
920
+ {
921
+ tmpRecPtr = targetPagePtr + pageHeaderSize ;
922
+ break ;
923
+ }
887
924
}
888
925
889
926
/*