1
0
mirror of https://github.com/postgres/postgres.git synced 2025-12-13 14:22:43 +03:00

pg_resetwal: Use separate flags for whether an option is given

Currently, we use special values that are otherwise invalid for each
option to indicate "option was not given". Replace that with separate
boolean variables for each option. It seems more clear to be explicit.

We were already doing that for the -m option, because there were no
invalid values for nextMulti that we could use (since commit
94939c5f3a).

Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Discussion: https://www.postgresql.org/message-id/81adf5f3-36ad-4bcd-9ba5-1b95c7b7a807@iki.fi
This commit is contained in:
Heikki Linnakangas
2025-12-08 16:54:54 +02:00
parent 636c1914b4
commit 978cf02bb8

View File

@@ -64,21 +64,43 @@ static ControlFileData ControlFile; /* pg_control values */
static XLogSegNo newXlogSegNo; /* new XLOG segment # */ static XLogSegNo newXlogSegNo; /* new XLOG segment # */
static bool guessed = false; /* T if we had to guess at any values */ static bool guessed = false; /* T if we had to guess at any values */
static const char *progname; static const char *progname;
static uint32 set_xid_epoch = (uint32) -1;
static TransactionId set_oldest_xid = 0; /*
static TransactionId set_xid = 0; * New values given on the command-line
static TransactionId set_oldest_commit_ts_xid = 0; */
static TransactionId set_newest_commit_ts_xid = 0; static bool next_xid_epoch_given = false;
static Oid set_oid = 0; static uint32 next_xid_epoch_val;
static bool mxid_given = false;
static MultiXactId set_mxid = 0; static bool oldest_xid_given = false;
static bool mxoff_given = false; static TransactionId oldest_xid_val;
static MultiXactOffset set_mxoff = 0;
static bool next_xid_given = false;
static TransactionId next_xid_val;
static bool commit_ts_xids_given = false;
static TransactionId oldest_commit_ts_xid_val;
static TransactionId newest_commit_ts_xid_val;
static bool next_oid_given = false;
static Oid next_oid_val;
static bool mxids_given = false;
static MultiXactId next_mxid_val;
static MultiXactId oldest_mxid_val = 0;
static bool next_mxoff_given = false;
static MultiXactOffset next_mxoff_val;
static bool wal_segsize_given = false;
static int wal_segsize_val;
static bool char_signedness_given = false;
static bool char_signedness_val;
static TimeLineID minXlogTli = 0; static TimeLineID minXlogTli = 0;
static XLogSegNo minXlogSegNo = 0; static XLogSegNo minXlogSegNo = 0;
static int WalSegSz; static int WalSegSz;
static int set_wal_segsize;
static int set_char_signedness = -1;
static void CheckDataVersion(void); static void CheckDataVersion(void);
static bool read_controlfile(void); static bool read_controlfile(void);
@@ -118,7 +140,6 @@ main(int argc, char *argv[])
int c; int c;
bool force = false; bool force = false;
bool noupdate = false; bool noupdate = false;
MultiXactId set_oldestmxid = 0;
char *endptr; char *endptr;
char *endptr2; char *endptr2;
char *DataDir = NULL; char *DataDir = NULL;
@@ -162,7 +183,7 @@ main(int argc, char *argv[])
case 'e': case 'e':
errno = 0; errno = 0;
set_xid_epoch = strtouint32_strict(optarg, &endptr, 0); next_xid_epoch_val = strtouint32_strict(optarg, &endptr, 0);
if (endptr == optarg || *endptr != '\0' || errno != 0) if (endptr == optarg || *endptr != '\0' || errno != 0)
{ {
/*------ /*------
@@ -171,46 +192,47 @@ main(int argc, char *argv[])
pg_log_error_hint("Try \"%s --help\" for more information.", progname); pg_log_error_hint("Try \"%s --help\" for more information.", progname);
exit(1); exit(1);
} }
if (set_xid_epoch == -1) next_xid_epoch_given = true;
pg_fatal("transaction ID epoch (-e) must not be -1");
break; break;
case 'u': case 'u':
errno = 0; errno = 0;
set_oldest_xid = strtouint32_strict(optarg, &endptr, 0); oldest_xid_val = strtouint32_strict(optarg, &endptr, 0);
if (endptr == optarg || *endptr != '\0' || errno != 0) if (endptr == optarg || *endptr != '\0' || errno != 0)
{ {
pg_log_error("invalid argument for option %s", "-u"); pg_log_error("invalid argument for option %s", "-u");
pg_log_error_hint("Try \"%s --help\" for more information.", progname); pg_log_error_hint("Try \"%s --help\" for more information.", progname);
exit(1); exit(1);
} }
if (!TransactionIdIsNormal(set_oldest_xid)) if (!TransactionIdIsNormal(oldest_xid_val))
pg_fatal("oldest transaction ID (-u) must be greater than or equal to %u", FirstNormalTransactionId); pg_fatal("oldest transaction ID (-u) must be greater than or equal to %u", FirstNormalTransactionId);
oldest_xid_given = true;
break; break;
case 'x': case 'x':
errno = 0; errno = 0;
set_xid = strtouint32_strict(optarg, &endptr, 0); next_xid_val = strtouint32_strict(optarg, &endptr, 0);
if (endptr == optarg || *endptr != '\0' || errno != 0) if (endptr == optarg || *endptr != '\0' || errno != 0)
{ {
pg_log_error("invalid argument for option %s", "-x"); pg_log_error("invalid argument for option %s", "-x");
pg_log_error_hint("Try \"%s --help\" for more information.", progname); pg_log_error_hint("Try \"%s --help\" for more information.", progname);
exit(1); exit(1);
} }
if (!TransactionIdIsNormal(set_xid)) if (!TransactionIdIsNormal(next_xid_val))
pg_fatal("transaction ID (-x) must be greater than or equal to %u", FirstNormalTransactionId); pg_fatal("transaction ID (-x) must be greater than or equal to %u", FirstNormalTransactionId);
next_xid_given = true;
break; break;
case 'c': case 'c':
errno = 0; errno = 0;
set_oldest_commit_ts_xid = strtouint32_strict(optarg, &endptr, 0); oldest_commit_ts_xid_val = strtouint32_strict(optarg, &endptr, 0);
if (endptr == optarg || *endptr != ',' || errno != 0) if (endptr == optarg || *endptr != ',' || errno != 0)
{ {
pg_log_error("invalid argument for option %s", "-c"); pg_log_error("invalid argument for option %s", "-c");
pg_log_error_hint("Try \"%s --help\" for more information.", progname); pg_log_error_hint("Try \"%s --help\" for more information.", progname);
exit(1); exit(1);
} }
set_newest_commit_ts_xid = strtoul(endptr + 1, &endptr2, 0); newest_commit_ts_xid_val = strtoul(endptr + 1, &endptr2, 0);
if (endptr2 == endptr + 1 || *endptr2 != '\0' || errno != 0) if (endptr2 == endptr + 1 || *endptr2 != '\0' || errno != 0)
{ {
pg_log_error("invalid argument for option %s", "-c"); pg_log_error("invalid argument for option %s", "-c");
@@ -218,31 +240,33 @@ main(int argc, char *argv[])
exit(1); exit(1);
} }
if (set_oldest_commit_ts_xid < FirstNormalTransactionId && if (oldest_commit_ts_xid_val < FirstNormalTransactionId &&
set_oldest_commit_ts_xid != InvalidTransactionId) oldest_commit_ts_xid_val != InvalidTransactionId)
pg_fatal("transaction ID (-c) must be either %u or greater than or equal to %u", InvalidTransactionId, FirstNormalTransactionId); pg_fatal("transaction ID (-c) must be either %u or greater than or equal to %u", InvalidTransactionId, FirstNormalTransactionId);
if (set_newest_commit_ts_xid < FirstNormalTransactionId && if (newest_commit_ts_xid_val < FirstNormalTransactionId &&
set_newest_commit_ts_xid != InvalidTransactionId) newest_commit_ts_xid_val != InvalidTransactionId)
pg_fatal("transaction ID (-c) must be either %u or greater than or equal to %u", InvalidTransactionId, FirstNormalTransactionId); pg_fatal("transaction ID (-c) must be either %u or greater than or equal to %u", InvalidTransactionId, FirstNormalTransactionId);
commit_ts_xids_given = true;
break; break;
case 'o': case 'o':
errno = 0; errno = 0;
set_oid = strtouint32_strict(optarg, &endptr, 0); next_oid_val = strtouint32_strict(optarg, &endptr, 0);
if (endptr == optarg || *endptr != '\0' || errno != 0) if (endptr == optarg || *endptr != '\0' || errno != 0)
{ {
pg_log_error("invalid argument for option %s", "-o"); pg_log_error("invalid argument for option %s", "-o");
pg_log_error_hint("Try \"%s --help\" for more information.", progname); pg_log_error_hint("Try \"%s --help\" for more information.", progname);
exit(1); exit(1);
} }
if (set_oid == 0) if (next_oid_val == 0)
pg_fatal("OID (-o) must not be 0"); pg_fatal("OID (-o) must not be 0");
next_oid_given = true;
break; break;
case 'm': case 'm':
errno = 0; errno = 0;
set_mxid = strtouint32_strict(optarg, &endptr, 0); next_mxid_val = strtouint32_strict(optarg, &endptr, 0);
if (endptr == optarg || *endptr != ',' || errno != 0) if (endptr == optarg || *endptr != ',' || errno != 0)
{ {
pg_log_error("invalid argument for option %s", "-m"); pg_log_error("invalid argument for option %s", "-m");
@@ -250,7 +274,7 @@ main(int argc, char *argv[])
exit(1); exit(1);
} }
set_oldestmxid = strtouint32_strict(endptr + 1, &endptr2, 0); oldest_mxid_val = strtouint32_strict(endptr + 1, &endptr2, 0);
if (endptr2 == endptr + 1 || *endptr2 != '\0' || errno != 0) if (endptr2 == endptr + 1 || *endptr2 != '\0' || errno != 0)
{ {
pg_log_error("invalid argument for option %s", "-m"); pg_log_error("invalid argument for option %s", "-m");
@@ -262,21 +286,21 @@ main(int argc, char *argv[])
* XXX It'd be nice to have more sanity checks here, e.g. so * XXX It'd be nice to have more sanity checks here, e.g. so
* that oldest is not wrapped around w.r.t. nextMulti. * that oldest is not wrapped around w.r.t. nextMulti.
*/ */
if (set_oldestmxid == 0) if (oldest_mxid_val == 0)
pg_fatal("oldest multitransaction ID (-m) must not be 0"); pg_fatal("oldest multitransaction ID (-m) must not be 0");
mxid_given = true; mxids_given = true;
break; break;
case 'O': case 'O':
errno = 0; errno = 0;
set_mxoff = strtouint32_strict(optarg, &endptr, 0); next_mxoff_val = strtouint32_strict(optarg, &endptr, 0);
if (endptr == optarg || *endptr != '\0' || errno != 0) if (endptr == optarg || *endptr != '\0' || errno != 0)
{ {
pg_log_error("invalid argument for option %s", "-O"); pg_log_error("invalid argument for option %s", "-O");
pg_log_error_hint("Try \"%s --help\" for more information.", progname); pg_log_error_hint("Try \"%s --help\" for more information.", progname);
exit(1); exit(1);
} }
mxoff_given = true; next_mxoff_given = true;
break; break;
case 'l': case 'l':
@@ -300,9 +324,10 @@ main(int argc, char *argv[])
if (!option_parse_int(optarg, "--wal-segsize", 1, 1024, &wal_segsize_mb)) if (!option_parse_int(optarg, "--wal-segsize", 1, 1024, &wal_segsize_mb))
exit(1); exit(1);
set_wal_segsize = wal_segsize_mb * 1024 * 1024; wal_segsize_val = wal_segsize_mb * 1024 * 1024;
if (!IsValidWalSegSize(set_wal_segsize)) if (!IsValidWalSegSize(wal_segsize_val))
pg_fatal("argument of %s must be a power of two between 1 and 1024", "--wal-segsize"); pg_fatal("argument of %s must be a power of two between 1 and 1024", "--wal-segsize");
wal_segsize_given = true;
break; break;
} }
@@ -311,15 +336,16 @@ main(int argc, char *argv[])
errno = 0; errno = 0;
if (pg_strcasecmp(optarg, "signed") == 0) if (pg_strcasecmp(optarg, "signed") == 0)
set_char_signedness = 1; char_signedness_val = true;
else if (pg_strcasecmp(optarg, "unsigned") == 0) else if (pg_strcasecmp(optarg, "unsigned") == 0)
set_char_signedness = 0; char_signedness_val = false;
else else
{ {
pg_log_error("invalid argument for option %s", "--char-signedness"); pg_log_error("invalid argument for option %s", "--char-signedness");
pg_log_error_hint("Try \"%s --help\" for more information.", progname); pg_log_error_hint("Try \"%s --help\" for more information.", progname);
exit(1); exit(1);
} }
char_signedness_given = true;
break; break;
} }
@@ -407,8 +433,8 @@ main(int argc, char *argv[])
/* /*
* If no new WAL segment size was specified, use the control file value. * If no new WAL segment size was specified, use the control file value.
*/ */
if (set_wal_segsize != 0) if (wal_segsize_given)
WalSegSz = set_wal_segsize; WalSegSz = wal_segsize_val;
else else
WalSegSz = ControlFile.xlog_seg_size; WalSegSz = ControlFile.xlog_seg_size;
@@ -431,42 +457,43 @@ main(int argc, char *argv[])
* Adjust fields if required by switches. (Do this now so that printout, * Adjust fields if required by switches. (Do this now so that printout,
* if any, includes these values.) * if any, includes these values.)
*/ */
if (set_xid_epoch != -1) if (next_xid_epoch_given)
ControlFile.checkPointCopy.nextXid = ControlFile.checkPointCopy.nextXid =
FullTransactionIdFromEpochAndXid(set_xid_epoch, FullTransactionIdFromEpochAndXid(next_xid_epoch_val,
XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid)); XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
if (set_oldest_xid != 0) if (oldest_xid_given)
{ {
ControlFile.checkPointCopy.oldestXid = set_oldest_xid; ControlFile.checkPointCopy.oldestXid = oldest_xid_val;
ControlFile.checkPointCopy.oldestXidDB = InvalidOid; ControlFile.checkPointCopy.oldestXidDB = InvalidOid;
} }
if (set_xid != 0) if (next_xid_given)
ControlFile.checkPointCopy.nextXid = ControlFile.checkPointCopy.nextXid =
FullTransactionIdFromEpochAndXid(EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), FullTransactionIdFromEpochAndXid(EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid),
set_xid); next_xid_val);
if (set_oldest_commit_ts_xid != 0) if (commit_ts_xids_given)
ControlFile.checkPointCopy.oldestCommitTsXid = set_oldest_commit_ts_xid;
if (set_newest_commit_ts_xid != 0)
ControlFile.checkPointCopy.newestCommitTsXid = set_newest_commit_ts_xid;
if (set_oid != 0)
ControlFile.checkPointCopy.nextOid = set_oid;
if (mxid_given)
{ {
ControlFile.checkPointCopy.nextMulti = set_mxid; ControlFile.checkPointCopy.oldestCommitTsXid = oldest_commit_ts_xid_val;
ControlFile.checkPointCopy.newestCommitTsXid = newest_commit_ts_xid_val;
}
ControlFile.checkPointCopy.oldestMulti = set_oldestmxid; if (next_oid_given)
ControlFile.checkPointCopy.nextOid = next_oid_val;
if (mxids_given)
{
ControlFile.checkPointCopy.nextMulti = next_mxid_val;
ControlFile.checkPointCopy.oldestMulti = oldest_mxid_val;
if (ControlFile.checkPointCopy.oldestMulti < FirstMultiXactId) if (ControlFile.checkPointCopy.oldestMulti < FirstMultiXactId)
ControlFile.checkPointCopy.oldestMulti += FirstMultiXactId; ControlFile.checkPointCopy.oldestMulti += FirstMultiXactId;
ControlFile.checkPointCopy.oldestMultiDB = InvalidOid; ControlFile.checkPointCopy.oldestMultiDB = InvalidOid;
} }
if (mxoff_given) if (next_mxoff_given)
ControlFile.checkPointCopy.nextMultiOffset = set_mxoff; ControlFile.checkPointCopy.nextMultiOffset = next_mxoff_val;
if (minXlogTli > ControlFile.checkPointCopy.ThisTimeLineID) if (minXlogTli > ControlFile.checkPointCopy.ThisTimeLineID)
{ {
@@ -474,11 +501,11 @@ main(int argc, char *argv[])
ControlFile.checkPointCopy.PrevTimeLineID = minXlogTli; ControlFile.checkPointCopy.PrevTimeLineID = minXlogTli;
} }
if (set_wal_segsize != 0) if (wal_segsize_given)
ControlFile.xlog_seg_size = WalSegSz; ControlFile.xlog_seg_size = WalSegSz;
if (set_char_signedness != -1) if (char_signedness_given)
ControlFile.default_char_signedness = (set_char_signedness == 1); ControlFile.default_char_signedness = char_signedness_val;
if (minXlogSegNo > newXlogSegNo) if (minXlogSegNo > newXlogSegNo)
newXlogSegNo = minXlogSegNo; newXlogSegNo = minXlogSegNo;
@@ -809,7 +836,7 @@ PrintNewControlValues(void)
newXlogSegNo, WalSegSz); newXlogSegNo, WalSegSz);
printf(_("First log segment after reset: %s\n"), fname); printf(_("First log segment after reset: %s\n"), fname);
if (mxid_given) if (mxids_given)
{ {
printf(_("NextMultiXactId: %u\n"), printf(_("NextMultiXactId: %u\n"),
ControlFile.checkPointCopy.nextMulti); ControlFile.checkPointCopy.nextMulti);
@@ -819,25 +846,25 @@ PrintNewControlValues(void)
ControlFile.checkPointCopy.oldestMultiDB); ControlFile.checkPointCopy.oldestMultiDB);
} }
if (mxoff_given) if (next_mxoff_given)
{ {
printf(_("NextMultiOffset: %u\n"), printf(_("NextMultiOffset: %u\n"),
ControlFile.checkPointCopy.nextMultiOffset); ControlFile.checkPointCopy.nextMultiOffset);
} }
if (set_oid != 0) if (next_oid_given)
{ {
printf(_("NextOID: %u\n"), printf(_("NextOID: %u\n"),
ControlFile.checkPointCopy.nextOid); ControlFile.checkPointCopy.nextOid);
} }
if (set_xid != 0) if (next_xid_given)
{ {
printf(_("NextXID: %u\n"), printf(_("NextXID: %u\n"),
XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid)); XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
} }
if (set_oldest_xid != 0) if (oldest_xid_given)
{ {
printf(_("OldestXID: %u\n"), printf(_("OldestXID: %u\n"),
ControlFile.checkPointCopy.oldestXid); ControlFile.checkPointCopy.oldestXid);
@@ -845,24 +872,21 @@ PrintNewControlValues(void)
ControlFile.checkPointCopy.oldestXidDB); ControlFile.checkPointCopy.oldestXidDB);
} }
if (set_xid_epoch != -1) if (next_xid_epoch_given)
{ {
printf(_("NextXID epoch: %u\n"), printf(_("NextXID epoch: %u\n"),
EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid)); EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
} }
if (set_oldest_commit_ts_xid != 0) if (commit_ts_xids_given)
{ {
printf(_("oldestCommitTsXid: %u\n"), printf(_("oldestCommitTsXid: %u\n"),
ControlFile.checkPointCopy.oldestCommitTsXid); ControlFile.checkPointCopy.oldestCommitTsXid);
}
if (set_newest_commit_ts_xid != 0)
{
printf(_("newestCommitTsXid: %u\n"), printf(_("newestCommitTsXid: %u\n"),
ControlFile.checkPointCopy.newestCommitTsXid); ControlFile.checkPointCopy.newestCommitTsXid);
} }
if (set_wal_segsize != 0) if (wal_segsize_given)
{ {
printf(_("Bytes per WAL segment: %u\n"), printf(_("Bytes per WAL segment: %u\n"),
ControlFile.xlog_seg_size); ControlFile.xlog_seg_size);