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/heaptoast.h"
#include "access/multixact.h"
#include "access/xlog.h"
#include "access/xlog_internal.h"
#include "common/controldata_utils.h"
#include "common/fe_memutils.h"
#include "common/file_perm.h"
#include "common/logging.h"
#include "common/restricted_token.h"
#include "common/string.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 537 of file pg_resetwal.c.

References pg_log_error, pg_log_info, and pg_strip_crlf().

Referenced by main().

538 {
539  const char *ver_file = "PG_VERSION";
540  FILE *ver_fd;
541  char rawline[64];
542 
543  if ((ver_fd = fopen(ver_file, "r")) == NULL)
544  {
545  pg_log_error("could not open file \"%s\" for reading: %m",
546  ver_file);
547  exit(1);
548  }
549 
550  /* version number has to be the first line read */
551  if (!fgets(rawline, sizeof(rawline), ver_fd))
552  {
553  if (!ferror(ver_fd))
554  pg_log_error("unexpected empty file \"%s\"", ver_file);
555  else
556  pg_log_error("could not read file \"%s\": %m", ver_file);
557  exit(1);
558  }
559 
560  /* strip trailing newline and carriage return */
561  (void) pg_strip_crlf(rawline);
562 
563  if (strcmp(rawline, PG_MAJORVERSION) != 0)
564  {
565  pg_log_error("data directory is of wrong version");
566  pg_log_info("File \"%s\" contains \"%s\", which is not compatible with this program's version \"%s\".",
567  ver_file, rawline, PG_MAJORVERSION);
568  exit(1);
569  }
570 
571  fclose(ver_fd);
572 }
int pg_strip_crlf(char *str)
Definition: string.c:105
#define pg_log_error(...)
Definition: logging.h:79
#define pg_log_info(...)
Definition: logging.h:87

◆ FindEndOfXLOG()

static void FindEndOfXLOG ( void  )
static

Definition at line 937 of file pg_resetwal.c.

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

Referenced by main().

938 {
939  DIR *xldir;
940  struct dirent *xlde;
941  uint64 segs_per_xlogid;
942  uint64 xlogbytepos;
943 
944  /*
945  * Initialize the max() computation using the last checkpoint address from
946  * old pg_control. Note that for the moment we are working with segment
947  * numbering according to the old xlog seg size.
948  */
949  segs_per_xlogid = (UINT64CONST(0x0000000100000000) / ControlFile.xlog_seg_size);
951 
952  /*
953  * Scan the pg_wal directory to find existing WAL segment files. We assume
954  * any present have been used; in most scenarios this should be
955  * conservative, because of xlog.c's attempts to pre-create files.
956  */
957  xldir = opendir(XLOGDIR);
958  if (xldir == NULL)
959  {
960  pg_log_error("could not open directory \"%s\": %m", XLOGDIR);
961  exit(1);
962  }
963 
964  while (errno = 0, (xlde = readdir(xldir)) != NULL)
965  {
966  if (IsXLogFileName(xlde->d_name) ||
968  {
969  unsigned int tli,
970  log,
971  seg;
972  XLogSegNo segno;
973 
974  /*
975  * Note: We don't use XLogFromFileName here, because we want to
976  * use the segment size from the control file, not the size the
977  * pg_resetwal binary was compiled with
978  */
979  sscanf(xlde->d_name, "%08X%08X%08X", &tli, &log, &seg);
980  segno = ((uint64) log) * segs_per_xlogid + seg;
981 
982  /*
983  * Note: we take the max of all files found, regardless of their
984  * timelines. Another possibility would be to ignore files of
985  * timelines other than the target TLI, but this seems safer.
986  * Better too large a result than too small...
987  */
988  if (segno > newXlogSegNo)
989  newXlogSegNo = segno;
990  }
991  }
992 
993  if (errno)
994  {
995  pg_log_error("could not read directory \"%s\": %m", XLOGDIR);
996  exit(1);
997  }
998 
999  if (closedir(xldir))
1000  {
1001  pg_log_error("could not close directory \"%s\": %m", XLOGDIR);
1002  exit(1);
1003  }
1004 
1005  /*
1006  * Finally, convert to new xlog seg size, and advance by one to ensure we
1007  * are in virgin territory.
1008  */
1009  xlogbytepos = newXlogSegNo * ControlFile.xlog_seg_size;
1010  newXlogSegNo = (xlogbytepos + ControlFile.xlog_seg_size - 1) / WalSegSz;
1011  newXlogSegNo++;
1012 }
#define pg_log_error(...)
Definition: logging.h:79
int closedir(DIR *)
Definition: dirent.c:113
CheckPoint checkPointCopy
Definition: pg_control.h:131
Definition: dirent.h:9
uint32 xlog_seg_size
Definition: pg_control.h:209
Definition: dirent.c:25
#define IsXLogFileName(fname)
DIR * opendir(const char *)
Definition: dirent.c:33
uint64 XLogSegNo
Definition: xlogdefs.h:41
#define XLOGDIR
static int WalSegSz
Definition: pg_resetwal.c:76
static ControlFileData ControlFile
Definition: pg_resetwal.c:63
struct dirent * readdir(DIR *)
Definition: dirent.c:77
static XLogSegNo newXlogSegNo
Definition: pg_resetwal.c:64
#define IsPartialXLogFileName(fname)
char d_name[MAX_PATH]
Definition: dirent.h:14
XLogRecPtr redo
Definition: pg_control.h:37

◆ GuessControlValues()

static void GuessControlValues ( void  )
static

Definition at line 659 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, FullTransactionIdFromEpochAndXid(), gettimeofday(), guessed, INDEX_MAX_KEYS, ControlFileData::indexMaxKeys, InvalidOid, InvalidTransactionId, LOBLKSIZE, ControlFileData::loblksize, ControlFileData::max_locks_per_xact, ControlFileData::max_prepared_xacts, ControlFileData::max_wal_senders, ControlFileData::max_worker_processes, ControlFileData::maxAlign, ControlFileData::MaxConnections, NAMEDATALEN, ControlFileData::nameDataLen, CheckPoint::nextFullXid, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, CheckPoint::nextOid, 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().

660 {
661  uint64 sysidentifier;
662  struct timeval tv;
663 
664  /*
665  * Set up a completely default set of pg_control values.
666  */
667  guessed = true;
668  memset(&ControlFile, 0, sizeof(ControlFile));
669 
672 
673  /*
674  * Create a new unique installation identifier, since we can no longer use
675  * any old XLOG records. See notes in xlog.c about the algorithm.
676  */
677  gettimeofday(&tv, NULL);
678  sysidentifier = ((uint64) tv.tv_sec) << 32;
679  sysidentifier |= ((uint64) tv.tv_usec) << 12;
680  sysidentifier |= getpid() & 0xFFF;
681 
682  ControlFile.system_identifier = sysidentifier;
683 
697  ControlFile.checkPointCopy.time = (pg_time_t) time(NULL);
699 
701  ControlFile.time = (pg_time_t) time(NULL);
704 
705  /* minRecoveryPoint, backupStartPoint and backupEndPoint can be left zero */
706 
708  ControlFile.wal_log_hints = false;
715 
716  ControlFile.maxAlign = MAXIMUM_ALIGNOF;
718  ControlFile.blcksz = BLCKSZ;
719  ControlFile.relseg_size = RELSEG_SIZE;
720  ControlFile.xlog_blcksz = XLOG_BLCKSZ;
726  ControlFile.float4ByVal = FLOAT4PASSBYVAL;
727  ControlFile.float8ByVal = FLOAT8PASSBYVAL;
728 
729  /*
730  * XXX eventually, should try to grovel through old XLOG to develop more
731  * accurate values for TimeLineID, nextXID, etc.
732  */
733 }
#define LOBLKSIZE
Definition: large_object.h:70
int max_locks_per_xact
Definition: pg_control.h:182
int gettimeofday(struct timeval *tp, struct timezone *tzp)
Definition: gettimeofday.c:105
int max_prepared_xacts
Definition: pg_control.h:181
int64 pg_time_t
Definition: pgtime.h:23
#define TOAST_MAX_CHUNK_SIZE
Definition: heaptoast.h:84
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:211
MultiXactId oldestMulti
Definition: pg_control.h:49
#define DEFAULT_XLOG_SEG_SIZE
TimeLineID PrevTimeLineID
Definition: pg_control.h:40
#define CATALOG_VERSION_NO
Definition: catversion.h:56
#define PG_CONTROL_VERSION
Definition: pg_control.h:25
uint32 pg_control_version
Definition: pg_control.h:121
CheckPoint checkPointCopy
Definition: pg_control.h:131
uint32 xlog_blcksz
Definition: pg_control.h:208
TransactionId oldestXid
Definition: pg_control.h:47
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:209
#define FirstNormalTransactionId
Definition: transam.h:34
uint64 system_identifier
Definition: pg_control.h:106
XLogRecPtr unloggedLSN
Definition: pg_control.h:133
#define InvalidTransactionId
Definition: transam.h:31
#define FirstBootstrapObjectId
Definition: transam.h:140
#define FirstMultiXactId
Definition: multixact.h:24
uint32 loblksize
Definition: pg_control.h:215
uint32 indexMaxKeys
Definition: pg_control.h:212
static bool guessed
Definition: pg_resetwal.c:65
Oid oldestMultiDB
Definition: pg_control.h:50
uint32 toast_max_chunk_size
Definition: pg_control.h:214
#define InvalidOid
Definition: postgres_ext.h:36
Oid nextOid
Definition: pg_control.h:44
bool fullPageWrites
Definition: pg_control.h:42
bool track_commit_timestamp
Definition: pg_control.h:183
FullTransactionId nextFullXid
Definition: pg_control.h:43
Oid oldestXidDB
Definition: pg_control.h:48
static ControlFileData ControlFile
Definition: pg_resetwal.c:63
double floatFormat
Definition: pg_control.h:198
#define INDEX_MAX_KEYS
MultiXactId nextMulti
Definition: pg_control.h:45
static FullTransactionId FullTransactionIdFromEpochAndXid(uint32 epoch, TransactionId xid)
Definition: transam.h:65
uint32 catalog_version_no
Definition: pg_control.h:122
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
#define FLOATFORMAT_VALUE
Definition: pg_control.h:199
uint32 relseg_size
Definition: pg_control.h:206
XLogRecPtr checkPoint
Definition: pg_control.h:129
XLogRecPtr redo
Definition: pg_control.h:37
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:72

◆ KillExistingArchiveStatus()

static void KillExistingArchiveStatus ( void  )
static

Definition at line 1064 of file pg_resetwal.c.

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

Referenced by main().

1065 {
1066 #define ARCHSTATDIR XLOGDIR "/archive_status"
1067 
1068  DIR *xldir;
1069  struct dirent *xlde;
1070  char path[MAXPGPATH + sizeof(ARCHSTATDIR)];
1071 
1072  xldir = opendir(ARCHSTATDIR);
1073  if (xldir == NULL)
1074  {
1075  pg_log_error("could not open directory \"%s\": %m", ARCHSTATDIR);
1076  exit(1);
1077  }
1078 
1079  while (errno = 0, (xlde = readdir(xldir)) != NULL)
1080  {
1081  if (strspn(xlde->d_name, "0123456789ABCDEF") == XLOG_FNAME_LEN &&
1082  (strcmp(xlde->d_name + XLOG_FNAME_LEN, ".ready") == 0 ||
1083  strcmp(xlde->d_name + XLOG_FNAME_LEN, ".done") == 0 ||
1084  strcmp(xlde->d_name + XLOG_FNAME_LEN, ".partial.ready") == 0 ||
1085  strcmp(xlde->d_name + XLOG_FNAME_LEN, ".partial.done") == 0))
1086  {
1087  snprintf(path, sizeof(path), "%s/%s", ARCHSTATDIR, xlde->d_name);
1088  if (unlink(path) < 0)
1089  {
1090  pg_log_error("could not delete file \"%s\": %m", path);
1091  exit(1);
1092  }
1093  }
1094  }
1095 
1096  if (errno)
1097  {
1098  pg_log_error("could not read directory \"%s\": %m", ARCHSTATDIR);
1099  exit(1);
1100  }
1101 
1102  if (closedir(xldir))
1103  {
1104  pg_log_error("could not close directory \"%s\": %m", ARCHSTATDIR);
1105  exit(1);
1106  }
1107 }
#define pg_log_error(...)
Definition: logging.h:79
int closedir(DIR *)
Definition: dirent.c:113
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
DIR * opendir(const char *)
Definition: dirent.c:33
struct dirent * readdir(DIR *)
Definition: dirent.c:77
#define ARCHSTATDIR
#define XLOG_FNAME_LEN
char d_name[MAX_PATH]
Definition: dirent.h:14
#define snprintf
Definition: port.h:192

◆ KillExistingXLOG()

static void KillExistingXLOG ( void  )
static

Definition at line 1019 of file pg_resetwal.c.

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

Referenced by main().

1020 {
1021  DIR *xldir;
1022  struct dirent *xlde;
1023  char path[MAXPGPATH + sizeof(XLOGDIR)];
1024 
1025  xldir = opendir(XLOGDIR);
1026  if (xldir == NULL)
1027  {
1028  pg_log_error("could not open directory \"%s\": %m", XLOGDIR);
1029  exit(1);
1030  }
1031 
1032  while (errno = 0, (xlde = readdir(xldir)) != NULL)
1033  {
1034  if (IsXLogFileName(xlde->d_name) ||
1036  {
1037  snprintf(path, sizeof(path), "%s/%s", XLOGDIR, xlde->d_name);
1038  if (unlink(path) < 0)
1039  {
1040  pg_log_error("could not delete file \"%s\": %m", path);
1041  exit(1);
1042  }
1043  }
1044  }
1045 
1046  if (errno)
1047  {
1048  pg_log_error("could not read directory \"%s\": %m", XLOGDIR);
1049  exit(1);
1050  }
1051 
1052  if (closedir(xldir))
1053  {
1054  pg_log_error("could not close directory \"%s\": %m", XLOGDIR);
1055  exit(1);
1056  }
1057 }
#define pg_log_error(...)
Definition: logging.h:79
int closedir(DIR *)
Definition: dirent.c:113
Definition: dirent.h:9
Definition: dirent.c:25
#define IsXLogFileName(fname)
#define MAXPGPATH
DIR * opendir(const char *)
Definition: dirent.c:33
#define XLOGDIR
struct dirent * readdir(DIR *)
Definition: dirent.c:77
#define IsPartialXLogFileName(fname)
char d_name[MAX_PATH]
Definition: dirent.h:14
#define snprintf
Definition: port.h:192

◆ main()

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

Definition at line 93 of file pg_resetwal.c.

References _, CheckDataVersion(), ControlFileData::checkPointCopy, DataDir, DB_SHUTDOWNED, EpochFromFullTransactionId, fd(), FindEndOfXLOG(), FirstMultiXactId, FirstNormalTransactionId, fprintf, FullTransactionIdFromEpochAndXid(), get_progname(), get_restricted_token(), GetDataDirectoryCreatePerm(), getopt_long(), GuessControlValues(), guessed, InvalidOid, IsValidWalSegSize, KillExistingArchiveStatus(), KillExistingXLOG(), minXlogSegNo, minXlogTli, CheckPoint::newestCommitTsXid, newXlogSegNo, CheckPoint::nextFullXid, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, CheckPoint::nextOid, no_argument, CheckPoint::oldestCommitTsXid, CheckPoint::oldestMulti, CheckPoint::oldestMultiDB, CheckPoint::oldestXid, CheckPoint::oldestXidDB, optarg, optind, pg_log_error, pg_log_info, pg_logging_init(), pg_mode_mask, pg_strdup(), PG_TEXTDOMAIN, CheckPoint::PrevTimeLineID, PrintControlValues(), printf, 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, CheckPoint::ThisTimeLineID, usage(), WalSegSz, WriteEmptyXLOG(), XidFromFullTransactionId, XLOG_FNAME_LEN, ControlFileData::xlog_seg_size, and XLogFromFileName.

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

◆ PrintControlValues()

static void PrintControlValues ( bool  guessed)
static

Definition at line 743 of file pg_resetwal.c.

References _, ControlFileData::blcksz, ControlFileData::catalog_version_no, ControlFileData::checkPointCopy, ControlFileData::data_checksum_version, EpochFromFullTransactionId, ControlFileData::float4ByVal, ControlFileData::float8ByVal, CheckPoint::fullPageWrites, ControlFileData::indexMaxKeys, ControlFileData::loblksize, ControlFileData::maxAlign, ControlFileData::nameDataLen, CheckPoint::newestCommitTsXid, CheckPoint::nextFullXid, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, CheckPoint::nextOid, CheckPoint::oldestActiveXid, CheckPoint::oldestCommitTsXid, CheckPoint::oldestMulti, CheckPoint::oldestMultiDB, CheckPoint::oldestXid, CheckPoint::oldestXidDB, ControlFileData::pg_control_version, printf, ControlFileData::relseg_size, ControlFileData::system_identifier, CheckPoint::ThisTimeLineID, ControlFileData::toast_max_chunk_size, XidFromFullTransactionId, ControlFileData::xlog_blcksz, and ControlFileData::xlog_seg_size.

Referenced by main().

744 {
745  if (guessed)
746  printf(_("Guessed pg_control values:\n\n"));
747  else
748  printf(_("Current pg_control values:\n\n"));
749 
750  printf(_("pg_control version number: %u\n"),
752  printf(_("Catalog version number: %u\n"),
754  printf(_("Database system identifier: %llu\n"),
755  (unsigned long long) ControlFile.system_identifier);
756  printf(_("Latest checkpoint's TimeLineID: %u\n"),
758  printf(_("Latest checkpoint's full_page_writes: %s\n"),
759  ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off"));
760  printf(_("Latest checkpoint's NextXID: %u:%u\n"),
763  printf(_("Latest checkpoint's NextOID: %u\n"),
765  printf(_("Latest checkpoint's NextMultiXactId: %u\n"),
767  printf(_("Latest checkpoint's NextMultiOffset: %u\n"),
769  printf(_("Latest checkpoint's oldestXID: %u\n"),
771  printf(_("Latest checkpoint's oldestXID's DB: %u\n"),
773  printf(_("Latest checkpoint's oldestActiveXID: %u\n"),
775  printf(_("Latest checkpoint's oldestMultiXid: %u\n"),
777  printf(_("Latest checkpoint's oldestMulti's DB: %u\n"),
779  printf(_("Latest checkpoint's oldestCommitTsXid:%u\n"),
781  printf(_("Latest checkpoint's newestCommitTsXid:%u\n"),
783  printf(_("Maximum data alignment: %u\n"),
785  /* we don't print floatFormat since can't say much useful about it */
786  printf(_("Database block size: %u\n"),
788  printf(_("Blocks per segment of large relation: %u\n"),
790  printf(_("WAL block size: %u\n"),
792  printf(_("Bytes per WAL segment: %u\n"),
794  printf(_("Maximum length of identifiers: %u\n"),
796  printf(_("Maximum columns in an index: %u\n"),
798  printf(_("Maximum size of a TOAST chunk: %u\n"),
800  printf(_("Size of a large-object chunk: %u\n"),
802  /* This is no longer configurable, but users may still expect to see it: */
803  printf(_("Date/time type storage: %s\n"),
804  _("64-bit integers"));
805  printf(_("Float4 argument passing: %s\n"),
806  (ControlFile.float4ByVal ? _("by value") : _("by reference")));
807  printf(_("Float8 argument passing: %s\n"),
808  (ControlFile.float8ByVal ? _("by value") : _("by reference")));
809  printf(_("Data page checksum version: %u\n"),
811 }
TransactionId oldestActiveXid
Definition: pg_control.h:63
uint32 nameDataLen
Definition: pg_control.h:211
MultiXactId oldestMulti
Definition: pg_control.h:49
uint32 pg_control_version
Definition: pg_control.h:121
#define printf(...)
Definition: port.h:198
CheckPoint checkPointCopy
Definition: pg_control.h:131
uint32 xlog_blcksz
Definition: pg_control.h:208
TransactionId oldestXid
Definition: pg_control.h:47
#define XidFromFullTransactionId(x)
Definition: transam.h:48
MultiXactOffset nextMultiOffset
Definition: pg_control.h:46
TransactionId oldestCommitTsXid
Definition: pg_control.h:52
uint32 xlog_seg_size
Definition: pg_control.h:209
uint64 system_identifier
Definition: pg_control.h:106
uint32 data_checksum_version
Definition: pg_control.h:222
uint32 loblksize
Definition: pg_control.h:215
uint32 indexMaxKeys
Definition: pg_control.h:212
static bool guessed
Definition: pg_resetwal.c:65
TransactionId newestCommitTsXid
Definition: pg_control.h:54
Oid oldestMultiDB
Definition: pg_control.h:50
uint32 toast_max_chunk_size
Definition: pg_control.h:214
#define EpochFromFullTransactionId(x)
Definition: transam.h:47
Oid nextOid
Definition: pg_control.h:44
bool fullPageWrites
Definition: pg_control.h:42
FullTransactionId nextFullXid
Definition: pg_control.h:43
Oid oldestXidDB
Definition: pg_control.h:48
static ControlFileData ControlFile
Definition: pg_resetwal.c:63
MultiXactId nextMulti
Definition: pg_control.h:45
uint32 catalog_version_no
Definition: pg_control.h:122
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
#define _(x)
Definition: elog.c:84
uint32 relseg_size
Definition: pg_control.h:206

◆ PrintNewControlValues()

static void PrintNewControlValues ( void  )
static

Definition at line 818 of file pg_resetwal.c.

References _, ControlFileData::checkPointCopy, EpochFromFullTransactionId, MAXFNAMELEN, CheckPoint::newestCommitTsXid, newXlogSegNo, CheckPoint::nextFullXid, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, CheckPoint::nextOid, CheckPoint::oldestCommitTsXid, CheckPoint::oldestMulti, CheckPoint::oldestMultiDB, CheckPoint::oldestXid, CheckPoint::oldestXidDB, printf, 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, XidFromFullTransactionId, ControlFileData::xlog_seg_size, and XLogFileName.

Referenced by main().

819 {
820  char fname[MAXFNAMELEN];
821 
822  /* This will be always printed in order to keep format same. */
823  printf(_("\n\nValues to be changed:\n\n"));
824 
827  printf(_("First log segment after reset: %s\n"), fname);
828 
829  if (set_mxid != 0)
830  {
831  printf(_("NextMultiXactId: %u\n"),
833  printf(_("OldestMultiXid: %u\n"),
835  printf(_("OldestMulti's DB: %u\n"),
837  }
838 
839  if (set_mxoff != -1)
840  {
841  printf(_("NextMultiOffset: %u\n"),
843  }
844 
845  if (set_oid != 0)
846  {
847  printf(_("NextOID: %u\n"),
849  }
850 
851  if (set_xid != 0)
852  {
853  printf(_("NextXID: %u\n"),
855  printf(_("OldestXID: %u\n"),
857  printf(_("OldestXID's DB: %u\n"),
859  }
860 
861  if (set_xid_epoch != -1)
862  {
863  printf(_("NextXID epoch: %u\n"),
865  }
866 
867  if (set_oldest_commit_ts_xid != 0)
868  {
869  printf(_("oldestCommitTsXid: %u\n"),
871  }
872  if (set_newest_commit_ts_xid != 0)
873  {
874  printf(_("newestCommitTsXid: %u\n"),
876  }
877 
878  if (set_wal_segsize != 0)
879  {
880  printf(_("Bytes per WAL segment: %u\n"),
882  }
883 }
static MultiXactId set_mxid
Definition: pg_resetwal.c:72
static TransactionId set_xid
Definition: pg_resetwal.c:68
static int set_wal_segsize
Definition: pg_resetwal.c:77
MultiXactId oldestMulti
Definition: pg_control.h:49
static Oid set_oid
Definition: pg_resetwal.c:71
#define printf(...)
Definition: port.h:198
CheckPoint checkPointCopy
Definition: pg_control.h:131
TransactionId oldestXid
Definition: pg_control.h:47
#define XidFromFullTransactionId(x)
Definition: transam.h:48
static TransactionId set_newest_commit_ts_xid
Definition: pg_resetwal.c:70
MultiXactOffset nextMultiOffset
Definition: pg_control.h:46
TransactionId oldestCommitTsXid
Definition: pg_control.h:52
uint32 xlog_seg_size
Definition: pg_control.h:209
static TransactionId set_oldest_commit_ts_xid
Definition: pg_resetwal.c:69
#define MAXFNAMELEN
TransactionId newestCommitTsXid
Definition: pg_control.h:54
Oid oldestMultiDB
Definition: pg_control.h:50
#define EpochFromFullTransactionId(x)
Definition: transam.h:47
Oid nextOid
Definition: pg_control.h:44
static int WalSegSz
Definition: pg_resetwal.c:76
FullTransactionId nextFullXid
Definition: pg_control.h:43
Oid oldestXidDB
Definition: pg_control.h:48
static ControlFileData ControlFile
Definition: pg_resetwal.c:63
#define XLogFileName(fname, tli, logSegNo, wal_segsz_bytes)
MultiXactId nextMulti
Definition: pg_control.h:45
static MultiXactOffset set_mxoff
Definition: pg_resetwal.c:73
static XLogSegNo newXlogSegNo
Definition: pg_resetwal.c:64
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
#define _(x)
Definition: elog.c:84
static uint32 set_xid_epoch
Definition: pg_resetwal.c:67

◆ ReadControlFile()

static bool ReadControlFile ( void  )
static

Definition at line 582 of file pg_resetwal.c.

References close, COMP_CRC32C, EQ_CRC32C, fd(), FIN_CRC32C, guessed, INIT_CRC32C, IsValidWalSegSize, ngettext, offsetof, PG_BINARY, PG_CONTROL_FILE_SIZE, PG_CONTROL_VERSION, pg_log_error, pg_log_info, pg_log_warning, pg_malloc(), read, XLOG_CONTROL_FILE, and ControlFileData::xlog_seg_size.

Referenced by main().

583 {
584  int fd;
585  int len;
586  char *buffer;
587  pg_crc32c crc;
588 
589  if ((fd = open(XLOG_CONTROL_FILE, O_RDONLY | PG_BINARY, 0)) < 0)
590  {
591  /*
592  * If pg_control is not there at all, or we can't read it, the odds
593  * are we've been handed a bad DataDir path, so give up. User can do
594  * "touch pg_control" to force us to proceed.
595  */
596  pg_log_error("could not open file \"%s\" for reading: %m",
598  if (errno == ENOENT)
599  pg_log_info("If you are sure the data directory path is correct, execute\n"
600  " touch %s\n"
601  "and try again.",
603  exit(1);
604  }
605 
606  /* Use malloc to ensure we have a maxaligned buffer */
607  buffer = (char *) pg_malloc(PG_CONTROL_FILE_SIZE);
608 
609  len = read(fd, buffer, PG_CONTROL_FILE_SIZE);
610  if (len < 0)
611  {
612  pg_log_error("could not read file \"%s\": %m", XLOG_CONTROL_FILE);
613  exit(1);
614  }
615  close(fd);
616 
617  if (len >= sizeof(ControlFileData) &&
618  ((ControlFileData *) buffer)->pg_control_version == PG_CONTROL_VERSION)
619  {
620  /* Check the CRC. */
621  INIT_CRC32C(crc);
622  COMP_CRC32C(crc,
623  buffer,
624  offsetof(ControlFileData, crc));
625  FIN_CRC32C(crc);
626 
627  if (!EQ_CRC32C(crc, ((ControlFileData *) buffer)->crc))
628  {
629  /* We will use the data but treat it as guessed. */
630  pg_log_warning("pg_control exists but has invalid CRC; proceed with caution");
631  guessed = true;
632  }
633 
634  memcpy(&ControlFile, buffer, sizeof(ControlFile));
635 
636  /* return false if WAL segment size is not valid */
638  {
639  pg_log_warning(ngettext("pg_control specifies invalid WAL segment size (%d byte); proceed with caution",
640  "pg_control specifies invalid WAL segment size (%d bytes); proceed with caution",
643  return false;
644  }
645 
646  return true;
647  }
648 
649  /* Looks like it's a mess. */
650  pg_log_warning("pg_control exists but is broken or wrong version; ignoring it");
651  return false;
652 }
#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
#define pg_log_error(...)
Definition: logging.h:79
uint32 pg_crc32c
Definition: pg_crc32c.h:38
#define PG_CONTROL_VERSION
Definition: pg_control.h:25
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1191
uint32 xlog_seg_size
Definition: pg_control.h:209
#define EQ_CRC32C(c1, c2)
Definition: pg_crc32c.h:42
static bool guessed
Definition: pg_resetwal.c:65
#define ngettext(s, p, n)
Definition: c.h:1103
#define XLOG_CONTROL_FILE
static ControlFileData ControlFile
Definition: pg_resetwal.c:63
#define PG_CONTROL_FILE_SIZE
Definition: pg_control.h:250
#define close(a)
Definition: win32.h:12
#define pg_log_warning(...)
Definition: pgfnames.c:24
#define COMP_CRC32C(crc, data, len)
Definition: pg_crc32c.h:89
#define FIN_CRC32C(crc)
Definition: pg_crc32c.h:94
#define read(a, b, c)
Definition: win32.h:13
#define offsetof(type, field)
Definition: c.h:655
#define pg_log_info(...)
Definition: logging.h:87

◆ RewriteControlFile()

static void RewriteControlFile ( void  )
static

Definition at line 890 of file pg_resetwal.c.

References ControlFileData::backupEndPoint, ControlFileData::backupEndRequired, ControlFileData::backupStartPoint, ControlFileData::checkPoint, ControlFileData::checkPointCopy, DB_SHUTDOWNED, ControlFileData::max_locks_per_xact, ControlFileData::max_prepared_xacts, ControlFileData::max_wal_senders, ControlFileData::max_worker_processes, ControlFileData::MaxConnections, ControlFileData::minRecoveryPoint, ControlFileData::minRecoveryPointTLI, newXlogSegNo, CheckPoint::redo, SizeOfXLogLongPHD, ControlFileData::state, CheckPoint::time, ControlFileData::time, ControlFileData::track_commit_timestamp, update_controlfile(), ControlFileData::wal_level, WAL_LEVEL_MINIMAL, ControlFileData::wal_log_hints, WalSegSz, and XLogSegNoOffsetToRecPtr.

Referenced by main().

891 {
892  /*
893  * Adjust fields as needed to force an empty XLOG starting at
894  * newXlogSegNo.
895  */
898  ControlFile.checkPointCopy.time = (pg_time_t) time(NULL);
899 
901  ControlFile.time = (pg_time_t) time(NULL);
908 
909  /*
910  * Force the defaults for max_* settings. The values don't really matter
911  * as long as wal_level='minimal'; the postmaster will reset these fields
912  * anyway at startup.
913  */
915  ControlFile.wal_log_hints = false;
922 
923  /* The control file gets flushed here. */
924  update_controlfile(".", &ControlFile, true);
925 }
int max_locks_per_xact
Definition: pg_control.h:182
int max_prepared_xacts
Definition: pg_control.h:181
int64 pg_time_t
Definition: pgtime.h:23
pg_time_t time
Definition: pg_control.h:128
TimeLineID minRecoveryPointTLI
Definition: pg_control.h:167
int max_worker_processes
Definition: pg_control.h:179
CheckPoint checkPointCopy
Definition: pg_control.h:131
pg_time_t time
Definition: pg_control.h:51
bool backupEndRequired
Definition: pg_control.h:170
void update_controlfile(const char *DataDir, ControlFileData *ControlFile, bool do_sync)
XLogRecPtr backupEndPoint
Definition: pg_control.h:169
static int WalSegSz
Definition: pg_resetwal.c:76
#define XLogSegNoOffsetToRecPtr(segno, offset, wal_segsz_bytes, dest)
bool track_commit_timestamp
Definition: pg_control.h:183
static ControlFileData ControlFile
Definition: pg_resetwal.c:63
static XLogSegNo newXlogSegNo
Definition: pg_resetwal.c:64
XLogRecPtr backupStartPoint
Definition: pg_control.h:168
XLogRecPtr checkPoint
Definition: pg_control.h:129
XLogRecPtr redo
Definition: pg_control.h:37
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:166
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:72

◆ usage()

static void usage ( void  )
static

Definition at line 1210 of file pg_resetwal.c.

References _, printf, and progname.

Referenced by main().

1211 {
1212  printf(_("%s resets the PostgreSQL write-ahead log.\n\n"), progname);
1213  printf(_("Usage:\n %s [OPTION]... DATADIR\n\n"), progname);
1214  printf(_("Options:\n"));
1215  printf(_(" -c, --commit-timestamp-ids=XID,XID\n"
1216  " set oldest and newest transactions bearing\n"
1217  " commit timestamp (zero means no change)\n"));
1218  printf(_(" [-D, --pgdata=]DATADIR data directory\n"));
1219  printf(_(" -e, --epoch=XIDEPOCH set next transaction ID epoch\n"));
1220  printf(_(" -f, --force force update to be done\n"));
1221  printf(_(" -l, --next-wal-file=WALFILE set minimum starting location for new WAL\n"));
1222  printf(_(" -m, --multixact-ids=MXID,MXID set next and oldest multitransaction ID\n"));
1223  printf(_(" -n, --dry-run no update, just show what would be done\n"));
1224  printf(_(" -o, --next-oid=OID set next OID\n"));
1225  printf(_(" -O, --multixact-offset=OFFSET set next multitransaction offset\n"));
1226  printf(_(" -V, --version output version information, then exit\n"));
1227  printf(_(" -x, --next-transaction-id=XID set next transaction ID\n"));
1228  printf(_(" --wal-segsize=SIZE size of WAL segments, in megabytes\n"));
1229  printf(_(" -?, --help show this help, then exit\n"));
1230  printf(_("\nReport bugs to <pgsql-bugs@lists.postgresql.org>.\n"));
1231 }
#define printf(...)
Definition: port.h:198
static const char * progname
Definition: pg_resetwal.c:66
#define _(x)
Definition: elog.c:84

◆ WriteEmptyXLOG()

static void WriteEmptyXLOG ( void  )
static

Definition at line 1115 of file pg_resetwal.c.

References ControlFileData::checkPointCopy, close, COMP_CRC32C, PGAlignedXLogBlock::data, fd(), FIN_CRC32C, fsync, INIT_CRC32C, InvalidTransactionId, MAXPGPATH, newXlogSegNo, offsetof, PG_BINARY, pg_file_create_mode, pg_log_error, CheckPoint::redo, SizeOfXLogLongPHD, SizeOfXLogRecord, SizeOfXLogRecordDataHeaderShort, 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().

1116 {
1117  PGAlignedXLogBlock buffer;
1118  XLogPageHeader page;
1119  XLogLongPageHeader longpage;
1120  XLogRecord *record;
1121  pg_crc32c crc;
1122  char path[MAXPGPATH];
1123  int fd;
1124  int nbytes;
1125  char *recptr;
1126 
1127  memset(buffer.data, 0, XLOG_BLCKSZ);
1128 
1129  /* Set up the XLOG page header */
1130  page = (XLogPageHeader) buffer.data;
1131  page->xlp_magic = XLOG_PAGE_MAGIC;
1132  page->xlp_info = XLP_LONG_HEADER;
1135  longpage = (XLogLongPageHeader) page;
1137  longpage->xlp_seg_size = WalSegSz;
1138  longpage->xlp_xlog_blcksz = XLOG_BLCKSZ;
1139 
1140  /* Insert the initial checkpoint record */
1141  recptr = (char *) page + SizeOfXLogLongPHD;
1142  record = (XLogRecord *) recptr;
1143  record->xl_prev = 0;
1144  record->xl_xid = InvalidTransactionId;
1147  record->xl_rmid = RM_XLOG_ID;
1148 
1149  recptr += SizeOfXLogRecord;
1150  *(recptr++) = (char) XLR_BLOCK_ID_DATA_SHORT;
1151  *(recptr++) = sizeof(CheckPoint);
1152  memcpy(recptr, &ControlFile.checkPointCopy,
1153  sizeof(CheckPoint));
1154 
1155  INIT_CRC32C(crc);
1156  COMP_CRC32C(crc, ((char *) record) + SizeOfXLogRecord, record->xl_tot_len - SizeOfXLogRecord);
1157  COMP_CRC32C(crc, (char *) record, offsetof(XLogRecord, xl_crc));
1158  FIN_CRC32C(crc);
1159  record->xl_crc = crc;
1160 
1161  /* Write the first page */
1164 
1165  unlink(path);
1166 
1167  fd = open(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
1169  if (fd < 0)
1170  {
1171  pg_log_error("could not open file \"%s\": %m", path);
1172  exit(1);
1173  }
1174 
1175  errno = 0;
1176  if (write(fd, buffer.data, XLOG_BLCKSZ) != XLOG_BLCKSZ)
1177  {
1178  /* if write didn't set errno, assume problem is no disk space */
1179  if (errno == 0)
1180  errno = ENOSPC;
1181  pg_log_error("could not write file \"%s\": %m", path);
1182  exit(1);
1183  }
1184 
1185  /* Fill the rest of the file with zeroes */
1186  memset(buffer.data, 0, XLOG_BLCKSZ);
1187  for (nbytes = XLOG_BLCKSZ; nbytes < WalSegSz; nbytes += XLOG_BLCKSZ)
1188  {
1189  errno = 0;
1190  if (write(fd, buffer.data, XLOG_BLCKSZ) != XLOG_BLCKSZ)
1191  {
1192  if (errno == 0)
1193  errno = ENOSPC;
1194  pg_log_error("could not write file \"%s\": %m", path);
1195  exit(1);
1196  }
1197  }
1198 
1199  if (fsync(fd) != 0)
1200  {
1201  pg_log_error("fsync error: %m");
1202  exit(1);
1203  }
1204 
1205  close(fd);
1206 }
#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
#define write(a, b, c)
Definition: win32.h:14
#define SizeOfXLogRecordDataHeaderShort
Definition: xlogrecord.h:200
#define pg_log_error(...)
Definition: logging.h:79
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:1191
#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
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:76
#define XLP_LONG_HEADER
Definition: xlog_internal.h:79
static ControlFileData ControlFile
Definition: pg_resetwal.c:63
uint8 xl_info
Definition: xlogrecord.h:46
struct CheckPoint CheckPoint
#define XLR_BLOCK_ID_DATA_SHORT
Definition: xlogrecord.h:223
#define XLogFilePath(path, tli, logSegNo, wal_segsz_bytes)
TransactionId xl_xid
Definition: xlogrecord.h:44
static XLogSegNo newXlogSegNo
Definition: pg_resetwal.c:64
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
#define close(a)
Definition: win32.h:12
#define COMP_CRC32C(crc, data, len)
Definition: pg_crc32c.h:89
char data[XLOG_BLCKSZ]
Definition: c.h:1068
#define FIN_CRC32C(crc)
Definition: pg_crc32c.h:94
XLogRecPtr redo
Definition: pg_control.h:37
#define offsetof(type, field)
Definition: c.h:655
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:72

Variable Documentation

◆ ControlFile

ControlFileData ControlFile
static

Definition at line 63 of file pg_resetwal.c.

◆ guessed

bool guessed = false
static

Definition at line 65 of file pg_resetwal.c.

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

◆ minXlogSegNo

XLogSegNo minXlogSegNo = 0
static

Definition at line 75 of file pg_resetwal.c.

Referenced by main().

◆ minXlogTli

uint32 minXlogTli = 0
static

Definition at line 74 of file pg_resetwal.c.

Referenced by main().

◆ newXlogSegNo

XLogSegNo newXlogSegNo
static

◆ progname

const char* progname
static

Definition at line 66 of file pg_resetwal.c.

Referenced by main(), and usage().

◆ set_mxid

MultiXactId set_mxid = 0
static

Definition at line 72 of file pg_resetwal.c.

Referenced by main(), and PrintNewControlValues().

◆ set_mxoff

MultiXactOffset set_mxoff = (MultiXactOffset) -1
static

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

Referenced by main(), and PrintNewControlValues().

◆ set_oid

Oid set_oid = 0
static

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

Referenced by main(), and PrintNewControlValues().

◆ set_wal_segsize

int set_wal_segsize
static

Definition at line 77 of file pg_resetwal.c.

Referenced by main(), and PrintNewControlValues().

◆ set_xid

TransactionId set_xid = 0
static

Definition at line 68 of file pg_resetwal.c.

Referenced by main(), and PrintNewControlValues().

◆ set_xid_epoch

uint32 set_xid_epoch = (uint32) -1
static

Definition at line 67 of file pg_resetwal.c.

Referenced by main(), and PrintNewControlValues().

◆ WalSegSz

int WalSegSz
static