If a restartpoint is in progress at end of recovery, hurry it.
authorHeikki Linnakangas <[email protected]>
Mon, 9 Feb 2009 09:52:19 +0000 (11:52 +0200)
committerHeikki Linnakangas <[email protected]>
Mon, 9 Feb 2009 09:52:19 +0000 (11:52 +0200)
src/backend/access/transam/xlog.c
src/backend/postmaster/bgwriter.c

index bcc54eb1746adbd7be3359beaccd66e99f744659..0ace629e8ff5f0e94c2307e908b59effa74cae13 100644 (file)
@@ -6026,7 +6026,26 @@ CreateCheckPoint(int flags)
        /*
         * 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.
index c1f29189ea2fce471f0b7e36954463dcca3c373a..79aa36dc3ad46e237f8d85b5a63e4e2b9718e11e 100644 (file)
@@ -499,12 +499,12 @@ BackgroundWriterMain(void)
                        /*
                         * 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
@@ -517,10 +517,10 @@ BackgroundWriterMain(void)
                                /*
                                 * 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;