]> granicus.if.org Git - postgresql/blob - contrib/pg_upgrade/pg_upgrade.c
On Windows, have pg_upgrade use different two files to log pg_ctl
[postgresql] / contrib / pg_upgrade / pg_upgrade.c
1 /*
2  *      pg_upgrade.c
3  *
4  *      main source file
5  *
6  *      Copyright (c) 2010-2012, PostgreSQL Global Development Group
7  *      contrib/pg_upgrade/pg_upgrade.c
8  */
9
10 /*
11  *      To simplify the upgrade process, we force certain system values to be
12  *      identical between old and new clusters:
13  *
14  *      We control all assignments of pg_class.oid (and relfilenode) so toast
15  *      oids are the same between old and new clusters.  This is important
16  *      because toast oids are stored as toast pointers in user tables.
17  *
18  *      FYI, while pg_class.oid and pg_class.relfilenode are initially the same
19  *      in a cluster, but they can diverge due to CLUSTER, REINDEX, or VACUUM
20  *      FULL.  The new cluster will have matching pg_class.oid and
21  *      pg_class.relfilenode values and be based on the old oid value.  This can
22  *      cause the old and new pg_class.relfilenode values to differ.  In summary,
23  *      old and new pg_class.oid and new pg_class.relfilenode will have the
24  *      same value, and old pg_class.relfilenode might differ.
25  *
26  *      We control all assignments of pg_type.oid because these oids are stored
27  *      in user composite type values.
28  *
29  *      We control all assignments of pg_enum.oid because these oids are stored
30  *      in user tables as enum values.
31  *
32  *      We control all assignments of pg_auth.oid because these oids are stored
33  *      in pg_largeobject_metadata.
34  */
35
36
37
38 #include "postgres.h"
39
40 #include "pg_upgrade.h"
41
42 #ifdef HAVE_LANGINFO_H
43 #include <langinfo.h>
44 #endif
45
46 static void prepare_new_cluster(void);
47 static void prepare_new_databases(void);
48 static void create_new_objects(void);
49 static void copy_clog_xlog_xid(void);
50 static void set_frozenxids(void);
51 static void setup(char *argv0, bool live_check);
52 static void cleanup(void);
53
54 ClusterInfo old_cluster,
55                         new_cluster;
56 OSInfo          os_info;
57
58 char *output_files[] = {
59         SERVER_LOG_FILE,
60 #ifdef WIN32
61         SERVER_START_LOG_FILE,
62         SERVER_STOP_LOG_FILE,
63 #endif
64         RESTORE_LOG_FILE,
65         UTILITY_LOG_FILE,
66         INTERNAL_LOG_FILE,
67         NULL
68 };
69
70
71 int
72 main(int argc, char **argv)
73 {
74         char       *sequence_script_file_name = NULL;
75         char       *analyze_script_file_name = NULL;
76         char       *deletion_script_file_name = NULL;
77         bool            live_check = false;
78
79         parseCommandLine(argc, argv);
80
81         adjust_data_dir(&old_cluster);
82         adjust_data_dir(&new_cluster);
83
84         output_check_banner(&live_check);
85
86         setup(argv[0], live_check);
87
88         check_cluster_versions();
89         check_cluster_compatibility(live_check);
90
91         check_old_cluster(live_check, &sequence_script_file_name);
92
93
94         /* -- NEW -- */
95         start_postmaster(&new_cluster);
96
97         check_new_cluster();
98         report_clusters_compatible();
99
100         pg_log(PG_REPORT, "\nPerforming Upgrade\n");
101         pg_log(PG_REPORT, "------------------\n");
102
103         prepare_new_cluster();
104
105         stop_postmaster(false);
106
107         /*
108          * Destructive Changes to New Cluster
109          */
110
111         copy_clog_xlog_xid();
112
113         /* New now using xids of the old system */
114
115         /* -- NEW -- */
116         start_postmaster(&new_cluster);
117
118         prepare_new_databases();
119
120         create_new_objects();
121
122         stop_postmaster(false);
123
124         /*
125          *      Most failures happen in create_new_objects(), which has
126          *      completed at this point.  We do this here because it is just
127          *      before linking, which will link the old and new cluster data
128          *      files, preventing the old cluster from being safely started
129          *      once the new cluster is started.
130          */
131         if (user_opts.transfer_mode == TRANSFER_MODE_LINK)
132                 disable_old_cluster();
133
134         transfer_all_new_dbs(&old_cluster.dbarr, &new_cluster.dbarr,
135                                                  old_cluster.pgdata, new_cluster.pgdata);
136
137         /*
138          * Assuming OIDs are only used in system tables, there is no need to
139          * restore the OID counter because we have not transferred any OIDs from
140          * the old system, but we do it anyway just in case.  We do it late here
141          * because there is no need to have the schema load use new oids.
142          */
143         prep_status("Setting next OID for new cluster");
144         exec_prog(true, true, UTILITY_LOG_FILE,
145                           SYSTEMQUOTE "\"%s/pg_resetxlog\" -o %u \"%s\" >> \"%s\" 2>&1"
146                           SYSTEMQUOTE,
147                           new_cluster.bindir, old_cluster.controldata.chkpnt_nxtoid,
148                           new_cluster.pgdata, UTILITY_LOG_FILE);
149         check_ok();
150
151         create_script_for_cluster_analyze(&analyze_script_file_name);
152         create_script_for_old_cluster_deletion(&deletion_script_file_name);
153
154         issue_warnings(sequence_script_file_name);
155
156         pg_log(PG_REPORT, "\nUpgrade Complete\n");
157         pg_log(PG_REPORT, "----------------\n");
158
159         output_completion_banner(analyze_script_file_name,
160                                                          deletion_script_file_name);
161
162         pg_free(analyze_script_file_name);
163         pg_free(deletion_script_file_name);
164         pg_free(sequence_script_file_name);
165
166         cleanup();
167
168         return 0;
169 }
170
171
172 static void
173 setup(char *argv0, bool live_check)
174 {
175         char            exec_path[MAXPGPATH];   /* full path to my executable */
176
177         /*
178          * make sure the user has a clean environment, otherwise, we may confuse
179          * libpq when we connect to one (or both) of the servers.
180          */
181         check_pghost_envvar();
182
183         verify_directories();
184
185         /* no postmasters should be running */
186         if (!live_check && is_server_running(old_cluster.pgdata))
187                 pg_log(PG_FATAL, "There seems to be a postmaster servicing the old cluster.\n"
188                            "Please shutdown that postmaster and try again.\n");
189
190         /* same goes for the new postmaster */
191         if (is_server_running(new_cluster.pgdata))
192                 pg_log(PG_FATAL, "There seems to be a postmaster servicing the new cluster.\n"
193                            "Please shutdown that postmaster and try again.\n");
194
195         /* get path to pg_upgrade executable */
196         if (find_my_exec(argv0, exec_path) < 0)
197                 pg_log(PG_FATAL, "Could not get path name to pg_upgrade: %s\n", getErrorText(errno));
198
199         /* Trim off program name and keep just path */
200         *last_dir_separator(exec_path) = '\0';
201         canonicalize_path(exec_path);
202         os_info.exec_path = pg_strdup(exec_path);
203 }
204
205
206 static void
207 prepare_new_cluster(void)
208 {
209         /*
210          * It would make more sense to freeze after loading the schema, but that
211          * would cause us to lose the frozenids restored by the load. We use
212          * --analyze so autovacuum doesn't update statistics later
213          */
214         prep_status("Analyzing all rows in the new cluster");
215         exec_prog(true, true, UTILITY_LOG_FILE,
216                           SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
217                           "--all --analyze %s >> \"%s\" 2>&1" SYSTEMQUOTE,
218           new_cluster.bindir, new_cluster.port, os_info.user,
219           log_opts.verbose ? "--verbose" : "", UTILITY_LOG_FILE);
220         check_ok();
221
222         /*
223          * We do freeze after analyze so pg_statistic is also frozen. template0 is
224          * not frozen here, but data rows were frozen by initdb, and we set its
225          * datfrozenxid and relfrozenxids later to match the new xid counter
226          * later.
227          */
228         prep_status("Freezing all rows on the new cluster");
229         exec_prog(true, true, UTILITY_LOG_FILE,
230                           SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
231                           "--all --freeze %s >> \"%s\" 2>&1" SYSTEMQUOTE,
232           new_cluster.bindir, new_cluster.port, os_info.user,
233           log_opts.verbose ? "--verbose" : "", UTILITY_LOG_FILE);
234         check_ok();
235
236         get_pg_database_relfilenode(&new_cluster);
237 }
238
239
240 static void
241 prepare_new_databases(void)
242 {
243         /*
244          * We set autovacuum_freeze_max_age to its maximum value so autovacuum
245          * does not launch here and delete clog files, before the frozen xids are
246          * set.
247          */
248
249         set_frozenxids();
250
251         prep_status("Creating databases in the new cluster");
252
253         /*
254          * Install support functions in the global-object restore database to
255          * preserve pg_authid.oid.  pg_dumpall uses 'template0' as its template
256          * database so objects we add into 'template1' are not propogated.  They
257          * are removed on pg_upgrade exit.
258          */
259         install_support_functions_in_new_db("template1");
260
261         /*
262          * We have to create the databases first so we can install support
263          * functions in all the other databases.  Ideally we could create the
264          * support functions in template1 but pg_dumpall creates database using
265          * the template0 template.
266          */
267         exec_prog(true, true, RESTORE_LOG_FILE,
268                           SYSTEMQUOTE "\"%s/psql\" --echo-queries "
269                           "--set ON_ERROR_STOP=on "
270                           /* --no-psqlrc prevents AUTOCOMMIT=off */
271                           "--no-psqlrc --port %d --username \"%s\" "
272                           "-f \"%s\" --dbname template1 >> \"%s\" 2>&1" SYSTEMQUOTE,
273                           new_cluster.bindir, new_cluster.port, os_info.user,
274                           GLOBALS_DUMP_FILE, RESTORE_LOG_FILE);
275         check_ok();
276
277         /* we load this to get a current list of databases */
278         get_db_and_rel_infos(&new_cluster);
279 }
280
281
282 static void
283 create_new_objects(void)
284 {
285         int                     dbnum;
286
287         prep_status("Adding support functions to new cluster");
288
289         for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
290         {
291                 DbInfo     *new_db = &new_cluster.dbarr.dbs[dbnum];
292
293                 /* skip db we already installed */
294                 if (strcmp(new_db->db_name, "template1") != 0)
295                         install_support_functions_in_new_db(new_db->db_name);
296         }
297         check_ok();
298
299         prep_status("Restoring database schema to new cluster");
300         exec_prog(true, true, RESTORE_LOG_FILE,
301                           SYSTEMQUOTE "\"%s/psql\" --echo-queries "
302                           "--set ON_ERROR_STOP=on "
303                           "--no-psqlrc --port %d --username \"%s\" "
304                           "-f \"%s\" --dbname template1 >> \"%s\" 2>&1" SYSTEMQUOTE,
305                           new_cluster.bindir, new_cluster.port, os_info.user,
306                           DB_DUMP_FILE, RESTORE_LOG_FILE);
307         check_ok();
308
309         /* regenerate now that we have objects in the databases */
310         get_db_and_rel_infos(&new_cluster);
311
312         uninstall_support_functions_from_new_cluster();
313 }
314
315
316 static void
317 copy_clog_xlog_xid(void)
318 {
319         char            old_clog_path[MAXPGPATH];
320         char            new_clog_path[MAXPGPATH];
321
322         /* copy old commit logs to new data dir */
323         prep_status("Deleting new commit clogs");
324
325         snprintf(old_clog_path, sizeof(old_clog_path), "%s/pg_clog", old_cluster.pgdata);
326         snprintf(new_clog_path, sizeof(new_clog_path), "%s/pg_clog", new_cluster.pgdata);
327         if (!rmtree(new_clog_path, true))
328                 pg_log(PG_FATAL, "could not delete directory \"%s\"\n", new_clog_path);
329         check_ok();
330
331         prep_status("Copying old commit clogs to new server");
332         exec_prog(true, false, UTILITY_LOG_FILE,
333 #ifndef WIN32
334                           SYSTEMQUOTE "%s \"%s\" \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE,
335                           "cp -Rf",
336 #else
337         /* flags: everything, no confirm, quiet, overwrite read-only */
338                           SYSTEMQUOTE "%s \"%s\" \"%s\\\" >> \"%s\" 2>&1" SYSTEMQUOTE,
339                           "xcopy /e /y /q /r",
340 #endif
341                           old_clog_path, new_clog_path, UTILITY_LOG_FILE);
342         check_ok();
343
344         /* set the next transaction id of the new cluster */
345         prep_status("Setting next transaction ID for new cluster");
346         exec_prog(true, true, UTILITY_LOG_FILE,
347                           SYSTEMQUOTE
348                           "\"%s/pg_resetxlog\" -f -x %u \"%s\" >> \"%s\" 2>&1"
349                           SYSTEMQUOTE, new_cluster.bindir,
350                           old_cluster.controldata.chkpnt_nxtxid,
351                           new_cluster.pgdata, UTILITY_LOG_FILE);
352         check_ok();
353
354         /* now reset the wal archives in the new cluster */
355         prep_status("Resetting WAL archives");
356         exec_prog(true, true, UTILITY_LOG_FILE,
357                           SYSTEMQUOTE
358                           "\"%s/pg_resetxlog\" -l %u,%u,%u \"%s\" >> \"%s\" 2>&1"
359                           SYSTEMQUOTE, new_cluster.bindir,
360                           old_cluster.controldata.chkpnt_tli,
361                           old_cluster.controldata.logid,
362                           old_cluster.controldata.nxtlogseg,
363                           new_cluster.pgdata, UTILITY_LOG_FILE);
364         check_ok();
365 }
366
367
368 /*
369  *      set_frozenxids()
370  *
371  *      We have frozen all xids, so set relfrozenxid and datfrozenxid
372  *      to be the old cluster's xid counter, which we just set in the new
373  *      cluster.  User-table frozenxid values will be set by pg_dumpall
374  *      --binary-upgrade, but objects not set by the pg_dump must have
375  *      proper frozen counters.
376  */
377 static
378 void
379 set_frozenxids(void)
380 {
381         int                     dbnum;
382         PGconn     *conn,
383                            *conn_template1;
384         PGresult   *dbres;
385         int                     ntups;
386         int                     i_datname;
387         int                     i_datallowconn;
388
389         prep_status("Setting frozenxid counters in new cluster");
390
391         conn_template1 = connectToServer(&new_cluster, "template1");
392
393         /* set pg_database.datfrozenxid */
394         PQclear(executeQueryOrDie(conn_template1,
395                                                           "UPDATE pg_catalog.pg_database "
396                                                           "SET  datfrozenxid = '%u'",
397                                                           old_cluster.controldata.chkpnt_nxtxid));
398
399         /* get database names */
400         dbres = executeQueryOrDie(conn_template1,
401                                                           "SELECT       datname, datallowconn "
402                                                           "FROM pg_catalog.pg_database");
403
404         i_datname = PQfnumber(dbres, "datname");
405         i_datallowconn = PQfnumber(dbres, "datallowconn");
406
407         ntups = PQntuples(dbres);
408         for (dbnum = 0; dbnum < ntups; dbnum++)
409         {
410                 char       *datname = PQgetvalue(dbres, dbnum, i_datname);
411                 char       *datallowconn = PQgetvalue(dbres, dbnum, i_datallowconn);
412
413                 /*
414                  * We must update databases where datallowconn = false, e.g.
415                  * template0, because autovacuum increments their datfrozenxids and
416                  * relfrozenxids even if autovacuum is turned off, and even though all
417                  * the data rows are already frozen  To enable this, we temporarily
418                  * change datallowconn.
419                  */
420                 if (strcmp(datallowconn, "f") == 0)
421                         PQclear(executeQueryOrDie(conn_template1,
422                                                                           "UPDATE pg_catalog.pg_database "
423                                                                           "SET  datallowconn = true "
424                                                                           "WHERE datname = '%s'", datname));
425
426                 conn = connectToServer(&new_cluster, datname);
427
428                 /* set pg_class.relfrozenxid */
429                 PQclear(executeQueryOrDie(conn,
430                                                                   "UPDATE       pg_catalog.pg_class "
431                                                                   "SET  relfrozenxid = '%u' "
432                 /* only heap and TOAST are vacuumed */
433                                                                   "WHERE        relkind IN ('r', 't')",
434                                                                   old_cluster.controldata.chkpnt_nxtxid));
435                 PQfinish(conn);
436
437                 /* Reset datallowconn flag */
438                 if (strcmp(datallowconn, "f") == 0)
439                         PQclear(executeQueryOrDie(conn_template1,
440                                                                           "UPDATE pg_catalog.pg_database "
441                                                                           "SET  datallowconn = false "
442                                                                           "WHERE datname = '%s'", datname));
443         }
444
445         PQclear(dbres);
446
447         PQfinish(conn_template1);
448
449         check_ok();
450 }
451
452
453 static void
454 cleanup(void)
455 {
456         
457         fclose(log_opts.internal);
458
459         /* Remove dump and log files? */
460         if (!log_opts.retain)
461         {
462                 char            **filename;
463
464                 for (filename = output_files; *filename != NULL; filename++)
465                         unlink(*filename);
466
467                 /* remove SQL files */
468                 unlink(ALL_DUMP_FILE);
469                 unlink(GLOBALS_DUMP_FILE);
470                 unlink(DB_DUMP_FILE);
471         }
472 }