Fix two bugs: minSafeStartPoint must never move backwards, and
authorHeikki Linnakangas <heikki@enterprisedb.com>
Wed, 28 Jan 2009 09:47:28 +0000 (11:47 +0200)
committerHeikki Linnakangas <heikki@enterprisedb.com>
Wed, 28 Jan 2009 09:48:21 +0000 (11:48 +0200)
recoveryLogRestartpoints needs to be accessible to bgwriter.

src/backend/access/transam/xlog.c

index 2a645b26c140e6651e27bf76b4b457c81e523fc9..30fea493979db8b6ea065960c17320d20fd35e31 100644 (file)
@@ -147,10 +147,13 @@ static char *recoveryRestoreCommand = NULL;
 static bool recoveryTarget = false;
 static bool recoveryTargetExact = false;
 static bool recoveryTargetInclusive = true;
-static bool recoveryLogRestartpoints = false;
 static TransactionId recoveryTargetXid;
 static TimestampTz recoveryTargetTime;
 static TimestampTz recoveryLastXTime = 0;
+/*
+ * log_restartpoints is stored in shared memory because it needs to be
+ * accessed by bgwriter when it performs restartpoints
+ */
 
 /* if recoveryStopsHere returns true, it saves actual stop xid/time here */
 static TransactionId recoveryStopXid;
@@ -346,6 +349,9 @@ typedef struct XLogCtlData
        XLogRecPtr      lastCheckPointRecPtr;
        CheckPoint      lastCheckPoint;
 
+       /* Should restartpoints be logged? Taken from recovery.conf */
+       bool            recoveryLogRestartpoints;
+
        slock_t         info_lck;               /* locks shared variables shown above */
 } XLogCtlData;
 
@@ -2459,15 +2465,20 @@ XLogFileRead(uint32 log, uint32 seg, int emode)
                         */
                        if (InArchiveRecovery)
                        {
-                               uint32 nextLog = log;
-                               uint32 nextSeg = seg;
+                               XLogRecPtr      nextSegRecPtr;
+                               uint32          nextLog = log;
+                               uint32          nextSeg = seg;
 
                                NextLogSeg(nextLog, nextSeg);
+                               nextSegRecPtr.xlogid = nextLog;
+                               nextSegRecPtr.xrecoff = nextSeg * XLogSegSize;
 
                                LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
-                               ControlFile->minSafeStartPoint.xlogid = nextLog;
-                               ControlFile->minSafeStartPoint.xrecoff = nextSeg * XLogSegSize;
-                               UpdateControlFile();
+                               if (XLByteLT(ControlFile->minSafeStartPoint, nextSegRecPtr))
+                               {
+                                       ControlFile->minSafeStartPoint = nextSegRecPtr;
+                                       UpdateControlFile();
+                               }
                                LWLockRelease(ControlFileLock);
                        }
 
@@ -4654,7 +4665,7 @@ readRecoveryCommandFile(void)
                        /*
                         * does nothing if a recovery_target is not also set
                         */
-                       if (!parse_bool(tok2, &recoveryLogRestartpoints))
+                       if (!parse_bool(tok2, &XLogCtl->recoveryLogRestartpoints))
                                ereport(ERROR,
                                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                                        errmsg("parameter \"log_restartpoints\" requires a Boolean value")));
@@ -5229,12 +5240,19 @@ StartupXLOG(void)
                        bool            recoveryContinue = true;
                        bool            recoveryApply = true;
                        ErrorContextCallback errcontext;
+                       XLogRecPtr      minSafeStartPoint;
 
                        InRedo = true;
                        ereport(LOG,
                                        (errmsg("redo starts at %X/%X",
                                                        ReadRecPtr.xlogid, ReadRecPtr.xrecoff)));
 
+                       /*
+                        * Take a local copy of minSafeStartPoint at the beginning of
+                        * recovery, because it's updated as we go.
+                        */
+                       minSafeStartPoint = ControlFile->minSafeStartPoint;
+
                        /*
                         * main redo apply loop
                         */
@@ -5303,7 +5321,7 @@ StartupXLOG(void)
                                 * latest LSN that recovery could have reached prior to crash.
                                 */
                                if (!reachedSafeStartPoint && 
-                                        XLByteLE(ControlFile->minSafeStartPoint, EndRecPtr) && 
+                                        XLByteLE(minSafeStartPoint, EndRecPtr) && 
                                         XLByteLE(ControlFile->minRecoveryPoint, EndRecPtr))
                                {
                                        reachedSafeStartPoint = true;
@@ -6352,7 +6370,7 @@ CreateRestartPoint(int flags)
                return;
        }
 
-       if (recoveryLogRestartpoints)
+       if (XLogCtl->recoveryLogRestartpoints)
        {
                /*
                 * Prepare to accumulate statistics.
@@ -6383,15 +6401,15 @@ CreateRestartPoint(int flags)
         */
 
        /* All real work is done, but log before releasing lock. */
-       if (recoveryLogRestartpoints)
+       if (XLogCtl->recoveryLogRestartpoints)
                LogCheckpointEnd(flags, true);
 
-       ereport((recoveryLogRestartpoints ? LOG : DEBUG2),
+       ereport((XLogCtl->recoveryLogRestartpoints ? LOG : DEBUG2),
                        (errmsg("recovery restart point at %X/%X",
                                        lastCheckPoint.redo.xlogid, lastCheckPoint.redo.xrecoff)));
 
        if (recoveryLastXTime)
-               ereport((recoveryLogRestartpoints ? LOG : DEBUG2),
+               ereport((XLogCtl->recoveryLogRestartpoints ? LOG : DEBUG2),
                        (errmsg("last completed transaction was at log time %s",
                                        timestamptz_to_str(recoveryLastXTime))));