]> granicus.if.org Git - postgresql/blobdiff - src/backend/access/transam/xlogarchive.c
Fix initialization of fake LSN for unlogged relations
[postgresql] / src / backend / access / transam / xlogarchive.c
index f435f65e98bfe261a2c9f8fb21bf381eca09ef59..e14bcf8ea6092fb40a7618ba1a6b76ba4411bbad 100644 (file)
@@ -4,7 +4,7 @@
  *             Functions for archiving WAL files and restoring from the archive.
  *
  *
- * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * src/backend/access/transam/xlogarchive.c
@@ -14,7 +14,6 @@
 
 #include "postgres.h"
 
-#include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
 #include <signal.h>
  * Attempt to retrieve the specified file from off-line archival storage.
  * If successful, fill "path" with its complete path (note that this will be
  * a temp file name that doesn't follow the normal naming convention), and
- * return TRUE.
+ * return true.
  *
  * If not successful, fill "path" with the name of the normal on-line file
  * (which may or may not actually exist, but we'll try to use it), and return
- * FALSE.
+ * false.
  *
  * For fixed-size files, the caller may pass the expected size as an
  * additional crosscheck on successful recovery.  If the file size is not
@@ -60,14 +59,20 @@ RestoreArchivedFile(char *path, const char *xlogfname,
        char       *endp;
        const char *sp;
        int                     rc;
-       bool            signaled;
        struct stat stat_buf;
        XLogSegNo       restartSegNo;
        XLogRecPtr      restartRedoPtr;
        TimeLineID      restartTli;
 
+       /*
+        * Ignore restore_command when not in archive recovery (meaning
+        * we are in crash recovery).
+        */
+       if (!ArchiveRecoveryRequested)
+               goto not_available;
+
        /* In standby mode, restore_command might not be supplied */
-       if (recoveryRestoreCommand == NULL)
+       if (recoveryRestoreCommand == NULL || strcmp(recoveryRestoreCommand, "") == 0)
                goto not_available;
 
        /*
@@ -135,13 +140,14 @@ RestoreArchivedFile(char *path, const char *xlogfname,
        if (cleanupEnabled)
        {
                GetOldestRestartPoint(&restartRedoPtr, &restartTli);
-               XLByteToSeg(restartRedoPtr, restartSegNo);
-               XLogFileName(lastRestartPointFname, restartTli, restartSegNo);
+               XLByteToSeg(restartRedoPtr, restartSegNo, wal_segment_size);
+               XLogFileName(lastRestartPointFname, restartTli, restartSegNo,
+                                        wal_segment_size);
                /* we shouldn't need anything earlier than last restart point */
                Assert(strcmp(lastRestartPointFname, xlogfname) <= 0);
        }
        else
-               XLogFileName(lastRestartPointFname, 0, 0L);
+               XLogFileName(lastRestartPointFname, 0, 0L, wal_segment_size);
 
        /*
         * construct the command to be executed
@@ -289,17 +295,12 @@ RestoreArchivedFile(char *path, const char *xlogfname,
         * will perform an immediate shutdown when it sees us exiting
         * unexpectedly.
         *
-        * Per the Single Unix Spec, shells report exit status > 128 when a called
-        * command died on a signal.  Also, 126 and 127 are used to report
-        * problems such as an unfindable command; treat those as fatal errors
-        * too.
+        * We treat hard shell errors such as "command not found" as fatal, too.
         */
-       if (WIFSIGNALED(rc) && WTERMSIG(rc) == SIGTERM)
+       if (wait_result_is_signal(rc, SIGTERM))
                proc_exit(1);
 
-       signaled = WIFSIGNALED(rc) || WEXITSTATUS(rc) > 125;
-
-       ereport(signaled ? FATAL : DEBUG2,
+       ereport(wait_result_is_any_signal(rc, true) ? FATAL : DEBUG2,
                        (errmsg("could not restore file \"%s\" from archive: %s",
                                        xlogfname, wait_result_to_str(rc))));
 
@@ -327,7 +328,7 @@ not_available:
  * This is currently used for recovery_end_command and archive_cleanup_command.
  */
 void
-ExecuteRecoveryCommand(char *command, char *commandName, bool failOnSignal)
+ExecuteRecoveryCommand(const char *command, const char *commandName, bool failOnSignal)
 {
        char            xlogRecoveryCmd[MAXPGPATH];
        char            lastRestartPointFname[MAXPGPATH];
@@ -335,7 +336,6 @@ ExecuteRecoveryCommand(char *command, char *commandName, bool failOnSignal)
        char       *endp;
        const char *sp;
        int                     rc;
-       bool            signaled;
        XLogSegNo       restartSegNo;
        XLogRecPtr      restartRedoPtr;
        TimeLineID      restartTli;
@@ -348,8 +348,9 @@ ExecuteRecoveryCommand(char *command, char *commandName, bool failOnSignal)
         * archive, though there is no requirement to do so.
         */
        GetOldestRestartPoint(&restartRedoPtr, &restartTli);
-       XLByteToSeg(restartRedoPtr, restartSegNo);
-       XLogFileName(lastRestartPointFname, restartTli, restartSegNo);
+       XLByteToSeg(restartRedoPtr, restartSegNo, wal_segment_size);
+       XLogFileName(lastRestartPointFname, restartTli, restartSegNo,
+                                wal_segment_size);
 
        /*
         * construct the command to be executed
@@ -402,14 +403,11 @@ ExecuteRecoveryCommand(char *command, char *commandName, bool failOnSignal)
        {
                /*
                 * If the failure was due to any sort of signal, it's best to punt and
-                * abort recovery. See also detailed comments on signals in
-                * RestoreArchivedFile().
+                * abort recovery.  See comments in RestoreArchivedFile().
                 */
-               signaled = WIFSIGNALED(rc) || WEXITSTATUS(rc) > 125;
-
-               ereport((signaled && failOnSignal) ? FATAL : WARNING,
+               ereport((failOnSignal && wait_result_is_any_signal(rc, true)) ? FATAL : WARNING,
                /*------
-                  translator: First %s represents a recovery.conf parameter name like
+                  translator: First %s represents a postgresql.conf parameter name like
                  "recovery_end_command", the 2nd is the value of that parameter, the
                  third an already translated error message. */
                                (errmsg("%s \"%s\": %s", commandName,
@@ -421,10 +419,10 @@ ExecuteRecoveryCommand(char *command, char *commandName, bool failOnSignal)
 /*
  * A file was restored from the archive under a temporary filename (path),
  * and now we want to keep it. Rename it under the permanent filename in
- * in pg_xlog (xlogfname), replacing any existing file with the same name.
+ * pg_wal (xlogfname), replacing any existing file with the same name.
  */
 void
-KeepFileRestoredFromArchive(char *path, char *xlogfname)
+KeepFileRestoredFromArchive(const char *path, const char *xlogfname)
 {
        char            xlogfpath[MAXPGPATH];
        bool            reload = false;
@@ -470,17 +468,16 @@ KeepFileRestoredFromArchive(char *path, char *xlogfname)
                reload = true;
        }
 
-       if (rename(path, xlogfpath) < 0)
-               ereport(ERROR,
-                               (errcode_for_file_access(),
-                                errmsg("could not rename file \"%s\" to \"%s\": %m",
-                                               path, xlogfpath)));
+       durable_rename(path, xlogfpath, ERROR);
 
        /*
         * Create .done file forcibly to prevent the restored segment from being
         * archived again later.
         */
-       XLogArchiveForceDone(xlogfname);
+       if (XLogArchiveMode != ARCHIVE_MODE_ALWAYS)
+               XLogArchiveForceDone(xlogfname);
+       else
+               XLogArchiveNotify(xlogfname);
 
        /*
         * If the existing file was replaced, since walsenders might have it open,
@@ -549,7 +546,7 @@ XLogArchiveNotifySeg(XLogSegNo segno)
 {
        char            xlog[MAXFNAMELEN];
 
-       XLogFileName(xlog, ThisTimeLineID, segno);
+       XLogFileName(xlog, ThisTimeLineID, segno, wal_segment_size);
        XLogArchiveNotify(xlog);
 }
 
@@ -577,12 +574,7 @@ XLogArchiveForceDone(const char *xlog)
        StatusFilePath(archiveReady, xlog, ".ready");
        if (stat(archiveReady, &stat_buf) == 0)
        {
-               if (rename(archiveReady, archiveDone) < 0)
-                       ereport(WARNING,
-                                       (errcode_for_file_access(),
-                                        errmsg("could not rename file \"%s\" to \"%s\": %m",
-                                                       archiveReady, archiveDone)));
-
+               (void) durable_rename(archiveReady, archiveDone, WARNING);
                return;
        }
 
@@ -625,9 +617,16 @@ XLogArchiveCheckDone(const char *xlog)
 {
        char            archiveStatusPath[MAXPGPATH];
        struct stat stat_buf;
+       bool            inRecovery = RecoveryInProgress();
 
-       /* Always deletable if archiving is off */
-       if (!XLogArchivingActive())
+       /*
+        * The file is always deletable if archive_mode is "off".  On standbys
+        * archiving is disabled if archive_mode is "on", and enabled with
+        * "always".  On a primary, archiving is enabled if archive_mode is "on"
+        * or "always".
+        */
+       if (!((XLogArchivingActive() && !inRecovery) ||
+                 (XLogArchivingAlways() && inRecovery)))
                return true;
 
        /* First check for .done --- this means archiver is done with it */
@@ -694,6 +693,41 @@ XLogArchiveIsBusy(const char *xlog)
        return true;
 }
 
+/*
+ * XLogArchiveIsReadyOrDone
+ *
+ * Check to see if an XLOG segment file has a .ready or .done file.
+ * This is similar to XLogArchiveIsBusy(), but returns true if the file
+ * is already archived or is about to be archived.
+ *
+ * This is currently only used at recovery.  During normal operation this
+ * would be racy: the file might get removed or marked with .ready as we're
+ * checking it, or immediately after we return.
+ */
+bool
+XLogArchiveIsReadyOrDone(const char *xlog)
+{
+       char            archiveStatusPath[MAXPGPATH];
+       struct stat stat_buf;
+
+       /* First check for .done --- this means archiver is done with it */
+       StatusFilePath(archiveStatusPath, xlog, ".done");
+       if (stat(archiveStatusPath, &stat_buf) == 0)
+               return true;
+
+       /* check for .ready --- this means archiver is still busy with it */
+       StatusFilePath(archiveStatusPath, xlog, ".ready");
+       if (stat(archiveStatusPath, &stat_buf) == 0)
+               return true;
+
+       /* Race condition --- maybe archiver just finished, so recheck */
+       StatusFilePath(archiveStatusPath, xlog, ".done");
+       if (stat(archiveStatusPath, &stat_buf) == 0)
+               return true;
+
+       return false;
+}
+
 /*
  * XLogArchiveIsReady
  *