Revert some more changes back the way it's in CVS HEAD, now that we
authorHeikki Linnakangas <[email protected]>
Thu, 5 Feb 2009 12:28:31 +0000 (14:28 +0200)
committerHeikki Linnakangas <[email protected]>
Thu, 5 Feb 2009 12:47:54 +0000 (14:47 +0200)
do startup checkpoints again.

src/backend/access/transam/xlog.c
src/backend/postmaster/bgwriter.c

index 67542b787fcfe538a5b873b97bf4a482c917068e..0055e7aa6db095b93b8f20eabe8ddbbb34a1464b 100644 (file)
@@ -257,9 +257,8 @@ static XLogRecPtr RedoRecPtr;
  * ControlFileLock: must be held to read/update control file or create
  * new log file.
  *
- * CheckpointLock: must be held to do a checkpoint (ensures only one
- * checkpointer at a time; currently, with all checkpoints done by the
- * bgwriter, this is just pro forma).
+ * CheckpointLock: must be held to do a checkpoint or restartpoint (ensures
+ * only one checkpointer at a time)
  *
  *----------
  */
@@ -2790,7 +2789,7 @@ RestoreArchivedFile(char *path, const char *xlogfname,
         */
        if (shutdown_requested && InRedo)
        {
-               /* XXX: Is EndRecPtr always the right value? */
+               /* XXX: Is EndRecPtr always the right value here? */
                UpdateMinRecoveryPoint(EndRecPtr);
                proc_exit(0);
        }
@@ -4980,7 +4979,6 @@ StartupXLOG(void)
        CheckPoint      checkPoint;
        bool            wasShutdown;
        bool            reachedStopPoint = false;
-       bool            reachedMinRecoveryPoint = false;
        bool            haveBackupLabel = false;
        XLogRecPtr      RecPtr,
                                LastRec,
@@ -5273,6 +5271,7 @@ StartupXLOG(void)
                {
                        bool            recoveryContinue = true;
                        bool            recoveryApply = true;
+                       bool            reachedMinRecoveryPoint = false;
                        ErrorContextCallback errcontext;
                        /* use volatile pointer to prevent code rearrangement */
                        volatile XLogCtlData *xlogctl = XLogCtl;
@@ -5414,7 +5413,6 @@ StartupXLOG(void)
                        /* there are no WAL records following the checkpoint */
                        ereport(LOG,
                                        (errmsg("redo is not required")));
-                       reachedMinRecoveryPoint = true;
                }
        }
 
@@ -5574,6 +5572,9 @@ StartupXLOG(void)
         */
        PreallocXlogFiles(EndOfLog);
 
+       /*
+        * Okay, we're officially UP.
+        */
        InRecovery = false;
 
        LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
@@ -5926,9 +5927,9 @@ LogCheckpointStart(int flags, bool restartpoint)
         * for the main message, but what about all the flags?
         */
        if (restartpoint)
-               msg = "restartpoint starting:%s%s%s%s%s%s%s";
+               msg = "restartpoint starting:%s%s%s%s%s%s";
        else
-               msg = "checkpoint starting:%s%s%s%s%s%s%s";
+               msg = "checkpoint starting:%s%s%s%s%s%s";
 
        elog(LOG, msg,
                 (flags & CHECKPOINT_IS_SHUTDOWN) ? " shutdown" : "",
@@ -6022,9 +6023,6 @@ CreateCheckPoint(int flags)
 
        /*
         * Acquire CheckpointLock to ensure only one checkpoint happens at a time.
-        * (This is just pro forma, since in the present system structure there is
-        * only one process that is allowed to issue checkpoints at any given
-        * time.)
         */
        LWLockAcquire(CheckpointLock, LW_EXCLUSIVE);
 
@@ -6257,10 +6255,11 @@ CreateCheckPoint(int flags)
        XLByteToSeg(ControlFile->checkPointCopy.redo, _logId, _logSeg);
 
        /*
-        * Update the control file. This also sets state to IN_DB_PRODUCTION
-        * if this is the first checkpoint after recovery.
+        * Update the control file.
         */
        LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
+       if (shutdown)
+               ControlFile->state = DB_SHUTDOWNED;
        ControlFile->prevCheckPoint = ControlFile->checkPoint;
        ControlFile->checkPoint = ProcLastRecPtr;
        ControlFile->checkPointCopy = checkPoint;
@@ -6311,9 +6310,11 @@ CreateCheckPoint(int flags)
         * Truncate pg_subtrans if possible.  We can throw away all data before
         * the oldest XMIN of any running transaction.  No future transaction will
         * attempt to reference any pg_subtrans entry older than that (see Asserts
-        * in subtrans.c).
+        * in subtrans.c).  During recovery, though, we mustn't do this because
+        * StartupSUBTRANS hasn't been called yet.
         */
-       TruncateSUBTRANS(GetOldestXmin(true, false));
+       if (!InRecovery)
+               TruncateSUBTRANS(GetOldestXmin(true, false));
 
        /* All real work is done, but log before releasing lock. */
        if (log_checkpoints)
@@ -6400,10 +6401,8 @@ CreateRestartPoint(int flags)
        volatile XLogCtlData *xlogctl = XLogCtl;
 
        /*
-        * Acquire CheckpointLock to ensure only one restartpoint happens at a 
-        * time. (This is just pro forma, since in the present system structure 
-        * there is only one process that is allowed to issue checkpoints or
-        * restart points at any given time.)
+        * Acquire CheckpointLock to ensure only one restartpoint or checkpoint
+        * happens at a time.
         */
        LWLockAcquire(CheckpointLock, LW_EXCLUSIVE);
 
@@ -6588,9 +6587,20 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
                ControlFile->checkPointCopy.nextXid = checkPoint.nextXid;
 
                /*
-                * TLI no longer changes at shutdown checkpoint, since as of 8.4,
+                * TLI may change in a shutdown checkpoint, but it shouldn't decrease
                 * shutdown checkpoints only occur at shutdown. Much less confusing.
                 */
+               if (checkPoint.ThisTimeLineID != ThisTimeLineID)
+               {
+                       if (checkPoint.ThisTimeLineID < ThisTimeLineID ||
+                               !list_member_int(expectedTLIs,
+                                                                (int) checkPoint.ThisTimeLineID))
+                               ereport(PANIC,
+                                               (errmsg("unexpected timeline ID %u (after %u) in checkpoint record",
+                               checkPoint.ThisTimeLineID, ThisTimeLineID)));
+           /* Following WAL records should be run with new TLI */
+           ThisTimeLineID = checkPoint.ThisTimeLineID;
+               }
 
                RecoveryRestartPoint(&checkPoint);
        }
@@ -6615,7 +6625,7 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
                ControlFile->checkPointCopy.nextXidEpoch = checkPoint.nextXidEpoch;
                ControlFile->checkPointCopy.nextXid = checkPoint.nextXid;
 
-               /* TLI must not change at a checkpoint */
+               /* TLI should not change in an on-line checkpoint */
                if (checkPoint.ThisTimeLineID != ThisTimeLineID)
                        ereport(PANIC,
                                        (errmsg("unexpected timeline ID %u (should be %u) in checkpoint record",
index d38e0c645230d7bdcc9a694432cd5ca112726b25..58b982dac1410d2e3d01fbd9a419dbdaf3cb1668 100644 (file)
@@ -199,8 +199,6 @@ BackgroundWriterMain(void)
        sigjmp_buf      local_sigjmp_buf;
        MemoryContext bgwriter_context;
        bool            BgWriterRecoveryMode = true;
-       /* use volatile pointer to prevent code rearrangement */
-       volatile BgWriterShmemStruct *bgs = BgWriterShmem;
 
        BgWriterShmem->bgwriter_pid = MyProcPid;
        am_bg_writer = true;
@@ -359,20 +357,6 @@ BackgroundWriterMain(void)
         */
        PG_SETMASK(&UnBlockSig);
 
-       /*
-        * If someone requested a checkpoint before we started up, process that.
-        *
-        * This check exists primarily for crash recovery: after the startup
-        * process is finished with WAL replay, it will request a checkpoint, but
-        * the background writer might not have started yet. This check will
-        * actually not notice a checkpoint that's been requested without any
-        * flags, but it's good enough for the startup checkpoint.
-        */
-       SpinLockAcquire(&bgs->ckpt_lck);
-       if (bgs->ckpt_flags)
-               checkpoint_requested = true;
-       SpinLockRelease(&bgs->ckpt_lck);
-
        /*
         * Loop forever
         */
@@ -415,7 +399,6 @@ BackgroundWriterMain(void)
                        ExitOnAnyError = true;
                        /* Close down the database */
                        ShutdownXLOG(0, 0);
-
                        /* Normal exit from the bgwriter is here */
                        proc_exit(0);           /* done */
                }
@@ -440,9 +423,9 @@ BackgroundWriterMain(void)
                 * Check if we've exited recovery. We do this after determining
                 * whether to perform a checkpoint or not, to be sure that we
                 * perform a real checkpoint and not a restartpoint, if someone
-                * (like the startup process!) requested a checkpoint immediately
-                * after exiting recovery. And we must have the right TimeLineID
-                * when we perform a checkpoint.
+                * requested a checkpoint immediately after exiting recovery. And
+                * we must have the right TimeLineID when we perform a checkpoint;
+                * IsRecoveryProcessingMode() initializes that as a side-effect.
                 */
                if (BgWriterRecoveryMode && !IsRecoveryProcessingMode())
                {
@@ -456,6 +439,9 @@ BackgroundWriterMain(void)
                 */
                if (do_checkpoint)
                {
+                       /* use volatile pointer to prevent code rearrangement */
+                       volatile BgWriterShmemStruct *bgs = BgWriterShmem;
+
                        /*
                         * Atomically fetch the request flags to figure out what kind of a
                         * checkpoint we should perform, and increase the started-counter