Don't delete unarchived WAL files during crash recovery.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Fri, 15 Feb 2013 15:25:16 +0000 (17:25 +0200)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Fri, 15 Feb 2013 15:43:59 +0000 (17:43 +0200)
Bug reported by Jehan-Guillaume (ioguix) de Rorthais. This was introduced
with the change to keep WAL files restored from archive in pg_xlog, in 9.2.

src/backend/access/transam/xlog.c

index 479c14da902a02f609f4f60ebfd657a2512e87f7..6c9935c5f58a1da4b2fac33174fab239e1b65c39 100644 (file)
@@ -433,6 +433,7 @@ typedef struct XLogCtlData
     * recovery.  Protected by info_lck.
     */
    bool        SharedRecoveryInProgress;
+   bool        SharedInArchiveRecovery;
 
    /*
     * SharedHotStandbyActive indicates if we're still in crash or archive
@@ -619,6 +620,7 @@ static bool bgwriterLaunched = false;
 
 static void readRecoveryCommandFile(void);
 static void exitArchiveRecovery(TimeLineID endTLI, XLogSegNo endLogSegNo);
+static bool ArchiveRecoveryInProgress(void);
 static bool recoveryStopsHere(XLogRecord *record, bool *includeThis);
 static void recoveryPausesHere(void);
 static void SetLatestXTime(TimestampTz xtime);
@@ -2923,7 +2925,7 @@ RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr endptr)
            strspn(xlde->d_name, "0123456789ABCDEF") == 24 &&
            strcmp(xlde->d_name + 8, lastoff + 8) <= 0)
        {
-           if (RecoveryInProgress() || XLogArchiveCheckDone(xlde->d_name))
+           if (ArchiveRecoveryInProgress() || XLogArchiveCheckDone(xlde->d_name))
            {
                snprintf(path, MAXPGPATH, XLOGDIR "/%s", xlde->d_name);
 
@@ -3869,6 +3871,7 @@ XLOGShmemInit(void)
     */
    XLogCtl->XLogCacheBlck = XLOGbuffers - 1;
    XLogCtl->SharedRecoveryInProgress = true;
+   XLogCtl->SharedInArchiveRecovery = false;
    XLogCtl->SharedHotStandbyActive = false;
    XLogCtl->WalWriterSleeping = false;
    XLogCtl->Insert.currpage = (XLogPageHeader) (XLogCtl->pages);
@@ -4262,6 +4265,7 @@ readRecoveryCommandFile(void)
 
    /* Enable fetching from archive recovery area */
    InArchiveRecovery = true;
+   XLogCtl->SharedInArchiveRecovery = true;
 
    /*
     * If user specified recovery_target_timeline, validate it or compute the
@@ -4300,11 +4304,16 @@ exitArchiveRecovery(TimeLineID endTLI, XLogSegNo endLogSegNo)
 {
    char        recoveryPath[MAXPGPATH];
    char        xlogpath[MAXPGPATH];
+   /* use volatile pointer to prevent code rearrangement */
+   volatile XLogCtlData *xlogctl = XLogCtl;
 
    /*
     * We are no longer in archive recovery state.
     */
    InArchiveRecovery = false;
+   SpinLockAcquire(&xlogctl->info_lck);
+   xlogctl->SharedInArchiveRecovery = false;
+   SpinLockRelease(&xlogctl->info_lck);
 
    /*
     * Update min recovery point one last time.
@@ -6101,6 +6110,25 @@ RecoveryInProgress(void)
    }
 }
 
+/*
+ * Are we currently in archive recovery? In the startup process, you can just
+ * check InArchiveRecovery variable instead.
+ */
+static bool
+ArchiveRecoveryInProgress()
+{
+   bool        result;
+   /* use volatile pointer to prevent code rearrangement */
+   volatile XLogCtlData *xlogctl = XLogCtl;
+
+   /* spinlock is essential on machines with weak memory ordering! */
+   SpinLockAcquire(&xlogctl->info_lck);
+   result = xlogctl->SharedInArchiveRecovery;
+   SpinLockRelease(&xlogctl->info_lck);
+
+   return result;
+}
+
 /*
  * Is HotStandby active yet? This is only important in special backends
  * since normal backends won't ever be able to connect until this returns