/*
* Acquire CheckpointLock to ensure only one checkpoint happens at a time.
*/
- LWLockAcquire(CheckpointLock, LW_EXCLUSIVE);
+ if (!LWLockConditionalAcquire(CheckpointLock, LW_EXCLUSIVE))
+ {
+ /*
+ * This should only happen at the end of archive recovery.
+ * During normal operation, only bgwriter creates checkpoints.
+ */
+ Assert(InRecovery);
+
+ /*
+ * A restartpoint is in progress. Wait until it finishes. This can
+ * cause an extra restartpoint to be performed, but that's OK because
+ * we're just about to perform a checkpoint anyway. Flushing the
+ * buffers in this restartpoint can take some time, but that time is
+ * saved from the upcoming checkpoint so the net effect is zero.
+ */
+ elog(DEBUG2, "hurrying in-progress restartpoint");
+ RequestCheckpoint(CHECKPOINT_IMMEDIATE | CHECKPOINT_WAIT);
+
+ LWLockAcquire(CheckpointLock, LW_EXCLUSIVE);
+ }
/*
* Prepare to accumulate statistics.
/*
* Indicate checkpoint completion to any waiting backends.
*/
+ SpinLockAcquire(&bgs->ckpt_lck);
+ bgs->ckpt_done = bgs->ckpt_started;
+ SpinLockRelease(&bgs->ckpt_lck);
+
if (ckpt_performed)
{
- SpinLockAcquire(&bgs->ckpt_lck);
- bgs->ckpt_done = bgs->ckpt_started;
- SpinLockRelease(&bgs->ckpt_lck);
-
/*
* Note we record the checkpoint start time not end time as
* last_checkpoint_time. This is so that time-driven
/*
* We were not able to perform the restartpoint (checkpoints
* throw an ERROR in case of error). Most likely because we
- * have not received a new checkpoint WAL record since the
+ * have not received any new checkpoint WAL records since the
* last restartpoint. Try again in 15 s.
*/
- last_checkpoint_time = now - CheckPointTimeout - 15;
+ last_checkpoint_time = now - CheckPointTimeout + 15;
}
ckpt_active = false;