* step 2 ...
*
*
- * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/bin/pg_resetxlog/pg_resetxlog.c,v 1.79 2010/04/28 16:10:43 heikki Exp $
+ * src/bin/pg_resetxlog/pg_resetxlog.c
*
*-------------------------------------------------------------------------
*/
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
-#ifdef HAVE_GETOPT_H
-#include <getopt.h>
-#endif
#include "access/transam.h"
#include "access/tuptoaster.h"
#include "access/xlog_internal.h"
#include "catalog/catversion.h"
#include "catalog/pg_control.h"
-
-extern int optind;
-extern char *optarg;
+#include "common/fe_memutils.h"
+#include "pg_getopt.h"
static ControlFileData ControlFile; /* pg_control values */
-static uint32 newXlogId,
- newXlogSeg; /* ID/Segment of new XLOG segment */
+static XLogSegNo newXlogSegNo; /* new XLOG segment # */
static bool guessed = false; /* T if we had to guess at any values */
static const char *progname;
+static uint32 set_xid_epoch = (uint32) -1;
+static TransactionId set_xid = 0;
+static Oid set_oid = 0;
+static MultiXactId set_mxid = 0;
+static MultiXactOffset set_mxoff = (MultiXactOffset) -1;
+static uint32 minXlogTli = 0;
+static XLogSegNo minXlogSegNo = 0;
static bool ReadControlFile(void);
static void GuessControlValues(void);
static void PrintControlValues(bool guessed);
+static void PrintNewControlValues(void);
static void RewriteControlFile(void);
static void FindEndOfXLOG(void);
static void KillExistingXLOG(void);
int c;
bool force = false;
bool noupdate = false;
- uint32 set_xid_epoch = (uint32) -1;
- TransactionId set_xid = 0;
- Oid set_oid = 0;
- MultiXactId set_mxid = 0;
- MultiXactOffset set_mxoff = (MultiXactOffset) -1;
- uint32 minXlogTli = 0,
- minXlogId = 0,
- minXlogSeg = 0;
+ MultiXactId set_oldestmxid = 0;
char *endptr;
char *endptr2;
- char *endptr3;
char *DataDir;
int fd;
- char path[MAXPGPATH];
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_resetxlog"));
case 'm':
set_mxid = strtoul(optarg, &endptr, 0);
- if (endptr == optarg || *endptr != '\0')
+ if (endptr == optarg || *endptr != ',')
+ {
+ fprintf(stderr, _("%s: invalid argument for option -m\n"), progname);
+ fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
+ exit(1);
+ }
+
+ set_oldestmxid = strtoul(endptr + 1, &endptr2, 0);
+ if (endptr2 == endptr + 1 || *endptr2 != '\0')
{
fprintf(stderr, _("%s: invalid argument for option -m\n"), progname);
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
fprintf(stderr, _("%s: multitransaction ID (-m) must not be 0\n"), progname);
exit(1);
}
+
+ /*
+ * XXX It'd be nice to have more sanity checks here, e.g. so
+ * that oldest is not wrapped around w.r.t. nextMulti.
+ */
+ if (set_oldestmxid == 0)
+ {
+ fprintf(stderr, _("%s: oldest multitransaction ID (-m) must not be 0\n"),
+ progname);
+ exit(1);
+ }
break;
case 'O':
break;
case 'l':
- minXlogTli = strtoul(optarg, &endptr, 0);
- if (endptr == optarg || *endptr != ',')
- {
- 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')
+ 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);
}
+ XLogFromFileName(optarg, &minXlogTli, &minXlogSegNo);
break;
default:
* Check for a postmaster lock file --- if there is one, refuse to
* proceed, on grounds we might be interfering with a live installation.
*/
- snprintf(path, MAXPGPATH, "%s/postmaster.pid", DataDir);
-
- if ((fd = open(path, O_RDONLY, 0)) < 0)
+ if ((fd = open("postmaster.pid", O_RDONLY, 0)) < 0)
{
if (errno != ENOENT)
{
- fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"), progname, path, strerror(errno));
+ fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
+ progname, "postmaster.pid", strerror(errno));
exit(1);
}
}
{
fprintf(stderr, _("%s: lock file \"%s\" exists\n"
"Is a server running? If not, delete the lock file and try again.\n"),
- progname, path);
+ progname, "postmaster.pid");
exit(1);
}
GuessControlValues();
/*
- * Also look at existing segment files to set up newXlogId/newXlogSeg
+ * Also look at existing segment files to set up newXlogSegNo
*/
FindEndOfXLOG();
+ /*
+ * If we're not going to proceed with the reset, print the current control
+ * file parameters.
+ */
+ if ((guessed && !force) || noupdate)
+ PrintControlValues(guessed);
+
/*
* Adjust fields if required by switches. (Do this now so that printout,
* if any, includes these values.)
ControlFile.checkPointCopy.nextOid = set_oid;
if (set_mxid != 0)
+ {
ControlFile.checkPointCopy.nextMulti = set_mxid;
+ ControlFile.checkPointCopy.oldestMulti = set_oldestmxid;
+ if (ControlFile.checkPointCopy.oldestMulti < FirstMultiXactId)
+ ControlFile.checkPointCopy.oldestMulti += FirstMultiXactId;
+ ControlFile.checkPointCopy.oldestMultiDB = InvalidOid;
+ }
+
if (set_mxoff != -1)
ControlFile.checkPointCopy.nextMultiOffset = set_mxoff;
if (minXlogTli > ControlFile.checkPointCopy.ThisTimeLineID)
- ControlFile.checkPointCopy.ThisTimeLineID = minXlogTli;
-
- if (minXlogId > newXlogId ||
- (minXlogId == newXlogId &&
- minXlogSeg > newXlogSeg))
{
- newXlogId = minXlogId;
- newXlogSeg = minXlogSeg;
+ ControlFile.checkPointCopy.ThisTimeLineID = minXlogTli;
+ ControlFile.checkPointCopy.PrevTimeLineID = minXlogTli;
}
+ if (minXlogSegNo > newXlogSegNo)
+ newXlogSegNo = minXlogSegNo;
+
/*
* If we had to guess anything, and -f was not given, just print the
* guessed values and exit. Also print if -n is given.
*/
if ((guessed && !force) || noupdate)
{
- PrintControlValues(guessed);
+ PrintNewControlValues();
if (!noupdate)
{
printf(_("\nIf these values seem acceptable, use -f to force reset.\n"));
}
/* Use malloc to ensure we have a maxaligned buffer */
- buffer = (char *) malloc(PG_CONTROL_SIZE);
+ buffer = (char *) pg_malloc(PG_CONTROL_SIZE);
len = read(fd, buffer, PG_CONTROL_SIZE);
if (len < 0)
ControlFile.system_identifier = sysidentifier;
- ControlFile.checkPointCopy.redo.xlogid = 0;
- ControlFile.checkPointCopy.redo.xrecoff = SizeOfXLogLongPHD;
+ ControlFile.checkPointCopy.redo = SizeOfXLogLongPHD;
ControlFile.checkPointCopy.ThisTimeLineID = 1;
+ ControlFile.checkPointCopy.PrevTimeLineID = 1;
+ ControlFile.checkPointCopy.fullPageWrites = false;
ControlFile.checkPointCopy.nextXidEpoch = 0;
ControlFile.checkPointCopy.nextXid = FirstNormalTransactionId;
ControlFile.checkPointCopy.nextOid = FirstBootstrapObjectId;
ControlFile.checkPointCopy.nextMultiOffset = 0;
ControlFile.checkPointCopy.oldestXid = FirstNormalTransactionId;
ControlFile.checkPointCopy.oldestXidDB = InvalidOid;
+ ControlFile.checkPointCopy.oldestMulti = FirstMultiXactId;
+ ControlFile.checkPointCopy.oldestMultiDB = InvalidOid;
ControlFile.checkPointCopy.time = (pg_time_t) time(NULL);
+ ControlFile.checkPointCopy.oldestActiveXid = InvalidTransactionId;
ControlFile.state = DB_SHUTDOWNED;
ControlFile.time = (pg_time_t) time(NULL);
ControlFile.checkPoint = ControlFile.checkPointCopy.redo;
+ ControlFile.unloggedLSN = 1;
+
+ /* minRecoveryPoint, backupStartPoint and backupEndPoint can be left zero */
+
+ ControlFile.wal_level = WAL_LEVEL_MINIMAL;
+ ControlFile.wal_log_hints = false;
+ ControlFile.MaxConnections = 100;
+ ControlFile.max_worker_processes = 8;
+ ControlFile.max_prepared_xacts = 0;
+ ControlFile.max_locks_per_xact = 64;
ControlFile.maxAlign = MAXIMUM_ALIGNOF;
ControlFile.floatFormat = FLOATFORMAT_VALUE;
if (guessed)
printf(_("Guessed pg_control values:\n\n"));
else
- printf(_("pg_control values:\n\n"));
+ printf(_("Current pg_control values:\n\n"));
/*
* Format system_identifier separately to keep platform-dependent format
snprintf(sysident_str, sizeof(sysident_str), UINT64_FORMAT,
ControlFile.system_identifier);
- printf(_("First log file ID after reset: %u\n"),
- newXlogId);
- printf(_("First log file segment after reset: %u\n"),
- newXlogSeg);
printf(_("pg_control version number: %u\n"),
ControlFile.pg_control_version);
printf(_("Catalog version number: %u\n"),
sysident_str);
printf(_("Latest checkpoint's TimeLineID: %u\n"),
ControlFile.checkPointCopy.ThisTimeLineID);
+ printf(_("Latest checkpoint's full_page_writes: %s\n"),
+ ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off"));
printf(_("Latest checkpoint's NextXID: %u/%u\n"),
ControlFile.checkPointCopy.nextXidEpoch,
ControlFile.checkPointCopy.nextXid);
ControlFile.checkPointCopy.oldestXid);
printf(_("Latest checkpoint's oldestXID's DB: %u\n"),
ControlFile.checkPointCopy.oldestXidDB);
+ printf(_("Latest checkpoint's oldestActiveXID: %u\n"),
+ ControlFile.checkPointCopy.oldestActiveXid);
+ printf(_("Latest checkpoint's oldestMultiXid: %u\n"),
+ ControlFile.checkPointCopy.oldestMulti);
+ printf(_("Latest checkpoint's oldestMulti's DB: %u\n"),
+ ControlFile.checkPointCopy.oldestMultiDB);
printf(_("Maximum data alignment: %u\n"),
ControlFile.maxAlign);
/* we don't print floatFormat since can't say much useful about it */
(ControlFile.float4ByVal ? _("by value") : _("by reference")));
printf(_("Float8 argument passing: %s\n"),
(ControlFile.float8ByVal ? _("by value") : _("by reference")));
+ printf(_("Data page checksum version: %u\n"),
+ ControlFile.data_checksum_version);
+}
+
+
+/*
+ * Print the values to be changed.
+ */
+static void
+PrintNewControlValues()
+{
+ char fname[MAXFNAMELEN];
+
+ /* This will be always printed in order to keep format same. */
+ printf(_("\n\nValues to be changed:\n\n"));
+
+ XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID, newXlogSegNo);
+ printf(_("First log segment after reset: %s\n"), fname);
+
+ if (set_mxid != 0)
+ {
+ printf(_("NextMultiXactId: %u\n"),
+ ControlFile.checkPointCopy.nextMulti);
+ printf(_("OldestMultiXid: %u\n"),
+ ControlFile.checkPointCopy.oldestMulti);
+ printf(_("OldestMulti's DB: %u\n"),
+ ControlFile.checkPointCopy.oldestMultiDB);
+ }
+
+ if (set_mxoff != -1)
+ {
+ printf(_("NextMultiOffset: %u\n"),
+ ControlFile.checkPointCopy.nextMultiOffset);
+ }
+
+ if (set_oid != 0)
+ {
+ printf(_("NextOID: %u\n"),
+ ControlFile.checkPointCopy.nextOid);
+ }
+
+ if (set_xid != 0)
+ {
+ printf(_("NextXID: %u\n"),
+ ControlFile.checkPointCopy.nextXid);
+ printf(_("OldestXID: %u\n"),
+ ControlFile.checkPointCopy.oldestXid);
+ printf(_("OldestXID's DB: %u\n"),
+ ControlFile.checkPointCopy.oldestXidDB);
+ }
+
+ if (set_xid_epoch != -1)
+ {
+ printf(_("NextXID Epoch: %u\n"),
+ ControlFile.checkPointCopy.nextXidEpoch);
+ }
}
/*
* Adjust fields as needed to force an empty XLOG starting at
- * newXlogId/newXlogSeg.
+ * newXlogSegNo.
*/
- ControlFile.checkPointCopy.redo.xlogid = newXlogId;
- ControlFile.checkPointCopy.redo.xrecoff =
- newXlogSeg * XLogSegSize + SizeOfXLogLongPHD;
+ XLogSegNoOffsetToRecPtr(newXlogSegNo, SizeOfXLogLongPHD,
+ ControlFile.checkPointCopy.redo);
ControlFile.checkPointCopy.time = (pg_time_t) time(NULL);
ControlFile.state = DB_SHUTDOWNED;
ControlFile.time = (pg_time_t) time(NULL);
ControlFile.checkPoint = ControlFile.checkPointCopy.redo;
- ControlFile.prevCheckPoint.xlogid = 0;
- ControlFile.prevCheckPoint.xrecoff = 0;
- ControlFile.minRecoveryPoint.xlogid = 0;
- ControlFile.minRecoveryPoint.xrecoff = 0;
- ControlFile.backupStartPoint.xlogid = 0;
- ControlFile.backupStartPoint.xrecoff = 0;
+ ControlFile.prevCheckPoint = 0;
+ ControlFile.minRecoveryPoint = 0;
+ ControlFile.minRecoveryPointTLI = 0;
+ ControlFile.backupStartPoint = 0;
+ ControlFile.backupEndPoint = 0;
+ ControlFile.backupEndRequired = false;
/*
- * Use the defaults for max_* settings. The values don't matter
- * as long as wal_level='minimal'.
+ * Force the defaults for max_* settings. The values don't really matter
+ * as long as wal_level='minimal'; the postmaster will reset these fields
+ * anyway at startup.
*/
+ ControlFile.wal_level = WAL_LEVEL_MINIMAL;
+ ControlFile.wal_log_hints = false;
ControlFile.MaxConnections = 100;
+ ControlFile.max_worker_processes = 8;
ControlFile.max_prepared_xacts = 0;
ControlFile.max_locks_per_xact = 64;
- ControlFile.wal_level = WAL_LEVEL_MINIMAL;
/* Now we can force the recorded xlog seg size to the right thing. */
ControlFile.xlog_seg_size = XLogSegSize;
{
DIR *xldir;
struct dirent *xlde;
+ uint64 segs_per_xlogid;
+ uint64 xlogbytepos;
/*
* Initialize the max() computation using the last checkpoint address from
* old pg_control. Note that for the moment we are working with segment
* numbering according to the old xlog seg size.
*/
- newXlogId = ControlFile.checkPointCopy.redo.xlogid;
- newXlogSeg = ControlFile.checkPointCopy.redo.xrecoff / ControlFile.xlog_seg_size;
+ segs_per_xlogid = (UINT64CONST(0x0000000100000000) / ControlFile.xlog_seg_size);
+ newXlogSegNo = ControlFile.checkPointCopy.redo / ControlFile.xlog_seg_size;
/*
* Scan the pg_xlog directory to find existing WAL segment files. We
exit(1);
}
- errno = 0;
- while ((xlde = readdir(xldir)) != NULL)
+ while (errno = 0, (xlde = readdir(xldir)) != NULL)
{
if (strlen(xlde->d_name) == 24 &&
strspn(xlde->d_name, "0123456789ABCDEF") == 24)
unsigned int tli,
log,
seg;
+ XLogSegNo segno;
sscanf(xlde->d_name, "%08X%08X%08X", &tli, &log, &seg);
+ segno = ((uint64) log) * segs_per_xlogid + seg;
/*
* Note: we take the max of all files found, regardless of their
* timelines other than the target TLI, but this seems safer.
* Better too large a result than too small...
*/
- if (log > newXlogId ||
- (log == newXlogId && seg > newXlogSeg))
- {
- newXlogId = log;
- newXlogSeg = seg;
- }
+ if (segno > newXlogSegNo)
+ newXlogSegNo = segno;
}
- errno = 0;
}
-#ifdef WIN32
- /*
- * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
- * released version
- */
+#ifdef WIN32
+ /* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
if (GetLastError() == ERROR_NO_MORE_FILES)
errno = 0;
#endif
if (errno)
{
- fprintf(stderr, _("%s: could not read from directory \"%s\": %s\n"),
+ fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
+ progname, XLOGDIR, strerror(errno));
+ exit(1);
+ }
+
+ if (closedir(xldir))
+ {
+ fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
progname, XLOGDIR, strerror(errno));
exit(1);
}
- closedir(xldir);
/*
* Finally, convert to new xlog seg size, and advance by one to ensure we
* are in virgin territory.
*/
- newXlogSeg *= ControlFile.xlog_seg_size;
- newXlogSeg = (newXlogSeg + XLogSegSize - 1) / XLogSegSize;
-
- /* be sure we wrap around correctly at end of a logfile */
- NextLogSeg(newXlogId, newXlogSeg);
+ xlogbytepos = newXlogSegNo * ControlFile.xlog_seg_size;
+ newXlogSegNo = (xlogbytepos + XLogSegSize - 1) / XLogSegSize;
+ newXlogSegNo++;
}
exit(1);
}
- errno = 0;
- while ((xlde = readdir(xldir)) != NULL)
+ while (errno = 0, (xlde = readdir(xldir)) != NULL)
{
if (strlen(xlde->d_name) == 24 &&
strspn(xlde->d_name, "0123456789ABCDEF") == 24)
exit(1);
}
}
- errno = 0;
}
-#ifdef WIN32
- /*
- * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
- * released version
- */
+#ifdef WIN32
+ /* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
if (GetLastError() == ERROR_NO_MORE_FILES)
errno = 0;
#endif
if (errno)
{
- fprintf(stderr, _("%s: could not read from directory \"%s\": %s\n"),
+ fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
+ progname, XLOGDIR, strerror(errno));
+ exit(1);
+ }
+
+ if (closedir(xldir))
+ {
+ fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
progname, XLOGDIR, strerror(errno));
exit(1);
}
- closedir(xldir);
}
exit(1);
}
- errno = 0;
- while ((xlde = readdir(xldir)) != NULL)
+ while (errno = 0, (xlde = readdir(xldir)) != NULL)
{
if (strspn(xlde->d_name, "0123456789ABCDEF") == 24 &&
(strcmp(xlde->d_name + 24, ".ready") == 0 ||
exit(1);
}
}
- errno = 0;
}
-#ifdef WIN32
- /*
- * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
- * released version
- */
+#ifdef WIN32
+ /* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
if (GetLastError() == ERROR_NO_MORE_FILES)
errno = 0;
#endif
if (errno)
{
- fprintf(stderr, _("%s: could not read from directory \"%s\": %s\n"),
+ fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
+ progname, ARCHSTATDIR, strerror(errno));
+ exit(1);
+ }
+
+ if (closedir(xldir))
+ {
+ fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
progname, ARCHSTATDIR, strerror(errno));
exit(1);
}
- closedir(xldir);
}
int nbytes;
/* Use malloc() to ensure buffer is MAXALIGNED */
- buffer = (char *) malloc(XLOG_BLCKSZ);
+ buffer = (char *) pg_malloc(XLOG_BLCKSZ);
page = (XLogPageHeader) buffer;
memset(buffer, 0, XLOG_BLCKSZ);
page->xlp_magic = XLOG_PAGE_MAGIC;
page->xlp_info = XLP_LONG_HEADER;
page->xlp_tli = ControlFile.checkPointCopy.ThisTimeLineID;
- page->xlp_pageaddr.xlogid =
- ControlFile.checkPointCopy.redo.xlogid;
- page->xlp_pageaddr.xrecoff =
- ControlFile.checkPointCopy.redo.xrecoff - SizeOfXLogLongPHD;
+ page->xlp_pageaddr = ControlFile.checkPointCopy.redo - SizeOfXLogLongPHD;
longpage = (XLogLongPageHeader) page;
longpage->xlp_sysid = ControlFile.system_identifier;
longpage->xlp_seg_size = XLogSegSize;
/* Insert the initial checkpoint record */
record = (XLogRecord *) ((char *) page + SizeOfXLogLongPHD);
- record->xl_prev.xlogid = 0;
- record->xl_prev.xrecoff = 0;
+ record->xl_prev = 0;
record->xl_xid = InvalidTransactionId;
record->xl_tot_len = SizeOfXLogRecord + sizeof(CheckPoint);
record->xl_len = sizeof(CheckPoint);
INIT_CRC32(crc);
COMP_CRC32(crc, &ControlFile.checkPointCopy, sizeof(CheckPoint));
- COMP_CRC32(crc, (char *) record + sizeof(pg_crc32),
- SizeOfXLogRecord - sizeof(pg_crc32));
+ COMP_CRC32(crc, (char *) record, offsetof(XLogRecord, xl_crc));
FIN_CRC32(crc);
record->xl_crc = crc;
/* Write the first page */
- XLogFilePath(path, ControlFile.checkPointCopy.ThisTimeLineID,
- newXlogId, newXlogSeg);
+ XLogFilePath(path, ControlFile.checkPointCopy.ThisTimeLineID, newXlogSegNo);
unlink(path);
printf(_("%s resets the PostgreSQL transaction log.\n\n"), progname);
printf(_("Usage:\n %s [OPTION]... DATADIR\n\n"), progname);
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(_(" -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"));
- printf(_(" -O OFFSET set next multitransaction offset\n"));
- printf(_(" -x XID set next transaction ID\n"));
- printf(_(" --help show this help, then exit\n"));
- printf(_(" --version output version information, then exit\n"));
+ printf(_(" -e XIDEPOCH set next transaction ID epoch\n"));
+ printf(_(" -f force update to be done\n"));
+ printf(_(" -l XLOGFILE force minimum WAL starting location for new transaction log\n"));
+ printf(_(" -m MXID,MXID set next and oldest multitransaction ID\n"));
+ 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(_(" -V, --version output version information, then exit\n"));
+ printf(_(" -x XID set next transaction ID\n"));
+ printf(_(" -?, --help show this help, then exit\n"));
printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
}