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 1021 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().

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

680 {
681  uint64 sysidentifier;
682  struct timeval tv;
683 
684  /*
685  * Set up a completely default set of pg_control values.
686  */
687  guessed = true;
688  memset(&ControlFile, 0, sizeof(ControlFile));
689 
692 
693  /*
694  * Create a new unique installation identifier, since we can no longer use
695  * any old XLOG records. See notes in xlog.c about the algorithm.
696  */
697  gettimeofday(&tv, NULL);
698  sysidentifier = ((uint64) tv.tv_sec) << 32;
699  sysidentifier |= ((uint64) tv.tv_usec) << 12;
700  sysidentifier |= getpid() & 0xFFF;
701 
702  ControlFile.system_identifier = sysidentifier;
703 
717  ControlFile.checkPointCopy.time = (pg_time_t) time(NULL);
719 
721  ControlFile.time = (pg_time_t) time(NULL);
724 
725  /* minRecoveryPoint, backupStartPoint and backupEndPoint can be left zero */
726 
728  ControlFile.wal_log_hints = false;
734 
735  ControlFile.maxAlign = MAXIMUM_ALIGNOF;
737  ControlFile.blcksz = BLCKSZ;
738  ControlFile.relseg_size = RELSEG_SIZE;
739  ControlFile.xlog_blcksz = XLOG_BLCKSZ;
745  ControlFile.float4ByVal = FLOAT4PASSBYVAL;
746  ControlFile.float8ByVal = FLOAT8PASSBYVAL;
747 
748  /*
749  * XXX eventually, should try to grovel through old XLOG to develop more
750  * accurate values for TimeLineID, nextXID, etc.
751  */
752 }
#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 1155 of file pg_resetwal.c.

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

Referenced by main().

1156 {
1157 #define ARCHSTATDIR XLOGDIR "/archive_status"
1158 
1159  DIR *xldir;
1160  struct dirent *xlde;
1161  char path[MAXPGPATH + sizeof(ARCHSTATDIR)];
1162 
1163  xldir = opendir(ARCHSTATDIR);
1164  if (xldir == NULL)
1165  {
1166  fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
1167  progname, ARCHSTATDIR, strerror(errno));
1168  exit(1);
1169  }
1170 
1171  while (errno = 0, (xlde = readdir(xldir)) != NULL)
1172  {
1173  if (strspn(xlde->d_name, "0123456789ABCDEF") == XLOG_FNAME_LEN &&
1174  (strcmp(xlde->d_name + XLOG_FNAME_LEN, ".ready") == 0 ||
1175  strcmp(xlde->d_name + XLOG_FNAME_LEN, ".done") == 0 ||
1176  strcmp(xlde->d_name + XLOG_FNAME_LEN, ".partial.ready") == 0 ||
1177  strcmp(xlde->d_name + XLOG_FNAME_LEN, ".partial.done") == 0))
1178  {
1179  snprintf(path, sizeof(path), "%s/%s", ARCHSTATDIR, xlde->d_name);
1180  if (unlink(path) < 0)
1181  {
1182  fprintf(stderr, _("%s: could not delete file \"%s\": %s\n"),
1183  progname, path, strerror(errno));
1184  exit(1);
1185  }
1186  }
1187  }
1188 
1189  if (errno)
1190  {
1191  fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
1192  progname, ARCHSTATDIR, strerror(errno));
1193  exit(1);
1194  }
1195 
1196  if (closedir(xldir))
1197  {
1198  fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
1199  progname, ARCHSTATDIR, strerror(errno));
1200  exit(1);
1201  }
1202 }
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 1106 of file pg_resetwal.c.

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

Referenced by main().

1107 {
1108  DIR *xldir;
1109  struct dirent *xlde;
1110  char path[MAXPGPATH + sizeof(XLOGDIR)];
1111 
1112  xldir = opendir(XLOGDIR);
1113  if (xldir == NULL)
1114  {
1115  fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
1116  progname, XLOGDIR, strerror(errno));
1117  exit(1);
1118  }
1119 
1120  while (errno = 0, (xlde = readdir(xldir)) != NULL)
1121  {
1122  if (IsXLogFileName(xlde->d_name) ||
1124  {
1125  snprintf(path, sizeof(path), "%s/%s", XLOGDIR, xlde->d_name);
1126  if (unlink(path) < 0)
1127  {
1128  fprintf(stderr, _("%s: could not delete file \"%s\": %s\n"),
1129  progname, path, strerror(errno));
1130  exit(1);
1131  }
1132  }
1133  }
1134 
1135  if (errno)
1136  {
1137  fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
1138  progname, XLOGDIR, strerror(errno));
1139  exit(1);
1140  }
1141 
1142  if (closedir(xldir))
1143  {
1144  fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
1145  progname, XLOGDIR, strerror(errno));
1146  exit(1);
1147  }
1148 }
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  /* Set mask based on PGDATA permissions */
360  if (!GetDataDirectoryCreatePerm(DataDir))
361  {
362  fprintf(stderr, _("%s: could not read permissions of directory \"%s\": %s\n"),
363  progname, DataDir, strerror(errno));
364  exit(1);
365  }
366 
367  umask(pg_mode_mask);
368 
369  if (chdir(DataDir) < 0)
370  {
371  fprintf(stderr, _("%s: could not change directory to \"%s\": %s\n"),
372  progname, DataDir, strerror(errno));
373  exit(1);
374  }
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:762
#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:1310
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:846
MultiXactId oldestMulti
Definition: pg_control.h:49
static void FindEndOfXLOG(void)
Definition: pg_resetwal.c:1021
TimeLineID PrevTimeLineID
Definition: pg_control.h:39
static void WriteEmptyXLOG(void)
Definition: pg_resetwal.c:1210
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:1106
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:1155
#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:918
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:679
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:61
#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:25
static uint32 set_xid_epoch
Definition: pg_resetwal.c:66

◆ PrintControlValues()

static void PrintControlValues ( bool  guessed)
static

Definition at line 762 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().

763 {
764  char sysident_str[32];
765 
766  if (guessed)
767  printf(_("Guessed pg_control values:\n\n"));
768  else
769  printf(_("Current pg_control values:\n\n"));
770 
771  /*
772  * Format system_identifier separately to keep platform-dependent format
773  * code out of the translatable message string.
774  */
775  snprintf(sysident_str, sizeof(sysident_str), UINT64_FORMAT,
777 
778  printf(_("pg_control version number: %u\n"),
780  printf(_("Catalog version number: %u\n"),
782  printf(_("Database system identifier: %s\n"),
783  sysident_str);
784  printf(_("Latest checkpoint's TimeLineID: %u\n"),
786  printf(_("Latest checkpoint's full_page_writes: %s\n"),
787  ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off"));
788  printf(_("Latest checkpoint's NextXID: %u:%u\n"),
791  printf(_("Latest checkpoint's NextOID: %u\n"),
793  printf(_("Latest checkpoint's NextMultiXactId: %u\n"),
795  printf(_("Latest checkpoint's NextMultiOffset: %u\n"),
797  printf(_("Latest checkpoint's oldestXID: %u\n"),
799  printf(_("Latest checkpoint's oldestXID's DB: %u\n"),
801  printf(_("Latest checkpoint's oldestActiveXID: %u\n"),
803  printf(_("Latest checkpoint's oldestMultiXid: %u\n"),
805  printf(_("Latest checkpoint's oldestMulti's DB: %u\n"),
807  printf(_("Latest checkpoint's oldestCommitTsXid:%u\n"),
809  printf(_("Latest checkpoint's newestCommitTsXid:%u\n"),
811  printf(_("Maximum data alignment: %u\n"),
813  /* we don't print floatFormat since can't say much useful about it */
814  printf(_("Database block size: %u\n"),
816  printf(_("Blocks per segment of large relation: %u\n"),
818  printf(_("WAL block size: %u\n"),
820  printf(_("Bytes per WAL segment: %u\n"),
822  printf(_("Maximum length of identifiers: %u\n"),
824  printf(_("Maximum columns in an index: %u\n"),
826  printf(_("Maximum size of a TOAST chunk: %u\n"),
828  printf(_("Size of a large-object chunk: %u\n"),
830  /* This is no longer configurable, but users may still expect to see it: */
831  printf(_("Date/time type storage: %s\n"),
832  _("64-bit integers"));
833  printf(_("Float4 argument passing: %s\n"),
834  (ControlFile.float4ByVal ? _("by value") : _("by reference")));
835  printf(_("Float8 argument passing: %s\n"),
836  (ControlFile.float8ByVal ? _("by value") : _("by reference")));
837  printf(_("Data page checksum version: %u\n"),
839 }
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 846 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().

847 {
848  char fname[MAXFNAMELEN];
849 
850  /* This will be always printed in order to keep format same. */
851  printf(_("\n\nValues to be changed:\n\n"));
852 
855  printf(_("First log segment after reset: %s\n"), fname);
856 
857  if (set_mxid != 0)
858  {
859  printf(_("NextMultiXactId: %u\n"),
861  printf(_("OldestMultiXid: %u\n"),
863  printf(_("OldestMulti's DB: %u\n"),
865  }
866 
867  if (set_mxoff != -1)
868  {
869  printf(_("NextMultiOffset: %u\n"),
871  }
872 
873  if (set_oid != 0)
874  {
875  printf(_("NextOID: %u\n"),
877  }
878 
879  if (set_xid != 0)
880  {
881  printf(_("NextXID: %u\n"),
883  printf(_("OldestXID: %u\n"),
885  printf(_("OldestXID's DB: %u\n"),
887  }
888 
889  if (set_xid_epoch != -1)
890  {
891  printf(_("NextXID epoch: %u\n"),
893  }
894 
895  if (set_oldest_commit_ts_xid != 0)
896  {
897  printf(_("oldestCommitTsXid: %u\n"),
899  }
900  if (set_newest_commit_ts_xid != 0)
901  {
902  printf(_("newestCommitTsXid: %u\n"),
904  }
905 
906  if (set_wal_segsize != 0)
907  {
908  printf(_("Bytes per WAL segment: %u\n"),
910  }
911 }
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, ngettext, 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  ngettext("%s: pg_control specifies invalid WAL segment size (%d byte); proceed with caution\n",
659  "%s: pg_control specifies invalid WAL segment size (%d bytes); proceed with caution\n",
662  return false;
663  }
664 
665  return true;
666  }
667 
668  /* Looks like it's a mess. */
669  fprintf(stderr, _("%s: pg_control exists but is broken or wrong version; ignoring it\n"),
670  progname);
671  return false;
672 }
#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 ngettext(s, p, n)
Definition: c.h:1022
#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 918 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().

919 {
920  int fd;
921  char buffer[PG_CONTROL_FILE_SIZE]; /* need not be aligned */
922 
923  /*
924  * For good luck, apply the same static assertions as in backend's
925  * WriteControlFile().
926  */
928  "pg_control is too large for atomic disk writes");
930  "sizeof(ControlFileData) exceeds PG_CONTROL_FILE_SIZE");
931 
932  /*
933  * Adjust fields as needed to force an empty XLOG starting at
934  * newXlogSegNo.
935  */
938  ControlFile.checkPointCopy.time = (pg_time_t) time(NULL);
939 
941  ControlFile.time = (pg_time_t) time(NULL);
948 
949  /*
950  * Force the defaults for max_* settings. The values don't really matter
951  * as long as wal_level='minimal'; the postmaster will reset these fields
952  * anyway at startup.
953  */
955  ControlFile.wal_log_hints = false;
961 
962  /* Contents are protected with a CRC */
965  (char *) &ControlFile,
966  offsetof(ControlFileData, crc));
967  FIN_CRC32C(ControlFile.crc);
968 
969  /*
970  * We write out PG_CONTROL_FILE_SIZE bytes into pg_control, zero-padding
971  * the excess over sizeof(ControlFileData). This reduces the odds of
972  * premature-EOF errors when reading pg_control. We'll still fail when we
973  * check the contents of the file, but hopefully with a more specific
974  * error than "couldn't read pg_control".
975  */
976  memset(buffer, 0, PG_CONTROL_FILE_SIZE);
977  memcpy(buffer, &ControlFile, sizeof(ControlFileData));
978 
979  unlink(XLOG_CONTROL_FILE);
980 
981  fd = open(XLOG_CONTROL_FILE,
982  O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
984  if (fd < 0)
985  {
986  fprintf(stderr, _("%s: could not create pg_control file: %s\n"),
987  progname, strerror(errno));
988  exit(1);
989  }
990 
991  errno = 0;
992  if (write(fd, buffer, PG_CONTROL_FILE_SIZE) != PG_CONTROL_FILE_SIZE)
993  {
994  /* if write didn't set errno, assume problem is no disk space */
995  if (errno == 0)
996  errno = ENOSPC;
997  fprintf(stderr, _("%s: could not write pg_control file: %s\n"),
998  progname, strerror(errno));
999  exit(1);
1000  }
1001 
1002  if (fsync(fd) != 0)
1003  {
1004  fprintf(stderr, _("%s: fsync error: %s\n"), progname, strerror(errno));
1005  exit(1);
1006  }
1007 
1008  close(fd);
1009 }
#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:19
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 1310 of file pg_resetwal.c.

References _, and progname.

Referenced by main().

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

◆ WriteEmptyXLOG()

static void WriteEmptyXLOG ( void  )
static

Definition at line 1210 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().

1211 {
1212  char *buffer;
1213  XLogPageHeader page;
1214  XLogLongPageHeader longpage;
1215  XLogRecord *record;
1216  pg_crc32c crc;
1217  char path[MAXPGPATH];
1218  int fd;
1219  int nbytes;
1220  char *recptr;
1221 
1222  /* Use malloc() to ensure buffer is MAXALIGNED */
1223  buffer = (char *) pg_malloc(XLOG_BLCKSZ);
1224  page = (XLogPageHeader) buffer;
1225  memset(buffer, 0, XLOG_BLCKSZ);
1226 
1227  /* Set up the XLOG page header */
1228  page->xlp_magic = XLOG_PAGE_MAGIC;
1229  page->xlp_info = XLP_LONG_HEADER;
1232  longpage = (XLogLongPageHeader) page;
1234  longpage->xlp_seg_size = WalSegSz;
1235  longpage->xlp_xlog_blcksz = XLOG_BLCKSZ;
1236 
1237  /* Insert the initial checkpoint record */
1238  recptr = (char *) page + SizeOfXLogLongPHD;
1239  record = (XLogRecord *) recptr;
1240  record->xl_prev = 0;
1241  record->xl_xid = InvalidTransactionId;
1244  record->xl_rmid = RM_XLOG_ID;
1245 
1246  recptr += SizeOfXLogRecord;
1247  *(recptr++) = (char) XLR_BLOCK_ID_DATA_SHORT;
1248  *(recptr++) = sizeof(CheckPoint);
1249  memcpy(recptr, &ControlFile.checkPointCopy,
1250  sizeof(CheckPoint));
1251 
1252  INIT_CRC32C(crc);
1253  COMP_CRC32C(crc, ((char *) record) + SizeOfXLogRecord, record->xl_tot_len - SizeOfXLogRecord);
1254  COMP_CRC32C(crc, (char *) record, offsetof(XLogRecord, xl_crc));
1255  FIN_CRC32C(crc);
1256  record->xl_crc = crc;
1257 
1258  /* Write the first page */
1261 
1262  unlink(path);
1263 
1264  fd = open(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
1266  if (fd < 0)
1267  {
1268  fprintf(stderr, _("%s: could not open file \"%s\": %s\n"),
1269  progname, path, strerror(errno));
1270  exit(1);
1271  }
1272 
1273  errno = 0;
1274  if (write(fd, buffer, XLOG_BLCKSZ) != XLOG_BLCKSZ)
1275  {
1276  /* if write didn't set errno, assume problem is no disk space */
1277  if (errno == 0)
1278  errno = ENOSPC;
1279  fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
1280  progname, path, strerror(errno));
1281  exit(1);
1282  }
1283 
1284  /* Fill the rest of the file with zeroes */
1285  memset(buffer, 0, XLOG_BLCKSZ);
1286  for (nbytes = XLOG_BLCKSZ; nbytes < WalSegSz; nbytes += XLOG_BLCKSZ)
1287  {
1288  errno = 0;
1289  if (write(fd, buffer, XLOG_BLCKSZ) != XLOG_BLCKSZ)
1290  {
1291  if (errno == 0)
1292  errno = ENOSPC;
1293  fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
1294  progname, path, strerror(errno));
1295  exit(1);
1296  }
1297  }
1298 
1299  if (fsync(fd) != 0)
1300  {
1301  fprintf(stderr, _("%s: fsync error: %s\n"), progname, strerror(errno));
1302  exit(1);
1303  }
1304 
1305  close(fd);
1306 }
#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:19
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