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