Skip to content

Commit 038f3a0

Browse files
committed
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.
1 parent 8a504a3 commit 038f3a0

File tree

5 files changed

+51
-44
lines changed

5 files changed

+51
-44
lines changed

contrib/pg_upgrade/controldata.c

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ get_control_data(ClusterInfo *cluster, bool live_check)
3939
char *p;
4040
bool got_xid = false;
4141
bool got_oid = false;
42+
bool got_nextxlogfile = false;
4243
bool got_log_id = false;
4344
bool got_log_seg = false;
4445
bool got_tli = false;
@@ -61,6 +62,10 @@ get_control_data(ClusterInfo *cluster, bool live_check)
6162
char *language = NULL;
6263
char *lc_all = NULL;
6364
char *lc_messages = NULL;
65+
uint32 logid = 0;
66+
uint32 segno = 0;
67+
uint32 tli = 0;
68+
6469

6570
/*
6671
* 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)
166171
p++; /* removing ':' char */
167172
cluster->controldata.cat_ver = str2uint(p);
168173
}
174+
else if ((p = strstr(bufin, "First log segment after reset:")) != NULL)
175+
{
176+
/* Skip the colon and any whitespace after it */
177+
p = strchr(p, ':');
178+
if (p == NULL || strlen(p) <= 1)
179+
pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
180+
p = strpbrk(p, "01234567890ABCDEF");
181+
if (p == NULL || strlen(p) <= 1)
182+
pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
183+
184+
/* Make sure it looks like a valid WAL file name */
185+
if (strspn(p, "0123456789ABCDEF") != 24)
186+
pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
187+
188+
strlcpy(cluster->controldata.nextxlogfile, p, 25);
189+
got_nextxlogfile = true;
190+
}
169191
else if ((p = strstr(bufin, "First log file ID after reset:")) != NULL)
170192
{
171193
p = strchr(p, ':');
@@ -174,7 +196,7 @@ get_control_data(ClusterInfo *cluster, bool live_check)
174196
pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
175197

176198
p++; /* removing ':' char */
177-
cluster->controldata.logid = str2uint(p);
199+
logid = str2uint(p);
178200
got_log_id = true;
179201
}
180202
else if ((p = strstr(bufin, "First log file segment after reset:")) != NULL)
@@ -185,7 +207,7 @@ get_control_data(ClusterInfo *cluster, bool live_check)
185207
pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
186208

187209
p++; /* removing ':' char */
188-
cluster->controldata.nxtlogseg = str2uint(p);
210+
segno = str2uint(p);
189211
got_log_seg = true;
190212
}
191213
else if ((p = strstr(bufin, "Latest checkpoint's TimeLineID:")) != NULL)
@@ -393,10 +415,25 @@ get_control_data(ClusterInfo *cluster, bool live_check)
393415
pg_free(lc_all);
394416
pg_free(lc_messages);
395417

418+
/*
419+
* Before 9.3, pg_resetxlog reported the xlogid and segno of the first
420+
* log file after reset as separate lines. Starting with 9.3, it reports
421+
* the WAL file name. If the old cluster is older than 9.3, we construct
422+
* the WAL file name from the xlogid and segno.
423+
*/
424+
if (GET_MAJOR_VERSION(cluster->major_version) <= 902)
425+
{
426+
if (got_log_id && got_log_seg)
427+
{
428+
snprintf(cluster->controldata.nextxlogfile, 24, "%08X%08X%08X",
429+
tli, logid, segno);
430+
got_nextxlogfile = true;
431+
}
432+
}
433+
396434
/* verify that we got all the mandatory pg_control data */
397435
if (!got_xid || !got_oid ||
398-
(!live_check && !got_log_id) ||
399-
(!live_check && !got_log_seg) ||
436+
(!live_check && !got_nextxlogfile) ||
400437
!got_tli ||
401438
!got_align || !got_blocksz || !got_largesz || !got_walsz ||
402439
!got_walseg || !got_ident || !got_index || !got_toast ||
@@ -411,11 +448,8 @@ get_control_data(ClusterInfo *cluster, bool live_check)
411448
if (!got_oid)
412449
pg_log(PG_REPORT, " latest checkpoint next OID\n");
413450

414-
if (!live_check && !got_log_id)
415-
pg_log(PG_REPORT, " first log file ID after reset\n");
416-
417-
if (!live_check && !got_log_seg)
418-
pg_log(PG_REPORT, " first log file segment after reset\n");
451+
if (!live_check && !got_nextxlogfile)
452+
pg_log(PG_REPORT, " first WAL segment after reset\n");
419453

420454
if (!got_tli)
421455
pg_log(PG_REPORT, " latest checkpoint timeline ID\n");

contrib/pg_upgrade/pg_upgrade.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -354,11 +354,9 @@ copy_clog_xlog_xid(void)
354354
prep_status("Resetting WAL archives");
355355
exec_prog(true, true, UTILITY_LOG_FILE,
356356
SYSTEMQUOTE
357-
"\"%s/pg_resetxlog\" -l %u,%u,%u \"%s\" >> \"%s\" 2>&1"
357+
"\"%s/pg_resetxlog\" -l %s \"%s\" >> \"%s\" 2>&1"
358358
SYSTEMQUOTE, new_cluster.bindir,
359-
old_cluster.controldata.chkpnt_tli,
360-
old_cluster.controldata.logid,
361-
old_cluster.controldata.nxtlogseg,
359+
old_cluster.controldata.nextxlogfile,
362360
new_cluster.pgdata, UTILITY_LOG_FILE);
363361
check_ok();
364362
}

contrib/pg_upgrade/pg_upgrade.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,7 @@ typedef struct
168168
{
169169
uint32 ctrl_ver;
170170
uint32 cat_ver;
171-
uint32 logid;
172-
uint32 nxtlogseg;
171+
char nextxlogfile[25];
173172
uint32 chkpnt_tli;
174173
uint32 chkpnt_nxtxid;
175174
uint32 chkpnt_nxtoid;

doc/src/sgml/ref/pg_resetxlog.sgml

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,13 +131,8 @@ PostgreSQL documentation
131131
the directory <filename>pg_xlog</> under the data directory.
132132
These names are also in hexadecimal and have three parts. The first
133133
part is the <quote>timeline ID</> and should usually be kept the same.
134-
Do not choose a value larger than 255 (<literal>0xFF</>) for the third
135-
part; instead increment the second part and reset the third part to 0.
136134
For example, if <filename>00000001000000320000004A</> is the
137-
largest entry in <filename>pg_xlog</>, <literal>-l 0x1,0x32,0x4B</> will
138-
work; but if the largest entry is
139-
<filename>000000010000003A000000FF</>, choose <literal>-l 0x1,0x3B,0x0</>
140-
or more.
135+
largest entry in <filename>pg_xlog</>, use <literal>-l 00000001000000320000004B</> or higher.
141136
</para>
142137

143138
<note>

src/bin/pg_resetxlog/pg_resetxlog.c

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,9 @@ main(int argc, char *argv[])
8686
Oid set_oid = 0;
8787
MultiXactId set_mxid = 0;
8888
MultiXactOffset set_mxoff = (MultiXactOffset) -1;
89-
uint32 minXlogTli = 0,
90-
minXlogId = 0,
91-
minXlogSeg = 0;
89+
uint32 minXlogTli = 0;
9290
XLogSegNo minXlogSegNo = 0;
9391
char *endptr;
94-
char *endptr2;
95-
char *endptr3;
9692
char *DataDir;
9793
int fd;
9894
char path[MAXPGPATH];
@@ -204,28 +200,13 @@ main(int argc, char *argv[])
204200
break;
205201

206202
case 'l':
207-
minXlogTli = strtoul(optarg, &endptr, 0);
208-
if (endptr == optarg || *endptr != ',')
203+
if (strspn(optarg, "01234567890ABCDEFabcdef") != 24)
209204
{
210205
fprintf(stderr, _("%s: invalid argument for option -l\n"), progname);
211206
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
212207
exit(1);
213208
}
214-
minXlogId = strtoul(endptr + 1, &endptr2, 0);
215-
if (endptr2 == endptr + 1 || *endptr2 != ',')
216-
{
217-
fprintf(stderr, _("%s: invalid argument for option -l\n"), progname);
218-
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
219-
exit(1);
220-
}
221-
minXlogSeg = strtoul(endptr2 + 1, &endptr3, 0);
222-
if (endptr3 == endptr2 + 1 || *endptr3 != '\0')
223-
{
224-
fprintf(stderr, _("%s: invalid argument for option -l\n"), progname);
225-
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
226-
exit(1);
227-
}
228-
minXlogSegNo = (uint64) minXlogId * XLogSegmentsPerXLogId + minXlogSeg;
209+
XLogFromFileName(optarg, &minXlogTli, &minXlogSegNo);
229210
break;
230211

231212
default:
@@ -1013,7 +994,7 @@ usage(void)
1013994
printf(_("Options:\n"));
1014995
printf(_(" -e XIDEPOCH set next transaction ID epoch\n"));
1015996
printf(_(" -f force update to be done\n"));
1016-
printf(_(" -l TLI,FILE,SEG force minimum WAL starting location for new transaction log\n"));
997+
printf(_(" -l xlogfile force minimum WAL starting location for new transaction log\n"));
1017998
printf(_(" -m XID set next multitransaction ID\n"));
1018999
printf(_(" -n no update, just show extracted control values (for testing)\n"));
10191000
printf(_(" -o OID set next OID\n"));

0 commit comments

Comments
 (0)