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-2021, 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/heaptoast.h"
48 #include "access/multixact.h"
49 #include "access/transam.h"
50 #include "access/xlog.h"
51 #include "access/xlog_internal.h"
53 #include "common/fe_memutils.h"
54 #include "common/file_perm.h"
55 #include "common/logging.h"
57 #include "common/string.h"
58 #include "getopt_long.h"
59 #include "pg_getopt.h"
60 #include "storage/large_object.h"
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;
71 static Oid set_oid = 0;
72 static MultiXactId set_mxid = 0;
74 static uint32 minXlogTli = 0;
76 static int WalSegSz;
77 static int set_wal_segsize;
78 
79 static void CheckDataVersion(void);
80 static bool read_controlfile(void);
81 static void GuessControlValues(void);
82 static void PrintControlValues(bool guessed);
83 static void PrintNewControlValues(void);
84 static void RewriteControlFile(void);
85 static void FindEndOfXLOG(void);
86 static void KillExistingXLOG(void);
87 static void KillExistingArchiveStatus(void);
88 static void WriteEmptyXLOG(void);
89 static void usage(void);
90 
91 
92 int
93 main(int argc, char *argv[])
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
430  WalSegSz = ControlFile.xlog_seg_size;
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)
452  ControlFile.checkPointCopy.nextXid =
455 
456  if (set_oldest_xid != 0)
457  {
459  ControlFile.checkPointCopy.oldestXidDB = InvalidOid;
460  }
461 
462  if (set_xid != 0)
463  ControlFile.checkPointCopy.nextXid =
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)
473  ControlFile.checkPointCopy.nextOid = set_oid;
474 
475  if (set_mxid != 0)
476  {
477  ControlFile.checkPointCopy.nextMulti = set_mxid;
478 
479  ControlFile.checkPointCopy.oldestMulti = set_oldestmxid;
480  if (ControlFile.checkPointCopy.oldestMulti < FirstMultiXactId)
483  }
484 
485  if (set_mxoff != -1)
487 
488  if (minXlogTli > ControlFile.checkPointCopy.ThisTimeLineID)
489  {
492  }
493 
494  if (set_wal_segsize != 0)
495  ControlFile.xlog_seg_size = WalSegSz;
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 }
538 
539 
540 /*
541  * Look at the version string stored in PG_VERSION and decide if this utility
542  * can be run safely or not.
543  *
544  * We don't want to inject pg_control and WAL files that are for a different
545  * major version; that can't do anything good. Note that we don't treat
546  * mismatching version info in pg_control as a reason to bail out, because
547  * recovering from a corrupted pg_control is one of the main reasons for this
548  * program to exist at all. However, PG_VERSION is unlikely to get corrupted,
549  * and if it were it would be easy to fix by hand. So let's make this check
550  * to prevent simple user errors.
551  */
552 static void
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 }
589 
590 
591 /*
592  * Try to read the existing pg_control file.
593  *
594  * This routine is also responsible for updating old pg_control versions
595  * to the current format. (Currently we don't do anything of the sort.)
596  */
597 static bool
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 */
653  if (!IsValidWalSegSize(ControlFile.xlog_seg_size))
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",
657  ControlFile.xlog_seg_size),
658  ControlFile.xlog_seg_size);
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 }
669 
670 
671 /*
672  * Guess at pg_control values when we can't read the old ones.
673  */
674 static void
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 
700  ControlFile.checkPointCopy.redo = SizeOfXLogLongPHD;
701  ControlFile.checkPointCopy.ThisTimeLineID = 1;
702  ControlFile.checkPointCopy.PrevTimeLineID = 1;
703  ControlFile.checkPointCopy.fullPageWrites = false;
704  ControlFile.checkPointCopy.nextXid =
708  ControlFile.checkPointCopy.nextMultiOffset = 0;
710  ControlFile.checkPointCopy.oldestXidDB = InvalidOid;
713  ControlFile.checkPointCopy.time = (pg_time_t) time(NULL);
715 
716  ControlFile.state = DB_SHUTDOWNED;
717  ControlFile.time = (pg_time_t) time(NULL);
718  ControlFile.checkPoint = ControlFile.checkPointCopy.redo;
719  ControlFile.unloggedLSN = FirstNormalUnloggedLSN;
720 
721  /* minRecoveryPoint, backupStartPoint and backupEndPoint can be left zero */
722 
723  ControlFile.wal_level = WAL_LEVEL_MINIMAL;
724  ControlFile.wal_log_hints = false;
725  ControlFile.track_commit_timestamp = false;
726  ControlFile.MaxConnections = 100;
727  ControlFile.max_wal_senders = 10;
728  ControlFile.max_worker_processes = 8;
729  ControlFile.max_prepared_xacts = 0;
730  ControlFile.max_locks_per_xact = 64;
731 
732  ControlFile.maxAlign = MAXIMUM_ALIGNOF;
733  ControlFile.floatFormat = FLOATFORMAT_VALUE;
734  ControlFile.blcksz = BLCKSZ;
735  ControlFile.relseg_size = RELSEG_SIZE;
736  ControlFile.xlog_blcksz = XLOG_BLCKSZ;
737  ControlFile.xlog_seg_size = DEFAULT_XLOG_SEG_SIZE;
738  ControlFile.nameDataLen = NAMEDATALEN;
739  ControlFile.indexMaxKeys = INDEX_MAX_KEYS;
741  ControlFile.loblksize = LOBLKSIZE;
742  ControlFile.float8ByVal = FLOAT8PASSBYVAL;
743 
744  /*
745  * XXX eventually, should try to grovel through old XLOG to develop more
746  * accurate values for TimeLineID, nextXID, etc.
747  */
748 }
749 
750 
751 /*
752  * Print the guessed pg_control values when we had to guess.
753  *
754  * NB: this display should be just those fields that will not be
755  * reset by RewriteControlFile().
756  */
757 static void
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"),
766  ControlFile.pg_control_version);
767  printf(_("Catalog version number: %u\n"),
768  ControlFile.catalog_version_no);
769  printf(_("Database system identifier: %llu\n"),
770  (unsigned long long) ControlFile.system_identifier);
771  printf(_("Latest checkpoint's TimeLineID: %u\n"),
772  ControlFile.checkPointCopy.ThisTimeLineID);
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"),
779  ControlFile.checkPointCopy.nextOid);
780  printf(_("Latest checkpoint's NextMultiXactId: %u\n"),
781  ControlFile.checkPointCopy.nextMulti);
782  printf(_("Latest checkpoint's NextMultiOffset: %u\n"),
783  ControlFile.checkPointCopy.nextMultiOffset);
784  printf(_("Latest checkpoint's oldestXID: %u\n"),
785  ControlFile.checkPointCopy.oldestXid);
786  printf(_("Latest checkpoint's oldestXID's DB: %u\n"),
787  ControlFile.checkPointCopy.oldestXidDB);
788  printf(_("Latest checkpoint's oldestActiveXID: %u\n"),
789  ControlFile.checkPointCopy.oldestActiveXid);
790  printf(_("Latest checkpoint's oldestMultiXid: %u\n"),
791  ControlFile.checkPointCopy.oldestMulti);
792  printf(_("Latest checkpoint's oldestMulti's DB: %u\n"),
793  ControlFile.checkPointCopy.oldestMultiDB);
794  printf(_("Latest checkpoint's oldestCommitTsXid:%u\n"),
795  ControlFile.checkPointCopy.oldestCommitTsXid);
796  printf(_("Latest checkpoint's newestCommitTsXid:%u\n"),
797  ControlFile.checkPointCopy.newestCommitTsXid);
798  printf(_("Maximum data alignment: %u\n"),
799  ControlFile.maxAlign);
800  /* we don't print floatFormat since can't say much useful about it */
801  printf(_("Database block size: %u\n"),
802  ControlFile.blcksz);
803  printf(_("Blocks per segment of large relation: %u\n"),
804  ControlFile.relseg_size);
805  printf(_("WAL block size: %u\n"),
806  ControlFile.xlog_blcksz);
807  printf(_("Bytes per WAL segment: %u\n"),
808  ControlFile.xlog_seg_size);
809  printf(_("Maximum length of identifiers: %u\n"),
810  ControlFile.nameDataLen);
811  printf(_("Maximum columns in an index: %u\n"),
812  ControlFile.indexMaxKeys);
813  printf(_("Maximum size of a TOAST chunk: %u\n"),
814  ControlFile.toast_max_chunk_size);
815  printf(_("Size of a large-object chunk: %u\n"),
816  ControlFile.loblksize);
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"),
823  ControlFile.data_checksum_version);
824 }
825 
826 
827 /*
828  * Print the values to be changed.
829  */
830 static void
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 
838  XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
840  printf(_("First log segment after reset: %s\n"), fname);
841 
842  if (set_mxid != 0)
843  {
844  printf(_("NextMultiXactId: %u\n"),
845  ControlFile.checkPointCopy.nextMulti);
846  printf(_("OldestMultiXid: %u\n"),
847  ControlFile.checkPointCopy.oldestMulti);
848  printf(_("OldestMulti's DB: %u\n"),
849  ControlFile.checkPointCopy.oldestMultiDB);
850  }
851 
852  if (set_mxoff != -1)
853  {
854  printf(_("NextMultiOffset: %u\n"),
855  ControlFile.checkPointCopy.nextMultiOffset);
856  }
857 
858  if (set_oid != 0)
859  {
860  printf(_("NextOID: %u\n"),
861  ControlFile.checkPointCopy.nextOid);
862  }
863 
864  if (set_xid != 0)
865  {
866  printf(_("NextXID: %u\n"),
868  printf(_("OldestXID: %u\n"),
869  ControlFile.checkPointCopy.oldestXid);
870  printf(_("OldestXID's DB: %u\n"),
871  ControlFile.checkPointCopy.oldestXidDB);
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"),
883  ControlFile.checkPointCopy.oldestCommitTsXid);
884  }
885  if (set_newest_commit_ts_xid != 0)
886  {
887  printf(_("newestCommitTsXid: %u\n"),
888  ControlFile.checkPointCopy.newestCommitTsXid);
889  }
890 
891  if (set_wal_segsize != 0)
892  {
893  printf(_("Bytes per WAL segment: %u\n"),
894  ControlFile.xlog_seg_size);
895  }
896 }
897 
898 
899 /*
900  * Write out the new pg_control file.
901  */
902 static void
904 {
905  /*
906  * Adjust fields as needed to force an empty XLOG starting at
907  * newXlogSegNo.
908  */
910  ControlFile.checkPointCopy.redo);
911  ControlFile.checkPointCopy.time = (pg_time_t) time(NULL);
912 
913  ControlFile.state = DB_SHUTDOWNED;
914  ControlFile.time = (pg_time_t) time(NULL);
915  ControlFile.checkPoint = ControlFile.checkPointCopy.redo;
916  ControlFile.minRecoveryPoint = 0;
917  ControlFile.minRecoveryPointTLI = 0;
918  ControlFile.backupStartPoint = 0;
919  ControlFile.backupEndPoint = 0;
920  ControlFile.backupEndRequired = false;
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  */
927  ControlFile.wal_level = WAL_LEVEL_MINIMAL;
928  ControlFile.wal_log_hints = false;
929  ControlFile.track_commit_timestamp = false;
930  ControlFile.MaxConnections = 100;
931  ControlFile.max_wal_senders = 10;
932  ControlFile.max_worker_processes = 8;
933  ControlFile.max_prepared_xacts = 0;
934  ControlFile.max_locks_per_xact = 64;
935 
936  /* The control file gets flushed here. */
937  update_controlfile(".", &ControlFile, true);
938 }
939 
940 
941 /*
942  * Scan existing XLOG files and determine the highest existing WAL address
943  *
944  * On entry, ControlFile.checkPointCopy.redo and ControlFile.xlog_seg_size
945  * are assumed valid (note that we allow the old xlog seg size to differ
946  * from what we're using). On exit, newXlogSegNo is set to suitable
947  * value for the beginning of replacement WAL (in our seg size).
948  */
949 static void
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);
963  newXlogSegNo = ControlFile.checkPointCopy.redo / 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 }
1026 
1027 
1028 /*
1029  * Remove existing XLOG files
1030  */
1031 static void
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 }
1071 
1072 
1073 /*
1074  * Remove existing archive status files
1075  */
1076 static void
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 }
1121 
1122 
1123 /*
1124  * Write an empty XLOG file, containing only the checkpoint record
1125  * already set up in ControlFile.
1126  */
1127 static void
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;
1146  page->xlp_tli = ControlFile.checkPointCopy.ThisTimeLineID;
1147  page->xlp_pageaddr = ControlFile.checkPointCopy.redo - SizeOfXLogLongPHD;
1148  longpage = (XLogLongPageHeader) page;
1149  longpage->xlp_sysid = ControlFile.system_identifier;
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 */
1175  XLogFilePath(path, ControlFile.checkPointCopy.ThisTimeLineID,
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 }
1220 
1221 
1222 static void
1223 usage(void)
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 }
static void PrintControlValues(bool guessed)
Definition: pg_resetwal.c:758
#define INIT_CRC32C(crc)
Definition: pg_crc32c.h:41
#define IsValidWalSegSize(size)
Definition: xlog_internal.h:94
#define LOBLKSIZE
Definition: large_object.h:70
XLogRecPtr xl_prev
Definition: xlogrecord.h:45
int max_locks_per_xact
Definition: pg_control.h:182
static MultiXactId set_mxid
Definition: pg_resetwal.c:72
int pg_file_create_mode
Definition: file_perm.c:19
int gettimeofday(struct timeval *tp, struct timezone *tzp)
Definition: gettimeofday.c:104
int max_prepared_xacts
Definition: pg_control.h:181
int64 pg_time_t
Definition: pgtime.h:23
#define TOAST_MAX_CHUNK_SIZE
Definition: heaptoast.h:84
uint32 MultiXactOffset
Definition: c.h:599
static void usage(void)
Definition: pg_resetwal.c:1223
int pg_strip_crlf(char *str)
Definition: string.c:121
static TransactionId set_xid
Definition: pg_resetwal.c:68
pg_time_t time
Definition: pg_control.h:128
uint32 TransactionId
Definition: c.h:587
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:77
const char * get_progname(const char *argv0)
Definition: path.c:453
#define SizeOfXLogRecordDataHeaderShort
Definition: xlogrecord.h:204
int max_worker_processes
Definition: pg_control.h:179
#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)
uint32 pg_crc32c
Definition: pg_crc32c.h:38
TransactionId oldestActiveXid
Definition: pg_control.h:63
static void PrintNewControlValues(void)
Definition: pg_resetwal.c:831
void pg_logging_init(const char *argv0)
Definition: logging.c:81
uint32 nameDataLen
Definition: pg_control.h:211
MultiXactId oldestMulti
Definition: pg_control.h:49
static void FindEndOfXLOG(void)
Definition: pg_resetwal.c:950
#define DEFAULT_XLOG_SEG_SIZE
TimeLineID PrevTimeLineID
Definition: pg_control.h:40
int closedir(DIR *)
Definition: dirent.c:123
static void WriteEmptyXLOG(void)
Definition: pg_resetwal.c:1128
#define CATALOG_VERSION_NO
Definition: catversion.h:56
#define PG_CONTROL_VERSION
Definition: pg_control.h:25
static Oid set_oid
Definition: pg_resetwal.c:71
RmgrId xl_rmid
Definition: xlogrecord.h:47
XLogPageHeaderData * XLogPageHeader
Definition: xlog_internal.h:54
uint32 pg_control_version
Definition: pg_control.h:121
#define printf(...)
Definition: port.h:222
CheckPoint checkPointCopy
Definition: pg_control.h:131
uint32 xlog_blcksz
Definition: pg_control.h:208
TransactionId oldestXid
Definition: pg_control.h:47
unsigned int Oid
Definition: postgres_ext.h:31
#define fprintf
Definition: port.h:220
Definition: dirent.h:9
pg_time_t time
Definition: pg_control.h:51
static void CheckDataVersion(void)
Definition: pg_resetwal.c:553
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1271
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
#define NAMEDATALEN
bool backupEndRequired
Definition: pg_control.h:170
MultiXactOffset nextMultiOffset
Definition: pg_control.h:46
void update_controlfile(const char *DataDir, ControlFileData *ControlFile, bool do_sync)
#define required_argument
Definition: getopt_long.h:25
#define fsync(fd)
Definition: win32_port.h:68
TransactionId oldestCommitTsXid
Definition: pg_control.h:52
uint32 xlog_seg_size
Definition: pg_control.h:209
int optind
Definition: getopt.c:50
Definition: dirent.c:25
static void KillExistingArchiveStatus(void)
Definition: pg_resetwal.c:1077
#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
DIR * opendir(const char *)
Definition: dirent.c:33
static TransactionId set_oldest_commit_ts_xid
Definition: pg_resetwal.c:69
#define XLogFromFileName(fname, tli, logSegNo, wal_segsz_bytes)
uint32 data_checksum_version
Definition: pg_control.h:220
char * c
#define XLOG_CHECKPOINT_SHUTDOWN
Definition: pg_control.h:67
XLogRecPtr unloggedLSN
Definition: pg_control.h:133
uint64 XLogSegNo
Definition: xlogdefs.h:48
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
#define InvalidTransactionId
Definition: transam.h:31
unsigned int uint32
Definition: c.h:441
#define FirstMultiXactId
Definition: multixact.h:25
uint32 loblksize
Definition: pg_control.h:215
#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:212
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 no_argument
Definition: getopt_long.h:24
#define ngettext(s, p, n)
Definition: c.h:1182
TransactionId newestCommitTsXid
Definition: pg_control.h:54
#define PG_TEXTDOMAIN(domain)
Definition: c.h:1215
#define XLOGDIR
#define FirstNormalUnloggedLSN
Definition: xlogdefs.h:36
Oid oldestMultiDB
Definition: pg_control.h:50
uint32 toast_max_chunk_size
Definition: pg_control.h:214
#define EpochFromFullTransactionId(x)
Definition: transam.h:47
#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:42
static int WalSegSz
Definition: pg_resetwal.c:76
TransactionId MultiXactId
Definition: c.h:597
#define XLogSegNoOffsetToRecPtr(segno, offset, wal_segsz_bytes, dest)
#define FLOAT8PASSBYVAL
Definition: c.h:570
bool track_commit_timestamp
Definition: pg_control.h:183
#define XLP_LONG_HEADER
Definition: xlog_internal.h:76
Oid oldestXidDB
Definition: pg_control.h:48
int main(int argc, char *argv[])
Definition: pg_resetwal.c:93
static ControlFileData ControlFile
Definition: pg_resetwal.c:62
double floatFormat
Definition: pg_control.h:198
#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:903
static MultiXactOffset set_mxoff
Definition: pg_resetwal.c:73
uint32 catalog_version_no
Definition: pg_control.h:122
static FullTransactionId FullTransactionIdFromEpochAndXid(uint32 epoch, TransactionId xid)
Definition: transam.h:71
struct dirent * readdir(DIR *)
Definition: dirent.c:78
#define PG_CONTROL_FILE_SIZE
Definition: pg_control.h:248
struct CheckPoint CheckPoint
#define XLR_BLOCK_ID_DATA_SHORT
Definition: xlogrecord.h:227
#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:675
static uint32 minXlogTli
Definition: pg_resetwal.c:74
#define FirstGenbkiObjectId
Definition: transam.h:195
static bool read_controlfile(void)
Definition: pg_resetwal.c:598
#define IsPartialXLogFileName(fname)
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
void set_pglocale_pgservice(const char *argv0, const char *app)
Definition: exec.c:433
#define ARCHSTATDIR
char * optarg
Definition: getopt.c:52
char * DataDir
Definition: globals.c:65
#define XLOG_FNAME_LEN
char d_name[MAX_PATH]
Definition: dirent.h:15
#define close(a)
Definition: win32.h:12
#define pg_log_warning(...)
Definition: pgfnames.c:24
#define FLOATFORMAT_VALUE
Definition: pg_control.h:199
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
#define COMP_CRC32C(crc, data, len)
Definition: pg_crc32c.h:89
char data[XLOG_BLCKSZ]
Definition: c.h:1149
#define snprintf
Definition: port.h:216
#define FIN_CRC32C(crc)
Definition: pg_crc32c.h:94
#define _(x)
Definition: elog.c:89
static XLogSegNo minXlogSegNo
Definition: pg_resetwal.c:75
int pg_mode_mask
Definition: file_perm.c:25
XLogRecPtr backupStartPoint
Definition: pg_control.h:168
uint32 relseg_size
Definition: pg_control.h:206
XLogRecPtr checkPoint
Definition: pg_control.h:129
XLogRecPtr redo
Definition: pg_control.h:37
#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
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:166
FullTransactionId nextXid
Definition: pg_control.h:43
static uint32 set_xid_epoch
Definition: pg_resetwal.c:66
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:69