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