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-2019, 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;
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  pg_logging_init(argv[0]);
120  set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_resetwal"));
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  pg_log_error("invalid argument for option %s", "-e");
161  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
162  exit(1);
163  }
164  if (set_xid_epoch == -1)
165  {
166  pg_log_error("transaction ID epoch (-e) must not be -1");
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  pg_log_error("invalid argument for option %s", "-x");
176  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
177  exit(1);
178  }
179  if (set_xid == 0)
180  {
181  pg_log_error("transaction ID (-x) must not be 0");
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  pg_log_error("invalid argument for option %s", "-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  pg_log_error("invalid argument for option %s", "-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  pg_log_error("transaction ID (-c) must be either 0 or greater than or equal to 2");
206  exit(1);
207  }
208 
209  if (set_newest_commit_ts_xid < 2 &&
211  {
212  pg_log_error("transaction ID (-c) must be either 0 or greater than or equal to 2");
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  pg_log_error("invalid argument for option %s", "-o");
222  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
223  exit(1);
224  }
225  if (set_oid == 0)
226  {
227  pg_log_error("OID (-o) must not be 0");
228  exit(1);
229  }
230  break;
231 
232  case 'm':
233  set_mxid = strtoul(optarg, &endptr, 0);
234  if (endptr == optarg || *endptr != ',')
235  {
236  pg_log_error("invalid argument for option %s", "-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  pg_log_error("invalid argument for option %s", "-m");
245  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
246  exit(1);
247  }
248  if (set_mxid == 0)
249  {
250  pg_log_error("multitransaction ID (-m) must not be 0");
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  pg_log_error("oldest multitransaction ID (-m) must not be 0");
261  exit(1);
262  }
263  break;
264 
265  case 'O':
266  set_mxoff = strtoul(optarg, &endptr, 0);
267  if (endptr == optarg || *endptr != '\0')
268  {
269  pg_log_error("invalid argument for option %s", "-O");
270  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
271  exit(1);
272  }
273  if (set_mxoff == -1)
274  {
275  pg_log_error("multitransaction offset (-O) must not be -1");
276  exit(1);
277  }
278  break;
279 
280  case 'l':
281  if (strspn(optarg, "01234567890ABCDEFabcdef") != XLOG_FNAME_LEN)
282  {
283  pg_log_error("invalid argument for option %s", "-l");
284  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
285  exit(1);
286  }
287 
288  /*
289  * XLogFromFileName requires wal segment size which is not yet
290  * set. Hence wal details are set later on.
291  */
292  log_fname = pg_strdup(optarg);
293  break;
294 
295  case 1:
296  set_wal_segsize = strtol(optarg, &endptr, 10) * 1024 * 1024;
297  if (endptr == optarg || *endptr != '\0')
298  {
299  pg_log_error("argument of --wal-segsize must be a number");
300  exit(1);
301  }
303  {
304  pg_log_error("argument of --wal-segsize must be a power of 2 between 1 and 1024");
305  exit(1);
306  }
307  break;
308 
309  default:
310  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
311  exit(1);
312  }
313  }
314 
315  if (DataDir == NULL && optind < argc)
316  DataDir = argv[optind++];
317 
318  /* Complain if any arguments remain */
319  if (optind < argc)
320  {
321  pg_log_error("too many command-line arguments (first is \"%s\")",
322  argv[optind]);
323  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
324  progname);
325  exit(1);
326  }
327 
328  if (DataDir == NULL)
329  {
330  pg_log_error("no data directory specified");
331  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
332  exit(1);
333  }
334 
335  /*
336  * Don't allow pg_resetwal to be run as root, to avoid overwriting the
337  * ownership of files in the data directory. We need only check for root
338  * -- any other user won't have sufficient permissions to modify files in
339  * the data directory.
340  */
341 #ifndef WIN32
342  if (geteuid() == 0)
343  {
344  pg_log_error("cannot be executed by \"root\"");
345  pg_log_info("You must run %s as the PostgreSQL superuser.",
346  progname);
347  exit(1);
348  }
349 #endif
350 
352 
353  /* Set mask based on PGDATA permissions */
354  if (!GetDataDirectoryCreatePerm(DataDir))
355  {
356  pg_log_error("could not read permissions of directory \"%s\": %m",
357  DataDir);
358  exit(1);
359  }
360 
361  umask(pg_mode_mask);
362 
363  if (chdir(DataDir) < 0)
364  {
365  pg_log_error("could not change directory to \"%s\": %m",
366  DataDir);
367  exit(1);
368  }
369 
370  /* Check that data directory matches our server version */
372 
373  /*
374  * Check for a postmaster lock file --- if there is one, refuse to
375  * proceed, on grounds we might be interfering with a live installation.
376  */
377  if ((fd = open("postmaster.pid", O_RDONLY, 0)) < 0)
378  {
379  if (errno != ENOENT)
380  {
381  pg_log_error("could not open file \"%s\" for reading: %m",
382  "postmaster.pid");
383  exit(1);
384  }
385  }
386  else
387  {
388  pg_log_error("lock file \"%s\" exists", "postmaster.pid");
389  pg_log_info("Is a server running? If not, delete the lock file and try again.");
390  exit(1);
391  }
392 
393  /*
394  * Attempt to read the existing pg_control file
395  */
396  if (!ReadControlFile())
398 
399  /*
400  * If no new WAL segment size was specified, use the control file value.
401  */
402  if (set_wal_segsize != 0)
404  else
405  WalSegSz = ControlFile.xlog_seg_size;
406 
407  if (log_fname != NULL)
409 
410  /*
411  * Also look at existing segment files to set up newXlogSegNo
412  */
413  FindEndOfXLOG();
414 
415  /*
416  * If we're not going to proceed with the reset, print the current control
417  * file parameters.
418  */
419  if ((guessed && !force) || noupdate)
421 
422  /*
423  * Adjust fields if required by switches. (Do this now so that printout,
424  * if any, includes these values.)
425  */
426  if (set_xid_epoch != -1)
427  ControlFile.checkPointCopy.nextFullXid =
430 
431  if (set_xid != 0)
432  {
433  ControlFile.checkPointCopy.nextFullXid =
435  set_xid);
436 
437  /*
438  * For the moment, just set oldestXid to a value that will force
439  * immediate autovacuum-for-wraparound. It's not clear whether adding
440  * user control of this is useful, so let's just do something that's
441  * reasonably safe. The magic constant here corresponds to the
442  * maximum allowed value of autovacuum_freeze_max_age.
443  */
444  ControlFile.checkPointCopy.oldestXid = set_xid - 2000000000;
447  ControlFile.checkPointCopy.oldestXidDB = InvalidOid;
448  }
449 
450  if (set_oldest_commit_ts_xid != 0)
452  if (set_newest_commit_ts_xid != 0)
454 
455  if (set_oid != 0)
456  ControlFile.checkPointCopy.nextOid = set_oid;
457 
458  if (set_mxid != 0)
459  {
460  ControlFile.checkPointCopy.nextMulti = set_mxid;
461 
462  ControlFile.checkPointCopy.oldestMulti = set_oldestmxid;
463  if (ControlFile.checkPointCopy.oldestMulti < FirstMultiXactId)
466  }
467 
468  if (set_mxoff != -1)
470 
471  if (minXlogTli > ControlFile.checkPointCopy.ThisTimeLineID)
472  {
475  }
476 
477  if (set_wal_segsize != 0)
478  ControlFile.xlog_seg_size = WalSegSz;
479 
482 
483  /*
484  * If we had to guess anything, and -f was not given, just print the
485  * guessed values and exit. Also print if -n is given.
486  */
487  if ((guessed && !force) || noupdate)
488  {
490  if (!noupdate)
491  {
492  printf(_("\nIf these values seem acceptable, use -f to force reset.\n"));
493  exit(1);
494  }
495  else
496  exit(0);
497  }
498 
499  /*
500  * Don't reset from a dirty pg_control without -f, either.
501  */
502  if (ControlFile.state != DB_SHUTDOWNED && !force)
503  {
504  printf(_("The database server was not shut down cleanly.\n"
505  "Resetting the write-ahead log might cause data to be lost.\n"
506  "If you want to proceed anyway, use -f to force reset.\n"));
507  exit(1);
508  }
509 
510  /*
511  * Else, do the dirty deed.
512  */
516  WriteEmptyXLOG();
517 
518  printf(_("Write-ahead log reset\n"));
519  return 0;
520 }
521 
522 
523 /*
524  * Look at the version string stored in PG_VERSION and decide if this utility
525  * can be run safely or not.
526  *
527  * We don't want to inject pg_control and WAL files that are for a different
528  * major version; that can't do anything good. Note that we don't treat
529  * mismatching version info in pg_control as a reason to bail out, because
530  * recovering from a corrupted pg_control is one of the main reasons for this
531  * program to exist at all. However, PG_VERSION is unlikely to get corrupted,
532  * and if it were it would be easy to fix by hand. So let's make this check
533  * to prevent simple user errors.
534  */
535 static void
537 {
538  const char *ver_file = "PG_VERSION";
539  FILE *ver_fd;
540  char rawline[64];
541 
542  if ((ver_fd = fopen(ver_file, "r")) == NULL)
543  {
544  pg_log_error("could not open file \"%s\" for reading: %m",
545  ver_file);
546  exit(1);
547  }
548 
549  /* version number has to be the first line read */
550  if (!fgets(rawline, sizeof(rawline), ver_fd))
551  {
552  if (!ferror(ver_fd))
553  pg_log_error("unexpected empty file \"%s\"", ver_file);
554  else
555  pg_log_error("could not read file \"%s\": %m", ver_file);
556  exit(1);
557  }
558 
559  /* strip trailing newline and carriage return */
560  (void) pg_strip_crlf(rawline);
561 
562  if (strcmp(rawline, PG_MAJORVERSION) != 0)
563  {
564  pg_log_error("data directory is of wrong version");
565  pg_log_info("File \"%s\" contains \"%s\", which is not compatible with this program's version \"%s\".",
566  ver_file, rawline, PG_MAJORVERSION);
567  exit(1);
568  }
569 
570  fclose(ver_fd);
571 }
572 
573 
574 /*
575  * Try to read the existing pg_control file.
576  *
577  * This routine is also responsible for updating old pg_control versions
578  * to the current format. (Currently we don't do anything of the sort.)
579  */
580 static bool
582 {
583  int fd;
584  int len;
585  char *buffer;
586  pg_crc32c crc;
587 
588  if ((fd = open(XLOG_CONTROL_FILE, O_RDONLY | PG_BINARY, 0)) < 0)
589  {
590  /*
591  * If pg_control is not there at all, or we can't read it, the odds
592  * are we've been handed a bad DataDir path, so give up. User can do
593  * "touch pg_control" to force us to proceed.
594  */
595  pg_log_error("could not open file \"%s\" for reading: %m",
597  if (errno == ENOENT)
598  pg_log_info("If you are sure the data directory path is correct, execute\n"
599  " touch %s\n"
600  "and try again.",
602  exit(1);
603  }
604 
605  /* Use malloc to ensure we have a maxaligned buffer */
606  buffer = (char *) pg_malloc(PG_CONTROL_FILE_SIZE);
607 
608  len = read(fd, buffer, PG_CONTROL_FILE_SIZE);
609  if (len < 0)
610  {
611  pg_log_error("could not read file \"%s\": %m", XLOG_CONTROL_FILE);
612  exit(1);
613  }
614  close(fd);
615 
616  if (len >= sizeof(ControlFileData) &&
617  ((ControlFileData *) buffer)->pg_control_version == PG_CONTROL_VERSION)
618  {
619  /* Check the CRC. */
620  INIT_CRC32C(crc);
621  COMP_CRC32C(crc,
622  buffer,
623  offsetof(ControlFileData, crc));
624  FIN_CRC32C(crc);
625 
626  if (!EQ_CRC32C(crc, ((ControlFileData *) buffer)->crc))
627  {
628  /* We will use the data but treat it as guessed. */
629  pg_log_warning("pg_control exists but has invalid CRC; proceed with caution");
630  guessed = true;
631  }
632 
633  memcpy(&ControlFile, buffer, sizeof(ControlFile));
634 
635  /* return false if WAL segment size is not valid */
636  if (!IsValidWalSegSize(ControlFile.xlog_seg_size))
637  {
638  pg_log_warning(ngettext("pg_control specifies invalid WAL segment size (%d byte); proceed with caution",
639  "pg_control specifies invalid WAL segment size (%d bytes); proceed with caution",
640  ControlFile.xlog_seg_size),
641  ControlFile.xlog_seg_size);
642  return false;
643  }
644 
645  return true;
646  }
647 
648  /* Looks like it's a mess. */
649  pg_log_warning("pg_control exists but is broken or wrong version; ignoring it");
650  return false;
651 }
652 
653 
654 /*
655  * Guess at pg_control values when we can't read the old ones.
656  */
657 static void
659 {
660  uint64 sysidentifier;
661  struct timeval tv;
662 
663  /*
664  * Set up a completely default set of pg_control values.
665  */
666  guessed = true;
667  memset(&ControlFile, 0, sizeof(ControlFile));
668 
671 
672  /*
673  * Create a new unique installation identifier, since we can no longer use
674  * any old XLOG records. See notes in xlog.c about the algorithm.
675  */
676  gettimeofday(&tv, NULL);
677  sysidentifier = ((uint64) tv.tv_sec) << 32;
678  sysidentifier |= ((uint64) tv.tv_usec) << 12;
679  sysidentifier |= getpid() & 0xFFF;
680 
681  ControlFile.system_identifier = sysidentifier;
682 
683  ControlFile.checkPointCopy.redo = SizeOfXLogLongPHD;
684  ControlFile.checkPointCopy.ThisTimeLineID = 1;
685  ControlFile.checkPointCopy.PrevTimeLineID = 1;
686  ControlFile.checkPointCopy.fullPageWrites = false;
687  ControlFile.checkPointCopy.nextFullXid =
691  ControlFile.checkPointCopy.nextMultiOffset = 0;
693  ControlFile.checkPointCopy.oldestXidDB = InvalidOid;
696  ControlFile.checkPointCopy.time = (pg_time_t) time(NULL);
698 
699  ControlFile.state = DB_SHUTDOWNED;
700  ControlFile.time = (pg_time_t) time(NULL);
701  ControlFile.checkPoint = ControlFile.checkPointCopy.redo;
702  ControlFile.unloggedLSN = FirstNormalUnloggedLSN;
703 
704  /* minRecoveryPoint, backupStartPoint and backupEndPoint can be left zero */
705 
706  ControlFile.wal_level = WAL_LEVEL_MINIMAL;
707  ControlFile.wal_log_hints = false;
708  ControlFile.track_commit_timestamp = false;
709  ControlFile.MaxConnections = 100;
710  ControlFile.max_wal_senders = 10;
711  ControlFile.max_worker_processes = 8;
712  ControlFile.max_prepared_xacts = 0;
713  ControlFile.max_locks_per_xact = 64;
714 
715  ControlFile.maxAlign = MAXIMUM_ALIGNOF;
716  ControlFile.floatFormat = FLOATFORMAT_VALUE;
717  ControlFile.blcksz = BLCKSZ;
718  ControlFile.relseg_size = RELSEG_SIZE;
719  ControlFile.xlog_blcksz = XLOG_BLCKSZ;
720  ControlFile.xlog_seg_size = DEFAULT_XLOG_SEG_SIZE;
721  ControlFile.nameDataLen = NAMEDATALEN;
722  ControlFile.indexMaxKeys = INDEX_MAX_KEYS;
724  ControlFile.loblksize = LOBLKSIZE;
725  ControlFile.float8ByVal = FLOAT8PASSBYVAL;
726 
727  /*
728  * XXX eventually, should try to grovel through old XLOG to develop more
729  * accurate values for TimeLineID, nextXID, etc.
730  */
731 }
732 
733 
734 /*
735  * Print the guessed pg_control values when we had to guess.
736  *
737  * NB: this display should be just those fields that will not be
738  * reset by RewriteControlFile().
739  */
740 static void
742 {
743  if (guessed)
744  printf(_("Guessed pg_control values:\n\n"));
745  else
746  printf(_("Current pg_control values:\n\n"));
747 
748  printf(_("pg_control version number: %u\n"),
749  ControlFile.pg_control_version);
750  printf(_("Catalog version number: %u\n"),
751  ControlFile.catalog_version_no);
752  printf(_("Database system identifier: %llu\n"),
753  (unsigned long long) ControlFile.system_identifier);
754  printf(_("Latest checkpoint's TimeLineID: %u\n"),
755  ControlFile.checkPointCopy.ThisTimeLineID);
756  printf(_("Latest checkpoint's full_page_writes: %s\n"),
757  ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off"));
758  printf(_("Latest checkpoint's NextXID: %u:%u\n"),
761  printf(_("Latest checkpoint's NextOID: %u\n"),
762  ControlFile.checkPointCopy.nextOid);
763  printf(_("Latest checkpoint's NextMultiXactId: %u\n"),
764  ControlFile.checkPointCopy.nextMulti);
765  printf(_("Latest checkpoint's NextMultiOffset: %u\n"),
766  ControlFile.checkPointCopy.nextMultiOffset);
767  printf(_("Latest checkpoint's oldestXID: %u\n"),
768  ControlFile.checkPointCopy.oldestXid);
769  printf(_("Latest checkpoint's oldestXID's DB: %u\n"),
770  ControlFile.checkPointCopy.oldestXidDB);
771  printf(_("Latest checkpoint's oldestActiveXID: %u\n"),
772  ControlFile.checkPointCopy.oldestActiveXid);
773  printf(_("Latest checkpoint's oldestMultiXid: %u\n"),
774  ControlFile.checkPointCopy.oldestMulti);
775  printf(_("Latest checkpoint's oldestMulti's DB: %u\n"),
776  ControlFile.checkPointCopy.oldestMultiDB);
777  printf(_("Latest checkpoint's oldestCommitTsXid:%u\n"),
778  ControlFile.checkPointCopy.oldestCommitTsXid);
779  printf(_("Latest checkpoint's newestCommitTsXid:%u\n"),
780  ControlFile.checkPointCopy.newestCommitTsXid);
781  printf(_("Maximum data alignment: %u\n"),
782  ControlFile.maxAlign);
783  /* we don't print floatFormat since can't say much useful about it */
784  printf(_("Database block size: %u\n"),
785  ControlFile.blcksz);
786  printf(_("Blocks per segment of large relation: %u\n"),
787  ControlFile.relseg_size);
788  printf(_("WAL block size: %u\n"),
789  ControlFile.xlog_blcksz);
790  printf(_("Bytes per WAL segment: %u\n"),
791  ControlFile.xlog_seg_size);
792  printf(_("Maximum length of identifiers: %u\n"),
793  ControlFile.nameDataLen);
794  printf(_("Maximum columns in an index: %u\n"),
795  ControlFile.indexMaxKeys);
796  printf(_("Maximum size of a TOAST chunk: %u\n"),
797  ControlFile.toast_max_chunk_size);
798  printf(_("Size of a large-object chunk: %u\n"),
799  ControlFile.loblksize);
800  /* This is no longer configurable, but users may still expect to see it: */
801  printf(_("Date/time type storage: %s\n"),
802  _("64-bit integers"));
803  printf(_("Float8 argument passing: %s\n"),
804  (ControlFile.float8ByVal ? _("by value") : _("by reference")));
805  printf(_("Data page checksum version: %u\n"),
806  ControlFile.data_checksum_version);
807 }
808 
809 
810 /*
811  * Print the values to be changed.
812  */
813 static void
815 {
816  char fname[MAXFNAMELEN];
817 
818  /* This will be always printed in order to keep format same. */
819  printf(_("\n\nValues to be changed:\n\n"));
820 
821  XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
823  printf(_("First log segment after reset: %s\n"), fname);
824 
825  if (set_mxid != 0)
826  {
827  printf(_("NextMultiXactId: %u\n"),
828  ControlFile.checkPointCopy.nextMulti);
829  printf(_("OldestMultiXid: %u\n"),
830  ControlFile.checkPointCopy.oldestMulti);
831  printf(_("OldestMulti's DB: %u\n"),
832  ControlFile.checkPointCopy.oldestMultiDB);
833  }
834 
835  if (set_mxoff != -1)
836  {
837  printf(_("NextMultiOffset: %u\n"),
838  ControlFile.checkPointCopy.nextMultiOffset);
839  }
840 
841  if (set_oid != 0)
842  {
843  printf(_("NextOID: %u\n"),
844  ControlFile.checkPointCopy.nextOid);
845  }
846 
847  if (set_xid != 0)
848  {
849  printf(_("NextXID: %u\n"),
851  printf(_("OldestXID: %u\n"),
852  ControlFile.checkPointCopy.oldestXid);
853  printf(_("OldestXID's DB: %u\n"),
854  ControlFile.checkPointCopy.oldestXidDB);
855  }
856 
857  if (set_xid_epoch != -1)
858  {
859  printf(_("NextXID epoch: %u\n"),
861  }
862 
863  if (set_oldest_commit_ts_xid != 0)
864  {
865  printf(_("oldestCommitTsXid: %u\n"),
866  ControlFile.checkPointCopy.oldestCommitTsXid);
867  }
868  if (set_newest_commit_ts_xid != 0)
869  {
870  printf(_("newestCommitTsXid: %u\n"),
871  ControlFile.checkPointCopy.newestCommitTsXid);
872  }
873 
874  if (set_wal_segsize != 0)
875  {
876  printf(_("Bytes per WAL segment: %u\n"),
877  ControlFile.xlog_seg_size);
878  }
879 }
880 
881 
882 /*
883  * Write out the new pg_control file.
884  */
885 static void
887 {
888  /*
889  * Adjust fields as needed to force an empty XLOG starting at
890  * newXlogSegNo.
891  */
893  ControlFile.checkPointCopy.redo);
894  ControlFile.checkPointCopy.time = (pg_time_t) time(NULL);
895 
896  ControlFile.state = DB_SHUTDOWNED;
897  ControlFile.time = (pg_time_t) time(NULL);
898  ControlFile.checkPoint = ControlFile.checkPointCopy.redo;
899  ControlFile.minRecoveryPoint = 0;
900  ControlFile.minRecoveryPointTLI = 0;
901  ControlFile.backupStartPoint = 0;
902  ControlFile.backupEndPoint = 0;
903  ControlFile.backupEndRequired = false;
904 
905  /*
906  * Force the defaults for max_* settings. The values don't really matter
907  * as long as wal_level='minimal'; the postmaster will reset these fields
908  * anyway at startup.
909  */
910  ControlFile.wal_level = WAL_LEVEL_MINIMAL;
911  ControlFile.wal_log_hints = false;
912  ControlFile.track_commit_timestamp = false;
913  ControlFile.MaxConnections = 100;
914  ControlFile.max_wal_senders = 10;
915  ControlFile.max_worker_processes = 8;
916  ControlFile.max_prepared_xacts = 0;
917  ControlFile.max_locks_per_xact = 64;
918 
919  /* The control file gets flushed here. */
920  update_controlfile(".", &ControlFile, true);
921 }
922 
923 
924 /*
925  * Scan existing XLOG files and determine the highest existing WAL address
926  *
927  * On entry, ControlFile.checkPointCopy.redo and ControlFile.xlog_seg_size
928  * are assumed valid (note that we allow the old xlog seg size to differ
929  * from what we're using). On exit, newXlogSegNo is set to suitable
930  * value for the beginning of replacement WAL (in our seg size).
931  */
932 static void
934 {
935  DIR *xldir;
936  struct dirent *xlde;
937  uint64 segs_per_xlogid;
938  uint64 xlogbytepos;
939 
940  /*
941  * Initialize the max() computation using the last checkpoint address from
942  * old pg_control. Note that for the moment we are working with segment
943  * numbering according to the old xlog seg size.
944  */
945  segs_per_xlogid = (UINT64CONST(0x0000000100000000) / ControlFile.xlog_seg_size);
946  newXlogSegNo = ControlFile.checkPointCopy.redo / ControlFile.xlog_seg_size;
947 
948  /*
949  * Scan the pg_wal directory to find existing WAL segment files. We assume
950  * any present have been used; in most scenarios this should be
951  * conservative, because of xlog.c's attempts to pre-create files.
952  */
953  xldir = opendir(XLOGDIR);
954  if (xldir == NULL)
955  {
956  pg_log_error("could not open directory \"%s\": %m", XLOGDIR);
957  exit(1);
958  }
959 
960  while (errno = 0, (xlde = readdir(xldir)) != NULL)
961  {
962  if (IsXLogFileName(xlde->d_name) ||
964  {
965  unsigned int tli,
966  log,
967  seg;
968  XLogSegNo segno;
969 
970  /*
971  * Note: We don't use XLogFromFileName here, because we want to
972  * use the segment size from the control file, not the size the
973  * pg_resetwal binary was compiled with
974  */
975  sscanf(xlde->d_name, "%08X%08X%08X", &tli, &log, &seg);
976  segno = ((uint64) log) * segs_per_xlogid + seg;
977 
978  /*
979  * Note: we take the max of all files found, regardless of their
980  * timelines. Another possibility would be to ignore files of
981  * timelines other than the target TLI, but this seems safer.
982  * Better too large a result than too small...
983  */
984  if (segno > newXlogSegNo)
985  newXlogSegNo = segno;
986  }
987  }
988 
989  if (errno)
990  {
991  pg_log_error("could not read directory \"%s\": %m", XLOGDIR);
992  exit(1);
993  }
994 
995  if (closedir(xldir))
996  {
997  pg_log_error("could not close directory \"%s\": %m", XLOGDIR);
998  exit(1);
999  }
1000 
1001  /*
1002  * Finally, convert to new xlog seg size, and advance by one to ensure we
1003  * are in virgin territory.
1004  */
1005  xlogbytepos = newXlogSegNo * ControlFile.xlog_seg_size;
1006  newXlogSegNo = (xlogbytepos + ControlFile.xlog_seg_size - 1) / WalSegSz;
1007  newXlogSegNo++;
1008 }
1009 
1010 
1011 /*
1012  * Remove existing XLOG files
1013  */
1014 static void
1016 {
1017  DIR *xldir;
1018  struct dirent *xlde;
1019  char path[MAXPGPATH + sizeof(XLOGDIR)];
1020 
1021  xldir = opendir(XLOGDIR);
1022  if (xldir == NULL)
1023  {
1024  pg_log_error("could not open directory \"%s\": %m", XLOGDIR);
1025  exit(1);
1026  }
1027 
1028  while (errno = 0, (xlde = readdir(xldir)) != NULL)
1029  {
1030  if (IsXLogFileName(xlde->d_name) ||
1032  {
1033  snprintf(path, sizeof(path), "%s/%s", XLOGDIR, xlde->d_name);
1034  if (unlink(path) < 0)
1035  {
1036  pg_log_error("could not delete file \"%s\": %m", path);
1037  exit(1);
1038  }
1039  }
1040  }
1041 
1042  if (errno)
1043  {
1044  pg_log_error("could not read directory \"%s\": %m", XLOGDIR);
1045  exit(1);
1046  }
1047 
1048  if (closedir(xldir))
1049  {
1050  pg_log_error("could not close directory \"%s\": %m", XLOGDIR);
1051  exit(1);
1052  }
1053 }
1054 
1055 
1056 /*
1057  * Remove existing archive status files
1058  */
1059 static void
1061 {
1062 #define ARCHSTATDIR XLOGDIR "/archive_status"
1063 
1064  DIR *xldir;
1065  struct dirent *xlde;
1066  char path[MAXPGPATH + sizeof(ARCHSTATDIR)];
1067 
1068  xldir = opendir(ARCHSTATDIR);
1069  if (xldir == NULL)
1070  {
1071  pg_log_error("could not open directory \"%s\": %m", ARCHSTATDIR);
1072  exit(1);
1073  }
1074 
1075  while (errno = 0, (xlde = readdir(xldir)) != NULL)
1076  {
1077  if (strspn(xlde->d_name, "0123456789ABCDEF") == XLOG_FNAME_LEN &&
1078  (strcmp(xlde->d_name + XLOG_FNAME_LEN, ".ready") == 0 ||
1079  strcmp(xlde->d_name + XLOG_FNAME_LEN, ".done") == 0 ||
1080  strcmp(xlde->d_name + XLOG_FNAME_LEN, ".partial.ready") == 0 ||
1081  strcmp(xlde->d_name + XLOG_FNAME_LEN, ".partial.done") == 0))
1082  {
1083  snprintf(path, sizeof(path), "%s/%s", ARCHSTATDIR, xlde->d_name);
1084  if (unlink(path) < 0)
1085  {
1086  pg_log_error("could not delete file \"%s\": %m", path);
1087  exit(1);
1088  }
1089  }
1090  }
1091 
1092  if (errno)
1093  {
1094  pg_log_error("could not read directory \"%s\": %m", ARCHSTATDIR);
1095  exit(1);
1096  }
1097 
1098  if (closedir(xldir))
1099  {
1100  pg_log_error("could not close directory \"%s\": %m", ARCHSTATDIR);
1101  exit(1);
1102  }
1103 }
1104 
1105 
1106 /*
1107  * Write an empty XLOG file, containing only the checkpoint record
1108  * already set up in ControlFile.
1109  */
1110 static void
1112 {
1113  PGAlignedXLogBlock buffer;
1114  XLogPageHeader page;
1115  XLogLongPageHeader longpage;
1116  XLogRecord *record;
1117  pg_crc32c crc;
1118  char path[MAXPGPATH];
1119  int fd;
1120  int nbytes;
1121  char *recptr;
1122 
1123  memset(buffer.data, 0, XLOG_BLCKSZ);
1124 
1125  /* Set up the XLOG page header */
1126  page = (XLogPageHeader) buffer.data;
1127  page->xlp_magic = XLOG_PAGE_MAGIC;
1128  page->xlp_info = XLP_LONG_HEADER;
1129  page->xlp_tli = ControlFile.checkPointCopy.ThisTimeLineID;
1130  page->xlp_pageaddr = ControlFile.checkPointCopy.redo - SizeOfXLogLongPHD;
1131  longpage = (XLogLongPageHeader) page;
1132  longpage->xlp_sysid = ControlFile.system_identifier;
1133  longpage->xlp_seg_size = WalSegSz;
1134  longpage->xlp_xlog_blcksz = XLOG_BLCKSZ;
1135 
1136  /* Insert the initial checkpoint record */
1137  recptr = (char *) page + SizeOfXLogLongPHD;
1138  record = (XLogRecord *) recptr;
1139  record->xl_prev = 0;
1140  record->xl_xid = InvalidTransactionId;
1143  record->xl_rmid = RM_XLOG_ID;
1144 
1145  recptr += SizeOfXLogRecord;
1146  *(recptr++) = (char) XLR_BLOCK_ID_DATA_SHORT;
1147  *(recptr++) = sizeof(CheckPoint);
1148  memcpy(recptr, &ControlFile.checkPointCopy,
1149  sizeof(CheckPoint));
1150 
1151  INIT_CRC32C(crc);
1152  COMP_CRC32C(crc, ((char *) record) + SizeOfXLogRecord, record->xl_tot_len - SizeOfXLogRecord);
1153  COMP_CRC32C(crc, (char *) record, offsetof(XLogRecord, xl_crc));
1154  FIN_CRC32C(crc);
1155  record->xl_crc = crc;
1156 
1157  /* Write the first page */
1158  XLogFilePath(path, ControlFile.checkPointCopy.ThisTimeLineID,
1160 
1161  unlink(path);
1162 
1163  fd = open(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
1165  if (fd < 0)
1166  {
1167  pg_log_error("could not open file \"%s\": %m", path);
1168  exit(1);
1169  }
1170 
1171  errno = 0;
1172  if (write(fd, buffer.data, XLOG_BLCKSZ) != XLOG_BLCKSZ)
1173  {
1174  /* if write didn't set errno, assume problem is no disk space */
1175  if (errno == 0)
1176  errno = ENOSPC;
1177  pg_log_error("could not write file \"%s\": %m", path);
1178  exit(1);
1179  }
1180 
1181  /* Fill the rest of the file with zeroes */
1182  memset(buffer.data, 0, XLOG_BLCKSZ);
1183  for (nbytes = XLOG_BLCKSZ; nbytes < WalSegSz; nbytes += XLOG_BLCKSZ)
1184  {
1185  errno = 0;
1186  if (write(fd, buffer.data, XLOG_BLCKSZ) != XLOG_BLCKSZ)
1187  {
1188  if (errno == 0)
1189  errno = ENOSPC;
1190  pg_log_error("could not write file \"%s\": %m", path);
1191  exit(1);
1192  }
1193  }
1194 
1195  if (fsync(fd) != 0)
1196  {
1197  pg_log_error("fsync error: %m");
1198  exit(1);
1199  }
1200 
1201  close(fd);
1202 }
1203 
1204 
1205 static void
1206 usage(void)
1207 {
1208  printf(_("%s resets the PostgreSQL write-ahead log.\n\n"), progname);
1209  printf(_("Usage:\n %s [OPTION]... DATADIR\n\n"), progname);
1210  printf(_("Options:\n"));
1211  printf(_(" -c, --commit-timestamp-ids=XID,XID\n"
1212  " set oldest and newest transactions bearing\n"
1213  " commit timestamp (zero means no change)\n"));
1214  printf(_(" [-D, --pgdata=]DATADIR data directory\n"));
1215  printf(_(" -e, --epoch=XIDEPOCH set next transaction ID epoch\n"));
1216  printf(_(" -f, --force force update to be done\n"));
1217  printf(_(" -l, --next-wal-file=WALFILE set minimum starting location for new WAL\n"));
1218  printf(_(" -m, --multixact-ids=MXID,MXID set next and oldest multitransaction ID\n"));
1219  printf(_(" -n, --dry-run no update, just show what would be done\n"));
1220  printf(_(" -o, --next-oid=OID set next OID\n"));
1221  printf(_(" -O, --multixact-offset=OFFSET set next multitransaction offset\n"));
1222  printf(_(" -V, --version output version information, then exit\n"));
1223  printf(_(" -x, --next-transaction-id=XID set next transaction ID\n"));
1224  printf(_(" --wal-segsize=SIZE size of WAL segments, in megabytes\n"));
1225  printf(_(" -?, --help show this help, then exit\n"));
1226  printf(_("\nReport bugs to <pgsql-bugs@lists.postgresql.org>.\n"));
1227 }
static void PrintControlValues(bool guessed)
Definition: pg_resetwal.c:741
#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:182
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:181
int64 pg_time_t
Definition: pgtime.h:23
#define TOAST_MAX_CHUNK_SIZE
Definition: heaptoast.h:84
uint32 MultiXactOffset
Definition: c.h:526
static void usage(void)
Definition: pg_resetwal.c:1206
int pg_strip_crlf(char *str)
Definition: string.c:105
static TransactionId set_xid
Definition: pg_resetwal.c:67
pg_time_t time
Definition: pg_control.h:128
uint32 TransactionId
Definition: c.h:514
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:200
int max_worker_processes
Definition: pg_control.h:179
#define pg_log_error(...)
Definition: logging.h:79
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition: getopt_long.c:57
void get_restricted_token(void)
uint32 pg_crc32c
Definition: pg_crc32c.h:38
TransactionId oldestActiveXid
Definition: pg_control.h:63
static void PrintNewControlValues(void)
Definition: pg_resetwal.c:814
void pg_logging_init(const char *argv0)
Definition: logging.c:39
uint32 nameDataLen
Definition: pg_control.h:211
MultiXactId oldestMulti
Definition: pg_control.h:49
static void FindEndOfXLOG(void)
Definition: pg_resetwal.c:933
#define DEFAULT_XLOG_SEG_SIZE
TimeLineID PrevTimeLineID
Definition: pg_control.h:40
int closedir(DIR *)
Definition: dirent.c:113
static void WriteEmptyXLOG(void)
Definition: pg_resetwal.c:1111
#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:70
RmgrId xl_rmid
Definition: xlogrecord.h:47
XLogPageHeaderData * XLogPageHeader
Definition: xlog_internal.h:57
uint32 pg_control_version
Definition: pg_control.h:121
#define printf(...)
Definition: port.h:198
CheckPoint checkPointCopy
Definition: pg_control.h:131
uint32 xlog_blcksz
Definition: pg_control.h:208
TransactionId oldestXid
Definition: pg_control.h:47
unsigned int Oid
Definition: postgres_ext.h:31
#define fprintf
Definition: port.h:196
Definition: dirent.h:9
pg_time_t time
Definition: pg_control.h:51
static void CheckDataVersion(void)
Definition: pg_resetwal.c:536
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1222
static bool ReadControlFile(void)
Definition: pg_resetwal.c:581
#define XidFromFullTransactionId(x)
Definition: transam.h:48
static TransactionId set_newest_commit_ts_xid
Definition: pg_resetwal.c:69
static void KillExistingXLOG(void)
Definition: pg_resetwal.c:1015
#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:63
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:1060
#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:68
#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:41
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
#define InvalidTransactionId
Definition: transam.h:31
unsigned int uint32
Definition: c.h:359
#define FirstBootstrapObjectId
Definition: transam.h:140
#define FirstMultiXactId
Definition: multixact.h:24
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:1134
TransactionId newestCommitTsXid
Definition: pg_control.h:54
#define PG_TEXTDOMAIN(domain)
Definition: c.h:1166
#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:75
TransactionId MultiXactId
Definition: c.h:524
#define XLogSegNoOffsetToRecPtr(segno, offset, wal_segsz_bytes, dest)
#define FLOAT8PASSBYVAL
Definition: c.h:497
bool track_commit_timestamp
Definition: pg_control.h:183
#define XLP_LONG_HEADER
Definition: xlog_internal.h:79
FullTransactionId nextFullXid
Definition: pg_control.h:43
Oid oldestXidDB
Definition: pg_control.h:48
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: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:886
static MultiXactOffset set_mxoff
Definition: pg_resetwal.c:72
uint32 catalog_version_no
Definition: pg_control.h:122
static FullTransactionId FullTransactionIdFromEpochAndXid(uint32 epoch, TransactionId xid)
Definition: transam.h:65
struct dirent * readdir(DIR *)
Definition: dirent.c:77
#define PG_CONTROL_FILE_SIZE
Definition: pg_control.h:248
struct CheckPoint CheckPoint
#define XLR_BLOCK_ID_DATA_SHORT
Definition: xlogrecord.h:223
#define XLogFilePath(path, tli, logSegNo, wal_segsz_bytes)
TransactionId xl_xid
Definition: xlogrecord.h:44
static XLogSegNo newXlogSegNo
Definition: pg_resetwal.c:63
bool GetDataDirectoryCreatePerm(const char *dataDir)
static void GuessControlValues(void)
Definition: pg_resetwal.c:658
static uint32 minXlogTli
Definition: pg_resetwal.c:73
#define IsPartialXLogFileName(fname)
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
void set_pglocale_pgservice(const char *argv0, const char *app)
Definition: exec.c:565
#define ARCHSTATDIR
char * optarg
Definition: getopt.c:52
char * DataDir
Definition: globals.c:62
#define XLOG_FNAME_LEN
char d_name[MAX_PATH]
Definition: dirent.h:14
#define close(a)
Definition: win32.h:12
#define pg_log_warning(...)
Definition: pgfnames.c:24
#define FLOATFORMAT_VALUE
Definition: pg_control.h:199
#define COMP_CRC32C(crc, data, len)
Definition: pg_crc32c.h:89
char data[XLOG_BLCKSZ]
Definition: c.h:1099
#define snprintf
Definition: port.h:192
#define FIN_CRC32C(crc)
Definition: pg_crc32c.h:94
#define _(x)
Definition: elog.c:87
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: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:662
#define pg_log_info(...)
Definition: logging.h:87
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:166
static uint32 set_xid_epoch
Definition: pg_resetwal.c:66
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:72