From 71e74a2f587ab8847e99b431b40d6acf62144128 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Wed, 2 Oct 2002 21:30:13 +0000
Subject: [PATCH] Re-enable pg_resetxlog to accept -l values in hexadecimal (it
 used to be able to do that, but the ability seems to have got lost in the
 shuffle).  Add a -o nextOID switch for completeness.  Improve the
 documentation to explain how and why to use these switches.

---
 doc/src/sgml/ref/pg_resetxlog.sgml  | 51 ++++++++++++++++-----
 src/bin/pg_resetxlog/pg_resetxlog.c | 71 ++++++++++++++++++++++-------
 2 files changed, 94 insertions(+), 28 deletions(-)

diff --git a/doc/src/sgml/ref/pg_resetxlog.sgml b/doc/src/sgml/ref/pg_resetxlog.sgml
index 00b24fe0168..61fce46a17d 100644
--- a/doc/src/sgml/ref/pg_resetxlog.sgml
+++ b/doc/src/sgml/ref/pg_resetxlog.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_resetxlog.sgml,v 1.5 2002/08/29 22:19:03 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_resetxlog.sgml,v 1.6 2002/10/02 21:30:13 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -12,7 +12,7 @@ PostgreSQL documentation
 
  <refnamediv>
   <refname>pg_resetxlog</refname>
-  <refpurpose>reset write-ahead log file and optionally the pg_control file</refpurpose>
+  <refpurpose>reset write-ahead log and pg_control contents</refpurpose>
  </refnamediv>
 
  <refsynopsisdiv>
@@ -20,6 +20,7 @@ PostgreSQL documentation
    <command>pg_resetxlog</command>
    <arg> -f </arg>
    <arg> -n </arg>
+   <arg> -o <replaceable class="parameter">oid</replaceable> </arg>
    <arg> -x <replaceable class="parameter">xid</replaceable> </arg>
    <arg> -l <replaceable class="parameter">fileid</replaceable>,<replaceable class="parameter">seg</replaceable> </arg>
    <arg choice="plain"><replaceable>datadir</replaceable></arg>
@@ -29,8 +30,9 @@ PostgreSQL documentation
  <refsect1 id="R1-APP-PGRESETXLOG-1">
   <title>Description</title>
   <para>
-   <command>pg_resetxlog</command> clears the write-ahead log file and
-   optionally the <filename>pg_control</> file.  This function is sometimes
+   <command>pg_resetxlog</command> clears the write-ahead log and
+   optionally resets some fields in the <filename>pg_control</> file.  This
+   function is sometimes 
    needed if these files have become corrupted.
    It should be used only as a last resort,
    when the server will not start due to such corruption.
@@ -55,14 +57,45 @@ PostgreSQL documentation
   <para>
    If <command>pg_resetxlog</command> complains that it cannot determine
    valid data for <filename>pg_control</>, you can force it to proceed anyway
-   by specifying the <literal>-f</> (force) switch.  In this case plausible values
-   will be substituted for the missing data.  If <literal>-f</> is used then
+   by specifying the <literal>-f</> (force) switch.  In this case plausible
+   values will be substituted for the missing data.  Most of the fields can be
+   expected to match, but manual assistance may be needed for the next OID,
+   next transaction ID, WAL starting address, and database locale fields.
+   The first three of these can be set using the switches discussed below.
+   <command>pg_resetxlog</command>'s own environment is the source for its
+   guess at the locale fields; take care that <envar>LANG</> and so forth
+   match the environment that <application>initdb</> was run in.
+   If you are not able to determine correct values for all these fields,
+   <literal>-f</> can still be used, but
    the recovered database must be treated with even more suspicion than
    usual --- an immediate dump and reload is imperative.  <emphasis>Do not</>
    execute any data-modifying operations in the database before you dump,
    as any such action is likely to make the corruption worse.
   </para>
 
+  <para>
+   The <literal>-o</>, <literal>-x</>, and <literal>-l</> switches allow
+   the next OID, next transaction ID, and WAL starting address values to
+   be set manually.  These are only needed when
+   <command>pg_resetxlog</command> is unable to determine appropriate values
+   by reading <filename>pg_control</>.  A safe value for the
+   next transaction ID may be determined by looking for the largest
+   file name in <envar>$PGDATA</><filename>/pg_clog</>, adding one,
+   and then multiplying by 1048576.  Note that the file names are in
+   hexadecimal.  It is usually easiest to specify the switch value in
+   hexadecimal too. For example, if <filename>0011</> is the largest entry
+   in <filename>pg_clog</>, <literal>-x 0x1200000</> will work (five trailing
+   zeroes provide the proper multiplier).
+   The WAL starting address should be
+   larger than any file number currently existing in
+   <envar>$PGDATA</><filename>/pg_xlog</>.  These also are in hex, and
+   have two parts.   For example, if <filename>000000FF0000003A</> is the
+   largest entry in <filename>pg_xlog</>, <literal>-l 0xFF,0x3B</> will work.
+   There is no comparably easy way to determine a next OID that's beyond
+   the largest one in the database, but fortunately it is not critical to
+   get the next-OID setting right.
+  </para>
+
   <para>
    The <literal>-n</> (no operation) switch instructs
    <command>pg_resetxlog</command> to print the values reconstructed from
@@ -70,12 +103,6 @@ PostgreSQL documentation
    This is mainly a debugging tool, but may be useful as a sanity check
    before allowing <command>pg_resetxlog</command> to proceed for real.
   </para>
-
-  <para>
-   The <literal>-x</> and <literal>-l</> switches are intended for use by
-   <application>pg_upgrade</>.  In most cases they should not be used in
-   manual recovery operations.
-  </para>
  </refsect1>
 
  <refsect1>
diff --git a/src/bin/pg_resetxlog/pg_resetxlog.c b/src/bin/pg_resetxlog/pg_resetxlog.c
index 56621cd5569..81fb79b3a39 100644
--- a/src/bin/pg_resetxlog/pg_resetxlog.c
+++ b/src/bin/pg_resetxlog/pg_resetxlog.c
@@ -23,7 +23,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/bin/pg_resetxlog/pg_resetxlog.c,v 1.6 2002/10/02 19:45:47 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/bin/pg_resetxlog/pg_resetxlog.c,v 1.7 2002/10/02 21:30:13 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -90,8 +90,11 @@ main(int argc, char *argv[])
 	bool		force = false;
 	bool		noupdate = false;
 	TransactionId set_xid = 0;
+	Oid			set_oid = 0;
 	uint32		minXlogId = 0,
 				minXlogSeg = 0;
+	char	   *endptr;
+	char	   *endptr2;
 	char	   *DataDir;
 	int			fd;
 	char		path[MAXPGPATH];
@@ -122,7 +125,7 @@ main(int argc, char *argv[])
 	}
 
 
-	while ((c = getopt(argc, argv, "fl:nx:")) != -1)
+	while ((c = getopt(argc, argv, "fl:no:x:")) != -1)
 	{
 		switch (c)
 		{
@@ -135,7 +138,13 @@ main(int argc, char *argv[])
 				break;
 
 			case 'x':
-				set_xid = strtoul(optarg, NULL, 0);
+				set_xid = strtoul(optarg, &endptr, 0);
+				if (endptr == optarg || *endptr != '\0')
+				{
+					fprintf(stderr, _("%s: invalid argument for -x option\n"), progname);
+					fprintf(stderr, _("Try '%s --help' for more information.\n"), progname);
+					exit(1);
+				}
 				if (set_xid == 0)
 				{
 					fprintf(stderr, _("%s: transaction ID (-x) must not be 0\n"), progname);
@@ -143,8 +152,31 @@ main(int argc, char *argv[])
 				}
 				break;
 
+			case 'o':
+				set_oid = strtoul(optarg, &endptr, 0);
+				if (endptr == optarg || *endptr != '\0')
+				{
+					fprintf(stderr, _("%s: invalid argument for -o option\n"), progname);
+					fprintf(stderr, _("Try '%s --help' for more information.\n"), progname);
+					exit(1);
+				}
+				if (set_oid == 0)
+				{
+					fprintf(stderr, _("%s: OID (-o) must not be 0\n"), progname);
+					exit(1);
+				}
+				break;
+
 			case 'l':
-				if (sscanf(optarg, "%u,%u", &minXlogId, &minXlogSeg) != 2)
+				minXlogId = strtoul(optarg, &endptr, 0);
+				if (endptr == optarg || *endptr != ',')
+				{
+					fprintf(stderr, _("%s: invalid argument for -l option\n"), progname);
+					fprintf(stderr, _("Try '%s --help' for more information.\n"), progname);
+					exit(1);
+				}
+				minXlogSeg = strtoul(endptr+1, &endptr2, 0);
+				if (endptr2 == endptr+1 || *endptr2 != '\0')
 				{
 					fprintf(stderr, _("%s: invalid argument for -l option\n"), progname);
 					fprintf(stderr, _("Try '%s --help' for more information.\n"), progname);
@@ -198,6 +230,24 @@ main(int argc, char *argv[])
 	if (!ReadControlFile())
 		GuessControlValues();
 
+	/*
+	 * Adjust fields if required by switches.  (Do this now so that
+	 * printout, if any, includes these values.)
+	 */
+	if (set_xid != 0)
+		ControlFile.checkPointCopy.nextXid = set_xid;
+
+	if (set_oid != 0)
+		ControlFile.checkPointCopy.nextOid = set_oid;
+
+	if (minXlogId > ControlFile.logId ||
+		(minXlogId == ControlFile.logId &&
+		 minXlogSeg > ControlFile.logSeg))
+	{
+		ControlFile.logId = minXlogId;
+		ControlFile.logSeg = minXlogSeg;
+	}
+
 	/*
 	 * If we had to guess anything, and -f was not given, just print the
 	 * guessed values and exit.  Also print if -n is given.
@@ -227,19 +277,7 @@ main(int argc, char *argv[])
 
 	/*
 	 * Else, do the dirty deed.
-	 *
-	 * First adjust fields if required by switches.
 	 */
-	if (set_xid != 0)
-		ControlFile.checkPointCopy.nextXid = set_xid;
-
-	if (minXlogId > ControlFile.logId ||
-	 (minXlogId == ControlFile.logId && minXlogSeg > ControlFile.logSeg))
-	{
-		ControlFile.logId = minXlogId;
-		ControlFile.logSeg = minXlogSeg;
-	}
-
 	RewriteControlFile();
 	KillExistingXLOG();
 	WriteEmptyXLOG();
@@ -659,6 +697,7 @@ usage(void)
 	printf(_("  -f                force update to be done\n"));
 	printf(_("  -l FILEID,SEG     force minimum WAL starting location for new transaction log\n"));
 	printf(_("  -n                no update, just show extracted control values (for testing)\n"));
+	printf(_("  -o OID            set next OID\n"));
 	printf(_("  -x XID            set next transaction ID\n"));
 	printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
 }
-- 
GitLab