Fix pg_upgrade, broken by the xlogid/segno -> 64-bit int refactoring.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Tue, 26 Jun 2012 04:35:57 +0000 (07:35 +0300)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Tue, 26 Jun 2012 04:49:02 +0000 (07:49 +0300)
The xlogid + segno representation of a particular WAL segment doesn't make
much sense in pg_resetxlog anymore, now that we don't use that anywhere
else. Use the WAL filename instead, since that's a convenient way to name a
particular WAL segment.

I did this partially for pg_resetxlog in the original xlogid/segno -> uint64
patch, but I neglected pg_upgrade and the docs. This should now be more
complete.

contrib/pg_upgrade/controldata.c
contrib/pg_upgrade/pg_upgrade.c
contrib/pg_upgrade/pg_upgrade.h
doc/src/sgml/ref/pg_resetxlog.sgml
src/bin/pg_resetxlog/pg_resetxlog.c

index 6bffe549e59610846eaa391f63bb956ab05d37f3..5d5ab854ca8323d726359d9edfa52d162d8b2e65 100644 (file)
@@ -39,6 +39,7 @@ get_control_data(ClusterInfo *cluster, bool live_check)
        char       *p;
        bool            got_xid = false;
        bool            got_oid = false;
+       bool            got_nextxlogfile = false;
        bool            got_log_id = false;
        bool            got_log_seg = false;
        bool            got_tli = false;
@@ -61,6 +62,10 @@ get_control_data(ClusterInfo *cluster, bool live_check)
        char       *language = NULL;
        char       *lc_all = NULL;
        char       *lc_messages = NULL;
+       uint32          logid = 0;
+       uint32          segno = 0;
+       uint32          tli = 0;
+
 
        /*
         * Because we test the pg_resetxlog output as strings, it has to be in
@@ -166,6 +171,23 @@ get_control_data(ClusterInfo *cluster, bool live_check)
                        p++;                            /* removing ':' char */
                        cluster->controldata.cat_ver = str2uint(p);
                }
+               else if ((p = strstr(bufin, "First log segment after reset:")) != NULL)
+               {
+                       /* Skip the colon and any whitespace after it */
+                       p = strchr(p, ':');
+                       if (p == NULL || strlen(p) <= 1)
+                               pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
+                       p = strpbrk(p, "01234567890ABCDEF");
+                       if (p == NULL || strlen(p) <= 1)
+                               pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
+
+                       /* Make sure it looks like a valid WAL file name */
+                       if (strspn(p, "0123456789ABCDEF") != 24)
+                               pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
+
+                       strlcpy(cluster->controldata.nextxlogfile, p, 25);
+                       got_nextxlogfile = true;
+               }
                else if ((p = strstr(bufin, "First log file ID after reset:")) != NULL)
                {
                        p = strchr(p, ':');
@@ -174,7 +196,7 @@ get_control_data(ClusterInfo *cluster, bool live_check)
                                pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
 
                        p++;                            /* removing ':' char */
-                       cluster->controldata.logid = str2uint(p);
+                       logid = str2uint(p);
                        got_log_id = true;
                }
                else if ((p = strstr(bufin, "First log file segment after reset:")) != NULL)
@@ -185,7 +207,7 @@ get_control_data(ClusterInfo *cluster, bool live_check)
                                pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
 
                        p++;                            /* removing ':' char */
-                       cluster->controldata.nxtlogseg = str2uint(p);
+                       segno = str2uint(p);
                        got_log_seg = true;
                }
                else if ((p = strstr(bufin, "Latest checkpoint's TimeLineID:")) != NULL)
@@ -393,10 +415,25 @@ get_control_data(ClusterInfo *cluster, bool live_check)
        pg_free(lc_all);
        pg_free(lc_messages);
 
+       /*
+        * Before 9.3, pg_resetxlog reported the xlogid and segno of the first
+        * log file after reset as separate lines. Starting with 9.3, it reports
+        * the WAL file name. If the old cluster is older than 9.3, we construct
+        * the WAL file name from the xlogid and segno.
+        */
+       if (GET_MAJOR_VERSION(cluster->major_version) <= 902)
+       {
+               if (got_log_id && got_log_seg)
+               {
+                       snprintf(cluster->controldata.nextxlogfile, 24, "%08X%08X%08X",
+                                        tli, logid, segno);
+                       got_nextxlogfile = true;
+               }
+       }
+
        /* verify that we got all the mandatory pg_control data */
        if (!got_xid || !got_oid ||
-               (!live_check && !got_log_id) ||
-               (!live_check && !got_log_seg) ||
+               (!live_check && !got_nextxlogfile) ||
                !got_tli ||
                !got_align || !got_blocksz || !got_largesz || !got_walsz ||
                !got_walseg || !got_ident || !got_index || !got_toast ||
@@ -411,11 +448,8 @@ get_control_data(ClusterInfo *cluster, bool live_check)
                if (!got_oid)
                        pg_log(PG_REPORT, "  latest checkpoint next OID\n");
 
-               if (!live_check && !got_log_id)
-                       pg_log(PG_REPORT, "  first log file ID after reset\n");
-
-               if (!live_check && !got_log_seg)
-                       pg_log(PG_REPORT, "  first log file segment after reset\n");
+               if (!live_check && !got_nextxlogfile)
+                       pg_log(PG_REPORT, "  first WAL segment after reset\n");
 
                if (!got_tli)
                        pg_log(PG_REPORT, "  latest checkpoint timeline ID\n");
index 27ff8fc85a17c22f98b139cebcce333bb2d8af99..07006aed96f75e16d2b900ab49bf7797b3185a37 100644 (file)
@@ -354,11 +354,9 @@ copy_clog_xlog_xid(void)
        prep_status("Resetting WAL archives");
        exec_prog(true, true, UTILITY_LOG_FILE,
                          SYSTEMQUOTE
-                         "\"%s/pg_resetxlog\" -l %u,%u,%u \"%s\" >> \"%s\" 2>&1"
+                         "\"%s/pg_resetxlog\" -l %s \"%s\" >> \"%s\" 2>&1"
                          SYSTEMQUOTE, new_cluster.bindir,
-                         old_cluster.controldata.chkpnt_tli,
-                         old_cluster.controldata.logid,
-                         old_cluster.controldata.nxtlogseg,
+                         old_cluster.controldata.nextxlogfile,
                          new_cluster.pgdata, UTILITY_LOG_FILE);
        check_ok();
 }
index 8b2062181fdfdf6c2fe5dbe9c53e65a4ce4c9f57..3274227a0a3d516f8ae2b06bfa9fe0152d497e69 100644 (file)
@@ -168,8 +168,7 @@ typedef struct
 {
        uint32          ctrl_ver;
        uint32          cat_ver;
-       uint32          logid;
-       uint32          nxtlogseg;
+       char            nextxlogfile[25];
        uint32          chkpnt_tli;
        uint32          chkpnt_nxtxid;
        uint32          chkpnt_nxtoid;
index e98ae4044599f46de0250ce7cd59b282bfa315fb..27b9ab41d0f5f06939778acdc5782ef514ca4c2f 100644 (file)
@@ -131,13 +131,8 @@ PostgreSQL documentation
       the directory <filename>pg_xlog</> under the data directory.
       These names are also in hexadecimal and have three parts.  The first
       part is the <quote>timeline ID</> and should usually be kept the same.
-      Do not choose a value larger than 255 (<literal>0xFF</>) for the third
-      part; instead increment the second part and reset the third part to 0.
       For example, if <filename>00000001000000320000004A</> is the
-      largest entry in <filename>pg_xlog</>, <literal>-l 0x1,0x32,0x4B</> will
-      work; but if the largest entry is
-      <filename>000000010000003A000000FF</>, choose <literal>-l 0x1,0x3B,0x0</>
-      or more.
+      largest entry in <filename>pg_xlog</>, use <literal>-l 00000001000000320000004B</> or higher.
      </para>
 
      <note>
index 3e337ee902ea12907845ef2b82a4afbba1c4d656..d5d89ec3ad7031ed7a28d659b8dc144e521f19ff 100644 (file)
@@ -86,13 +86,9 @@ main(int argc, char *argv[])
        Oid                     set_oid = 0;
        MultiXactId set_mxid = 0;
        MultiXactOffset set_mxoff = (MultiXactOffset) -1;
-       uint32          minXlogTli = 0,
-                               minXlogId = 0,
-                               minXlogSeg = 0;
+       uint32          minXlogTli = 0;
        XLogSegNo       minXlogSegNo = 0;
        char       *endptr;
-       char       *endptr2;
-       char       *endptr3;
        char       *DataDir;
        int                     fd;
        char            path[MAXPGPATH];
@@ -204,28 +200,13 @@ main(int argc, char *argv[])
                                break;
 
                        case 'l':
-                               minXlogTli = strtoul(optarg, &endptr, 0);
-                               if (endptr == optarg || *endptr != ',')
+                               if (strspn(optarg, "01234567890ABCDEFabcdef") != 24)
                                {
                                        fprintf(stderr, _("%s: invalid argument for option -l\n"), progname);
                                        fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
                                        exit(1);
                                }
-                               minXlogId = strtoul(endptr + 1, &endptr2, 0);
-                               if (endptr2 == endptr + 1 || *endptr2 != ',')
-                               {
-                                       fprintf(stderr, _("%s: invalid argument for option -l\n"), progname);
-                                       fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
-                                       exit(1);
-                               }
-                               minXlogSeg = strtoul(endptr2 + 1, &endptr3, 0);
-                               if (endptr3 == endptr2 + 1 || *endptr3 != '\0')
-                               {
-                                       fprintf(stderr, _("%s: invalid argument for option -l\n"), progname);
-                                       fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
-                                       exit(1);
-                               }
-                               minXlogSegNo = (uint64) minXlogId * XLogSegmentsPerXLogId + minXlogSeg;
+                               XLogFromFileName(optarg, &minXlogTli, &minXlogSegNo);
                                break;
 
                        default:
@@ -1013,7 +994,7 @@ usage(void)
        printf(_("Options:\n"));
        printf(_("  -e XIDEPOCH      set next transaction ID epoch\n"));
        printf(_("  -f               force update to be done\n"));
-       printf(_("  -l TLI,FILE,SEG  force minimum WAL starting location for new transaction log\n"));
+       printf(_("  -l xlogfile      force minimum WAL starting location for new transaction log\n"));
        printf(_("  -m XID           set next multitransaction ID\n"));
        printf(_("  -n               no update, just show extracted control values (for testing)\n"));
        printf(_("  -o OID           set next OID\n"));