@@ -754,6 +754,7 @@ typedef struct XLogCtlData
754
754
TimeLineID lastReplayedTLI ;
755
755
XLogRecPtr replayEndRecPtr ;
756
756
TimeLineID replayEndTLI ;
757
+ ConditionVariable replayProgressCV ;
757
758
/* timestamp of last COMMIT/ABORT record replayed (or being replayed) */
758
759
TimestampTz recoveryLastXTime ;
759
760
@@ -5342,9 +5343,67 @@ XLOGShmemInit(void)
5342
5343
SpinLockInit (& XLogCtl -> info_lck );
5343
5344
SpinLockInit (& XLogCtl -> ulsn_lck );
5344
5345
InitSharedLatch (& XLogCtl -> recoveryWakeupLatch );
5346
+ ConditionVariableInit (& XLogCtl -> replayProgressCV );
5345
5347
ConditionVariableInit (& XLogCtl -> recoveryNotPausedCV );
5346
5348
}
5347
5349
5350
+ /*
5351
+ * Wait for recovery to complete replaying all WAL up to and including
5352
+ * redoEndRecPtr.
5353
+ *
5354
+ * This gets woken up for every WAL record replayed, so make sure you're not
5355
+ * trying to wait an LSN that is too far in the future.
5356
+ */
5357
+ void
5358
+ XLogWaitForReplayOf (XLogRecPtr redoEndRecPtr )
5359
+ {
5360
+ static XLogRecPtr replayRecPtr = 0 ;
5361
+
5362
+ if (!RecoveryInProgress ())
5363
+ return ;
5364
+
5365
+ /*
5366
+ * Check the backend-local variable first, we may be able to skip accessing
5367
+ * shared memory (which requires locking)
5368
+ */
5369
+ if (redoEndRecPtr <= replayRecPtr )
5370
+ return ;
5371
+
5372
+ replayRecPtr = GetXLogReplayRecPtr (NULL );
5373
+
5374
+ /*
5375
+ * Check again if we're going to need to wait, now that we've updated
5376
+ * the local cached variable.
5377
+ */
5378
+ if (redoEndRecPtr <= replayRecPtr )
5379
+ return ;
5380
+
5381
+ /*
5382
+ * We need to wait for the variable, so prepare for that.
5383
+ *
5384
+ * Note: This wakes up every time a WAL record is replayed, so this can
5385
+ * be expensive.
5386
+ */
5387
+ ConditionVariablePrepareToSleep (& XLogCtl -> replayProgressCV );
5388
+
5389
+ while (redoEndRecPtr > replayRecPtr )
5390
+ {
5391
+ bool timeout ;
5392
+ timeout = ConditionVariableTimedSleep (& XLogCtl -> replayProgressCV ,
5393
+ 10000000 ,
5394
+ WAIT_EVENT_RECOVERY_WAL_STREAM );
5395
+
5396
+ if (timeout )
5397
+ ereport (LOG ,
5398
+ (errmsg ("Waiting for recovery to catch up to %X/%X" ,
5399
+ LSN_FORMAT_ARGS (redoEndRecPtr ))));
5400
+ else
5401
+ replayRecPtr = GetXLogReplayRecPtr (NULL );
5402
+ }
5403
+
5404
+ ConditionVariableCancelSleep ();
5405
+ }
5406
+
5348
5407
/*
5349
5408
* This func must be called ONCE on system install. It creates pg_control
5350
5409
* and the initial XLOG segment.
@@ -7267,6 +7326,14 @@ StartupXLOG(void)
7267
7326
abortedRecPtr = InvalidXLogRecPtr ;
7268
7327
missingContrecPtr = InvalidXLogRecPtr ;
7269
7328
7329
+ /*
7330
+ * Setup last written lsn cache, max written LSN.
7331
+ * Starting from here, we could be modifying pages through REDO, which requires
7332
+ * the existance of maxLwLsn + LwLsn LRU.
7333
+ */
7334
+ XLogCtl -> maxLastWrittenLsn = RedoRecPtr ;
7335
+ dlist_init (& XLogCtl -> lastWrittenLsnLRU );
7336
+
7270
7337
/* REDO */
7271
7338
if (InRecovery )
7272
7339
{
@@ -7774,6 +7841,8 @@ StartupXLOG(void)
7774
7841
WalSndWakeup ();
7775
7842
}
7776
7843
7844
+ ConditionVariableBroadcast (& XLogCtl -> replayProgressCV );
7845
+
7777
7846
/* Exit loop if we reached inclusive recovery target */
7778
7847
if (recoveryStopsAfter (xlogreader ))
7779
7848
{
@@ -8169,8 +8238,6 @@ StartupXLOG(void)
8169
8238
8170
8239
XLogCtl -> LogwrtRqst .Write = EndOfLog ;
8171
8240
XLogCtl -> LogwrtRqst .Flush = EndOfLog ;
8172
- XLogCtl -> maxLastWrittenLsn = EndOfLog ;
8173
- dlist_init (& XLogCtl -> lastWrittenLsnLRU );
8174
8241
8175
8242
LocalSetXLogInsertAllowed ();
8176
8243
@@ -10980,11 +11047,14 @@ xlog_redo(XLogReaderState *record)
10980
11047
XLogRedoAction result ;
10981
11048
10982
11049
result = XLogReadBufferForRedo (record , block_id , & buffer );
10983
- if (result == BLK_DONE && !IsUnderPostmaster )
11050
+ if (result == BLK_DONE && ( !IsUnderPostmaster || StandbyMode ) )
10984
11051
{
10985
11052
/*
10986
- * In the special WAL process, blocks that are being ignored
10987
- * return BLK_DONE. Accept that.
11053
+ * NEON: In the special WAL redo process, blocks that are being
11054
+ * ignored return BLK_DONE. Accept that.
11055
+ * Additionally, in standby mode, blocks that are not present
11056
+ * in shared buffers are ignored during replay, so we also
11057
+ * ignore those blocks.
10988
11058
*/
10989
11059
}
10990
11060
else if (result != BLK_RESTORED )
0 commit comments