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 <locale.h>
43 #include <sys/stat.h>
44 #include <sys/time.h>
45 #include <time.h>
46 #include <unistd.h>
47 
48 #include "access/transam.h"
49 #include "access/tuptoaster.h"
50 #include "access/multixact.h"
51 #include "access/xlog.h"
52 #include "access/xlog_internal.h"
53 #include "catalog/catversion.h"
54 #include "catalog/pg_control.h"
55 #include "common/fe_memutils.h"
57 #include "storage/large_object.h"
58 #include "pg_getopt.h"
59 
60 
61 static ControlFileData ControlFile; /* pg_control values */
62 static XLogSegNo newXlogSegNo; /* new XLOG segment # */
63 static bool guessed = false; /* T if we had to guess at any values */
64 static const char *progname;
65 static uint32 set_xid_epoch = (uint32) -1;
69 static Oid set_oid = 0;
70 static MultiXactId set_mxid = 0;
72 static uint32 minXlogTli = 0;
74 
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  /*
324  * Check for a postmaster lock file --- if there is one, refuse to
325  * proceed, on grounds we might be interfering with a live installation.
326  */
327  if ((fd = open("postmaster.pid", O_RDONLY, 0)) < 0)
328  {
329  if (errno != ENOENT)
330  {
331  fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
332  progname, "postmaster.pid", strerror(errno));
333  exit(1);
334  }
335  }
336  else
337  {
338  fprintf(stderr, _("%s: lock file \"%s\" exists\n"
339  "Is a server running? If not, delete the lock file and try again.\n"),
340  progname, "postmaster.pid");
341  exit(1);
342  }
343 
344  /*
345  * Attempt to read the existing pg_control file
346  */
347  if (!ReadControlFile())
349 
350  /*
351  * Also look at existing segment files to set up newXlogSegNo
352  */
353  FindEndOfXLOG();
354 
355  /*
356  * If we're not going to proceed with the reset, print the current control
357  * file parameters.
358  */
359  if ((guessed && !force) || noupdate)
361 
362  /*
363  * Adjust fields if required by switches. (Do this now so that printout,
364  * if any, includes these values.)
365  */
366  if (set_xid_epoch != -1)
368 
369  if (set_xid != 0)
370  {
371  ControlFile.checkPointCopy.nextXid = set_xid;
372 
373  /*
374  * For the moment, just set oldestXid to a value that will force
375  * immediate autovacuum-for-wraparound. It's not clear whether adding
376  * user control of this is useful, so let's just do something that's
377  * reasonably safe. The magic constant here corresponds to the
378  * maximum allowed value of autovacuum_freeze_max_age.
379  */
380  ControlFile.checkPointCopy.oldestXid = set_xid - 2000000000;
383  ControlFile.checkPointCopy.oldestXidDB = InvalidOid;
384  }
385 
386  if (set_oldest_commit_ts_xid != 0)
388  if (set_newest_commit_ts_xid != 0)
390 
391  if (set_oid != 0)
392  ControlFile.checkPointCopy.nextOid = set_oid;
393 
394  if (set_mxid != 0)
395  {
396  ControlFile.checkPointCopy.nextMulti = set_mxid;
397 
398  ControlFile.checkPointCopy.oldestMulti = set_oldestmxid;
399  if (ControlFile.checkPointCopy.oldestMulti < FirstMultiXactId)
402  }
403 
404  if (set_mxoff != -1)
406 
407  if (minXlogTli > ControlFile.checkPointCopy.ThisTimeLineID)
408  {
411  }
412 
415 
416  /*
417  * If we had to guess anything, and -f was not given, just print the
418  * guessed values and exit. Also print if -n is given.
419  */
420  if ((guessed && !force) || noupdate)
421  {
423  if (!noupdate)
424  {
425  printf(_("\nIf these values seem acceptable, use -f to force reset.\n"));
426  exit(1);
427  }
428  else
429  exit(0);
430  }
431 
432  /*
433  * Don't reset from a dirty pg_control without -f, either.
434  */
435  if (ControlFile.state != DB_SHUTDOWNED && !force)
436  {
437  printf(_("The database server was not shut down cleanly.\n"
438  "Resetting the transaction log might cause data to be lost.\n"
439  "If you want to proceed anyway, use -f to force reset.\n"));
440  exit(1);
441  }
442 
443  /*
444  * Else, do the dirty deed.
445  */
449  WriteEmptyXLOG();
450 
451  printf(_("Transaction log reset\n"));
452  return 0;
453 }
454 
455 
456 /*
457  * Try to read the existing pg_control file.
458  *
459  * This routine is also responsible for updating old pg_control versions
460  * to the current format. (Currently we don't do anything of the sort.)
461  */
462 static bool
464 {
465  int fd;
466  int len;
467  char *buffer;
468  pg_crc32c crc;
469 
470  if ((fd = open(XLOG_CONTROL_FILE, O_RDONLY | PG_BINARY, 0)) < 0)
471  {
472  /*
473  * If pg_control is not there at all, or we can't read it, the odds
474  * are we've been handed a bad DataDir path, so give up. User can do
475  * "touch pg_control" to force us to proceed.
476  */
477  fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
479  if (errno == ENOENT)
480  fprintf(stderr, _("If you are sure the data directory path is correct, execute\n"
481  " touch %s\n"
482  "and try again.\n"),
484  exit(1);
485  }
486 
487  /* Use malloc to ensure we have a maxaligned buffer */
488  buffer = (char *) pg_malloc(PG_CONTROL_SIZE);
489 
490  len = read(fd, buffer, PG_CONTROL_SIZE);
491  if (len < 0)
492  {
493  fprintf(stderr, _("%s: could not read file \"%s\": %s\n"),
495  exit(1);
496  }
497  close(fd);
498 
499  if (len >= sizeof(ControlFileData) &&
500  ((ControlFileData *) buffer)->pg_control_version == PG_CONTROL_VERSION)
501  {
502  /* Check the CRC. */
503  INIT_CRC32C(crc);
504  COMP_CRC32C(crc,
505  buffer,
506  offsetof(ControlFileData, crc));
507  FIN_CRC32C(crc);
508 
509  if (EQ_CRC32C(crc, ((ControlFileData *) buffer)->crc))
510  {
511  /* Valid data... */
512  memcpy(&ControlFile, buffer, sizeof(ControlFile));
513  return true;
514  }
515 
516  fprintf(stderr, _("%s: pg_control exists but has invalid CRC; proceed with caution\n"),
517  progname);
518  /* We will use the data anyway, but treat it as guessed. */
519  memcpy(&ControlFile, buffer, sizeof(ControlFile));
520  guessed = true;
521  return true;
522  }
523 
524  /* Looks like it's a mess. */
525  fprintf(stderr, _("%s: pg_control exists but is broken or unknown version; ignoring it\n"),
526  progname);
527  return false;
528 }
529 
530 
531 /*
532  * Guess at pg_control values when we can't read the old ones.
533  */
534 static void
536 {
537  uint64 sysidentifier;
538  struct timeval tv;
539 
540  /*
541  * Set up a completely default set of pg_control values.
542  */
543  guessed = true;
544  memset(&ControlFile, 0, sizeof(ControlFile));
545 
548 
549  /*
550  * Create a new unique installation identifier, since we can no longer use
551  * any old XLOG records. See notes in xlog.c about the algorithm.
552  */
553  gettimeofday(&tv, NULL);
554  sysidentifier = ((uint64) tv.tv_sec) << 32;
555  sysidentifier |= ((uint64) tv.tv_usec) << 12;
556  sysidentifier |= getpid() & 0xFFF;
557 
558  ControlFile.system_identifier = sysidentifier;
559 
560  ControlFile.checkPointCopy.redo = SizeOfXLogLongPHD;
561  ControlFile.checkPointCopy.ThisTimeLineID = 1;
562  ControlFile.checkPointCopy.PrevTimeLineID = 1;
563  ControlFile.checkPointCopy.fullPageWrites = false;
564  ControlFile.checkPointCopy.nextXidEpoch = 0;
568  ControlFile.checkPointCopy.nextMultiOffset = 0;
570  ControlFile.checkPointCopy.oldestXidDB = InvalidOid;
573  ControlFile.checkPointCopy.time = (pg_time_t) time(NULL);
575 
576  ControlFile.state = DB_SHUTDOWNED;
577  ControlFile.time = (pg_time_t) time(NULL);
578  ControlFile.checkPoint = ControlFile.checkPointCopy.redo;
579  ControlFile.unloggedLSN = 1;
580 
581  /* minRecoveryPoint, backupStartPoint and backupEndPoint can be left zero */
582 
583  ControlFile.wal_level = WAL_LEVEL_MINIMAL;
584  ControlFile.wal_log_hints = false;
585  ControlFile.track_commit_timestamp = false;
586  ControlFile.MaxConnections = 100;
587  ControlFile.max_worker_processes = 8;
588  ControlFile.max_prepared_xacts = 0;
589  ControlFile.max_locks_per_xact = 64;
590 
591  ControlFile.maxAlign = MAXIMUM_ALIGNOF;
592  ControlFile.floatFormat = FLOATFORMAT_VALUE;
593  ControlFile.blcksz = BLCKSZ;
594  ControlFile.relseg_size = RELSEG_SIZE;
595  ControlFile.xlog_blcksz = XLOG_BLCKSZ;
596  ControlFile.xlog_seg_size = XLOG_SEG_SIZE;
597  ControlFile.nameDataLen = NAMEDATALEN;
598  ControlFile.indexMaxKeys = INDEX_MAX_KEYS;
600  ControlFile.loblksize = LOBLKSIZE;
601 #ifdef HAVE_INT64_TIMESTAMP
602  ControlFile.enableIntTimes = true;
603 #else
604  ControlFile.enableIntTimes = false;
605 #endif
606  ControlFile.float4ByVal = FLOAT4PASSBYVAL;
607  ControlFile.float8ByVal = FLOAT8PASSBYVAL;
608 
609  /*
610  * XXX eventually, should try to grovel through old XLOG to develop more
611  * accurate values for TimeLineID, nextXID, etc.
612  */
613 }
614 
615 
616 /*
617  * Print the guessed pg_control values when we had to guess.
618  *
619  * NB: this display should be just those fields that will not be
620  * reset by RewriteControlFile().
621  */
622 static void
624 {
625  char sysident_str[32];
626 
627  if (guessed)
628  printf(_("Guessed pg_control values:\n\n"));
629  else
630  printf(_("Current pg_control values:\n\n"));
631 
632  /*
633  * Format system_identifier separately to keep platform-dependent format
634  * code out of the translatable message string.
635  */
636  snprintf(sysident_str, sizeof(sysident_str), UINT64_FORMAT,
637  ControlFile.system_identifier);
638 
639  printf(_("pg_control version number: %u\n"),
640  ControlFile.pg_control_version);
641  printf(_("Catalog version number: %u\n"),
642  ControlFile.catalog_version_no);
643  printf(_("Database system identifier: %s\n"),
644  sysident_str);
645  printf(_("Latest checkpoint's TimeLineID: %u\n"),
646  ControlFile.checkPointCopy.ThisTimeLineID);
647  printf(_("Latest checkpoint's full_page_writes: %s\n"),
648  ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off"));
649  printf(_("Latest checkpoint's NextXID: %u:%u\n"),
650  ControlFile.checkPointCopy.nextXidEpoch,
651  ControlFile.checkPointCopy.nextXid);
652  printf(_("Latest checkpoint's NextOID: %u\n"),
653  ControlFile.checkPointCopy.nextOid);
654  printf(_("Latest checkpoint's NextMultiXactId: %u\n"),
655  ControlFile.checkPointCopy.nextMulti);
656  printf(_("Latest checkpoint's NextMultiOffset: %u\n"),
657  ControlFile.checkPointCopy.nextMultiOffset);
658  printf(_("Latest checkpoint's oldestXID: %u\n"),
659  ControlFile.checkPointCopy.oldestXid);
660  printf(_("Latest checkpoint's oldestXID's DB: %u\n"),
661  ControlFile.checkPointCopy.oldestXidDB);
662  printf(_("Latest checkpoint's oldestActiveXID: %u\n"),
663  ControlFile.checkPointCopy.oldestActiveXid);
664  printf(_("Latest checkpoint's oldestMultiXid: %u\n"),
665  ControlFile.checkPointCopy.oldestMulti);
666  printf(_("Latest checkpoint's oldestMulti's DB: %u\n"),
667  ControlFile.checkPointCopy.oldestMultiDB);
668  printf(_("Latest checkpoint's oldestCommitTsXid:%u\n"),
669  ControlFile.checkPointCopy.oldestCommitTsXid);
670  printf(_("Latest checkpoint's newestCommitTsXid:%u\n"),
671  ControlFile.checkPointCopy.newestCommitTsXid);
672  printf(_("Maximum data alignment: %u\n"),
673  ControlFile.maxAlign);
674  /* we don't print floatFormat since can't say much useful about it */
675  printf(_("Database block size: %u\n"),
676  ControlFile.blcksz);
677  printf(_("Blocks per segment of large relation: %u\n"),
678  ControlFile.relseg_size);
679  printf(_("WAL block size: %u\n"),
680  ControlFile.xlog_blcksz);
681  printf(_("Bytes per WAL segment: %u\n"),
682  ControlFile.xlog_seg_size);
683  printf(_("Maximum length of identifiers: %u\n"),
684  ControlFile.nameDataLen);
685  printf(_("Maximum columns in an index: %u\n"),
686  ControlFile.indexMaxKeys);
687  printf(_("Maximum size of a TOAST chunk: %u\n"),
688  ControlFile.toast_max_chunk_size);
689  printf(_("Size of a large-object chunk: %u\n"),
690  ControlFile.loblksize);
691  printf(_("Date/time type storage: %s\n"),
692  (ControlFile.enableIntTimes ? _("64-bit integers") : _("floating-point numbers")));
693  printf(_("Float4 argument passing: %s\n"),
694  (ControlFile.float4ByVal ? _("by value") : _("by reference")));
695  printf(_("Float8 argument passing: %s\n"),
696  (ControlFile.float8ByVal ? _("by value") : _("by reference")));
697  printf(_("Data page checksum version: %u\n"),
698  ControlFile.data_checksum_version);
699 }
700 
701 
702 /*
703  * Print the values to be changed.
704  */
705 static void
707 {
708  char fname[MAXFNAMELEN];
709 
710  /* This will be always printed in order to keep format same. */
711  printf(_("\n\nValues to be changed:\n\n"));
712 
714  printf(_("First log segment after reset: %s\n"), fname);
715 
716  if (set_mxid != 0)
717  {
718  printf(_("NextMultiXactId: %u\n"),
719  ControlFile.checkPointCopy.nextMulti);
720  printf(_("OldestMultiXid: %u\n"),
721  ControlFile.checkPointCopy.oldestMulti);
722  printf(_("OldestMulti's DB: %u\n"),
723  ControlFile.checkPointCopy.oldestMultiDB);
724  }
725 
726  if (set_mxoff != -1)
727  {
728  printf(_("NextMultiOffset: %u\n"),
729  ControlFile.checkPointCopy.nextMultiOffset);
730  }
731 
732  if (set_oid != 0)
733  {
734  printf(_("NextOID: %u\n"),
735  ControlFile.checkPointCopy.nextOid);
736  }
737 
738  if (set_xid != 0)
739  {
740  printf(_("NextXID: %u\n"),
741  ControlFile.checkPointCopy.nextXid);
742  printf(_("OldestXID: %u\n"),
743  ControlFile.checkPointCopy.oldestXid);
744  printf(_("OldestXID's DB: %u\n"),
745  ControlFile.checkPointCopy.oldestXidDB);
746  }
747 
748  if (set_xid_epoch != -1)
749  {
750  printf(_("NextXID epoch: %u\n"),
751  ControlFile.checkPointCopy.nextXidEpoch);
752  }
753 
754  if (set_oldest_commit_ts_xid != 0)
755  {
756  printf(_("oldestCommitTsXid: %u\n"),
757  ControlFile.checkPointCopy.oldestCommitTsXid);
758  }
759  if (set_newest_commit_ts_xid != 0)
760  {
761  printf(_("newestCommitTsXid: %u\n"),
762  ControlFile.checkPointCopy.newestCommitTsXid);
763  }
764 }
765 
766 
767 /*
768  * Write out the new pg_control file.
769  */
770 static void
772 {
773  int fd;
774  char buffer[PG_CONTROL_SIZE]; /* need not be aligned */
775 
776  /*
777  * Adjust fields as needed to force an empty XLOG starting at
778  * newXlogSegNo.
779  */
781  ControlFile.checkPointCopy.redo);
782  ControlFile.checkPointCopy.time = (pg_time_t) time(NULL);
783 
784  ControlFile.state = DB_SHUTDOWNED;
785  ControlFile.time = (pg_time_t) time(NULL);
786  ControlFile.checkPoint = ControlFile.checkPointCopy.redo;
787  ControlFile.prevCheckPoint = 0;
788  ControlFile.minRecoveryPoint = 0;
789  ControlFile.minRecoveryPointTLI = 0;
790  ControlFile.backupStartPoint = 0;
791  ControlFile.backupEndPoint = 0;
792  ControlFile.backupEndRequired = false;
793 
794  /*
795  * Force the defaults for max_* settings. The values don't really matter
796  * as long as wal_level='minimal'; the postmaster will reset these fields
797  * anyway at startup.
798  */
799  ControlFile.wal_level = WAL_LEVEL_MINIMAL;
800  ControlFile.wal_log_hints = false;
801  ControlFile.track_commit_timestamp = false;
802  ControlFile.MaxConnections = 100;
803  ControlFile.max_worker_processes = 8;
804  ControlFile.max_prepared_xacts = 0;
805  ControlFile.max_locks_per_xact = 64;
806 
807  /* Now we can force the recorded xlog seg size to the right thing. */
808  ControlFile.xlog_seg_size = XLogSegSize;
809 
810  /* Contents are protected with a CRC */
811  INIT_CRC32C(ControlFile.crc);
812  COMP_CRC32C(ControlFile.crc,
813  (char *) &ControlFile,
814  offsetof(ControlFileData, crc));
815  FIN_CRC32C(ControlFile.crc);
816 
817  /*
818  * We write out PG_CONTROL_SIZE bytes into pg_control, zero-padding the
819  * excess over sizeof(ControlFileData). This reduces the odds of
820  * premature-EOF errors when reading pg_control. We'll still fail when we
821  * check the contents of the file, but hopefully with a more specific
822  * error than "couldn't read pg_control".
823  */
824  if (sizeof(ControlFileData) > PG_CONTROL_SIZE)
825  {
826  fprintf(stderr,
827  _("%s: internal error -- sizeof(ControlFileData) is too large ... fix PG_CONTROL_SIZE\n"),
828  progname);
829  exit(1);
830  }
831 
832  memset(buffer, 0, PG_CONTROL_SIZE);
833  memcpy(buffer, &ControlFile, sizeof(ControlFileData));
834 
836 
837  fd = open(XLOG_CONTROL_FILE,
838  O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
839  S_IRUSR | S_IWUSR);
840  if (fd < 0)
841  {
842  fprintf(stderr, _("%s: could not create pg_control file: %s\n"),
843  progname, strerror(errno));
844  exit(1);
845  }
846 
847  errno = 0;
848  if (write(fd, buffer, PG_CONTROL_SIZE) != PG_CONTROL_SIZE)
849  {
850  /* if write didn't set errno, assume problem is no disk space */
851  if (errno == 0)
852  errno = ENOSPC;
853  fprintf(stderr, _("%s: could not write pg_control file: %s\n"),
854  progname, strerror(errno));
855  exit(1);
856  }
857 
858  if (fsync(fd) != 0)
859  {
860  fprintf(stderr, _("%s: fsync error: %s\n"), progname, strerror(errno));
861  exit(1);
862  }
863 
864  close(fd);
865 }
866 
867 
868 /*
869  * Scan existing XLOG files and determine the highest existing WAL address
870  *
871  * On entry, ControlFile.checkPointCopy.redo and ControlFile.xlog_seg_size
872  * are assumed valid (note that we allow the old xlog seg size to differ
873  * from what we're using). On exit, newXlogId and newXlogSeg are set to
874  * suitable values for the beginning of replacement WAL (in our seg size).
875  */
876 static void
878 {
879  DIR *xldir;
880  struct dirent *xlde;
881  uint64 segs_per_xlogid;
882  uint64 xlogbytepos;
883 
884  /*
885  * Initialize the max() computation using the last checkpoint address from
886  * old pg_control. Note that for the moment we are working with segment
887  * numbering according to the old xlog seg size.
888  */
889  segs_per_xlogid = (UINT64CONST(0x0000000100000000) / ControlFile.xlog_seg_size);
890  newXlogSegNo = ControlFile.checkPointCopy.redo / ControlFile.xlog_seg_size;
891 
892  /*
893  * Scan the pg_wal directory to find existing WAL segment files. We
894  * assume any present have been used; in most scenarios this should be
895  * conservative, because of xlog.c's attempts to pre-create files.
896  */
897  xldir = opendir(XLOGDIR);
898  if (xldir == NULL)
899  {
900  fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
901  progname, XLOGDIR, strerror(errno));
902  exit(1);
903  }
904 
905  while (errno = 0, (xlde = readdir(xldir)) != NULL)
906  {
907  if (IsXLogFileName(xlde->d_name) ||
909  {
910  unsigned int tli,
911  log,
912  seg;
913  XLogSegNo segno;
914 
915  /*
916  * Note: We don't use XLogFromFileName here, because we want to
917  * use the segment size from the control file, not the size the
918  * pg_resetwal binary was compiled with
919  */
920  sscanf(xlde->d_name, "%08X%08X%08X", &tli, &log, &seg);
921  segno = ((uint64) log) * segs_per_xlogid + seg;
922 
923  /*
924  * Note: we take the max of all files found, regardless of their
925  * timelines. Another possibility would be to ignore files of
926  * timelines other than the target TLI, but this seems safer.
927  * Better too large a result than too small...
928  */
929  if (segno > newXlogSegNo)
930  newXlogSegNo = segno;
931  }
932  }
933 
934  if (errno)
935  {
936  fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
937  progname, XLOGDIR, strerror(errno));
938  exit(1);
939  }
940 
941  if (closedir(xldir))
942  {
943  fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
944  progname, XLOGDIR, strerror(errno));
945  exit(1);
946  }
947 
948  /*
949  * Finally, convert to new xlog seg size, and advance by one to ensure we
950  * are in virgin territory.
951  */
952  xlogbytepos = newXlogSegNo * ControlFile.xlog_seg_size;
953  newXlogSegNo = (xlogbytepos + XLogSegSize - 1) / XLogSegSize;
954  newXlogSegNo++;
955 }
956 
957 
958 /*
959  * Remove existing XLOG files
960  */
961 static void
963 {
964  DIR *xldir;
965  struct dirent *xlde;
966  char path[MAXPGPATH];
967 
968  xldir = opendir(XLOGDIR);
969  if (xldir == NULL)
970  {
971  fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
972  progname, XLOGDIR, strerror(errno));
973  exit(1);
974  }
975 
976  while (errno = 0, (xlde = readdir(xldir)) != NULL)
977  {
978  if (IsXLogFileName(xlde->d_name) ||
980  {
981  snprintf(path, MAXPGPATH, "%s/%s", XLOGDIR, xlde->d_name);
982  if (unlink(path) < 0)
983  {
984  fprintf(stderr, _("%s: could not delete file \"%s\": %s\n"),
985  progname, path, strerror(errno));
986  exit(1);
987  }
988  }
989  }
990 
991  if (errno)
992  {
993  fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
994  progname, XLOGDIR, strerror(errno));
995  exit(1);
996  }
997 
998  if (closedir(xldir))
999  {
1000  fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
1001  progname, XLOGDIR, strerror(errno));
1002  exit(1);
1003  }
1004 }
1005 
1006 
1007 /*
1008  * Remove existing archive status files
1009  */
1010 static void
1012 {
1013  DIR *xldir;
1014  struct dirent *xlde;
1015  char path[MAXPGPATH];
1016 
1017 #define ARCHSTATDIR XLOGDIR "/archive_status"
1018 
1019  xldir = opendir(ARCHSTATDIR);
1020  if (xldir == NULL)
1021  {
1022  fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
1023  progname, ARCHSTATDIR, strerror(errno));
1024  exit(1);
1025  }
1026 
1027  while (errno = 0, (xlde = readdir(xldir)) != NULL)
1028  {
1029  if (strspn(xlde->d_name, "0123456789ABCDEF") == XLOG_FNAME_LEN &&
1030  (strcmp(xlde->d_name + XLOG_FNAME_LEN, ".ready") == 0 ||
1031  strcmp(xlde->d_name + XLOG_FNAME_LEN, ".done") == 0 ||
1032  strcmp(xlde->d_name + XLOG_FNAME_LEN, ".partial.ready") == 0 ||
1033  strcmp(xlde->d_name + XLOG_FNAME_LEN, ".partial.done") == 0))
1034  {
1035  snprintf(path, MAXPGPATH, "%s/%s", ARCHSTATDIR, xlde->d_name);
1036  if (unlink(path) < 0)
1037  {
1038  fprintf(stderr, _("%s: could not delete file \"%s\": %s\n"),
1039  progname, path, strerror(errno));
1040  exit(1);
1041  }
1042  }
1043  }
1044 
1045  if (errno)
1046  {
1047  fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
1048  progname, ARCHSTATDIR, strerror(errno));
1049  exit(1);
1050  }
1051 
1052  if (closedir(xldir))
1053  {
1054  fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
1055  progname, ARCHSTATDIR, strerror(errno));
1056  exit(1);
1057  }
1058 }
1059 
1060 
1061 /*
1062  * Write an empty XLOG file, containing only the checkpoint record
1063  * already set up in ControlFile.
1064  */
1065 static void
1067 {
1068  char *buffer;
1069  XLogPageHeader page;
1070  XLogLongPageHeader longpage;
1071  XLogRecord *record;
1072  pg_crc32c crc;
1073  char path[MAXPGPATH];
1074  int fd;
1075  int nbytes;
1076  char *recptr;
1077 
1078  /* Use malloc() to ensure buffer is MAXALIGNED */
1079  buffer = (char *) pg_malloc(XLOG_BLCKSZ);
1080  page = (XLogPageHeader) buffer;
1081  memset(buffer, 0, XLOG_BLCKSZ);
1082 
1083  /* Set up the XLOG page header */
1084  page->xlp_magic = XLOG_PAGE_MAGIC;
1085  page->xlp_info = XLP_LONG_HEADER;
1086  page->xlp_tli = ControlFile.checkPointCopy.ThisTimeLineID;
1087  page->xlp_pageaddr = ControlFile.checkPointCopy.redo - SizeOfXLogLongPHD;
1088  longpage = (XLogLongPageHeader) page;
1089  longpage->xlp_sysid = ControlFile.system_identifier;
1090  longpage->xlp_seg_size = XLogSegSize;
1091  longpage->xlp_xlog_blcksz = XLOG_BLCKSZ;
1092 
1093  /* Insert the initial checkpoint record */
1094  recptr = (char *) page + SizeOfXLogLongPHD;
1095  record = (XLogRecord *) recptr;
1096  record->xl_prev = 0;
1097  record->xl_xid = InvalidTransactionId;
1100  record->xl_rmid = RM_XLOG_ID;
1101 
1102  recptr += SizeOfXLogRecord;
1103  *(recptr++) = XLR_BLOCK_ID_DATA_SHORT;
1104  *(recptr++) = sizeof(CheckPoint);
1105  memcpy(recptr, &ControlFile.checkPointCopy,
1106  sizeof(CheckPoint));
1107 
1108  INIT_CRC32C(crc);
1109  COMP_CRC32C(crc, ((char *) record) + SizeOfXLogRecord, record->xl_tot_len - SizeOfXLogRecord);
1110  COMP_CRC32C(crc, (char *) record, offsetof(XLogRecord, xl_crc));
1111  FIN_CRC32C(crc);
1112  record->xl_crc = crc;
1113 
1114  /* Write the first page */
1116 
1117  unlink(path);
1118 
1119  fd = open(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
1120  S_IRUSR | S_IWUSR);
1121  if (fd < 0)
1122  {
1123  fprintf(stderr, _("%s: could not open file \"%s\": %s\n"),
1124  progname, path, strerror(errno));
1125  exit(1);
1126  }
1127 
1128  errno = 0;
1129  if (write(fd, buffer, XLOG_BLCKSZ) != XLOG_BLCKSZ)
1130  {
1131  /* if write didn't set errno, assume problem is no disk space */
1132  if (errno == 0)
1133  errno = ENOSPC;
1134  fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
1135  progname, path, strerror(errno));
1136  exit(1);
1137  }
1138 
1139  /* Fill the rest of the file with zeroes */
1140  memset(buffer, 0, XLOG_BLCKSZ);
1141  for (nbytes = XLOG_BLCKSZ; nbytes < XLogSegSize; nbytes += XLOG_BLCKSZ)
1142  {
1143  errno = 0;
1144  if (write(fd, buffer, XLOG_BLCKSZ) != XLOG_BLCKSZ)
1145  {
1146  if (errno == 0)
1147  errno = ENOSPC;
1148  fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
1149  progname, path, strerror(errno));
1150  exit(1);
1151  }
1152  }
1153 
1154  if (fsync(fd) != 0)
1155  {
1156  fprintf(stderr, _("%s: fsync error: %s\n"), progname, strerror(errno));
1157  exit(1);
1158  }
1159 
1160  close(fd);
1161 }
1162 
1163 
1164 static void
1165 usage(void)
1166 {
1167  printf(_("%s resets the PostgreSQL transaction log.\n\n"), progname);
1168  printf(_("Usage:\n %s [OPTION]... DATADIR\n\n"), progname);
1169  printf(_("Options:\n"));
1170  printf(_(" -c XID,XID set oldest and newest transactions bearing commit timestamp\n"));
1171  printf(_(" (zero in either value means no change)\n"));
1172  printf(_(" [-D] DATADIR data directory\n"));
1173  printf(_(" -e XIDEPOCH set next transaction ID epoch\n"));
1174  printf(_(" -f force update to be done\n"));
1175  printf(_(" -l XLOGFILE force minimum WAL starting location for new transaction log\n"));
1176  printf(_(" -m MXID,MXID set next and oldest multitransaction ID\n"));
1177  printf(_(" -n no update, just show what would be done (for testing)\n"));
1178  printf(_(" -o OID set next OID\n"));
1179  printf(_(" -O OFFSET set next multitransaction offset\n"));
1180  printf(_(" -V, --version output version information, then exit\n"));
1181  printf(_(" -x XID set next transaction ID\n"));
1182  printf(_(" -?, --help show this help, then exit\n"));
1183  printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
1184 }
static void PrintControlValues(bool guessed)
Definition: pg_resetwal.c:623
#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:183
static MultiXactId set_mxid
Definition: pg_resetwal.c:70
int gettimeofday(struct timeval *tp, struct timezone *tzp)
Definition: gettimeofday.c:105
int max_prepared_xacts
Definition: pg_control.h:182
int64 pg_time_t
Definition: pgtime.h:23
uint32 MultiXactOffset
Definition: c.h:405
static void usage(void)
Definition: pg_resetwal.c:1165
static TransactionId set_xid
Definition: pg_resetwal.c:66
pg_time_t time
Definition: pg_control.h:129
uint32 TransactionId
Definition: c.h:393
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
TimeLineID minRecoveryPointTLI
Definition: pg_control.h:169
#define write(a, b, c)
Definition: win32.h:19
const char * get_progname(const char *argv0)
Definition: path.c:453
#define SizeOfXLogRecordDataHeaderShort
Definition: xlogrecord.h:200
int max_worker_processes
Definition: pg_control.h:181
uint32 pg_crc32c
Definition: pg_crc32c.h:38
TransactionId oldestActiveXid
Definition: pg_control.h:60
static void PrintNewControlValues(void)
Definition: pg_resetwal.c:706
uint32 nameDataLen
Definition: pg_control.h:212
#define XLogFileName(fname, tli, logSegNo)
MultiXactId oldestMulti
Definition: pg_control.h:46
static void FindEndOfXLOG(void)
Definition: pg_resetwal.c:877
TimeLineID PrevTimeLineID
Definition: pg_control.h:36
int closedir(DIR *)
Definition: dirent.c:113
static void WriteEmptyXLOG(void)
Definition: pg_resetwal.c:1066
#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:69
RmgrId xl_rmid
Definition: xlogrecord.h:47
#define PG_CONTROL_SIZE
Definition: pg_control.h:239
XLogPageHeaderData * XLogPageHeader
Definition: xlog_internal.h:57
uint32 pg_control_version
Definition: pg_control.h:122
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
CheckPoint checkPointCopy
Definition: pg_control.h:133
uint32 xlog_blcksz
Definition: pg_control.h:209
TransactionId oldestXid
Definition: pg_control.h:44
unsigned int Oid
Definition: postgres_ext.h:31
TransactionId nextXid
Definition: pg_control.h:40
Definition: dirent.h:9
pg_time_t time
Definition: pg_control.h:48
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1037
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:463
void get_restricted_token(const char *progname)
static TransactionId set_newest_commit_ts_xid
Definition: pg_resetwal.c:68
XLogLongPageHeaderData * XLogLongPageHeader
Definition: xlog_internal.h:74
static void KillExistingXLOG(void)
Definition: pg_resetwal.c:962
#define NAMEDATALEN
bool backupEndRequired
Definition: pg_control.h:172
MultiXactOffset nextMultiOffset
Definition: pg_control.h:43
TransactionId oldestCommitTsXid
Definition: pg_control.h:49
uint32 xlog_seg_size
Definition: pg_control.h:210
int optind
Definition: getopt.c:51
Definition: dirent.c:25
static void KillExistingArchiveStatus(void)
Definition: pg_resetwal.c:1011
#define FirstNormalTransactionId
Definition: transam.h:34
#define IsXLogFileName(fname)
uint64 system_identifier
Definition: pg_control.h:107
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:39
DIR * opendir(const char *)
Definition: dirent.c:33
static TransactionId set_oldest_commit_ts_xid
Definition: pg_resetwal.c:67
#define XLogFilePath(path, tli, logSegNo)
uint32 data_checksum_version
Definition: pg_control.h:226
char * c
#define XLOG_CHECKPOINT_SHUTDOWN
Definition: pg_control.h:64
XLogRecPtr unloggedLSN
Definition: pg_control.h:135
uint64 XLogSegNo
Definition: xlogdefs.h:34
#define InvalidTransactionId
Definition: transam.h:31
unsigned int uint32
Definition: c.h:265
pg_crc32c crc
Definition: pg_control.h:229
#define FirstBootstrapObjectId
Definition: transam.h:93
#define FirstMultiXactId
Definition: multixact.h:24
uint32 loblksize
Definition: pg_control.h:216
#define EQ_CRC32C(c1, c2)
Definition: pg_crc32c.h:42
static const char * progname
Definition: pg_resetwal.c:64
int unlink(const char *filename)
#define fsync(fd)
Definition: win32.h:70
uint32 indexMaxKeys
Definition: pg_control.h:213
TimeLineID xlp_tli
Definition: xlog_internal.h:40
XLogRecPtr xlp_pageaddr
Definition: xlog_internal.h:41
static bool guessed
Definition: pg_resetwal.c:63
#define SizeOfXLogRecord
Definition: xlogrecord.h:55
#define MAXFNAMELEN
#define TOAST_MAX_CHUNK_SIZE
Definition: tuptoaster.h:91
TransactionId newestCommitTsXid
Definition: pg_control.h:51
#define PG_TEXTDOMAIN(domain)
Definition: c.h:1011
#define XLOGDIR
#define UINT64CONST(x)
Definition: c.h:308
Oid oldestMultiDB
Definition: pg_control.h:47
XLogRecPtr prevCheckPoint
Definition: pg_control.h:131
uint32 toast_max_chunk_size
Definition: pg_control.h:215
#define XLOG_CONTROL_FILE
#define InvalidOid
Definition: postgres_ext.h:36
Oid nextOid
Definition: pg_control.h:41
XLogRecPtr backupEndPoint
Definition: pg_control.h:171
bool fullPageWrites
Definition: pg_control.h:38
TransactionId MultiXactId
Definition: c.h:403
#define NULL
Definition: c.h:226
bool track_commit_timestamp
Definition: pg_control.h:184
#define XLP_LONG_HEADER
Definition: xlog_internal.h:79
Oid oldestXidDB
Definition: pg_control.h:45
int main(int argc, char *argv[])
Definition: pg_resetwal.c:88
static ControlFileData ControlFile
Definition: pg_resetwal.c:61
double floatFormat
Definition: pg_control.h:199
#define INDEX_MAX_KEYS
uint8 xl_info
Definition: xlogrecord.h:46
MultiXactId nextMulti
Definition: pg_control.h:42
static void RewriteControlFile(void)
Definition: pg_resetwal.c:771
static MultiXactOffset set_mxoff
Definition: pg_resetwal.c:71
uint32 catalog_version_no
Definition: pg_control.h:123
struct dirent * readdir(DIR *)
Definition: dirent.c:78
pg_crc32c xl_crc
Definition: xlogrecord.h:49
struct CheckPoint CheckPoint
#define XLR_BLOCK_ID_DATA_SHORT
Definition: xlogrecord.h:223
TransactionId xl_xid
Definition: xlogrecord.h:44
static XLogSegNo newXlogSegNo
Definition: pg_resetwal.c:62
static void GuessControlValues(void)
Definition: pg_resetwal.c:535
static uint32 minXlogTli
Definition: pg_resetwal.c:72
#define IsPartialXLogFileName(fname)
TimeLineID ThisTimeLineID
Definition: pg_control.h:35
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:59
#define XLOG_FNAME_LEN
char d_name[MAX_PATH]
Definition: dirent.h:14
#define close(a)
Definition: win32.h:17
#define FLOATFORMAT_VALUE
Definition: pg_control.h:200
#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:313
static XLogSegNo minXlogSegNo
Definition: pg_resetwal.c:73
XLogRecPtr backupStartPoint
Definition: pg_control.h:170
uint32 relseg_size
Definition: pg_control.h:207
XLogRecPtr checkPoint
Definition: pg_control.h:130
XLogRecPtr redo
Definition: pg_control.h:33
#define read(a, b, c)
Definition: win32.h:18
#define offsetof(type, field)
Definition: c.h:550
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:168
static uint32 set_xid_epoch
Definition: pg_resetwal.c:65
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:72