On 18/07/14 00:41, Andres Freund wrote:
On 2014-06-27 00:51:02 +0200, Petr Jelinek wrote:
{
switch (c)
{
@@ -227,6 +229,33 @@ main(int argc, char *argv[])
XLogFromFileName(optarg, &minXlogTli,
&minXlogSegNo);
break;
+ case 's':
+ if (optarg)
+ {
+#ifdef HAVE_STRTOULL
+ set_sysid = strtoull(optarg, &endptr,
10);
+#else
+ set_sysid = strtoul(optarg, &endptr,
10);
+#endif
Wouldn't it be better to use sscanf()? That should work with large
inputs across platforms.
Well, sscanf does not do much validation and silently truncates too big
input (which is why I replaced it with strtoull, original patch did have
sscanf), also I think the portability of sscanf might not be as good,
see 9d7ded0f4277f5c0063eca8e871a34e2355a8371 commit.
+ /*
+ * Validate input, we use strspn
because strtoul(l) accepts
+ * negative numbers and silently
converts them to unsigned
+ */
+ if (set_sysid == 0 || errno != 0 ||
+ endptr == optarg || *endptr !=
'\0' ||
+ strspn(optarg, "0123456789") !=
strlen(optarg))
+ {
+ fprintf(stderr, _("%s: invalid
argument for option -s\n"), progname);
+ fprintf(stderr, _("Try \"%s --help\"
for more information.\n"), progname);
+ exit(1);
+ }
Maybe: 'invalid argument \"%s\" ...'?
Ok
@@ -1087,6 +1147,7 @@ usage(void)
printf(_(" -o OID set next OID\n"));
printf(_(" -O OFFSET set next multitransaction offset\n"));
printf(_(" -V, --version output version information, then exit\n"));
+ printf(_(" -s [SYSID] set system identifier (or generate
one)\n"));
printf(_(" -x XID set next transaction ID\n"));
printf(_(" -?, --help show this help, then exit\n"));
printf(_("\nReport bugs to <pgsql-b...@postgresql.org>.\n"));
I think we usually try to keep the options roughly alphabetically
ordered. Same in the getopt() above.
Ok, attached v4 with those changes.
--
Petr Jelinek http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
diff --git a/doc/src/sgml/ref/pg_resetxlog.sgml b/doc/src/sgml/ref/pg_resetxlog.sgml
index 34b0606..39ae574 100644
--- a/doc/src/sgml/ref/pg_resetxlog.sgml
+++ b/doc/src/sgml/ref/pg_resetxlog.sgml
@@ -30,6 +30,7 @@ PostgreSQL documentation
<arg choice="opt"><option>-m</option> <replaceable class="parameter">mxid</replaceable>,<replaceable class="parameter">mxid</replaceable></arg>
<arg choice="opt"><option>-O</option> <replaceable class="parameter">mxoff</replaceable></arg>
<arg choice="opt"><option>-l</option> <replaceable class="parameter">xlogfile</replaceable></arg>
+ <arg choice="opt"><option>-s</option> [<replaceable class="parameter">sysid</replaceable>]</arg>
<arg choice="plain"><replaceable>datadir</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
@@ -184,6 +185,13 @@ PostgreSQL documentation
</para>
<para>
+ The <option>-s</> option instructs <command>pg_resetxlog</command> to
+ set the system identifier of the cluster to specified <replaceable>sysid</>.
+ If the <replaceable>sysid</> is not provided new one will be generated using
+ same algorithm <command>initdb</> uses.
+ </para>
+
+ <para>
The <option>-V</> and <option>--version</> options print
the <application>pg_resetxlog</application> version and exit. The
options <option>-?</> and <option>--help</> show supported arguments,
diff --git a/src/bin/pg_resetxlog/pg_resetxlog.c b/src/bin/pg_resetxlog/pg_resetxlog.c
index 915a1ed..c94ccda 100644
--- a/src/bin/pg_resetxlog/pg_resetxlog.c
+++ b/src/bin/pg_resetxlog/pg_resetxlog.c
@@ -67,7 +67,9 @@ static MultiXactId set_mxid = 0;
static MultiXactOffset set_mxoff = (MultiXactOffset) -1;
static uint32 minXlogTli = 0;
static XLogSegNo minXlogSegNo = 0;
+static uint64 set_sysid = 0;
+static uint64 GenerateSystemIdentifier(void);
static bool ReadControlFile(void);
static void GuessControlValues(void);
static void PrintControlValues(bool guessed);
@@ -111,7 +113,7 @@ main(int argc, char *argv[])
}
- while ((c = getopt(argc, argv, "fl:m:no:O:x:e:")) != -1)
+ while ((c = getopt(argc, argv, "fl:m:no:O:s::x:e:")) != -1)
{
switch (c)
{
@@ -227,6 +229,33 @@ main(int argc, char *argv[])
XLogFromFileName(optarg, &minXlogTli, &minXlogSegNo);
break;
+ case 's':
+ if (optarg)
+ {
+#ifdef HAVE_STRTOULL
+ set_sysid = strtoull(optarg, &endptr, 10);
+#else
+ set_sysid = strtoul(optarg, &endptr, 10);
+#endif
+ /*
+ * Validate input, we use strspn because strtoul(l) accepts
+ * negative numbers and silently converts them to unsigned
+ */
+ if (set_sysid == 0 || errno != 0 ||
+ endptr == optarg || *endptr != '\0' ||
+ strspn(optarg, " 0123456789") != strlen(optarg))
+ {
+ fprintf(stderr, _("%s: invalid argument \"%s\" for option -s\n"), progname, optarg);
+ fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
+ exit(1);
+ }
+ }
+ else
+ {
+ set_sysid = GenerateSystemIdentifier();
+ }
+ break;
+
default:
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
exit(1);
@@ -354,6 +383,9 @@ main(int argc, char *argv[])
if (minXlogSegNo > newXlogSegNo)
newXlogSegNo = minXlogSegNo;
+ if (set_sysid != 0)
+ ControlFile.system_identifier = set_sysid;
+
/*
* If we had to guess anything, and -f was not given, just print the
* guessed values and exit. Also print if -n is given.
@@ -395,6 +427,26 @@ main(int argc, char *argv[])
/*
+ * Create a new unique installation identifier.
+ *
+ * See notes in xlog.c about the algorithm.
+ */
+static uint64
+GenerateSystemIdentifier(void)
+{
+ uint64 sysidentifier;
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+ sysidentifier = ((uint64) tv.tv_sec) << 32;
+ sysidentifier |= ((uint64) tv.tv_usec) << 12;
+ sysidentifier |= getpid() & 0xFFF;
+
+ return sysidentifier;
+}
+
+
+/*
* Try to read the existing pg_control file.
*
* This routine is also responsible for updating old pg_control versions
@@ -475,9 +527,6 @@ ReadControlFile(void)
static void
GuessControlValues(void)
{
- uint64 sysidentifier;
- struct timeval tv;
-
/*
* Set up a completely default set of pg_control values.
*/
@@ -489,14 +538,10 @@ GuessControlValues(void)
/*
* Create a new unique installation identifier, since we can no longer use
- * any old XLOG records. See notes in xlog.c about the algorithm.
+ * any old XLOG records.
*/
- gettimeofday(&tv, NULL);
- sysidentifier = ((uint64) tv.tv_sec) << 32;
- sysidentifier |= ((uint64) tv.tv_usec) << 12;
- sysidentifier |= getpid() & 0xFFF;
- ControlFile.system_identifier = sysidentifier;
+ ControlFile.system_identifier = GenerateSystemIdentifier();
ControlFile.checkPointCopy.redo = SizeOfXLogLongPHD;
ControlFile.checkPointCopy.ThisTimeLineID = 1;
@@ -649,6 +694,21 @@ PrintNewControlValues()
XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID, newXlogSegNo);
printf(_("First log segment after reset: %s\n"), fname);
+ if (set_sysid != 0)
+ {
+ char sysident_str[32];
+
+ /*
+ * Format system_identifier separately to keep platform-dependent format
+ * code out of the translatable message string.
+ */
+ snprintf(sysident_str, sizeof(sysident_str), UINT64_FORMAT,
+ ControlFile.system_identifier);
+
+ printf(_("Database system identifier: %s\n"),
+ sysident_str);
+ }
+
if (set_mxid != 0)
{
printf(_("NextMultiXactId: %u\n"),
@@ -1086,6 +1146,7 @@ usage(void)
printf(_(" -n no update, just show what would be done (for testing)\n"));
printf(_(" -o OID set next OID\n"));
printf(_(" -O OFFSET set next multitransaction offset\n"));
+ printf(_(" -s [SYSID] set system identifier (or generate one)\n"));
printf(_(" -V, --version output version information, then exit\n"));
printf(_(" -x XID set next transaction ID\n"));
printf(_(" -?, --help show this help, then exit\n"));
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers