PostgreSQL Source Code  git master
pg_resetwal.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * pg_resetwal.c
4  * A utility to "zero out" the xlog when it's corrupt beyond recovery.
5  * Can also rebuild pg_control if needed.
6  *
7  * The theory of operation is fairly simple:
8  * 1. Read the existing pg_control (which will include the last
9  * checkpoint record). If it is an old format then update to
10  * current format.
11  * 2. If pg_control is corrupt, attempt to intuit reasonable values,
12  * by scanning the old xlog if necessary.
13  * 3. Modify pg_control to reflect a "shutdown" state with a checkpoint
14  * record at the start of xlog.
15  * 4. Flush the existing xlog files and write a new segment with
16  * just a checkpoint record in it. The new segment is positioned
17  * just past the end of the old xlog, so that existing LSNs in
18  * data pages will appear to be "in the past".
19  * This is all pretty straightforward except for the intuition part of
20  * step 2 ...
21  *
22  *
23  * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
24  * Portions Copyright (c) 1994, Regents of the University of California
25  *
26  * src/bin/pg_resetwal/pg_resetwal.c
27  *
28  *-------------------------------------------------------------------------
29  */
30 
31 /*
32  * We have to use postgres.h not postgres_fe.h here, because there's so much
33  * backend-only stuff in the XLOG include files we need. But we need a
34  * frontend-ish environment otherwise. Hence this ugly hack.
35  */
36 #define FRONTEND 1
37 
38 #include "postgres.h"
39 
40 #include <dirent.h>
41 #include <fcntl.h>
42 #include <sys/stat.h>
43 #include <sys/time.h>
44 #include <time.h>
45 #include <unistd.h>
46 
47 #include "access/transam.h"
48 #include "access/tuptoaster.h"
49 #include "access/multixact.h"
50 #include "access/xlog.h"
51 #include "access/xlog_internal.h"
52 #include "catalog/catversion.h"
53 #include "catalog/pg_control.h"
54 #include "common/fe_memutils.h"
55 #include "common/file_perm.h"
57 #include "storage/large_object.h"
58 #include "pg_getopt.h"
59 #include "getopt_long.h"
60 
61 
62 static ControlFileData ControlFile; /* pg_control values */
63 static XLogSegNo newXlogSegNo; /* new XLOG segment # */
64 static bool guessed = false; /* T if we had to guess at any values */
65 static const char *progname;
66 static uint32 set_xid_epoch = (uint32) -1;
70 static Oid set_oid = 0;
71 static MultiXactId set_mxid = 0;
73 static uint32 minXlogTli = 0;
75 static int WalSegSz;
76 static int set_wal_segsize;
77 
78 static void CheckDataVersion(void);
79 static bool ReadControlFile(void);
80 static void GuessControlValues(void);
81 static void PrintControlValues(bool guessed);
82 static void PrintNewControlValues(void);
83 static void RewriteControlFile(void);
84 static void FindEndOfXLOG(void);
85 static void KillExistingXLOG(void);
86 static void KillExistingArchiveStatus(void);
87 static void WriteEmptyXLOG(void);
88 static void usage(void);
89 
90 
91 int
92 main(int argc, char *argv[])
93 {
94  static struct option long_options[] = {
95  {"commit-timestamp-ids", required_argument, NULL, 'c'},
96  {"pgdata", required_argument, NULL, 'D'},
97  {"epoch", required_argument, NULL, 'e'},
98  {"force", no_argument, NULL, 'f'},
99  {"next-wal-file", required_argument, NULL, 'l'},
100  {"multixact-ids", required_argument, NULL, 'm'},
101  {"dry-run", no_argument, NULL, 'n'},
102  {"next-oid", required_argument, NULL, 'o'},
103  {"multixact-offset", required_argument, NULL, 'O'},
104  {"next-transaction-id", required_argument, NULL, 'x'},
105  {"wal-segsize", required_argument, NULL, 1},
106  {NULL, 0, NULL, 0}
107  };
108 
109  int c;
110  bool force = false;
111  bool noupdate = false;
112  MultiXactId set_oldestmxid = 0;
113  char *endptr;
114  char *endptr2;
115  char *DataDir = NULL;
116  char *log_fname = NULL;
117  int fd;
118 
119  set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_resetwal"));
120 
121  progname = get_progname(argv[0]);
122 
123  if (argc > 1)
124  {
125  if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
126  {
127  usage();
128  exit(0);
129  }
130  if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
131  {
132  puts("pg_resetwal (PostgreSQL) " PG_VERSION);
133  exit(0);
134  }
135  }
136 
137 
138  while ((c = getopt_long(argc, argv, "c:D:e:fl:m:no:O:x:", long_options, NULL)) != -1)
139  {
140  switch (c)
141  {
142  case 'D':
143  DataDir = optarg;
144  break;
145 
146  case 'f':
147  force = true;
148  break;
149 
150  case 'n':
151  noupdate = true;
152  break;
153 
154  case 'e':
155  set_xid_epoch = strtoul(optarg, &endptr, 0);
156  if (endptr == optarg || *endptr != '\0')
157  {
158  /*------
159  translator: the second %s is a command line argument (-e, etc) */
160  fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-e");
161  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
162  exit(1);
163  }
164  if (set_xid_epoch == -1)
165  {
166  fprintf(stderr, _("%s: transaction ID epoch (-e) must not be -1\n"), progname);
167  exit(1);
168  }
169  break;
170 
171  case 'x':
172  set_xid = strtoul(optarg, &endptr, 0);
173  if (endptr == optarg || *endptr != '\0')
174  {
175  fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-x");
176  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
177  exit(1);
178  }
179  if (set_xid == 0)
180  {
181  fprintf(stderr, _("%s: transaction ID (-x) must not be 0\n"), progname);
182  exit(1);
183  }
184  break;
185 
186  case 'c':
187  set_oldest_commit_ts_xid = strtoul(optarg, &endptr, 0);
188  if (endptr == optarg || *endptr != ',')
189  {
190  fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-c");
191  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
192  exit(1);
193  }
194  set_newest_commit_ts_xid = strtoul(endptr + 1, &endptr2, 0);
195  if (endptr2 == endptr + 1 || *endptr2 != '\0')
196  {
197  fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-c");
198  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
199  exit(1);
200  }
201 
202  if (set_oldest_commit_ts_xid < 2 &&
204  {
205  fprintf(stderr, _("%s: transaction ID (-c) must be either 0 or greater than or equal to 2\n"), progname);
206  exit(1);
207  }
208 
209  if (set_newest_commit_ts_xid < 2 &&
211  {
212  fprintf(stderr, _("%s: transaction ID (-c) must be either 0 or greater than or equal to 2\n"), progname);
213  exit(1);
214  }
215  break;
216 
217  case 'o':
218  set_oid = strtoul(optarg, &endptr, 0);
219  if (endptr == optarg || *endptr != '\0')
220  {
221  fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-o");
222  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
223  exit(1);
224  }
225  if (set_oid == 0)
226  {
227  fprintf(stderr, _("%s: OID (-o) must not be 0\n"), progname);
228  exit(1);
229  }
230  break;
231 
232  case 'm':
233  set_mxid = strtoul(optarg, &endptr, 0);
234  if (endptr == optarg || *endptr != ',')
235  {
236  fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-m");
237  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
238  exit(1);
239  }
240 
241  set_oldestmxid = strtoul(endptr + 1, &endptr2, 0);
242  if (endptr2 == endptr + 1 || *endptr2 != '\0')
243  {
244  fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-m");
245  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
246  exit(1);
247  }
248  if (set_mxid == 0)
249  {
250  fprintf(stderr, _("%s: multitransaction ID (-m) must not be 0\n"), progname);
251  exit(1);
252  }
253 
254  /*
255  * XXX It'd be nice to have more sanity checks here, e.g. so
256  * that oldest is not wrapped around w.r.t. nextMulti.
257  */
258  if (set_oldestmxid == 0)
259  {
260  fprintf(stderr, _("%s: oldest multitransaction ID (-m) must not be 0\n"),
261  progname);
262  exit(1);
263  }
264  break;
265 
266  case 'O':
267  set_mxoff = strtoul(optarg, &endptr, 0);
268  if (endptr == optarg || *endptr != '\0')
269  {
270  fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-O");
271  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
272  exit(1);
273  }
274  if (set_mxoff == -1)
275  {
276  fprintf(stderr, _("%s: multitransaction offset (-O) must not be -1\n"), progname);
277  exit(1);
278  }
279  break;
280 
281  case 'l':
282  if (strspn(optarg, "01234567890ABCDEFabcdef") != XLOG_FNAME_LEN)
283  {
284  fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-l");
285  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
286  exit(1);
287  }
288 
289  /*
290  * XLogFromFileName requires wal segment size which is not yet
291  * set. Hence wal details are set later on.
292  */
293  log_fname = pg_strdup(optarg);
294  break;
295 
296  case 1:
297  set_wal_segsize = strtol(optarg, &endptr, 10) * 1024 * 1024;
298  if (endptr == optarg || *endptr != '\0')
299  {
300  fprintf(stderr,
301  _("%s: argument of --wal-segsize must be a number\n"),
302  progname);
303  exit(1);
304  }
306  {
307  fprintf(stderr,
308  _("%s: argument of --wal-segsize must be a power of 2 between 1 and 1024\n"),
309  progname);
310  exit(1);
311  }
312  break;
313 
314  default:
315  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
316  exit(1);
317  }
318  }
319 
320  if (DataDir == NULL && optind < argc)
321  DataDir = argv[optind++];
322 
323  /* Complain if any arguments remain */
324  if (optind < argc)
325  {
326  fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
327  progname, argv[optind]);
328  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
329  progname);
330  exit(1);
331  }
332 
333  if (DataDir == NULL)
334  {
335  fprintf(stderr, _("%s: no data directory specified\n"), progname);
336  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
337  exit(1);
338  }
339 
340  /*
341  * Don't allow pg_resetwal to be run as root, to avoid overwriting the
342  * ownership of files in the data directory. We need only check for root
343  * -- any other user won't have sufficient permissions to modify files in
344  * the data directory.
345  */
346 #ifndef WIN32
347  if (geteuid() == 0)
348  {
349  fprintf(stderr, _("%s: cannot be executed by \"root\"\n"),
350  progname);
351  fprintf(stderr, _("You must run %s as the PostgreSQL superuser.\n"),
352  progname);
353  exit(1);
354  }
355 #endif
356 
358 
359  /* Set mask based on PGDATA permissions */
360  if (!GetDataDirectoryCreatePerm(DataDir))
361  {
362  fprintf(stderr, _("%s: could not read permissions of directory \"%s\": %s\n"),
363  progname, DataDir, strerror(errno));
364  exit(1);
365  }
366 
367  umask(pg_mode_mask);
368 
369  if (chdir(DataDir) < 0)
370  {
371  fprintf(stderr, _("%s: could not change directory to \"%s\": %s\n"),
372  progname, DataDir, strerror(errno));
373  exit(1);
374  }
375 
376  /* Check that data directory matches our server version */
378 
379  /*
380  * Check for a postmaster lock file --- if there is one, refuse to
381  * proceed, on grounds we might be interfering with a live installation.
382  */
383  if ((fd = open("postmaster.pid", O_RDONLY, 0)) < 0)
384  {
385  if (errno != ENOENT)
386  {
387  fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
388  progname, "postmaster.pid", strerror(errno));
389  exit(1);
390  }
391  }
392  else
393  {
394  fprintf(stderr, _("%s: lock file \"%s\" exists\n"
395  "Is a server running? If not, delete the lock file and try again.\n"),
396  progname, "postmaster.pid");
397  exit(1);
398  }
399 
400  /*
401  * Attempt to read the existing pg_control file
402  */
403  if (!ReadControlFile())
405 
406  /*
407  * If no new WAL segment size was specified, use the control file value.
408  */
409  if (set_wal_segsize != 0)
411  else
412  WalSegSz = ControlFile.xlog_seg_size;
413 
414  if (log_fname != NULL)
416 
417  /*
418  * Also look at existing segment files to set up newXlogSegNo
419  */
420  FindEndOfXLOG();
421 
422  /*
423  * If we're not going to proceed with the reset, print the current control
424  * file parameters.
425  */
426  if ((guessed && !force) || noupdate)
428 
429  /*
430  * Adjust fields if required by switches. (Do this now so that printout,
431  * if any, includes these values.)
432  */
433  if (set_xid_epoch != -1)
435 
436  if (set_xid != 0)
437  {
438  ControlFile.checkPointCopy.nextXid = set_xid;
439 
440  /*
441  * For the moment, just set oldestXid to a value that will force
442  * immediate autovacuum-for-wraparound. It's not clear whether adding
443  * user control of this is useful, so let's just do something that's
444  * reasonably safe. The magic constant here corresponds to the
445  * maximum allowed value of autovacuum_freeze_max_age.
446  */
447  ControlFile.checkPointCopy.oldestXid = set_xid - 2000000000;
450  ControlFile.checkPointCopy.oldestXidDB = InvalidOid;
451  }
452 
453  if (set_oldest_commit_ts_xid != 0)
455  if (set_newest_commit_ts_xid != 0)
457 
458  if (set_oid != 0)
459  ControlFile.checkPointCopy.nextOid = set_oid;
460 
461  if (set_mxid != 0)
462  {
463  ControlFile.checkPointCopy.nextMulti = set_mxid;
464 
465  ControlFile.checkPointCopy.oldestMulti = set_oldestmxid;
466  if (ControlFile.checkPointCopy.oldestMulti < FirstMultiXactId)
469  }
470 
471  if (set_mxoff != -1)
473 
474  if (minXlogTli > ControlFile.checkPointCopy.ThisTimeLineID)
475  {
478  }
479 
480  if (set_wal_segsize != 0)
481  ControlFile.xlog_seg_size = WalSegSz;
482 
485 
486  /*
487  * If we had to guess anything, and -f was not given, just print the
488  * guessed values and exit. Also print if -n is given.
489  */
490  if ((guessed && !force) || noupdate)
491  {
493  if (!noupdate)
494  {
495  printf(_("\nIf these values seem acceptable, use -f to force reset.\n"));
496  exit(1);
497  }
498  else
499  exit(0);
500  }
501 
502  /*
503  * Don't reset from a dirty pg_control without -f, either.
504  */
505  if (ControlFile.state != DB_SHUTDOWNED && !force)
506  {
507  printf(_("The database server was not shut down cleanly.\n"
508  "Resetting the write-ahead log might cause data to be lost.\n"
509  "If you want to proceed anyway, use -f to force reset.\n"));
510  exit(1);
511  }
512 
513  /*
514  * Else, do the dirty deed.
515  */
519  WriteEmptyXLOG();
520 
521  printf(_("Write-ahead log reset\n"));
522  return 0;
523 }
524 
525 
526 /*
527  * Look at the version string stored in PG_VERSION and decide if this utility
528  * can be run safely or not.
529  *
530  * We don't want to inject pg_control and WAL files that are for a different
531  * major version; that can't do anything good. Note that we don't treat
532  * mismatching version info in pg_control as a reason to bail out, because
533  * recovering from a corrupted pg_control is one of the main reasons for this
534  * program to exist at all. However, PG_VERSION is unlikely to get corrupted,
535  * and if it were it would be easy to fix by hand. So let's make this check
536  * to prevent simple user errors.
537  */
538 static void
540 {
541  const char *ver_file = "PG_VERSION";
542  FILE *ver_fd;
543  char rawline[64];
544  int len;
545 
546  if ((ver_fd = fopen(ver_file, "r")) == NULL)
547  {
548  fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
549  progname, ver_file, strerror(errno));
550  exit(1);
551  }
552 
553  /* version number has to be the first line read */
554  if (!fgets(rawline, sizeof(rawline), ver_fd))
555  {
556  if (!ferror(ver_fd))
557  {
558  fprintf(stderr, _("%s: unexpected empty file \"%s\"\n"),
559  progname, ver_file);
560  }
561  else
562  {
563  fprintf(stderr, _("%s: could not read file \"%s\": %s\n"),
564  progname, ver_file, strerror(errno));
565  }
566  exit(1);
567  }
568 
569  /* remove trailing newline, handling Windows newlines as well */
570  len = strlen(rawline);
571  if (len > 0 && rawline[len - 1] == '\n')
572  {
573  rawline[--len] = '\0';
574  if (len > 0 && rawline[len - 1] == '\r')
575  rawline[--len] = '\0';
576  }
577 
578  if (strcmp(rawline, PG_MAJORVERSION) != 0)
579  {
580  fprintf(stderr, _("%s: data directory is of wrong version\n"
581  "File \"%s\" contains \"%s\", which is not compatible with this program's version \"%s\".\n"),
582  progname, ver_file, rawline, PG_MAJORVERSION);
583  exit(1);
584  }
585 
586  fclose(ver_fd);
587 }
588 
589 
590 /*
591  * Try to read the existing pg_control file.
592  *
593  * This routine is also responsible for updating old pg_control versions
594  * to the current format. (Currently we don't do anything of the sort.)
595  */
596 static bool
598 {
599  int fd;
600  int len;
601  char *buffer;
602  pg_crc32c crc;
603 
604  if ((fd = open(XLOG_CONTROL_FILE, O_RDONLY | PG_BINARY, 0)) < 0)
605  {
606  /*
607  * If pg_control is not there at all, or we can't read it, the odds
608  * are we've been handed a bad DataDir path, so give up. User can do
609  * "touch pg_control" to force us to proceed.
610  */
611  fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
613  if (errno == ENOENT)
614  fprintf(stderr, _("If you are sure the data directory path is correct, execute\n"
615  " touch %s\n"
616  "and try again.\n"),
618  exit(1);
619  }
620 
621  /* Use malloc to ensure we have a maxaligned buffer */
622  buffer = (char *) pg_malloc(PG_CONTROL_FILE_SIZE);
623 
624  len = read(fd, buffer, PG_CONTROL_FILE_SIZE);
625  if (len < 0)
626  {
627  fprintf(stderr, _("%s: could not read file \"%s\": %s\n"),
629  exit(1);
630  }
631  close(fd);
632 
633  if (len >= sizeof(ControlFileData) &&
634  ((ControlFileData *) buffer)->pg_control_version == PG_CONTROL_VERSION)
635  {
636  /* Check the CRC. */
637  INIT_CRC32C(crc);
638  COMP_CRC32C(crc,
639  buffer,
640  offsetof(ControlFileData, crc));
641  FIN_CRC32C(crc);
642 
643  if (!EQ_CRC32C(crc, ((ControlFileData *) buffer)->crc))
644  {
645  /* We will use the data but treat it as guessed. */
646  fprintf(stderr,
647  _("%s: pg_control exists but has invalid CRC; proceed with caution\n"),
648  progname);
649  guessed = true;
650  }
651 
652  memcpy(&ControlFile, buffer, sizeof(ControlFile));
653 
654  /* return false if WAL segment size is not valid */
655  if (!IsValidWalSegSize(ControlFile.xlog_seg_size))
656  {
657  fprintf(stderr,
658  ngettext("%s: pg_control specifies invalid WAL segment size (%d byte); proceed with caution\n",
659  "%s: pg_control specifies invalid WAL segment size (%d bytes); proceed with caution\n",
660  ControlFile.xlog_seg_size),
661  progname, ControlFile.xlog_seg_size);
662  return false;
663  }
664 
665  return true;
666  }
667 
668  /* Looks like it's a mess. */
669  fprintf(stderr, _("%s: pg_control exists but is broken or wrong version; ignoring it\n"),
670  progname);
671  return false;
672 }
673 
674 
675 /*
676  * Guess at pg_control values when we can't read the old ones.
677  */
678 static void
680 {
681  uint64 sysidentifier;
682  struct timeval tv;
683 
684  /*
685  * Set up a completely default set of pg_control values.
686  */
687  guessed = true;
688  memset(&ControlFile, 0, sizeof(ControlFile));
689 
692 
693  /*
694  * Create a new unique installation identifier, since we can no longer use
695  * any old XLOG records. See notes in xlog.c about the algorithm.
696  */
697  gettimeofday(&tv, NULL);
698  sysidentifier = ((uint64) tv.tv_sec) << 32;
699  sysidentifier |= ((uint64) tv.tv_usec) << 12;
700  sysidentifier |= getpid() & 0xFFF;
701 
702  ControlFile.system_identifier = sysidentifier;
703 
704  ControlFile.checkPointCopy.redo = SizeOfXLogLongPHD;
705  ControlFile.checkPointCopy.ThisTimeLineID = 1;
706  ControlFile.checkPointCopy.PrevTimeLineID = 1;
707  ControlFile.checkPointCopy.fullPageWrites = false;
708  ControlFile.checkPointCopy.nextXidEpoch = 0;
712  ControlFile.checkPointCopy.nextMultiOffset = 0;
714  ControlFile.checkPointCopy.oldestXidDB = InvalidOid;
717  ControlFile.checkPointCopy.time = (pg_time_t) time(NULL);
719 
720  ControlFile.state = DB_SHUTDOWNED;
721  ControlFile.time = (pg_time_t) time(NULL);
722  ControlFile.checkPoint = ControlFile.checkPointCopy.redo;
723  ControlFile.unloggedLSN = 1;
724 
725  /* minRecoveryPoint, backupStartPoint and backupEndPoint can be left zero */
726 
727  ControlFile.wal_level = WAL_LEVEL_MINIMAL;
728  ControlFile.wal_log_hints = false;
729  ControlFile.track_commit_timestamp = false;
730  ControlFile.MaxConnections = 100;
731  ControlFile.max_worker_processes = 8;
732  ControlFile.max_prepared_xacts = 0;
733  ControlFile.max_locks_per_xact = 64;
734 
735  ControlFile.maxAlign = MAXIMUM_ALIGNOF;
736  ControlFile.floatFormat = FLOATFORMAT_VALUE;
737  ControlFile.blcksz = BLCKSZ;
738  ControlFile.relseg_size = RELSEG_SIZE;
739  ControlFile.xlog_blcksz = XLOG_BLCKSZ;
740  ControlFile.xlog_seg_size = DEFAULT_XLOG_SEG_SIZE;
741  ControlFile.nameDataLen = NAMEDATALEN;
742  ControlFile.indexMaxKeys = INDEX_MAX_KEYS;
744  ControlFile.loblksize = LOBLKSIZE;
745  ControlFile.float4ByVal = FLOAT4PASSBYVAL;
746  ControlFile.float8ByVal = FLOAT8PASSBYVAL;
747 
748  /*
749  * XXX eventually, should try to grovel through old XLOG to develop more
750  * accurate values for TimeLineID, nextXID, etc.
751  */
752 }
753 
754 
755 /*
756  * Print the guessed pg_control values when we had to guess.
757  *
758  * NB: this display should be just those fields that will not be
759  * reset by RewriteControlFile().
760  */
761 static void
763 {
764  char sysident_str[32];
765 
766  if (guessed)
767  printf(_("Guessed pg_control values:\n\n"));
768  else
769  printf(_("Current pg_control values:\n\n"));
770 
771  /*
772  * Format system_identifier separately to keep platform-dependent format
773  * code out of the translatable message string.
774  */
775  snprintf(sysident_str, sizeof(sysident_str), UINT64_FORMAT,
776  ControlFile.system_identifier);
777 
778  printf(_("pg_control version number: %u\n"),
779  ControlFile.pg_control_version);
780  printf(_("Catalog version number: %u\n"),
781  ControlFile.catalog_version_no);
782  printf(_("Database system identifier: %s\n"),
783  sysident_str);
784  printf(_("Latest checkpoint's TimeLineID: %u\n"),
785  ControlFile.checkPointCopy.ThisTimeLineID);
786  printf(_("Latest checkpoint's full_page_writes: %s\n"),
787  ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off"));
788  printf(_("Latest checkpoint's NextXID: %u:%u\n"),
789  ControlFile.checkPointCopy.nextXidEpoch,
790  ControlFile.checkPointCopy.nextXid);
791  printf(_("Latest checkpoint's NextOID: %u\n"),
792  ControlFile.checkPointCopy.nextOid);
793  printf(_("Latest checkpoint's NextMultiXactId: %u\n"),
794  ControlFile.checkPointCopy.nextMulti);
795  printf(_("Latest checkpoint's NextMultiOffset: %u\n"),
796  ControlFile.checkPointCopy.nextMultiOffset);
797  printf(_("Latest checkpoint's oldestXID: %u\n"),
798  ControlFile.checkPointCopy.oldestXid);
799  printf(_("Latest checkpoint's oldestXID's DB: %u\n"),
800  ControlFile.checkPointCopy.oldestXidDB);
801  printf(_("Latest checkpoint's oldestActiveXID: %u\n"),
802  ControlFile.checkPointCopy.oldestActiveXid);
803  printf(_("Latest checkpoint's oldestMultiXid: %u\n"),
804  ControlFile.checkPointCopy.oldestMulti);
805  printf(_("Latest checkpoint's oldestMulti's DB: %u\n"),
806  ControlFile.checkPointCopy.oldestMultiDB);
807  printf(_("Latest checkpoint's oldestCommitTsXid:%u\n"),
808  ControlFile.checkPointCopy.oldestCommitTsXid);
809  printf(_("Latest checkpoint's newestCommitTsXid:%u\n"),
810  ControlFile.checkPointCopy.newestCommitTsXid);
811  printf(_("Maximum data alignment: %u\n"),
812  ControlFile.maxAlign);
813  /* we don't print floatFormat since can't say much useful about it */
814  printf(_("Database block size: %u\n"),
815  ControlFile.blcksz);
816  printf(_("Blocks per segment of large relation: %u\n"),
817  ControlFile.relseg_size);
818  printf(_("WAL block size: %u\n"),
819  ControlFile.xlog_blcksz);
820  printf(_("Bytes per WAL segment: %u\n"),
821  ControlFile.xlog_seg_size);
822  printf(_("Maximum length of identifiers: %u\n"),
823  ControlFile.nameDataLen);
824  printf(_("Maximum columns in an index: %u\n"),
825  ControlFile.indexMaxKeys);
826  printf(_("Maximum size of a TOAST chunk: %u\n"),
827  ControlFile.toast_max_chunk_size);
828  printf(_("Size of a large-object chunk: %u\n"),
829  ControlFile.loblksize);
830  /* This is no longer configurable, but users may still expect to see it: */
831  printf(_("Date/time type storage: %s\n"),
832  _("64-bit integers"));
833  printf(_("Float4 argument passing: %s\n"),
834  (ControlFile.float4ByVal ? _("by value") : _("by reference")));
835  printf(_("Float8 argument passing: %s\n"),
836  (ControlFile.float8ByVal ? _("by value") : _("by reference")));
837  printf(_("Data page checksum version: %u\n"),
838  ControlFile.data_checksum_version);
839 }
840 
841 
842 /*
843  * Print the values to be changed.
844  */
845 static void
847 {
848  char fname[MAXFNAMELEN];
849 
850  /* This will be always printed in order to keep format same. */
851  printf(_("\n\nValues to be changed:\n\n"));
852 
853  XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
855  printf(_("First log segment after reset: %s\n"), fname);
856 
857  if (set_mxid != 0)
858  {
859  printf(_("NextMultiXactId: %u\n"),
860  ControlFile.checkPointCopy.nextMulti);
861  printf(_("OldestMultiXid: %u\n"),
862  ControlFile.checkPointCopy.oldestMulti);
863  printf(_("OldestMulti's DB: %u\n"),
864  ControlFile.checkPointCopy.oldestMultiDB);
865  }
866 
867  if (set_mxoff != -1)
868  {
869  printf(_("NextMultiOffset: %u\n"),
870  ControlFile.checkPointCopy.nextMultiOffset);
871  }
872 
873  if (set_oid != 0)
874  {
875  printf(_("NextOID: %u\n"),
876  ControlFile.checkPointCopy.nextOid);
877  }
878 
879  if (set_xid != 0)
880  {
881  printf(_("NextXID: %u\n"),
882  ControlFile.checkPointCopy.nextXid);
883  printf(_("OldestXID: %u\n"),
884  ControlFile.checkPointCopy.oldestXid);
885  printf(_("OldestXID's DB: %u\n"),
886  ControlFile.checkPointCopy.oldestXidDB);
887  }
888 
889  if (set_xid_epoch != -1)
890  {
891  printf(_("NextXID epoch: %u\n"),
892  ControlFile.checkPointCopy.nextXidEpoch);
893  }
894 
895  if (set_oldest_commit_ts_xid != 0)
896  {
897  printf(_("oldestCommitTsXid: %u\n"),
898  ControlFile.checkPointCopy.oldestCommitTsXid);
899  }
900  if (set_newest_commit_ts_xid != 0)
901  {
902  printf(_("newestCommitTsXid: %u\n"),
903  ControlFile.checkPointCopy.newestCommitTsXid);
904  }
905 
906  if (set_wal_segsize != 0)
907  {
908  printf(_("Bytes per WAL segment: %u\n"),
909  ControlFile.xlog_seg_size);
910  }
911 }
912 
913 
914 /*
915  * Write out the new pg_control file.
916  */
917 static void
919 {
920  int fd;
921  char buffer[PG_CONTROL_FILE_SIZE]; /* need not be aligned */
922 
923  /*
924  * For good luck, apply the same static assertions as in backend's
925  * WriteControlFile().
926  */
928  "pg_control is too large for atomic disk writes");
930  "sizeof(ControlFileData) exceeds PG_CONTROL_FILE_SIZE");
931 
932  /*
933  * Adjust fields as needed to force an empty XLOG starting at
934  * newXlogSegNo.
935  */
937  ControlFile.checkPointCopy.redo, WalSegSz);
938  ControlFile.checkPointCopy.time = (pg_time_t) time(NULL);
939 
940  ControlFile.state = DB_SHUTDOWNED;
941  ControlFile.time = (pg_time_t) time(NULL);
942  ControlFile.checkPoint = ControlFile.checkPointCopy.redo;
943  ControlFile.minRecoveryPoint = 0;
944  ControlFile.minRecoveryPointTLI = 0;
945  ControlFile.backupStartPoint = 0;
946  ControlFile.backupEndPoint = 0;
947  ControlFile.backupEndRequired = false;
948 
949  /*
950  * Force the defaults for max_* settings. The values don't really matter
951  * as long as wal_level='minimal'; the postmaster will reset these fields
952  * anyway at startup.
953  */
954  ControlFile.wal_level = WAL_LEVEL_MINIMAL;
955  ControlFile.wal_log_hints = false;
956  ControlFile.track_commit_timestamp = false;
957  ControlFile.MaxConnections = 100;
958  ControlFile.max_worker_processes = 8;
959  ControlFile.max_prepared_xacts = 0;
960  ControlFile.max_locks_per_xact = 64;
961 
962  /* Contents are protected with a CRC */
963  INIT_CRC32C(ControlFile.crc);
964  COMP_CRC32C(ControlFile.crc,
965  (char *) &ControlFile,
966  offsetof(ControlFileData, crc));
967  FIN_CRC32C(ControlFile.crc);
968 
969  /*
970  * We write out PG_CONTROL_FILE_SIZE bytes into pg_control, zero-padding
971  * the excess over sizeof(ControlFileData). This reduces the odds of
972  * premature-EOF errors when reading pg_control. We'll still fail when we
973  * check the contents of the file, but hopefully with a more specific
974  * error than "couldn't read pg_control".
975  */
976  memset(buffer, 0, PG_CONTROL_FILE_SIZE);
977  memcpy(buffer, &ControlFile, sizeof(ControlFileData));
978 
979  unlink(XLOG_CONTROL_FILE);
980 
981  fd = open(XLOG_CONTROL_FILE,
982  O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
984  if (fd < 0)
985  {
986  fprintf(stderr, _("%s: could not create pg_control file: %s\n"),
987  progname, strerror(errno));
988  exit(1);
989  }
990 
991  errno = 0;
992  if (write(fd, buffer, PG_CONTROL_FILE_SIZE) != PG_CONTROL_FILE_SIZE)
993  {
994  /* if write didn't set errno, assume problem is no disk space */
995  if (errno == 0)
996  errno = ENOSPC;
997  fprintf(stderr, _("%s: could not write pg_control file: %s\n"),
998  progname, strerror(errno));
999  exit(1);
1000  }
1001 
1002  if (fsync(fd) != 0)
1003  {
1004  fprintf(stderr, _("%s: fsync error: %s\n"), progname, strerror(errno));
1005  exit(1);
1006  }
1007 
1008  close(fd);
1009 }
1010 
1011 
1012 /*
1013  * Scan existing XLOG files and determine the highest existing WAL address
1014  *
1015  * On entry, ControlFile.checkPointCopy.redo and ControlFile.xlog_seg_size
1016  * are assumed valid (note that we allow the old xlog seg size to differ
1017  * from what we're using). On exit, newXlogId and newXlogSeg are set to
1018  * suitable values for the beginning of replacement WAL (in our seg size).
1019  */
1020 static void
1022 {
1023  DIR *xldir;
1024  struct dirent *xlde;
1025  uint64 segs_per_xlogid;
1026  uint64 xlogbytepos;
1027 
1028  /*
1029  * Initialize the max() computation using the last checkpoint address from
1030  * old pg_control. Note that for the moment we are working with segment
1031  * numbering according to the old xlog seg size.
1032  */
1033  segs_per_xlogid = (UINT64CONST(0x0000000100000000) / ControlFile.xlog_seg_size);
1034  newXlogSegNo = ControlFile.checkPointCopy.redo / ControlFile.xlog_seg_size;
1035 
1036  /*
1037  * Scan the pg_wal directory to find existing WAL segment files. We assume
1038  * any present have been used; in most scenarios this should be
1039  * conservative, because of xlog.c's attempts to pre-create files.
1040  */
1041  xldir = opendir(XLOGDIR);
1042  if (xldir == NULL)
1043  {
1044  fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
1045  progname, XLOGDIR, strerror(errno));
1046  exit(1);
1047  }
1048 
1049  while (errno = 0, (xlde = readdir(xldir)) != NULL)
1050  {
1051  if (IsXLogFileName(xlde->d_name) ||
1053  {
1054  unsigned int tli,
1055  log,
1056  seg;
1057  XLogSegNo segno;
1058 
1059  /*
1060  * Note: We don't use XLogFromFileName here, because we want to
1061  * use the segment size from the control file, not the size the
1062  * pg_resetwal binary was compiled with
1063  */
1064  sscanf(xlde->d_name, "%08X%08X%08X", &tli, &log, &seg);
1065  segno = ((uint64) log) * segs_per_xlogid + seg;
1066 
1067  /*
1068  * Note: we take the max of all files found, regardless of their
1069  * timelines. Another possibility would be to ignore files of
1070  * timelines other than the target TLI, but this seems safer.
1071  * Better too large a result than too small...
1072  */
1073  if (segno > newXlogSegNo)
1074  newXlogSegNo = segno;
1075  }
1076  }
1077 
1078  if (errno)
1079  {
1080  fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
1081  progname, XLOGDIR, strerror(errno));
1082  exit(1);
1083  }
1084 
1085  if (closedir(xldir))
1086  {
1087  fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
1088  progname, XLOGDIR, strerror(errno));
1089  exit(1);
1090  }
1091 
1092  /*
1093  * Finally, convert to new xlog seg size, and advance by one to ensure we
1094  * are in virgin territory.
1095  */
1096  xlogbytepos = newXlogSegNo * ControlFile.xlog_seg_size;
1097  newXlogSegNo = (xlogbytepos + ControlFile.xlog_seg_size - 1) / WalSegSz;
1098  newXlogSegNo++;
1099 }
1100 
1101 
1102 /*
1103  * Remove existing XLOG files
1104  */
1105 static void
1107 {
1108  DIR *xldir;
1109  struct dirent *xlde;
1110  char path[MAXPGPATH + sizeof(XLOGDIR)];
1111 
1112  xldir = opendir(XLOGDIR);
1113  if (xldir == NULL)
1114  {
1115  fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
1116  progname, XLOGDIR, strerror(errno));
1117  exit(1);
1118  }
1119 
1120  while (errno = 0, (xlde = readdir(xldir)) != NULL)
1121  {
1122  if (IsXLogFileName(xlde->d_name) ||
1124  {
1125  snprintf(path, sizeof(path), "%s/%s", XLOGDIR, xlde->d_name);
1126  if (unlink(path) < 0)
1127  {
1128  fprintf(stderr, _("%s: could not delete file \"%s\": %s\n"),
1129  progname, path, strerror(errno));
1130  exit(1);
1131  }
1132  }
1133  }
1134 
1135  if (errno)
1136  {
1137  fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
1138  progname, XLOGDIR, strerror(errno));
1139  exit(1);
1140  }
1141 
1142  if (closedir(xldir))
1143  {
1144  fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
1145  progname, XLOGDIR, strerror(errno));
1146  exit(1);
1147  }
1148 }
1149 
1150 
1151 /*
1152  * Remove existing archive status files
1153  */
1154 static void
1156 {
1157 #define ARCHSTATDIR XLOGDIR "/archive_status"
1158 
1159  DIR *xldir;
1160  struct dirent *xlde;
1161  char path[MAXPGPATH + sizeof(ARCHSTATDIR)];
1162 
1163  xldir = opendir(ARCHSTATDIR);
1164  if (xldir == NULL)
1165  {
1166  fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
1167  progname, ARCHSTATDIR, strerror(errno));
1168  exit(1);
1169  }
1170 
1171  while (errno = 0, (xlde = readdir(xldir)) != NULL)
1172  {
1173  if (strspn(xlde->d_name, "0123456789ABCDEF") == XLOG_FNAME_LEN &&
1174  (strcmp(xlde->d_name + XLOG_FNAME_LEN, ".ready") == 0 ||
1175  strcmp(xlde->d_name + XLOG_FNAME_LEN, ".done") == 0 ||
1176  strcmp(xlde->d_name + XLOG_FNAME_LEN, ".partial.ready") == 0 ||
1177  strcmp(xlde->d_name + XLOG_FNAME_LEN, ".partial.done") == 0))
1178  {
1179  snprintf(path, sizeof(path), "%s/%s", ARCHSTATDIR, xlde->d_name);
1180  if (unlink(path) < 0)
1181  {
1182  fprintf(stderr, _("%s: could not delete file \"%s\": %s\n"),
1183  progname, path, strerror(errno));
1184  exit(1);
1185  }
1186  }
1187  }
1188 
1189  if (errno)
1190  {
1191  fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
1192  progname, ARCHSTATDIR, strerror(errno));
1193  exit(1);
1194  }
1195 
1196  if (closedir(xldir))
1197  {
1198  fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
1199  progname, ARCHSTATDIR, strerror(errno));
1200  exit(1);
1201  }
1202 }
1203 
1204 
1205 /*
1206  * Write an empty XLOG file, containing only the checkpoint record
1207  * already set up in ControlFile.
1208  */
1209 static void
1211 {
1212  char *buffer;
1213  XLogPageHeader page;
1214  XLogLongPageHeader longpage;
1215  XLogRecord *record;
1216  pg_crc32c crc;
1217  char path[MAXPGPATH];
1218  int fd;
1219  int nbytes;
1220  char *recptr;
1221 
1222  /* Use malloc() to ensure buffer is MAXALIGNED */
1223  buffer = (char *) pg_malloc(XLOG_BLCKSZ);
1224  page = (XLogPageHeader) buffer;
1225  memset(buffer, 0, XLOG_BLCKSZ);
1226 
1227  /* Set up the XLOG page header */
1228  page->xlp_magic = XLOG_PAGE_MAGIC;
1229  page->xlp_info = XLP_LONG_HEADER;
1230  page->xlp_tli = ControlFile.checkPointCopy.ThisTimeLineID;
1231  page->xlp_pageaddr = ControlFile.checkPointCopy.redo - SizeOfXLogLongPHD;
1232  longpage = (XLogLongPageHeader) page;
1233  longpage->xlp_sysid = ControlFile.system_identifier;
1234  longpage->xlp_seg_size = WalSegSz;
1235  longpage->xlp_xlog_blcksz = XLOG_BLCKSZ;
1236 
1237  /* Insert the initial checkpoint record */
1238  recptr = (char *) page + SizeOfXLogLongPHD;
1239  record = (XLogRecord *) recptr;
1240  record->xl_prev = 0;
1241  record->xl_xid = InvalidTransactionId;
1244  record->xl_rmid = RM_XLOG_ID;
1245 
1246  recptr += SizeOfXLogRecord;
1247  *(recptr++) = (char) XLR_BLOCK_ID_DATA_SHORT;
1248  *(recptr++) = sizeof(CheckPoint);
1249  memcpy(recptr, &ControlFile.checkPointCopy,
1250  sizeof(CheckPoint));
1251 
1252  INIT_CRC32C(crc);
1253  COMP_CRC32C(crc, ((char *) record) + SizeOfXLogRecord, record->xl_tot_len - SizeOfXLogRecord);
1254  COMP_CRC32C(crc, (char *) record, offsetof(XLogRecord, xl_crc));
1255  FIN_CRC32C(crc);
1256  record->xl_crc = crc;
1257 
1258  /* Write the first page */
1259  XLogFilePath(path, ControlFile.checkPointCopy.ThisTimeLineID,
1261 
1262  unlink(path);
1263 
1264  fd = open(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
1266  if (fd < 0)
1267  {
1268  fprintf(stderr, _("%s: could not open file \"%s\": %s\n"),
1269  progname, path, strerror(errno));
1270  exit(1);
1271  }
1272 
1273  errno = 0;
1274  if (write(fd, buffer, XLOG_BLCKSZ) != XLOG_BLCKSZ)
1275  {
1276  /* if write didn't set errno, assume problem is no disk space */
1277  if (errno == 0)
1278  errno = ENOSPC;
1279  fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
1280  progname, path, strerror(errno));
1281  exit(1);
1282  }
1283 
1284  /* Fill the rest of the file with zeroes */
1285  memset(buffer, 0, XLOG_BLCKSZ);
1286  for (nbytes = XLOG_BLCKSZ; nbytes < WalSegSz; nbytes += XLOG_BLCKSZ)
1287  {
1288  errno = 0;
1289  if (write(fd, buffer, XLOG_BLCKSZ) != XLOG_BLCKSZ)
1290  {
1291  if (errno == 0)
1292  errno = ENOSPC;
1293  fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
1294  progname, path, strerror(errno));
1295  exit(1);
1296  }
1297  }
1298 
1299  if (fsync(fd) != 0)
1300  {
1301  fprintf(stderr, _("%s: fsync error: %s\n"), progname, strerror(errno));
1302  exit(1);
1303  }
1304 
1305  close(fd);
1306 }
1307 
1308 
1309 static void
1310 usage(void)
1311 {
1312  printf(_("%s resets the PostgreSQL write-ahead log.\n\n"), progname);
1313  printf(_("Usage:\n %s [OPTION]... DATADIR\n\n"), progname);
1314  printf(_("Options:\n"));
1315  printf(_(" -c, --commit-timestamp-ids=XID,XID\n"
1316  " set oldest and newest transactions bearing\n"
1317  " commit timestamp (zero means no change)\n"));
1318  printf(_(" [-D, --pgdata=]DATADIR data directory\n"));
1319  printf(_(" -e, --epoch=XIDEPOCH set next transaction ID epoch\n"));
1320  printf(_(" -f, --force force update to be done\n"));
1321  printf(_(" -l, --next-wal-file=WALFILE set minimum starting location for new WAL\n"));
1322  printf(_(" -m, --multixact-ids=MXID,MXID set next and oldest multitransaction ID\n"));
1323  printf(_(" -n, --dry-run no update, just show what would be done\n"));
1324  printf(_(" -o, --next-oid=OID set next OID\n"));
1325  printf(_(" -O, --multixact-offset=OFFSET set next multitransaction offset\n"));
1326  printf(_(" -V, --version output version information, then exit\n"));
1327  printf(_(" -x, --next-transaction-id=XID set next transaction ID\n"));
1328  printf(_(" --wal-segsize=SIZE size of WAL segments, in megabytes\n"));
1329  printf(_(" -?, --help show this help, then exit\n"));
1330  printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
1331 }
static void PrintControlValues(bool guessed)
Definition: pg_resetwal.c:762
#define INIT_CRC32C(crc)
Definition: pg_crc32c.h:41
#define IsValidWalSegSize(size)
Definition: xlog_internal.h:97
#define LOBLKSIZE
Definition: large_object.h:70
XLogRecPtr xl_prev
Definition: xlogrecord.h:45
int max_locks_per_xact
Definition: pg_control.h:181
static MultiXactId set_mxid
Definition: pg_resetwal.c:71
int pg_file_create_mode
Definition: file_perm.c:19
int gettimeofday(struct timeval *tp, struct timezone *tzp)
Definition: gettimeofday.c:105
int max_prepared_xacts
Definition: pg_control.h:180
int64 pg_time_t
Definition: pgtime.h:23
uint32 MultiXactOffset
Definition: c.h:486
static void usage(void)
Definition: pg_resetwal.c:1310
static TransactionId set_xid
Definition: pg_resetwal.c:67
pg_time_t time
Definition: pg_control.h:128
uint32 TransactionId
Definition: c.h:474
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
TimeLineID minRecoveryPointTLI
Definition: pg_control.h:167
#define write(a, b, c)
Definition: win32.h:14
static int set_wal_segsize
Definition: pg_resetwal.c:76
const char * get_progname(const char *argv0)
Definition: path.c:453
#define SizeOfXLogRecordDataHeaderShort
Definition: xlogrecord.h:201
int max_worker_processes
Definition: pg_control.h:179
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition: getopt_long.c:57
uint32 pg_crc32c
Definition: pg_crc32c.h:38
TransactionId oldestActiveXid
Definition: pg_control.h:63
static void PrintNewControlValues(void)
Definition: pg_resetwal.c:846
uint32 nameDataLen
Definition: pg_control.h:210
MultiXactId oldestMulti
Definition: pg_control.h:49
static void FindEndOfXLOG(void)
Definition: pg_resetwal.c:1021
#define DEFAULT_XLOG_SEG_SIZE
TimeLineID PrevTimeLineID
Definition: pg_control.h:39
int closedir(DIR *)
Definition: dirent.c:111
static void WriteEmptyXLOG(void)
Definition: pg_resetwal.c:1210
#define CATALOG_VERSION_NO
Definition: catversion.h:56
#define PG_CONTROL_VERSION
Definition: pg_control.h:24
static Oid set_oid
Definition: pg_resetwal.c:70
RmgrId xl_rmid
Definition: xlogrecord.h:47
XLogPageHeaderData * XLogPageHeader
Definition: xlog_internal.h:57
uint32 pg_control_version
Definition: pg_control.h:121
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
CheckPoint checkPointCopy
Definition: pg_control.h:131
uint32 xlog_blcksz
Definition: pg_control.h:207
TransactionId oldestXid
Definition: pg_control.h:47
unsigned int Oid
Definition: postgres_ext.h:31
TransactionId nextXid
Definition: pg_control.h:43
#define PG_CONTROL_MAX_SAFE_SIZE
Definition: pg_control.h:240
Definition: dirent.h:9
pg_time_t time
Definition: pg_control.h:51
static void CheckDataVersion(void)
Definition: pg_resetwal.c:539
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1080
static bool ReadControlFile(void)
Definition: pg_resetwal.c:597
void get_restricted_token(const char *progname)
static TransactionId set_newest_commit_ts_xid
Definition: pg_resetwal.c:69
XLogLongPageHeaderData * XLogLongPageHeader
Definition: xlog_internal.h:74
static void KillExistingXLOG(void)
Definition: pg_resetwal.c:1106
#define NAMEDATALEN
bool backupEndRequired
Definition: pg_control.h:170
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:795
MultiXactOffset nextMultiOffset
Definition: pg_control.h:46
#define required_argument
Definition: getopt_long.h:25
#define fsync(fd)
Definition: win32_port.h:63
TransactionId oldestCommitTsXid
Definition: pg_control.h:52
uint32 xlog_seg_size
Definition: pg_control.h:208
int optind
Definition: getopt.c:51
Definition: dirent.c:25
static void KillExistingArchiveStatus(void)
Definition: pg_resetwal.c:1155
#define FirstNormalTransactionId
Definition: transam.h:34
#define IsXLogFileName(fname)
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
uint32 nextXidEpoch
Definition: pg_control.h:42
DIR * opendir(const char *)
Definition: dirent.c:33
static TransactionId set_oldest_commit_ts_xid
Definition: pg_resetwal.c:68
#define XLogFromFileName(fname, tli, logSegNo, wal_segsz_bytes)
uint32 data_checksum_version
Definition: pg_control.h:221
char * c
#define XLOG_CHECKPOINT_SHUTDOWN
Definition: pg_control.h:67
XLogRecPtr unloggedLSN
Definition: pg_control.h:133
uint64 XLogSegNo
Definition: xlogdefs.h:34
#define XLogSegNoOffsetToRecPtr(segno, offset, dest, wal_segsz_bytes)
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
#define InvalidTransactionId
Definition: transam.h:31
unsigned int uint32
Definition: c.h:325
pg_crc32c crc
Definition: pg_control.h:231
#define FirstBootstrapObjectId
Definition: transam.h:93
#define FirstMultiXactId
Definition: multixact.h:24
uint32 loblksize
Definition: pg_control.h:214
#define EQ_CRC32C(c1, c2)
Definition: pg_crc32c.h:42
static const char * progname
Definition: pg_resetwal.c:65
uint32 indexMaxKeys
Definition: pg_control.h:211
TimeLineID xlp_tli
Definition: xlog_internal.h:40
XLogRecPtr xlp_pageaddr
Definition: xlog_internal.h:41
static bool guessed
Definition: pg_resetwal.c:64
#define SizeOfXLogRecord
Definition: xlogrecord.h:55
#define MAXFNAMELEN
#define TOAST_MAX_CHUNK_SIZE
Definition: tuptoaster.h:91
#define no_argument
Definition: getopt_long.h:24
#define ngettext(s, p, n)
Definition: c.h:1022
TransactionId newestCommitTsXid
Definition: pg_control.h:54
#define PG_TEXTDOMAIN(domain)
Definition: c.h:1054
#define XLOGDIR
Oid oldestMultiDB
Definition: pg_control.h:50
uint32 toast_max_chunk_size
Definition: pg_control.h:213
#define XLOG_CONTROL_FILE
#define InvalidOid
Definition: postgres_ext.h:36
Oid nextOid
Definition: pg_control.h:44
XLogRecPtr backupEndPoint
Definition: pg_control.h:169
bool fullPageWrites
Definition: pg_control.h:41
static int WalSegSz
Definition: pg_resetwal.c:75
TransactionId MultiXactId
Definition: c.h:484
bool track_commit_timestamp
Definition: pg_control.h:182
#define XLP_LONG_HEADER
Definition: xlog_internal.h:79
Oid oldestXidDB
Definition: pg_control.h:48
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
int main(int argc, char *argv[])
Definition: pg_resetwal.c:92
static ControlFileData ControlFile
Definition: pg_resetwal.c:62
double floatFormat
Definition: pg_control.h:197
#define INDEX_MAX_KEYS
#define XLogFileName(fname, tli, logSegNo, wal_segsz_bytes)
uint8 xl_info
Definition: xlogrecord.h:46
MultiXactId nextMulti
Definition: pg_control.h:45
static void RewriteControlFile(void)
Definition: pg_resetwal.c:918
static MultiXactOffset set_mxoff
Definition: pg_resetwal.c:72
uint32 catalog_version_no
Definition: pg_control.h:122
struct dirent * readdir(DIR *)
Definition: dirent.c:77
#define PG_CONTROL_FILE_SIZE
Definition: pg_control.h:249
struct CheckPoint CheckPoint
#define XLR_BLOCK_ID_DATA_SHORT
Definition: xlogrecord.h:224
#define XLogFilePath(path, tli, logSegNo, wal_segsz_bytes)
TransactionId xl_xid
Definition: xlogrecord.h:44
static XLogSegNo newXlogSegNo
Definition: pg_resetwal.c:63
bool GetDataDirectoryCreatePerm(const char *dataDir)
static void GuessControlValues(void)
Definition: pg_resetwal.c:679
static uint32 minXlogTli
Definition: pg_resetwal.c:73
#define IsPartialXLogFileName(fname)
TimeLineID ThisTimeLineID
Definition: pg_control.h:38
void set_pglocale_pgservice(const char *argv0, const char *app)
Definition: exec.c:550
#define ARCHSTATDIR
char * optarg
Definition: getopt.c:53
const char * strerror(int errnum)
Definition: strerror.c:19
char * DataDir
Definition: globals.c:61
#define XLOG_FNAME_LEN
char d_name[MAX_PATH]
Definition: dirent.h:14
#define close(a)
Definition: win32.h:12
#define FLOATFORMAT_VALUE
Definition: pg_control.h:198
#define COMP_CRC32C(crc, data, len)
Definition: pg_crc32c.h:89
#define FIN_CRC32C(crc)
Definition: pg_crc32c.h:94
#define _(x)
Definition: elog.c:84
#define UINT64_FORMAT
Definition: c.h:368
static XLogSegNo minXlogSegNo
Definition: pg_resetwal.c:74
int pg_mode_mask
Definition: file_perm.c:25
XLogRecPtr backupStartPoint
Definition: pg_control.h:168
uint32 relseg_size
Definition: pg_control.h:205
XLogRecPtr checkPoint
Definition: pg_control.h:129
XLogRecPtr redo
Definition: pg_control.h:36
#define read(a, b, c)
Definition: win32.h:13
#define offsetof(type, field)
Definition: c.h:622
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:166
static uint32 set_xid_epoch
Definition: pg_resetwal.c:66
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:72