Folks,

The nice people at VMware, where I work, have come up with a small
patch to allow PITR to create a new timeline.  This is useful in cases
where you're using filesystem snapshots of $PGDATA which may be old.

PFA a patch implementing and documenting same :)

Cheers,
David.
-- 
David Fetter <da...@fetter.org> http://fetter.org/
Phone: +1 415 235 3778  AIM: dfetter666  Yahoo!: dfetter
Skype: davidfetter      XMPP: david.fet...@gmail.com
iCal: webcal://www.tripit.com/feed/ical/people/david74/tripit.ics

Remember to vote!
Consider donating to Postgres: http://www.postgresql.org/about/donate
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;
        }
 
        /*
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to