pg_upgrade: Don't print progress status when output is not a tty.
authorAndres Freund <andres@anarazel.de>
Mon, 21 Feb 2022 16:34:59 +0000 (08:34 -0800)
committerAndres Freund <andres@anarazel.de>
Mon, 21 Feb 2022 16:34:59 +0000 (08:34 -0800)
Until this change pg_upgrade with output redirected to a file / pipe would end
up printing all files in the cluster. This has made check-world output
exceedingly verbose.

Author: Andres Freund <andres@anarazel.de>
Reviewed-By: Justin Pryzby <pryzby@telsasoft.com>
Reviewed-By: Daniel Gustafsson <daniel@yesql.se>
Discussion: https://postgr.es/m/CA+hUKGKjrV61ZVJ8OSag+3rKRmCZXPc03bDyWMqhXg3rdZ=fOw@mail.gmail.com

src/bin/pg_upgrade/dump.c
src/bin/pg_upgrade/option.c
src/bin/pg_upgrade/pg_upgrade.c
src/bin/pg_upgrade/pg_upgrade.h
src/bin/pg_upgrade/relfilenode.c
src/bin/pg_upgrade/util.c

index b69b4f95695ec107995c6050dc3daa68f501a8ec..29b9e44f78268a3bcb75d46c5e465edffd2bc7d3 100644 (file)
@@ -29,7 +29,7 @@ generate_old_dump(void)
                          GLOBALS_DUMP_FILE);
        check_ok();
 
-       prep_status("Creating dump of database schemas\n");
+       prep_status_progress("Creating dump of database schemas");
 
        /* create per-db dump files */
        for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
index d2c82cc2bbb97570b54e627b006c7fddfaffa753..e75be2c423e554a118c4fd83a931e013ec6a65c2 100644 (file)
@@ -207,6 +207,8 @@ parseCommandLine(int argc, char *argv[])
        if (log_opts.verbose)
                pg_log(PG_REPORT, "Running in verbose mode\n");
 
+       log_opts.isatty = isatty(fileno(stdout));
+
        /* Turn off read-only mode;  add prefix to PGOPTIONS? */
        if (getenv("PGOPTIONS"))
        {
index f66bbd530799f65f7ecc409077c0f10d5ce53bda..ecb3e1f64742da0d29301ce06f2f36f8df5aaae1 100644 (file)
@@ -381,7 +381,7 @@ create_new_objects(void)
 {
        int                     dbnum;
 
-       prep_status("Restoring database schemas in the new cluster\n");
+       prep_status_progress("Restoring database schemas in the new cluster");
 
        /*
         * We cannot process the template1 database concurrently with others,
index 0aca0a77aaee6ef36a1f435ba07e4e2ec609e8a8..ca86c1129245f4a357bc3c3cd776ae02dc5a5085 100644 (file)
@@ -274,6 +274,7 @@ typedef struct
        char       *basedir;            /* Base output directory */
        char       *dumpdir;            /* Dumps */
        char       *logdir;                     /* Log files */
+       bool            isatty;                 /* is stdout a tty */
 } LogOpts;
 
 
@@ -427,6 +428,7 @@ void                pg_log(eLogType type, const char *fmt,...) pg_attribute_printf(2, 3);
 void           pg_fatal(const char *fmt,...) pg_attribute_printf(1, 2) pg_attribute_noreturn();
 void           end_progress_output(void);
 void           prep_status(const char *fmt,...) pg_attribute_printf(1, 2);
+void           prep_status_progress(const char *fmt,...) pg_attribute_printf(1, 2);
 void           check_ok(void);
 unsigned int str2uint(const char *str);
 
index 2f4deb3416320c31636558e2ee40b010e302a1c3..d23ac884bd1733a2fd76c8a2b50403a5a581a68e 100644 (file)
@@ -32,13 +32,13 @@ transfer_all_new_tablespaces(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
        switch (user_opts.transfer_mode)
        {
                case TRANSFER_MODE_CLONE:
-                       pg_log(PG_REPORT, "Cloning user relation files\n");
+                       prep_status_progress("Cloning user relation files");
                        break;
                case TRANSFER_MODE_COPY:
-                       pg_log(PG_REPORT, "Copying user relation files\n");
+                       prep_status_progress("Copying user relation files");
                        break;
                case TRANSFER_MODE_LINK:
-                       pg_log(PG_REPORT, "Linking user relation files\n");
+                       prep_status_progress("Linking user relation files");
                        break;
        }
 
index d98deb7f24e4c1ee359e64dd328b0c7f45c5aff3..414de063496b1d4d303b2105c18795ce5bff9f5b 100644 (file)
@@ -38,15 +38,18 @@ report_status(eLogType type, const char *fmt,...)
 }
 
 
-/* force blank output for progress display */
 void
 end_progress_output(void)
 {
        /*
-        * In case nothing printed; pass a space so gcc doesn't complain about
-        * empty format string.
+        * For output to a tty, erase prior contents of progress line. When either
+        * tty or verbose, indent so that report_status() output will align
+        * nicely.
         */
-       prep_status(" ");
+       if (log_opts.isatty)
+               pg_log(PG_REPORT, "\r%-*s", MESSAGE_WIDTH, "");
+       else if (log_opts.verbose)
+               pg_log(PG_REPORT, "%-*s", MESSAGE_WIDTH, "");
 }
 
 
@@ -75,14 +78,43 @@ prep_status(const char *fmt,...)
        vsnprintf(message, sizeof(message), fmt, args);
        va_end(args);
 
-       if (strlen(message) > 0 && message[strlen(message) - 1] == '\n')
-               pg_log(PG_REPORT, "%s", message);
+       /* trim strings */
+       pg_log(PG_REPORT, "%-*s", MESSAGE_WIDTH, message);
+}
+
+/*
+ * prep_status_progress
+ *
+ *   Like prep_status(), but for potentially longer running operations.
+ *   Details about what item is currently being processed can be displayed
+ *   with pg_log(PG_STATUS, ...). A typical sequence would look like this:
+ *
+ *   prep_status_progress("copying files");
+ *   for (...)
+ *     pg_log(PG_STATUS, "%s", filename);
+ *   end_progress_output();
+ *   report_status(PG_REPORT, "ok");
+ */
+void
+prep_status_progress(const char *fmt,...)
+{
+       va_list         args;
+       char            message[MAX_STRING];
+
+       va_start(args, fmt);
+       vsnprintf(message, sizeof(message), fmt, args);
+       va_end(args);
+
+       /*
+        * If outputting to a tty or in verbose, append newline. pg_log_v() will
+        * put the individual progress items onto the next line.
+        */
+       if (log_opts.isatty || log_opts.verbose)
+               pg_log(PG_REPORT, "%-*s\n", MESSAGE_WIDTH, message);
        else
-               /* trim strings that don't end in a newline */
                pg_log(PG_REPORT, "%-*s", MESSAGE_WIDTH, message);
 }
 
-
 static void
 pg_log_v(eLogType type, const char *fmt, va_list ap)
 {
@@ -111,8 +143,15 @@ pg_log_v(eLogType type, const char *fmt, va_list ap)
                        break;
 
                case PG_STATUS:
-                       /* for output to a display, do leading truncation and append \r */
-                       if (isatty(fileno(stdout)))
+                       /*
+                        * For output to a display, do leading truncation. Append \r so
+                        * that the next message is output at the start of the line.
+                        *
+                        * If going to non-interactive output, only display progress if
+                        * verbose is enabled. Otherwise the output gets unreasonably
+                        * large by default.
+                        */
+                       if (log_opts.isatty)
                                /* -2 because we use a 2-space indent */
                                printf("  %s%-*.*s\r",
                                /* prefix with "..." if we do leading truncation */
@@ -121,7 +160,7 @@ pg_log_v(eLogType type, const char *fmt, va_list ap)
                                /* optional leading truncation */
                                           strlen(message) <= MESSAGE_WIDTH - 2 ? message :
                                           message + strlen(message) - MESSAGE_WIDTH + 3 + 2);
-                       else
+                       else if (log_opts.verbose)
                                printf("  %s\n", message);
                        break;