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;
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
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, ':');
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)
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)
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 ||
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");
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();
}
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>
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];
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:
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"));