PostgreSQL Source Code  git master
pg_resetwal.c File Reference
#include "postgres.h"
#include <dirent.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
#include "access/transam.h"
#include "access/tuptoaster.h"
#include "access/multixact.h"
#include "access/xlog.h"
#include "access/xlog_internal.h"
#include "catalog/catversion.h"
#include "catalog/pg_control.h"
#include "common/fe_memutils.h"
#include "common/file_perm.h"
#include "common/restricted_token.h"
#include "storage/large_object.h"
#include "pg_getopt.h"
#include "getopt_long.h"
Include dependency graph for pg_resetwal.c:

Go to the source code of this file.

Macros

#define FRONTEND   1
 
#define ARCHSTATDIR   XLOGDIR "/archive_status"
 

Functions

static void CheckDataVersion (void)
 
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)
 
static void KillExistingArchiveStatus (void)
 
static void WriteEmptyXLOG (void)
 
static void usage (void)
 
int main (int argc, char *argv[])
 

Variables

static ControlFileData ControlFile
 
static XLogSegNo newXlogSegNo
 
static bool guessed = false
 
static const char * progname
 
static uint32 set_xid_epoch = (uint32) -1
 
static TransactionId set_xid = 0
 
static TransactionId set_oldest_commit_ts_xid = 0
 
static TransactionId set_newest_commit_ts_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 int WalSegSz
 
static int set_wal_segsize
 

Macro Definition Documentation

◆ ARCHSTATDIR

#define ARCHSTATDIR   XLOGDIR "/archive_status"

◆ FRONTEND

#define FRONTEND   1

Definition at line 36 of file pg_resetwal.c.

Function Documentation

◆ CheckDataVersion()

static void CheckDataVersion ( void  )
static

Definition at line 539 of file pg_resetwal.c.

References _, progname, and strerror().

Referenced by main().

540 {
541  const char *ver_file = "PG_VERSION";
542  FILE *ver_fd;
543  char rawline[64];
544  int len;
545 
546  if ((ver_fd = fopen(ver_file, "r")) == NULL)
547  {
548  fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
549  progname, ver_file, strerror(errno));
550  exit(1);
551  }
552 
553  /* version number has to be the first line read */
554  if (!fgets(rawline, sizeof(rawline), ver_fd))
555  {
556  if (!ferror(ver_fd))
557  {
558  fprintf(stderr, _("%s: unexpected empty file \"%s\"\n"),
559  progname, ver_file);
560  }
561  else
562  {
563  fprintf(stderr, _("%s: could not read file \"%s\": %s\n"),
564  progname, ver_file, strerror(errno));
565  }
566  exit(1);
567  }
568 
569  /* remove trailing newline, handling Windows newlines as well */
570  len = strlen(rawline);
571  if (len > 0 && rawline[len - 1] == '\n')
572  {
573  rawline[--len] = '\0';
574  if (len > 0 && rawline[len - 1] == '\r')
575  rawline[--len] = '\0';
576  }
577 
578  if (strcmp(rawline, PG_MAJORVERSION) != 0)
579  {
580  fprintf(stderr, _("%s: data directory is of wrong version\n"
581  "File \"%s\" contains \"%s\", which is not compatible with this program's version \"%s\".\n"),
582  progname, ver_file, rawline, PG_MAJORVERSION);
583  exit(1);
584  }
585 
586  fclose(ver_fd);
587 }
static const char * progname
Definition: pg_resetwal.c:65
const char * strerror(int errnum)
Definition: strerror.c:19
#define _(x)
Definition: elog.c:84

◆ FindEndOfXLOG()

static void FindEndOfXLOG ( void  )
static

Definition at line 1019 of file pg_resetwal.c.

References _, ControlFileData::checkPointCopy, closedir(), dirent::d_name, IsPartialXLogFileName, IsXLogFileName, newXlogSegNo, opendir(), progname, readdir(), CheckPoint::redo, strerror(), WalSegSz, ControlFileData::xlog_seg_size, and XLOGDIR.

Referenced by main().

1020 {
1021  DIR *xldir;
1022  struct dirent *xlde;
1023  uint64 segs_per_xlogid;
1024  uint64 xlogbytepos;
1025 
1026  /*
1027  * Initialize the max() computation using the last checkpoint address from
1028  * old pg_control. Note that for the moment we are working with segment
1029  * numbering according to the old xlog seg size.
1030  */
1031  segs_per_xlogid = (UINT64CONST(0x0000000100000000) / ControlFile.xlog_seg_size);
1033 
1034  /*
1035  * Scan the pg_wal directory to find existing WAL segment files. We assume
1036  * any present have been used; in most scenarios this should be
1037  * conservative, because of xlog.c's attempts to pre-create files.
1038  */
1039  xldir = opendir(XLOGDIR);
1040  if (xldir == NULL)
1041  {
1042  fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
1043  progname, XLOGDIR, strerror(errno));
1044  exit(1);
1045  }
1046 
1047  while (errno = 0, (xlde = readdir(xldir)) != NULL)
1048  {
1049  if (IsXLogFileName(xlde->d_name) ||
1051  {
1052  unsigned int tli,
1053  log,
1054  seg;
1055  XLogSegNo segno;
1056 
1057  /*
1058  * Note: We don't use XLogFromFileName here, because we want to
1059  * use the segment size from the control file, not the size the
1060  * pg_resetwal binary was compiled with
1061  */
1062  sscanf(xlde->d_name, "%08X%08X%08X", &tli, &log, &seg);
1063  segno = ((uint64) log) * segs_per_xlogid + seg;
1064 
1065  /*
1066  * Note: we take the max of all files found, regardless of their
1067  * timelines. Another possibility would be to ignore files of
1068  * timelines other than the target TLI, but this seems safer.
1069  * Better too large a result than too small...
1070  */
1071  if (segno > newXlogSegNo)
1072  newXlogSegNo = segno;
1073  }
1074  }
1075 
1076  if (errno)
1077  {
1078  fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
1079  progname, XLOGDIR, strerror(errno));
1080  exit(1);
1081  }
1082 
1083  if (closedir(xldir))
1084  {
1085  fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
1086  progname, XLOGDIR, strerror(errno));
1087  exit(1);
1088  }
1089 
1090  /*
1091  * Finally, convert to new xlog seg size, and advance by one to ensure we
1092  * are in virgin territory.
1093  */
1094  xlogbytepos = newXlogSegNo * ControlFile.xlog_seg_size;
1095  newXlogSegNo = (xlogbytepos + ControlFile.xlog_seg_size - 1) / WalSegSz;
1096  newXlogSegNo++;
1097 }
int closedir(DIR *)
Definition: dirent.c:111
CheckPoint checkPointCopy
Definition: pg_control.h:131
Definition: dirent.h:9
uint32 xlog_seg_size
Definition: pg_control.h:208
Definition: dirent.c:25
#define IsXLogFileName(fname)
DIR * opendir(const char *)
Definition: dirent.c:33
uint64 XLogSegNo
Definition: xlogdefs.h:34
static const char * progname
Definition: pg_resetwal.c:65
#define XLOGDIR
static int WalSegSz
Definition: pg_resetwal.c:75
static ControlFileData ControlFile
Definition: pg_resetwal.c:62
struct dirent * readdir(DIR *)
Definition: dirent.c:77
static XLogSegNo newXlogSegNo
Definition: pg_resetwal.c:63
#define IsPartialXLogFileName(fname)
const char * strerror(int errnum)
Definition: strerror.c:19
char d_name[MAX_PATH]
Definition: dirent.h:14
#define _(x)
Definition: elog.c:84
XLogRecPtr redo
Definition: pg_control.h:36

◆ GuessControlValues()

static void GuessControlValues ( void  )
static

Definition at line 677 of file pg_resetwal.c.

References ControlFileData::blcksz, CATALOG_VERSION_NO, ControlFileData::catalog_version_no, ControlFileData::checkPoint, ControlFileData::checkPointCopy, DB_SHUTDOWNED, DEFAULT_XLOG_SEG_SIZE, FirstBootstrapObjectId, FirstMultiXactId, FirstNormalTransactionId, ControlFileData::float4ByVal, ControlFileData::float8ByVal, ControlFileData::floatFormat, FLOATFORMAT_VALUE, CheckPoint::fullPageWrites, gettimeofday(), guessed, INDEX_MAX_KEYS, ControlFileData::indexMaxKeys, InvalidOid, InvalidTransactionId, LOBLKSIZE, ControlFileData::loblksize, ControlFileData::max_locks_per_xact, ControlFileData::max_prepared_xacts, ControlFileData::max_worker_processes, ControlFileData::maxAlign, ControlFileData::MaxConnections, NAMEDATALEN, ControlFileData::nameDataLen, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, CheckPoint::nextOid, CheckPoint::nextXid, CheckPoint::nextXidEpoch, CheckPoint::oldestActiveXid, CheckPoint::oldestMulti, CheckPoint::oldestMultiDB, CheckPoint::oldestXid, CheckPoint::oldestXidDB, PG_CONTROL_VERSION, ControlFileData::pg_control_version, CheckPoint::PrevTimeLineID, CheckPoint::redo, ControlFileData::relseg_size, SizeOfXLogLongPHD, ControlFileData::state, ControlFileData::system_identifier, CheckPoint::ThisTimeLineID, CheckPoint::time, ControlFileData::time, TOAST_MAX_CHUNK_SIZE, ControlFileData::toast_max_chunk_size, ControlFileData::track_commit_timestamp, ControlFileData::unloggedLSN, ControlFileData::wal_level, WAL_LEVEL_MINIMAL, ControlFileData::wal_log_hints, ControlFileData::xlog_blcksz, and ControlFileData::xlog_seg_size.

Referenced by main().

678 {
679  uint64 sysidentifier;
680  struct timeval tv;
681 
682  /*
683  * Set up a completely default set of pg_control values.
684  */
685  guessed = true;
686  memset(&ControlFile, 0, sizeof(ControlFile));
687 
690 
691  /*
692  * Create a new unique installation identifier, since we can no longer use
693  * any old XLOG records. See notes in xlog.c about the algorithm.
694  */
695  gettimeofday(&tv, NULL);
696  sysidentifier = ((uint64) tv.tv_sec) << 32;
697  sysidentifier |= ((uint64) tv.tv_usec) << 12;
698  sysidentifier |= getpid() & 0xFFF;
699 
700  ControlFile.system_identifier = sysidentifier;
701 
715  ControlFile.checkPointCopy.time = (pg_time_t) time(NULL);
717 
719  ControlFile.time = (pg_time_t) time(NULL);
722 
723  /* minRecoveryPoint, backupStartPoint and backupEndPoint can be left zero */
724 
726  ControlFile.wal_log_hints = false;
732 
733  ControlFile.maxAlign = MAXIMUM_ALIGNOF;
735  ControlFile.blcksz = BLCKSZ;
736  ControlFile.relseg_size = RELSEG_SIZE;
737  ControlFile.xlog_blcksz = XLOG_BLCKSZ;
743  ControlFile.float4ByVal = FLOAT4PASSBYVAL;
744  ControlFile.float8ByVal = FLOAT8PASSBYVAL;
745 
746  /*
747  * XXX eventually, should try to grovel through old XLOG to develop more
748  * accurate values for TimeLineID, nextXID, etc.
749  */
750 }
#define LOBLKSIZE
Definition: large_object.h:70
int max_locks_per_xact
Definition: pg_control.h:181
int gettimeofday(struct timeval *tp, struct timezone *tzp)
Definition: gettimeofday.c:105
int max_prepared_xacts
Definition: pg_control.h:180
int64 pg_time_t
Definition: pgtime.h:23
pg_time_t time
Definition: pg_control.h:128
int max_worker_processes
Definition: pg_control.h:179
TransactionId oldestActiveXid
Definition: pg_control.h:63
uint32 nameDataLen
Definition: pg_control.h:210
MultiXactId oldestMulti
Definition: pg_control.h:49
#define DEFAULT_XLOG_SEG_SIZE
TimeLineID PrevTimeLineID
Definition: pg_control.h:39
#define CATALOG_VERSION_NO
Definition: catversion.h:56
#define PG_CONTROL_VERSION
Definition: pg_control.h:24
uint32 pg_control_version
Definition: pg_control.h:121
CheckPoint checkPointCopy
Definition: pg_control.h:131
uint32 xlog_blcksz
Definition: pg_control.h:207
TransactionId oldestXid
Definition: pg_control.h:47
TransactionId nextXid
Definition: pg_control.h:43
pg_time_t time
Definition: pg_control.h:51
#define NAMEDATALEN
MultiXactOffset nextMultiOffset
Definition: pg_control.h:46
uint32 xlog_seg_size
Definition: pg_control.h:208
#define FirstNormalTransactionId
Definition: transam.h:34
uint64 system_identifier
Definition: pg_control.h:106
uint32 nextXidEpoch
Definition: pg_control.h:42
XLogRecPtr unloggedLSN
Definition: pg_control.h:133
#define InvalidTransactionId
Definition: transam.h:31
#define FirstBootstrapObjectId
Definition: transam.h:93
#define FirstMultiXactId
Definition: multixact.h:24
uint32 loblksize
Definition: pg_control.h:214
uint32 indexMaxKeys
Definition: pg_control.h:211
static bool guessed
Definition: pg_resetwal.c:64
#define TOAST_MAX_CHUNK_SIZE
Definition: tuptoaster.h:91
Oid oldestMultiDB
Definition: pg_control.h:50
uint32 toast_max_chunk_size
Definition: pg_control.h:213
#define InvalidOid
Definition: postgres_ext.h:36
Oid nextOid
Definition: pg_control.h:44
bool fullPageWrites
Definition: pg_control.h:41
bool track_commit_timestamp
Definition: pg_control.h:182
Oid oldestXidDB
Definition: pg_control.h:48
static ControlFileData ControlFile
Definition: pg_resetwal.c:62
double floatFormat
Definition: pg_control.h:197
#define INDEX_MAX_KEYS
MultiXactId nextMulti
Definition: pg_control.h:45
uint32 catalog_version_no
Definition: pg_control.h:122
TimeLineID ThisTimeLineID
Definition: pg_control.h:38
#define FLOATFORMAT_VALUE
Definition: pg_control.h:198
uint32 relseg_size
Definition: pg_control.h:205
XLogRecPtr checkPoint
Definition: pg_control.h:129
XLogRecPtr redo
Definition: pg_control.h:36
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:72

◆ KillExistingArchiveStatus()

static void KillExistingArchiveStatus ( void  )
static

Definition at line 1153 of file pg_resetwal.c.

References _, ARCHSTATDIR, closedir(), dirent::d_name, MAXPGPATH, opendir(), progname, readdir(), snprintf(), strerror(), and XLOG_FNAME_LEN.

Referenced by main().

1154 {
1155 #define ARCHSTATDIR XLOGDIR "/archive_status"
1156 
1157  DIR *xldir;
1158  struct dirent *xlde;
1159  char path[MAXPGPATH + sizeof(ARCHSTATDIR)];
1160 
1161  xldir = opendir(ARCHSTATDIR);
1162  if (xldir == NULL)
1163  {
1164  fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
1165  progname, ARCHSTATDIR, strerror(errno));
1166  exit(1);
1167  }
1168 
1169  while (errno = 0, (xlde = readdir(xldir)) != NULL)
1170  {
1171  if (strspn(xlde->d_name, "0123456789ABCDEF") == XLOG_FNAME_LEN &&
1172  (strcmp(xlde->d_name + XLOG_FNAME_LEN, ".ready") == 0 ||
1173  strcmp(xlde->d_name + XLOG_FNAME_LEN, ".done") == 0 ||
1174  strcmp(xlde->d_name + XLOG_FNAME_LEN, ".partial.ready") == 0 ||
1175  strcmp(xlde->d_name + XLOG_FNAME_LEN, ".partial.done") == 0))
1176  {
1177  snprintf(path, sizeof(path), "%s/%s", ARCHSTATDIR, xlde->d_name);
1178  if (unlink(path) < 0)
1179  {
1180  fprintf(stderr, _("%s: could not delete file \"%s\": %s\n"),
1181  progname, path, strerror(errno));
1182  exit(1);
1183  }
1184  }
1185  }
1186 
1187  if (errno)
1188  {
1189  fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
1190  progname, ARCHSTATDIR, strerror(errno));
1191  exit(1);
1192  }
1193 
1194  if (closedir(xldir))
1195  {
1196  fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
1197  progname, ARCHSTATDIR, strerror(errno));
1198  exit(1);
1199  }
1200 }
int closedir(DIR *)
Definition: dirent.c:111
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
DIR * opendir(const char *)
Definition: dirent.c:33
static const char * progname
Definition: pg_resetwal.c:65
struct dirent * readdir(DIR *)
Definition: dirent.c:77
#define ARCHSTATDIR
const char * strerror(int errnum)
Definition: strerror.c:19
#define XLOG_FNAME_LEN
char d_name[MAX_PATH]
Definition: dirent.h:14
#define _(x)
Definition: elog.c:84

◆ KillExistingXLOG()

static void KillExistingXLOG ( void  )
static

Definition at line 1104 of file pg_resetwal.c.

References _, closedir(), dirent::d_name, IsPartialXLogFileName, IsXLogFileName, MAXPGPATH, opendir(), progname, readdir(), snprintf(), strerror(), and XLOGDIR.

Referenced by main().

1105 {
1106  DIR *xldir;
1107  struct dirent *xlde;
1108  char path[MAXPGPATH + sizeof(XLOGDIR)];
1109 
1110  xldir = opendir(XLOGDIR);
1111  if (xldir == NULL)
1112  {
1113  fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
1114  progname, XLOGDIR, strerror(errno));
1115  exit(1);
1116  }
1117 
1118  while (errno = 0, (xlde = readdir(xldir)) != NULL)
1119  {
1120  if (IsXLogFileName(xlde->d_name) ||
1122  {
1123  snprintf(path, sizeof(path), "%s/%s", XLOGDIR, xlde->d_name);
1124  if (unlink(path) < 0)
1125  {
1126  fprintf(stderr, _("%s: could not delete file \"%s\": %s\n"),
1127  progname, path, strerror(errno));
1128  exit(1);
1129  }
1130  }
1131  }
1132 
1133  if (errno)
1134  {
1135  fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
1136  progname, XLOGDIR, strerror(errno));
1137  exit(1);
1138  }
1139 
1140  if (closedir(xldir))
1141  {
1142  fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
1143  progname, XLOGDIR, strerror(errno));
1144  exit(1);
1145  }
1146 }
int closedir(DIR *)
Definition: dirent.c:111
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
Definition: dirent.h:9
Definition: dirent.c:25
#define IsXLogFileName(fname)
#define MAXPGPATH
DIR * opendir(const char *)
Definition: dirent.c:33
static const char * progname
Definition: pg_resetwal.c:65
#define XLOGDIR
struct dirent * readdir(DIR *)
Definition: dirent.c:77
#define IsPartialXLogFileName(fname)
const char * strerror(int errnum)
Definition: strerror.c:19
char d_name[MAX_PATH]
Definition: dirent.h:14
#define _(x)
Definition: elog.c:84

◆ main()

int main ( int  argc,
char *  argv[] 
)

Definition at line 92 of file pg_resetwal.c.

References _, CheckDataVersion(), ControlFileData::checkPointCopy, DataDir, DB_SHUTDOWNED, fd(), FindEndOfXLOG(), FirstMultiXactId, FirstNormalTransactionId, get_progname(), get_restricted_token(), GetDataDirectoryCreatePerm(), getopt_long(), GuessControlValues(), guessed, InvalidOid, IsValidWalSegSize, KillExistingArchiveStatus(), KillExistingXLOG(), minXlogSegNo, minXlogTli, CheckPoint::newestCommitTsXid, newXlogSegNo, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, CheckPoint::nextOid, CheckPoint::nextXid, CheckPoint::nextXidEpoch, no_argument, CheckPoint::oldestCommitTsXid, CheckPoint::oldestMulti, CheckPoint::oldestMultiDB, CheckPoint::oldestXid, CheckPoint::oldestXidDB, optarg, optind, pg_mode_mask, pg_strdup(), PG_TEXTDOMAIN, CheckPoint::PrevTimeLineID, PrintControlValues(), PrintNewControlValues(), progname, ReadControlFile(), required_argument, RewriteControlFile(), set_mxid, set_mxoff, set_newest_commit_ts_xid, set_oid, set_oldest_commit_ts_xid, set_pglocale_pgservice(), set_wal_segsize, set_xid, set_xid_epoch, ControlFileData::state, strerror(), CheckPoint::ThisTimeLineID, usage(), WalSegSz, WriteEmptyXLOG(), XLOG_FNAME_LEN, ControlFileData::xlog_seg_size, and XLogFromFileName.

93 {
94  static struct option long_options[] = {
95  {"commit-timestamp-ids", required_argument, NULL, 'c'},
96  {"pgdata", required_argument, NULL, 'D'},
97  {"epoch", required_argument, NULL, 'e'},
98  {"force", no_argument, NULL, 'f'},
99  {"next-wal-file", required_argument, NULL, 'l'},
100  {"multixact-ids", required_argument, NULL, 'm'},
101  {"dry-run", no_argument, NULL, 'n'},
102  {"next-oid", required_argument, NULL, 'o'},
103  {"multixact-offset", required_argument, NULL, 'O'},
104  {"next-transaction-id", required_argument, NULL, 'x'},
105  {"wal-segsize", required_argument, NULL, 1},
106  {NULL, 0, NULL, 0}
107  };
108 
109  int c;
110  bool force = false;
111  bool noupdate = false;
112  MultiXactId set_oldestmxid = 0;
113  char *endptr;
114  char *endptr2;
115  char *DataDir = NULL;
116  char *log_fname = NULL;
117  int fd;
118 
119  set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_resetwal"));
120 
121  progname = get_progname(argv[0]);
122 
123  if (argc > 1)
124  {
125  if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
126  {
127  usage();
128  exit(0);
129  }
130  if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
131  {
132  puts("pg_resetwal (PostgreSQL) " PG_VERSION);
133  exit(0);
134  }
135  }
136 
137 
138  while ((c = getopt_long(argc, argv, "c:D:e:fl:m:no:O:x:", long_options, NULL)) != -1)
139  {
140  switch (c)
141  {
142  case 'D':
143  DataDir = optarg;
144  break;
145 
146  case 'f':
147  force = true;
148  break;
149 
150  case 'n':
151  noupdate = true;
152  break;
153 
154  case 'e':
155  set_xid_epoch = strtoul(optarg, &endptr, 0);
156  if (endptr == optarg || *endptr != '\0')
157  {
158  /*------
159  translator: the second %s is a command line argument (-e, etc) */
160  fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-e");
161  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
162  exit(1);
163  }
164  if (set_xid_epoch == -1)
165  {
166  fprintf(stderr, _("%s: transaction ID epoch (-e) must not be -1\n"), progname);
167  exit(1);
168  }
169  break;
170 
171  case 'x':
172  set_xid = strtoul(optarg, &endptr, 0);
173  if (endptr == optarg || *endptr != '\0')
174  {
175  fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-x");
176  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
177  exit(1);
178  }
179  if (set_xid == 0)
180  {
181  fprintf(stderr, _("%s: transaction ID (-x) must not be 0\n"), progname);
182  exit(1);
183  }
184  break;
185 
186  case 'c':
187  set_oldest_commit_ts_xid = strtoul(optarg, &endptr, 0);
188  if (endptr == optarg || *endptr != ',')
189  {
190  fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-c");
191  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
192  exit(1);
193  }
194  set_newest_commit_ts_xid = strtoul(endptr + 1, &endptr2, 0);
195  if (endptr2 == endptr + 1 || *endptr2 != '\0')
196  {
197  fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-c");
198  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
199  exit(1);
200  }
201 
202  if (set_oldest_commit_ts_xid < 2 &&
204  {
205  fprintf(stderr, _("%s: transaction ID (-c) must be either 0 or greater than or equal to 2\n"), progname);
206  exit(1);
207  }
208 
209  if (set_newest_commit_ts_xid < 2 &&
211  {
212  fprintf(stderr, _("%s: transaction ID (-c) must be either 0 or greater than or equal to 2\n"), progname);
213  exit(1);
214  }
215  break;
216 
217  case 'o':
218  set_oid = strtoul(optarg, &endptr, 0);
219  if (endptr == optarg || *endptr != '\0')
220  {
221  fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-o");
222  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
223  exit(1);
224  }
225  if (set_oid == 0)
226  {
227  fprintf(stderr, _("%s: OID (-o) must not be 0\n"), progname);
228  exit(1);
229  }
230  break;
231 
232  case 'm':
233  set_mxid = strtoul(optarg, &endptr, 0);
234  if (endptr == optarg || *endptr != ',')
235  {
236  fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-m");
237  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
238  exit(1);
239  }
240 
241  set_oldestmxid = strtoul(endptr + 1, &endptr2, 0);
242  if (endptr2 == endptr + 1 || *endptr2 != '\0')
243  {
244  fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-m");
245  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
246  exit(1);
247  }
248  if (set_mxid == 0)
249  {
250  fprintf(stderr, _("%s: multitransaction ID (-m) must not be 0\n"), progname);
251  exit(1);
252  }
253 
254  /*
255  * XXX It'd be nice to have more sanity checks here, e.g. so
256  * that oldest is not wrapped around w.r.t. nextMulti.
257  */
258  if (set_oldestmxid == 0)
259  {
260  fprintf(stderr, _("%s: oldest multitransaction ID (-m) must not be 0\n"),
261  progname);
262  exit(1);
263  }
264  break;
265 
266  case 'O':
267  set_mxoff = strtoul(optarg, &endptr, 0);
268  if (endptr == optarg || *endptr != '\0')
269  {
270  fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-O");
271  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
272  exit(1);
273  }
274  if (set_mxoff == -1)
275  {
276  fprintf(stderr, _("%s: multitransaction offset (-O) must not be -1\n"), progname);
277  exit(1);
278  }
279  break;
280 
281  case 'l':
282  if (strspn(optarg, "01234567890ABCDEFabcdef") != XLOG_FNAME_LEN)
283  {
284  fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-l");
285  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
286  exit(1);
287  }
288 
289  /*
290  * XLogFromFileName requires wal segment size which is not yet
291  * set. Hence wal details are set later on.
292  */
293  log_fname = pg_strdup(optarg);
294  break;
295 
296  case 1:
297  set_wal_segsize = strtol(optarg, &endptr, 10) * 1024 * 1024;
298  if (endptr == optarg || *endptr != '\0')
299  {
300  fprintf(stderr,
301  _("%s: argument of --wal-segsize must be a number\n"),
302  progname);
303  exit(1);
304  }
306  {
307  fprintf(stderr,
308  _("%s: argument of --wal-segsize must be a power of 2 between 1 and 1024\n"),
309  progname);
310  exit(1);
311  }
312  break;
313 
314  default:
315  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
316  exit(1);
317  }
318  }
319 
320  if (DataDir == NULL && optind < argc)
321  DataDir = argv[optind++];
322 
323  /* Complain if any arguments remain */
324  if (optind < argc)
325  {
326  fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
327  progname, argv[optind]);
328  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
329  progname);
330  exit(1);
331  }
332 
333  if (DataDir == NULL)
334  {
335  fprintf(stderr, _("%s: no data directory specified\n"), progname);
336  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
337  exit(1);
338  }
339 
340  /*
341  * Don't allow pg_resetwal to be run as root, to avoid overwriting the
342  * ownership of files in the data directory. We need only check for root
343  * -- any other user won't have sufficient permissions to modify files in
344  * the data directory.
345  */
346 #ifndef WIN32
347  if (geteuid() == 0)
348  {
349  fprintf(stderr, _("%s: cannot be executed by \"root\"\n"),
350  progname);
351  fprintf(stderr, _("You must run %s as the PostgreSQL superuser.\n"),
352  progname);
353  exit(1);
354  }
355 #endif
356 
358 
359  if (chdir(DataDir) < 0)
360  {
361  fprintf(stderr, _("%s: could not change directory to \"%s\": %s\n"),
362  progname, DataDir, strerror(errno));
363  exit(1);
364  }
365 
366  /* Set mask based on PGDATA permissions */
367  if (!GetDataDirectoryCreatePerm(DataDir))
368  {
369  fprintf(stderr, _("%s: unable to read permissions from \"%s\"\n"),
370  progname, DataDir);
371  exit(1);
372  }
373 
374  umask(pg_mode_mask);
375 
376  /* Check that data directory matches our server version */
378 
379  /*
380  * Check for a postmaster lock file --- if there is one, refuse to
381  * proceed, on grounds we might be interfering with a live installation.
382  */
383  if ((fd = open("postmaster.pid", O_RDONLY, 0)) < 0)
384  {
385  if (errno != ENOENT)
386  {
387  fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
388  progname, "postmaster.pid", strerror(errno));
389  exit(1);
390  }
391  }
392  else
393  {
394  fprintf(stderr, _("%s: lock file \"%s\" exists\n"
395  "Is a server running? If not, delete the lock file and try again.\n"),
396  progname, "postmaster.pid");
397  exit(1);
398  }
399 
400  /*
401  * Attempt to read the existing pg_control file
402  */
403  if (!ReadControlFile())
405 
406  /*
407  * If no new WAL segment size was specified, use the control file value.
408  */
409  if (set_wal_segsize != 0)
411  else
413 
414  if (log_fname != NULL)
416 
417  /*
418  * Also look at existing segment files to set up newXlogSegNo
419  */
420  FindEndOfXLOG();
421 
422  /*
423  * If we're not going to proceed with the reset, print the current control
424  * file parameters.
425  */
426  if ((guessed && !force) || noupdate)
428 
429  /*
430  * Adjust fields if required by switches. (Do this now so that printout,
431  * if any, includes these values.)
432  */
433  if (set_xid_epoch != -1)
435 
436  if (set_xid != 0)
437  {
439 
440  /*
441  * For the moment, just set oldestXid to a value that will force
442  * immediate autovacuum-for-wraparound. It's not clear whether adding
443  * user control of this is useful, so let's just do something that's
444  * reasonably safe. The magic constant here corresponds to the
445  * maximum allowed value of autovacuum_freeze_max_age.
446  */
451  }
452 
453  if (set_oldest_commit_ts_xid != 0)
455  if (set_newest_commit_ts_xid != 0)
457 
458  if (set_oid != 0)
460 
461  if (set_mxid != 0)
462  {
464 
465  ControlFile.checkPointCopy.oldestMulti = set_oldestmxid;
469  }
470 
471  if (set_mxoff != -1)
473 
475  {
478  }
479 
480  if (set_wal_segsize != 0)
482 
485 
486  /*
487  * If we had to guess anything, and -f was not given, just print the
488  * guessed values and exit. Also print if -n is given.
489  */
490  if ((guessed && !force) || noupdate)
491  {
493  if (!noupdate)
494  {
495  printf(_("\nIf these values seem acceptable, use -f to force reset.\n"));
496  exit(1);
497  }
498  else
499  exit(0);
500  }
501 
502  /*
503  * Don't reset from a dirty pg_control without -f, either.
504  */
505  if (ControlFile.state != DB_SHUTDOWNED && !force)
506  {
507  printf(_("The database server was not shut down cleanly.\n"
508  "Resetting the write-ahead log might cause data to be lost.\n"
509  "If you want to proceed anyway, use -f to force reset.\n"));
510  exit(1);
511  }
512 
513  /*
514  * Else, do the dirty deed.
515  */
519  WriteEmptyXLOG();
520 
521  printf(_("Write-ahead log reset\n"));
522  return 0;
523 }
static void PrintControlValues(bool guessed)
Definition: pg_resetwal.c:760
#define IsValidWalSegSize(size)
Definition: xlog_internal.h:97
static MultiXactId set_mxid
Definition: pg_resetwal.c:71
static void usage(void)
Definition: pg_resetwal.c:1308
static TransactionId set_xid
Definition: pg_resetwal.c:67
static int set_wal_segsize
Definition: pg_resetwal.c:76
const char * get_progname(const char *argv0)
Definition: path.c:453
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition: getopt_long.c:57
static void PrintNewControlValues(void)
Definition: pg_resetwal.c:844
MultiXactId oldestMulti
Definition: pg_control.h:49
static void FindEndOfXLOG(void)
Definition: pg_resetwal.c:1019
TimeLineID PrevTimeLineID
Definition: pg_control.h:39
static void WriteEmptyXLOG(void)
Definition: pg_resetwal.c:1208
static Oid set_oid
Definition: pg_resetwal.c:70
CheckPoint checkPointCopy
Definition: pg_control.h:131
TransactionId oldestXid
Definition: pg_control.h:47
TransactionId nextXid
Definition: pg_control.h:43
static void CheckDataVersion(void)
Definition: pg_resetwal.c:539
static int fd(const char *x, int i)
Definition: preproc-init.c:105
static bool ReadControlFile(void)
Definition: pg_resetwal.c:597
void get_restricted_token(const char *progname)
static TransactionId set_newest_commit_ts_xid
Definition: pg_resetwal.c:69
static void KillExistingXLOG(void)
Definition: pg_resetwal.c:1104
MultiXactOffset nextMultiOffset
Definition: pg_control.h:46
#define required_argument
Definition: getopt_long.h:25
TransactionId oldestCommitTsXid
Definition: pg_control.h:52
uint32 xlog_seg_size
Definition: pg_control.h:208
int optind
Definition: getopt.c:51
static void KillExistingArchiveStatus(void)
Definition: pg_resetwal.c:1153
#define FirstNormalTransactionId
Definition: transam.h:34
uint32 nextXidEpoch
Definition: pg_control.h:42
static TransactionId set_oldest_commit_ts_xid
Definition: pg_resetwal.c:68
#define XLogFromFileName(fname, tli, logSegNo, wal_segsz_bytes)
char * c
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
#define FirstMultiXactId
Definition: multixact.h:24
static const char * progname
Definition: pg_resetwal.c:65
static bool guessed
Definition: pg_resetwal.c:64
#define no_argument
Definition: getopt_long.h:24
TransactionId newestCommitTsXid
Definition: pg_control.h:54
#define PG_TEXTDOMAIN(domain)
Definition: c.h:1054
Oid oldestMultiDB
Definition: pg_control.h:50
#define InvalidOid
Definition: postgres_ext.h:36
Oid nextOid
Definition: pg_control.h:44
static int WalSegSz
Definition: pg_resetwal.c:75
TransactionId MultiXactId
Definition: c.h:484
Oid oldestXidDB
Definition: pg_control.h:48
static ControlFileData ControlFile
Definition: pg_resetwal.c:62
MultiXactId nextMulti
Definition: pg_control.h:45
static void RewriteControlFile(void)
Definition: pg_resetwal.c:916
static MultiXactOffset set_mxoff
Definition: pg_resetwal.c:72
static XLogSegNo newXlogSegNo
Definition: pg_resetwal.c:63
bool GetDataDirectoryCreatePerm(const char *dataDir)
static void GuessControlValues(void)
Definition: pg_resetwal.c:677
static uint32 minXlogTli
Definition: pg_resetwal.c:73
TimeLineID ThisTimeLineID
Definition: pg_control.h:38
void set_pglocale_pgservice(const char *argv0, const char *app)
Definition: exec.c:550
char * optarg
Definition: getopt.c:53
const char * strerror(int errnum)
Definition: strerror.c:19
char * DataDir
Definition: globals.c:63
#define XLOG_FNAME_LEN
#define _(x)
Definition: elog.c:84
static XLogSegNo minXlogSegNo
Definition: pg_resetwal.c:74
int pg_mode_mask
Definition: file_perm.c:26
static uint32 set_xid_epoch
Definition: pg_resetwal.c:66

◆ PrintControlValues()

static void PrintControlValues ( bool  guessed)
static

Definition at line 760 of file pg_resetwal.c.

References _, ControlFileData::blcksz, ControlFileData::catalog_version_no, ControlFileData::checkPointCopy, ControlFileData::data_checksum_version, ControlFileData::float4ByVal, ControlFileData::float8ByVal, CheckPoint::fullPageWrites, ControlFileData::indexMaxKeys, ControlFileData::loblksize, ControlFileData::maxAlign, ControlFileData::nameDataLen, CheckPoint::newestCommitTsXid, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, CheckPoint::nextOid, CheckPoint::nextXid, CheckPoint::nextXidEpoch, CheckPoint::oldestActiveXid, CheckPoint::oldestCommitTsXid, CheckPoint::oldestMulti, CheckPoint::oldestMultiDB, CheckPoint::oldestXid, CheckPoint::oldestXidDB, ControlFileData::pg_control_version, ControlFileData::relseg_size, snprintf(), ControlFileData::system_identifier, CheckPoint::ThisTimeLineID, ControlFileData::toast_max_chunk_size, UINT64_FORMAT, ControlFileData::xlog_blcksz, and ControlFileData::xlog_seg_size.

Referenced by main().

761 {
762  char sysident_str[32];
763 
764  if (guessed)
765  printf(_("Guessed pg_control values:\n\n"));
766  else
767  printf(_("Current pg_control values:\n\n"));
768 
769  /*
770  * Format system_identifier separately to keep platform-dependent format
771  * code out of the translatable message string.
772  */
773  snprintf(sysident_str, sizeof(sysident_str), UINT64_FORMAT,
775 
776  printf(_("pg_control version number: %u\n"),
778  printf(_("Catalog version number: %u\n"),
780  printf(_("Database system identifier: %s\n"),
781  sysident_str);
782  printf(_("Latest checkpoint's TimeLineID: %u\n"),
784  printf(_("Latest checkpoint's full_page_writes: %s\n"),
785  ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off"));
786  printf(_("Latest checkpoint's NextXID: %u:%u\n"),
789  printf(_("Latest checkpoint's NextOID: %u\n"),
791  printf(_("Latest checkpoint's NextMultiXactId: %u\n"),
793  printf(_("Latest checkpoint's NextMultiOffset: %u\n"),
795  printf(_("Latest checkpoint's oldestXID: %u\n"),
797  printf(_("Latest checkpoint's oldestXID's DB: %u\n"),
799  printf(_("Latest checkpoint's oldestActiveXID: %u\n"),
801  printf(_("Latest checkpoint's oldestMultiXid: %u\n"),
803  printf(_("Latest checkpoint's oldestMulti's DB: %u\n"),
805  printf(_("Latest checkpoint's oldestCommitTsXid:%u\n"),
807  printf(_("Latest checkpoint's newestCommitTsXid:%u\n"),
809  printf(_("Maximum data alignment: %u\n"),
811  /* we don't print floatFormat since can't say much useful about it */
812  printf(_("Database block size: %u\n"),
814  printf(_("Blocks per segment of large relation: %u\n"),
816  printf(_("WAL block size: %u\n"),
818  printf(_("Bytes per WAL segment: %u\n"),
820  printf(_("Maximum length of identifiers: %u\n"),
822  printf(_("Maximum columns in an index: %u\n"),
824  printf(_("Maximum size of a TOAST chunk: %u\n"),
826  printf(_("Size of a large-object chunk: %u\n"),
828  /* This is no longer configurable, but users may still expect to see it: */
829  printf(_("Date/time type storage: %s\n"),
830  _("64-bit integers"));
831  printf(_("Float4 argument passing: %s\n"),
832  (ControlFile.float4ByVal ? _("by value") : _("by reference")));
833  printf(_("Float8 argument passing: %s\n"),
834  (ControlFile.float8ByVal ? _("by value") : _("by reference")));
835  printf(_("Data page checksum version: %u\n"),
837 }
TransactionId oldestActiveXid
Definition: pg_control.h:63
uint32 nameDataLen
Definition: pg_control.h:210
MultiXactId oldestMulti
Definition: pg_control.h:49
uint32 pg_control_version
Definition: pg_control.h:121
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
CheckPoint checkPointCopy
Definition: pg_control.h:131
uint32 xlog_blcksz
Definition: pg_control.h:207
TransactionId oldestXid
Definition: pg_control.h:47
TransactionId nextXid
Definition: pg_control.h:43
MultiXactOffset nextMultiOffset
Definition: pg_control.h:46
TransactionId oldestCommitTsXid
Definition: pg_control.h:52
uint32 xlog_seg_size
Definition: pg_control.h:208
uint64 system_identifier
Definition: pg_control.h:106
uint32 nextXidEpoch
Definition: pg_control.h:42
uint32 data_checksum_version
Definition: pg_control.h:221
uint32 loblksize
Definition: pg_control.h:214
uint32 indexMaxKeys
Definition: pg_control.h:211
static bool guessed
Definition: pg_resetwal.c:64
TransactionId newestCommitTsXid
Definition: pg_control.h:54
Oid oldestMultiDB
Definition: pg_control.h:50
uint32 toast_max_chunk_size
Definition: pg_control.h:213
Oid nextOid
Definition: pg_control.h:44
bool fullPageWrites
Definition: pg_control.h:41
Oid oldestXidDB
Definition: pg_control.h:48
static ControlFileData ControlFile
Definition: pg_resetwal.c:62
MultiXactId nextMulti
Definition: pg_control.h:45
uint32 catalog_version_no
Definition: pg_control.h:122
TimeLineID ThisTimeLineID
Definition: pg_control.h:38
#define _(x)
Definition: elog.c:84
#define UINT64_FORMAT
Definition: c.h:368
uint32 relseg_size
Definition: pg_control.h:205

◆ PrintNewControlValues()

static void PrintNewControlValues ( void  )
static

Definition at line 844 of file pg_resetwal.c.

References _, ControlFileData::checkPointCopy, MAXFNAMELEN, CheckPoint::newestCommitTsXid, newXlogSegNo, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, CheckPoint::nextOid, CheckPoint::nextXid, CheckPoint::nextXidEpoch, CheckPoint::oldestCommitTsXid, CheckPoint::oldestMulti, CheckPoint::oldestMultiDB, CheckPoint::oldestXid, CheckPoint::oldestXidDB, set_mxid, set_mxoff, set_newest_commit_ts_xid, set_oid, set_oldest_commit_ts_xid, set_wal_segsize, set_xid, set_xid_epoch, CheckPoint::ThisTimeLineID, WalSegSz, ControlFileData::xlog_seg_size, and XLogFileName.

Referenced by main().

845 {
846  char fname[MAXFNAMELEN];
847 
848  /* This will be always printed in order to keep format same. */
849  printf(_("\n\nValues to be changed:\n\n"));
850 
853  printf(_("First log segment after reset: %s\n"), fname);
854 
855  if (set_mxid != 0)
856  {
857  printf(_("NextMultiXactId: %u\n"),
859  printf(_("OldestMultiXid: %u\n"),
861  printf(_("OldestMulti's DB: %u\n"),
863  }
864 
865  if (set_mxoff != -1)
866  {
867  printf(_("NextMultiOffset: %u\n"),
869  }
870 
871  if (set_oid != 0)
872  {
873  printf(_("NextOID: %u\n"),
875  }
876 
877  if (set_xid != 0)
878  {
879  printf(_("NextXID: %u\n"),
881  printf(_("OldestXID: %u\n"),
883  printf(_("OldestXID's DB: %u\n"),
885  }
886 
887  if (set_xid_epoch != -1)
888  {
889  printf(_("NextXID epoch: %u\n"),
891  }
892 
893  if (set_oldest_commit_ts_xid != 0)
894  {
895  printf(_("oldestCommitTsXid: %u\n"),
897  }
898  if (set_newest_commit_ts_xid != 0)
899  {
900  printf(_("newestCommitTsXid: %u\n"),
902  }
903 
904  if (set_wal_segsize != 0)
905  {
906  printf(_("Bytes per WAL segment: %u\n"),
908  }
909 }
static MultiXactId set_mxid
Definition: pg_resetwal.c:71
static TransactionId set_xid
Definition: pg_resetwal.c:67
static int set_wal_segsize
Definition: pg_resetwal.c:76
MultiXactId oldestMulti
Definition: pg_control.h:49
static Oid set_oid
Definition: pg_resetwal.c:70
CheckPoint checkPointCopy
Definition: pg_control.h:131
TransactionId oldestXid
Definition: pg_control.h:47
TransactionId nextXid
Definition: pg_control.h:43
static TransactionId set_newest_commit_ts_xid
Definition: pg_resetwal.c:69
MultiXactOffset nextMultiOffset
Definition: pg_control.h:46
TransactionId oldestCommitTsXid
Definition: pg_control.h:52
uint32 xlog_seg_size
Definition: pg_control.h:208
uint32 nextXidEpoch
Definition: pg_control.h:42
static TransactionId set_oldest_commit_ts_xid
Definition: pg_resetwal.c:68
#define MAXFNAMELEN
TransactionId newestCommitTsXid
Definition: pg_control.h:54
Oid oldestMultiDB
Definition: pg_control.h:50
Oid nextOid
Definition: pg_control.h:44
static int WalSegSz
Definition: pg_resetwal.c:75
Oid oldestXidDB
Definition: pg_control.h:48
static ControlFileData ControlFile
Definition: pg_resetwal.c:62
#define XLogFileName(fname, tli, logSegNo, wal_segsz_bytes)
MultiXactId nextMulti
Definition: pg_control.h:45
static MultiXactOffset set_mxoff
Definition: pg_resetwal.c:72
static XLogSegNo newXlogSegNo
Definition: pg_resetwal.c:63
TimeLineID ThisTimeLineID
Definition: pg_control.h:38
#define _(x)
Definition: elog.c:84
static uint32 set_xid_epoch
Definition: pg_resetwal.c:66

◆ ReadControlFile()

static bool ReadControlFile ( void  )
static

Definition at line 597 of file pg_resetwal.c.

References _, buffer, close, COMP_CRC32C, EQ_CRC32C, fd(), FIN_CRC32C, guessed, INIT_CRC32C, IsValidWalSegSize, offsetof, PG_BINARY, PG_CONTROL_FILE_SIZE, PG_CONTROL_VERSION, pg_malloc(), progname, read, strerror(), XLOG_CONTROL_FILE, and ControlFileData::xlog_seg_size.

Referenced by main().

598 {
599  int fd;
600  int len;
601  char *buffer;
602  pg_crc32c crc;
603 
604  if ((fd = open(XLOG_CONTROL_FILE, O_RDONLY | PG_BINARY, 0)) < 0)
605  {
606  /*
607  * If pg_control is not there at all, or we can't read it, the odds
608  * are we've been handed a bad DataDir path, so give up. User can do
609  * "touch pg_control" to force us to proceed.
610  */
611  fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
613  if (errno == ENOENT)
614  fprintf(stderr, _("If you are sure the data directory path is correct, execute\n"
615  " touch %s\n"
616  "and try again.\n"),
618  exit(1);
619  }
620 
621  /* Use malloc to ensure we have a maxaligned buffer */
622  buffer = (char *) pg_malloc(PG_CONTROL_FILE_SIZE);
623 
624  len = read(fd, buffer, PG_CONTROL_FILE_SIZE);
625  if (len < 0)
626  {
627  fprintf(stderr, _("%s: could not read file \"%s\": %s\n"),
629  exit(1);
630  }
631  close(fd);
632 
633  if (len >= sizeof(ControlFileData) &&
634  ((ControlFileData *) buffer)->pg_control_version == PG_CONTROL_VERSION)
635  {
636  /* Check the CRC. */
637  INIT_CRC32C(crc);
638  COMP_CRC32C(crc,
639  buffer,
640  offsetof(ControlFileData, crc));
641  FIN_CRC32C(crc);
642 
643  if (!EQ_CRC32C(crc, ((ControlFileData *) buffer)->crc))
644  {
645  /* We will use the data but treat it as guessed. */
646  fprintf(stderr,
647  _("%s: pg_control exists but has invalid CRC; proceed with caution\n"),
648  progname);
649  guessed = true;
650  }
651 
652  memcpy(&ControlFile, buffer, sizeof(ControlFile));
653 
654  /* return false if WAL segment size is not valid */
656  {
657  fprintf(stderr,
658  _("%s: pg_control specifies invalid WAL segment size (%d bytes); proceed with caution \n"),
660  return false;
661  }
662 
663  return true;
664  }
665 
666  /* Looks like it's a mess. */
667  fprintf(stderr, _("%s: pg_control exists but is broken or wrong version; ignoring it\n"),
668  progname);
669  return false;
670 }
#define INIT_CRC32C(crc)
Definition: pg_crc32c.h:41
#define IsValidWalSegSize(size)
Definition: xlog_internal.h:97
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
uint32 pg_crc32c
Definition: pg_crc32c.h:38
#define PG_CONTROL_VERSION
Definition: pg_control.h:24
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1080
uint32 xlog_seg_size
Definition: pg_control.h:208
#define EQ_CRC32C(c1, c2)
Definition: pg_crc32c.h:42
static const char * progname
Definition: pg_resetwal.c:65
static bool guessed
Definition: pg_resetwal.c:64
#define XLOG_CONTROL_FILE
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
static ControlFileData ControlFile
Definition: pg_resetwal.c:62
#define PG_CONTROL_FILE_SIZE
Definition: pg_control.h:249
const char * strerror(int errnum)
Definition: strerror.c:19
#define close(a)
Definition: win32.h:12
#define COMP_CRC32C(crc, data, len)
Definition: pg_crc32c.h:89
#define FIN_CRC32C(crc)
Definition: pg_crc32c.h:94
#define _(x)
Definition: elog.c:84
#define read(a, b, c)
Definition: win32.h:13
#define offsetof(type, field)
Definition: c.h:622

◆ RewriteControlFile()

static void RewriteControlFile ( void  )
static

Definition at line 916 of file pg_resetwal.c.

References _, ControlFileData::backupEndPoint, ControlFileData::backupEndRequired, ControlFileData::backupStartPoint, buffer, ControlFileData::checkPoint, ControlFileData::checkPointCopy, close, COMP_CRC32C, ControlFileData::crc, DB_SHUTDOWNED, fd(), FIN_CRC32C, fsync, INIT_CRC32C, ControlFileData::max_locks_per_xact, ControlFileData::max_prepared_xacts, ControlFileData::max_worker_processes, ControlFileData::MaxConnections, ControlFileData::minRecoveryPoint, ControlFileData::minRecoveryPointTLI, newXlogSegNo, offsetof, PG_BINARY, PG_CONTROL_FILE_SIZE, PG_CONTROL_MAX_SAFE_SIZE, pg_file_create_mode, progname, CheckPoint::redo, SizeOfXLogLongPHD, ControlFileData::state, StaticAssertStmt, strerror(), CheckPoint::time, ControlFileData::time, ControlFileData::track_commit_timestamp, ControlFileData::wal_level, WAL_LEVEL_MINIMAL, ControlFileData::wal_log_hints, WalSegSz, write, XLOG_CONTROL_FILE, and XLogSegNoOffsetToRecPtr.

Referenced by main().

917 {
918  int fd;
919  char buffer[PG_CONTROL_FILE_SIZE]; /* need not be aligned */
920 
921  /*
922  * For good luck, apply the same static assertions as in backend's
923  * WriteControlFile().
924  */
926  "pg_control is too large for atomic disk writes");
928  "sizeof(ControlFileData) exceeds PG_CONTROL_FILE_SIZE");
929 
930  /*
931  * Adjust fields as needed to force an empty XLOG starting at
932  * newXlogSegNo.
933  */
936  ControlFile.checkPointCopy.time = (pg_time_t) time(NULL);
937 
939  ControlFile.time = (pg_time_t) time(NULL);
946 
947  /*
948  * Force the defaults for max_* settings. The values don't really matter
949  * as long as wal_level='minimal'; the postmaster will reset these fields
950  * anyway at startup.
951  */
953  ControlFile.wal_log_hints = false;
959 
960  /* Contents are protected with a CRC */
963  (char *) &ControlFile,
964  offsetof(ControlFileData, crc));
965  FIN_CRC32C(ControlFile.crc);
966 
967  /*
968  * We write out PG_CONTROL_FILE_SIZE bytes into pg_control, zero-padding
969  * the excess over sizeof(ControlFileData). This reduces the odds of
970  * premature-EOF errors when reading pg_control. We'll still fail when we
971  * check the contents of the file, but hopefully with a more specific
972  * error than "couldn't read pg_control".
973  */
974  memset(buffer, 0, PG_CONTROL_FILE_SIZE);
975  memcpy(buffer, &ControlFile, sizeof(ControlFileData));
976 
977  unlink(XLOG_CONTROL_FILE);
978 
979  fd = open(XLOG_CONTROL_FILE,
980  O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
982  if (fd < 0)
983  {
984  fprintf(stderr, _("%s: could not create pg_control file: %s\n"),
985  progname, strerror(errno));
986  exit(1);
987  }
988 
989  errno = 0;
990  if (write(fd, buffer, PG_CONTROL_FILE_SIZE) != PG_CONTROL_FILE_SIZE)
991  {
992  /* if write didn't set errno, assume problem is no disk space */
993  if (errno == 0)
994  errno = ENOSPC;
995  fprintf(stderr, _("%s: could not write pg_control file: %s\n"),
996  progname, strerror(errno));
997  exit(1);
998  }
999 
1000  if (fsync(fd) != 0)
1001  {
1002  fprintf(stderr, _("%s: fsync error: %s\n"), progname, strerror(errno));
1003  exit(1);
1004  }
1005 
1006  close(fd);
1007 }
#define INIT_CRC32C(crc)
Definition: pg_crc32c.h:41
int max_locks_per_xact
Definition: pg_control.h:181
int pg_file_create_mode
Definition: file_perm.c:20
int max_prepared_xacts
Definition: pg_control.h:180
int64 pg_time_t
Definition: pgtime.h:23
pg_time_t time
Definition: pg_control.h:128
TimeLineID minRecoveryPointTLI
Definition: pg_control.h:167
#define write(a, b, c)
Definition: win32.h:14
int max_worker_processes
Definition: pg_control.h:179
CheckPoint checkPointCopy
Definition: pg_control.h:131
#define PG_CONTROL_MAX_SAFE_SIZE
Definition: pg_control.h:240
pg_time_t time
Definition: pg_control.h:51
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1080
bool backupEndRequired
Definition: pg_control.h:170
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:795
#define fsync(fd)
Definition: win32_port.h:63
#define XLogSegNoOffsetToRecPtr(segno, offset, dest, wal_segsz_bytes)
pg_crc32c crc
Definition: pg_control.h:231
static const char * progname
Definition: pg_resetwal.c:65
#define XLOG_CONTROL_FILE
XLogRecPtr backupEndPoint
Definition: pg_control.h:169
static int WalSegSz
Definition: pg_resetwal.c:75
bool track_commit_timestamp
Definition: pg_control.h:182
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
static ControlFileData ControlFile
Definition: pg_resetwal.c:62
#define PG_CONTROL_FILE_SIZE
Definition: pg_control.h:249
static XLogSegNo newXlogSegNo
Definition: pg_resetwal.c:63
const char * strerror(int errnum)
Definition: strerror.c:19
#define close(a)
Definition: win32.h:12
#define COMP_CRC32C(crc, data, len)
Definition: pg_crc32c.h:89
#define FIN_CRC32C(crc)
Definition: pg_crc32c.h:94
#define _(x)
Definition: elog.c:84
XLogRecPtr backupStartPoint
Definition: pg_control.h:168
XLogRecPtr checkPoint
Definition: pg_control.h:129
XLogRecPtr redo
Definition: pg_control.h:36
#define offsetof(type, field)
Definition: c.h:622
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:166
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:72

◆ usage()

static void usage ( void  )
static

Definition at line 1308 of file pg_resetwal.c.

References _, and progname.

Referenced by main().

1309 {
1310  printf(_("%s resets the PostgreSQL write-ahead log.\n\n"), progname);
1311  printf(_("Usage:\n %s [OPTION]... DATADIR\n\n"), progname);
1312  printf(_("Options:\n"));
1313  printf(_(" -c, --commit-timestamp-ids=XID,XID\n"
1314  " set oldest and newest transactions bearing\n"
1315  " commit timestamp (zero means no change)\n"));
1316  printf(_(" [-D, --pgdata=]DATADIR data directory\n"));
1317  printf(_(" -e, --epoch=XIDEPOCH set next transaction ID epoch\n"));
1318  printf(_(" -f, --force force update to be done\n"));
1319  printf(_(" -l, --next-wal-file=WALFILE set minimum starting location for new WAL\n"));
1320  printf(_(" -m, --multixact-ids=MXID,MXID set next and oldest multitransaction ID\n"));
1321  printf(_(" -n, --dry-run no update, just show what would be done\n"));
1322  printf(_(" -o, --next-oid=OID set next OID\n"));
1323  printf(_(" -O, --multixact-offset=OFFSET set next multitransaction offset\n"));
1324  printf(_(" -V, --version output version information, then exit\n"));
1325  printf(_(" -x, --next-transaction-id=XID set next transaction ID\n"));
1326  printf(_(" --wal-segsize=SIZE size of WAL segments, in megabytes\n"));
1327  printf(_(" -?, --help show this help, then exit\n"));
1328  printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
1329 }
static const char * progname
Definition: pg_resetwal.c:65
#define _(x)
Definition: elog.c:84

◆ WriteEmptyXLOG()

static void WriteEmptyXLOG ( void  )
static

Definition at line 1208 of file pg_resetwal.c.

References _, buffer, ControlFileData::checkPointCopy, close, COMP_CRC32C, fd(), FIN_CRC32C, fsync, INIT_CRC32C, InvalidTransactionId, MAXPGPATH, newXlogSegNo, offsetof, PG_BINARY, pg_file_create_mode, pg_malloc(), progname, CheckPoint::redo, SizeOfXLogLongPHD, SizeOfXLogRecord, SizeOfXLogRecordDataHeaderShort, strerror(), ControlFileData::system_identifier, CheckPoint::ThisTimeLineID, WalSegSz, write, XLogRecord::xl_info, XLogRecord::xl_prev, XLogRecord::xl_rmid, XLogRecord::xl_tot_len, XLogRecord::xl_xid, XLOG_CHECKPOINT_SHUTDOWN, XLOG_PAGE_MAGIC, XLogFilePath, XLogPageHeaderData::xlp_info, XLP_LONG_HEADER, XLogPageHeaderData::xlp_magic, XLogPageHeaderData::xlp_pageaddr, XLogLongPageHeaderData::xlp_seg_size, XLogLongPageHeaderData::xlp_sysid, XLogPageHeaderData::xlp_tli, XLogLongPageHeaderData::xlp_xlog_blcksz, and XLR_BLOCK_ID_DATA_SHORT.

Referenced by main().

1209 {
1210  char *buffer;
1211  XLogPageHeader page;
1212  XLogLongPageHeader longpage;
1213  XLogRecord *record;
1214  pg_crc32c crc;
1215  char path[MAXPGPATH];
1216  int fd;
1217  int nbytes;
1218  char *recptr;
1219 
1220  /* Use malloc() to ensure buffer is MAXALIGNED */
1221  buffer = (char *) pg_malloc(XLOG_BLCKSZ);
1222  page = (XLogPageHeader) buffer;
1223  memset(buffer, 0, XLOG_BLCKSZ);
1224 
1225  /* Set up the XLOG page header */
1226  page->xlp_magic = XLOG_PAGE_MAGIC;
1227  page->xlp_info = XLP_LONG_HEADER;
1230  longpage = (XLogLongPageHeader) page;
1232  longpage->xlp_seg_size = WalSegSz;
1233  longpage->xlp_xlog_blcksz = XLOG_BLCKSZ;
1234 
1235  /* Insert the initial checkpoint record */
1236  recptr = (char *) page + SizeOfXLogLongPHD;
1237  record = (XLogRecord *) recptr;
1238  record->xl_prev = 0;
1239  record->xl_xid = InvalidTransactionId;
1242  record->xl_rmid = RM_XLOG_ID;
1243 
1244  recptr += SizeOfXLogRecord;
1245  *(recptr++) = (char) XLR_BLOCK_ID_DATA_SHORT;
1246  *(recptr++) = sizeof(CheckPoint);
1247  memcpy(recptr, &ControlFile.checkPointCopy,
1248  sizeof(CheckPoint));
1249 
1250  INIT_CRC32C(crc);
1251  COMP_CRC32C(crc, ((char *) record) + SizeOfXLogRecord, record->xl_tot_len - SizeOfXLogRecord);
1252  COMP_CRC32C(crc, (char *) record, offsetof(XLogRecord, xl_crc));
1253  FIN_CRC32C(crc);
1254  record->xl_crc = crc;
1255 
1256  /* Write the first page */
1259 
1260  unlink(path);
1261 
1262  fd = open(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
1264  if (fd < 0)
1265  {
1266  fprintf(stderr, _("%s: could not open file \"%s\": %s\n"),
1267  progname, path, strerror(errno));
1268  exit(1);
1269  }
1270 
1271  errno = 0;
1272  if (write(fd, buffer, XLOG_BLCKSZ) != XLOG_BLCKSZ)
1273  {
1274  /* if write didn't set errno, assume problem is no disk space */
1275  if (errno == 0)
1276  errno = ENOSPC;
1277  fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
1278  progname, path, strerror(errno));
1279  exit(1);
1280  }
1281 
1282  /* Fill the rest of the file with zeroes */
1283  memset(buffer, 0, XLOG_BLCKSZ);
1284  for (nbytes = XLOG_BLCKSZ; nbytes < WalSegSz; nbytes += XLOG_BLCKSZ)
1285  {
1286  errno = 0;
1287  if (write(fd, buffer, XLOG_BLCKSZ) != XLOG_BLCKSZ)
1288  {
1289  if (errno == 0)
1290  errno = ENOSPC;
1291  fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
1292  progname, path, strerror(errno));
1293  exit(1);
1294  }
1295  }
1296 
1297  if (fsync(fd) != 0)
1298  {
1299  fprintf(stderr, _("%s: fsync error: %s\n"), progname, strerror(errno));
1300  exit(1);
1301  }
1302 
1303  close(fd);
1304 }
#define INIT_CRC32C(crc)
Definition: pg_crc32c.h:41
XLogRecPtr xl_prev
Definition: xlogrecord.h:45
int pg_file_create_mode
Definition: file_perm.c:20
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
#define write(a, b, c)
Definition: win32.h:14
#define SizeOfXLogRecordDataHeaderShort
Definition: xlogrecord.h:201
uint32 pg_crc32c
Definition: pg_crc32c.h:38
RmgrId xl_rmid
Definition: xlogrecord.h:47
XLogPageHeaderData * XLogPageHeader
Definition: xlog_internal.h:57
CheckPoint checkPointCopy
Definition: pg_control.h:131
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1080
XLogLongPageHeaderData * XLogLongPageHeader
Definition: xlog_internal.h:74
#define fsync(fd)
Definition: win32_port.h:63
uint64 system_identifier
Definition: pg_control.h:106
uint32 xl_tot_len
Definition: xlogrecord.h:43
#define XLOG_PAGE_MAGIC
Definition: xlog_internal.h:34
#define MAXPGPATH
#define XLOG_CHECKPOINT_SHUTDOWN
Definition: pg_control.h:67
#define InvalidTransactionId
Definition: transam.h:31
static const char * progname
Definition: pg_resetwal.c:65
TimeLineID xlp_tli
Definition: xlog_internal.h:40
XLogRecPtr xlp_pageaddr
Definition: xlog_internal.h:41
#define SizeOfXLogRecord
Definition: xlogrecord.h:55
static int WalSegSz
Definition: pg_resetwal.c:75
#define XLP_LONG_HEADER
Definition: xlog_internal.h:79
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
static ControlFileData ControlFile
Definition: pg_resetwal.c:62
uint8 xl_info
Definition: xlogrecord.h:46
struct CheckPoint CheckPoint
#define XLR_BLOCK_ID_DATA_SHORT
Definition: xlogrecord.h:224
#define XLogFilePath(path, tli, logSegNo, wal_segsz_bytes)
TransactionId xl_xid
Definition: xlogrecord.h:44
static XLogSegNo newXlogSegNo
Definition: pg_resetwal.c:63
TimeLineID ThisTimeLineID
Definition: pg_control.h:38
const char * strerror(int errnum)
Definition: strerror.c:19
#define close(a)
Definition: win32.h:12
#define COMP_CRC32C(crc, data, len)
Definition: pg_crc32c.h:89
#define FIN_CRC32C(crc)
Definition: pg_crc32c.h:94
#define _(x)
Definition: elog.c:84
XLogRecPtr redo
Definition: pg_control.h:36
#define offsetof(type, field)
Definition: c.h:622
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:72

Variable Documentation

◆ ControlFile

ControlFileData ControlFile
static

Definition at line 62 of file pg_resetwal.c.

◆ guessed

bool guessed = false
static

Definition at line 64 of file pg_resetwal.c.

Referenced by GuessControlValues(), main(), and ReadControlFile().

◆ minXlogSegNo

XLogSegNo minXlogSegNo = 0
static

Definition at line 74 of file pg_resetwal.c.

Referenced by main().

◆ minXlogTli

uint32 minXlogTli = 0
static

Definition at line 73 of file pg_resetwal.c.

Referenced by main().

◆ newXlogSegNo

XLogSegNo newXlogSegNo
static

◆ progname

◆ set_mxid

MultiXactId set_mxid = 0
static

Definition at line 71 of file pg_resetwal.c.

Referenced by main(), and PrintNewControlValues().

◆ set_mxoff

MultiXactOffset set_mxoff = (MultiXactOffset) -1
static

Definition at line 72 of file pg_resetwal.c.

Referenced by main(), and PrintNewControlValues().

◆ set_newest_commit_ts_xid

TransactionId set_newest_commit_ts_xid = 0
static

Definition at line 69 of file pg_resetwal.c.

Referenced by main(), and PrintNewControlValues().

◆ set_oid

Oid set_oid = 0
static

Definition at line 70 of file pg_resetwal.c.

Referenced by main(), and PrintNewControlValues().

◆ set_oldest_commit_ts_xid

TransactionId set_oldest_commit_ts_xid = 0
static

Definition at line 68 of file pg_resetwal.c.

Referenced by main(), and PrintNewControlValues().

◆ set_wal_segsize

int set_wal_segsize
static

Definition at line 76 of file pg_resetwal.c.

Referenced by main(), and PrintNewControlValues().

◆ set_xid

TransactionId set_xid = 0
static

Definition at line 67 of file pg_resetwal.c.

Referenced by main(), and PrintNewControlValues().

◆ set_xid_epoch

uint32 set_xid_epoch = (uint32) -1
static

Definition at line 66 of file pg_resetwal.c.

Referenced by main(), and PrintNewControlValues().

◆ WalSegSz

int WalSegSz
static