new_timeline02.diff

text/plain

Filename: new_timeline02.diff
Type: text/plain
Part: 0
Message: [v9.2] Start new timeline for PITR

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: unified
File+
doc/src/sgml/recovery-config.sgml 26 0
src/backend/access/transam/recovery.conf.sample 8 0
src/backend/access/transam/xlog.c 36 4
diff --git a/doc/src/sgml/recovery-config.sgml b/doc/src/sgml/recovery-config.sgml
index de60905..0df3977 100644
--- a/doc/src/sgml/recovery-config.sgml
+++ b/doc/src/sgml/recovery-config.sgml
@@ -73,6 +73,32 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"'  # Windows
       </listitem>
      </varlistentry>
 
+     <varlistentry id="create-new-timeline" xreflabel="create_new_timeline">
+      <term><varname>create_new_timeline</varname> (<type>boolean</type>)</term>
+      <indexterm>
+        <primary><varname>create_new_timeline</varname> recovery parameter</primary>
+      </indexterm>
+      <listitem>
+       <para>
+        If set, create a new timeline unconditionally.  This parameter is
+        used in archive recovery scenarios where filesystem snapshots
+        are used.
+       </para>
+       <para>
+        If set to true, this overrides any recover_target that is
+        specified in the recovery.conf file.  Instead, it will perform
+        a crash recovery, then switch to a new timeline.
+       </para>
+       <para>
+        When using create_new_timeline, the restore_command should be
+        the same as for a regular point-in-time recovery.  In this
+        case it only gets used to retrieve the timeline history files
+        from the archive disk, so that postgres can correctly choose a
+        new timeline.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry id="archive-cleanup-command" xreflabel="archive_cleanup_command">
       <term><varname>archive_cleanup_command</varname> (<type>string</type>)</term>
       <indexterm>
diff --git a/src/backend/access/transam/recovery.conf.sample b/src/backend/access/transam/recovery.conf.sample
index 229c749..e962938 100644
--- a/src/backend/access/transam/recovery.conf.sample
+++ b/src/backend/access/transam/recovery.conf.sample
@@ -44,6 +44,14 @@
 #restore_command = ''		# e.g. 'cp /mnt/server/archivedir/%f %p'
 #
 #
+# create_new_timeline
+#
+# specifies whether we are starting a new timeline for recovery.  This
+# is useful in scenarios using filesystem snapshots.
+#
+#create_new_timeline = false
+#
+#
 # archive_cleanup_command
 #
 # specifies an optional shell command to execute at every restartpoint.
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 5c3ca47..ee43f44 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -201,6 +201,9 @@ static bool StandbyMode = false;
 static char *PrimaryConnInfo = NULL;
 static char *TriggerFile = NULL;
 
+/* option, possibly overridden by recovery.conf, for creating a new timeline for crash recovery */
+static bool createNewTimeLine = false;
+
 /* if recoveryStopsHere returns true, it saves actual stop xid/time/name here */
 static TransactionId recoveryStopXid;
 static TimestampTz recoveryStopTime;
@@ -5385,6 +5388,15 @@ readRecoveryCommandFile(void)
 					(errmsg("trigger_file = '%s'",
 							TriggerFile)));
 		}
+		else if (strcmp(item->name, "create_new_timeline") == 0)
+		{
+			if (!parse_bool(item->value, &createNewTimeLine))
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+						 errmsg("parameter \"%s\" requires a Boolean value", item->name)));
+			ereport(DEBUG2,
+					(errmsg("create_new_timeline = '%s'", item->value)));
+		}
 		else
 			ereport(FATAL,
 					(errmsg("unrecognized recovery parameter \"%s\"",
@@ -5410,8 +5422,14 @@ readRecoveryCommandFile(void)
 							RECOVERY_COMMAND_FILE)));
 	}
 
-	/* Enable fetching from archive recovery area */
-	InArchiveRecovery = true;
+	/*
+	 * Check whether we're creating a new timeline.
+	 */
+	if (createNewTimeLine)
+		InRecovery = true;
+	else
+		/* Enable fetching from archive recovery area */
+		InArchiveRecovery = true;
 
 	/*
 	 * If user specified recovery_target_timeline, validate it or compute the
@@ -5524,8 +5542,15 @@ exitArchiveRecovery(TimeLineID endTLI, uint32 endLogId, uint32 endLogSeg)
 		{
 			XLogFileCopy(endLogId, endLogSeg,
 						 endTLI, endLogId, endLogSeg);
-
-			if (XLogArchivingActive())
+			/*
+			 * The PITR script should have set the '.done' flag for
+			 * this file, so we don't want to archive it again, as the
+			 * archive version is newer.
+			 *
+			 * If the '.done' flag was not set, the archiver will
+			 * eventually handle it.
+			 */
+			if (XLogArchivingActive() && !createNewTimeLine)
 			{
 				XLogFileName(xlogpath, endTLI, endLogId, endLogSeg);
 				XLogArchiveNotify(xlogpath);
@@ -6676,6 +6701,13 @@ StartupXLOG(void)
 				ereport(FATAL,
 					  (errmsg("WAL ends before consistent recovery point")));
 		}
+		
+		/*
+		 * Check whether we're creating a new timeline, and if we are,
+		 * put us into archive recovery mode.
+		 */
+		if (createNewTimeLine)
+			InArchiveRecovery = true;
 	}
 
 	/*