]> granicus.if.org Git - postgresql/blobdiff - contrib/pg_upgrade/option.c
Update copyright for 2014
[postgresql] / contrib / pg_upgrade / option.c
index 960fcdace7223a7082858fe8dd8509f0da119f17..79b59ee17d25f7a3fd2d77b19d1d8374f681e036 100644 (file)
@@ -3,11 +3,13 @@
  *
  *     options functions
  *
- *     Copyright (c) 2010-2012, PostgreSQL Global Development Group
+ *     Copyright (c) 2010-2014, PostgreSQL Global Development Group
  *     contrib/pg_upgrade/option.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
+
+#include "miscadmin.h"
 
 #include "pg_upgrade.h"
 
@@ -23,6 +25,7 @@
 static void usage(void);
 static void check_required_directory(char **dirpath, char **configpath,
                                   char *envVarName, char *cmdLineOption, char *description);
+#define FIX_DEFAULT_READ_ONLY "-c default_transaction_read_only=false"
 
 
 UserOpts       user_opts;
@@ -46,10 +49,11 @@ parseCommandLine(int argc, char *argv[])
                {"old-port", required_argument, NULL, 'p'},
                {"new-port", required_argument, NULL, 'P'},
 
-               {"user", required_argument, NULL, 'u'},
+               {"username", required_argument, NULL, 'U'},
                {"check", no_argument, NULL, 'c'},
                {"link", no_argument, NULL, 'k'},
                {"retain", no_argument, NULL, 'r'},
+               {"jobs", required_argument, NULL, 'j'},
                {"verbose", no_argument, NULL, 'v'},
                {NULL, 0, NULL, 0}
        };
@@ -79,8 +83,7 @@ parseCommandLine(int argc, char *argv[])
 
        if (argc > 1)
        {
-               if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0 ||
-                       strcmp(argv[1], "-?") == 0)
+               if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
                {
                        usage();
                        exit(0);
@@ -94,12 +97,12 @@ parseCommandLine(int argc, char *argv[])
 
        /* Allow help and version to be run as root, so do the test here. */
        if (os_user_effective_id == 0)
-               pg_log(PG_FATAL, "%s: cannot be run as root\n", os_info.progname);
+               pg_fatal("%s: cannot be run as root\n", os_info.progname);
 
        if ((log_opts.internal = fopen_priv(INTERNAL_LOG_FILE, "a")) == NULL)
-               pg_log(PG_FATAL, "cannot write to log file %s\n", INTERNAL_LOG_FILE);
+               pg_fatal("cannot write to log file %s\n", INTERNAL_LOG_FILE);
 
-       while ((option = getopt_long(argc, argv, "d:D:b:B:cko:O:p:P:ru:v",
+       while ((option = getopt_long(argc, argv, "d:D:b:B:cj:ko:O:p:P:rU:v",
                                                                 long_options, &optindex)) != -1)
        {
                switch (option)
@@ -126,6 +129,10 @@ parseCommandLine(int argc, char *argv[])
                                new_cluster.pgconfig = pg_strdup(optarg);
                                break;
 
+                       case 'j':
+                               user_opts.jobs = atoi(optarg);
+                               break;
+
                        case 'k':
                                user_opts.transfer_mode = TRANSFER_MODE_LINK;
                                break;
@@ -146,7 +153,7 @@ parseCommandLine(int argc, char *argv[])
                        case 'p':
                                if ((old_cluster.port = atoi(optarg)) <= 0)
                                {
-                                       pg_log(PG_FATAL, "invalid old port number\n");
+                                       pg_fatal("invalid old port number\n");
                                        exit(1);
                                }
                                break;
@@ -154,7 +161,7 @@ parseCommandLine(int argc, char *argv[])
                        case 'P':
                                if ((new_cluster.port = atoi(optarg)) <= 0)
                                {
-                                       pg_log(PG_FATAL, "invalid new port number\n");
+                                       pg_fatal("invalid new port number\n");
                                        exit(1);
                                }
                                break;
@@ -163,9 +170,10 @@ parseCommandLine(int argc, char *argv[])
                                log_opts.retain = true;
                                break;
 
-                       case 'u':
+                       case 'U':
                                pg_free(os_info.user);
                                os_info.user = pg_strdup(optarg);
+                               os_info.user_specified = true;
 
                                /*
                                 * Push the user name into the environment so pre-9.1
@@ -180,8 +188,7 @@ parseCommandLine(int argc, char *argv[])
                                break;
 
                        default:
-                               pg_log(PG_FATAL,
-                                          "Try \"%s --help\" for more information.\n",
+                               pg_fatal("Try \"%s --help\" for more information.\n",
                                           os_info.progname);
                                break;
                }
@@ -191,7 +198,7 @@ parseCommandLine(int argc, char *argv[])
        for (filename = output_files; *filename != NULL; filename++)
        {
                if ((fp = fopen_priv(*filename, "a")) == NULL)
-                       pg_log(PG_FATAL, "cannot write to log file %s\n", *filename);
+                       pg_fatal("cannot write to log file %s\n", *filename);
 
                /* Start with newline because we might be appending to a file. */
                fprintf(fp, "\n"
@@ -202,6 +209,17 @@ parseCommandLine(int argc, char *argv[])
                fclose(fp);
        }
 
+       /* Turn off read-only mode;  add prefix to PGOPTIONS? */
+       if (getenv("PGOPTIONS"))
+       {
+               char *pgoptions = psprintf("%s %s", FIX_DEFAULT_READ_ONLY,
+                                                                       getenv("PGOPTIONS"));
+               pg_putenv("PGOPTIONS", pgoptions);
+               pfree(pgoptions);
+       }
+       else
+               pg_putenv("PGOPTIONS", FIX_DEFAULT_READ_ONLY);
+
        /* Get values from env if not already set */
        check_required_directory(&old_cluster.bindir, NULL, "PGBINOLD", "-b",
                                                         "old cluster binaries reside");
@@ -222,21 +240,22 @@ usage(void)
   pg_upgrade [OPTION]...\n\
 \n\
 Options:\n\
-  -b, --old-bindir=OLDBINDIR    old cluster executable directory\n\
-  -B, --new-bindir=NEWBINDIR    new cluster executable directory\n\
+  -b, --old-bindir=BINDIR      old cluster executable directory\n\
+  -B, --new-bindir=BINDIR       new cluster executable directory\n\
   -c, --check                   check clusters only, don't change any data\n\
-  -d, --old-datadir=OLDDATADIR  old cluster data directory\n\
-  -D, --new-datadir=NEWDATADIR  new cluster data directory\n\
+  -d, --old-datadir=DATADIR     old cluster data directory\n\
+  -D, --new-datadir=DATADIR     new cluster data directory\n\
+  -j, --jobs                    number of simultaneous processes or threads to use\n\
   -k, --link                    link instead of copying files to new cluster\n\
   -o, --old-options=OPTIONS     old cluster options to pass to the server\n\
   -O, --new-options=OPTIONS     new cluster options to pass to the server\n\
-  -p, --old-port=OLDPORT        old cluster port number (default %d)\n\
-  -P, --new-port=NEWPORT        new cluster port number (default %d)\n\
+  -p, --old-port=PORT           old cluster port number (default %d)\n\
+  -P, --new-port=PORT           new cluster port number (default %d)\n\
   -r, --retain                  retain SQL and log files after success\n\
-  -u, --user=NAME               cluster superuser (default \"%s\")\n\
+  -U, --username=NAME           cluster superuser (default \"%s\")\n\
   -v, --verbose                 enable verbose internal logging\n\
   -V, --version                 display version information, then exit\n\
-  -?, -h, --help                show this help, then exit\n\
+  -?, --help                    show this help, then exit\n\
 \n\
 Before running pg_upgrade you must:\n\
   create a new database cluster (using the new version of initdb)\n\
@@ -244,10 +263,10 @@ Before running pg_upgrade you must:\n\
   shutdown the postmaster servicing the new cluster\n\
 \n\
 When you run pg_upgrade, you must provide the following information:\n\
-  the data directory for the old cluster  (-d OLDDATADIR)\n\
-  the data directory for the new cluster  (-D NEWDATADIR)\n\
-  the \"bin\" directory for the old version (-b OLDBINDIR)\n\
-  the \"bin\" directory for the new version (-B NEWBINDIR)\n\
+  the data directory for the old cluster  (-d DATADIR)\n\
+  the data directory for the new cluster  (-D DATADIR)\n\
+  the \"bin\" directory for the old version (-b BINDIR)\n\
+  the \"bin\" directory for the new version (-B BINDIR)\n\
 \n\
 For example:\n\
   pg_upgrade -d oldCluster/data -D newCluster/data -b oldCluster/bin -B newCluster/bin\n\
@@ -276,6 +295,7 @@ or\n"), old_cluster.port, new_cluster.port, os_info.user);
  *
  * Checks a directory option.
  *     dirpath           - the directory name supplied on the command line
+ *     configpath        - optional configuration directory
  *     envVarName        - the name of an environment variable to get if dirpath is NULL
  *     cmdLineOption - the command line option corresponds to this directory (-o, -O, -n, -N)
  *     description   - a description of this directory option
@@ -299,13 +319,14 @@ check_required_directory(char **dirpath, char **configpath,
                                *configpath = pg_strdup(envVar);
                }
                else
-                       pg_log(PG_FATAL, "You must identify the directory where the %s.\n"
+                       pg_fatal("You must identify the directory where the %s.\n"
                                   "Please use the %s command-line option or the %s environment variable.\n",
                                   description, cmdLineOption, envVarName);
        }
 
        /*
-        * Trim off any trailing path separators
+        * Trim off any trailing path separators because we construct paths by
+        * appending to this path.
         */
 #ifndef WIN32
        if ((*dirpath)[strlen(*dirpath) - 1] == '/')
@@ -361,7 +382,7 @@ adjust_data_dir(ClusterInfo *cluster)
 
        if ((output = popen(cmd, "r")) == NULL ||
                fgets(cmd_output, sizeof(cmd_output), output) == NULL)
-               pg_log(PG_FATAL, "Could not get data directory using %s: %s\n",
+               pg_fatal("Could not get data directory using %s: %s\n",
                           cmd, getErrorText(errno));
 
        pclose(output);
@@ -374,3 +395,85 @@ 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
+
+       /*
+        * sockdir and port were added to postmaster.pid in PG 9.1. Pre-9.1 cannot
+        * process pg_ctl -w for sockets in non-default locations.
+        */
+       if (GET_MAJOR_VERSION(cluster->major_version) >= 901)
+       {
+               if (!live_check)
+               {
+                       /* Use the current directory for the socket */
+                       cluster->sockdir = pg_malloc(MAXPGPATH);
+                       if (!getcwd(cluster->sockdir, MAXPGPATH))
+                               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.
+                        */
+                       unsigned short orig_port = cluster->port;
+                       char            filename[MAXPGPATH],
+                                               line[MAXPGPATH];
+                       FILE       *fp;
+                       int                     lineno;
+
+                       snprintf(filename, sizeof(filename), "%s/postmaster.pid",
+                                        cluster->pgdata);
+                       if ((fp = fopen(filename, "r")) == NULL)
+                               pg_fatal("Cannot open file %s: %m\n", filename);
+
+                       for (lineno = 1;
+                          lineno <= Max(LOCK_FILE_LINE_PORT, LOCK_FILE_LINE_SOCKET_DIR);
+                                lineno++)
+                       {
+                               if (fgets(line, sizeof(line), fp) == NULL)
+                                       pg_fatal("Cannot read line %d from %s: %m\n", lineno, filename);
+
+                               /* potentially overwrite user-supplied value */
+                               if (lineno == LOCK_FILE_LINE_PORT)
+                                       sscanf(line, "%hu", &old_cluster.port);
+                               if (lineno == LOCK_FILE_LINE_SOCKET_DIR)
+                               {
+                                       cluster->sockdir = pg_malloc(MAXPGPATH);
+                                       /* strip off newline */
+                                       sscanf(line, "%s\n", cluster->sockdir);
+                               }
+                       }
+                       fclose(fp);
+
+                       /* warn of port number correction */
+                       if (orig_port != DEF_PGUPORT && old_cluster.port != orig_port)
+                               pg_log(PG_WARNING, "User-supplied old port number %hu corrected to %hu\n",
+                                          orig_port, cluster->port);
+               }
+       }
+       else
+
+               /*
+                * Can't get sockdir and pg_ctl -w can't use a non-default, use
+                * default
+                */
+               cluster->sockdir = NULL;
+#else                                                  /* !HAVE_UNIX_SOCKETS */
+       cluster->sockdir = NULL;
+#endif
+}