On Fri, Jan 14, 2022 at 04:53:12PM -0500, Robert Haas wrote:
> On Thu, Jan 13, 2022 at 10:23 PM Michael Paquier <mich...@paquier.xyz> wrote:
>> Using --compression-level=NUMBER and --server-compress=METHOD to
>> specify a server-side compression method with a level is fine by me,
>> but I find the reuse of --compress to specify a compression method
>> confusing as it maps with the past option we have kept in
>> pg_basebackup for a couple of years now.  Based on your suggested set
>> of options, we could then have a --client-compress=METHOD and
>> --compression-level=NUMBER to specify a client-side compression method
>> with a level.  If we do that, I guess that we should then:
>> 1) Block the combination of --server-compress and --client-compress.
>> 2) Remove the existing -Z/--compress and -z/--gzip.
> 
> I could live with that. I'm not sure that --client-compress instead of
> reusing --compress is going to be better ... but I don't think it's
> awful so much as just not my first choice. I also don't think it would
> be horrid to leave -z, --gzip, and -Z as shorthands for the
> --client-compress=gzip with --compression-level also in the last case,
> instead of removing all that stuff.

Okay.  So, based on this feedback, I guess that something like the
attached would be what we are looking for.  I have maximized the
amount of code removed with the removal of -z/-Z,  but I won't fight
hard if the consensus is to keep them, either.  We could also keep
-z/--gzip, and stick -Z to the new --compression-level with
--compress removed.
--
Michael
From 1bbe624a4bea5e00a1997f81fe3b1ec1f637fa44 Mon Sep 17 00:00:00 2001
From: Michael Paquier <mich...@paquier.xyz>
Date: Sat, 15 Jan 2022 11:51:40 +0900
Subject: [PATCH v4] Rework the option set of pg_basebackup

---
 src/bin/pg_basebackup/pg_basebackup.c        | 99 ++++++++++++++------
 src/bin/pg_basebackup/t/010_pg_basebackup.pl | 37 ++++----
 doc/src/sgml/ref/pg_basebackup.sgml          | 33 ++++---
 3 files changed, 105 insertions(+), 64 deletions(-)

diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c
index aa43fc0924..57b054a8ad 100644
--- a/src/bin/pg_basebackup/pg_basebackup.c
+++ b/src/bin/pg_basebackup/pg_basebackup.c
@@ -113,6 +113,7 @@ static bool showprogress = false;
 static bool estimatesize = true;
 static int	verbose = 0;
 static int	compresslevel = 0;
+static WalCompressionMethod client_method = COMPRESSION_NONE;
 static IncludeWal includewal = STREAM_WAL;
 static bool fastcheckpoint = false;
 static bool writerecoveryconf = false;
@@ -358,8 +359,10 @@ usage(void)
 	printf(_("      --waldir=WALDIR    location for the write-ahead log directory\n"));
 	printf(_("  -X, --wal-method=none|fetch|stream\n"
 			 "                         include required WAL files with specified method\n"));
-	printf(_("  -z, --gzip             compress tar output\n"));
-	printf(_("  -Z, --compress=0-9     compress tar output with given compression level\n"));
+	printf(_("      --client-compress=METHOD\n"
+			 "                         method to compress data (client-side)\n"));
+	printf(_("      --compression-level=1-9\n"
+			 "                         compress tar output with given compression level\n"));
 	printf(_("\nGeneral options:\n"));
 	printf(_("  -c, --checkpoint=fast|spread\n"
 			 "                         set fast or spread checkpointing\n"));
@@ -524,8 +527,7 @@ LogStreamerMain(logstreamer_param *param)
 													stream.do_sync);
 	else
 		stream.walmethod = CreateWalTarMethod(param->xlog,
-											  (compresslevel != 0) ?
-											  COMPRESSION_GZIP : COMPRESSION_NONE,
+											  client_method,
 											  compresslevel,
 											  stream.do_sync);
 
@@ -976,7 +978,7 @@ CreateBackupStreamer(char *archive_name, char *spclocation,
 					 bool is_recovery_guc_supported,
 					 bool expect_unterminated_tarfile)
 {
-	bbstreamer *streamer;
+	bbstreamer *streamer = NULL;
 	bbstreamer *manifest_inject_streamer = NULL;
 	bool		inject_manifest;
 	bool		must_parse_archive;
@@ -1035,19 +1037,22 @@ CreateBackupStreamer(char *archive_name, char *spclocation,
 			archive_file = NULL;
 		}
 
+		if (client_method == COMPRESSION_NONE)
+			streamer = bbstreamer_plain_writer_new(archive_filename,
+												   archive_file);
 #ifdef HAVE_LIBZ
-		if (compresslevel != 0)
+		else if (client_method == COMPRESSION_GZIP)
 		{
 			strlcat(archive_filename, ".gz", sizeof(archive_filename));
 			streamer = bbstreamer_gzip_writer_new(archive_filename,
 												  archive_file,
 												  compresslevel);
 		}
-		else
 #endif
-			streamer = bbstreamer_plain_writer_new(archive_filename,
-												   archive_file);
-
+		else
+		{
+			Assert(false);		/* not reachable */
+		}
 
 		/*
 		 * If we need to parse the archive for whatever reason, then we'll
@@ -1745,8 +1750,6 @@ main(int argc, char **argv)
 		{"slot", required_argument, NULL, 'S'},
 		{"tablespace-mapping", required_argument, NULL, 'T'},
 		{"wal-method", required_argument, NULL, 'X'},
-		{"gzip", no_argument, NULL, 'z'},
-		{"compress", required_argument, NULL, 'Z'},
 		{"label", required_argument, NULL, 'l'},
 		{"no-clean", no_argument, NULL, 'n'},
 		{"no-sync", no_argument, NULL, 'N'},
@@ -1766,6 +1769,8 @@ main(int argc, char **argv)
 		{"no-manifest", no_argument, NULL, 5},
 		{"manifest-force-encode", no_argument, NULL, 6},
 		{"manifest-checksums", required_argument, NULL, 7},
+		{"client-compress", required_argument, NULL, 8},
+		{"compression-level", required_argument, NULL, 9},
 		{NULL, 0, NULL, 0}
 	};
 	int			c;
@@ -1793,7 +1798,7 @@ main(int argc, char **argv)
 
 	atexit(cleanup_directories_atexit);
 
-	while ((c = getopt_long(argc, argv, "CD:F:r:RS:T:X:l:nNzZ:d:c:h:p:U:s:wWkvP",
+	while ((c = getopt_long(argc, argv, "CD:F:r:RS:T:X:l:nNd:c:h:p:U:s:wWkvP",
 							long_options, &option_index)) != -1)
 	{
 		switch (c)
@@ -1872,18 +1877,6 @@ main(int argc, char **argv)
 			case 'N':
 				do_sync = false;
 				break;
-			case 'z':
-#ifdef HAVE_LIBZ
-				compresslevel = Z_DEFAULT_COMPRESSION;
-#else
-				compresslevel = 1;	/* will be rejected below */
-#endif
-				break;
-			case 'Z':
-				if (!option_parse_int(optarg, "-Z/--compress", 0, 9,
-									  &compresslevel))
-					exit(1);
-				break;
 			case 'c':
 				if (pg_strcasecmp(optarg, "fast") == 0)
 					fastcheckpoint = true;
@@ -1942,6 +1935,24 @@ main(int argc, char **argv)
 			case 7:
 				manifest_checksums = pg_strdup(optarg);
 				break;
+			case 8:
+				if (pg_strcasecmp(optarg, "gzip") == 0)
+					client_method = COMPRESSION_GZIP;
+				else if (pg_strcasecmp(optarg, "none") == 0)
+					client_method = COMPRESSION_NONE;
+				else
+				{
+					pg_log_error("invalid value \"%s\" for option %s",
+								 optarg, "--client-compress");
+					exit(1);
+				}
+				break;
+			case 9:
+				if (!option_parse_int(optarg, "--compression-level", 1, 9,
+									  &compresslevel))
+					exit(1);
+				break;
+				break;
 			default:
 
 				/*
@@ -1979,7 +1990,7 @@ main(int argc, char **argv)
 	/*
 	 * Mutually exclusive arguments
 	 */
-	if (format == 'p' && compresslevel != 0)
+	if (format == 'p' && client_method != COMPRESSION_NONE)
 	{
 		pg_log_error("only tar mode backups can be compressed");
 		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
@@ -2057,13 +2068,39 @@ main(int argc, char **argv)
 		}
 	}
 
-#ifndef HAVE_LIBZ
-	if (compresslevel != 0)
+	/*
+	 * Compression-related options.
+	 */
+	switch (client_method)
 	{
-		pg_log_error("this build does not support compression");
-		exit(1);
-	}
+		case COMPRESSION_NONE:
+			if (compresslevel != 0)
+			{
+				pg_log_error("cannot use --compression-level with --client-compress=%s",
+							 "none");
+				fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+						progname);
+				exit(1);
+			}
+			break;
+		case COMPRESSION_GZIP:
+#ifdef HAVE_LIBZ
+			if (compresslevel == 0)
+			{
+				pg_log_info("no value specified for --compression-level, switching to default");
+				compresslevel = Z_DEFAULT_COMPRESSION;
+			}
+#else
+			pg_log_error("this build does not support compression with %s",
+						 "gzip");
+			exit(1);
 #endif
+			break;
+		case COMPRESSION_LZ4:
+			/* option not supported */
+			Assert(false);
+			break;
+	}
 
 	if (showprogress && !estimatesize)
 	{
diff --git a/src/bin/pg_basebackup/t/010_pg_basebackup.pl b/src/bin/pg_basebackup/t/010_pg_basebackup.pl
index 872fec3d35..0f84b3952a 100644
--- a/src/bin/pg_basebackup/t/010_pg_basebackup.pl
+++ b/src/bin/pg_basebackup/t/010_pg_basebackup.pl
@@ -31,6 +31,17 @@ my $pgdata = $node->data_dir;
 $node->command_fails(['pg_basebackup'],
 	'pg_basebackup needs target directory specified');
 
+# Sanity checks for options
+$node->command_fails_like(
+	[
+		'pg_basebackup',   '-D',
+		"$tempdir/backup", '--client-compress',
+		'none',            '--compression-level',
+		'1'
+	],
+	qr/\Qpg_basebackup: error: cannot use --compression-level with --client-compress=none/,
+	'failure if --compression-level specified with --client-compress=none');
+
 # Some Windows ANSI code pages may reject this filename, in which case we
 # quietly proceed without this bit of test coverage.
 if (open my $badchars, '>>', "$tempdir/pgdata/FOO\xe0\xe0\xe0BAR")
@@ -630,23 +641,14 @@ note "Testing pg_basebackup with compression methods";
 # Check ZLIB compression if available.
 SKIP:
 {
-	skip "postgres was not built with ZLIB support", 5
+	skip "postgres was not built with ZLIB support", 3
 	  if (!check_pg_config("#define HAVE_LIBZ 1"));
 
 	$node->command_ok(
 		[
 			'pg_basebackup',        '-D',
-			"$tempdir/backup_gzip", '--compress',
-			'1',                    '--no-sync',
-			'--format',             't'
-		],
-		'pg_basebackup with --compress');
-	$node->command_ok(
-		[
-			'pg_basebackup',         '-D',
-			"$tempdir/backup_gzip2", '--gzip',
-			'--no-sync',             '--format',
-			't'
+			"$tempdir/backup_gzip", '--client-compress',
+			'gzip',                 '--no-sync', '--format', 't'
 		],
 		'pg_basebackup with --gzip');
 
@@ -654,11 +656,8 @@ SKIP:
 	# names.
 	my @zlib_files = glob "$tempdir/backup_gzip/*.tar.gz";
 	is(scalar(@zlib_files), 2,
-		"two files created with --compress (base.tar.gz and pg_wal.tar.gz)");
-	my @zlib_files2 = glob "$tempdir/backup_gzip2/*.tar.gz";
-	is(scalar(@zlib_files2), 2,
-		"two files created with --gzip (base.tar.gz and pg_wal.tar.gz)");
-
+		"two files created with --client-compress=gzip (base.tar.gz and pg_wal.tar.gz)"
+	);
 	# Check the integrity of the files generated.
 	my $gzip = $ENV{GZIP_PROGRAM};
 	skip "program gzip is not found in your system", 1
@@ -666,9 +665,7 @@ SKIP:
 		|| $gzip eq ''
 		|| system_log($gzip, '--version') != 0);
 
-	my $gzip_is_valid =
-	  system_log($gzip, '--test', @zlib_files, @zlib_files2);
+	my $gzip_is_valid = system_log($gzip, '--test', @zlib_files);
 	is($gzip_is_valid, 0, "gzip verified the integrity of compressed data");
 	rmtree("$tempdir/backup_gzip");
-	rmtree("$tempdir/backup_gzip2");
 }
diff --git a/doc/src/sgml/ref/pg_basebackup.sgml b/doc/src/sgml/ref/pg_basebackup.sgml
index 9e6807b457..1a859794b2 100644
--- a/doc/src/sgml/ref/pg_basebackup.sgml
+++ b/doc/src/sgml/ref/pg_basebackup.sgml
@@ -354,28 +354,35 @@ PostgreSQL documentation
      </varlistentry>
 
      <varlistentry>
-      <term><option>-z</option></term>
-      <term><option>--gzip</option></term>
+      <term><option>--compression-level=<replaceable class="parameter">level</replaceable></option></term>
       <listitem>
        <para>
-        Enables gzip compression of tar file output, with the default
-        compression level. Compression is only available when using
-        the tar format, and the suffix <filename>.gz</filename> will
-        automatically be added to all tar filenames.
+        Controls the level of compression used with the tar file output,
+        and specifies the compression level (1 through 9, 1 being worst
+        compression and 9 being best compression). Compression is only
+        available when using the tar format, and the suffix
+        <filename>.gz</filename> will automatically be added to all tar
+        filenames.
+       </para>
+       <para>
+        This option is only available with <literal>--client-compress</literal>
+        set to <literal>gzip</literal>.
        </para>
       </listitem>
      </varlistentry>
 
      <varlistentry>
-      <term><option>-Z <replaceable class="parameter">level</replaceable></option></term>
-      <term><option>--compress=<replaceable class="parameter">level</replaceable></option></term>
+      <term><option>--client-compress=<replaceable class="parameter">method</replaceable></option></term>
       <listitem>
        <para>
-        Enables gzip compression of tar file output, and specifies the
-        compression level (0 through 9, 0 being no compression and 9 being best
-        compression). Compression is only available when using the tar
-        format, and the suffix <filename>.gz</filename> will
-        automatically be added to all tar filenames.
+        Enables client-side compression of backup data using the specified
+        method. Supported values are <literal>gzip</literal> and
+        <literal>none</literal>, the default.
+       </para>
+
+       <para>
+        The suffix <filename>.gz</filename> will automatically be added to
+        all filenames when using <literal>gzip</literal>.
        </para>
       </listitem>
      </varlistentry>
-- 
2.34.1

Attachment: signature.asc
Description: PGP signature

Reply via email to