Commit 038f3a05 authored by Heikki Linnakangas's avatar Heikki Linnakangas

Fix pg_upgrade, broken by the xlogid/segno -> 64-bit int refactoring.

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.
parent 8a504a36
...@@ -39,6 +39,7 @@ get_control_data(ClusterInfo *cluster, bool live_check) ...@@ -39,6 +39,7 @@ get_control_data(ClusterInfo *cluster, bool live_check)
char *p; char *p;
bool got_xid = false; bool got_xid = false;
bool got_oid = false; bool got_oid = false;
bool got_nextxlogfile = false;
bool got_log_id = false; bool got_log_id = false;
bool got_log_seg = false; bool got_log_seg = false;
bool got_tli = false; bool got_tli = false;
...@@ -61,6 +62,10 @@ get_control_data(ClusterInfo *cluster, bool live_check) ...@@ -61,6 +62,10 @@ get_control_data(ClusterInfo *cluster, bool live_check)
char *language = NULL; char *language = NULL;
char *lc_all = NULL; char *lc_all = NULL;
char *lc_messages = 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 * 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) ...@@ -166,6 +171,23 @@ get_control_data(ClusterInfo *cluster, bool live_check)
p++; /* removing ':' char */ p++; /* removing ':' char */
cluster->controldata.cat_ver = str2uint(p); 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) else if ((p = strstr(bufin, "First log file ID after reset:")) != NULL)
{ {
p = strchr(p, ':'); p = strchr(p, ':');
...@@ -174,7 +196,7 @@ get_control_data(ClusterInfo *cluster, bool live_check) ...@@ -174,7 +196,7 @@ get_control_data(ClusterInfo *cluster, bool live_check)
pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__); pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
p++; /* removing ':' char */ p++; /* removing ':' char */
cluster->controldata.logid = str2uint(p); logid = str2uint(p);
got_log_id = true; got_log_id = true;
} }
else if ((p = strstr(bufin, "First log file segment after reset:")) != NULL) else if ((p = strstr(bufin, "First log file segment after reset:")) != NULL)
...@@ -185,7 +207,7 @@ get_control_data(ClusterInfo *cluster, bool live_check) ...@@ -185,7 +207,7 @@ get_control_data(ClusterInfo *cluster, bool live_check)
pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__); pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
p++; /* removing ':' char */ p++; /* removing ':' char */
cluster->controldata.nxtlogseg = str2uint(p); segno = str2uint(p);
got_log_seg = true; got_log_seg = true;
} }
else if ((p = strstr(bufin, "Latest checkpoint's TimeLineID:")) != NULL) else if ((p = strstr(bufin, "Latest checkpoint's TimeLineID:")) != NULL)
...@@ -393,10 +415,25 @@ get_control_data(ClusterInfo *cluster, bool live_check) ...@@ -393,10 +415,25 @@ get_control_data(ClusterInfo *cluster, bool live_check)
pg_free(lc_all); pg_free(lc_all);
pg_free(lc_messages); 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 */ /* verify that we got all the mandatory pg_control data */
if (!got_xid || !got_oid || if (!got_xid || !got_oid ||
(!live_check && !got_log_id) || (!live_check && !got_nextxlogfile) ||
(!live_check && !got_log_seg) ||
!got_tli || !got_tli ||
!got_align || !got_blocksz || !got_largesz || !got_walsz || !got_align || !got_blocksz || !got_largesz || !got_walsz ||
!got_walseg || !got_ident || !got_index || !got_toast || !got_walseg || !got_ident || !got_index || !got_toast ||
...@@ -411,11 +448,8 @@ get_control_data(ClusterInfo *cluster, bool live_check) ...@@ -411,11 +448,8 @@ get_control_data(ClusterInfo *cluster, bool live_check)
if (!got_oid) if (!got_oid)
pg_log(PG_REPORT, " latest checkpoint next OID\n"); pg_log(PG_REPORT, " latest checkpoint next OID\n");
if (!live_check && !got_log_id) if (!live_check && !got_nextxlogfile)
pg_log(PG_REPORT, " first log file ID after reset\n"); pg_log(PG_REPORT, " first WAL segment after reset\n");
if (!live_check && !got_log_seg)
pg_log(PG_REPORT, " first log file segment after reset\n");
if (!got_tli) if (!got_tli)
pg_log(PG_REPORT, " latest checkpoint timeline ID\n"); pg_log(PG_REPORT, " latest checkpoint timeline ID\n");
......
...@@ -354,11 +354,9 @@ copy_clog_xlog_xid(void) ...@@ -354,11 +354,9 @@ copy_clog_xlog_xid(void)
prep_status("Resetting WAL archives"); prep_status("Resetting WAL archives");
exec_prog(true, true, UTILITY_LOG_FILE, exec_prog(true, true, UTILITY_LOG_FILE,
SYSTEMQUOTE 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, SYSTEMQUOTE, new_cluster.bindir,
old_cluster.controldata.chkpnt_tli, old_cluster.controldata.nextxlogfile,
old_cluster.controldata.logid,
old_cluster.controldata.nxtlogseg,
new_cluster.pgdata, UTILITY_LOG_FILE); new_cluster.pgdata, UTILITY_LOG_FILE);
check_ok(); check_ok();
} }
......
...@@ -168,8 +168,7 @@ typedef struct ...@@ -168,8 +168,7 @@ typedef struct
{ {
uint32 ctrl_ver; uint32 ctrl_ver;
uint32 cat_ver; uint32 cat_ver;
uint32 logid; char nextxlogfile[25];
uint32 nxtlogseg;
uint32 chkpnt_tli; uint32 chkpnt_tli;
uint32 chkpnt_nxtxid; uint32 chkpnt_nxtxid;
uint32 chkpnt_nxtoid; uint32 chkpnt_nxtoid;
......
...@@ -131,13 +131,8 @@ PostgreSQL documentation ...@@ -131,13 +131,8 @@ PostgreSQL documentation
the directory <filename>pg_xlog</> under the data directory. the directory <filename>pg_xlog</> under the data directory.
These names are also in hexadecimal and have three parts. The first 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. 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 For example, if <filename>00000001000000320000004A</> is the
largest entry in <filename>pg_xlog</>, <literal>-l 0x1,0x32,0x4B</> will largest entry in <filename>pg_xlog</>, use <literal>-l 00000001000000320000004B</> or higher.
work; but if the largest entry is
<filename>000000010000003A000000FF</>, choose <literal>-l 0x1,0x3B,0x0</>
or more.
</para> </para>
<note> <note>
......
...@@ -86,13 +86,9 @@ main(int argc, char *argv[]) ...@@ -86,13 +86,9 @@ main(int argc, char *argv[])
Oid set_oid = 0; Oid set_oid = 0;
MultiXactId set_mxid = 0; MultiXactId set_mxid = 0;
MultiXactOffset set_mxoff = (MultiXactOffset) -1; MultiXactOffset set_mxoff = (MultiXactOffset) -1;
uint32 minXlogTli = 0, uint32 minXlogTli = 0;
minXlogId = 0,
minXlogSeg = 0;
XLogSegNo minXlogSegNo = 0; XLogSegNo minXlogSegNo = 0;
char *endptr; char *endptr;
char *endptr2;
char *endptr3;
char *DataDir; char *DataDir;
int fd; int fd;
char path[MAXPGPATH]; char path[MAXPGPATH];
...@@ -204,28 +200,13 @@ main(int argc, char *argv[]) ...@@ -204,28 +200,13 @@ main(int argc, char *argv[])
break; break;
case 'l': case 'l':
minXlogTli = strtoul(optarg, &endptr, 0); if (strspn(optarg, "01234567890ABCDEFabcdef") != 24)
if (endptr == optarg || *endptr != ',')
{ {
fprintf(stderr, _("%s: invalid argument for option -l\n"), progname); fprintf(stderr, _("%s: invalid argument for option -l\n"), progname);
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
exit(1); exit(1);
} }
minXlogId = strtoul(endptr + 1, &endptr2, 0); XLogFromFileName(optarg, &minXlogTli, &minXlogSegNo);
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;
break; break;
default: default:
...@@ -1013,7 +994,7 @@ usage(void) ...@@ -1013,7 +994,7 @@ usage(void)
printf(_("Options:\n")); printf(_("Options:\n"));
printf(_(" -e XIDEPOCH set next transaction ID epoch\n")); printf(_(" -e XIDEPOCH set next transaction ID epoch\n"));
printf(_(" -f force update to be done\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(_(" -m XID set next multitransaction ID\n"));
printf(_(" -n no update, just show extracted control values (for testing)\n")); printf(_(" -n no update, just show extracted control values (for testing)\n"));
printf(_(" -o OID set next OID\n")); printf(_(" -o OID set next OID\n"));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment