int main(int argc, char **argv) { char *analyze_script_file_name = NULL; char *deletion_script_file_name = NULL; bool live_check = false; set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_upgrade")); /* Set default restrictive mask until new cluster permissions are read */ umask(PG_MODE_MASK_OWNER); parseCommandLine(argc, argv); get_restricted_token(os_info.progname); adjust_data_dir(&old_cluster); adjust_data_dir(&new_cluster); setup(argv[0], &live_check); output_check_banner(live_check); check_cluster_versions(); get_sock_dir(&old_cluster, live_check); get_sock_dir(&new_cluster, false); check_cluster_compatibility(live_check); /* Set mask based on PGDATA permissions */ if (!GetDataDirectoryCreatePerm(new_cluster.pgdata)) { pg_log(PG_FATAL, "could not read permissions of directory \"%s\": %s\n", new_cluster.pgdata, strerror(errno)); exit(1); } umask(pg_mode_mask); check_and_dump_old_cluster(live_check); /* -- NEW -- */ start_postmaster(&new_cluster, true); check_new_cluster(); report_clusters_compatible(); pg_log(PG_REPORT, "\n" "Performing Upgrade\n" "------------------\n"); prepare_new_cluster(); stop_postmaster(false); /* * Destructive Changes to New Cluster */ copy_xact_xlog_xid(); /* New now using xids of the old system */ /* -- NEW -- */ start_postmaster(&new_cluster, true); prepare_new_globals(); create_new_objects(); stop_postmaster(false); /* * Most failures happen in create_new_objects(), which has completed at * this point. We do this here because it is just before linking, which * will link the old and new cluster data files, preventing the old * cluster from being safely started once the new cluster is started. */ if (user_opts.transfer_mode == TRANSFER_MODE_LINK) disable_old_cluster(); transfer_all_new_tablespaces(&old_cluster.dbarr, &new_cluster.dbarr, old_cluster.pgdata, new_cluster.pgdata); /* * Assuming OIDs are only used in system tables, there is no need to * restore the OID counter because we have not transferred any OIDs from * the old system, but we do it anyway just in case. We do it late here * because there is no need to have the schema load use new oids. */ prep_status("Setting next OID for new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, "\"%s/pg_resetwal\" -o %u \"%s\"", new_cluster.bindir, old_cluster.controldata.chkpnt_nxtoid, new_cluster.pgdata); check_ok(); prep_status("Sync data directory to disk"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, "\"%s/initdb\" --sync-only \"%s\"", new_cluster.bindir, new_cluster.pgdata); check_ok(); create_script_for_cluster_analyze(&analyze_script_file_name); create_script_for_old_cluster_deletion(&deletion_script_file_name); issue_warnings_and_set_wal_level(); pg_log(PG_REPORT, "\n" "Upgrade Complete\n" "----------------\n"); output_completion_banner(analyze_script_file_name, deletion_script_file_name); pg_free(analyze_script_file_name); pg_free(deletion_script_file_name); cleanup(); return 0; }
int main(int argc, char *argv[]) { int c; bool force = false; bool noupdate = false; MultiXactId set_oldestmxid = 0; char *endptr; char *endptr2; char *DataDir = NULL; int fd; set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_resetxlog")); progname = get_progname(argv[0]); if (argc > 1) { if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0) { usage(); exit(0); } if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0) { puts("pg_resetxlog (PostgreSQL) " PG_VERSION); exit(0); } } while ((c = getopt(argc, argv, "c:D:e:fl:m:no:O:x:")) != -1) { switch (c) { case 'D': DataDir = optarg; break; case 'f': force = true; break; case 'n': noupdate = true; break; case 'e': set_xid_epoch = strtoul(optarg, &endptr, 0); if (endptr == optarg || *endptr != '\0') { /*------ translator: the second %s is a command line argument (-e, etc) */ fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-e"); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); exit(1); } if (set_xid_epoch == -1) { fprintf(stderr, _("%s: transaction ID epoch (-e) must not be -1\n"), progname); exit(1); } break; case 'x': set_xid = strtoul(optarg, &endptr, 0); if (endptr == optarg || *endptr != '\0') { fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-x"); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); exit(1); } if (set_xid == 0) { fprintf(stderr, _("%s: transaction ID (-x) must not be 0\n"), progname); exit(1); } break; case 'c': set_oldest_commit_ts = strtoul(optarg, &endptr, 0); if (endptr == optarg || *endptr != ',') { fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-c"); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); exit(1); } set_newest_commit_ts = strtoul(endptr + 1, &endptr2, 0); if (endptr2 == endptr + 1 || *endptr2 != '\0') { fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-c"); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); exit(1); } if (set_oldest_commit_ts < 2 && set_oldest_commit_ts != 0) { fprintf(stderr, _("%s: transaction ID (-c) must be either 0 or greater than or equal to 2\n"), progname); exit(1); } if (set_newest_commit_ts < 2 && set_newest_commit_ts != 0) { fprintf(stderr, _("%s: transaction ID (-c) must be either 0 or greater than or equal to 2\n"), progname); exit(1); } break; case 'o': set_oid = strtoul(optarg, &endptr, 0); if (endptr == optarg || *endptr != '\0') { fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-o"); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); exit(1); } if (set_oid == 0) { fprintf(stderr, _("%s: OID (-o) must not be 0\n"), progname); exit(1); } break; case 'm': set_mxid = strtoul(optarg, &endptr, 0); if (endptr == optarg || *endptr != ',') { fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-m"); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); exit(1); } set_oldestmxid = strtoul(endptr + 1, &endptr2, 0); if (endptr2 == endptr + 1 || *endptr2 != '\0') { fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-m"); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); exit(1); } if (set_mxid == 0) { fprintf(stderr, _("%s: multitransaction ID (-m) must not be 0\n"), progname); exit(1); } /* * XXX It'd be nice to have more sanity checks here, e.g. so * that oldest is not wrapped around w.r.t. nextMulti. */ if (set_oldestmxid == 0) { fprintf(stderr, _("%s: oldest multitransaction ID (-m) must not be 0\n"), progname); exit(1); } break; case 'O': set_mxoff = strtoul(optarg, &endptr, 0); if (endptr == optarg || *endptr != '\0') { fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-O"); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); exit(1); } if (set_mxoff == -1) { fprintf(stderr, _("%s: multitransaction offset (-O) must not be -1\n"), progname); exit(1); } break; case 'l': if (strspn(optarg, "01234567890ABCDEFabcdef") != 24) { fprintf(stderr, _("%s: invalid argument for option %s\n"), progname, "-l"); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); exit(1); } XLogFromFileName(optarg, &minXlogTli, &minXlogSegNo); break; default: fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); exit(1); } } if (DataDir == NULL && optind < argc) DataDir = argv[optind++]; /* Complain if any arguments remain */ if (optind < argc) { fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"), progname, argv[optind]); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); exit(1); } if (DataDir == NULL) { fprintf(stderr, _("%s: no data directory specified\n"), progname); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); exit(1); } /* * Don't allow pg_resetxlog to be run as root, to avoid overwriting the * ownership of files in the data directory. We need only check for root * -- any other user won't have sufficient permissions to modify files in * the data directory. */ #ifndef WIN32 if (geteuid() == 0) { fprintf(stderr, _("%s: cannot be executed by \"root\"\n"), progname); fprintf(stderr, _("You must run %s as the PostgreSQL superuser.\n"), progname); exit(1); } #endif get_restricted_token(progname); if (chdir(DataDir) < 0) { fprintf(stderr, _("%s: could not change directory to \"%s\": %s\n"), progname, DataDir, strerror(errno)); exit(1); } /* * Check for a postmaster lock file --- if there is one, refuse to * proceed, on grounds we might be interfering with a live installation. */ if ((fd = open("postmaster.pid", O_RDONLY, 0)) < 0) { if (errno != ENOENT) { fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"), progname, "postmaster.pid", strerror(errno)); exit(1); } } else { fprintf(stderr, _("%s: lock file \"%s\" exists\n" "Is a server running? If not, delete the lock file and try again.\n"), progname, "postmaster.pid"); exit(1); } /* * Attempt to read the existing pg_control file */ if (!ReadControlFile()) GuessControlValues(); /* * Also look at existing segment files to set up newXlogSegNo */ FindEndOfXLOG(); /* * If we're not going to proceed with the reset, print the current control * file parameters. */ if ((guessed && !force) || noupdate) PrintControlValues(guessed); /* * Adjust fields if required by switches. (Do this now so that printout, * if any, includes these values.) */ if (set_xid_epoch != -1) ControlFile.checkPointCopy.nextXidEpoch = set_xid_epoch; if (set_xid != 0) { ControlFile.checkPointCopy.nextXid = set_xid; /* * For the moment, just set oldestXid to a value that will force * immediate autovacuum-for-wraparound. It's not clear whether adding * user control of this is useful, so let's just do something that's * reasonably safe. The magic constant here corresponds to the * maximum allowed value of autovacuum_freeze_max_age. */ ControlFile.checkPointCopy.oldestXid = set_xid - 2000000000; if (ControlFile.checkPointCopy.oldestXid < FirstNormalTransactionId) ControlFile.checkPointCopy.oldestXid += FirstNormalTransactionId; ControlFile.checkPointCopy.oldestXidDB = InvalidOid; } if (set_oldest_commit_ts != 0) ControlFile.checkPointCopy.oldestCommitTs = set_oldest_commit_ts; if (set_newest_commit_ts != 0) ControlFile.checkPointCopy.newestCommitTs = set_newest_commit_ts; if (set_oid != 0) ControlFile.checkPointCopy.nextOid = set_oid; if (set_mxid != 0) { ControlFile.checkPointCopy.nextMulti = set_mxid; ControlFile.checkPointCopy.oldestMulti = set_oldestmxid; if (ControlFile.checkPointCopy.oldestMulti < FirstMultiXactId) ControlFile.checkPointCopy.oldestMulti += FirstMultiXactId; ControlFile.checkPointCopy.oldestMultiDB = InvalidOid; } if (set_mxoff != -1) ControlFile.checkPointCopy.nextMultiOffset = set_mxoff; if (minXlogTli > ControlFile.checkPointCopy.ThisTimeLineID) { ControlFile.checkPointCopy.ThisTimeLineID = minXlogTli; ControlFile.checkPointCopy.PrevTimeLineID = minXlogTli; } if (minXlogSegNo > newXlogSegNo) newXlogSegNo = minXlogSegNo; /* * If we had to guess anything, and -f was not given, just print the * guessed values and exit. Also print if -n is given. */ if ((guessed && !force) || noupdate) { PrintNewControlValues(); if (!noupdate) { printf(_("\nIf these values seem acceptable, use -f to force reset.\n")); exit(1); } else exit(0); } /* * Don't reset from a dirty pg_control without -f, either. */ if (ControlFile.state != DB_SHUTDOWNED && !force) { printf(_("The database server was not shut down cleanly.\n" "Resetting the transaction log might cause data to be lost.\n" "If you want to proceed anyway, use -f to force reset.\n")); exit(1); } /* * Else, do the dirty deed. */ RewriteControlFile(); KillExistingXLOG(); KillExistingArchiveStatus(); WriteEmptyXLOG(); printf(_("Transaction log reset\n")); return 0; }