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/restricted_token.h"
#include "storage/large_object.h"
#include "pg_getopt.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
 

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 482 of file pg_resetwal.c.

References _, progname, and strerror().

Referenced by main().

483 {
484  const char *ver_file = "PG_VERSION";
485  FILE *ver_fd;
486  char rawline[64];
487  int len;
488 
489  if ((ver_fd = fopen(ver_file, "r")) == NULL)
490  {
491  fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
492  progname, ver_file, strerror(errno));
493  exit(1);
494  }
495 
496  /* version number has to be the first line read */
497  if (!fgets(rawline, sizeof(rawline), ver_fd))
498  {
499  if (!ferror(ver_fd))
500  {
501  fprintf(stderr, _("%s: unexpected empty file \"%s\"\n"),
502  progname, ver_file);
503  }
504  else
505  {
506  fprintf(stderr, _("%s: could not read file \"%s\": %s\n"),
507  progname, ver_file, strerror(errno));
508  }
509  exit(1);
510  }
511 
512  /* remove trailing newline, handling Windows newlines as well */
513  len = strlen(rawline);
514  if (len > 0 && rawline[len - 1] == '\n')
515  {
516  rawline[--len] = '\0';
517  if (len > 0 && rawline[len - 1] == '\r')
518  rawline[--len] = '\0';
519  }
520 
521  if (strcmp(rawline, PG_MAJORVERSION) != 0)
522  {
523  fprintf(stderr, _("%s: data directory is of wrong version\n"
524  "File \"%s\" contains \"%s\", which is not compatible with this program's version \"%s\".\n"),
525  progname, ver_file, rawline, PG_MAJORVERSION);
526  exit(1);
527  }
528 
529  fclose(ver_fd);
530 }
static const char * progname
Definition: pg_resetwal.c:63
const char * strerror(int errnum)
Definition: strerror.c:19
#define _(x)
Definition: elog.c:84

◆ FindEndOfXLOG()

static void FindEndOfXLOG ( void  )
static

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

961 {
962  DIR *xldir;
963  struct dirent *xlde;
964  uint64 segs_per_xlogid;
965  uint64 xlogbytepos;
966 
967  /*
968  * Initialize the max() computation using the last checkpoint address from
969  * old pg_control. Note that for the moment we are working with segment
970  * numbering according to the old xlog seg size.
971  */
972  segs_per_xlogid = (UINT64CONST(0x0000000100000000) / ControlFile.xlog_seg_size);
974 
975  /*
976  * Scan the pg_wal directory to find existing WAL segment files. We assume
977  * any present have been used; in most scenarios this should be
978  * conservative, because of xlog.c's attempts to pre-create files.
979  */
980  xldir = opendir(XLOGDIR);
981  if (xldir == NULL)
982  {
983  fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
984  progname, XLOGDIR, strerror(errno));
985  exit(1);
986  }
987 
988  while (errno = 0, (xlde = readdir(xldir)) != NULL)
989  {
990  if (IsXLogFileName(xlde->d_name) ||
992  {
993  unsigned int tli,
994  log,
995  seg;
996  XLogSegNo segno;
997 
998  /*
999  * Note: We don't use XLogFromFileName here, because we want to
1000  * use the segment size from the control file, not the size the
1001  * pg_resetwal binary was compiled with
1002  */
1003  sscanf(xlde->d_name, "%08X%08X%08X", &tli, &log, &seg);
1004  segno = ((uint64) log) * segs_per_xlogid + seg;
1005 
1006  /*
1007  * Note: we take the max of all files found, regardless of their
1008  * timelines. Another possibility would be to ignore files of
1009  * timelines other than the target TLI, but this seems safer.
1010  * Better too large a result than too small...
1011  */
1012  if (segno > newXlogSegNo)
1013  newXlogSegNo = segno;
1014  }
1015  }
1016 
1017  if (errno)
1018  {
1019  fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
1020  progname, XLOGDIR, strerror(errno));
1021  exit(1);
1022  }
1023 
1024  if (closedir(xldir))
1025  {
1026  fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
1027  progname, XLOGDIR, strerror(errno));
1028  exit(1);
1029  }
1030 
1031  /*
1032  * Finally, convert to new xlog seg size, and advance by one to ensure we
1033  * are in virgin territory.
1034  */
1035  xlogbytepos = newXlogSegNo * ControlFile.xlog_seg_size;
1036  newXlogSegNo = (xlogbytepos + WalSegSz - 1) / WalSegSz;
1037  newXlogSegNo++;
1038 }
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:63
#define XLOGDIR
static int WalSegSz
Definition: pg_resetwal.c:73
static ControlFileData ControlFile
Definition: pg_resetwal.c:60
struct dirent * readdir(DIR *)
Definition: dirent.c:77
static XLogSegNo newXlogSegNo
Definition: pg_resetwal.c:61
#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 621 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().

622 {
623  uint64 sysidentifier;
624  struct timeval tv;
625 
626  /*
627  * Set up a completely default set of pg_control values.
628  */
629  guessed = true;
630  memset(&ControlFile, 0, sizeof(ControlFile));
631 
634 
635  /*
636  * Create a new unique installation identifier, since we can no longer use
637  * any old XLOG records. See notes in xlog.c about the algorithm.
638  */
639  gettimeofday(&tv, NULL);
640  sysidentifier = ((uint64) tv.tv_sec) << 32;
641  sysidentifier |= ((uint64) tv.tv_usec) << 12;
642  sysidentifier |= getpid() & 0xFFF;
643 
644  ControlFile.system_identifier = sysidentifier;
645 
659  ControlFile.checkPointCopy.time = (pg_time_t) time(NULL);
661 
663  ControlFile.time = (pg_time_t) time(NULL);
666 
667  /* minRecoveryPoint, backupStartPoint and backupEndPoint can be left zero */
668 
670  ControlFile.wal_log_hints = false;
676 
677  ControlFile.maxAlign = MAXIMUM_ALIGNOF;
679  ControlFile.blcksz = BLCKSZ;
680  ControlFile.relseg_size = RELSEG_SIZE;
681  ControlFile.xlog_blcksz = XLOG_BLCKSZ;
687  ControlFile.float4ByVal = FLOAT4PASSBYVAL;
688  ControlFile.float8ByVal = FLOAT8PASSBYVAL;
689 
690  /*
691  * XXX eventually, should try to grovel through old XLOG to develop more
692  * accurate values for TimeLineID, nextXID, etc.
693  */
694 }
#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:62
#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:60
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 1094 of file pg_resetwal.c.

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

Referenced by main().

1095 {
1096 #define ARCHSTATDIR XLOGDIR "/archive_status"
1097 
1098  DIR *xldir;
1099  struct dirent *xlde;
1100  char path[MAXPGPATH + sizeof(ARCHSTATDIR)];
1101 
1102  xldir = opendir(ARCHSTATDIR);
1103  if (xldir == NULL)
1104  {
1105  fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
1106  progname, ARCHSTATDIR, strerror(errno));
1107  exit(1);
1108  }
1109 
1110  while (errno = 0, (xlde = readdir(xldir)) != NULL)
1111  {
1112  if (strspn(xlde->d_name, "0123456789ABCDEF") == XLOG_FNAME_LEN &&
1113  (strcmp(xlde->d_name + XLOG_FNAME_LEN, ".ready") == 0 ||
1114  strcmp(xlde->d_name + XLOG_FNAME_LEN, ".done") == 0 ||
1115  strcmp(xlde->d_name + XLOG_FNAME_LEN, ".partial.ready") == 0 ||
1116  strcmp(xlde->d_name + XLOG_FNAME_LEN, ".partial.done") == 0))
1117  {
1118  snprintf(path, sizeof(path), "%s/%s", ARCHSTATDIR, xlde->d_name);
1119  if (unlink(path) < 0)
1120  {
1121  fprintf(stderr, _("%s: could not delete file \"%s\": %s\n"),
1122  progname, path, strerror(errno));
1123  exit(1);
1124  }
1125  }
1126  }
1127 
1128  if (errno)
1129  {
1130  fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
1131  progname, ARCHSTATDIR, strerror(errno));
1132  exit(1);
1133  }
1134 
1135  if (closedir(xldir))
1136  {
1137  fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
1138  progname, ARCHSTATDIR, strerror(errno));
1139  exit(1);
1140  }
1141 }
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:63
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 1045 of file pg_resetwal.c.

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

Referenced by main().

1046 {
1047  DIR *xldir;
1048  struct dirent *xlde;
1049  char path[MAXPGPATH + sizeof(XLOGDIR)];
1050 
1051  xldir = opendir(XLOGDIR);
1052  if (xldir == NULL)
1053  {
1054  fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
1055  progname, XLOGDIR, strerror(errno));
1056  exit(1);
1057  }
1058 
1059  while (errno = 0, (xlde = readdir(xldir)) != NULL)
1060  {
1061  if (IsXLogFileName(xlde->d_name) ||
1063  {
1064  snprintf(path, sizeof(path), "%s/%s", XLOGDIR, xlde->d_name);
1065  if (unlink(path) < 0)
1066  {
1067  fprintf(stderr, _("%s: could not delete file \"%s\": %s\n"),
1068  progname, path, strerror(errno));
1069  exit(1);
1070  }
1071  }
1072  }
1073 
1074  if (errno)
1075  {
1076  fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
1077  progname, XLOGDIR, strerror(errno));
1078  exit(1);
1079  }
1080 
1081  if (closedir(xldir))
1082  {
1083  fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
1084  progname, XLOGDIR, strerror(errno));
1085  exit(1);
1086  }
1087 }
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:63
#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 89 of file pg_resetwal.c.

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

90 {
91  int c;
92  bool force = false;
93  bool noupdate = false;
94  MultiXactId set_oldestmxid = 0;
95  char *endptr;
96  char *endptr2;
97  char *DataDir = NULL;
98  char *log_fname = NULL;
99  int fd;
100 
101  set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_resetwal"));
102 
103  progname = get_progname(argv[0]);
104 
105  if (argc > 1)
106  {
107  if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
108  {
109  usage();
110  exit(0);
111  }
112  if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
113  {
114  puts("pg_resetwal (PostgreSQL) " PG_VERSION);
115  exit(0);
116  }
117  }
118 
119 
120  while ((c = getopt(argc, argv, "c:D:e:fl:m:no:O:x:")) != -1)
121  {
122  switch (c)
123  {
124  case 'D':
125  DataDir = optarg;
126  break;
127 
128  case 'f':
129  force = true;
130  break;
131 
132  case 'n':
133  noupdate = true;
134  break;
135 
136  case 'e':
137  set_xid_epoch = strtoul(optarg, &endptr, 0);
138  if (endptr == optarg || *endptr != '\0')
139  {
140  /*------
141  translator: the second %s is a command line argument (-e, etc) */
142  fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-e");
143  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
144  exit(1);
145  }
146  if (set_xid_epoch == -1)
147  {
148  fprintf(stderr, _("%s: transaction ID epoch (-e) must not be -1\n"), progname);
149  exit(1);
150  }
151  break;
152 
153  case 'x':
154  set_xid = strtoul(optarg, &endptr, 0);
155  if (endptr == optarg || *endptr != '\0')
156  {
157  fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-x");
158  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
159  exit(1);
160  }
161  if (set_xid == 0)
162  {
163  fprintf(stderr, _("%s: transaction ID (-x) must not be 0\n"), progname);
164  exit(1);
165  }
166  break;
167 
168  case 'c':
169  set_oldest_commit_ts_xid = strtoul(optarg, &endptr, 0);
170  if (endptr == optarg || *endptr != ',')
171  {
172  fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-c");
173  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
174  exit(1);
175  }
176  set_newest_commit_ts_xid = strtoul(endptr + 1, &endptr2, 0);
177  if (endptr2 == endptr + 1 || *endptr2 != '\0')
178  {
179  fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-c");
180  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
181  exit(1);
182  }
183 
184  if (set_oldest_commit_ts_xid < 2 &&
186  {
187  fprintf(stderr, _("%s: transaction ID (-c) must be either 0 or greater than or equal to 2\n"), progname);
188  exit(1);
189  }
190 
191  if (set_newest_commit_ts_xid < 2 &&
193  {
194  fprintf(stderr, _("%s: transaction ID (-c) must be either 0 or greater than or equal to 2\n"), progname);
195  exit(1);
196  }
197  break;
198 
199  case 'o':
200  set_oid = strtoul(optarg, &endptr, 0);
201  if (endptr == optarg || *endptr != '\0')
202  {
203  fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-o");
204  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
205  exit(1);
206  }
207  if (set_oid == 0)
208  {
209  fprintf(stderr, _("%s: OID (-o) must not be 0\n"), progname);
210  exit(1);
211  }
212  break;
213 
214  case 'm':
215  set_mxid = strtoul(optarg, &endptr, 0);
216  if (endptr == optarg || *endptr != ',')
217  {
218  fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-m");
219  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
220  exit(1);
221  }
222 
223  set_oldestmxid = strtoul(endptr + 1, &endptr2, 0);
224  if (endptr2 == endptr + 1 || *endptr2 != '\0')
225  {
226  fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-m");
227  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
228  exit(1);
229  }
230  if (set_mxid == 0)
231  {
232  fprintf(stderr, _("%s: multitransaction ID (-m) must not be 0\n"), progname);
233  exit(1);
234  }
235 
236  /*
237  * XXX It'd be nice to have more sanity checks here, e.g. so
238  * that oldest is not wrapped around w.r.t. nextMulti.
239  */
240  if (set_oldestmxid == 0)
241  {
242  fprintf(stderr, _("%s: oldest multitransaction ID (-m) must not be 0\n"),
243  progname);
244  exit(1);
245  }
246  break;
247 
248  case 'O':
249  set_mxoff = strtoul(optarg, &endptr, 0);
250  if (endptr == optarg || *endptr != '\0')
251  {
252  fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-O");
253  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
254  exit(1);
255  }
256  if (set_mxoff == -1)
257  {
258  fprintf(stderr, _("%s: multitransaction offset (-O) must not be -1\n"), progname);
259  exit(1);
260  }
261  break;
262 
263  case 'l':
264  if (strspn(optarg, "01234567890ABCDEFabcdef") != XLOG_FNAME_LEN)
265  {
266  fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-l");
267  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
268  exit(1);
269  }
270 
271  /*
272  * XLogFromFileName requires wal segment size which is not yet
273  * set. Hence wal details are set later on.
274  */
275  log_fname = pg_strdup(optarg);
276  break;
277 
278  default:
279  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
280  exit(1);
281  }
282  }
283 
284  if (DataDir == NULL && optind < argc)
285  DataDir = argv[optind++];
286 
287  /* Complain if any arguments remain */
288  if (optind < argc)
289  {
290  fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
291  progname, argv[optind]);
292  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
293  progname);
294  exit(1);
295  }
296 
297  if (DataDir == NULL)
298  {
299  fprintf(stderr, _("%s: no data directory specified\n"), progname);
300  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
301  exit(1);
302  }
303 
304  /*
305  * Don't allow pg_resetwal to be run as root, to avoid overwriting the
306  * ownership of files in the data directory. We need only check for root
307  * -- any other user won't have sufficient permissions to modify files in
308  * the data directory.
309  */
310 #ifndef WIN32
311  if (geteuid() == 0)
312  {
313  fprintf(stderr, _("%s: cannot be executed by \"root\"\n"),
314  progname);
315  fprintf(stderr, _("You must run %s as the PostgreSQL superuser.\n"),
316  progname);
317  exit(1);
318  }
319 #endif
320 
322 
323  if (chdir(DataDir) < 0)
324  {
325  fprintf(stderr, _("%s: could not change directory to \"%s\": %s\n"),
326  progname, DataDir, strerror(errno));
327  exit(1);
328  }
329 
330  /* Check that data directory matches our server version */
332 
333  /*
334  * Check for a postmaster lock file --- if there is one, refuse to
335  * proceed, on grounds we might be interfering with a live installation.
336  */
337  if ((fd = open("postmaster.pid", O_RDONLY, 0)) < 0)
338  {
339  if (errno != ENOENT)
340  {
341  fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
342  progname, "postmaster.pid", strerror(errno));
343  exit(1);
344  }
345  }
346  else
347  {
348  fprintf(stderr, _("%s: lock file \"%s\" exists\n"
349  "Is a server running? If not, delete the lock file and try again.\n"),
350  progname, "postmaster.pid");
351  exit(1);
352  }
353 
354  /*
355  * Attempt to read the existing pg_control file
356  */
357  if (!ReadControlFile())
359 
360  if (log_fname != NULL)
362 
363  /*
364  * Also look at existing segment files to set up newXlogSegNo
365  */
366  FindEndOfXLOG();
367 
368  /*
369  * If we're not going to proceed with the reset, print the current control
370  * file parameters.
371  */
372  if ((guessed && !force) || noupdate)
374 
375  /*
376  * Adjust fields if required by switches. (Do this now so that printout,
377  * if any, includes these values.)
378  */
379  if (set_xid_epoch != -1)
381 
382  if (set_xid != 0)
383  {
385 
386  /*
387  * For the moment, just set oldestXid to a value that will force
388  * immediate autovacuum-for-wraparound. It's not clear whether adding
389  * user control of this is useful, so let's just do something that's
390  * reasonably safe. The magic constant here corresponds to the
391  * maximum allowed value of autovacuum_freeze_max_age.
392  */
397  }
398 
399  if (set_oldest_commit_ts_xid != 0)
401  if (set_newest_commit_ts_xid != 0)
403 
404  if (set_oid != 0)
406 
407  if (set_mxid != 0)
408  {
410 
411  ControlFile.checkPointCopy.oldestMulti = set_oldestmxid;
415  }
416 
417  if (set_mxoff != -1)
419 
421  {
424  }
425 
428 
429  /*
430  * If we had to guess anything, and -f was not given, just print the
431  * guessed values and exit. Also print if -n is given.
432  */
433  if ((guessed && !force) || noupdate)
434  {
436  if (!noupdate)
437  {
438  printf(_("\nIf these values seem acceptable, use -f to force reset.\n"));
439  exit(1);
440  }
441  else
442  exit(0);
443  }
444 
445  /*
446  * Don't reset from a dirty pg_control without -f, either.
447  */
448  if (ControlFile.state != DB_SHUTDOWNED && !force)
449  {
450  printf(_("The database server was not shut down cleanly.\n"
451  "Resetting the write-ahead log might cause data to be lost.\n"
452  "If you want to proceed anyway, use -f to force reset.\n"));
453  exit(1);
454  }
455 
456  /*
457  * Else, do the dirty deed.
458  */
462  WriteEmptyXLOG();
463 
464  printf(_("Write-ahead log reset\n"));
465  return 0;
466 }
static void PrintControlValues(bool guessed)
Definition: pg_resetwal.c:704
static MultiXactId set_mxid
Definition: pg_resetwal.c:69
static void usage(void)
Definition: pg_resetwal.c:1249
static TransactionId set_xid
Definition: pg_resetwal.c:65
const char * get_progname(const char *argv0)
Definition: path.c:453
static void PrintNewControlValues(void)
Definition: pg_resetwal.c:788
MultiXactId oldestMulti
Definition: pg_control.h:49
static void FindEndOfXLOG(void)
Definition: pg_resetwal.c:960
TimeLineID PrevTimeLineID
Definition: pg_control.h:39
static void WriteEmptyXLOG(void)
Definition: pg_resetwal.c:1149
static Oid set_oid
Definition: pg_resetwal.c:68
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:482
static int fd(const char *x, int i)
Definition: preproc-init.c:105
int getopt(int nargc, char *const *nargv, const char *ostr)
Definition: getopt.c:72
static bool ReadControlFile(void)
Definition: pg_resetwal.c:540
void get_restricted_token(const char *progname)
static TransactionId set_newest_commit_ts_xid
Definition: pg_resetwal.c:67
static void KillExistingXLOG(void)
Definition: pg_resetwal.c:1045
MultiXactOffset nextMultiOffset
Definition: pg_control.h:46
TransactionId oldestCommitTsXid
Definition: pg_control.h:52
int optind
Definition: getopt.c:51
static void KillExistingArchiveStatus(void)
Definition: pg_resetwal.c:1094
#define FirstNormalTransactionId
Definition: transam.h:34
uint32 nextXidEpoch
Definition: pg_control.h:42
static TransactionId set_oldest_commit_ts_xid
Definition: pg_resetwal.c:66
#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:63
static bool guessed
Definition: pg_resetwal.c:62
TransactionId newestCommitTsXid
Definition: pg_control.h:54
#define PG_TEXTDOMAIN(domain)
Definition: c.h:1009
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:73
TransactionId MultiXactId
Definition: c.h:465
Oid oldestXidDB
Definition: pg_control.h:48
static ControlFileData ControlFile
Definition: pg_resetwal.c:60
MultiXactId nextMulti
Definition: pg_control.h:45
static void RewriteControlFile(void)
Definition: pg_resetwal.c:854
static MultiXactOffset set_mxoff
Definition: pg_resetwal.c:70
static XLogSegNo newXlogSegNo
Definition: pg_resetwal.c:61
static void GuessControlValues(void)
Definition: pg_resetwal.c:621
static uint32 minXlogTli
Definition: pg_resetwal.c:71
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:60
#define XLOG_FNAME_LEN
#define _(x)
Definition: elog.c:84
static XLogSegNo minXlogSegNo
Definition: pg_resetwal.c:72
static uint32 set_xid_epoch
Definition: pg_resetwal.c:64

◆ PrintControlValues()

static void PrintControlValues ( bool  guessed)
static

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

705 {
706  char sysident_str[32];
707 
708  if (guessed)
709  printf(_("Guessed pg_control values:\n\n"));
710  else
711  printf(_("Current pg_control values:\n\n"));
712 
713  /*
714  * Format system_identifier separately to keep platform-dependent format
715  * code out of the translatable message string.
716  */
717  snprintf(sysident_str, sizeof(sysident_str), UINT64_FORMAT,
719 
720  printf(_("pg_control version number: %u\n"),
722  printf(_("Catalog version number: %u\n"),
724  printf(_("Database system identifier: %s\n"),
725  sysident_str);
726  printf(_("Latest checkpoint's TimeLineID: %u\n"),
728  printf(_("Latest checkpoint's full_page_writes: %s\n"),
729  ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off"));
730  printf(_("Latest checkpoint's NextXID: %u:%u\n"),
733  printf(_("Latest checkpoint's NextOID: %u\n"),
735  printf(_("Latest checkpoint's NextMultiXactId: %u\n"),
737  printf(_("Latest checkpoint's NextMultiOffset: %u\n"),
739  printf(_("Latest checkpoint's oldestXID: %u\n"),
741  printf(_("Latest checkpoint's oldestXID's DB: %u\n"),
743  printf(_("Latest checkpoint's oldestActiveXID: %u\n"),
745  printf(_("Latest checkpoint's oldestMultiXid: %u\n"),
747  printf(_("Latest checkpoint's oldestMulti's DB: %u\n"),
749  printf(_("Latest checkpoint's oldestCommitTsXid:%u\n"),
751  printf(_("Latest checkpoint's newestCommitTsXid:%u\n"),
753  printf(_("Maximum data alignment: %u\n"),
755  /* we don't print floatFormat since can't say much useful about it */
756  printf(_("Database block size: %u\n"),
758  printf(_("Blocks per segment of large relation: %u\n"),
760  printf(_("WAL block size: %u\n"),
762  printf(_("Bytes per WAL segment: %u\n"),
764  printf(_("Maximum length of identifiers: %u\n"),
766  printf(_("Maximum columns in an index: %u\n"),
768  printf(_("Maximum size of a TOAST chunk: %u\n"),
770  printf(_("Size of a large-object chunk: %u\n"),
772  /* This is no longer configurable, but users may still expect to see it: */
773  printf(_("Date/time type storage: %s\n"),
774  _("64-bit integers"));
775  printf(_("Float4 argument passing: %s\n"),
776  (ControlFile.float4ByVal ? _("by value") : _("by reference")));
777  printf(_("Float8 argument passing: %s\n"),
778  (ControlFile.float8ByVal ? _("by value") : _("by reference")));
779  printf(_("Data page checksum version: %u\n"),
781 }
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:62
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:60
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:349
uint32 relseg_size
Definition: pg_control.h:205

◆ PrintNewControlValues()

static void PrintNewControlValues ( void  )
static

Definition at line 788 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_xid, set_xid_epoch, CheckPoint::ThisTimeLineID, WalSegSz, and XLogFileName.

Referenced by main().

789 {
790  char fname[MAXFNAMELEN];
791 
792  /* This will be always printed in order to keep format same. */
793  printf(_("\n\nValues to be changed:\n\n"));
794 
797  printf(_("First log segment after reset: %s\n"), fname);
798 
799  if (set_mxid != 0)
800  {
801  printf(_("NextMultiXactId: %u\n"),
803  printf(_("OldestMultiXid: %u\n"),
805  printf(_("OldestMulti's DB: %u\n"),
807  }
808 
809  if (set_mxoff != -1)
810  {
811  printf(_("NextMultiOffset: %u\n"),
813  }
814 
815  if (set_oid != 0)
816  {
817  printf(_("NextOID: %u\n"),
819  }
820 
821  if (set_xid != 0)
822  {
823  printf(_("NextXID: %u\n"),
825  printf(_("OldestXID: %u\n"),
827  printf(_("OldestXID's DB: %u\n"),
829  }
830 
831  if (set_xid_epoch != -1)
832  {
833  printf(_("NextXID epoch: %u\n"),
835  }
836 
837  if (set_oldest_commit_ts_xid != 0)
838  {
839  printf(_("oldestCommitTsXid: %u\n"),
841  }
842  if (set_newest_commit_ts_xid != 0)
843  {
844  printf(_("newestCommitTsXid: %u\n"),
846  }
847 }
static MultiXactId set_mxid
Definition: pg_resetwal.c:69
static TransactionId set_xid
Definition: pg_resetwal.c:65
MultiXactId oldestMulti
Definition: pg_control.h:49
static Oid set_oid
Definition: pg_resetwal.c:68
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:67
MultiXactOffset nextMultiOffset
Definition: pg_control.h:46
TransactionId oldestCommitTsXid
Definition: pg_control.h:52
uint32 nextXidEpoch
Definition: pg_control.h:42
static TransactionId set_oldest_commit_ts_xid
Definition: pg_resetwal.c:66
#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:73
Oid oldestXidDB
Definition: pg_control.h:48
static ControlFileData ControlFile
Definition: pg_resetwal.c:60
#define XLogFileName(fname, tli, logSegNo, wal_segsz_bytes)
MultiXactId nextMulti
Definition: pg_control.h:45
static MultiXactOffset set_mxoff
Definition: pg_resetwal.c:70
static XLogSegNo newXlogSegNo
Definition: pg_resetwal.c:61
TimeLineID ThisTimeLineID
Definition: pg_control.h:38
#define _(x)
Definition: elog.c:84
static uint32 set_xid_epoch
Definition: pg_resetwal.c:64

◆ ReadControlFile()

static bool ReadControlFile ( void  )
static

Definition at line 540 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(), WalSegSz, XLOG_CONTROL_FILE, and ControlFileData::xlog_seg_size.

Referenced by main().

541 {
542  int fd;
543  int len;
544  char *buffer;
545  pg_crc32c crc;
546 
547  if ((fd = open(XLOG_CONTROL_FILE, O_RDONLY | PG_BINARY, 0)) < 0)
548  {
549  /*
550  * If pg_control is not there at all, or we can't read it, the odds
551  * are we've been handed a bad DataDir path, so give up. User can do
552  * "touch pg_control" to force us to proceed.
553  */
554  fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
556  if (errno == ENOENT)
557  fprintf(stderr, _("If you are sure the data directory path is correct, execute\n"
558  " touch %s\n"
559  "and try again.\n"),
561  exit(1);
562  }
563 
564  /* Use malloc to ensure we have a maxaligned buffer */
565  buffer = (char *) pg_malloc(PG_CONTROL_FILE_SIZE);
566 
567  len = read(fd, buffer, PG_CONTROL_FILE_SIZE);
568  if (len < 0)
569  {
570  fprintf(stderr, _("%s: could not read file \"%s\": %s\n"),
572  exit(1);
573  }
574  close(fd);
575 
576  if (len >= sizeof(ControlFileData) &&
577  ((ControlFileData *) buffer)->pg_control_version == PG_CONTROL_VERSION)
578  {
579  /* Check the CRC. */
580  INIT_CRC32C(crc);
581  COMP_CRC32C(crc,
582  buffer,
583  offsetof(ControlFileData, crc));
584  FIN_CRC32C(crc);
585 
586  if (!EQ_CRC32C(crc, ((ControlFileData *) buffer)->crc))
587  {
588  /* We will use the data but treat it as guessed. */
589  fprintf(stderr,
590  _("%s: pg_control exists but has invalid CRC; proceed with caution\n"),
591  progname);
592  guessed = true;
593  }
594 
595  memcpy(&ControlFile, buffer, sizeof(ControlFile));
597 
598  /* return false if WalSegSz is not valid */
600  {
601  fprintf(stderr,
602  _("%s: pg_control specifies invalid WAL segment size (%d bytes); proceed with caution \n"),
603  progname, WalSegSz);
604  guessed = true;
605  }
606 
607  return true;
608  }
609 
610  /* Looks like it's a mess. */
611  fprintf(stderr, _("%s: pg_control exists but is broken or wrong version; ignoring it\n"),
612  progname);
613  return false;
614 }
#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:1035
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:63
static bool guessed
Definition: pg_resetwal.c:62
#define XLOG_CONTROL_FILE
static int WalSegSz
Definition: pg_resetwal.c:73
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
static ControlFileData ControlFile
Definition: pg_resetwal.c:60
#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:73
#define FIN_CRC32C(crc)
Definition: pg_crc32c.h:78
#define _(x)
Definition: elog.c:84
#define read(a, b, c)
Definition: win32.h:13
#define offsetof(type, field)
Definition: c.h:603

◆ RewriteControlFile()

static void RewriteControlFile ( void  )
static

Definition at line 854 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, progname, CheckPoint::redo, S_IRUSR, S_IWUSR, 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, ControlFileData::xlog_seg_size, and XLogSegNoOffsetToRecPtr.

Referenced by main().

855 {
856  int fd;
857  char buffer[PG_CONTROL_FILE_SIZE]; /* need not be aligned */
858 
859  /*
860  * For good luck, apply the same static assertions as in backend's
861  * WriteControlFile().
862  */
864  "pg_control is too large for atomic disk writes");
866  "sizeof(ControlFileData) exceeds PG_CONTROL_FILE_SIZE");
867 
868  /*
869  * Adjust fields as needed to force an empty XLOG starting at
870  * newXlogSegNo.
871  */
874  ControlFile.checkPointCopy.time = (pg_time_t) time(NULL);
875 
877  ControlFile.time = (pg_time_t) time(NULL);
884 
885  /*
886  * Force the defaults for max_* settings. The values don't really matter
887  * as long as wal_level='minimal'; the postmaster will reset these fields
888  * anyway at startup.
889  */
891  ControlFile.wal_log_hints = false;
897 
898  /* Now we can force the recorded xlog seg size to the right thing. */
900 
901  /* Contents are protected with a CRC */
904  (char *) &ControlFile,
905  offsetof(ControlFileData, crc));
906  FIN_CRC32C(ControlFile.crc);
907 
908  /*
909  * We write out PG_CONTROL_FILE_SIZE bytes into pg_control, zero-padding
910  * the excess over sizeof(ControlFileData). This reduces the odds of
911  * premature-EOF errors when reading pg_control. We'll still fail when we
912  * check the contents of the file, but hopefully with a more specific
913  * error than "couldn't read pg_control".
914  */
915  memset(buffer, 0, PG_CONTROL_FILE_SIZE);
916  memcpy(buffer, &ControlFile, sizeof(ControlFileData));
917 
918  unlink(XLOG_CONTROL_FILE);
919 
920  fd = open(XLOG_CONTROL_FILE,
921  O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
922  S_IRUSR | S_IWUSR);
923  if (fd < 0)
924  {
925  fprintf(stderr, _("%s: could not create pg_control file: %s\n"),
926  progname, strerror(errno));
927  exit(1);
928  }
929 
930  errno = 0;
931  if (write(fd, buffer, PG_CONTROL_FILE_SIZE) != PG_CONTROL_FILE_SIZE)
932  {
933  /* if write didn't set errno, assume problem is no disk space */
934  if (errno == 0)
935  errno = ENOSPC;
936  fprintf(stderr, _("%s: could not write pg_control file: %s\n"),
937  progname, strerror(errno));
938  exit(1);
939  }
940 
941  if (fsync(fd) != 0)
942  {
943  fprintf(stderr, _("%s: fsync error: %s\n"), progname, strerror(errno));
944  exit(1);
945  }
946 
947  close(fd);
948 }
#define INIT_CRC32C(crc)
Definition: pg_crc32c.h:41
int max_locks_per_xact
Definition: pg_control.h:181
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:1035
bool backupEndRequired
Definition: pg_control.h:170
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:763
#define fsync(fd)
Definition: win32_port.h:63
uint32 xlog_seg_size
Definition: pg_control.h:208
#define S_IWUSR
Definition: win32_port.h:274
#define XLogSegNoOffsetToRecPtr(segno, offset, dest, wal_segsz_bytes)
pg_crc32c crc
Definition: pg_control.h:231
static const char * progname
Definition: pg_resetwal.c:63
#define XLOG_CONTROL_FILE
XLogRecPtr backupEndPoint
Definition: pg_control.h:169
static int WalSegSz
Definition: pg_resetwal.c:73
bool track_commit_timestamp
Definition: pg_control.h:182
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
static ControlFileData ControlFile
Definition: pg_resetwal.c:60
#define PG_CONTROL_FILE_SIZE
Definition: pg_control.h:249
#define S_IRUSR
Definition: win32_port.h:271
static XLogSegNo newXlogSegNo
Definition: pg_resetwal.c:61
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:73
#define FIN_CRC32C(crc)
Definition: pg_crc32c.h:78
#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:603
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:166
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:72

◆ usage()

static void usage ( void  )
static

Definition at line 1249 of file pg_resetwal.c.

References _, and progname.

Referenced by main().

1250 {
1251  printf(_("%s resets the PostgreSQL write-ahead log.\n\n"), progname);
1252  printf(_("Usage:\n %s [OPTION]... DATADIR\n\n"), progname);
1253  printf(_("Options:\n"));
1254  printf(_(" -c XID,XID set oldest and newest transactions bearing commit timestamp\n"));
1255  printf(_(" (zero in either value means no change)\n"));
1256  printf(_(" [-D] DATADIR data directory\n"));
1257  printf(_(" -e XIDEPOCH set next transaction ID epoch\n"));
1258  printf(_(" -f force update to be done\n"));
1259  printf(_(" -l WALFILE force minimum WAL starting location for new write-ahead log\n"));
1260  printf(_(" -m MXID,MXID set next and oldest multitransaction ID\n"));
1261  printf(_(" -n no update, just show what would be done (for testing)\n"));
1262  printf(_(" -o OID set next OID\n"));
1263  printf(_(" -O OFFSET set next multitransaction offset\n"));
1264  printf(_(" -V, --version output version information, then exit\n"));
1265  printf(_(" -x XID set next transaction ID\n"));
1266  printf(_(" -?, --help show this help, then exit\n"));
1267  printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
1268 }
static const char * progname
Definition: pg_resetwal.c:63
#define _(x)
Definition: elog.c:84

◆ WriteEmptyXLOG()

static void WriteEmptyXLOG ( void  )
static

Definition at line 1149 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_malloc(), progname, CheckPoint::redo, S_IRUSR, S_IWUSR, 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().

1150 {
1151  char *buffer;
1152  XLogPageHeader page;
1153  XLogLongPageHeader longpage;
1154  XLogRecord *record;
1155  pg_crc32c crc;
1156  char path[MAXPGPATH];
1157  int fd;
1158  int nbytes;
1159  char *recptr;
1160 
1161  /* Use malloc() to ensure buffer is MAXALIGNED */
1162  buffer = (char *) pg_malloc(XLOG_BLCKSZ);
1163  page = (XLogPageHeader) buffer;
1164  memset(buffer, 0, XLOG_BLCKSZ);
1165 
1166  /* Set up the XLOG page header */
1167  page->xlp_magic = XLOG_PAGE_MAGIC;
1168  page->xlp_info = XLP_LONG_HEADER;
1171  longpage = (XLogLongPageHeader) page;
1173  longpage->xlp_seg_size = WalSegSz;
1174  longpage->xlp_xlog_blcksz = XLOG_BLCKSZ;
1175 
1176  /* Insert the initial checkpoint record */
1177  recptr = (char *) page + SizeOfXLogLongPHD;
1178  record = (XLogRecord *) recptr;
1179  record->xl_prev = 0;
1180  record->xl_xid = InvalidTransactionId;
1183  record->xl_rmid = RM_XLOG_ID;
1184 
1185  recptr += SizeOfXLogRecord;
1186  *(recptr++) = (char) XLR_BLOCK_ID_DATA_SHORT;
1187  *(recptr++) = sizeof(CheckPoint);
1188  memcpy(recptr, &ControlFile.checkPointCopy,
1189  sizeof(CheckPoint));
1190 
1191  INIT_CRC32C(crc);
1192  COMP_CRC32C(crc, ((char *) record) + SizeOfXLogRecord, record->xl_tot_len - SizeOfXLogRecord);
1193  COMP_CRC32C(crc, (char *) record, offsetof(XLogRecord, xl_crc));
1194  FIN_CRC32C(crc);
1195  record->xl_crc = crc;
1196 
1197  /* Write the first page */
1200 
1201  unlink(path);
1202 
1203  fd = open(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
1204  S_IRUSR | S_IWUSR);
1205  if (fd < 0)
1206  {
1207  fprintf(stderr, _("%s: could not open file \"%s\": %s\n"),
1208  progname, path, strerror(errno));
1209  exit(1);
1210  }
1211 
1212  errno = 0;
1213  if (write(fd, buffer, XLOG_BLCKSZ) != XLOG_BLCKSZ)
1214  {
1215  /* if write didn't set errno, assume problem is no disk space */
1216  if (errno == 0)
1217  errno = ENOSPC;
1218  fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
1219  progname, path, strerror(errno));
1220  exit(1);
1221  }
1222 
1223  /* Fill the rest of the file with zeroes */
1224  memset(buffer, 0, XLOG_BLCKSZ);
1225  for (nbytes = XLOG_BLCKSZ; nbytes < WalSegSz; nbytes += XLOG_BLCKSZ)
1226  {
1227  errno = 0;
1228  if (write(fd, buffer, XLOG_BLCKSZ) != XLOG_BLCKSZ)
1229  {
1230  if (errno == 0)
1231  errno = ENOSPC;
1232  fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
1233  progname, path, strerror(errno));
1234  exit(1);
1235  }
1236  }
1237 
1238  if (fsync(fd) != 0)
1239  {
1240  fprintf(stderr, _("%s: fsync error: %s\n"), progname, strerror(errno));
1241  exit(1);
1242  }
1243 
1244  close(fd);
1245 }
#define INIT_CRC32C(crc)
Definition: pg_crc32c.h:41
XLogRecPtr xl_prev
Definition: xlogrecord.h:45
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:1035
XLogLongPageHeaderData * XLogLongPageHeader
Definition: xlog_internal.h:74
#define fsync(fd)
Definition: win32_port.h:63
#define S_IWUSR
Definition: win32_port.h:274
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:63
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:73
#define XLP_LONG_HEADER
Definition: xlog_internal.h:79
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
static ControlFileData ControlFile
Definition: pg_resetwal.c:60
uint8 xl_info
Definition: xlogrecord.h:46
struct CheckPoint CheckPoint
#define S_IRUSR
Definition: win32_port.h:271
#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:61
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:73
#define FIN_CRC32C(crc)
Definition: pg_crc32c.h:78
#define _(x)
Definition: elog.c:84
XLogRecPtr redo
Definition: pg_control.h:36
#define offsetof(type, field)
Definition: c.h:603
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:72

Variable Documentation

◆ ControlFile

ControlFileData ControlFile
static

Definition at line 60 of file pg_resetwal.c.

◆ guessed

bool guessed = false
static

Definition at line 62 of file pg_resetwal.c.

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

◆ minXlogSegNo

XLogSegNo minXlogSegNo = 0
static

Definition at line 72 of file pg_resetwal.c.

Referenced by main().

◆ minXlogTli

uint32 minXlogTli = 0
static

Definition at line 71 of file pg_resetwal.c.

Referenced by main().

◆ newXlogSegNo

XLogSegNo newXlogSegNo
static

◆ progname

◆ set_mxid

MultiXactId set_mxid = 0
static

Definition at line 69 of file pg_resetwal.c.

Referenced by main(), and PrintNewControlValues().

◆ set_mxoff

MultiXactOffset set_mxoff = (MultiXactOffset) -1
static

Definition at line 70 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 67 of file pg_resetwal.c.

Referenced by main(), and PrintNewControlValues().

◆ set_oid

Oid set_oid = 0
static

Definition at line 68 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 66 of file pg_resetwal.c.

Referenced by main(), and PrintNewControlValues().

◆ set_xid

TransactionId set_xid = 0
static

Definition at line 65 of file pg_resetwal.c.

Referenced by main(), and PrintNewControlValues().

◆ set_xid_epoch

uint32 set_xid_epoch = (uint32) -1
static

Definition at line 64 of file pg_resetwal.c.

Referenced by main(), and PrintNewControlValues().

◆ WalSegSz

int WalSegSz
static