]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
pg_rewind: Don't error if the two clusters are already on the same timeline
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 14 Dec 2015 23:21:42 +0000 (18:21 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 14 Dec 2015 23:21:42 +0000 (18:21 -0500)
This previously resulted in an error and a nonzero exit status, but
after discussion this should rather be a noop with a zero exit status.

This is a back-patch of commit 6b34e5563849edc12896bf5754e8fe7b88012697,
plus two changes from commit e50cda78404d6400b1326a996a4fabb144871151
that teach pg_rewind to allow the initial control file states to be
DB_SHUTDOWNED_IN_RECOVERY as well as DB_SHUTDOWNED.  That's necessary
to get the additional regression test case to pass, and the old behavior
seems like rather a foot-gun anyway.

Peter Eisentraut and Tom Lane

src/bin/pg_rewind/pg_rewind.c
src/bin/pg_rewind/t/005_same_timeline.pl [new file with mode: 0644]

index a2d9ca36aa1f06d459b84f07e271c8ad6fb61fea..cf5f8487f4b2a04b3fbad0a882e81cae11534469 100644 (file)
@@ -212,40 +212,45 @@ main(int argc, char **argv)
         * do.
         */
        if (ControlFile_target.checkPointCopy.ThisTimeLineID == ControlFile_source.checkPointCopy.ThisTimeLineID)
-               pg_fatal("source and target cluster are on the same timeline\n");
-
-       findCommonAncestorTimeline(&divergerec, &lastcommontli);
-       printf(_("servers diverged at WAL position %X/%X on timeline %u\n"),
-                  (uint32) (divergerec >> 32), (uint32) divergerec, lastcommontli);
-
-       /*
-        * Check for the possibility that the target is in fact a direct ancestor
-        * of the source. In that case, there is no divergent history in the
-        * target that needs rewinding.
-        */
-       if (ControlFile_target.checkPoint >= divergerec)
        {
-               rewind_needed = true;
+               printf(_("source and target cluster are on the same timeline\n"));
+               rewind_needed = false;
        }
        else
        {
-               XLogRecPtr      chkptendrec;
-
-               /* Read the checkpoint record on the target to see where it ends. */
-               chkptendrec = readOneRecord(datadir_target,
-                                                                       ControlFile_target.checkPoint,
-                                                  ControlFile_target.checkPointCopy.ThisTimeLineID);
+               findCommonAncestorTimeline(&divergerec, &lastcommontli);
+               printf(_("servers diverged at WAL position %X/%X on timeline %u\n"),
+                          (uint32) (divergerec >> 32), (uint32) divergerec, lastcommontli);
 
                /*
-                * If the histories diverged exactly at the end of the shutdown
-                * checkpoint record on the target, there are no WAL records in the
-                * target that don't belong in the source's history, and no rewind is
-                * needed.
+                * Check for the possibility that the target is in fact a direct ancestor
+                * of the source. In that case, there is no divergent history in the
+                * target that needs rewinding.
                 */
-               if (chkptendrec == divergerec)
-                       rewind_needed = false;
-               else
+               if (ControlFile_target.checkPoint >= divergerec)
+               {
                        rewind_needed = true;
+               }
+               else
+               {
+                       XLogRecPtr      chkptendrec;
+
+                       /* Read the checkpoint record on the target to see where it ends. */
+                       chkptendrec = readOneRecord(datadir_target,
+                                                                               ControlFile_target.checkPoint,
+                                                  ControlFile_target.checkPointCopy.ThisTimeLineID);
+
+                       /*
+                        * If the histories diverged exactly at the end of the shutdown
+                        * checkpoint record on the target, there are no WAL records in the
+                        * target that don't belong in the source's history, and no rewind is
+                        * needed.
+                        */
+                       if (chkptendrec == divergerec)
+                               rewind_needed = false;
+                       else
+                               rewind_needed = true;
+               }
        }
 
        if (!rewind_needed)
@@ -374,10 +379,11 @@ sanityChecks(void)
        /*
         * Target cluster better not be running. This doesn't guard against
         * someone starting the cluster concurrently. Also, this is probably more
-        * strict than necessary; it's OK if the master was not shut down cleanly,
-        * as long as it isn't running at the moment.
+        * strict than necessary; it's OK if the target node was not shut down
+        * cleanly, as long as it isn't running at the moment.
         */
-       if (ControlFile_target.state != DB_SHUTDOWNED)
+       if (ControlFile_target.state != DB_SHUTDOWNED &&
+               ControlFile_target.state != DB_SHUTDOWNED_IN_RECOVERY)
                pg_fatal("target server must be shut down cleanly\n");
 
        /*
@@ -385,7 +391,9 @@ sanityChecks(void)
         * server is shut down. There isn't any very strong reason for this
         * limitation, but better safe than sorry.
         */
-       if (datadir_source && ControlFile_source.state != DB_SHUTDOWNED)
+       if (datadir_source &&
+               ControlFile_source.state != DB_SHUTDOWNED &&
+               ControlFile_source.state != DB_SHUTDOWNED_IN_RECOVERY)
                pg_fatal("source data directory must be shut down cleanly\n");
 }
 
diff --git a/src/bin/pg_rewind/t/005_same_timeline.pl b/src/bin/pg_rewind/t/005_same_timeline.pl
new file mode 100644 (file)
index 0000000..8ca4426
--- /dev/null
@@ -0,0 +1,14 @@
+use strict;
+use warnings;
+use TestLib;
+use Test::More tests => 1;
+
+use RewindTest;
+
+# Test that running pg_rewind if the two clusters are on the same
+# timeline runs successfully.
+
+RewindTest::setup_cluster();
+RewindTest::start_master();
+RewindTest::create_standby();
+RewindTest::run_pg_rewind('local');