Skip to content

Commit 600f2f5

Browse files
committed
Add condition variable for recovery resume.
Replace a sleep loop with a CV, to get a fast reaction time when recovery is resumed or the postmaster exits via standard infrastructure. Unfortunately we still need to wake up every second to perform extra polling during the recovery pause loop. Discussion: https://postgr.es/m/CA%2BhUKGK1607VmtrDUHQXrsooU%3Dap4g4R2yaoByWOOA3m8xevUQ%40mail.gmail.com
1 parent b82640d commit 600f2f5

File tree

1 file changed

+21
-10
lines changed
  • src/backend/access/transam

1 file changed

+21
-10
lines changed

src/backend/access/transam/xlog.c

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,7 @@ typedef struct XLogCtlData
724724
TimestampTz currentChunkStartTime;
725725
/* Recovery pause state */
726726
RecoveryPauseState recoveryPauseState;
727+
ConditionVariable recoveryNotPausedCV;
727728

728729
/*
729730
* lastFpwDisableRecPtr points to the start of the last replayed
@@ -5228,6 +5229,7 @@ XLOGShmemInit(void)
52285229
SpinLockInit(&XLogCtl->info_lck);
52295230
SpinLockInit(&XLogCtl->ulsn_lck);
52305231
InitSharedLatch(&XLogCtl->recoveryWakeupLatch);
5232+
ConditionVariableInit(&XLogCtl->recoveryNotPausedCV);
52315233
}
52325234

52335235
/*
@@ -6040,10 +6042,6 @@ recoveryStopsAfter(XLogReaderState *record)
60406042
* endOfRecovery is true if the recovery target is reached and
60416043
* the paused state starts at the end of recovery because of
60426044
* recovery_target_action=pause, and false otherwise.
6043-
*
6044-
* XXX Could also be done with shared latch, avoiding the pg_usleep loop.
6045-
* Probably not worth the trouble though. This state shouldn't be one that
6046-
* anyone cares about server power consumption in.
60476045
*/
60486046
static void
60496047
recoveryPausesHere(bool endOfRecovery)
@@ -6071,17 +6069,22 @@ recoveryPausesHere(bool endOfRecovery)
60716069
HandleStartupProcInterrupts();
60726070
if (CheckForStandbyTrigger())
60736071
return;
6074-
pgstat_report_wait_start(WAIT_EVENT_RECOVERY_PAUSE);
60756072

60766073
/*
60776074
* If recovery pause is requested then set it paused. While we are in
60786075
* the loop, user might resume and pause again so set this every time.
60796076
*/
60806077
ConfirmRecoveryPaused();
60816078

6082-
pg_usleep(1000000L); /* 1000 ms */
6083-
pgstat_report_wait_end();
6079+
/*
6080+
* We wait on a condition variable that will wake us as soon as the
6081+
* pause ends, but we use a timeout so we can check the above exit
6082+
* condition periodically too.
6083+
*/
6084+
ConditionVariableTimedSleep(&XLogCtl->recoveryNotPausedCV, 1000,
6085+
WAIT_EVENT_RECOVERY_PAUSE);
60846086
}
6087+
ConditionVariableCancelSleep();
60856088
}
60866089

60876090
/*
@@ -6118,6 +6121,9 @@ SetRecoveryPause(bool recoveryPause)
61186121
XLogCtl->recoveryPauseState = RECOVERY_PAUSE_REQUESTED;
61196122

61206123
SpinLockRelease(&XLogCtl->info_lck);
6124+
6125+
if (!recoveryPause)
6126+
ConditionVariableBroadcast(&XLogCtl->recoveryNotPausedCV);
61216127
}
61226128

61236129
/*
@@ -6357,10 +6363,15 @@ RecoveryRequiresIntParameter(const char *param_name, int currValue, int minValue
63576363
*/
63586364
ConfirmRecoveryPaused();
63596365

6360-
pgstat_report_wait_start(WAIT_EVENT_RECOVERY_PAUSE);
6361-
pg_usleep(1000000L); /* 1000 ms */
6362-
pgstat_report_wait_end();
6366+
/*
6367+
* We wait on a condition variable that will wake us as soon as
6368+
* the pause ends, but we use a timeout so we can check the
6369+
* above conditions periodically too.
6370+
*/
6371+
ConditionVariableTimedSleep(&XLogCtl->recoveryNotPausedCV, 1000,
6372+
WAIT_EVENT_RECOVERY_PAUSE);
63636373
}
6374+
ConditionVariableCancelSleep();
63646375
}
63656376

63666377
ereport(FATAL,

0 commit comments

Comments
 (0)