diff --git a/contrib/pg_upgrade/controldata.c b/contrib/pg_upgrade/controldata.c index 6bffe549e5..5d5ab854ca 100644 --- a/contrib/pg_upgrade/controldata.c +++ b/contrib/pg_upgrade/controldata.c @@ -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"); diff --git a/contrib/pg_upgrade/pg_upgrade.c b/contrib/pg_upgrade/pg_upgrade.c index 27ff8fc85a..07006aed96 100644 --- a/contrib/pg_upgrade/pg_upgrade.c +++ b/contrib/pg_upgrade/pg_upgrade.c @@ -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(); } diff --git a/contrib/pg_upgrade/pg_upgrade.h b/contrib/pg_upgrade/pg_upgrade.h index 8b2062181f..3274227a0a 100644 --- a/contrib/pg_upgrade/pg_upgrade.h +++ b/contrib/pg_upgrade/pg_upgrade.h @@ -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; diff --git a/doc/src/sgml/ref/pg_resetxlog.sgml b/doc/src/sgml/ref/pg_resetxlog.sgml index e98ae40445..27b9ab41d0 100644 --- a/doc/src/sgml/ref/pg_resetxlog.sgml +++ b/doc/src/sgml/ref/pg_resetxlog.sgml @@ -131,13 +131,8 @@ PostgreSQL documentation the directory pg_xlog under the data directory. These names are also in hexadecimal and have three parts. The first part is the timeline ID and should usually be kept the same. - Do not choose a value larger than 255 (0xFF) for the third - part; instead increment the second part and reset the third part to 0. For example, if 00000001000000320000004A is the - largest entry in pg_xlog, -l 0x1,0x32,0x4B will - work; but if the largest entry is - 000000010000003A000000FF, choose -l 0x1,0x3B,0x0 - or more. + largest entry in pg_xlog, use -l 00000001000000320000004B or higher. diff --git a/src/bin/pg_resetxlog/pg_resetxlog.c b/src/bin/pg_resetxlog/pg_resetxlog.c index 3e337ee902..d5d89ec3ad 100644 --- a/src/bin/pg_resetxlog/pg_resetxlog.c +++ b/src/bin/pg_resetxlog/pg_resetxlog.c @@ -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"));