diff --git a/contrib/pg_upgrade/check.c b/contrib/pg_upgrade/check.c index 0fec73ec7d..efb080befd 100644 --- a/contrib/pg_upgrade/check.c +++ b/contrib/pg_upgrade/check.c @@ -184,8 +184,8 @@ issue_warnings(char *sequence_script_file_name) { prep_status("Adjusting sequences"); exec_prog(UTILITY_LOG_FILE, NULL, true, - "\"%s/psql\" " EXEC_PSQL_ARGS " --port %d --username \"%s\" -f \"%s\"", - new_cluster.bindir, new_cluster.port, os_info.user, + "\"%s/psql\" " EXEC_PSQL_ARGS " %s -f \"%s\"", + new_cluster.bindir, cluster_conn_opts(&new_cluster), sequence_script_file_name); unlink(sequence_script_file_name); check_ok(); diff --git a/contrib/pg_upgrade/dump.c b/contrib/pg_upgrade/dump.c index cfc4017d51..b905ab084d 100644 --- a/contrib/pg_upgrade/dump.c +++ b/contrib/pg_upgrade/dump.c @@ -24,8 +24,8 @@ generate_old_dump(void) * restores the frozenid's for databases and relations. */ exec_prog(UTILITY_LOG_FILE, NULL, true, - "\"%s/pg_dumpall\" --port %d --username \"%s\" --schema-only --binary-upgrade %s -f %s", - new_cluster.bindir, old_cluster.port, os_info.user, + "\"%s/pg_dumpall\" %s --schema-only --binary-upgrade %s -f %s", + new_cluster.bindir, cluster_conn_opts(&old_cluster), log_opts.verbose ? "--verbose" : "", ALL_DUMP_FILE); check_ok(); diff --git a/contrib/pg_upgrade/option.c b/contrib/pg_upgrade/option.c index 94bce505cb..6d5a93a0a5 100644 --- a/contrib/pg_upgrade/option.c +++ b/contrib/pg_upgrade/option.c @@ -9,6 +9,8 @@ #include "postgres.h" +#include "miscadmin.h" + #include "pg_upgrade.h" #include @@ -376,3 +378,64 @@ adjust_data_dir(ClusterInfo *cluster) check_ok(); } + + +/* + * get_sock_dir + * + * Identify the socket directory to use for this cluster. If we're doing + * a live check (old cluster only), we need to find out where the postmaster + * is listening. Otherwise, we're going to put the socket into the current + * directory. + */ +void +get_sock_dir(ClusterInfo *cluster, bool live_check) +{ +#ifdef HAVE_UNIX_SOCKETS + if (!live_check) + { + /* Use the current directory for the socket */ + cluster->sockdir = pg_malloc(MAXPGPATH); + if (!getcwd(cluster->sockdir, MAXPGPATH)) + pg_log(PG_FATAL, "cannot find current directory\n"); + } + else + { + /* + * If we are doing a live check, we will use the old cluster's Unix + * domain socket directory so we can connect to the live server. + */ + + /* sockdir was added to postmaster.pid in PG 9.1 */ + if (GET_MAJOR_VERSION(cluster->major_version) >= 901) + { + char filename[MAXPGPATH]; + FILE *fp; + int i; + + snprintf(filename, sizeof(filename), "%s/postmaster.pid", + cluster->pgdata); + if ((fp = fopen(filename, "r")) == NULL) + pg_log(PG_FATAL, "Could not get socket directory of the old server\n"); + + cluster->sockdir = pg_malloc(MAXPGPATH); + for (i = 0; i < LOCK_FILE_LINE_SOCKET_DIR; i++) + if (fgets(cluster->sockdir, MAXPGPATH, fp) == NULL) + pg_log(PG_FATAL, "Could not get socket directory of the old server\n"); + + fclose(fp); + + /* Remove trailing newline */ + if (strchr(cluster->sockdir, '\n') != NULL) + *strchr(cluster->sockdir, '\n') = '\0'; + } + else + { + /* Can't get live sockdir, so assume the default is OK. */ + cluster->sockdir = NULL; + } + } +#else /* !HAVE_UNIX_SOCKETS */ + cluster->sockdir = NULL; +#endif +} diff --git a/contrib/pg_upgrade/pg_upgrade.c b/contrib/pg_upgrade/pg_upgrade.c index c47c8bba44..ee3a1517f4 100644 --- a/contrib/pg_upgrade/pg_upgrade.c +++ b/contrib/pg_upgrade/pg_upgrade.c @@ -88,6 +88,9 @@ main(int argc, char **argv) check_cluster_versions(); check_cluster_compatibility(live_check); + get_sock_dir(&old_cluster, live_check); + get_sock_dir(&new_cluster, false); + check_old_cluster(live_check, &sequence_script_file_name); @@ -211,8 +214,8 @@ prepare_new_cluster(void) */ prep_status("Analyzing all rows in the new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, - "\"%s/vacuumdb\" --port %d --username \"%s\" --all --analyze %s", - new_cluster.bindir, new_cluster.port, os_info.user, + "\"%s/vacuumdb\" %s --all --analyze %s", + new_cluster.bindir, cluster_conn_opts(&new_cluster), log_opts.verbose ? "--verbose" : ""); check_ok(); @@ -224,8 +227,8 @@ prepare_new_cluster(void) */ prep_status("Freezing all rows on the new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, - "\"%s/vacuumdb\" --port %d --username \"%s\" --all --freeze %s", - new_cluster.bindir, new_cluster.port, os_info.user, + "\"%s/vacuumdb\" %s --all --freeze %s", + new_cluster.bindir, cluster_conn_opts(&new_cluster), log_opts.verbose ? "--verbose" : ""); check_ok(); @@ -261,8 +264,8 @@ prepare_new_databases(void) * the template0 template. */ exec_prog(RESTORE_LOG_FILE, NULL, true, - "\"%s/psql\" " EXEC_PSQL_ARGS " --port %d --username \"%s\" -f \"%s\"", - new_cluster.bindir, new_cluster.port, os_info.user, + "\"%s/psql\" " EXEC_PSQL_ARGS " %s -f \"%s\"", + new_cluster.bindir, cluster_conn_opts(&new_cluster), GLOBALS_DUMP_FILE); check_ok(); @@ -290,8 +293,8 @@ create_new_objects(void) prep_status("Restoring database schema to new cluster"); exec_prog(RESTORE_LOG_FILE, NULL, true, - "\"%s/psql\" " EXEC_PSQL_ARGS " --port %d --username \"%s\" -f \"%s\"", - new_cluster.bindir, new_cluster.port, os_info.user, + "\"%s/psql\" " EXEC_PSQL_ARGS " %s -f \"%s\"", + new_cluster.bindir, cluster_conn_opts(&new_cluster), DB_DUMP_FILE); check_ok(); diff --git a/contrib/pg_upgrade/pg_upgrade.h b/contrib/pg_upgrade/pg_upgrade.h index fa4c6c0a47..7b19d916ff 100644 --- a/contrib/pg_upgrade/pg_upgrade.h +++ b/contrib/pg_upgrade/pg_upgrade.h @@ -226,6 +226,7 @@ typedef struct char *bindir; /* pathname for cluster's executable directory */ char *pgopts; /* options to pass to the server, like pg_ctl * -o */ + char *sockdir; /* directory for Unix Domain socket, if any */ unsigned short port; /* port number where postmaster is waiting */ uint32 major_version; /* PG_VERSION of cluster */ char major_version_str[64]; /* string PG_VERSION of cluster */ @@ -387,6 +388,7 @@ void print_maps(FileNameMap *maps, int n, void parseCommandLine(int argc, char *argv[]); void adjust_data_dir(ClusterInfo *cluster); +void get_sock_dir(ClusterInfo *cluster, bool live_check); /* relfilenode.c */ @@ -407,6 +409,8 @@ PGresult * executeQueryOrDie(PGconn *conn, const char *fmt,...) __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3))); +char *cluster_conn_opts(ClusterInfo *cluster); + void start_postmaster(ClusterInfo *cluster); void stop_postmaster(bool fast); uint32 get_major_server_version(ClusterInfo *cluster); diff --git a/contrib/pg_upgrade/server.c b/contrib/pg_upgrade/server.c index 1fb0d6ccce..11e7e75d78 100644 --- a/contrib/pg_upgrade/server.c +++ b/contrib/pg_upgrade/server.c @@ -46,21 +46,54 @@ connectToServer(ClusterInfo *cluster, const char *db_name) /* * get_db_conn() * - * get database connection + * get database connection, using named database + standard params for cluster */ static PGconn * get_db_conn(ClusterInfo *cluster, const char *db_name) { - char conn_opts[MAXPGPATH]; + char conn_opts[2 * NAMEDATALEN + MAXPGPATH + 100]; - snprintf(conn_opts, sizeof(conn_opts), - "dbname = '%s' user = '%s' port = %d", db_name, os_info.user, - cluster->port); + if (cluster->sockdir) + snprintf(conn_opts, sizeof(conn_opts), + "dbname = '%s' user = '%s' host = '%s' port = %d", + db_name, os_info.user, cluster->sockdir, cluster->port); + else + snprintf(conn_opts, sizeof(conn_opts), + "dbname = '%s' user = '%s' port = %d", + db_name, os_info.user, cluster->port); return PQconnectdb(conn_opts); } +/* + * cluster_conn_opts() + * + * Return standard command-line options for connecting to this cluster when + * using psql, pg_dump, etc. Ideally this would match what get_db_conn() + * sets, but the utilities we need aren't very consistent about the treatment + * of database name options, so we leave that out. + * + * Note result is in static storage, so use it right away. + */ +char * +cluster_conn_opts(ClusterInfo *cluster) +{ + static char conn_opts[MAXPGPATH + NAMEDATALEN + 100]; + + if (cluster->sockdir) + snprintf(conn_opts, sizeof(conn_opts), + "--host \"%s\" --port %d --username \"%s\"", + cluster->sockdir, cluster->port, os_info.user); + else + snprintf(conn_opts, sizeof(conn_opts), + "--port %d --username \"%s\"", + cluster->port, os_info.user); + + return conn_opts; +} + + /* * executeQueryOrDie() * @@ -140,10 +173,11 @@ stop_postmaster_atexit(void) void start_postmaster(ClusterInfo *cluster) { - char cmd[MAXPGPATH]; + char cmd[MAXPGPATH * 4 + 1000]; PGconn *conn; bool exit_hook_registered = false; bool pg_ctl_return = false; + char socket_string[MAXPGPATH + 200]; if (!exit_hook_registered) { @@ -151,6 +185,23 @@ start_postmaster(ClusterInfo *cluster) exit_hook_registered = true; } + socket_string[0] = '\0'; + +#ifdef HAVE_UNIX_SOCKETS + /* prevent TCP/IP connections, restrict socket access */ + strcat(socket_string, + " -c listen_addresses='' -c unix_socket_permissions=0700"); + + /* Have a sockdir? Tell the postmaster. */ + if (cluster->sockdir) + snprintf(socket_string + strlen(socket_string), + sizeof(socket_string) - strlen(socket_string), + " -c %s='%s'", + (GET_MAJOR_VERSION(cluster->major_version) < 903) ? + "unix_socket_directory" : "unix_socket_directories", + cluster->sockdir); +#endif + /* * Using autovacuum=off disables cleanup vacuum and analyze, but freeze * vacuums can still happen, so we set autovacuum_freeze_max_age to its @@ -159,12 +210,12 @@ start_postmaster(ClusterInfo *cluster) * not touch them. */ snprintf(cmd, sizeof(cmd), - "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" -o \"-p %d %s %s\" start", + "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" -o \"-p %d %s %s%s\" start", cluster->bindir, SERVER_LOG_FILE, cluster->pgconfig, cluster->port, (cluster->controldata.cat_ver >= BINARY_UPGRADE_SERVER_FLAG_CAT_VER) ? "-b" : "-c autovacuum=off -c autovacuum_freeze_max_age=2000000000", - cluster->pgopts ? cluster->pgopts : ""); + cluster->pgopts ? cluster->pgopts : "", socket_string); /* * Don't throw an error right away, let connecting throw the error because diff --git a/doc/src/sgml/pgupgrade.sgml b/doc/src/sgml/pgupgrade.sgml index b62aba2641..9e43f3ce13 100644 --- a/doc/src/sgml/pgupgrade.sgml +++ b/doc/src/sgml/pgupgrade.sgml @@ -519,6 +519,14 @@ psql --username postgres --file script.sql postgres -d /real-data-directory -o '-D /configuration-directory'. + + If doing + A Log-Shipping Standby Server () cannot be upgraded because the server must allow writes. The simplest way