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
00037
00038 #include "postgres_fe.h"
00039
00040 #include "pg_upgrade.h"
00041
00042 #ifdef HAVE_LANGINFO_H
00043 #include <langinfo.h>
00044 #endif
00045
00046 static void prepare_new_cluster(void);
00047 static void prepare_new_databases(void);
00048 static void create_new_objects(void);
00049 static void copy_clog_xlog_xid(void);
00050 static void set_frozenxids(void);
00051 static void setup(char *argv0, bool *live_check);
00052 static void cleanup(void);
00053
00054 ClusterInfo old_cluster,
00055 new_cluster;
00056 OSInfo os_info;
00057
00058 char *output_files[] = {
00059 SERVER_LOG_FILE,
00060 #ifdef WIN32
00061
00062 SERVER_START_LOG_FILE,
00063 #endif
00064 UTILITY_LOG_FILE,
00065 INTERNAL_LOG_FILE,
00066 NULL
00067 };
00068
00069
00070 int
00071 main(int argc, char **argv)
00072 {
00073 char *sequence_script_file_name = NULL;
00074 char *analyze_script_file_name = NULL;
00075 char *deletion_script_file_name = NULL;
00076 bool live_check = false;
00077
00078 parseCommandLine(argc, argv);
00079
00080 adjust_data_dir(&old_cluster);
00081 adjust_data_dir(&new_cluster);
00082
00083 setup(argv[0], &live_check);
00084
00085 output_check_banner(live_check);
00086
00087 check_cluster_versions();
00088
00089 get_sock_dir(&old_cluster, live_check);
00090 get_sock_dir(&new_cluster, false);
00091
00092 check_cluster_compatibility(live_check);
00093
00094 check_and_dump_old_cluster(live_check, &sequence_script_file_name);
00095
00096
00097
00098 start_postmaster(&new_cluster, true);
00099
00100 check_new_cluster();
00101 report_clusters_compatible();
00102
00103 pg_log(PG_REPORT, "\nPerforming Upgrade\n");
00104 pg_log(PG_REPORT, "------------------\n");
00105
00106 prepare_new_cluster();
00107
00108 stop_postmaster(false);
00109
00110
00111
00112
00113
00114 copy_clog_xlog_xid();
00115
00116
00117
00118
00119 start_postmaster(&new_cluster, true);
00120
00121 prepare_new_databases();
00122
00123 create_new_objects();
00124
00125 stop_postmaster(false);
00126
00127
00128
00129
00130
00131
00132
00133 if (user_opts.transfer_mode == TRANSFER_MODE_LINK)
00134 disable_old_cluster();
00135
00136 transfer_all_new_tablespaces(&old_cluster.dbarr, &new_cluster.dbarr,
00137 old_cluster.pgdata, new_cluster.pgdata);
00138
00139
00140
00141
00142
00143
00144
00145 prep_status("Setting next OID for new cluster");
00146 exec_prog(UTILITY_LOG_FILE, NULL, true,
00147 "\"%s/pg_resetxlog\" -o %u \"%s\"",
00148 new_cluster.bindir, old_cluster.controldata.chkpnt_nxtoid,
00149 new_cluster.pgdata);
00150 check_ok();
00151
00152 prep_status("Sync data directory to disk");
00153 exec_prog(UTILITY_LOG_FILE, NULL, true,
00154 "\"%s/initdb\" --sync-only \"%s\"", new_cluster.bindir,
00155 new_cluster.pgdata);
00156 check_ok();
00157
00158 create_script_for_cluster_analyze(&analyze_script_file_name);
00159 create_script_for_old_cluster_deletion(&deletion_script_file_name);
00160
00161 issue_warnings(sequence_script_file_name);
00162
00163 pg_log(PG_REPORT, "\nUpgrade Complete\n");
00164 pg_log(PG_REPORT, "----------------\n");
00165
00166 output_completion_banner(analyze_script_file_name,
00167 deletion_script_file_name);
00168
00169 pg_free(analyze_script_file_name);
00170 pg_free(deletion_script_file_name);
00171 pg_free(sequence_script_file_name);
00172
00173 cleanup();
00174
00175 return 0;
00176 }
00177
00178
00179 static void
00180 setup(char *argv0, bool *live_check)
00181 {
00182 char exec_path[MAXPGPATH];
00183
00184
00185
00186
00187
00188 check_pghost_envvar();
00189
00190 verify_directories();
00191
00192
00193 if (pid_lock_file_exists(old_cluster.pgdata))
00194 {
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 if (start_postmaster(&old_cluster, false))
00205 stop_postmaster(false);
00206 else
00207 {
00208 if (!user_opts.check)
00209 pg_log(PG_FATAL, "There seems to be a postmaster servicing the old cluster.\n"
00210 "Please shutdown that postmaster and try again.\n");
00211 else
00212 *live_check = true;
00213 }
00214 }
00215
00216
00217 if (pid_lock_file_exists(new_cluster.pgdata))
00218 {
00219 if (start_postmaster(&new_cluster, false))
00220 stop_postmaster(false);
00221 else
00222 pg_log(PG_FATAL, "There seems to be a postmaster servicing the new cluster.\n"
00223 "Please shutdown that postmaster and try again.\n");
00224 }
00225
00226
00227 if (find_my_exec(argv0, exec_path) < 0)
00228 pg_log(PG_FATAL, "Could not get path name to pg_upgrade: %s\n", getErrorText(errno));
00229
00230
00231 *last_dir_separator(exec_path) = '\0';
00232 canonicalize_path(exec_path);
00233 os_info.exec_path = pg_strdup(exec_path);
00234 }
00235
00236
00237 static void
00238 prepare_new_cluster(void)
00239 {
00240
00241
00242
00243
00244
00245 prep_status("Analyzing all rows in the new cluster");
00246 exec_prog(UTILITY_LOG_FILE, NULL, true,
00247 "\"%s/vacuumdb\" %s --all --analyze %s",
00248 new_cluster.bindir, cluster_conn_opts(&new_cluster),
00249 log_opts.verbose ? "--verbose" : "");
00250 check_ok();
00251
00252
00253
00254
00255
00256
00257
00258 prep_status("Freezing all rows on the new cluster");
00259 exec_prog(UTILITY_LOG_FILE, NULL, true,
00260 "\"%s/vacuumdb\" %s --all --freeze %s",
00261 new_cluster.bindir, cluster_conn_opts(&new_cluster),
00262 log_opts.verbose ? "--verbose" : "");
00263 check_ok();
00264
00265 get_pg_database_relfilenode(&new_cluster);
00266 }
00267
00268
00269 static void
00270 prepare_new_databases(void)
00271 {
00272
00273
00274
00275
00276
00277
00278 set_frozenxids();
00279
00280 prep_status("Restoring global objects in the new cluster");
00281
00282
00283
00284
00285
00286
00287
00288 install_support_functions_in_new_db("template1");
00289
00290
00291
00292
00293
00294
00295
00296 exec_prog(UTILITY_LOG_FILE, NULL, true,
00297 "\"%s/psql\" " EXEC_PSQL_ARGS " %s -f \"%s\"",
00298 new_cluster.bindir, cluster_conn_opts(&new_cluster),
00299 GLOBALS_DUMP_FILE);
00300 check_ok();
00301
00302
00303 get_db_and_rel_infos(&new_cluster);
00304 }
00305
00306
00307 static void
00308 create_new_objects(void)
00309 {
00310 int dbnum;
00311
00312 prep_status("Adding support functions to new cluster");
00313
00314
00315
00316
00317
00318
00319 for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
00320 {
00321 DbInfo *new_db = &new_cluster.dbarr.dbs[dbnum];
00322
00323
00324 if (strcmp(new_db->db_name, "template1") != 0)
00325 install_support_functions_in_new_db(new_db->db_name);
00326 }
00327 check_ok();
00328
00329 prep_status("Restoring database schemas in the new cluster\n");
00330
00331 for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
00332 {
00333 char sql_file_name[MAXPGPATH], log_file_name[MAXPGPATH];
00334 DbInfo *old_db = &old_cluster.dbarr.dbs[dbnum];
00335
00336 pg_log(PG_STATUS, "%s", old_db->db_name);
00337 snprintf(sql_file_name, sizeof(sql_file_name), DB_DUMP_FILE_MASK, old_db->db_oid);
00338 snprintf(log_file_name, sizeof(log_file_name), DB_DUMP_LOG_FILE_MASK, old_db->db_oid);
00339
00340
00341
00342
00343
00344 parallel_exec_prog(log_file_name, NULL,
00345 "\"%s/pg_restore\" %s --exit-on-error --verbose --dbname \"%s\" \"%s\"",
00346 new_cluster.bindir, cluster_conn_opts(&new_cluster),
00347 old_db->db_name, sql_file_name);
00348 }
00349
00350
00351 while (reap_child(true) == true)
00352 ;
00353
00354 end_progress_output();
00355 check_ok();
00356
00357
00358 get_db_and_rel_infos(&new_cluster);
00359
00360 uninstall_support_functions_from_new_cluster();
00361 }
00362
00363
00364
00365
00366
00367 static void
00368 copy_subdir_files(char *subdir)
00369 {
00370 char old_path[MAXPGPATH];
00371 char new_path[MAXPGPATH];
00372
00373 prep_status("Deleting files from new %s", subdir);
00374
00375 snprintf(old_path, sizeof(old_path), "%s/%s", old_cluster.pgdata, subdir);
00376 snprintf(new_path, sizeof(new_path), "%s/%s", new_cluster.pgdata, subdir);
00377 if (!rmtree(new_path, true))
00378 pg_log(PG_FATAL, "could not delete directory \"%s\"\n", new_path);
00379 check_ok();
00380
00381 prep_status("Copying old %s to new server", subdir);
00382
00383 exec_prog(UTILITY_LOG_FILE, NULL, true,
00384 #ifndef WIN32
00385 "cp -Rf \"%s\" \"%s\"",
00386 #else
00387
00388 "xcopy /e /y /q /r \"%s\" \"%s\\\"",
00389 #endif
00390 old_path, new_path);
00391
00392 check_ok();
00393 }
00394
00395 static void
00396 copy_clog_xlog_xid(void)
00397 {
00398
00399 copy_subdir_files("pg_clog");
00400
00401
00402 prep_status("Setting next transaction ID for new cluster");
00403 exec_prog(UTILITY_LOG_FILE, NULL, true,
00404 "\"%s/pg_resetxlog\" -f -x %u \"%s\"",
00405 new_cluster.bindir, old_cluster.controldata.chkpnt_nxtxid,
00406 new_cluster.pgdata);
00407 check_ok();
00408
00409
00410
00411
00412
00413
00414
00415 if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER &&
00416 new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER)
00417 {
00418 copy_subdir_files("pg_multixact/offsets");
00419 copy_subdir_files("pg_multixact/members");
00420 prep_status("Setting next multixact ID and offset for new cluster");
00421
00422
00423
00424
00425 exec_prog(UTILITY_LOG_FILE, NULL, true,
00426 "\"%s/pg_resetxlog\" -O %u -m %u,%u \"%s\"",
00427 new_cluster.bindir,
00428 old_cluster.controldata.chkpnt_nxtmxoff,
00429 old_cluster.controldata.chkpnt_nxtmulti,
00430 old_cluster.controldata.chkpnt_oldstMulti,
00431 new_cluster.pgdata);
00432 check_ok();
00433 }
00434 else if (new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER)
00435 {
00436 prep_status("Setting oldest multixact ID on new cluster");
00437
00438
00439
00440
00441
00442
00443
00444
00445 exec_prog(UTILITY_LOG_FILE, NULL, true,
00446 "\"%s/pg_resetxlog\" -m %u,%u \"%s\"",
00447 new_cluster.bindir,
00448 old_cluster.controldata.chkpnt_nxtmulti + 1,
00449 old_cluster.controldata.chkpnt_nxtmulti,
00450 new_cluster.pgdata);
00451 check_ok();
00452 }
00453
00454
00455 prep_status("Resetting WAL archives");
00456 exec_prog(UTILITY_LOG_FILE, NULL, true,
00457 "\"%s/pg_resetxlog\" -l %s \"%s\"", new_cluster.bindir,
00458 old_cluster.controldata.nextxlogfile,
00459 new_cluster.pgdata);
00460 check_ok();
00461 }
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473 static
00474 void
00475 set_frozenxids(void)
00476 {
00477 int dbnum;
00478 PGconn *conn,
00479 *conn_template1;
00480 PGresult *dbres;
00481 int ntups;
00482 int i_datname;
00483 int i_datallowconn;
00484
00485 prep_status("Setting frozenxid counters in new cluster");
00486
00487 conn_template1 = connectToServer(&new_cluster, "template1");
00488
00489
00490 PQclear(executeQueryOrDie(conn_template1,
00491 "UPDATE pg_catalog.pg_database "
00492 "SET datfrozenxid = '%u'",
00493 old_cluster.controldata.chkpnt_nxtxid));
00494
00495
00496 dbres = executeQueryOrDie(conn_template1,
00497 "SELECT datname, datallowconn "
00498 "FROM pg_catalog.pg_database");
00499
00500 i_datname = PQfnumber(dbres, "datname");
00501 i_datallowconn = PQfnumber(dbres, "datallowconn");
00502
00503 ntups = PQntuples(dbres);
00504 for (dbnum = 0; dbnum < ntups; dbnum++)
00505 {
00506 char *datname = PQgetvalue(dbres, dbnum, i_datname);
00507 char *datallowconn = PQgetvalue(dbres, dbnum, i_datallowconn);
00508
00509
00510
00511
00512
00513
00514
00515
00516 if (strcmp(datallowconn, "f") == 0)
00517 PQclear(executeQueryOrDie(conn_template1,
00518 "UPDATE pg_catalog.pg_database "
00519 "SET datallowconn = true "
00520 "WHERE datname = '%s'", datname));
00521
00522 conn = connectToServer(&new_cluster, datname);
00523
00524
00525 PQclear(executeQueryOrDie(conn,
00526 "UPDATE pg_catalog.pg_class "
00527 "SET relfrozenxid = '%u' "
00528
00529 "WHERE relkind IN ('r', 'm', 't')",
00530 old_cluster.controldata.chkpnt_nxtxid));
00531 PQfinish(conn);
00532
00533
00534 if (strcmp(datallowconn, "f") == 0)
00535 PQclear(executeQueryOrDie(conn_template1,
00536 "UPDATE pg_catalog.pg_database "
00537 "SET datallowconn = false "
00538 "WHERE datname = '%s'", datname));
00539 }
00540
00541 PQclear(dbres);
00542
00543 PQfinish(conn_template1);
00544
00545 check_ok();
00546 }
00547
00548
00549 static void
00550 cleanup(void)
00551 {
00552
00553 fclose(log_opts.internal);
00554
00555
00556 if (!log_opts.retain)
00557 {
00558 int dbnum;
00559 char **filename;
00560
00561 for (filename = output_files; *filename != NULL; filename++)
00562 unlink(*filename);
00563
00564
00565 unlink(GLOBALS_DUMP_FILE);
00566
00567 if (old_cluster.dbarr.dbs)
00568 for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
00569 {
00570 char sql_file_name[MAXPGPATH], log_file_name[MAXPGPATH];
00571 DbInfo *old_db = &old_cluster.dbarr.dbs[dbnum];
00572
00573 snprintf(sql_file_name, sizeof(sql_file_name), DB_DUMP_FILE_MASK, old_db->db_oid);
00574 unlink(sql_file_name);
00575
00576 snprintf(log_file_name, sizeof(log_file_name), DB_DUMP_LOG_FILE_MASK, old_db->db_oid);
00577 unlink(log_file_name);
00578 }
00579 }
00580 }