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/heaptoast.h"
#include "access/multixact.h"
#include "access/transam.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 "getopt_long.h"
#include "pg_getopt.h"
#include "storage/large_object.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 read_controlfile (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_oldest_xid = 0
 
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 553 of file pg_resetwal.c.

References pg_log_error, pg_log_info, and pg_strip_crlf().

Referenced by main().

554 {
555  const char *ver_file = "PG_VERSION";
556  FILE *ver_fd;
557  char rawline[64];
558 
559  if ((ver_fd = fopen(ver_file, "r")) == NULL)
560  {
561  pg_log_error("could not open file \"%s\" for reading: %m",
562  ver_file);
563  exit(1);
564  }
565 
566  /* version number has to be the first line read */
567  if (!fgets(rawline, sizeof(rawline), ver_fd))
568  {
569  if (!ferror(ver_fd))
570  pg_log_error("unexpected empty file \"%s\"", ver_file);
571  else
572  pg_log_error("could not read file \"%s\": %m", ver_file);
573  exit(1);
574  }
575 
576  /* strip trailing newline and carriage return */
577  (void) pg_strip_crlf(rawline);
578 
579  if (strcmp(rawline, PG_MAJORVERSION) != 0)
580  {
581  pg_log_error("data directory is of wrong version");
582  pg_log_info("File \"%s\" contains \"%s\", which is not compatible with this program's version \"%s\".",
583  ver_file, rawline, PG_MAJORVERSION);
584  exit(1);
585  }
586 
587  fclose(ver_fd);
588 }
int pg_strip_crlf(char *str)
Definition: string.c:121
#define pg_log_error(...)
Definition: logging.h:80
#define pg_log_info(...)
Definition: logging.h:88

◆ FindEndOfXLOG()

static void FindEndOfXLOG ( void  )
static

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

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

◆ GuessControlValues()

static void GuessControlValues ( void  )
static

Definition at line 675 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, FirstGenbkiObjectId, FirstMultiXactId, FirstNormalTransactionId, FirstNormalUnloggedLSN, ControlFileData::float8ByVal, FLOAT8PASSBYVAL, 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::nextMulti, CheckPoint::nextMultiOffset, CheckPoint::nextOid, CheckPoint::nextXid, 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().

676 {
677  uint64 sysidentifier;
678  struct timeval tv;
679 
680  /*
681  * Set up a completely default set of pg_control values.
682  */
683  guessed = true;
684  memset(&ControlFile, 0, sizeof(ControlFile));
685 
688 
689  /*
690  * Create a new unique installation identifier, since we can no longer use
691  * any old XLOG records. See notes in xlog.c about the algorithm.
692  */
693  gettimeofday(&tv, NULL);
694  sysidentifier = ((uint64) tv.tv_sec) << 32;
695  sysidentifier |= ((uint64) tv.tv_usec) << 12;
696  sysidentifier |= getpid() & 0xFFF;
697 
698  ControlFile.system_identifier = sysidentifier;
699 
713  ControlFile.checkPointCopy.time = (pg_time_t) time(NULL);
715 
717  ControlFile.time = (pg_time_t) time(NULL);
720 
721  /* minRecoveryPoint, backupStartPoint and backupEndPoint can be left zero */
722 
724  ControlFile.wal_log_hints = false;
731 
732  ControlFile.maxAlign = MAXIMUM_ALIGNOF;
734  ControlFile.blcksz = BLCKSZ;
735  ControlFile.relseg_size = RELSEG_SIZE;
736  ControlFile.xlog_blcksz = XLOG_BLCKSZ;
743 
744  /*
745  * XXX eventually, should try to grovel through old XLOG to develop more
746  * accurate values for TimeLineID, nextXID, etc.
747  */
748 }
#define LOBLKSIZE
Definition: large_object.h:70
int max_locks_per_xact
Definition: pg_control.h:184
int gettimeofday(struct timeval *tp, struct timezone *tzp)
Definition: gettimeofday.c:104
int max_prepared_xacts
Definition: pg_control.h:183
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:130
int max_worker_processes
Definition: pg_control.h:181
TransactionId oldestActiveXid
Definition: pg_control.h:63
uint32 nameDataLen
Definition: pg_control.h:213
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:123
CheckPoint checkPointCopy
Definition: pg_control.h:133
uint32 xlog_blcksz
Definition: pg_control.h:210
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:211
#define FirstNormalTransactionId
Definition: transam.h:34
uint64 system_identifier
Definition: pg_control.h:108
XLogRecPtr unloggedLSN
Definition: pg_control.h:135
#define InvalidTransactionId
Definition: transam.h:31
#define FirstMultiXactId
Definition: multixact.h:25
uint32 loblksize
Definition: pg_control.h:217
uint32 indexMaxKeys
Definition: pg_control.h:214
static bool guessed
Definition: pg_resetwal.c:64
#define FirstNormalUnloggedLSN
Definition: xlogdefs.h:36
Oid oldestMultiDB
Definition: pg_control.h:50
uint32 toast_max_chunk_size
Definition: pg_control.h:216
#define InvalidOid
Definition: postgres_ext.h:36
Oid nextOid
Definition: pg_control.h:44
bool fullPageWrites
Definition: pg_control.h:42
#define FLOAT8PASSBYVAL
Definition: c.h:570
bool track_commit_timestamp
Definition: pg_control.h:185
Oid oldestXidDB
Definition: pg_control.h:48
static ControlFileData ControlFile
Definition: pg_resetwal.c:62
double floatFormat
Definition: pg_control.h:200
#define INDEX_MAX_KEYS
MultiXactId nextMulti
Definition: pg_control.h:45
static FullTransactionId FullTransactionIdFromEpochAndXid(uint32 epoch, TransactionId xid)
Definition: transam.h:71
uint32 catalog_version_no
Definition: pg_control.h:124
#define FirstGenbkiObjectId
Definition: transam.h:195
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
#define FLOATFORMAT_VALUE
Definition: pg_control.h:201
uint32 relseg_size
Definition: pg_control.h:208
XLogRecPtr checkPoint
Definition: pg_control.h:131
XLogRecPtr redo
Definition: pg_control.h:37
FullTransactionId nextXid
Definition: pg_control.h:43
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:69

◆ KillExistingArchiveStatus()

static void KillExistingArchiveStatus ( void  )
static

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

1078 {
1079 #define ARCHSTATDIR XLOGDIR "/archive_status"
1080 
1081  DIR *xldir;
1082  struct dirent *xlde;
1083  char path[MAXPGPATH + sizeof(ARCHSTATDIR)];
1084 
1085  xldir = opendir(ARCHSTATDIR);
1086  if (xldir == NULL)
1087  {
1088  pg_log_error("could not open directory \"%s\": %m", ARCHSTATDIR);
1089  exit(1);
1090  }
1091 
1092  while (errno = 0, (xlde = readdir(xldir)) != NULL)
1093  {
1094  if (strspn(xlde->d_name, "0123456789ABCDEF") == XLOG_FNAME_LEN &&
1095  (strcmp(xlde->d_name + XLOG_FNAME_LEN, ".ready") == 0 ||
1096  strcmp(xlde->d_name + XLOG_FNAME_LEN, ".done") == 0 ||
1097  strcmp(xlde->d_name + XLOG_FNAME_LEN, ".partial.ready") == 0 ||
1098  strcmp(xlde->d_name + XLOG_FNAME_LEN, ".partial.done") == 0))
1099  {
1100  snprintf(path, sizeof(path), "%s/%s", ARCHSTATDIR, xlde->d_name);
1101  if (unlink(path) < 0)
1102  {
1103  pg_log_error("could not delete file \"%s\": %m", path);
1104  exit(1);
1105  }
1106  }
1107  }
1108 
1109  if (errno)
1110  {
1111  pg_log_error("could not read directory \"%s\": %m", ARCHSTATDIR);
1112  exit(1);
1113  }
1114 
1115  if (closedir(xldir))
1116  {
1117  pg_log_error("could not close directory \"%s\": %m", ARCHSTATDIR);
1118  exit(1);
1119  }
1120 }
#define pg_log_error(...)
Definition: logging.h:80
int closedir(DIR *)
Definition: dirent.c:123
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:78
#define ARCHSTATDIR
#define XLOG_FNAME_LEN
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:217

◆ KillExistingXLOG()

static void KillExistingXLOG ( void  )
static

Definition at line 1032 of file pg_resetwal.c.

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

Referenced by main().

1033 {
1034  DIR *xldir;
1035  struct dirent *xlde;
1036  char path[MAXPGPATH + sizeof(XLOGDIR)];
1037 
1038  xldir = opendir(XLOGDIR);
1039  if (xldir == NULL)
1040  {
1041  pg_log_error("could not open directory \"%s\": %m", XLOGDIR);
1042  exit(1);
1043  }
1044 
1045  while (errno = 0, (xlde = readdir(xldir)) != NULL)
1046  {
1047  if (IsXLogFileName(xlde->d_name) ||
1049  {
1050  snprintf(path, sizeof(path), "%s/%s", XLOGDIR, xlde->d_name);
1051  if (unlink(path) < 0)
1052  {
1053  pg_log_error("could not delete file \"%s\": %m", path);
1054  exit(1);
1055  }
1056  }
1057  }
1058 
1059  if (errno)
1060  {
1061  pg_log_error("could not read directory \"%s\": %m", XLOGDIR);
1062  exit(1);
1063  }
1064 
1065  if (closedir(xldir))
1066  {
1067  pg_log_error("could not close directory \"%s\": %m", XLOGDIR);
1068  exit(1);
1069  }
1070 }
#define pg_log_error(...)
Definition: logging.h:80
int closedir(DIR *)
Definition: dirent.c:123
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:78
#define IsPartialXLogFileName(fname)
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:217

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

◆ PrintControlValues()

static void PrintControlValues ( bool  guessed)
static

Definition at line 758 of file pg_resetwal.c.

References _, ControlFileData::blcksz, ControlFileData::catalog_version_no, ControlFileData::checkPointCopy, ControlFileData::data_checksum_version, EpochFromFullTransactionId, ControlFileData::float8ByVal, CheckPoint::fullPageWrites, ControlFileData::indexMaxKeys, ControlFileData::loblksize, ControlFileData::maxAlign, ControlFileData::nameDataLen, CheckPoint::newestCommitTsXid, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, CheckPoint::nextOid, CheckPoint::nextXid, 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().

759 {
760  if (guessed)
761  printf(_("Guessed pg_control values:\n\n"));
762  else
763  printf(_("Current pg_control values:\n\n"));
764 
765  printf(_("pg_control version number: %u\n"),
767  printf(_("Catalog version number: %u\n"),
769  printf(_("Database system identifier: %llu\n"),
770  (unsigned long long) ControlFile.system_identifier);
771  printf(_("Latest checkpoint's TimeLineID: %u\n"),
773  printf(_("Latest checkpoint's full_page_writes: %s\n"),
774  ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off"));
775  printf(_("Latest checkpoint's NextXID: %u:%u\n"),
778  printf(_("Latest checkpoint's NextOID: %u\n"),
780  printf(_("Latest checkpoint's NextMultiXactId: %u\n"),
782  printf(_("Latest checkpoint's NextMultiOffset: %u\n"),
784  printf(_("Latest checkpoint's oldestXID: %u\n"),
786  printf(_("Latest checkpoint's oldestXID's DB: %u\n"),
788  printf(_("Latest checkpoint's oldestActiveXID: %u\n"),
790  printf(_("Latest checkpoint's oldestMultiXid: %u\n"),
792  printf(_("Latest checkpoint's oldestMulti's DB: %u\n"),
794  printf(_("Latest checkpoint's oldestCommitTsXid:%u\n"),
796  printf(_("Latest checkpoint's newestCommitTsXid:%u\n"),
798  printf(_("Maximum data alignment: %u\n"),
800  /* we don't print floatFormat since can't say much useful about it */
801  printf(_("Database block size: %u\n"),
803  printf(_("Blocks per segment of large relation: %u\n"),
805  printf(_("WAL block size: %u\n"),
807  printf(_("Bytes per WAL segment: %u\n"),
809  printf(_("Maximum length of identifiers: %u\n"),
811  printf(_("Maximum columns in an index: %u\n"),
813  printf(_("Maximum size of a TOAST chunk: %u\n"),
815  printf(_("Size of a large-object chunk: %u\n"),
817  /* This is no longer configurable, but users may still expect to see it: */
818  printf(_("Date/time type storage: %s\n"),
819  _("64-bit integers"));
820  printf(_("Float8 argument passing: %s\n"),
821  (ControlFile.float8ByVal ? _("by value") : _("by reference")));
822  printf(_("Data page checksum version: %u\n"),
824 }
TransactionId oldestActiveXid
Definition: pg_control.h:63
uint32 nameDataLen
Definition: pg_control.h:213
MultiXactId oldestMulti
Definition: pg_control.h:49
uint32 pg_control_version
Definition: pg_control.h:123
#define printf(...)
Definition: port.h:223
CheckPoint checkPointCopy
Definition: pg_control.h:133
uint32 xlog_blcksz
Definition: pg_control.h:210
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:211
uint64 system_identifier
Definition: pg_control.h:108
uint32 data_checksum_version
Definition: pg_control.h:222
uint32 loblksize
Definition: pg_control.h:217
uint32 indexMaxKeys
Definition: pg_control.h:214
static bool guessed
Definition: pg_resetwal.c:64
TransactionId newestCommitTsXid
Definition: pg_control.h:54
Oid oldestMultiDB
Definition: pg_control.h:50
uint32 toast_max_chunk_size
Definition: pg_control.h:216
#define EpochFromFullTransactionId(x)
Definition: transam.h:47
Oid nextOid
Definition: pg_control.h:44
bool fullPageWrites
Definition: pg_control.h:42
Oid oldestXidDB
Definition: pg_control.h:48
static ControlFileData ControlFile
Definition: pg_resetwal.c:62
MultiXactId nextMulti
Definition: pg_control.h:45
uint32 catalog_version_no
Definition: pg_control.h:124
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
#define _(x)
Definition: elog.c:89
uint32 relseg_size
Definition: pg_control.h:208
FullTransactionId nextXid
Definition: pg_control.h:43

◆ PrintNewControlValues()

static void PrintNewControlValues ( void  )
static

Definition at line 831 of file pg_resetwal.c.

References _, ControlFileData::checkPointCopy, EpochFromFullTransactionId, MAXFNAMELEN, CheckPoint::newestCommitTsXid, newXlogSegNo, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, CheckPoint::nextOid, CheckPoint::nextXid, 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().

832 {
833  char fname[MAXFNAMELEN];
834 
835  /* This will be always printed in order to keep format same. */
836  printf(_("\n\nValues to be changed:\n\n"));
837 
840  printf(_("First log segment after reset: %s\n"), fname);
841 
842  if (set_mxid != 0)
843  {
844  printf(_("NextMultiXactId: %u\n"),
846  printf(_("OldestMultiXid: %u\n"),
848  printf(_("OldestMulti's DB: %u\n"),
850  }
851 
852  if (set_mxoff != -1)
853  {
854  printf(_("NextMultiOffset: %u\n"),
856  }
857 
858  if (set_oid != 0)
859  {
860  printf(_("NextOID: %u\n"),
862  }
863 
864  if (set_xid != 0)
865  {
866  printf(_("NextXID: %u\n"),
868  printf(_("OldestXID: %u\n"),
870  printf(_("OldestXID's DB: %u\n"),
872  }
873 
874  if (set_xid_epoch != -1)
875  {
876  printf(_("NextXID epoch: %u\n"),
878  }
879 
880  if (set_oldest_commit_ts_xid != 0)
881  {
882  printf(_("oldestCommitTsXid: %u\n"),
884  }
885  if (set_newest_commit_ts_xid != 0)
886  {
887  printf(_("newestCommitTsXid: %u\n"),
889  }
890 
891  if (set_wal_segsize != 0)
892  {
893  printf(_("Bytes per WAL segment: %u\n"),
895  }
896 }
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:223
CheckPoint checkPointCopy
Definition: pg_control.h:133
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:211
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
Oid oldestXidDB
Definition: pg_control.h:48
static ControlFileData ControlFile
Definition: pg_resetwal.c:62
#define XLogFileName(fname, tli, logSegNo, wal_segsz_bytes)
MultiXactId nextMulti
Definition: pg_control.h:45
static MultiXactOffset set_mxoff
Definition: pg_resetwal.c:73
static XLogSegNo newXlogSegNo
Definition: pg_resetwal.c:63
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
#define _(x)
Definition: elog.c:89
FullTransactionId nextXid
Definition: pg_control.h:43
static uint32 set_xid_epoch
Definition: pg_resetwal.c:66

◆ read_controlfile()

static bool read_controlfile ( void  )
static

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

599 {
600  int fd;
601  int len;
602  char *buffer;
603  pg_crc32c crc;
604 
605  if ((fd = open(XLOG_CONTROL_FILE, O_RDONLY | PG_BINARY, 0)) < 0)
606  {
607  /*
608  * If pg_control is not there at all, or we can't read it, the odds
609  * are we've been handed a bad DataDir path, so give up. User can do
610  * "touch pg_control" to force us to proceed.
611  */
612  pg_log_error("could not open file \"%s\" for reading: %m",
614  if (errno == ENOENT)
615  pg_log_info("If you are sure the data directory path is correct, execute\n"
616  " touch %s\n"
617  "and try again.",
619  exit(1);
620  }
621 
622  /* Use malloc to ensure we have a maxaligned buffer */
623  buffer = (char *) pg_malloc(PG_CONTROL_FILE_SIZE);
624 
625  len = read(fd, buffer, PG_CONTROL_FILE_SIZE);
626  if (len < 0)
627  {
628  pg_log_error("could not read file \"%s\": %m", XLOG_CONTROL_FILE);
629  exit(1);
630  }
631  close(fd);
632 
633  if (len >= sizeof(ControlFileData) &&
634  ((ControlFileData *) buffer)->pg_control_version == PG_CONTROL_VERSION)
635  {
636  /* Check the CRC. */
637  INIT_CRC32C(crc);
638  COMP_CRC32C(crc,
639  buffer,
640  offsetof(ControlFileData, crc));
641  FIN_CRC32C(crc);
642 
643  if (!EQ_CRC32C(crc, ((ControlFileData *) buffer)->crc))
644  {
645  /* We will use the data but treat it as guessed. */
646  pg_log_warning("pg_control exists but has invalid CRC; proceed with caution");
647  guessed = true;
648  }
649 
650  memcpy(&ControlFile, buffer, sizeof(ControlFile));
651 
652  /* return false if WAL segment size is not valid */
654  {
655  pg_log_warning(ngettext("pg_control specifies invalid WAL segment size (%d byte); proceed with caution",
656  "pg_control specifies invalid WAL segment size (%d bytes); proceed with caution",
659  return false;
660  }
661 
662  return true;
663  }
664 
665  /* Looks like it's a mess. */
666  pg_log_warning("pg_control exists but is broken or wrong version; ignoring it");
667  return false;
668 }
#define INIT_CRC32C(crc)
Definition: pg_crc32c.h:41
#define IsValidWalSegSize(size)
Definition: xlog_internal.h:96
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
#define pg_log_error(...)
Definition: logging.h:80
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:1271
uint32 xlog_seg_size
Definition: pg_control.h:211
#define EQ_CRC32C(c1, c2)
Definition: pg_crc32c.h:42
static bool guessed
Definition: pg_resetwal.c:64
#define ngettext(s, p, n)
Definition: c.h:1182
#define XLOG_CONTROL_FILE
static ControlFileData ControlFile
Definition: pg_resetwal.c:62
#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:727
#define pg_log_info(...)
Definition: logging.h:88

◆ RewriteControlFile()

static void RewriteControlFile ( void  )
static

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

904 {
905  /*
906  * Adjust fields as needed to force an empty XLOG starting at
907  * newXlogSegNo.
908  */
911  ControlFile.checkPointCopy.time = (pg_time_t) time(NULL);
912 
914  ControlFile.time = (pg_time_t) time(NULL);
921 
922  /*
923  * Force the defaults for max_* settings. The values don't really matter
924  * as long as wal_level='minimal'; the postmaster will reset these fields
925  * anyway at startup.
926  */
928  ControlFile.wal_log_hints = false;
935 
936  /* The control file gets flushed here. */
937  update_controlfile(".", &ControlFile, true);
938 }
int max_locks_per_xact
Definition: pg_control.h:184
int max_prepared_xacts
Definition: pg_control.h:183
int64 pg_time_t
Definition: pgtime.h:23
pg_time_t time
Definition: pg_control.h:130
TimeLineID minRecoveryPointTLI
Definition: pg_control.h:169
int max_worker_processes
Definition: pg_control.h:181
CheckPoint checkPointCopy
Definition: pg_control.h:133
pg_time_t time
Definition: pg_control.h:51
bool backupEndRequired
Definition: pg_control.h:172
void update_controlfile(const char *DataDir, ControlFileData *ControlFile, bool do_sync)
XLogRecPtr backupEndPoint
Definition: pg_control.h:171
static int WalSegSz
Definition: pg_resetwal.c:76
#define XLogSegNoOffsetToRecPtr(segno, offset, wal_segsz_bytes, dest)
bool track_commit_timestamp
Definition: pg_control.h:185
static ControlFileData ControlFile
Definition: pg_resetwal.c:62
static XLogSegNo newXlogSegNo
Definition: pg_resetwal.c:63
XLogRecPtr backupStartPoint
Definition: pg_control.h:170
XLogRecPtr checkPoint
Definition: pg_control.h:131
XLogRecPtr redo
Definition: pg_control.h:37
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:168
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:69

◆ usage()

static void usage ( void  )
static

Definition at line 1223 of file pg_resetwal.c.

References _, printf, and progname.

Referenced by main().

1224 {
1225  printf(_("%s resets the PostgreSQL write-ahead log.\n\n"), progname);
1226  printf(_("Usage:\n %s [OPTION]... DATADIR\n\n"), progname);
1227  printf(_("Options:\n"));
1228  printf(_(" -c, --commit-timestamp-ids=XID,XID\n"
1229  " set oldest and newest transactions bearing\n"
1230  " commit timestamp (zero means no change)\n"));
1231  printf(_(" [-D, --pgdata=]DATADIR data directory\n"));
1232  printf(_(" -e, --epoch=XIDEPOCH set next transaction ID epoch\n"));
1233  printf(_(" -f, --force force update to be done\n"));
1234  printf(_(" -l, --next-wal-file=WALFILE set minimum starting location for new WAL\n"));
1235  printf(_(" -m, --multixact-ids=MXID,MXID set next and oldest multitransaction ID\n"));
1236  printf(_(" -n, --dry-run no update, just show what would be done\n"));
1237  printf(_(" -o, --next-oid=OID set next OID\n"));
1238  printf(_(" -O, --multixact-offset=OFFSET set next multitransaction offset\n"));
1239  printf(_(" -u, --oldest-transaction-id=XID set oldest transaction ID\n"));
1240  printf(_(" -V, --version output version information, then exit\n"));
1241  printf(_(" -x, --next-transaction-id=XID set next transaction ID\n"));
1242  printf(_(" --wal-segsize=SIZE size of WAL segments, in megabytes\n"));
1243  printf(_(" -?, --help show this help, then exit\n"));
1244  printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
1245  printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
1246 }
#define printf(...)
Definition: port.h:223
static const char * progname
Definition: pg_resetwal.c:65
#define _(x)
Definition: elog.c:89

◆ WriteEmptyXLOG()

static void WriteEmptyXLOG ( void  )
static

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

1129 {
1130  PGAlignedXLogBlock buffer;
1131  XLogPageHeader page;
1132  XLogLongPageHeader longpage;
1133  XLogRecord *record;
1134  pg_crc32c crc;
1135  char path[MAXPGPATH];
1136  int fd;
1137  int nbytes;
1138  char *recptr;
1139 
1140  memset(buffer.data, 0, XLOG_BLCKSZ);
1141 
1142  /* Set up the XLOG page header */
1143  page = (XLogPageHeader) buffer.data;
1144  page->xlp_magic = XLOG_PAGE_MAGIC;
1145  page->xlp_info = XLP_LONG_HEADER;
1148  longpage = (XLogLongPageHeader) page;
1150  longpage->xlp_seg_size = WalSegSz;
1151  longpage->xlp_xlog_blcksz = XLOG_BLCKSZ;
1152 
1153  /* Insert the initial checkpoint record */
1154  recptr = (char *) page + SizeOfXLogLongPHD;
1155  record = (XLogRecord *) recptr;
1156  record->xl_prev = 0;
1157  record->xl_xid = InvalidTransactionId;
1160  record->xl_rmid = RM_XLOG_ID;
1161 
1162  recptr += SizeOfXLogRecord;
1163  *(recptr++) = (char) XLR_BLOCK_ID_DATA_SHORT;
1164  *(recptr++) = sizeof(CheckPoint);
1165  memcpy(recptr, &ControlFile.checkPointCopy,
1166  sizeof(CheckPoint));
1167 
1168  INIT_CRC32C(crc);
1169  COMP_CRC32C(crc, ((char *) record) + SizeOfXLogRecord, record->xl_tot_len - SizeOfXLogRecord);
1170  COMP_CRC32C(crc, (char *) record, offsetof(XLogRecord, xl_crc));
1171  FIN_CRC32C(crc);
1172  record->xl_crc = crc;
1173 
1174  /* Write the first page */
1177 
1178  unlink(path);
1179 
1180  fd = open(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
1182  if (fd < 0)
1183  {
1184  pg_log_error("could not open file \"%s\": %m", path);
1185  exit(1);
1186  }
1187 
1188  errno = 0;
1189  if (write(fd, buffer.data, XLOG_BLCKSZ) != XLOG_BLCKSZ)
1190  {
1191  /* if write didn't set errno, assume problem is no disk space */
1192  if (errno == 0)
1193  errno = ENOSPC;
1194  pg_log_error("could not write file \"%s\": %m", path);
1195  exit(1);
1196  }
1197 
1198  /* Fill the rest of the file with zeroes */
1199  memset(buffer.data, 0, XLOG_BLCKSZ);
1200  for (nbytes = XLOG_BLCKSZ; nbytes < WalSegSz; nbytes += XLOG_BLCKSZ)
1201  {
1202  errno = 0;
1203  if (write(fd, buffer.data, XLOG_BLCKSZ) != XLOG_BLCKSZ)
1204  {
1205  if (errno == 0)
1206  errno = ENOSPC;
1207  pg_log_error("could not write file \"%s\": %m", path);
1208  exit(1);
1209  }
1210  }
1211 
1212  if (fsync(fd) != 0)
1213  {
1214  pg_log_error("fsync error: %m");
1215  exit(1);
1216  }
1217 
1218  close(fd);
1219 }
#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:204
#define pg_log_error(...)
Definition: logging.h:80
uint32 pg_crc32c
Definition: pg_crc32c.h:38
RmgrId xl_rmid
Definition: xlogrecord.h:47
XLogPageHeaderData * XLogPageHeader
Definition: xlog_internal.h:54
CheckPoint checkPointCopy
Definition: pg_control.h:133
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1271
#define fsync(fd)
Definition: win32_port.h:76
uint64 system_identifier
Definition: pg_control.h:108
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:76
static ControlFileData ControlFile
Definition: pg_resetwal.c:62
uint8 xl_info
Definition: xlogrecord.h:46
struct CheckPoint CheckPoint
#define XLR_BLOCK_ID_DATA_SHORT
Definition: xlogrecord.h:228
#define XLogFilePath(path, tli, logSegNo, wal_segsz_bytes)
TransactionId xl_xid
Definition: xlogrecord.h:44
static XLogSegNo newXlogSegNo
Definition: pg_resetwal.c:63
TimeLineID ThisTimeLineID
Definition: pg_control.h: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:1149
#define FIN_CRC32C(crc)
Definition: pg_crc32c.h:94
XLogRecPtr redo
Definition: pg_control.h:37
#define offsetof(type, field)
Definition: c.h:727
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:69

Variable Documentation

◆ ControlFile

ControlFileData ControlFile
static

Definition at line 62 of file pg_resetwal.c.

◆ guessed

bool guessed = false
static

Definition at line 64 of file pg_resetwal.c.

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

◆ 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 65 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_oldest_xid

TransactionId set_oldest_xid = 0
static

Definition at line 67 of file pg_resetwal.c.

Referenced by main().

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

Referenced by main(), and PrintNewControlValues().

◆ WalSegSz

int WalSegSz
static