diff --git a/doc/src/sgml/ref/pg_resetxlog.sgml b/doc/src/sgml/ref/pg_resetxlog.sgml
index 00b24fe016..61fce46a17 100644
--- a/doc/src/sgml/ref/pg_resetxlog.sgml
+++ b/doc/src/sgml/ref/pg_resetxlog.sgml
@@ -1,5 +1,5 @@
@@ -12,7 +12,7 @@ PostgreSQL documentation
pg_resetxlog
- reset write-ahead log file and optionally the pg_control file
+ reset write-ahead log and pg_control contents
@@ -20,6 +20,7 @@ PostgreSQL documentation
pg_resetxlog
-f
-n
+ -o oid
-x xid
-l fileid,seg
datadir
@@ -29,8 +30,9 @@ PostgreSQL documentation
Description
- pg_resetxlog clears the write-ahead log file and
- optionally the pg_control> file. This function is sometimes
+ pg_resetxlog clears the write-ahead log and
+ optionally resets some fields in the 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
If pg_resetxlog complains that it cannot determine
valid data for pg_control>, you can force it to proceed anyway
- by specifying the -f> (force) switch. In this case plausible values
- will be substituted for the missing data. If -f> is used then
+ by specifying the -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.
+ pg_resetxlog's own environment is the source for its
+ guess at the locale fields; take care that LANG> and so forth
+ match the environment that initdb> was run in.
+ If you are not able to determine correct values for all these fields,
+ -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. Do not>
execute any data-modifying operations in the database before you dump,
as any such action is likely to make the corruption worse.
+
+ The -o>, -x>, and -l> switches allow
+ the next OID, next transaction ID, and WAL starting address values to
+ be set manually. These are only needed when
+ pg_resetxlog is unable to determine appropriate values
+ by reading pg_control>. A safe value for the
+ next transaction ID may be determined by looking for the largest
+ file name in $PGDATA>/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 0011> is the largest entry
+ in pg_clog>, -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
+ $PGDATA>/pg_xlog>. These also are in hex, and
+ have two parts. For example, if 000000FF0000003A> is the
+ largest entry in pg_xlog>, -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.
+
+
The -n> (no operation) switch instructs
pg_resetxlog 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 pg_resetxlog to proceed for real.
-
-
- The -x> and -l> switches are intended for use by
- pg_upgrade>. In most cases they should not be used in
- manual recovery operations.
-
diff --git a/src/bin/pg_resetxlog/pg_resetxlog.c b/src/bin/pg_resetxlog/pg_resetxlog.c
index 56621cd556..81fb79b3a3 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 .\n"));
}