]> granicus.if.org Git - postgresql/commitdiff
Back-patch recent pg_upgrade fixes into 9.2.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 3 Sep 2012 19:03:08 +0000 (15:03 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 3 Sep 2012 19:03:08 +0000 (15:03 -0400)
This syncs contrib/pg_upgrade in the 9.2 branch with HEAD, except for the
HEAD changes related to converting XLogRecPtr to 64-bit int.  It includes
back-patching these commits:

666d494d19dbd5dc7a177709a2f7069913f8ab89
pg_upgrade: abstract out copying of files from old cluster to new
7afa8bed65ea925208f128048f3a528a64e1319a
pg_upgrade: Run the created scripts in the test suite
ab577e63faf792593ca728625a8ef0b1dfaf7500
Remove analyze_new_cluster.sh on make clean, too
34c02044ed7e7defde5a853b26dcd806c872d974
Fix thinko in comment
088c065ce8e405fafbfa966937184ece9defcf20
pg_upgrade: Fix exec_prog API to be less flaky
f763b77193b04eba03a1f4ce46df34dc0348419e
Fix pg_upgrade to cope with non-default unix_socket_directory scenarios.

contrib/pg_upgrade/Makefile
contrib/pg_upgrade/check.c
contrib/pg_upgrade/dump.c
contrib/pg_upgrade/exec.c
contrib/pg_upgrade/file.c
contrib/pg_upgrade/option.c
contrib/pg_upgrade/pg_upgrade.c
contrib/pg_upgrade/pg_upgrade.h
contrib/pg_upgrade/server.c
contrib/pg_upgrade/test.sh
doc/src/sgml/pgupgrade.sgml

index 364b20df1ba3d4555da484c49576ab1c5693bff8..dec57a6130d97e3425107c2bba98273d9e2c0c27 100644 (file)
@@ -11,7 +11,7 @@ OBJS = check.o controldata.o dump.o exec.o file.o function.o info.o \
 PG_CPPFLAGS  = -DFRONTEND -DDLSUFFIX=\"$(DLSUFFIX)\" -I$(srcdir) -I$(libpq_srcdir)
 PG_LIBS = $(libpq_pgport)
 
-EXTRA_CLEAN = delete_old_cluster.sh log/ tmp_check/
+EXTRA_CLEAN = analyze_new_cluster.sh delete_old_cluster.sh log/ tmp_check/
 
 ifdef USE_PGXS
 PG_CONFIG = pg_config
index aa896b582375162792eb608fa66b6f28adb599ef..efb080befd4355e68981b35dc32e9b954e10810b 100644 (file)
@@ -183,13 +183,10 @@ issue_warnings(char *sequence_script_file_name)
                if (sequence_script_file_name)
                {
                        prep_status("Adjusting sequences");
-                       exec_prog(true, true, UTILITY_LOG_FILE, NULL,
-                                         SYSTEMQUOTE "\"%s/psql\" --echo-queries "
-                                         "--set ON_ERROR_STOP=on "
-                                         "--no-psqlrc --port %d --username \"%s\" "
-                                  "-f \"%s\" --dbname template1 >> \"%s\" 2>&1" SYSTEMQUOTE,
-                                         new_cluster.bindir, new_cluster.port, os_info.user,
-                                         sequence_script_file_name, UTILITY_LOG_FILE);
+                       exec_prog(UTILITY_LOG_FILE, NULL, true,
+                                         "\"%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();
                }
index 07a3b548a9f750f85a919380c790b6b58def6c9f..b905ab084d7337dc4fc5c5b064e09c9c3ab00552 100644 (file)
@@ -23,12 +23,11 @@ generate_old_dump(void)
         * --binary-upgrade records the width of dropped columns in pg_class, and
         * restores the frozenid's for databases and relations.
         */
-       exec_prog(true, true, UTILITY_LOG_FILE, NULL,
-                         SYSTEMQUOTE "\"%s/pg_dumpall\" --port %d --username \"%s\" "
-                         "--schema-only --binary-upgrade %s > \"%s\" 2>> \"%s\""
-                         SYSTEMQUOTE, new_cluster.bindir, old_cluster.port, os_info.user,
+       exec_prog(UTILITY_LOG_FILE, NULL, true,
+                         "\"%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, UTILITY_LOG_FILE);
+                         ALL_DUMP_FILE);
        check_ok();
 }
 
index 6f993df53a3dc0ec71c272b1f8b9ccb5d68f5e25..c75d9dbcc9722ccb69be626110228205e5e9e1c0 100644 (file)
@@ -26,77 +26,81 @@ static int  win32_check_directory_write_permissions(void);
 
 /*
  * exec_prog()
+ *             Execute an external program with stdout/stderr redirected, and report
+ *             errors
  *
- *     Formats a command from the given argument list and executes that
- *     command.  If the command executes, exec_prog() returns 1 otherwise
- *     exec_prog() logs an error message and returns 0.  Either way, the command
- *     line to be executed is saved to the specified log file.
+ * Formats a command from the given argument list, logs it to the log file,
+ * and attempts to execute that command.  If the command executes
+ * successfully, exec_prog() returns true.
  *
- *     If throw_error is TRUE, this function will throw a PG_FATAL error
- *     instead of returning should an error occur.  The command it appended
- *     to log_file;  opt_log_file is used in error messages.
+ * If the command fails, an error message is saved to the specified log_file.
+ * If throw_error is true, this raises a PG_FATAL error and pg_upgrade
+ * terminates; otherwise it is just reported as PG_REPORT and exec_prog()
+ * returns false.
  */
-int
-exec_prog(bool throw_error, bool is_priv, const char *log_file,
-                 const char *opt_log_file, const char *fmt,...)
+bool
+exec_prog(const char *log_file, const char *opt_log_file,
+                 bool throw_error, const char *fmt,...)
 {
-       va_list         args;
        int                     result;
-       int                     retval;
-       char            cmd[MAXPGPATH];
+       int                     written;
+#define MAXCMDLEN (2 * MAXPGPATH)
+       char            cmd[MAXCMDLEN];
        mode_t          old_umask = 0;
        FILE       *log;
+       va_list         ap;
 
-       if (is_priv)
-               old_umask = umask(S_IRWXG | S_IRWXO);
+       old_umask = umask(S_IRWXG | S_IRWXO);
 
-       va_start(args, fmt);
-       vsnprintf(cmd, MAXPGPATH, fmt, args);
-       va_end(args);
+       written = strlcpy(cmd, SYSTEMQUOTE, strlen(SYSTEMQUOTE));
+       va_start(ap, fmt);
+       written += vsnprintf(cmd + written, MAXCMDLEN - written, fmt, ap);
+       va_end(ap);
+       if (written >= MAXCMDLEN)
+               pg_log(PG_FATAL, "command too long\n");
+       written += snprintf(cmd + written, MAXCMDLEN - written,
+                                               " >> \"%s\" 2>&1" SYSTEMQUOTE, log_file);
+       if (written >= MAXCMDLEN)
+               pg_log(PG_FATAL, "command too long\n");
 
        if ((log = fopen_priv(log_file, "a+")) == NULL)
                pg_log(PG_FATAL, "cannot write to log file %s\n", log_file);
        pg_log(PG_VERBOSE, "%s\n", cmd);
        fprintf(log, "command: %s\n", cmd);
+
        /*
-        *      In Windows, we must close then reopen the log file so the file is
-        *      not open while the command is running, or we get a share violation.
+        * In Windows, we must close the log file at this point so the file is not
+        * open while the command is running, or we get a share violation.
         */
        fclose(log);
 
        result = system(cmd);
 
-       if (is_priv)
-               umask(old_umask);
+       umask(old_umask);
 
        if (result != 0)
        {
-               char opt_string[MAXPGPATH];
-
-               /* Create string for optional second log file */
-               if (opt_log_file)
-                       snprintf(opt_string, sizeof(opt_string), " or \"%s\"", opt_log_file);
-               else
-                       opt_string[0] = '\0';
-
                report_status(PG_REPORT, "*failure*");
                fflush(stdout);
                pg_log(PG_VERBOSE, "There were problems executing \"%s\"\n", cmd);
-               pg_log(throw_error ? PG_FATAL : PG_REPORT,
-                          "Consult the last few lines of \"%s\"%s for\n"
-                          "the probable cause of the failure.\n",
-                          log_file, opt_string);
-               retval = 1;
+               if (opt_log_file)
+                       pg_log(throw_error ? PG_FATAL : PG_REPORT,
+                                  "Consult the last few lines of \"%s\" or \"%s\" for\n"
+                                  "the probable cause of the failure.\n",
+                                  log_file, opt_log_file);
+               else
+                       pg_log(throw_error ? PG_FATAL : PG_REPORT,
+                                  "Consult the last few lines of \"%s\" for\n"
+                                  "the probable cause of the failure.\n",
+                                  log_file);
        }
-       else
-               retval = 0;
 
        if ((log = fopen_priv(log_file, "a+")) == NULL)
                pg_log(PG_FATAL, "cannot write to log file %s\n", log_file);
        fprintf(log, "\n\n");
        fclose(log);
 
-       return retval;
+       return result == 0;
 }
 
 
index 550967009b3dc815883df3635f58fb4e2b81e316..a5d92c62fce80bbd582b727b6f5c66c72ec0d84e 100644 (file)
@@ -103,10 +103,10 @@ copyAndUpdateFile(pageCnvCtx *pageConverter,
 /*
  * linkAndUpdateFile()
  *
- * Creates a symbolic link between the given relation files. We use
+ * Creates a hard link between the given relation files. We use
  * this function to perform a true in-place update. If the on-disk
  * format of the new cluster is bit-for-bit compatible with the on-disk
- * format of the old cluster, we can simply symlink each relation
+ * format of the old cluster, we can simply link each relation
  * instead of copying the data from the old cluster to the new cluster.
  */
 const char *
index 94bce505cb6bda2473442ea1231bb439411ddabc..6d5a93a0a566d433222d97ab762a91bc39274a3f 100644 (file)
@@ -9,6 +9,8 @@
 
 #include "postgres.h"
 
+#include "miscadmin.h"
+
 #include "pg_upgrade.h"
 
 #include <getopt_long.h>
@@ -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
+}
index 5a7e8e4c6e1b3a5285263b23426d662509225a27..54c886e11cae36a729e357aa373d62736f988c96 100644 (file)
@@ -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);
 
 
@@ -140,11 +143,10 @@ main(int argc, char **argv)
         * because there is no need to have the schema load use new oids.
         */
        prep_status("Setting next OID for new cluster");
-       exec_prog(true, true, UTILITY_LOG_FILE, NULL,
-                         SYSTEMQUOTE "\"%s/pg_resetxlog\" -o %u \"%s\" >> \"%s\" 2>&1"
-                         SYSTEMQUOTE,
+       exec_prog(UTILITY_LOG_FILE, NULL, true,
+                         "\"%s/pg_resetxlog\" -o %u \"%s\"",
                          new_cluster.bindir, old_cluster.controldata.chkpnt_nxtoid,
-                         new_cluster.pgdata, UTILITY_LOG_FILE);
+                         new_cluster.pgdata);
        check_ok();
 
        create_script_for_cluster_analyze(&analyze_script_file_name);
@@ -211,11 +213,10 @@ prepare_new_cluster(void)
         * --analyze so autovacuum doesn't update statistics later
         */
        prep_status("Analyzing all rows in the new cluster");
-       exec_prog(true, true, UTILITY_LOG_FILE, NULL,
-                         SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
-                         "--all --analyze %s >> \"%s\" 2>&1" SYSTEMQUOTE,
-                         new_cluster.bindir, new_cluster.port, os_info.user,
-                         log_opts.verbose ? "--verbose" : "", UTILITY_LOG_FILE);
+       exec_prog(UTILITY_LOG_FILE, NULL, true,
+                         "\"%s/vacuumdb\" %s --all --analyze %s",
+                         new_cluster.bindir, cluster_conn_opts(&new_cluster),
+                         log_opts.verbose ? "--verbose" : "");
        check_ok();
 
        /*
@@ -225,11 +226,10 @@ prepare_new_cluster(void)
         * later.
         */
        prep_status("Freezing all rows on the new cluster");
-       exec_prog(true, true, UTILITY_LOG_FILE, NULL,
-                         SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
-                         "--all --freeze %s >> \"%s\" 2>&1" SYSTEMQUOTE,
-                         new_cluster.bindir, new_cluster.port, os_info.user,
-                         log_opts.verbose ? "--verbose" : "", UTILITY_LOG_FILE);
+       exec_prog(UTILITY_LOG_FILE, NULL, true,
+                         "\"%s/vacuumdb\" %s --all --freeze %s",
+                         new_cluster.bindir, cluster_conn_opts(&new_cluster),
+                         log_opts.verbose ? "--verbose" : "");
        check_ok();
 
        get_pg_database_relfilenode(&new_cluster);
@@ -263,14 +263,10 @@ prepare_new_databases(void)
         * support functions in template1 but pg_dumpall creates database using
         * the template0 template.
         */
-       exec_prog(true, true, RESTORE_LOG_FILE, NULL,
-                         SYSTEMQUOTE "\"%s/psql\" --echo-queries "
-                         "--set ON_ERROR_STOP=on "
-       /* --no-psqlrc prevents AUTOCOMMIT=off */
-                         "--no-psqlrc --port %d --username \"%s\" "
-                         "-f \"%s\" --dbname template1 >> \"%s\" 2>&1" SYSTEMQUOTE,
-                         new_cluster.bindir, new_cluster.port, os_info.user,
-                         GLOBALS_DUMP_FILE, RESTORE_LOG_FILE);
+       exec_prog(RESTORE_LOG_FILE, NULL, true,
+                         "\"%s/psql\" " EXEC_PSQL_ARGS " %s -f \"%s\"",
+                         new_cluster.bindir, cluster_conn_opts(&new_cluster),
+                         GLOBALS_DUMP_FILE);
        check_ok();
 
        /* we load this to get a current list of databases */
@@ -296,13 +292,10 @@ create_new_objects(void)
        check_ok();
 
        prep_status("Restoring database schema to new cluster");
-       exec_prog(true, true, RESTORE_LOG_FILE, NULL,
-                         SYSTEMQUOTE "\"%s/psql\" --echo-queries "
-                         "--set ON_ERROR_STOP=on "
-                         "--no-psqlrc --port %d --username \"%s\" "
-                         "-f \"%s\" --dbname template1 >> \"%s\" 2>&1" SYSTEMQUOTE,
-                         new_cluster.bindir, new_cluster.port, os_info.user,
-                         DB_DUMP_FILE, RESTORE_LOG_FILE);
+       exec_prog(RESTORE_LOG_FILE, NULL, true,
+                         "\"%s/psql\" " EXEC_PSQL_ARGS " %s -f \"%s\"",
+                         new_cluster.bindir, cluster_conn_opts(&new_cluster),
+                         DB_DUMP_FILE);
        check_ok();
 
        /* regenerate now that we have objects in the databases */
@@ -311,55 +304,60 @@ create_new_objects(void)
        uninstall_support_functions_from_new_cluster();
 }
 
-
+/*
+ * Delete the given subdirectory contents from the new cluster, and copy the
+ * files from the old cluster into it.
+ */
 static void
-copy_clog_xlog_xid(void)
+copy_subdir_files(char *subdir)
 {
-       char            old_clog_path[MAXPGPATH];
-       char            new_clog_path[MAXPGPATH];
+       char            old_path[MAXPGPATH];
+       char            new_path[MAXPGPATH];
 
-       /* copy old commit logs to new data dir */
-       prep_status("Deleting new commit clogs");
+       prep_status("Deleting files from new %s", subdir);
 
-       snprintf(old_clog_path, sizeof(old_clog_path), "%s/pg_clog", old_cluster.pgdata);
-       snprintf(new_clog_path, sizeof(new_clog_path), "%s/pg_clog", new_cluster.pgdata);
-       if (!rmtree(new_clog_path, true))
-               pg_log(PG_FATAL, "could not delete directory \"%s\"\n", new_clog_path);
+       snprintf(old_path, sizeof(old_path), "%s/%s", old_cluster.pgdata, subdir);
+       snprintf(new_path, sizeof(new_path), "%s/%s", new_cluster.pgdata, subdir);
+       if (!rmtree(new_path, true))
+               pg_log(PG_FATAL, "could not delete directory \"%s\"\n", new_path);
        check_ok();
 
-       prep_status("Copying old commit clogs to new server");
-       exec_prog(true, false, UTILITY_LOG_FILE, NULL,
+       prep_status("Copying old %s to new server", subdir);
+
+       exec_prog(UTILITY_LOG_FILE, NULL, true,
 #ifndef WIN32
-                         SYSTEMQUOTE "%s \"%s\" \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE,
-                         "cp -Rf",
+                         "cp -Rf \"%s\" \"%s\"",
 #else
        /* flags: everything, no confirm, quiet, overwrite read-only */
-                         SYSTEMQUOTE "%s \"%s\" \"%s\\\" >> \"%s\" 2>&1" SYSTEMQUOTE,
-                         "xcopy /e /y /q /r",
+                         "xcopy /e /y /q /r \"%s\" \"%s\\\"",
 #endif
-                         old_clog_path, new_clog_path, UTILITY_LOG_FILE);
+                         old_path, new_path);
+
        check_ok();
+}
+
+static void
+copy_clog_xlog_xid(void)
+{
+       /* copy old commit logs to new data dir */
+       copy_subdir_files("pg_clog");
 
        /* set the next transaction id of the new cluster */
        prep_status("Setting next transaction ID for new cluster");
-       exec_prog(true, true, UTILITY_LOG_FILE, NULL,
-                         SYSTEMQUOTE
-                         "\"%s/pg_resetxlog\" -f -x %u \"%s\" >> \"%s\" 2>&1"
-                         SYSTEMQUOTE, new_cluster.bindir,
-                         old_cluster.controldata.chkpnt_nxtxid,
-                         new_cluster.pgdata, UTILITY_LOG_FILE);
+       exec_prog(UTILITY_LOG_FILE, NULL, true,
+                         "\"%s/pg_resetxlog\" -f -x %u \"%s\"",
+                         new_cluster.bindir, old_cluster.controldata.chkpnt_nxtxid,
+                         new_cluster.pgdata);
        check_ok();
 
        /* now reset the wal archives in the new cluster */
        prep_status("Resetting WAL archives");
-       exec_prog(true, true, UTILITY_LOG_FILE, NULL,
-                         SYSTEMQUOTE
-                         "\"%s/pg_resetxlog\" -l %u,%u,%u \"%s\" >> \"%s\" 2>&1"
-                         SYSTEMQUOTE, new_cluster.bindir,
+       exec_prog(UTILITY_LOG_FILE, NULL, true,
+                         "\"%s/pg_resetxlog\" -l %u,%u,%u \"%s\"", new_cluster.bindir,
                          old_cluster.controldata.chkpnt_tli,
                          old_cluster.controldata.logid,
                          old_cluster.controldata.nxtlogseg,
-                         new_cluster.pgdata, UTILITY_LOG_FILE);
+                         new_cluster.pgdata);
        check_ok();
 }
 
index 77c7150b318b3f0dc0f16b7aec61524810674639..36f3adaf7b97a6397ae588853d18f8863bcc3fd1 100644 (file)
@@ -227,6 +227,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 */
@@ -317,10 +318,11 @@ void              split_old_dump(void);
 
 /* exec.c */
 
-int
-exec_prog(bool throw_error, bool is_priv, const char *log_file,
-                 const char *opt_log_file, const char *cmd,...)
-__attribute__((format(PG_PRINTF_ATTRIBUTE, 5, 6)));
+#define EXEC_PSQL_ARGS "--echo-queries --set ON_ERROR_STOP=on --no-psqlrc --dbname=template1"
+bool
+exec_prog(const char *log_file, const char *opt_log_file,
+                 bool throw_error, const char *fmt,...)
+__attribute__((format(PG_PRINTF_ATTRIBUTE, 4, 5)));
 void           verify_directories(void);
 bool           is_server_running(const char *datadir);
 
@@ -387,6 +389,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 +410,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);
index e94a897c92c89963a4430f877516060acf4668e4..11e7e75d78f8947478be0b092cf135a2a7783614 100644 (file)
@@ -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;
-       int                     pg_ctl_return = 0;
+       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,22 +210,23 @@ start_postmaster(ClusterInfo *cluster)
         * not touch them.
         */
        snprintf(cmd, sizeof(cmd),
-                        SYSTEMQUOTE "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" "
-                        "-o \"-p %d %s %s\" start >> \"%s\" 2>&1" SYSTEMQUOTE,
+                        "\"%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 : "", SERVER_START_LOG_FILE);
+                        cluster->pgopts ? cluster->pgopts : "", socket_string);
 
        /*
         * Don't throw an error right away, let connecting throw the error because
         * it might supply a reason for the failure.
         */
-       pg_ctl_return = exec_prog(false, true, SERVER_START_LOG_FILE,
-       /* pass both file names if the differ */
-                                         (strcmp(SERVER_LOG_FILE, SERVER_START_LOG_FILE) != 0) ?
+       pg_ctl_return = exec_prog(SERVER_START_LOG_FILE,
+                                                         /* pass both file names if they differ */
+                                                         (strcmp(SERVER_LOG_FILE,
+                                                                         SERVER_START_LOG_FILE) != 0) ?
                                                          SERVER_LOG_FILE : NULL,
+                                                         false,
                                                          "%s", cmd);
 
        /* Check to see if we can connect to the server; if not, report it. */
@@ -185,13 +237,14 @@ start_postmaster(ClusterInfo *cluster)
                           PQerrorMessage(conn));
                if (conn)
                        PQfinish(conn);
-               pg_log(PG_FATAL, "could not connect to %s postmaster started with the command: %s\n",
+               pg_log(PG_FATAL, "could not connect to %s postmaster started with the command:\n"
+                          "%s\n",
                           CLUSTER_NAME(cluster), cmd);
        }
        PQfinish(conn);
 
        /* If the connection didn't fail, fail now */
-       if (pg_ctl_return != 0)
+       if (!pg_ctl_return)
                pg_log(PG_FATAL, "pg_ctl failed to start the %s server, or connection failed\n",
                           CLUSTER_NAME(cluster));
 
@@ -202,7 +255,6 @@ start_postmaster(ClusterInfo *cluster)
 void
 stop_postmaster(bool fast)
 {
-       char            cmd[MAXPGPATH];
        ClusterInfo *cluster;
 
        if (os_info.running_cluster == &old_cluster)
@@ -212,14 +264,11 @@ stop_postmaster(bool fast)
        else
                return;                                 /* no cluster running */
 
-       snprintf(cmd, sizeof(cmd),
-                        SYSTEMQUOTE "\"%s/pg_ctl\" -w -D \"%s\" -o \"%s\" "
-                        "%s stop >> \"%s\" 2>&1" SYSTEMQUOTE,
-                        cluster->bindir, cluster->pgconfig,
-                        cluster->pgopts ? cluster->pgopts : "",
-                        fast ? "-m fast" : "", SERVER_STOP_LOG_FILE);
-
-       exec_prog(fast ? false : true, true, SERVER_STOP_LOG_FILE, NULL, "%s", cmd);
+       exec_prog(SERVER_STOP_LOG_FILE, NULL, !fast,
+                         "\"%s/pg_ctl\" -w -D \"%s\" -o \"%s\" %s stop",
+                         cluster->bindir, cluster->pgconfig,
+                         cluster->pgopts ? cluster->pgopts : "",
+                         fast ? "-m fast" : "");
 
        os_info.running_cluster = NULL;
 }
index 299b7a5c477003b47e5d6aaf080678037042f661..31e30af777449c563ffe51ed3b45e20d9ff24856 100644 (file)
@@ -107,6 +107,7 @@ initdb
 pg_upgrade -d "${PGDATA}.old" -D "${PGDATA}" -b "$oldbindir" -B "$bindir"
 
 pg_ctl start -l "$logdir/postmaster2.log" -w
+sh ./analyze_new_cluster.sh
 pg_dumpall >"$temp_root"/dump2.sql || pg_dumpall2_status=$?
 pg_ctl -m fast stop
 if [ -n "$pg_dumpall2_status" ]; then
@@ -114,6 +115,8 @@ if [ -n "$pg_dumpall2_status" ]; then
        exit 1
 fi
 
+sh ./delete_old_cluster.sh
+
 if diff -q "$temp_root"/dump1.sql "$temp_root"/dump2.sql; then
        echo PASSED
        exit 0
index fcbe551e7646f4f0ce7978930b438a92791a64f3..9e43f3ce133ef6b29de12694bfa92bce3a1d0dac 100644 (file)
@@ -367,8 +367,10 @@ pg_upgrade.exe
      Obviously, no one should be accessing the clusters during the
      upgrade.  <application>pg_upgrade</> defaults to running servers
      on port 50432 to avoid unintended client connections.
-     You can use the same port numbers for both clusters because the
-     old and new clusters will not be running at the same time.
+     You can use the same port number for both clusters when doing an
+     upgrade because the old and new clusters will not be running at the
+     same time.  However, when checking an old running server, the old
+     and new port numbers must be different.
     </para>
 
     <para>
@@ -517,6 +519,14 @@ psql --username postgres --file script.sql postgres
    <literal>-d /real-data-directory -o '-D /configuration-directory'</>.
   </para>
 
+  <para>
+   If doing <option>--check</> with a running old server of a pre-9.1 version,
+   and the old server is using a Unix-domain socket directory that is
+   different from the default built into the new <productname>PostgreSQL</>
+   installation, set <envar>PGHOST</> to point to the socket location of the
+   old server.  (This is not relevant on Windows.)
+  </para>
+
   <para>
    A Log-Shipping Standby Server (<xref linkend="warm-standby">) cannot
    be upgraded because the server must allow writes.  The simplest way