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