Revert the recovery.conf file renaming change. Remove the (remains of the) code
authorHeikki Linnakangas <[email protected]>
Tue, 27 Jan 2009 16:40:59 +0000 (18:40 +0200)
committerHeikki Linnakangas <[email protected]>
Tue, 27 Jan 2009 18:16:36 +0000 (20:16 +0200)
to pass the redo location of the first checkpoint from startup process to
bgwriter. Silence LOG warning about bgwriter not being started yet when the
startup checkpoint is requested.

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

index 3005e44c533a69ad75621a200996382b9c81fc89..06ff2a5147045fa83f58ba9511324a405b75e80f 100644 (file)
@@ -4816,13 +4816,18 @@ exitArchiveRecovery(TimeLineID endTLI, uint32 endLogId, uint32 endLogSeg)
        unlink(recoveryPath);           /* ignore any error */
 
        /*
-        * As of 8.4 we no longer rename the recovery.conf file out of the
-        * way until after we have performed a full checkpoint. This ensures
-        * that any crash between now and the end of the checkpoint does not
-        * attempt to restart from a WAL file that is no longer available to us.
-        * As soon as we remove recovery.conf we lose our recovery_command and
-        * cannot reaccess WAL files from the archive.
-        */
+        * Rename the config file out of the way, so that we don't accidentally
+        * re-enter archive recovery mode in a subsequent crash. We have already
+        * restored all the WAL segments we need from the archive, and we trust
+        * that they are not going to go away even if we crash. (XXX: should
+        * we fsync() them all to ensure that?)
+        */
+       unlink(RECOVERY_COMMAND_DONE);
+       if (rename(RECOVERY_COMMAND_FILE, RECOVERY_COMMAND_DONE) != 0)
+               ereport(FATAL,
+                               (errcode_for_file_access(),
+                                errmsg("could not rename file \"%s\" to \"%s\": %m",
+                                               RECOVERY_COMMAND_FILE, RECOVERY_COMMAND_DONE)));
 
        ereport(LOG,
                        (errmsg("archive recovery complete")));
@@ -5547,39 +5552,21 @@ StartupXLOG(void)
        }
 
        /*
-        * Prior to 8.4 we wrote a Shutdown Checkpoint at the end of recovery.
-        * This could add minutes to the startup time, so we want bgwriter
-        * to perform it. This then frees the Startup process to complete so we can
-        * allow transactions and WAL inserts. We still write a checkpoint, but
-        * it will be an online checkpoint. Online checkpoints have a redo
-        * location that can be prior to the actual checkpoint record. So we want
-        * to derive that redo location *before* we let anybody else write WAL,
-        * otherwise we might miss some WAL records if we crash.
+        * If we had to replay any WAL records, request a checkpoint. This isn't
+        * strictly necessary: if we crash now, the recovery will simply restart
+        * from the same point where it started this time around (or from the
+        * last restartpoint). The control file is left in DB_IN_*_RECOVERY
+        * state; the first checkpoint will change that to DB_IN_PRODUCTION.
         */
        if (performedRecovery)
        {
-#ifdef DEADCODE
-               XLogRecPtr      redo;
-
-               /* 
-                * We must grab the pointer before anybody writes WAL 
-                */
-               redo = GetRedoLocationForCheckpoint();
-
-               /* 
-                * Tell the bgwriter
-                */
-               SetRedoLocationForArchiveCheckpoint(redo);
-#endif
                /*
                 * Okay, we can come up now. Allow others to write WAL.
                 */
                XLogCtl->SharedRecoveryProcessingMode = false;
 
-               /*
-                * Now request checkpoint
-                */
-               RequestCheckpoint(CHECKPOINT_FORCE | CHECKPOINT_IMMEDIATE);
+               RequestCheckpoint(CHECKPOINT_FORCE | CHECKPOINT_IMMEDIATE |
+                                                 CHECKPOINT_STARTUP);
        }
        else
        {
@@ -5978,7 +5965,6 @@ CreateCheckPoint(int flags)
        uint32          _logSeg;
        TransactionId *inCommitXids;
        int                     nInCommit;
-       bool            leavingArchiveRecovery = false;
 
        /*
         * Acquire CheckpointLock to ensure only one checkpoint happens at a time.
@@ -5997,13 +5983,6 @@ CreateCheckPoint(int flags)
        MemSet(&CheckpointStats, 0, sizeof(CheckpointStats));
        CheckpointStats.ckpt_start_t = GetCurrentTimestamp();
 
-       /*
-        * Find out if this is the first checkpoint after archive recovery.
-        */
-       LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
-       leavingArchiveRecovery = (ControlFile->state == DB_IN_ARCHIVE_RECOVERY);
-       LWLockRelease(ControlFileLock);
-
        /*
         * Use a critical section to force system panic if we have trouble.
         */
@@ -6030,69 +6009,62 @@ CreateCheckPoint(int flags)
        checkPoint.ThisTimeLineID = ThisTimeLineID;
        checkPoint.time = (pg_time_t) time(NULL);
 
-#ifdef DEADCODE
-       if (leavingArchiveRecovery)
-               checkPoint.redo = GetRedoLocationForArchiveCheckpoint();
-       else
-#endif
-       {
-               /*
-                * We must hold WALInsertLock while examining insert state to determine
-                * the checkpoint REDO pointer.
-                */
-               LWLockAcquire(WALInsertLock, LW_EXCLUSIVE);
+       /*
+        * We must hold WALInsertLock while examining insert state to determine
+        * the checkpoint REDO pointer.
+        */
+       LWLockAcquire(WALInsertLock, LW_EXCLUSIVE);
 
-               /*
-                * If this isn't a shutdown or forced checkpoint, and we have not inserted
-                * any XLOG records since the start of the last checkpoint, skip the
-                * checkpoint.  The idea here is to avoid inserting duplicate checkpoints
-                * when the system is idle. That wastes log space, and more importantly it
-                * exposes us to possible loss of both current and previous checkpoint
-                * records if the machine crashes just as we're writing the update.
-                * (Perhaps it'd make even more sense to checkpoint only when the previous
-                * checkpoint record is in a different xlog page?)
-                *
-                * We have to make two tests to determine that nothing has happened since
-                * the start of the last checkpoint: current insertion point must match
-                * the end of the last checkpoint record, and its redo pointer must point
-                * to itself.
-                */
-               if ((flags & (CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_FORCE)) == 0)
+       /*
+        * If this isn't a shutdown or forced checkpoint, and we have not inserted
+        * any XLOG records since the start of the last checkpoint, skip the
+        * checkpoint.  The idea here is to avoid inserting duplicate checkpoints
+        * when the system is idle. That wastes log space, and more importantly it
+        * exposes us to possible loss of both current and previous checkpoint
+        * records if the machine crashes just as we're writing the update.
+        * (Perhaps it'd make even more sense to checkpoint only when the previous
+        * checkpoint record is in a different xlog page?)
+        *
+        * We have to make two tests to determine that nothing has happened since
+        * the start of the last checkpoint: current insertion point must match
+        * the end of the last checkpoint record, and its redo pointer must point
+        * to itself.
+        */
+       if ((flags & (CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_FORCE)) == 0)
+       {
+               XLogRecPtr      curInsert;
+
+               INSERT_RECPTR(curInsert, Insert, Insert->curridx);
+               if (curInsert.xlogid == ControlFile->checkPoint.xlogid &&
+                       curInsert.xrecoff == ControlFile->checkPoint.xrecoff +
+                       MAXALIGN(SizeOfXLogRecord + sizeof(CheckPoint)) &&
+                       ControlFile->checkPoint.xlogid ==
+                       ControlFile->checkPointCopy.redo.xlogid &&
+                       ControlFile->checkPoint.xrecoff ==
+                       ControlFile->checkPointCopy.redo.xrecoff)
                {
-                       XLogRecPtr      curInsert;
-
-                       INSERT_RECPTR(curInsert, Insert, Insert->curridx);
-                       if (curInsert.xlogid == ControlFile->checkPoint.xlogid &&
-                               curInsert.xrecoff == ControlFile->checkPoint.xrecoff +
-                               MAXALIGN(SizeOfXLogRecord + sizeof(CheckPoint)) &&
-                               ControlFile->checkPoint.xlogid ==
-                               ControlFile->checkPointCopy.redo.xlogid &&
-                               ControlFile->checkPoint.xrecoff ==
-                               ControlFile->checkPointCopy.redo.xrecoff)
-                       {
-                               LWLockRelease(WALInsertLock);
-                               LWLockRelease(CheckpointLock);
-                               END_CRIT_SECTION();
-                               return;
-                       }
+                       LWLockRelease(WALInsertLock);
+                       LWLockRelease(CheckpointLock);
+                       END_CRIT_SECTION();
+                       return;
                }
+       }
 
-               /*
-                * Compute new REDO record ptr = location of next XLOG record.
-                *
-                * NB: this is NOT necessarily where the checkpoint record itself will be,
-                * since other backends may insert more XLOG records while we're off doing
-                * the buffer flush work.  Those XLOG records are logically after the
-                * checkpoint, even though physically before it.  Got that?
-                */
-               checkPoint.redo = GetRedoLocationForCheckpoint();
+       /*
+        * Compute new REDO record ptr = location of next XLOG record.
+        *
+        * NB: this is NOT necessarily where the checkpoint record itself will be,
+        * since other backends may insert more XLOG records while we're off doing
+        * the buffer flush work.  Those XLOG records are logically after the
+        * checkpoint, even though physically before it.  Got that?
+        */
+       checkPoint.redo = GetRedoLocationForCheckpoint();
 
-               /*
-                * Now we can release WAL insert lock, allowing other xacts to proceed
-                * while we are flushing disk buffers.
-                */
-               LWLockRelease(WALInsertLock);
-       }
+       /*
+        * Now we can release WAL insert lock, allowing other xacts to proceed
+        * while we are flushing disk buffers.
+        */
+       LWLockRelease(WALInsertLock);
 
        /*
         * If enabled, log checkpoint start.  We postpone this until now so as not
@@ -6225,21 +6197,6 @@ CreateCheckPoint(int flags)
 
        LWLockRelease(ControlFileLock);
 
-       if (leavingArchiveRecovery)
-       {
-               /*
-                * Rename the config file out of the way, so that we don't accidentally
-                * re-enter archive recovery mode in a subsequent crash. Prior to
-                * 8.4 this step was performed at end of exitArchiveRecovery().
-                */
-               unlink(RECOVERY_COMMAND_DONE);
-               if (rename(RECOVERY_COMMAND_FILE, RECOVERY_COMMAND_DONE) != 0)
-                       ereport(ERROR,
-                                       (errcode_for_file_access(),
-                                        errmsg("could not rename file \"%s\" to \"%s\": %m",
-                                                       RECOVERY_COMMAND_FILE, RECOVERY_COMMAND_DONE)));
-       }
-
        /* Update shared-memory copy of checkpoint XID/epoch */
        {
                /* use volatile pointer to prevent code rearrangement */
index 8923c3a1942f8c6a7fa18ef2f4a2a1c400f06dce..a4c12de2b02cd3550644174d74d3877e01ff8c40 100644 (file)
@@ -880,6 +880,7 @@ BgWriterShmemInit(void)
  *
  * flags is a bitwise OR of the following:
  *     CHECKPOINT_IS_SHUTDOWN: checkpoint is for database shutdown.
+ *     CHECKPOINT_IS_STARTUP: checkpoint is for database startup.
  *     CHECKPOINT_IMMEDIATE: finish the checkpoint ASAP,
  *             ignoring checkpoint_completion_target parameter.
  *     CHECKPOINT_FORCE: force a checkpoint even if no XLOG activity has occured
@@ -946,6 +947,18 @@ RequestCheckpoint(int flags)
        {
                if (BgWriterShmem->bgwriter_pid == 0)
                {
+                       /*
+                        * The only difference between a startup checkpoint and a normal
+                        * online checkpoint is that it's quite normal for the bgwriter
+                        * to not be up yet when the startup checkpoint is requested.
+                        * (it might be, though). That's ok, background writer will
+                        * perform the checkpoint as soon as it starts up.
+                        */
+                       if (flags & CHECKPOINT_STARTUP)
+                       {
+                               Assert(!(flags & CHECKPOINT_WAIT));
+                               break;
+                       }
                        if (ntries >= 20)               /* max wait 2.0 sec */
                        {
                                elog((flags & CHECKPOINT_WAIT) ? ERROR : LOG,
index 897974efae05909ee449011e2acd4e2bd4e20323..6f58b8040fd484eba81c1370c7a18394b4ca137c 100644 (file)
@@ -170,11 +170,12 @@ extern bool XLOG_DEBUG;
 #define CHECKPOINT_IS_SHUTDOWN 0x0001  /* Checkpoint is for shutdown */
 #define CHECKPOINT_IMMEDIATE   0x0002  /* Do it without delays */
 #define CHECKPOINT_FORCE               0x0004  /* Force even if no activity */
+#define CHECKPOINT_STARTUP             0x0008  /* Startup checkpoint */
 /* These are important to RequestCheckpoint */
-#define CHECKPOINT_WAIT                        0x0008  /* Wait for completion */
+#define CHECKPOINT_WAIT                        0x0010  /* Wait for completion */
 /* These indicate the cause of a checkpoint request */
-#define CHECKPOINT_CAUSE_XLOG  0x0010  /* XLOG consumption */
-#define CHECKPOINT_CAUSE_TIME  0x0020  /* Elapsed time */
+#define CHECKPOINT_CAUSE_XLOG  0x0020  /* XLOG consumption */
+#define CHECKPOINT_CAUSE_TIME  0x0040  /* Elapsed time */
 
 /* Checkpoint statistics */
 typedef struct CheckpointStatsData
index 00eb7a4fa7e55575886bee3ca2ef180de74bb71c..35f24d68c2f0218740d6ea2d7b09773cd1e9f6cc 100644 (file)
@@ -27,8 +27,6 @@ extern void BackgroundWriterMain(void);
 
 extern void RequestCheckpoint(int flags);
 extern void RequestRestartPointCompletion(void);
-extern XLogRecPtr GetRedoLocationForArchiveCheckpoint(void);
-extern void SetRedoLocationForArchiveCheckpoint(XLogRecPtr redo);
 
 extern void CheckpointWriteDelay(int flags, double progress);