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