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