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