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

Reply via email to