00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "postgres_fe.h"
00011
00012 #include "pg_upgrade.h"
00013
00014
00015 static PGconn *get_db_conn(ClusterInfo *cluster, const char *db_name);
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 PGconn *
00026 connectToServer(ClusterInfo *cluster, const char *db_name)
00027 {
00028 PGconn *conn = get_db_conn(cluster, db_name);
00029
00030 if (conn == NULL || PQstatus(conn) != CONNECTION_OK)
00031 {
00032 pg_log(PG_REPORT, "connection to database failed: %s\n",
00033 PQerrorMessage(conn));
00034
00035 if (conn)
00036 PQfinish(conn);
00037
00038 printf("Failure, exiting\n");
00039 exit(1);
00040 }
00041
00042 return conn;
00043 }
00044
00045
00046
00047
00048
00049
00050
00051 static PGconn *
00052 get_db_conn(ClusterInfo *cluster, const char *db_name)
00053 {
00054 char conn_opts[2 * NAMEDATALEN + MAXPGPATH + 100];
00055
00056 if (cluster->sockdir)
00057 snprintf(conn_opts, sizeof(conn_opts),
00058 "dbname = '%s' user = '%s' host = '%s' port = %d",
00059 db_name, os_info.user, cluster->sockdir, cluster->port);
00060 else
00061 snprintf(conn_opts, sizeof(conn_opts),
00062 "dbname = '%s' user = '%s' port = %d",
00063 db_name, os_info.user, cluster->port);
00064
00065 return PQconnectdb(conn_opts);
00066 }
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 char *
00080 cluster_conn_opts(ClusterInfo *cluster)
00081 {
00082 static char conn_opts[MAXPGPATH + NAMEDATALEN + 100];
00083
00084 if (cluster->sockdir)
00085 snprintf(conn_opts, sizeof(conn_opts),
00086 "--host \"%s\" --port %d --username \"%s\"",
00087 cluster->sockdir, cluster->port, os_info.user);
00088 else
00089 snprintf(conn_opts, sizeof(conn_opts),
00090 "--port %d --username \"%s\"",
00091 cluster->port, os_info.user);
00092
00093 return conn_opts;
00094 }
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 PGresult *
00105 executeQueryOrDie(PGconn *conn, const char *fmt,...)
00106 {
00107 static char command[8192];
00108 va_list args;
00109 PGresult *result;
00110 ExecStatusType status;
00111
00112 va_start(args, fmt);
00113 vsnprintf(command, sizeof(command), fmt, args);
00114 va_end(args);
00115
00116 pg_log(PG_VERBOSE, "executing: %s\n", command);
00117 result = PQexec(conn, command);
00118 status = PQresultStatus(result);
00119
00120 if ((status != PGRES_TUPLES_OK) && (status != PGRES_COMMAND_OK))
00121 {
00122 pg_log(PG_REPORT, "SQL command failed\n%s\n%s\n", command,
00123 PQerrorMessage(conn));
00124 PQclear(result);
00125 PQfinish(conn);
00126 printf("Failure, exiting\n");
00127 exit(1);
00128 }
00129 else
00130 return result;
00131 }
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 uint32
00142 get_major_server_version(ClusterInfo *cluster)
00143 {
00144 FILE *version_fd;
00145 char ver_filename[MAXPGPATH];
00146 int integer_version = 0;
00147 int fractional_version = 0;
00148
00149 snprintf(ver_filename, sizeof(ver_filename), "%s/PG_VERSION",
00150 cluster->pgdata);
00151 if ((version_fd = fopen(ver_filename, "r")) == NULL)
00152 pg_log(PG_FATAL, "could not open version file: %s\n", ver_filename);
00153
00154 if (fscanf(version_fd, "%63s", cluster->major_version_str) == 0 ||
00155 sscanf(cluster->major_version_str, "%d.%d", &integer_version,
00156 &fractional_version) != 2)
00157 pg_log(PG_FATAL, "could not get version from %s\n", cluster->pgdata);
00158
00159 fclose(version_fd);
00160
00161 return (100 * integer_version + fractional_version) * 100;
00162 }
00163
00164
00165 static void
00166 stop_postmaster_atexit(void)
00167 {
00168 stop_postmaster(true);
00169
00170 }
00171
00172
00173 bool
00174 start_postmaster(ClusterInfo *cluster, bool throw_error)
00175 {
00176 char cmd[MAXPGPATH * 4 + 1000];
00177 PGconn *conn;
00178 bool exit_hook_registered = false;
00179 bool pg_ctl_return = false;
00180 char socket_string[MAXPGPATH + 200];
00181
00182 if (!exit_hook_registered)
00183 {
00184 atexit(stop_postmaster_atexit);
00185 exit_hook_registered = true;
00186 }
00187
00188 socket_string[0] = '\0';
00189
00190 #ifdef HAVE_UNIX_SOCKETS
00191
00192 strcat(socket_string,
00193 " -c listen_addresses='' -c unix_socket_permissions=0700");
00194
00195
00196 if (cluster->sockdir)
00197 snprintf(socket_string + strlen(socket_string),
00198 sizeof(socket_string) - strlen(socket_string),
00199 " -c %s='%s'",
00200 (GET_MAJOR_VERSION(cluster->major_version) < 903) ?
00201 "unix_socket_directory" : "unix_socket_directories",
00202 cluster->sockdir);
00203 #endif
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217 snprintf(cmd, sizeof(cmd),
00218 "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" -o \"-p %d%s%s %s%s\" start",
00219 cluster->bindir, SERVER_LOG_FILE, cluster->pgconfig, cluster->port,
00220 (cluster->controldata.cat_ver >=
00221 BINARY_UPGRADE_SERVER_FLAG_CAT_VER) ? " -b" :
00222 " -c autovacuum=off -c autovacuum_freeze_max_age=2000000000",
00223 (cluster == &new_cluster) ?
00224 " -c synchronous_commit=off -c fsync=off -c full_page_writes=off" : "",
00225 cluster->pgopts ? cluster->pgopts : "", socket_string);
00226
00227
00228
00229
00230
00231 pg_ctl_return = exec_prog(SERVER_START_LOG_FILE,
00232
00233 (strcmp(SERVER_LOG_FILE,
00234 SERVER_START_LOG_FILE) != 0) ?
00235 SERVER_LOG_FILE : NULL,
00236 false,
00237 "%s", cmd);
00238
00239 if (!pg_ctl_return && !throw_error)
00240 return false;
00241
00242
00243 if ((conn = get_db_conn(cluster, "template1")) == NULL ||
00244 PQstatus(conn) != CONNECTION_OK)
00245 {
00246 pg_log(PG_REPORT, "\nconnection to database failed: %s\n",
00247 PQerrorMessage(conn));
00248 if (conn)
00249 PQfinish(conn);
00250 pg_log(PG_FATAL, "could not connect to %s postmaster started with the command:\n"
00251 "%s\n",
00252 CLUSTER_NAME(cluster), cmd);
00253 }
00254 PQfinish(conn);
00255
00256
00257 if (!pg_ctl_return)
00258 pg_log(PG_FATAL, "pg_ctl failed to start the %s server, or connection failed\n",
00259 CLUSTER_NAME(cluster));
00260
00261 os_info.running_cluster = cluster;
00262
00263 return true;
00264 }
00265
00266
00267 void
00268 stop_postmaster(bool fast)
00269 {
00270 ClusterInfo *cluster;
00271
00272 if (os_info.running_cluster == &old_cluster)
00273 cluster = &old_cluster;
00274 else if (os_info.running_cluster == &new_cluster)
00275 cluster = &new_cluster;
00276 else
00277 return;
00278
00279 exec_prog(SERVER_STOP_LOG_FILE, NULL, !fast,
00280 "\"%s/pg_ctl\" -w -D \"%s\" -o \"%s\" %s stop",
00281 cluster->bindir, cluster->pgconfig,
00282 cluster->pgopts ? cluster->pgopts : "",
00283 fast ? "-m fast" : "");
00284
00285 os_info.running_cluster = NULL;
00286 }
00287
00288
00289
00290
00291
00292
00293
00294 void
00295 check_pghost_envvar(void)
00296 {
00297 PQconninfoOption *option;
00298 PQconninfoOption *start;
00299
00300
00301
00302 start = PQconndefaults();
00303
00304 for (option = start; option->keyword != NULL; option++)
00305 {
00306 if (option->envvar && (strcmp(option->envvar, "PGHOST") == 0 ||
00307 strcmp(option->envvar, "PGHOSTADDR") == 0))
00308 {
00309 const char *value = getenv(option->envvar);
00310
00311 if (value && strlen(value) > 0 &&
00312
00313 (strcmp(value, "localhost") != 0 && strcmp(value, "127.0.0.1") != 0 &&
00314 strcmp(value, "::1") != 0 && value[0] != '/'))
00315 pg_log(PG_FATAL,
00316 "libpq environment variable %s has a non-local server value: %s\n",
00317 option->envvar, value);
00318 }
00319 }
00320
00321
00322 PQconninfoFree(start);
00323 }