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