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