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.
This commit is contained in:
Heikki Linnakangas 2012-06-26 07:35:57 +03:00
parent 8a504a3639
commit 038f3a0509
5 changed files with 51 additions and 44 deletions

View File

@ -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)
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)
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)
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)
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)
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)
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");

View File

@ -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();
} }

View File

@ -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;

View File

@ -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>

View File

@ -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[])
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)
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"));