00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #define FRONTEND 1
00037
00038 #include "postgres.h"
00039
00040 #include <dirent.h>
00041 #include <fcntl.h>
00042 #include <locale.h>
00043 #include <sys/stat.h>
00044 #include <sys/time.h>
00045 #include <time.h>
00046 #include <unistd.h>
00047 #ifdef HAVE_GETOPT_H
00048 #include <getopt.h>
00049 #endif
00050
00051 #include "access/transam.h"
00052 #include "access/tuptoaster.h"
00053 #include "access/multixact.h"
00054 #include "access/xlog_internal.h"
00055 #include "catalog/catversion.h"
00056 #include "catalog/pg_control.h"
00057 #include "common/fe_memutils.h"
00058
00059 extern int optind;
00060 extern char *optarg;
00061
00062
00063 static ControlFileData ControlFile;
00064 static XLogSegNo newXlogSegNo;
00065 static bool guessed = false;
00066 static const char *progname;
00067
00068 static bool ReadControlFile(void);
00069 static void GuessControlValues(void);
00070 static void PrintControlValues(bool guessed);
00071 static void RewriteControlFile(void);
00072 static void FindEndOfXLOG(void);
00073 static void KillExistingXLOG(void);
00074 static void KillExistingArchiveStatus(void);
00075 static void WriteEmptyXLOG(void);
00076 static void usage(void);
00077
00078
00079 int
00080 main(int argc, char *argv[])
00081 {
00082 int c;
00083 bool force = false;
00084 bool noupdate = false;
00085 uint32 set_xid_epoch = (uint32) -1;
00086 TransactionId set_xid = 0;
00087 Oid set_oid = 0;
00088 MultiXactId set_mxid = 0;
00089 MultiXactId set_oldestmxid = 0;
00090 MultiXactOffset set_mxoff = (MultiXactOffset) -1;
00091 uint32 minXlogTli = 0;
00092 XLogSegNo minXlogSegNo = 0;
00093 char *endptr;
00094 char *endptr2;
00095 char *DataDir;
00096 int fd;
00097
00098 set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_resetxlog"));
00099
00100 progname = get_progname(argv[0]);
00101
00102 if (argc > 1)
00103 {
00104 if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
00105 {
00106 usage();
00107 exit(0);
00108 }
00109 if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
00110 {
00111 puts("pg_resetxlog (PostgreSQL) " PG_VERSION);
00112 exit(0);
00113 }
00114 }
00115
00116
00117 while ((c = getopt(argc, argv, "fl:m:no:O:x:e:")) != -1)
00118 {
00119 switch (c)
00120 {
00121 case 'f':
00122 force = true;
00123 break;
00124
00125 case 'n':
00126 noupdate = true;
00127 break;
00128
00129 case 'e':
00130 set_xid_epoch = strtoul(optarg, &endptr, 0);
00131 if (endptr == optarg || *endptr != '\0')
00132 {
00133 fprintf(stderr, _("%s: invalid argument for option -e\n"), progname);
00134 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
00135 exit(1);
00136 }
00137 if (set_xid_epoch == -1)
00138 {
00139 fprintf(stderr, _("%s: transaction ID epoch (-e) must not be -1\n"), progname);
00140 exit(1);
00141 }
00142 break;
00143
00144 case 'x':
00145 set_xid = strtoul(optarg, &endptr, 0);
00146 if (endptr == optarg || *endptr != '\0')
00147 {
00148 fprintf(stderr, _("%s: invalid argument for option -x\n"), progname);
00149 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
00150 exit(1);
00151 }
00152 if (set_xid == 0)
00153 {
00154 fprintf(stderr, _("%s: transaction ID (-x) must not be 0\n"), progname);
00155 exit(1);
00156 }
00157 break;
00158
00159 case 'o':
00160 set_oid = strtoul(optarg, &endptr, 0);
00161 if (endptr == optarg || *endptr != '\0')
00162 {
00163 fprintf(stderr, _("%s: invalid argument for option -o\n"), progname);
00164 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
00165 exit(1);
00166 }
00167 if (set_oid == 0)
00168 {
00169 fprintf(stderr, _("%s: OID (-o) must not be 0\n"), progname);
00170 exit(1);
00171 }
00172 break;
00173
00174 case 'm':
00175 set_mxid = strtoul(optarg, &endptr, 0);
00176 if (endptr == optarg || *endptr != ',')
00177 {
00178 fprintf(stderr, _("%s: invalid argument for option -m\n"), progname);
00179 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
00180 exit(1);
00181 }
00182
00183 set_oldestmxid = strtoul(endptr + 1, &endptr2, 0);
00184 if (endptr2 == endptr + 1 || *endptr2 != '\0')
00185 {
00186 fprintf(stderr, _("%s: invalid argument for option -m\n"), progname);
00187 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
00188 exit(1);
00189 }
00190 if (set_mxid == 0)
00191 {
00192 fprintf(stderr, _("%s: multitransaction ID (-m) must not be 0\n"), progname);
00193 exit(1);
00194 }
00195
00196
00197
00198
00199 if (set_oldestmxid == 0)
00200 {
00201 fprintf(stderr, _("%s: oldest multitransaction ID (-m) must not be 0\n"),
00202 progname);
00203 exit(1);
00204 }
00205 break;
00206
00207 case 'O':
00208 set_mxoff = strtoul(optarg, &endptr, 0);
00209 if (endptr == optarg || *endptr != '\0')
00210 {
00211 fprintf(stderr, _("%s: invalid argument for option -O\n"), progname);
00212 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
00213 exit(1);
00214 }
00215 if (set_mxoff == -1)
00216 {
00217 fprintf(stderr, _("%s: multitransaction offset (-O) must not be -1\n"), progname);
00218 exit(1);
00219 }
00220 break;
00221
00222 case 'l':
00223 if (strspn(optarg, "01234567890ABCDEFabcdef") != 24)
00224 {
00225 fprintf(stderr, _("%s: invalid argument for option -l\n"), progname);
00226 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
00227 exit(1);
00228 }
00229 XLogFromFileName(optarg, &minXlogTli, &minXlogSegNo);
00230 break;
00231
00232 default:
00233 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
00234 exit(1);
00235 }
00236 }
00237
00238 if (optind == argc)
00239 {
00240 fprintf(stderr, _("%s: no data directory specified\n"), progname);
00241 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
00242 exit(1);
00243 }
00244
00245
00246
00247
00248
00249
00250
00251 #ifndef WIN32
00252 if (geteuid() == 0)
00253 {
00254 fprintf(stderr, _("%s: cannot be executed by \"root\"\n"),
00255 progname);
00256 fprintf(stderr, _("You must run %s as the PostgreSQL superuser.\n"),
00257 progname);
00258 exit(1);
00259 }
00260 #endif
00261
00262 DataDir = argv[optind];
00263
00264 if (chdir(DataDir) < 0)
00265 {
00266 fprintf(stderr, _("%s: could not change directory to \"%s\": %s\n"),
00267 progname, DataDir, strerror(errno));
00268 exit(1);
00269 }
00270
00271
00272
00273
00274
00275 if ((fd = open("postmaster.pid", O_RDONLY, 0)) < 0)
00276 {
00277 if (errno != ENOENT)
00278 {
00279 fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
00280 progname, "postmaster.pid", strerror(errno));
00281 exit(1);
00282 }
00283 }
00284 else
00285 {
00286 fprintf(stderr, _("%s: lock file \"%s\" exists\n"
00287 "Is a server running? If not, delete the lock file and try again.\n"),
00288 progname, "postmaster.pid");
00289 exit(1);
00290 }
00291
00292
00293
00294
00295 if (!ReadControlFile())
00296 GuessControlValues();
00297
00298
00299
00300
00301 FindEndOfXLOG();
00302
00303
00304
00305
00306
00307 if (set_xid_epoch != -1)
00308 ControlFile.checkPointCopy.nextXidEpoch = set_xid_epoch;
00309
00310 if (set_xid != 0)
00311 {
00312 ControlFile.checkPointCopy.nextXid = set_xid;
00313
00314
00315
00316
00317
00318
00319
00320
00321 ControlFile.checkPointCopy.oldestXid = set_xid - 2000000000;
00322 if (ControlFile.checkPointCopy.oldestXid < FirstNormalTransactionId)
00323 ControlFile.checkPointCopy.oldestXid += FirstNormalTransactionId;
00324 ControlFile.checkPointCopy.oldestXidDB = InvalidOid;
00325 }
00326
00327 if (set_oid != 0)
00328 ControlFile.checkPointCopy.nextOid = set_oid;
00329
00330 if (set_mxid != 0)
00331 {
00332 ControlFile.checkPointCopy.nextMulti = set_mxid;
00333
00334 ControlFile.checkPointCopy.oldestMulti = set_oldestmxid;
00335 if (ControlFile.checkPointCopy.oldestMulti < FirstMultiXactId)
00336 ControlFile.checkPointCopy.oldestMulti += FirstMultiXactId;
00337 ControlFile.checkPointCopy.oldestMultiDB = InvalidOid;
00338 }
00339
00340 if (set_mxoff != -1)
00341 ControlFile.checkPointCopy.nextMultiOffset = set_mxoff;
00342
00343 if (minXlogTli > ControlFile.checkPointCopy.ThisTimeLineID)
00344 {
00345 ControlFile.checkPointCopy.ThisTimeLineID = minXlogTli;
00346 ControlFile.checkPointCopy.PrevTimeLineID = minXlogTli;
00347 }
00348
00349 if (minXlogSegNo > newXlogSegNo)
00350 newXlogSegNo = minXlogSegNo;
00351
00352
00353
00354
00355
00356 if ((guessed && !force) || noupdate)
00357 {
00358 PrintControlValues(guessed);
00359 if (!noupdate)
00360 {
00361 printf(_("\nIf these values seem acceptable, use -f to force reset.\n"));
00362 exit(1);
00363 }
00364 else
00365 exit(0);
00366 }
00367
00368
00369
00370
00371 if (ControlFile.state != DB_SHUTDOWNED && !force)
00372 {
00373 printf(_("The database server was not shut down cleanly.\n"
00374 "Resetting the transaction log might cause data to be lost.\n"
00375 "If you want to proceed anyway, use -f to force reset.\n"));
00376 exit(1);
00377 }
00378
00379
00380
00381
00382 RewriteControlFile();
00383 KillExistingXLOG();
00384 KillExistingArchiveStatus();
00385 WriteEmptyXLOG();
00386
00387 printf(_("Transaction log reset\n"));
00388 return 0;
00389 }
00390
00391
00392
00393
00394
00395
00396
00397
00398 static bool
00399 ReadControlFile(void)
00400 {
00401 int fd;
00402 int len;
00403 char *buffer;
00404 pg_crc32 crc;
00405
00406 if ((fd = open(XLOG_CONTROL_FILE, O_RDONLY | PG_BINARY, 0)) < 0)
00407 {
00408
00409
00410
00411
00412
00413 fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
00414 progname, XLOG_CONTROL_FILE, strerror(errno));
00415 if (errno == ENOENT)
00416 fprintf(stderr, _("If you are sure the data directory path is correct, execute\n"
00417 " touch %s\n"
00418 "and try again.\n"),
00419 XLOG_CONTROL_FILE);
00420 exit(1);
00421 }
00422
00423
00424 buffer = (char *) pg_malloc(PG_CONTROL_SIZE);
00425
00426 len = read(fd, buffer, PG_CONTROL_SIZE);
00427 if (len < 0)
00428 {
00429 fprintf(stderr, _("%s: could not read file \"%s\": %s\n"),
00430 progname, XLOG_CONTROL_FILE, strerror(errno));
00431 exit(1);
00432 }
00433 close(fd);
00434
00435 if (len >= sizeof(ControlFileData) &&
00436 ((ControlFileData *) buffer)->pg_control_version == PG_CONTROL_VERSION)
00437 {
00438
00439 INIT_CRC32(crc);
00440 COMP_CRC32(crc,
00441 buffer,
00442 offsetof(ControlFileData, crc));
00443 FIN_CRC32(crc);
00444
00445 if (EQ_CRC32(crc, ((ControlFileData *) buffer)->crc))
00446 {
00447
00448 memcpy(&ControlFile, buffer, sizeof(ControlFile));
00449 return true;
00450 }
00451
00452 fprintf(stderr, _("%s: pg_control exists but has invalid CRC; proceed with caution\n"),
00453 progname);
00454
00455 memcpy(&ControlFile, buffer, sizeof(ControlFile));
00456 guessed = true;
00457 return true;
00458 }
00459
00460
00461 fprintf(stderr, _("%s: pg_control exists but is broken or unknown version; ignoring it\n"),
00462 progname);
00463 return false;
00464 }
00465
00466
00467
00468
00469
00470 static void
00471 GuessControlValues(void)
00472 {
00473 uint64 sysidentifier;
00474 struct timeval tv;
00475
00476
00477
00478
00479 guessed = true;
00480 memset(&ControlFile, 0, sizeof(ControlFile));
00481
00482 ControlFile.pg_control_version = PG_CONTROL_VERSION;
00483 ControlFile.catalog_version_no = CATALOG_VERSION_NO;
00484
00485
00486
00487
00488
00489 gettimeofday(&tv, NULL);
00490 sysidentifier = ((uint64) tv.tv_sec) << 32;
00491 sysidentifier |= (uint32) (tv.tv_sec | tv.tv_usec);
00492
00493 ControlFile.system_identifier = sysidentifier;
00494
00495 ControlFile.checkPointCopy.redo = SizeOfXLogLongPHD;
00496 ControlFile.checkPointCopy.ThisTimeLineID = 1;
00497 ControlFile.checkPointCopy.PrevTimeLineID = 1;
00498 ControlFile.checkPointCopy.fullPageWrites = false;
00499 ControlFile.checkPointCopy.nextXidEpoch = 0;
00500 ControlFile.checkPointCopy.nextXid = FirstNormalTransactionId;
00501 ControlFile.checkPointCopy.nextOid = FirstBootstrapObjectId;
00502 ControlFile.checkPointCopy.nextMulti = FirstMultiXactId;
00503 ControlFile.checkPointCopy.nextMultiOffset = 0;
00504 ControlFile.checkPointCopy.oldestXid = FirstNormalTransactionId;
00505 ControlFile.checkPointCopy.oldestXidDB = InvalidOid;
00506 ControlFile.checkPointCopy.oldestMulti = FirstMultiXactId;
00507 ControlFile.checkPointCopy.oldestMultiDB = InvalidOid;
00508 ControlFile.checkPointCopy.time = (pg_time_t) time(NULL);
00509 ControlFile.checkPointCopy.oldestActiveXid = InvalidTransactionId;
00510
00511 ControlFile.state = DB_SHUTDOWNED;
00512 ControlFile.time = (pg_time_t) time(NULL);
00513 ControlFile.checkPoint = ControlFile.checkPointCopy.redo;
00514 ControlFile.unloggedLSN = 1;
00515
00516
00517
00518 ControlFile.wal_level = WAL_LEVEL_MINIMAL;
00519 ControlFile.MaxConnections = 100;
00520 ControlFile.max_prepared_xacts = 0;
00521 ControlFile.max_locks_per_xact = 64;
00522
00523 ControlFile.maxAlign = MAXIMUM_ALIGNOF;
00524 ControlFile.floatFormat = FLOATFORMAT_VALUE;
00525 ControlFile.blcksz = BLCKSZ;
00526 ControlFile.relseg_size = RELSEG_SIZE;
00527 ControlFile.xlog_blcksz = XLOG_BLCKSZ;
00528 ControlFile.xlog_seg_size = XLOG_SEG_SIZE;
00529 ControlFile.nameDataLen = NAMEDATALEN;
00530 ControlFile.indexMaxKeys = INDEX_MAX_KEYS;
00531 ControlFile.toast_max_chunk_size = TOAST_MAX_CHUNK_SIZE;
00532 #ifdef HAVE_INT64_TIMESTAMP
00533 ControlFile.enableIntTimes = true;
00534 #else
00535 ControlFile.enableIntTimes = false;
00536 #endif
00537 ControlFile.float4ByVal = FLOAT4PASSBYVAL;
00538 ControlFile.float8ByVal = FLOAT8PASSBYVAL;
00539
00540
00541
00542
00543
00544 }
00545
00546
00547
00548
00549
00550
00551
00552
00553 static void
00554 PrintControlValues(bool guessed)
00555 {
00556 char sysident_str[32];
00557 char fname[MAXFNAMELEN];
00558
00559 if (guessed)
00560 printf(_("Guessed pg_control values:\n\n"));
00561 else
00562 printf(_("pg_control values:\n\n"));
00563
00564
00565
00566
00567
00568 snprintf(sysident_str, sizeof(sysident_str), UINT64_FORMAT,
00569 ControlFile.system_identifier);
00570
00571 XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID, newXlogSegNo);
00572
00573 printf(_("First log segment after reset: %s\n"),
00574 fname);
00575 printf(_("pg_control version number: %u\n"),
00576 ControlFile.pg_control_version);
00577 printf(_("Catalog version number: %u\n"),
00578 ControlFile.catalog_version_no);
00579 printf(_("Database system identifier: %s\n"),
00580 sysident_str);
00581 printf(_("Latest checkpoint's TimeLineID: %u\n"),
00582 ControlFile.checkPointCopy.ThisTimeLineID);
00583 printf(_("Latest checkpoint's full_page_writes: %s\n"),
00584 ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off"));
00585 printf(_("Latest checkpoint's NextXID: %u/%u\n"),
00586 ControlFile.checkPointCopy.nextXidEpoch,
00587 ControlFile.checkPointCopy.nextXid);
00588 printf(_("Latest checkpoint's NextOID: %u\n"),
00589 ControlFile.checkPointCopy.nextOid);
00590 printf(_("Latest checkpoint's NextMultiXactId: %u\n"),
00591 ControlFile.checkPointCopy.nextMulti);
00592 printf(_("Latest checkpoint's NextMultiOffset: %u\n"),
00593 ControlFile.checkPointCopy.nextMultiOffset);
00594 printf(_("Latest checkpoint's oldestXID: %u\n"),
00595 ControlFile.checkPointCopy.oldestXid);
00596 printf(_("Latest checkpoint's oldestXID's DB: %u\n"),
00597 ControlFile.checkPointCopy.oldestXidDB);
00598 printf(_("Latest checkpoint's oldestActiveXID: %u\n"),
00599 ControlFile.checkPointCopy.oldestActiveXid);
00600 printf(_("Latest checkpoint's oldestMultiXid: %u\n"),
00601 ControlFile.checkPointCopy.oldestMulti);
00602 printf(_("Latest checkpoint's oldestMulti's DB: %u\n"),
00603 ControlFile.checkPointCopy.oldestMultiDB);
00604 printf(_("Maximum data alignment: %u\n"),
00605 ControlFile.maxAlign);
00606
00607 printf(_("Database block size: %u\n"),
00608 ControlFile.blcksz);
00609 printf(_("Blocks per segment of large relation: %u\n"),
00610 ControlFile.relseg_size);
00611 printf(_("WAL block size: %u\n"),
00612 ControlFile.xlog_blcksz);
00613 printf(_("Bytes per WAL segment: %u\n"),
00614 ControlFile.xlog_seg_size);
00615 printf(_("Maximum length of identifiers: %u\n"),
00616 ControlFile.nameDataLen);
00617 printf(_("Maximum columns in an index: %u\n"),
00618 ControlFile.indexMaxKeys);
00619 printf(_("Maximum size of a TOAST chunk: %u\n"),
00620 ControlFile.toast_max_chunk_size);
00621 printf(_("Date/time type storage: %s\n"),
00622 (ControlFile.enableIntTimes ? _("64-bit integers") : _("floating-point numbers")));
00623 printf(_("Float4 argument passing: %s\n"),
00624 (ControlFile.float4ByVal ? _("by value") : _("by reference")));
00625 printf(_("Float8 argument passing: %s\n"),
00626 (ControlFile.float8ByVal ? _("by value") : _("by reference")));
00627 printf(_("Data page checksum version: %u\n"),
00628 ControlFile.data_checksum_version);
00629 }
00630
00631
00632
00633
00634
00635 static void
00636 RewriteControlFile(void)
00637 {
00638 int fd;
00639 char buffer[PG_CONTROL_SIZE];
00640
00641
00642
00643
00644
00645 XLogSegNoOffsetToRecPtr(newXlogSegNo, SizeOfXLogLongPHD,
00646 ControlFile.checkPointCopy.redo);
00647 ControlFile.checkPointCopy.time = (pg_time_t) time(NULL);
00648
00649 ControlFile.state = DB_SHUTDOWNED;
00650 ControlFile.time = (pg_time_t) time(NULL);
00651 ControlFile.checkPoint = ControlFile.checkPointCopy.redo;
00652 ControlFile.prevCheckPoint = 0;
00653 ControlFile.minRecoveryPoint = 0;
00654 ControlFile.minRecoveryPointTLI = 0;
00655 ControlFile.backupStartPoint = 0;
00656 ControlFile.backupEndPoint = 0;
00657 ControlFile.backupEndRequired = false;
00658
00659
00660
00661
00662
00663
00664 ControlFile.wal_level = WAL_LEVEL_MINIMAL;
00665 ControlFile.MaxConnections = 100;
00666 ControlFile.max_prepared_xacts = 0;
00667 ControlFile.max_locks_per_xact = 64;
00668
00669
00670 ControlFile.xlog_seg_size = XLogSegSize;
00671
00672
00673 INIT_CRC32(ControlFile.crc);
00674 COMP_CRC32(ControlFile.crc,
00675 (char *) &ControlFile,
00676 offsetof(ControlFileData, crc));
00677 FIN_CRC32(ControlFile.crc);
00678
00679
00680
00681
00682
00683
00684
00685
00686 if (sizeof(ControlFileData) > PG_CONTROL_SIZE)
00687 {
00688 fprintf(stderr,
00689 _("%s: internal error -- sizeof(ControlFileData) is too large ... fix PG_CONTROL_SIZE\n"),
00690 progname);
00691 exit(1);
00692 }
00693
00694 memset(buffer, 0, PG_CONTROL_SIZE);
00695 memcpy(buffer, &ControlFile, sizeof(ControlFileData));
00696
00697 unlink(XLOG_CONTROL_FILE);
00698
00699 fd = open(XLOG_CONTROL_FILE,
00700 O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
00701 S_IRUSR | S_IWUSR);
00702 if (fd < 0)
00703 {
00704 fprintf(stderr, _("%s: could not create pg_control file: %s\n"),
00705 progname, strerror(errno));
00706 exit(1);
00707 }
00708
00709 errno = 0;
00710 if (write(fd, buffer, PG_CONTROL_SIZE) != PG_CONTROL_SIZE)
00711 {
00712
00713 if (errno == 0)
00714 errno = ENOSPC;
00715 fprintf(stderr, _("%s: could not write pg_control file: %s\n"),
00716 progname, strerror(errno));
00717 exit(1);
00718 }
00719
00720 if (fsync(fd) != 0)
00721 {
00722 fprintf(stderr, _("%s: fsync error: %s\n"), progname, strerror(errno));
00723 exit(1);
00724 }
00725
00726 close(fd);
00727 }
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738 static void
00739 FindEndOfXLOG(void)
00740 {
00741 DIR *xldir;
00742 struct dirent *xlde;
00743 uint64 segs_per_xlogid;
00744 uint64 xlogbytepos;
00745
00746
00747
00748
00749
00750
00751 segs_per_xlogid = (UINT64CONST(0x0000000100000000) / ControlFile.xlog_seg_size);
00752 newXlogSegNo = ControlFile.checkPointCopy.redo / ControlFile.xlog_seg_size;
00753
00754
00755
00756
00757
00758
00759 xldir = opendir(XLOGDIR);
00760 if (xldir == NULL)
00761 {
00762 fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
00763 progname, XLOGDIR, strerror(errno));
00764 exit(1);
00765 }
00766
00767 errno = 0;
00768 while ((xlde = readdir(xldir)) != NULL)
00769 {
00770 if (strlen(xlde->d_name) == 24 &&
00771 strspn(xlde->d_name, "0123456789ABCDEF") == 24)
00772 {
00773 unsigned int tli,
00774 log,
00775 seg;
00776 XLogSegNo segno;
00777
00778 sscanf(xlde->d_name, "%08X%08X%08X", &tli, &log, &seg);
00779 segno = ((uint64) log) * segs_per_xlogid + seg;
00780
00781
00782
00783
00784
00785
00786
00787 if (segno > newXlogSegNo)
00788 newXlogSegNo = segno;
00789 }
00790 errno = 0;
00791 }
00792 #ifdef WIN32
00793
00794
00795
00796
00797
00798 if (GetLastError() == ERROR_NO_MORE_FILES)
00799 errno = 0;
00800 #endif
00801
00802 if (errno)
00803 {
00804 fprintf(stderr, _("%s: could not read from directory \"%s\": %s\n"),
00805 progname, XLOGDIR, strerror(errno));
00806 exit(1);
00807 }
00808 closedir(xldir);
00809
00810
00811
00812
00813
00814 xlogbytepos = newXlogSegNo * ControlFile.xlog_seg_size;
00815 newXlogSegNo = (xlogbytepos + XLogSegSize - 1) / XLogSegSize;
00816 newXlogSegNo++;
00817 }
00818
00819
00820
00821
00822
00823 static void
00824 KillExistingXLOG(void)
00825 {
00826 DIR *xldir;
00827 struct dirent *xlde;
00828 char path[MAXPGPATH];
00829
00830 xldir = opendir(XLOGDIR);
00831 if (xldir == NULL)
00832 {
00833 fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
00834 progname, XLOGDIR, strerror(errno));
00835 exit(1);
00836 }
00837
00838 errno = 0;
00839 while ((xlde = readdir(xldir)) != NULL)
00840 {
00841 if (strlen(xlde->d_name) == 24 &&
00842 strspn(xlde->d_name, "0123456789ABCDEF") == 24)
00843 {
00844 snprintf(path, MAXPGPATH, "%s/%s", XLOGDIR, xlde->d_name);
00845 if (unlink(path) < 0)
00846 {
00847 fprintf(stderr, _("%s: could not delete file \"%s\": %s\n"),
00848 progname, path, strerror(errno));
00849 exit(1);
00850 }
00851 }
00852 errno = 0;
00853 }
00854 #ifdef WIN32
00855
00856
00857
00858
00859
00860 if (GetLastError() == ERROR_NO_MORE_FILES)
00861 errno = 0;
00862 #endif
00863
00864 if (errno)
00865 {
00866 fprintf(stderr, _("%s: could not read from directory \"%s\": %s\n"),
00867 progname, XLOGDIR, strerror(errno));
00868 exit(1);
00869 }
00870 closedir(xldir);
00871 }
00872
00873
00874
00875
00876
00877 static void
00878 KillExistingArchiveStatus(void)
00879 {
00880 DIR *xldir;
00881 struct dirent *xlde;
00882 char path[MAXPGPATH];
00883
00884 #define ARCHSTATDIR XLOGDIR "/archive_status"
00885
00886 xldir = opendir(ARCHSTATDIR);
00887 if (xldir == NULL)
00888 {
00889 fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
00890 progname, ARCHSTATDIR, strerror(errno));
00891 exit(1);
00892 }
00893
00894 errno = 0;
00895 while ((xlde = readdir(xldir)) != NULL)
00896 {
00897 if (strspn(xlde->d_name, "0123456789ABCDEF") == 24 &&
00898 (strcmp(xlde->d_name + 24, ".ready") == 0 ||
00899 strcmp(xlde->d_name + 24, ".done") == 0))
00900 {
00901 snprintf(path, MAXPGPATH, "%s/%s", ARCHSTATDIR, xlde->d_name);
00902 if (unlink(path) < 0)
00903 {
00904 fprintf(stderr, _("%s: could not delete file \"%s\": %s\n"),
00905 progname, path, strerror(errno));
00906 exit(1);
00907 }
00908 }
00909 errno = 0;
00910 }
00911 #ifdef WIN32
00912
00913
00914
00915
00916
00917 if (GetLastError() == ERROR_NO_MORE_FILES)
00918 errno = 0;
00919 #endif
00920
00921 if (errno)
00922 {
00923 fprintf(stderr, _("%s: could not read from directory \"%s\": %s\n"),
00924 progname, ARCHSTATDIR, strerror(errno));
00925 exit(1);
00926 }
00927 closedir(xldir);
00928 }
00929
00930
00931
00932
00933
00934
00935 static void
00936 WriteEmptyXLOG(void)
00937 {
00938 char *buffer;
00939 XLogPageHeader page;
00940 XLogLongPageHeader longpage;
00941 XLogRecord *record;
00942 pg_crc32 crc;
00943 char path[MAXPGPATH];
00944 int fd;
00945 int nbytes;
00946
00947
00948 buffer = (char *) pg_malloc(XLOG_BLCKSZ);
00949 page = (XLogPageHeader) buffer;
00950 memset(buffer, 0, XLOG_BLCKSZ);
00951
00952
00953 page->xlp_magic = XLOG_PAGE_MAGIC;
00954 page->xlp_info = XLP_LONG_HEADER;
00955 page->xlp_tli = ControlFile.checkPointCopy.ThisTimeLineID;
00956 page->xlp_pageaddr = ControlFile.checkPointCopy.redo - SizeOfXLogLongPHD;
00957 longpage = (XLogLongPageHeader) page;
00958 longpage->xlp_sysid = ControlFile.system_identifier;
00959 longpage->xlp_seg_size = XLogSegSize;
00960 longpage->xlp_xlog_blcksz = XLOG_BLCKSZ;
00961
00962
00963 record = (XLogRecord *) ((char *) page + SizeOfXLogLongPHD);
00964 record->xl_prev = 0;
00965 record->xl_xid = InvalidTransactionId;
00966 record->xl_tot_len = SizeOfXLogRecord + sizeof(CheckPoint);
00967 record->xl_len = sizeof(CheckPoint);
00968 record->xl_info = XLOG_CHECKPOINT_SHUTDOWN;
00969 record->xl_rmid = RM_XLOG_ID;
00970 memcpy(XLogRecGetData(record), &ControlFile.checkPointCopy,
00971 sizeof(CheckPoint));
00972
00973 INIT_CRC32(crc);
00974 COMP_CRC32(crc, &ControlFile.checkPointCopy, sizeof(CheckPoint));
00975 COMP_CRC32(crc, (char *) record, offsetof(XLogRecord, xl_crc));
00976 FIN_CRC32(crc);
00977 record->xl_crc = crc;
00978
00979
00980 XLogFilePath(path, ControlFile.checkPointCopy.ThisTimeLineID, newXlogSegNo);
00981
00982 unlink(path);
00983
00984 fd = open(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
00985 S_IRUSR | S_IWUSR);
00986 if (fd < 0)
00987 {
00988 fprintf(stderr, _("%s: could not open file \"%s\": %s\n"),
00989 progname, path, strerror(errno));
00990 exit(1);
00991 }
00992
00993 errno = 0;
00994 if (write(fd, buffer, XLOG_BLCKSZ) != XLOG_BLCKSZ)
00995 {
00996
00997 if (errno == 0)
00998 errno = ENOSPC;
00999 fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
01000 progname, path, strerror(errno));
01001 exit(1);
01002 }
01003
01004
01005 memset(buffer, 0, XLOG_BLCKSZ);
01006 for (nbytes = XLOG_BLCKSZ; nbytes < XLogSegSize; nbytes += XLOG_BLCKSZ)
01007 {
01008 errno = 0;
01009 if (write(fd, buffer, XLOG_BLCKSZ) != XLOG_BLCKSZ)
01010 {
01011 if (errno == 0)
01012 errno = ENOSPC;
01013 fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
01014 progname, path, strerror(errno));
01015 exit(1);
01016 }
01017 }
01018
01019 if (fsync(fd) != 0)
01020 {
01021 fprintf(stderr, _("%s: fsync error: %s\n"), progname, strerror(errno));
01022 exit(1);
01023 }
01024
01025 close(fd);
01026 }
01027
01028
01029 static void
01030 usage(void)
01031 {
01032 printf(_("%s resets the PostgreSQL transaction log.\n\n"), progname);
01033 printf(_("Usage:\n %s [OPTION]... DATADIR\n\n"), progname);
01034 printf(_("Options:\n"));
01035 printf(_(" -e XIDEPOCH set next transaction ID epoch\n"));
01036 printf(_(" -f force update to be done\n"));
01037 printf(_(" -l XLOGFILE force minimum WAL starting location for new transaction log\n"));
01038 printf(_(" -m XID,OLDEST set next multitransaction ID and oldest value\n"));
01039 printf(_(" -n no update, just show extracted control values (for testing)\n"));
01040 printf(_(" -o OID set next OID\n"));
01041 printf(_(" -O OFFSET set next multitransaction offset\n"));
01042 printf(_(" -V, --version output version information, then exit\n"));
01043 printf(_(" -x XID set next transaction ID\n"));
01044 printf(_(" -?, --help show this help, then exit\n"));
01045 printf(_("\nReport bugs to <[email protected]>.\n"));
01046 }