* If the last checkpoint record we've replayed is already our last
* restartpoint, we're done.
*/
- if (XLByteLE(lastCheckPoint.redo, ControlFile->checkPointCopy.redo))
+ if (XLogRecPtrIsInvalid(lastCheckPointRecPtr) ||
+ XLByteLE(lastCheckPoint.redo, ControlFile->checkPointCopy.redo))
{
ereport(DEBUG2,
(errmsg("skipping restartpoint, already performed at %X/%X",
*
* Notice that this state variable does not distinguish *why* we entered
* states later than PM_RUN --- Shutdown and FatalError must be consulted
- * to find that out. FatalError is never true in PM_RUN state, nor in
- * PM_SHUTDOWN states (because we don't enter those states when trying to
- * recover from a crash). It can be true in PM_STARTUP state, because we
- * don't clear it until we've successfully recovered.
+ * to find that out. FatalError is never true in PM_RECOVERY_* or PM_RUN
+ * states, nor in PM_SHUTDOWN states (because we don't enter those states
+ * when trying to recover from a crash). It can be true in PM_STARTUP state,
+ * because we don't clear it until we've successfully started WAL redo.
*/
typedef enum
{
return CAC_WAITBACKUP; /* allow superusers only */
if (Shutdown > NoShutdown)
return CAC_SHUTDOWN; /* shutdown is pending */
- if (pmState == PM_STARTUP && !FatalError)
+ if (!FatalError &&
+ (pmState == PM_STARTUP ||
+ pmState == PM_RECOVERY ||
+ pmState == PM_RECOVERY_CONSISTENT))
return CAC_STARTUP; /* normal startup */
return CAC_RECOVERY; /* else must be crash recovery */
}
if (pmState == PM_STARTUP && RecoveryStatus > NoRecovery)
{
- /* Recovery has started */
+ /* WAL redo has started. We're out of reinitialization. */
+ FatalError = false;
/*
* Go to shutdown mode if a shutdown request was pending.