@@ -811,17 +811,13 @@ static XLogSegNo openLogSegNo = 0;
811811 * These variables are used similarly to the ones above, but for reading
812812 * the XLOG. Note, however, that readOff generally represents the offset
813813 * of the page just read, not the seek position of the FD itself, which
814- * will be just past that page. readLen indicates how much of the current
815- * page has been read into readBuf, and readSource indicates where we got
816- * the currently open file from.
814+ * will be just past that page. readSource indicates where we got the
815+ * currently open file from.
817816 * Note: we could use Reserve/ReleaseExternalFD to track consumption of
818817 * this FD too; but it doesn't currently seem worthwhile, since the XLOG is
819818 * not read by general-purpose sessions.
820819 */
821820static int readFile = -1 ;
822- static XLogSegNo readSegNo = 0 ;
823- static uint32 readOff = 0 ;
824- static uint32 readLen = 0 ;
825821static XLogSource readSource = XLOG_FROM_ANY ;
826822
827823/*
@@ -838,13 +834,6 @@ static XLogSource currentSource = XLOG_FROM_ANY;
838834static bool lastSourceFailed = false;
839835static bool pendingWalRcvRestart = false;
840836
841- typedef struct XLogPageReadPrivate
842- {
843- int emode ;
844- bool fetching_ckpt ;/* are we fetching a checkpoint record? */
845- bool randAccess ;
846- }XLogPageReadPrivate ;
847-
848837/*
849838 * These variables track when we last obtained some WAL data to process,
850839 * and where we got it from. (XLogReceiptSource is initially the same as
@@ -920,10 +909,12 @@ static bool InstallXLogFileSegment(XLogSegNo *segno, char *tmppath,
920909static int XLogFileRead (XLogSegNo segno ,int emode ,TimeLineID tli ,
921910XLogSource source ,bool notfoundOk );
922911static int XLogFileReadAnyTLI (XLogSegNo segno ,int emode ,XLogSource source );
923- static int XLogPageRead (XLogReaderState * xlogreader , XLogRecPtr targetPagePtr ,
924- int reqLen , XLogRecPtr targetRecPtr , char * readBuf );
912+ static bool XLogPageRead (XLogReaderState * state ,
913+ bool fetching_ckpt , int emode , bool randAccess );
925914static bool WaitForWALToBecomeAvailable (XLogRecPtr RecPtr ,bool randAccess ,
926- bool fetching_ckpt ,XLogRecPtr tliRecPtr );
915+ bool fetching_ckpt ,
916+ XLogRecPtr tliRecPtr ,
917+ XLogSegNo readSegNo );
927918static int emode_for_corrupt_record (int emode ,XLogRecPtr RecPtr );
928919static void XLogFileClose (void );
929920static void PreallocXlogFiles (XLogRecPtr endptr );
@@ -1234,8 +1225,7 @@ XLogInsertRecord(XLogRecData *rdata,
12341225appendBinaryStringInfo (& recordBuf ,rdata -> data ,rdata -> len );
12351226
12361227if (!debug_reader )
1237- debug_reader = XLogReaderAllocate (wal_segment_size ,NULL ,
1238- XL_ROUTINE (),NULL );
1228+ debug_reader = XLogReaderAllocate (wal_segment_size ,NULL ,NULL );
12391229
12401230if (!debug_reader )
12411231{
@@ -4373,21 +4363,24 @@ ReadRecord(XLogReaderState *xlogreader, int emode,
43734363bool fetching_ckpt )
43744364{
43754365XLogRecord * record ;
4376- XLogPageReadPrivate * private = (XLogPageReadPrivate * )xlogreader -> private_data ;
4377-
4378- /* Pass through parameters to XLogPageRead */
4379- private -> fetching_ckpt = fetching_ckpt ;
4380- private -> emode = emode ;
4381- private -> randAccess = (xlogreader -> ReadRecPtr == InvalidXLogRecPtr );
4366+ bool randAccess = (xlogreader -> ReadRecPtr == InvalidXLogRecPtr );
43824367
43834368/* This is the first attempt to read this page. */
43844369lastSourceFailed = false;
43854370
43864371for (;;)
43874372{
43884373char * errormsg ;
4374+ XLogReadRecordResult result ;
4375+
4376+ while ((result = XLogReadRecord (xlogreader ,& record ,& errormsg ))
4377+ == XLREAD_NEED_DATA )
4378+ {
4379+ if (!XLogPageRead (xlogreader ,fetching_ckpt ,emode ,randAccess ))
4380+ break ;
4381+
4382+ }
43894383
4390- record = XLogReadRecord (xlogreader ,& errormsg );
43914384ReadRecPtr = xlogreader -> ReadRecPtr ;
43924385EndRecPtr = xlogreader -> EndRecPtr ;
43934386if (record == NULL )
@@ -6457,7 +6450,6 @@ StartupXLOG(void)
64576450bool backupFromStandby = false;
64586451DBState dbstate_at_startup ;
64596452XLogReaderState * xlogreader ;
6460- XLogPageReadPrivate private ;
64616453bool promoted = false;
64626454struct stat st ;
64636455
@@ -6616,13 +6608,9 @@ StartupXLOG(void)
66166608OwnLatch (& XLogCtl -> recoveryWakeupLatch );
66176609
66186610/* Set up XLOG reader facility */
6619- MemSet (& private ,0 ,sizeof (XLogPageReadPrivate ));
66206611xlogreader =
6621- XLogReaderAllocate (wal_segment_size ,NULL ,
6622- XL_ROUTINE (.page_read = & XLogPageRead ,
6623- .segment_open = NULL ,
6624- .segment_close = wal_segment_close ),
6625- & private );
6612+ XLogReaderAllocate (wal_segment_size ,NULL ,wal_segment_close );
6613+
66266614if (!xlogreader )
66276615ereport (ERROR ,
66286616(errcode (ERRCODE_OUT_OF_MEMORY ),
@@ -7819,7 +7807,8 @@ StartupXLOG(void)
78197807XLogRecPtr pageBeginPtr ;
78207808
78217809pageBeginPtr = EndOfLog - (EndOfLog %XLOG_BLCKSZ );
7822- Assert (readOff == XLogSegmentOffset (pageBeginPtr ,wal_segment_size ));
7810+ Assert (XLogSegmentOffset (xlogreader -> readPagePtr ,wal_segment_size )==
7811+ XLogSegmentOffset (pageBeginPtr ,wal_segment_size ));
78237812
78247813firstIdx = XLogRecPtrToBufIdx (EndOfLog );
78257814
@@ -12107,13 +12096,15 @@ CancelBackup(void)
1210712096 * XLogPageRead() to try fetching the record from another source, or to
1210812097 * sleep and retry.
1210912098 */
12110- static int
12111- XLogPageRead (XLogReaderState * xlogreader ,XLogRecPtr targetPagePtr ,int reqLen ,
12112- XLogRecPtr targetRecPtr ,char * readBuf )
12113- {
12114- XLogPageReadPrivate * private =
12115- (XLogPageReadPrivate * )xlogreader -> private_data ;
12116- int emode = private -> emode ;
12099+ static bool
12100+ XLogPageRead (XLogReaderState * state ,
12101+ bool fetching_ckpt ,int emode ,bool randAccess )
12102+ {
12103+ char * readBuf = state -> readBuf ;
12104+ XLogRecPtr targetPagePtr = state -> readPagePtr ;
12105+ int reqLen = state -> reqLen ;
12106+ int readLen = 0 ;
12107+ XLogRecPtr targetRecPtr = state -> ReadRecPtr ;
1211712108uint32 targetPageOff ;
1211812109XLogSegNo targetSegNo PG_USED_FOR_ASSERTS_ONLY ;
1211912110int r ;
@@ -12126,18 +12117,18 @@ XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen,
1212612117 * is not in the currently open one.
1212712118 */
1212812119if (readFile >=0 &&
12129- !XLByteInSeg (targetPagePtr ,readSegNo ,wal_segment_size ))
12120+ !XLByteInSeg (targetPagePtr ,state -> seg . ws_segno ,wal_segment_size ))
1213012121{
1213112122/*
1213212123 * Request a restartpoint if we've replayed too much xlog since the
1213312124 * last one.
1213412125 */
1213512126if (bgwriterLaunched )
1213612127{
12137- if (XLogCheckpointNeeded (readSegNo ))
12128+ if (XLogCheckpointNeeded (state -> seg . ws_segno ))
1213812129{
1213912130(void )GetRedoRecPtr ();
12140- if (XLogCheckpointNeeded (readSegNo ))
12131+ if (XLogCheckpointNeeded (state -> seg . ws_segno ))
1214112132RequestCheckpoint (CHECKPOINT_CAUSE_XLOG );
1214212133}
1214312134}
@@ -12147,7 +12138,7 @@ XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen,
1214712138readSource = XLOG_FROM_ANY ;
1214812139}
1214912140
12150- XLByteToSeg (targetPagePtr ,readSegNo ,wal_segment_size );
12141+ XLByteToSeg (targetPagePtr ,state -> seg . ws_segno ,wal_segment_size );
1215112142
1215212143retry :
1215312144/* See if we need to retrieve more data */
@@ -12156,17 +12147,15 @@ XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen,
1215612147flushedUpto < targetPagePtr + reqLen ))
1215712148{
1215812149if (!WaitForWALToBecomeAvailable (targetPagePtr + reqLen ,
12159- private -> randAccess ,
12160- private -> fetching_ckpt ,
12161- targetRecPtr ))
12150+ randAccess ,fetching_ckpt ,
12151+ targetRecPtr ,state -> seg .ws_segno ))
1216212152{
1216312153if (readFile >=0 )
1216412154close (readFile );
1216512155readFile = -1 ;
12166- readLen = 0 ;
1216712156readSource = XLOG_FROM_ANY ;
12168-
12169- return -1 ;
12157+ XLogReaderSetInputData ( state , -1 );
12158+ return false ;
1217012159}
1217112160}
1217212161
@@ -12193,40 +12182,36 @@ XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen,
1219312182else
1219412183readLen = XLOG_BLCKSZ ;
1219512184
12196- /* Read the requested page */
12197- readOff = targetPageOff ;
12198-
1219912185pgstat_report_wait_start (WAIT_EVENT_WAL_READ );
12200- r = pg_pread (readFile ,readBuf ,XLOG_BLCKSZ , (off_t )readOff );
12186+ r = pg_pread (readFile ,readBuf ,XLOG_BLCKSZ , (off_t )targetPageOff );
1220112187if (r != XLOG_BLCKSZ )
1220212188{
1220312189char fname [MAXFNAMELEN ];
1220412190int save_errno = errno ;
1220512191
1220612192pgstat_report_wait_end ();
12207- XLogFileName (fname ,curFileTLI ,readSegNo ,wal_segment_size );
12193+ XLogFileName (fname ,curFileTLI ,state -> seg . ws_segno ,wal_segment_size );
1220812194if (r < 0 )
1220912195{
1221012196errno = save_errno ;
1221112197ereport (emode_for_corrupt_record (emode ,targetPagePtr + reqLen ),
1221212198(errcode_for_file_access (),
1221312199errmsg ("could not read from log segment %s, offset %u: %m" ,
12214- fname ,readOff )));
12200+ fname ,targetPageOff )));
1221512201}
1221612202else
1221712203ereport (emode_for_corrupt_record (emode ,targetPagePtr + reqLen ),
1221812204(errcode (ERRCODE_DATA_CORRUPTED ),
1221912205errmsg ("could not read from log segment %s, offset %u: read %d of %zu" ,
12220- fname ,readOff ,r , (Size )XLOG_BLCKSZ )));
12206+ fname ,targetPageOff ,r , (Size )XLOG_BLCKSZ )));
1222112207gotonext_record_is_invalid ;
1222212208}
1222312209pgstat_report_wait_end ();
1222412210
12225- Assert (targetSegNo == readSegNo );
12226- Assert (targetPageOff == readOff );
12227- Assert (reqLen <=readLen );
12211+ Assert (targetSegNo == state -> seg .ws_segno );
12212+ Assert (readLen >=reqLen );
1222812213
12229- xlogreader -> seg .ws_tli = curFileTLI ;
12214+ state -> seg .ws_tli = curFileTLI ;
1223012215
1223112216/*
1223212217 * Check the page header immediately, so that we can retry immediately if
@@ -12254,29 +12239,31 @@ XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen,
1225412239 * Validating the page header is cheap enough that doing it twice
1225512240 * shouldn't be a big deal from a performance point of view.
1225612241 */
12257- if (!XLogReaderValidatePageHeader (xlogreader ,targetPagePtr ,readBuf ))
12242+ if (!XLogReaderValidatePageHeader (state ,targetPagePtr ,readBuf ))
1225812243{
12259- /* reset any errorXLogReaderValidatePageHeader () might have set */
12260- xlogreader -> errormsg_buf [0 ]= '\0' ;
12244+ /* reset any errorStateValidatePageHeader () might have set */
12245+ state -> errormsg_buf [0 ]= '\0' ;
1226112246gotonext_record_is_invalid ;
1226212247}
1226312248
12264- return readLen ;
12249+ Assert (state -> readPagePtr == targetPagePtr );
12250+ XLogReaderSetInputData (state ,readLen );
12251+ return true;
1226512252
1226612253next_record_is_invalid :
1226712254lastSourceFailed = true;
1226812255
1226912256if (readFile >=0 )
1227012257close (readFile );
1227112258readFile = -1 ;
12272- readLen = 0 ;
1227312259readSource = XLOG_FROM_ANY ;
1227412260
1227512261/* In standby-mode, keep trying */
1227612262if (StandbyMode )
1227712263gotoretry ;
12278- else
12279- return -1 ;
12264+
12265+ XLogReaderSetInputData (state ,-1 );
12266+ return false;
1228012267}
1228112268
1228212269/*
@@ -12307,7 +12294,8 @@ XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen,
1230712294 */
1230812295static bool
1230912296WaitForWALToBecomeAvailable (XLogRecPtr RecPtr ,bool randAccess ,
12310- bool fetching_ckpt ,XLogRecPtr tliRecPtr )
12297+ bool fetching_ckpt ,XLogRecPtr tliRecPtr ,
12298+ XLogSegNo readSegNo )
1231112299{
1231212300static TimestampTz last_fail_time = 0 ;
1231312301TimestampTz now ;