]> granicus.if.org Git - postgresql/blob - src/bin/pg_upgrade/server.c
pgindent run for 9.5
[postgresql] / src / bin / pg_upgrade / server.c
1 /*
2  *      server.c
3  *
4  *      database server functions
5  *
6  *      Copyright (c) 2010-2015, PostgreSQL Global Development Group
7  *      src/bin/pg_upgrade/server.c
8  */
9
10 #include "postgres_fe.h"
11
12 #include "pg_upgrade.h"
13
14
15 static PGconn *get_db_conn(ClusterInfo *cluster, const char *db_name);
16
17
18 /*
19  * connectToServer()
20  *
21  *      Connects to the desired database on the designated server.
22  *      If the connection attempt fails, this function logs an error
23  *      message and calls exit() to kill the program.
24  */
25 PGconn *
26 connectToServer(ClusterInfo *cluster, const char *db_name)
27 {
28         PGconn     *conn = get_db_conn(cluster, db_name);
29
30         if (conn == NULL || PQstatus(conn) != CONNECTION_OK)
31         {
32                 pg_log(PG_REPORT, "connection to database failed: %s\n",
33                            PQerrorMessage(conn));
34
35                 if (conn)
36                         PQfinish(conn);
37
38                 printf("Failure, exiting\n");
39                 exit(1);
40         }
41
42         return conn;
43 }
44
45
46 /*
47  * get_db_conn()
48  *
49  * get database connection, using named database + standard params for cluster
50  */
51 static PGconn *
52 get_db_conn(ClusterInfo *cluster, const char *db_name)
53 {
54         char            conn_opts[2 * NAMEDATALEN + MAXPGPATH + 100];
55
56         if (cluster->sockdir)
57                 snprintf(conn_opts, sizeof(conn_opts),
58                                  "dbname = '%s' user = '%s' host = '%s' port = %d",
59                                  db_name, os_info.user, cluster->sockdir, cluster->port);
60         else
61                 snprintf(conn_opts, sizeof(conn_opts),
62                                  "dbname = '%s' user = '%s' port = %d",
63                                  db_name, os_info.user, cluster->port);
64
65         return PQconnectdb(conn_opts);
66 }
67
68
69 /*
70  * cluster_conn_opts()
71  *
72  * Return standard command-line options for connecting to this cluster when
73  * using psql, pg_dump, etc.  Ideally this would match what get_db_conn()
74  * sets, but the utilities we need aren't very consistent about the treatment
75  * of database name options, so we leave that out.
76  *
77  * Note result is in static storage, so use it right away.
78  */
79 char *
80 cluster_conn_opts(ClusterInfo *cluster)
81 {
82         static char conn_opts[MAXPGPATH + NAMEDATALEN + 100];
83
84         if (cluster->sockdir)
85                 snprintf(conn_opts, sizeof(conn_opts),
86                                  "--host \"%s\" --port %d --username \"%s\"",
87                                  cluster->sockdir, cluster->port, os_info.user);
88         else
89                 snprintf(conn_opts, sizeof(conn_opts),
90                                  "--port %d --username \"%s\"",
91                                  cluster->port, os_info.user);
92
93         return conn_opts;
94 }
95
96
97 /*
98  * executeQueryOrDie()
99  *
100  *      Formats a query string from the given arguments and executes the
101  *      resulting query.  If the query fails, this function logs an error
102  *      message and calls exit() to kill the program.
103  */
104 PGresult *
105 executeQueryOrDie(PGconn *conn, const char *fmt,...)
106 {
107         static char query[QUERY_ALLOC];
108         va_list         args;
109         PGresult   *result;
110         ExecStatusType status;
111
112         va_start(args, fmt);
113         vsnprintf(query, sizeof(query), fmt, args);
114         va_end(args);
115
116         pg_log(PG_VERBOSE, "executing: %s\n", query);
117         result = PQexec(conn, query);
118         status = PQresultStatus(result);
119
120         if ((status != PGRES_TUPLES_OK) && (status != PGRES_COMMAND_OK))
121         {
122                 pg_log(PG_REPORT, "SQL command failed\n%s\n%s\n", query,
123                            PQerrorMessage(conn));
124                 PQclear(result);
125                 PQfinish(conn);
126                 printf("Failure, exiting\n");
127                 exit(1);
128         }
129         else
130                 return result;
131 }
132
133
134 /*
135  * get_major_server_version()
136  *
137  * gets the version (in unsigned int form) for the given datadir. Assumes
138  * that datadir is an absolute path to a valid pgdata directory. The version
139  * is retrieved by reading the PG_VERSION file.
140  */
141 uint32
142 get_major_server_version(ClusterInfo *cluster)
143 {
144         FILE       *version_fd;
145         char            ver_filename[MAXPGPATH];
146         int                     integer_version = 0;
147         int                     fractional_version = 0;
148
149         snprintf(ver_filename, sizeof(ver_filename), "%s/PG_VERSION",
150                          cluster->pgdata);
151         if ((version_fd = fopen(ver_filename, "r")) == NULL)
152                 pg_fatal("could not open version file: %s\n", ver_filename);
153
154         if (fscanf(version_fd, "%63s", cluster->major_version_str) == 0 ||
155                 sscanf(cluster->major_version_str, "%d.%d", &integer_version,
156                            &fractional_version) != 2)
157                 pg_fatal("could not get version from %s\n", cluster->pgdata);
158
159         fclose(version_fd);
160
161         return (100 * integer_version + fractional_version) * 100;
162 }
163
164
165 static void
166 stop_postmaster_atexit(void)
167 {
168         stop_postmaster(true);
169 }
170
171
172 bool
173 start_postmaster(ClusterInfo *cluster, bool throw_error)
174 {
175         char            cmd[MAXPGPATH * 4 + 1000];
176         PGconn     *conn;
177         bool            exit_hook_registered = false;
178         bool            pg_ctl_return = false;
179         char            socket_string[MAXPGPATH + 200];
180
181         if (!exit_hook_registered)
182         {
183                 atexit(stop_postmaster_atexit);
184                 exit_hook_registered = true;
185         }
186
187         socket_string[0] = '\0';
188
189 #ifdef HAVE_UNIX_SOCKETS
190         /* prevent TCP/IP connections, restrict socket access */
191         strcat(socket_string,
192                    " -c listen_addresses='' -c unix_socket_permissions=0700");
193
194         /* Have a sockdir?      Tell the postmaster. */
195         if (cluster->sockdir)
196                 snprintf(socket_string + strlen(socket_string),
197                                  sizeof(socket_string) - strlen(socket_string),
198                                  " -c %s='%s'",
199                                  (GET_MAJOR_VERSION(cluster->major_version) < 903) ?
200                                  "unix_socket_directory" : "unix_socket_directories",
201                                  cluster->sockdir);
202 #endif
203
204         /*
205          * Since PG 9.1, we have used -b to disable autovacuum.  For earlier
206          * releases, setting autovacuum=off disables cleanup vacuum and analyze,
207          * but freeze vacuums can still happen, so we set
208          * autovacuum_freeze_max_age to its maximum.
209          * (autovacuum_multixact_freeze_max_age was introduced after 9.1, so there
210          * is no need to set that.)  We assume all datfrozenxid and relfrozenxid
211          * values are less than a gap of 2000000000 from the current xid counter,
212          * so autovacuum will not touch them.
213          *
214          * Turn off durability requirements to improve object creation speed, and
215          * we only modify the new cluster, so only use it there.  If there is a
216          * crash, the new cluster has to be recreated anyway.  fsync=off is a big
217          * win on ext4.
218          */
219         snprintf(cmd, sizeof(cmd),
220                   "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" -o \"-p %d%s%s %s%s\" start",
221                   cluster->bindir, SERVER_LOG_FILE, cluster->pgconfig, cluster->port,
222                          (cluster->controldata.cat_ver >=
223                           BINARY_UPGRADE_SERVER_FLAG_CAT_VER) ? " -b" :
224                          " -c autovacuum=off -c autovacuum_freeze_max_age=2000000000",
225                          (cluster == &new_cluster) ?
226           " -c synchronous_commit=off -c fsync=off -c full_page_writes=off" : "",
227                          cluster->pgopts ? cluster->pgopts : "", socket_string);
228
229         /*
230          * Don't throw an error right away, let connecting throw the error because
231          * it might supply a reason for the failure.
232          */
233         pg_ctl_return = exec_prog(SERVER_START_LOG_FILE,
234         /* pass both file names if they differ */
235                                                           (strcmp(SERVER_LOG_FILE,
236                                                                           SERVER_START_LOG_FILE) != 0) ?
237                                                           SERVER_LOG_FILE : NULL,
238                                                           false,
239                                                           "%s", cmd);
240
241         /* Did it fail and we are just testing if the server could be started? */
242         if (!pg_ctl_return && !throw_error)
243                 return false;
244
245         /*
246          * We set this here to make sure atexit() shuts down the server, but only
247          * if we started the server successfully.  We do it before checking for
248          * connectivity in case the server started but there is a connectivity
249          * failure.  If pg_ctl did not return success, we will exit below.
250          *
251          * Pre-9.1 servers do not have PQping(), so we could be leaving the server
252          * running if authentication was misconfigured, so someday we might went
253          * to be more aggressive about doing server shutdowns even if pg_ctl
254          * fails, but now (2013-08-14) it seems prudent to be cautious.  We don't
255          * want to shutdown a server that might have been accidentally started
256          * during the upgrade.
257          */
258         if (pg_ctl_return)
259                 os_info.running_cluster = cluster;
260
261         /*
262          * pg_ctl -w might have failed because the server couldn't be started, or
263          * there might have been a connection problem in _checking_ if the server
264          * has started.  Therefore, even if pg_ctl failed, we continue and test
265          * for connectivity in case we get a connection reason for the failure.
266          */
267         if ((conn = get_db_conn(cluster, "template1")) == NULL ||
268                 PQstatus(conn) != CONNECTION_OK)
269         {
270                 pg_log(PG_REPORT, "\nconnection to database failed: %s\n",
271                            PQerrorMessage(conn));
272                 if (conn)
273                         PQfinish(conn);
274                 pg_fatal("could not connect to %s postmaster started with the command:\n"
275                                  "%s\n",
276                                  CLUSTER_NAME(cluster), cmd);
277         }
278         PQfinish(conn);
279
280         /*
281          * If pg_ctl failed, and the connection didn't fail, and throw_error is
282          * enabled, fail now.  This could happen if the server was already
283          * running.
284          */
285         if (!pg_ctl_return)
286                 pg_fatal("pg_ctl failed to start the %s server, or connection failed\n",
287                                  CLUSTER_NAME(cluster));
288
289         return true;
290 }
291
292
293 void
294 stop_postmaster(bool fast)
295 {
296         ClusterInfo *cluster;
297
298         if (os_info.running_cluster == &old_cluster)
299                 cluster = &old_cluster;
300         else if (os_info.running_cluster == &new_cluster)
301                 cluster = &new_cluster;
302         else
303                 return;                                 /* no cluster running */
304
305         exec_prog(SERVER_STOP_LOG_FILE, NULL, !fast,
306                           "\"%s/pg_ctl\" -w -D \"%s\" -o \"%s\" %s stop",
307                           cluster->bindir, cluster->pgconfig,
308                           cluster->pgopts ? cluster->pgopts : "",
309                           fast ? "-m fast" : "");
310
311         os_info.running_cluster = NULL;
312 }
313
314
315 /*
316  * check_pghost_envvar()
317  *
318  * Tests that PGHOST does not point to a non-local server
319  */
320 void
321 check_pghost_envvar(void)
322 {
323         PQconninfoOption *option;
324         PQconninfoOption *start;
325
326         /* Get valid libpq env vars from the PQconndefaults function */
327
328         start = PQconndefaults();
329
330         if (!start)
331                 pg_fatal("out of memory\n");
332
333         for (option = start; option->keyword != NULL; option++)
334         {
335                 if (option->envvar && (strcmp(option->envvar, "PGHOST") == 0 ||
336                                                            strcmp(option->envvar, "PGHOSTADDR") == 0))
337                 {
338                         const char *value = getenv(option->envvar);
339
340                         if (value && strlen(value) > 0 &&
341                         /* check for 'local' host values */
342                                 (strcmp(value, "localhost") != 0 && strcmp(value, "127.0.0.1") != 0 &&
343                                  strcmp(value, "::1") != 0 && value[0] != '/'))
344                                 pg_fatal("libpq environment variable %s has a non-local server value: %s\n",
345                                                  option->envvar, value);
346                 }
347         }
348
349         /* Free the memory that libpq allocated on our behalf */
350         PQconninfoFree(start);
351 }