@@ -123,6 +123,7 @@ static bool showprogress = false;
123
123
static bool estimatesize = true;
124
124
static int verbose = 0 ;
125
125
static int compresslevel = 0 ;
126
+ static WalCompressionMethod compressmethod = COMPRESSION_NONE ;
126
127
static IncludeWal includewal = STREAM_WAL ;
127
128
static bool fastcheckpoint = false;
128
129
static bool writerecoveryconf = false;
@@ -379,7 +380,8 @@ usage(void)
379
380
printf (_ (" -X, --wal-method=none|fetch|stream\n"
380
381
" include required WAL files with specified method\n" ));
381
382
printf (_ (" -z, --gzip compress tar output\n" ));
382
- printf (_ (" -Z, --compress=0-9 compress tar output with given compression level\n" ));
383
+ printf (_ (" -Z, --compress={gzip,none}[:LEVEL] or [LEVEL]\n"
384
+ " compress tar output with given compression method or level\n" ));
383
385
printf (_ ("\nGeneral options:\n" ));
384
386
printf (_ (" -c, --checkpoint=fast|spread\n"
385
387
" set fast or spread checkpointing\n" ));
@@ -544,8 +546,7 @@ LogStreamerMain(logstreamer_param *param)
544
546
stream .do_sync );
545
547
else
546
548
stream .walmethod = CreateWalTarMethod (param -> xlog ,
547
- (compresslevel != 0 ) ?
548
- COMPRESSION_GZIP : COMPRESSION_NONE ,
549
+ compressmethod ,
549
550
compresslevel ,
550
551
stream .do_sync );
551
552
@@ -936,6 +937,81 @@ parse_max_rate(char *src)
936
937
return (int32 ) result ;
937
938
}
938
939
940
+ /*
941
+ * Utility wrapper to parse the values specified for -Z/--compress.
942
+ * *methodres and *levelres will be optionally filled with values coming
943
+ * from the parsed results.
944
+ */
945
+ static void
946
+ parse_compress_options (char * src , WalCompressionMethod * methodres ,
947
+ int * levelres )
948
+ {
949
+ char * sep ;
950
+ int firstlen ;
951
+ char * firstpart = NULL ;
952
+
953
+ /* check if the option is split in two */
954
+ sep = strchr (src , ':' );
955
+
956
+ /*
957
+ * The first part of the option value could be a method name, or just a
958
+ * level value.
959
+ */
960
+ firstlen = (sep != NULL ) ? (sep - src ) : strlen (src );
961
+ firstpart = pg_malloc (firstlen + 1 );
962
+ strncpy (firstpart , src , firstlen );
963
+ firstpart [firstlen ] = '\0' ;
964
+
965
+ /*
966
+ * Check if the first part of the string matches with a supported
967
+ * compression method.
968
+ */
969
+ if (pg_strcasecmp (firstpart , "gzip" ) == 0 )
970
+ * methodres = COMPRESSION_GZIP ;
971
+ else if (pg_strcasecmp (firstpart , "none" ) == 0 )
972
+ * methodres = COMPRESSION_NONE ;
973
+ else
974
+ {
975
+ /*
976
+ * It does not match anything known, so check for the
977
+ * backward-compatible case of only an integer where the implied
978
+ * compression method changes depending on the level value.
979
+ */
980
+ if (!option_parse_int (firstpart , "-Z/--compress" , 0 ,
981
+ INT_MAX , levelres ))
982
+ exit (1 );
983
+
984
+ * methodres = (* levelres > 0 ) ?
985
+ COMPRESSION_GZIP : COMPRESSION_NONE ;
986
+ return ;
987
+ }
988
+
989
+ if (sep == NULL )
990
+ {
991
+ /*
992
+ * The caller specified a method without a colon separator, so let any
993
+ * subsequent checks assign a default level.
994
+ */
995
+ return ;
996
+ }
997
+
998
+ /* Check the contents after the colon separator. */
999
+ sep ++ ;
1000
+ if (* sep == '\0' )
1001
+ {
1002
+ pg_log_error ("no compression level defined for method %s" , firstpart );
1003
+ exit (1 );
1004
+ }
1005
+
1006
+ /*
1007
+ * For any of the methods currently supported, the data after the
1008
+ * separator can just be an integer.
1009
+ */
1010
+ if (!option_parse_int (sep , "-Z/--compress" , 0 , INT_MAX ,
1011
+ levelres ))
1012
+ exit (1 );
1013
+ }
1014
+
939
1015
/*
940
1016
* Read a stream of COPY data and invoke the provided callback for each
941
1017
* chunk.
@@ -996,7 +1072,7 @@ CreateBackupStreamer(char *archive_name, char *spclocation,
996
1072
bool is_recovery_guc_supported ,
997
1073
bool expect_unterminated_tarfile )
998
1074
{
999
- bbstreamer * streamer ;
1075
+ bbstreamer * streamer = NULL ;
1000
1076
bbstreamer * manifest_inject_streamer = NULL ;
1001
1077
bool inject_manifest ;
1002
1078
bool must_parse_archive ;
@@ -1055,19 +1131,22 @@ CreateBackupStreamer(char *archive_name, char *spclocation,
1055
1131
archive_file = NULL ;
1056
1132
}
1057
1133
1134
+ if (compressmethod == COMPRESSION_NONE )
1135
+ streamer = bbstreamer_plain_writer_new (archive_filename ,
1136
+ archive_file );
1058
1137
#ifdef HAVE_LIBZ
1059
- if (compresslevel != 0 )
1138
+ else if (compressmethod == COMPRESSION_GZIP )
1060
1139
{
1061
1140
strlcat (archive_filename , ".gz" , sizeof (archive_filename ));
1062
1141
streamer = bbstreamer_gzip_writer_new (archive_filename ,
1063
1142
archive_file ,
1064
1143
compresslevel );
1065
1144
}
1066
- else
1067
1145
#endif
1068
- streamer = bbstreamer_plain_writer_new (archive_filename ,
1069
- archive_file );
1070
-
1146
+ else
1147
+ {
1148
+ Assert (false); /* not reachable */
1149
+ }
1071
1150
1072
1151
/*
1073
1152
* If we need to parse the archive for whatever reason, then we'll
@@ -2279,11 +2358,11 @@ main(int argc, char **argv)
2279
2358
#else
2280
2359
compresslevel = 1 ; /* will be rejected below */
2281
2360
#endif
2361
+ compressmethod = COMPRESSION_GZIP ;
2282
2362
break ;
2283
2363
case 'Z' :
2284
- if (!option_parse_int (optarg , "-Z/--compress" , 0 , 9 ,
2285
- & compresslevel ))
2286
- exit (1 );
2364
+ parse_compress_options (optarg , & compressmethod ,
2365
+ & compresslevel );
2287
2366
break ;
2288
2367
case 'c' :
2289
2368
if (pg_strcasecmp (optarg , "fast" ) == 0 )
@@ -2412,7 +2491,7 @@ main(int argc, char **argv)
2412
2491
/*
2413
2492
* Compression doesn't make sense unless tar format is in use.
2414
2493
*/
2415
- if (format == 'p' && compresslevel != 0 )
2494
+ if (format == 'p' && compressmethod != COMPRESSION_NONE )
2416
2495
{
2417
2496
if (backup_target == NULL )
2418
2497
pg_log_error ("only tar mode backups can be compressed" );
@@ -2516,14 +2595,43 @@ main(int argc, char **argv)
2516
2595
}
2517
2596
}
2518
2597
2519
- #ifndef HAVE_LIBZ
2520
- /* Sanity checks for compression level. */
2521
- if (compresslevel != 0 )
2598
+ /* Sanity checks for compression-related options. */
2599
+ switch (compressmethod )
2522
2600
{
2523
- pg_log_error ("this build does not support compression" );
2524
- exit (1 );
2525
- }
2601
+ case COMPRESSION_NONE :
2602
+ if (compresslevel != 0 )
2603
+ {
2604
+ pg_log_error ("cannot use compression level with method %s" ,
2605
+ "none" );
2606
+ fprintf (stderr , _ ("Try \"%s --help\" for more information.\n" ),
2607
+ progname );
2608
+ exit (1 );
2609
+ }
2610
+ break ;
2611
+ case COMPRESSION_GZIP :
2612
+ #ifdef HAVE_LIBZ
2613
+ if (compresslevel == 0 )
2614
+ {
2615
+ pg_log_info ("no value specified for compression level, switching to default" );
2616
+ compresslevel = Z_DEFAULT_COMPRESSION ;
2617
+ }
2618
+ if (compresslevel > 9 )
2619
+ {
2620
+ pg_log_error ("compression level %d of method %s higher than maximum of 9" ,
2621
+ compresslevel , "gzip" );
2622
+ exit (1 );
2623
+ }
2624
+ #else
2625
+ pg_log_error ("this build does not support compression with %s" ,
2626
+ "gzip" );
2627
+ exit (1 );
2526
2628
#endif
2629
+ break ;
2630
+ case COMPRESSION_LZ4 :
2631
+ /* option not supported */
2632
+ Assert (false);
2633
+ break ;
2634
+ }
2527
2635
2528
2636
/*
2529
2637
* Sanity checks for progress reporting options.
0 commit comments