diff --git a/build/lib/pgBackRestBuild/Config/Data.pm b/build/lib/pgBackRestBuild/Config/Data.pm index 33bea0083..e22745cc5 100644 --- a/build/lib/pgBackRestBuild/Config/Data.pm +++ b/build/lib/pgBackRestBuild/Config/Data.pm @@ -1236,6 +1236,7 @@ my %hConfigDefine = 'none', 'gz', 'lz4', + 'zst', ], &CFGDEF_COMMAND => CFGOPT_COMPRESS, }, diff --git a/doc/xml/contributing.xml b/doc/xml/contributing.xml index b1acf9801..626ec8d21 100644 --- a/doc/xml/contributing.xml +++ b/doc/xml/contributing.xml @@ -64,6 +64,7 @@ apt-get install rsync git devscripts build-essential valgrind lcov autoconf autoconf-archive libssl-dev zlib1g-dev libxml2-dev libpq-dev pkg-config libxml-checker-perl libyaml-libyaml-perl libdbd-pg-perl liblz4-dev liblz4-tool + zstd libzstd-dev -y 2>&1 diff --git a/doc/xml/reference.xml b/doc/xml/reference.xml index 94695d8d1..35763d7fb 100644 --- a/doc/xml/reference.xml +++ b/doc/xml/reference.xml @@ -143,6 +143,7 @@ n diff --git a/doc/xml/release.xml b/doc/xml/release.xml index 58e919a87..99745ee7d 100644 --- a/doc/xml/release.xml +++ b/doc/xml/release.xml @@ -53,6 +53,16 @@

Allow the user to remove a specified backup regardless of retention settings.

+ + + + + +

Add Zstandard compression support.

+ +

Note that setting compress-type=zst will make new backups and archive incompatible (unrestorable) with prior versions of .

+
+ diff --git a/doc/xml/user-guide.xml b/doc/xml/user-guide.xml index 12a0787f9..57d86a453 100644 --- a/doc/xml/user-guide.xml +++ b/doc/xml/user-guide.xml @@ -274,14 +274,13 @@ {[copy-ca-cert]} # Fix root tty - RUN sed -i 's/^mesg n/tty -s \&\& mesg n/g' /root/.profile && \ + RUN sed -i 's/^mesg n/tty -s \&\& mesg n/g' /root/.profile - # Suppress dpkg interactive output - rm /etc/apt/apt.conf.d/70debconf - - # Install base packages - RUN apt-get update && \ - apt-get install -y sudo ssh wget vim gnupg lsb-release iputils-ping ca-certificates locales 2>&1 + # Install base packages (suppress dpkg interactive output) + RUN export DEBIAN_FRONTEND=noninteractive && \ + rm /etc/apt/apt.conf.d/70debconf && \ + apt-get update && \ + apt-get install -y sudo ssh wget vim gnupg lsb-release iputils-ping ca-certificates tzdata locales 2>&1 # Install CA certificate RUN update-ca-certificates @@ -767,13 +766,16 @@ - apt-get install make gcc libpq-dev libssl-dev libxml2-dev pkg-config liblz4-dev + apt-get install make gcc libpq-dev libssl-dev libxml2-dev pkg-config + liblz4-dev libzstd-dev + -y 2>&1 - yum install make gcc postgresql-devel openssl-devel libxml2-devel lz4-devel + yum install make gcc postgresql-devel openssl-devel libxml2-devel + lz4-devel libzstd-devel -y 2>&1 diff --git a/src/Makefile.in b/src/Makefile.in index c3ec0952a..025751222 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -48,6 +48,9 @@ SRCS = \ common/compress/lz4/common.c \ common/compress/lz4/compress.c \ common/compress/lz4/decompress.c \ + common/compress/zst/common.c \ + common/compress/zst/compress.c \ + common/compress/zst/decompress.c \ common/crypto/cipherBlock.c \ common/crypto/common.c \ common/crypto/hash.c \ diff --git a/src/build.auto.h.in b/src/build.auto.h.in index 58f9cf060..cd6436280 100644 --- a/src/build.auto.h.in +++ b/src/build.auto.h.in @@ -12,3 +12,6 @@ Build Flags Generated by Configure // Is liblz4 present? #undef HAVE_LIBLZ4 + +// Is libzstd present? +#undef HAVE_LIBZST diff --git a/src/build/configure.ac b/src/build/configure.ac index fdecbea67..5e70446fc 100644 --- a/src/build/configure.ac +++ b/src/build/configure.ac @@ -125,6 +125,20 @@ AC_CHECK_LIB( [AC_CHECK_HEADER(lz4frame.h, [AC_DEFINE(HAVE_LIBLZ4) AC_SUBST(LIBS, "${LIBS} -llz4")], [AC_MSG_ERROR([header file is required])])]) +# Check optional zst library. Ignore any versions below 1.0. +# ---------------------------------------------------------------------------------------------------------------------------------- +AC_CHECK_LIB( + [zstd], [ZSTD_isError], + [AC_CHECK_HEADER(zstd.h, + [AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [#include ], + [#if ZSTD_VERSION_MAJOR < 1 + #error "ZSTD_VERSION_MAJOR must be >= 1" + #endif])], + [AC_DEFINE(HAVE_LIBZST) AC_SUBST(LIBS, "${LIBS} -lzstd")])], + [AC_MSG_ERROR([header file is required])])]) + # Write output # ---------------------------------------------------------------------------------------------------------------------------------- AC_CONFIG_HEADERS([build.auto.h]) diff --git a/src/common/compress/helper.c b/src/common/compress/helper.c index 4122c4cc5..d5842635e 100644 --- a/src/common/compress/helper.c +++ b/src/common/compress/helper.c @@ -12,6 +12,9 @@ Compression Helper #include "common/compress/lz4/common.h" #include "common/compress/lz4/compress.h" #include "common/compress/lz4/decompress.h" +#include "common/compress/zst/common.h" +#include "common/compress/zst/compress.h" +#include "common/compress/zst/decompress.h" #include "common/debug.h" #include "common/log.h" #include "version.h" @@ -22,7 +25,6 @@ Compression type constants #define COMPRESS_TYPE_NONE "none" // Constants for currently unsupported compression types -#define ZST_EXT "zst" #define BZ2_EXT "bz2" #define XZ_EXT "xz" @@ -67,6 +69,13 @@ static const struct CompressHelperLocal { .type = STRDEF(ZST_EXT), .ext = STRDEF("." ZST_EXT), +#ifdef HAVE_LIBZST + .compressType = ZST_COMPRESS_FILTER_TYPE, + .compressNew = zstCompressNew, + .decompressType = ZST_DECOMPRESS_FILTER_TYPE, + .decompressNew = zstDecompressNew, + .levelDefault = 3, +#endif }, { .type = STRDEF(XZ_EXT), diff --git a/src/common/compress/helper.h b/src/common/compress/helper.h index ee8e66dea..53d74ad10 100644 --- a/src/common/compress/helper.h +++ b/src/common/compress/helper.h @@ -17,11 +17,11 @@ typedef enum compressTypeNone, // No compression compressTypeGz, // gzip compressTypeLz4, // lz4 + compressTypeZst, // zstandard // These types have not been implemented but are included here so older versions can identify compression types added by future // versions. In that sense this list is speculative, but these seem to be all the types that are likely to be added in the // foreseeable future. - compressTypeZst, // zstandard compressTypeXz, // xz/lzma compressTypeBz2, // bzip2 } CompressType; diff --git a/src/common/compress/zst/common.c b/src/common/compress/zst/common.c new file mode 100644 index 000000000..e75839563 --- /dev/null +++ b/src/common/compress/zst/common.c @@ -0,0 +1,32 @@ +/*********************************************************************************************************************************** +ZST Common +***********************************************************************************************************************************/ +#include "build.auto.h" + +#ifdef HAVE_LIBZST + +#include + +// Check the version -- this is done in configure but it makes sense to be sure +#if ZSTD_VERSION_MAJOR < 1 + #error "ZSTD_VERSION_MAJOR must be >= 1" +#endif + +#include "common/compress/zst/common.h" +#include "common/debug.h" + +/**********************************************************************************************************************************/ +size_t +zstError(size_t error) +{ + FUNCTION_TEST_BEGIN(); + FUNCTION_TEST_PARAM(SIZE, error); + FUNCTION_TEST_END(); + + if (ZSTD_isError(error)) + THROW_FMT(FormatError, "zst error: [%zd] %s", (ssize_t)error, ZSTD_getErrorName(error)); + + FUNCTION_TEST_RETURN(error); +} + +#endif // HAVE_LIBZST diff --git a/src/common/compress/zst/common.h b/src/common/compress/zst/common.h new file mode 100644 index 000000000..75b78ad83 --- /dev/null +++ b/src/common/compress/zst/common.h @@ -0,0 +1,25 @@ +/*********************************************************************************************************************************** +ZST Common + +Developed using the documentation in https://github.com/facebook/zstd/blob/v1.0.0/lib/zstd.h. +***********************************************************************************************************************************/ +#ifndef COMMON_COMPRESS_ZST_COMMON_H +#define COMMON_COMPRESS_ZST_COMMON_H + +#include + +/*********************************************************************************************************************************** +ZST extension +***********************************************************************************************************************************/ +#define ZST_EXT "zst" + +#ifdef HAVE_LIBZST + +/*********************************************************************************************************************************** +Functions +***********************************************************************************************************************************/ +size_t zstError(size_t error); + +#endif // HAVE_LIBZST + +#endif diff --git a/src/common/compress/zst/compress.c b/src/common/compress/zst/compress.c new file mode 100644 index 000000000..e835e5d3c --- /dev/null +++ b/src/common/compress/zst/compress.c @@ -0,0 +1,207 @@ +/*********************************************************************************************************************************** +ZST Compress +***********************************************************************************************************************************/ +#include "build.auto.h" + +#ifdef HAVE_LIBZST + +#include + +#include "common/compress/zst/common.h" +#include "common/compress/zst/compress.h" +#include "common/debug.h" +#include "common/io/filter/filter.intern.h" +#include "common/log.h" +#include "common/memContext.h" +#include "common/type/object.h" + +/*********************************************************************************************************************************** +Filter type constant +***********************************************************************************************************************************/ +STRING_EXTERN(ZST_COMPRESS_FILTER_TYPE_STR, ZST_COMPRESS_FILTER_TYPE); + +/*********************************************************************************************************************************** +Object type +***********************************************************************************************************************************/ +#define ZST_COMPRESS_TYPE ZstCompress +#define ZST_COMPRESS_PREFIX zstCompress + +typedef struct ZstCompress +{ + MemContext *memContext; // Context to store data + ZSTD_CStream *context; // Compression context + int level; // Compression level + IoFilter *filter; // Filter interface + + bool inputSame; // Is the same input required on the next process call? + size_t inputOffset; // Current offset in input buffer + bool flushing; // Is input complete and flushing in progress? +} ZstCompress; + +/*********************************************************************************************************************************** +Render as string for logging +***********************************************************************************************************************************/ +static String * +zstCompressToLog(const ZstCompress *this) +{ + return strNewFmt( + "{level: %d, inputSame: %s, inputOffset: %zu, flushing: %s}", this->level, cvtBoolToConstZ(this->inputSame), + this->inputOffset, cvtBoolToConstZ(this->flushing)); +} + +#define FUNCTION_LOG_ZST_COMPRESS_TYPE \ + ZstCompress * +#define FUNCTION_LOG_ZST_COMPRESS_FORMAT(value, buffer, bufferSize) \ + FUNCTION_LOG_STRING_OBJECT_FORMAT(value, zstCompressToLog, buffer, bufferSize) + +/*********************************************************************************************************************************** +Free compression context +***********************************************************************************************************************************/ +OBJECT_DEFINE_FREE_RESOURCE_BEGIN(ZST_COMPRESS, LOG, logLevelTrace) +{ + ZSTD_freeCStream(this->context); +} +OBJECT_DEFINE_FREE_RESOURCE_END(LOG); + +/*********************************************************************************************************************************** +Compress data +***********************************************************************************************************************************/ +static void +zstCompressProcess(THIS_VOID, const Buffer *uncompressed, Buffer *compressed) +{ + THIS(ZstCompress); + + FUNCTION_LOG_BEGIN(logLevelTrace); + FUNCTION_LOG_PARAM(ZST_COMPRESS, this); + FUNCTION_LOG_PARAM(BUFFER, uncompressed); + FUNCTION_LOG_PARAM(BUFFER, compressed); + FUNCTION_LOG_END(); + + ASSERT(this != NULL); + ASSERT(!(this->flushing && !this->inputSame)); + ASSERT(this->context != NULL); + ASSERT(compressed != NULL); + ASSERT(!this->flushing || uncompressed == NULL); + + // Initialize output buffer + ZSTD_outBuffer out = {.dst = bufRemainsPtr(compressed), .size = bufRemains(compressed)}; + + // If input is NULL then start flushing + if (uncompressed == NULL) + { + this->flushing = true; + this->inputSame = zstError(ZSTD_endStream(this->context, &out)) != 0; + } + // Else still have input data + else + { + // Initialize input buffer + ZSTD_inBuffer in = + { + .src = bufPtrConst(uncompressed) + this->inputOffset, + .size = bufUsed(uncompressed) - this->inputOffset, + }; + + // Perform compression + zstError(ZSTD_compressStream(this->context, &out, &in)); + + // If the input buffer was not entirely consumed then set inputSame and store the offset where processing will restart + if (in.pos < in.size) + { + // Output buffer should be completely full + ASSERT(out.pos == out.size); + + this->inputSame = true; + this->inputOffset += in.pos; + } + // Else ready for more input + else + { + this->inputSame = false; + this->inputOffset = 0; + } + } + + bufUsedInc(compressed, out.pos); + + FUNCTION_LOG_RETURN_VOID(); +} + +/*********************************************************************************************************************************** +Is compress done? +***********************************************************************************************************************************/ +static bool +zstCompressDone(const THIS_VOID) +{ + THIS(const ZstCompress); + + FUNCTION_TEST_BEGIN(); + FUNCTION_TEST_PARAM(ZST_COMPRESS, this); + FUNCTION_TEST_END(); + + ASSERT(this != NULL); + + FUNCTION_TEST_RETURN(this->flushing && !this->inputSame); +} + +/*********************************************************************************************************************************** +Is the same input required on the next process call? +***********************************************************************************************************************************/ +static bool +zstCompressInputSame(const THIS_VOID) +{ + THIS(const ZstCompress); + + FUNCTION_TEST_BEGIN(); + FUNCTION_TEST_PARAM(ZST_COMPRESS, this); + FUNCTION_TEST_END(); + + ASSERT(this != NULL); + + FUNCTION_TEST_RETURN(this->inputSame); +} + +/**********************************************************************************************************************************/ +IoFilter * +zstCompressNew(int level) +{ + FUNCTION_LOG_BEGIN(logLevelTrace); + FUNCTION_LOG_PARAM(INT, level); + FUNCTION_LOG_END(); + + ASSERT(level >= 0); + + IoFilter *this = NULL; + + MEM_CONTEXT_NEW_BEGIN("ZstCompress") + { + ZstCompress *driver = memNew(sizeof(ZstCompress)); + + *driver = (ZstCompress) + { + .memContext = MEM_CONTEXT_NEW(), + .context = ZSTD_createCStream(), + .level = level, + }; + + // Set callback to ensure zst context is freed + memContextCallbackSet(driver->memContext, zstCompressFreeResource, driver); + + // Initialize context + zstError(ZSTD_initCStream(driver->context, driver->level)); + + // Create param list + VariantList *paramList = varLstNew(); + varLstAdd(paramList, varNewInt(level)); + + // Create filter interface + this = ioFilterNewP( + ZST_COMPRESS_FILTER_TYPE_STR, driver, paramList, .done = zstCompressDone, .inOut = zstCompressProcess, + .inputSame = zstCompressInputSame); + } + MEM_CONTEXT_NEW_END(); + + FUNCTION_LOG_RETURN(IO_FILTER, this); +} + +#endif // HAVE_LIBZST diff --git a/src/common/compress/zst/compress.h b/src/common/compress/zst/compress.h new file mode 100644 index 000000000..d1dc27c52 --- /dev/null +++ b/src/common/compress/zst/compress.h @@ -0,0 +1,26 @@ +/*********************************************************************************************************************************** +ZST Compress + +Compress IO to the zst format. +***********************************************************************************************************************************/ +#ifdef HAVE_LIBZST + +#ifndef COMMON_COMPRESS_ZST_COMPRESS_H +#define COMMON_COMPRESS_ZST_COMPRESS_H + +#include "common/io/filter/filter.h" + +/*********************************************************************************************************************************** +Filter type constant +***********************************************************************************************************************************/ +#define ZST_COMPRESS_FILTER_TYPE "zstCompress" + STRING_DECLARE(ZST_COMPRESS_FILTER_TYPE_STR); + +/*********************************************************************************************************************************** +Constructors +***********************************************************************************************************************************/ +IoFilter *zstCompressNew(int level); + +#endif + +#endif // HAVE_LIBZST diff --git a/src/common/compress/zst/decompress.c b/src/common/compress/zst/decompress.c new file mode 100644 index 000000000..6d1845b8f --- /dev/null +++ b/src/common/compress/zst/decompress.c @@ -0,0 +1,191 @@ +/*********************************************************************************************************************************** +ZST Decompress +***********************************************************************************************************************************/ +#include "build.auto.h" + +#ifdef HAVE_LIBZST + +#include + +#include "common/compress/zst/common.h" +#include "common/compress/zst/decompress.h" +#include "common/debug.h" +#include "common/io/filter/filter.intern.h" +#include "common/log.h" +#include "common/memContext.h" +#include "common/type/object.h" + +/*********************************************************************************************************************************** +Filter type constant +***********************************************************************************************************************************/ +STRING_EXTERN(ZST_DECOMPRESS_FILTER_TYPE_STR, ZST_DECOMPRESS_FILTER_TYPE); + +/*********************************************************************************************************************************** +Object type +***********************************************************************************************************************************/ +#define ZST_DECOMPRESS_TYPE ZstDecompress +#define ZST_DECOMPRESS_PREFIX zstDecompress + +typedef struct ZstDecompress +{ + MemContext *memContext; // Context to store data + ZSTD_DStream *context; // Decompression context + IoFilter *filter; // Filter interface + + bool inputSame; // Is the same input required on the next process call? + size_t inputOffset; // Current offset in input buffer + bool frameDone; // Has the current frame completed? + bool done; // Is decompression done? +} ZstDecompress; + +/*********************************************************************************************************************************** +Render as string for logging +***********************************************************************************************************************************/ +static String * +zstDecompressToLog(const ZstDecompress *this) +{ + return strNewFmt( + "{inputSame: %s, inputOffset: %zu, frameDone %s, done: %s}", cvtBoolToConstZ(this->inputSame), this->inputOffset, + cvtBoolToConstZ(this->frameDone), cvtBoolToConstZ(this->done)); +} + +#define FUNCTION_LOG_ZST_DECOMPRESS_TYPE \ + ZstDecompress * +#define FUNCTION_LOG_ZST_DECOMPRESS_FORMAT(value, buffer, bufferSize) \ + FUNCTION_LOG_STRING_OBJECT_FORMAT(value, zstDecompressToLog, buffer, bufferSize) + +/*********************************************************************************************************************************** +Free decompression context +***********************************************************************************************************************************/ +OBJECT_DEFINE_FREE_RESOURCE_BEGIN(ZST_DECOMPRESS, LOG, logLevelTrace) +{ + ZSTD_freeDStream(this->context); +} +OBJECT_DEFINE_FREE_RESOURCE_END(LOG); + +/*********************************************************************************************************************************** +Decompress data +***********************************************************************************************************************************/ +static void +zstDecompressProcess(THIS_VOID, const Buffer *compressed, Buffer *decompressed) +{ + THIS(ZstDecompress); + + FUNCTION_LOG_BEGIN(logLevelTrace); + FUNCTION_LOG_PARAM(ZST_DECOMPRESS, this); + FUNCTION_LOG_PARAM(BUFFER, compressed); + FUNCTION_LOG_PARAM(BUFFER, decompressed); + FUNCTION_LOG_END(); + + ASSERT(this != NULL); + ASSERT(this->context != NULL); + ASSERT(decompressed != NULL); + + // When there is no more input then decompression is done + if (compressed == NULL) + { + // If the current frame being decompressed was not completed then error + if (!this->frameDone) + THROW(FormatError, "unexpected eof in compressed data"); + + this->done = true; + } + else + { + // Initialize input/output buffer + ZSTD_inBuffer in = {.src = bufPtrConst(compressed) + this->inputOffset, .size = bufUsed(compressed) - this->inputOffset}; + ZSTD_outBuffer out = {.dst = bufRemainsPtr(decompressed), .size = bufRemains(decompressed)}; + + // Perform decompression. Track frame done so we can detect unexpected EOF. + this->frameDone = zstError(ZSTD_decompressStream(this->context, &out, &in)) == 0; + bufUsedInc(decompressed, out.pos); + + // If the input buffer was not entirely consumed then set inputSame and store the offset where processing will restart + if (in.pos < in.size) + { + // Output buffer should be completely full + ASSERT(out.pos == out.size); + + this->inputSame = true; + this->inputOffset += in.pos; + } + // Else ready for more input + else + { + this->inputOffset = 0; + this->inputSame = false; + } + } + + FUNCTION_LOG_RETURN_VOID(); +} + +/*********************************************************************************************************************************** +Is decompress done? +***********************************************************************************************************************************/ +static bool +zstDecompressDone(const THIS_VOID) +{ + THIS(const ZstDecompress); + + FUNCTION_TEST_BEGIN(); + FUNCTION_TEST_PARAM(ZST_DECOMPRESS, this); + FUNCTION_TEST_END(); + + ASSERT(this != NULL); + + FUNCTION_TEST_RETURN(this->done); +} + +/*********************************************************************************************************************************** +Is the same input required on the next process call? +***********************************************************************************************************************************/ +static bool +zstDecompressInputSame(const THIS_VOID) +{ + THIS(const ZstDecompress); + + FUNCTION_TEST_BEGIN(); + FUNCTION_TEST_PARAM(ZST_DECOMPRESS, this); + FUNCTION_TEST_END(); + + ASSERT(this != NULL); + + FUNCTION_TEST_RETURN(this->inputSame); +} + +/**********************************************************************************************************************************/ +IoFilter * +zstDecompressNew(void) +{ + FUNCTION_LOG_VOID(logLevelTrace); + + IoFilter *this = NULL; + + MEM_CONTEXT_NEW_BEGIN("ZstDecompress") + { + ZstDecompress *driver = memNew(sizeof(ZstDecompress)); + + *driver = (ZstDecompress) + { + .memContext = MEM_CONTEXT_NEW(), + .context = ZSTD_createDStream(), + }; + + // Set callback to ensure zst context is freed + memContextCallbackSet(driver->memContext, zstDecompressFreeResource, driver); + + // Initialize context + zstError(ZSTD_initDStream(driver->context)); + + // Create filter interface + this = ioFilterNewP( + ZST_DECOMPRESS_FILTER_TYPE_STR, driver, NULL, .done = zstDecompressDone, .inOut = zstDecompressProcess, + .inputSame = zstDecompressInputSame); + } + MEM_CONTEXT_NEW_END(); + + FUNCTION_LOG_RETURN(IO_FILTER, this); +} + +#endif // HAVE_LIBZST diff --git a/src/common/compress/zst/decompress.h b/src/common/compress/zst/decompress.h new file mode 100644 index 000000000..a22f4c41b --- /dev/null +++ b/src/common/compress/zst/decompress.h @@ -0,0 +1,26 @@ +/*********************************************************************************************************************************** +ZST Decompress + +Decompress IO from the zst format. +***********************************************************************************************************************************/ +#ifdef HAVE_LIBZST + +#ifndef COMMON_COMPRESS_ZST_DECOMPRESS_H +#define COMMON_COMPRESS_ZST_DECOMPRESS_H + +#include "common/io/filter/filter.h" + +/*********************************************************************************************************************************** +Filter type constant +***********************************************************************************************************************************/ +#define ZST_DECOMPRESS_FILTER_TYPE "zstDecompress" + STRING_DECLARE(ZST_DECOMPRESS_FILTER_TYPE_STR); + +/*********************************************************************************************************************************** +Constructors +***********************************************************************************************************************************/ +IoFilter *zstDecompressNew(void); + +#endif + +#endif // HAVE_LIBZST diff --git a/src/config/define.auto.c b/src/config/define.auto.c index 8b1ef34c7..6492864ea 100644 --- a/src/config/define.auto.c +++ b/src/config/define.auto.c @@ -833,7 +833,8 @@ static ConfigDefineOptionData configDefineOptionData[] = CFGDEFDATA_OPTION_LIST "The following compression types are supported:\n" "\n" "* gz - gzip compression format\n" - "* lz4 - lz4 compression format (not available on all platforms)" + "* lz4 - lz4 compression format (not available on all platforms)\n" + "* zst - Zstandard compression format (not available on all platforms)" ) CFGDEFDATA_OPTION_COMMAND_LIST @@ -848,7 +849,8 @@ static ConfigDefineOptionData configDefineOptionData[] = CFGDEFDATA_OPTION_LIST ( "none", "gz", - "lz4" + "lz4", + "zst" ) CFGDEFDATA_OPTION_OPTIONAL_DEFAULT("gz") diff --git a/src/configure b/src/configure index 4594fe821..e6451a50b 100755 --- a/src/configure +++ b/src/configure @@ -4070,6 +4070,75 @@ fi fi +# Check optional zst library. Ignore any versions below 1.0. +# ---------------------------------------------------------------------------------------------------------------------------------- +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ZSTD_isError in -lzstd" >&5 +$as_echo_n "checking for ZSTD_isError in -lzstd... " >&6; } +if ${ac_cv_lib_zstd_ZSTD_isError+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lzstd $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ZSTD_isError (); +int +main () +{ +return ZSTD_isError (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_zstd_ZSTD_isError=yes +else + ac_cv_lib_zstd_ZSTD_isError=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_zstd_ZSTD_isError" >&5 +$as_echo "$ac_cv_lib_zstd_ZSTD_isError" >&6; } +if test "x$ac_cv_lib_zstd_ZSTD_isError" = xyes; then : + ac_fn_c_check_header_mongrel "$LINENO" "zstd.h" "ac_cv_header_zstd_h" "$ac_includes_default" +if test "x$ac_cv_header_zstd_h" = xyes; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +#if ZSTD_VERSION_MAJOR < 1 + #error "ZSTD_VERSION_MAJOR must be >= 1" + #endif + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + $as_echo "#define HAVE_LIBZST 1" >>confdefs.h + LIBS="${LIBS} -lzstd" + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +else + as_fn_error $? "header file is required" "$LINENO" 5 +fi + + +fi + + # Write output # ---------------------------------------------------------------------------------------------------------------------------------- ac_config_headers="$ac_config_headers build.auto.h" @@ -5348,4 +5417,4 @@ if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi -# Generated from src/build/configure.ac sha1 8f4c0f8a2389f1f0f30c72c1a50c0c8905474095 +# Generated from src/build/configure.ac sha1 93fbf56725f3dab1089ddd4d7768f4414bf7941c diff --git a/test/Vagrantfile b/test/Vagrantfile index 3b30d516f..41b4c3bcf 100644 --- a/test/Vagrantfile +++ b/test/Vagrantfile @@ -75,7 +75,7 @@ Vagrant.configure(2) do |config| #----------------------------------------------------------------------------------------------------------------------- echo 'Install Build Tools' && date apt-get install -y devscripts build-essential lintian git cloc txt2man debhelper libssl-dev zlib1g-dev libperl-dev \ - libxml2-dev liblz4-dev liblz4-tool libpq-dev valgrind lcov autoconf-archive + libxml2-dev liblz4-dev liblz4-tool libpq-dev valgrind lcov autoconf-archive zstd libzstd-dev #----------------------------------------------------------------------------------------------------------------------- echo 'Install Docker' && date diff --git a/test/container.yaml b/test/container.yaml index ad5f229c3..27688a163 100644 --- a/test/container.yaml +++ b/test/container.yaml @@ -12,11 +12,13 @@ # - docker login -u pgbackrest # - VM=XXX;DATE=YYYYMMDDX;BASE=pgbackrest/test:${VM?}-base;docker tag ${BASE?} ${BASE?}-${DATE?} && docker push ${BASE?}-${DATE?} # ********************************************************************************************************************************** +20200504A: + co7: 9c922915380c0beb3d813c94d53f823d7008c69b + f30: 9ad36516c2403b835c24efbbcef359322a80fa1f + u18: 32426ecf8cd0e98976298f6f6b41a2b255aca692 + 20200310A: co6: beb7b5a62ebdf209bb54494129baeadbd0c2954f - co7: 833c4ef292b9b3c957d9d7d296ec7c03ec6310c2 - f30: 9ef023b179bd9e54bb079d60b75516067a4b4b1d - u18: 5e295130131d5fe96e2483885c171677b52c8ce3 20200124A: u12: 0f2fcf1bc79ee35e78121773c9a2155a77cb10d5 diff --git a/test/define.yaml b/test/define.yaml index 947db2b84..895e795e4 100644 --- a/test/define.yaml +++ b/test/define.yaml @@ -262,7 +262,7 @@ unit: # ---------------------------------------------------------------------------------------------------------------------------- - name: compress - total: 3 + total: 4 coverage: common/compress/gz/common: full @@ -271,6 +271,9 @@ unit: common/compress/lz4/common: full common/compress/lz4/compress: full common/compress/lz4/decompress: full + common/compress/zst/common: full + common/compress/zst/compress: full + common/compress/zst/decompress: full common/compress/helper: full # ---------------------------------------------------------------------------------------------------------------------------- diff --git a/test/expect/mock-all-001.log b/test/expect/mock-all-001.log index 5765b9780..5d7c90ae3 100644 --- a/test/expect/mock-all-001.log +++ b/test/expect/mock-all-001.log @@ -2176,11 +2176,11 @@ backrest-checksum="[CHECKSUM]" diff backup - remove files (db-master host) > [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --no-online --process-max=1 --delta --type=diff --stanza=db backup ------------------------------------------------------------------------------------------------------------------------------------ -P00 INFO: backup command begin [BACKREST-VERSION]: --buffer-size=[BUFFER-SIZE] --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --delta --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=[LOG-LEVEL-FILE] --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log[] --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base-2 --process-max=1 --protocol-timeout=60 --repo1-hardlink --repo1-path=[TEST_PATH]/db-master/repo --stanza=db --start-fast --type=diff +P00 INFO: backup command begin [BACKREST-VERSION]: --buffer-size=[BUFFER-SIZE] --compress-level=3 --compress-type=zst --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --delta --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=[LOG-LEVEL-FILE] --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log[] --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base-2 --process-max=1 --protocol-timeout=60 --repo1-hardlink --repo1-path=[TEST_PATH]/db-master/repo --stanza=db --start-fast --type=diff P00 WARN: option repo1-retention-full is not set, the repository may run out of space HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum. P00 INFO: last backup label = [BACKUP-FULL-2], version = [VERSION-1] -P00 WARN: diff backup cannot alter compress-type option to 'gz', reset to value in [BACKUP-FULL-2] +P00 WARN: diff backup cannot alter compress-type option to 'zst', reset to value in [BACKUP-FULL-2] P00 WARN: diff backup cannot alter hardlink option to 'true', reset to value in [BACKUP-FULL-2] P00 WARN: diff backup cannot alter 'checksum-page' option to 'false', reset to 'true' from [BACKUP-FULL-2] P01 DETAIL: match file from prior backup [TEST_PATH]/db-master/db/base-2/base/32768/33001 (64KB, 36%) checksum 6bf316f11d28c28914ea9be92c00de9bea6d9a6b @@ -2237,6 +2237,7 @@ tablespace-map=2=[TEST_PATH]/db-master/db/tablespace/ts2-2 [global] buffer-size=[BUFFER-SIZE] compress-level=3 +compress-type=zst db-timeout=45 lock-path=[TEST_PATH]/db-master/lock log-level-console=detail @@ -2391,7 +2392,7 @@ backrest-checksum="[CHECKSUM]" full backup - update file (db-master host) > [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --no-online --type=full --stanza=db backup ------------------------------------------------------------------------------------------------------------------------------------ -P00 INFO: backup command begin [BACKREST-VERSION]: --buffer-size=[BUFFER-SIZE] --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=[LOG-LEVEL-FILE] --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log[] --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base-2 --protocol-timeout=60 --repo1-hardlink --repo1-path=[TEST_PATH]/db-master/repo --stanza=db --start-fast --type=full +P00 INFO: backup command begin [BACKREST-VERSION]: --buffer-size=[BUFFER-SIZE] --compress-level=3 --compress-type=zst --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=[LOG-LEVEL-FILE] --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log[] --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base-2 --protocol-timeout=60 --repo1-hardlink --repo1-path=[TEST_PATH]/db-master/repo --stanza=db --start-fast --type=full P00 WARN: option repo1-retention-full is not set, the repository may run out of space HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum. P01 INFO: backup file [TEST_PATH]/db-master/db/base-2/base/32768/33001 (64KB, 36%) checksum 6bf316f11d28c28914ea9be92c00de9bea6d9a6b @@ -2434,6 +2435,7 @@ tablespace-map=2=[TEST_PATH]/db-master/db/tablespace/ts2-2 [global] buffer-size=[BUFFER-SIZE] compress-level=3 +compress-type=zst db-timeout=45 lock-path=[TEST_PATH]/db-master/lock log-level-console=detail @@ -2480,7 +2482,7 @@ option-checksum-page=false option-compress=true option-compress-level=3 option-compress-level-network=3 -option-compress-type="gz" +option-compress-type="zst" option-delta=false option-hardlink=true option-online=false @@ -2603,7 +2605,7 @@ P00 INFO: expire command end: completed successfully diff backup - add file (db-master host) > [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --no-online --checksum-page --type=diff --stanza=db backup ------------------------------------------------------------------------------------------------------------------------------------ -P00 INFO: backup command begin [BACKREST-VERSION]: --buffer-size=[BUFFER-SIZE] --checksum-page --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=[LOG-LEVEL-FILE] --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log[] --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base-2 --protocol-timeout=60 --repo1-hardlink --repo1-path=[TEST_PATH]/db-master/repo --stanza=db --start-fast --type=diff +P00 INFO: backup command begin [BACKREST-VERSION]: --buffer-size=[BUFFER-SIZE] --checksum-page --compress-level=3 --compress-type=zst --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=[LOG-LEVEL-FILE] --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log[] --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base-2 --protocol-timeout=60 --repo1-hardlink --repo1-path=[TEST_PATH]/db-master/repo --stanza=db --start-fast --type=diff P00 WARN: option repo1-retention-full is not set, the repository may run out of space HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum. P00 INFO: last backup label = [BACKUP-FULL-3], version = [VERSION-1] @@ -2648,6 +2650,7 @@ tablespace-map=2=[TEST_PATH]/db-master/db/tablespace/ts2-2 [global] buffer-size=[BUFFER-SIZE] compress-level=3 +compress-type=zst db-timeout=45 lock-path=[TEST_PATH]/db-master/lock log-level-console=detail @@ -2695,7 +2698,7 @@ option-checksum-page=false option-compress=true option-compress-level=3 option-compress-level-network=3 -option-compress-type="gz" +option-compress-type="zst" option-delta=false option-hardlink=true option-online=false @@ -3034,7 +3037,7 @@ restore_command = '[BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf diff backup - option backup-standby reset - backup performed from master (db-master host) > [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --no-online --log-level-console=info --backup-standby --type=diff --stanza=db backup ------------------------------------------------------------------------------------------------------------------------------------ -P00 INFO: backup command begin [BACKREST-VERSION]: --backup-standby --buffer-size=[BUFFER-SIZE] --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=info --log-level-file=[LOG-LEVEL-FILE] --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log[] --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base-2/base --protocol-timeout=60 --repo1-hardlink --repo1-path=[TEST_PATH]/db-master/repo --stanza=db --start-fast --type=diff +P00 INFO: backup command begin [BACKREST-VERSION]: --backup-standby --buffer-size=[BUFFER-SIZE] --compress-level=3 --compress-type=zst --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=info --log-level-file=[LOG-LEVEL-FILE] --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log[] --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base-2/base --protocol-timeout=60 --repo1-hardlink --repo1-path=[TEST_PATH]/db-master/repo --stanza=db --start-fast --type=diff P00 WARN: option repo1-retention-full is not set, the repository may run out of space HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum. P00 WARN: option backup-standby is enabled but backup is offline - backups will be performed from the primary @@ -3057,6 +3060,7 @@ pg1-path=[TEST_PATH]/db-master/db/base-2/base [global] buffer-size=[BUFFER-SIZE] compress-level=3 +compress-type=zst db-timeout=45 lock-path=[TEST_PATH]/db-master/lock log-level-console=detail @@ -3104,7 +3108,7 @@ option-checksum-page=false option-compress=true option-compress-level=3 option-compress-level-network=3 -option-compress-type="gz" +option-compress-type="zst" option-delta=false option-hardlink=true option-online=false diff --git a/test/expect/mock-archive-002.log b/test/expect/mock-archive-002.log index ac17269f7..c8db0f14d 100644 --- a/test/expect/mock-archive-002.log +++ b/test/expect/mock-archive-002.log @@ -1,5 +1,5 @@ -run 002 - rmt 1, s3 1, enc 0, cmp gz -==================================== +run 002 - rmt 1, s3 1, enc 0, cmp zst +===================================== > [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-push [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001 ------------------------------------------------------------------------------------------------------------------------------------ @@ -70,9 +70,9 @@ db-version="9.4" [backrest] backrest-checksum="[CHECKSUM]" -> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-push --cmd-ssh=/usr/bin/ssh --compress-type=gz [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001 +> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-push --cmd-ssh=/usr/bin/ssh --compress-type=zst [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001 ------------------------------------------------------------------------------------------------------------------------------------ -P00 INFO: archive-push command begin [BACKREST-VERSION]: [[TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001] --buffer-size=[BUFFER-SIZE] --cmd-ssh=/usr/bin/ssh --compress-level=3 --compress-level-network=1 --compress-type=gz --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=[LOG-LEVEL-FILE] --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log[] --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-host=backup --repo1-host-cmd=[BACKREST-BIN] --repo1-host-config=[TEST_PATH]/backup/pgbackrest.conf --repo1-host-user=[USER-1] --stanza=db +P00 INFO: archive-push command begin [BACKREST-VERSION]: [[TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001] --buffer-size=[BUFFER-SIZE] --cmd-ssh=/usr/bin/ssh --compress-level=3 --compress-level-network=1 --compress-type=zst --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=[LOG-LEVEL-FILE] --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log[] --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-host=backup --repo1-host-cmd=[BACKREST-BIN] --repo1-host-config=[TEST_PATH]/backup/pgbackrest.conf --repo1-host-user=[USER-1] --stanza=db P00 INFO: pushed WAL file '000000010000000100000001' to the archive P00 INFO: archive-push command end: completed successfully @@ -88,9 +88,9 @@ P00 INFO: archive-get command begin [BACKREST-VERSION]: [000000010000000100000 P00 INFO: found 000000010000000100000001 in the archive P00 INFO: archive-get command end: completed successfully -> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-push --compress-type=gz --archive-async --process-max=2 [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000002 +> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-push --compress-type=zst --archive-async --process-max=2 [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000002 ------------------------------------------------------------------------------------------------------------------------------------ -P00 INFO: archive-push command begin [BACKREST-VERSION]: [[TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000002] --archive-async --buffer-size=[BUFFER-SIZE] --compress-level=3 --compress-level-network=1 --compress-type=gz --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=[LOG-LEVEL-FILE] --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log[] --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --process-max=2 --protocol-timeout=60 --repo1-host=backup --repo1-host-cmd=[BACKREST-BIN] --repo1-host-config=[TEST_PATH]/backup/pgbackrest.conf --repo1-host-user=[USER-1] --spool-path=[TEST_PATH]/db-master/spool --stanza=db +P00 INFO: archive-push command begin [BACKREST-VERSION]: [[TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000002] --archive-async --buffer-size=[BUFFER-SIZE] --compress-level=3 --compress-level-network=1 --compress-type=zst --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=[LOG-LEVEL-FILE] --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log[] --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --process-max=2 --protocol-timeout=60 --repo1-host=backup --repo1-host-cmd=[BACKREST-BIN] --repo1-host-config=[TEST_PATH]/backup/pgbackrest.conf --repo1-host-user=[USER-1] --spool-path=[TEST_PATH]/db-master/spool --stanza=db P00 INFO: pushed WAL file '000000010000000100000002' to the archive asynchronously P00 INFO: archive-push command end: completed successfully diff --git a/test/expect/mock-stanza-001.log b/test/expect/mock-stanza-001.log index cdcf7a0d5..86c9113a4 100644 --- a/test/expect/mock-stanza-001.log +++ b/test/expect/mock-stanza-001.log @@ -1,5 +1,5 @@ -run 001 - remote 0, s3 0, enc 0, cmp gz -======================================= +run 001 - remote 0, s3 0, enc 0, cmp zst +======================================== stanza-create db - fail on missing control file (db-master host) > [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online --log-level-file=[LOG-LEVEL-FILE] stanza-create @@ -197,7 +197,7 @@ backrest-checksum="[CHECKSUM]" > [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-push [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001 ------------------------------------------------------------------------------------------------------------------------------------ -P00 INFO: archive-push command begin [BACKREST-VERSION]: [[TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001] --buffer-size=[BUFFER-SIZE] --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=[LOG-LEVEL-FILE] --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log[] --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db +P00 INFO: archive-push command begin [BACKREST-VERSION]: [[TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001] --buffer-size=[BUFFER-SIZE] --compress-level=3 --compress-type=zst --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=[LOG-LEVEL-FILE] --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log[] --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db P00 INFO: pushed WAL file '000000010000000100000001' to the archive P00 INFO: archive-push command end: completed successfully @@ -230,7 +230,7 @@ backrest-checksum="[CHECKSUM]" > [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-push [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000002 ------------------------------------------------------------------------------------------------------------------------------------ -P00 INFO: archive-push command begin [BACKREST-VERSION]: [[TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000002] --buffer-size=[BUFFER-SIZE] --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=[LOG-LEVEL-FILE] --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log[] --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db +P00 INFO: archive-push command begin [BACKREST-VERSION]: [[TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000002] --buffer-size=[BUFFER-SIZE] --compress-level=3 --compress-type=zst --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=[LOG-LEVEL-FILE] --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log[] --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db P00 INFO: pushed WAL file '000000010000000100000002' to the archive P00 INFO: archive-push command end: completed successfully @@ -295,7 +295,7 @@ P00 INFO: archive-get command end: completed successfully full backup - create first full backup (db-master host) > [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --repo1-retention-full=2 --no-online --type=full --stanza=db backup ------------------------------------------------------------------------------------------------------------------------------------ -P00 INFO: backup command begin [BACKREST-VERSION]: --buffer-size=[BUFFER-SIZE] --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=[LOG-LEVEL-FILE] --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log[] --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --repo1-retention-full=2 --stanza=db --start-fast --type=full +P00 INFO: backup command begin [BACKREST-VERSION]: --buffer-size=[BUFFER-SIZE] --compress-level=3 --compress-type=zst --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=[LOG-LEVEL-FILE] --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log[] --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --repo1-retention-full=2 --stanza=db --start-fast --type=full P01 INFO: backup file [TEST_PATH]/db-master/db/base/pg_xlog/RECOVERYXLOG (16MB, 33%) checksum 488ba4b8b98acc510bce86b8f16e3c1ed9886a29 P01 INFO: backup file [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000002 (16MB, 66%) checksum 488ba4b8b98acc510bce86b8f16e3c1ed9886a29 P01 INFO: backup file [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001 (16MB, 99%) checksum e40de8cea99dd469c3efb47f5f33a73c7390fb9c @@ -316,6 +316,7 @@ pg1-path=[TEST_PATH]/db-master/db/base [global] buffer-size=[BUFFER-SIZE] compress-level=3 +compress-type=zst db-timeout=45 lock-path=[TEST_PATH]/db-master/lock log-level-console=detail @@ -438,7 +439,7 @@ backrest-checksum="[CHECKSUM]" diff backup - diff changed to full backup (db-master host) > [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --repo1-retention-full=2 --no-online --type=diff --stanza=db backup ------------------------------------------------------------------------------------------------------------------------------------ -P00 INFO: backup command begin [BACKREST-VERSION]: --buffer-size=[BUFFER-SIZE] --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=[LOG-LEVEL-FILE] --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log[] --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --repo1-retention-full=2 --stanza=db --start-fast --type=diff +P00 INFO: backup command begin [BACKREST-VERSION]: --buffer-size=[BUFFER-SIZE] --compress-level=3 --compress-type=zst --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=[LOG-LEVEL-FILE] --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log[] --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --repo1-retention-full=2 --stanza=db --start-fast --type=diff P00 WARN: no prior backup exists, diff backup has been changed to full P01 INFO: backup file [TEST_PATH]/db-master/db/base/pg_xlog/RECOVERYXLOG (16MB, 33%) checksum 488ba4b8b98acc510bce86b8f16e3c1ed9886a29 P01 INFO: backup file [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000002 (16MB, 66%) checksum 488ba4b8b98acc510bce86b8f16e3c1ed9886a29 @@ -461,6 +462,7 @@ pg1-path=[TEST_PATH]/db-master/db/base [global] buffer-size=[BUFFER-SIZE] compress-level=3 +compress-type=zst db-timeout=45 lock-path=[TEST_PATH]/db-master/lock log-level-console=detail diff --git a/test/expect/real-all-006.log b/test/expect/real-all-006.log index 70ee17fe1..4881d7df8 100644 --- a/test/expect/real-all-006.log +++ b/test/expect/real-all-006.log @@ -1,5 +1,5 @@ -run 006 - bkp 1, sby 0, dst backup, cmp gz, s3 1, enc 0 -======================================================= +run 006 - bkp 1, sby 0, dst backup, cmp zst, s3 1, enc 0 +======================================================== stanza-create db - main create stanza info files (backup host) > [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db stanza-create @@ -108,6 +108,7 @@ pg1-socket-path=[TEST_PATH]/db-master/db buffer-size=[BUFFER-SIZE] compress-level=3 compress-level-network=1 +compress-type=zst db-timeout=45 lock-path=[TEST_PATH]/db-master/lock log-level-console=detail @@ -138,6 +139,7 @@ pg1-port=6543 buffer-size=[BUFFER-SIZE] compress-level=3 compress-level-network=1 +compress-type=zst db-timeout=45 lock-path=[TEST_PATH]/backup/lock log-level-console=detail @@ -176,6 +178,7 @@ pg1-socket-path=[TEST_PATH]/db-master/db buffer-size=[BUFFER-SIZE] compress-level=3 compress-level-network=1 +compress-type=zst db-timeout=45 lock-path=[TEST_PATH]/db-master/lock log-level-console=detail @@ -207,6 +210,7 @@ archive-async=y buffer-size=[BUFFER-SIZE] compress-level=3 compress-level-network=1 +compress-type=zst db-timeout=45 lock-path=[TEST_PATH]/backup/lock log-level-console=detail diff --git a/test/lib/pgBackRestTest/Common/ContainerTest.pm b/test/lib/pgBackRestTest/Common/ContainerTest.pm index 936fb5e43..b2e96604a 100755 --- a/test/lib/pgBackRestTest/Common/ContainerTest.pm +++ b/test/lib/pgBackRestTest/Common/ContainerTest.pm @@ -392,6 +392,19 @@ sub containerBuild } } + # Add zst command-line tool and development libs when available + if (vmWithZst($strOS)) + { + if ($oVm->{$strOS}{&VM_OS_BASE} eq VM_OS_BASE_RHEL) + { + $strScript .= ' zstd libzstd-devel'; + } + else + { + $strScript .= ' zstd libzstd-dev'; + } + } + # If no specific version of lcov is requested then install the default package if (!defined($oVm->{$strOS}{&VMDEF_LCOV_VERSION})) { diff --git a/test/lib/pgBackRestTest/Common/JobTest.pm b/test/lib/pgBackRestTest/Common/JobTest.pm index f984bb0eb..1743c1185 100644 --- a/test/lib/pgBackRestTest/Common/JobTest.pm +++ b/test/lib/pgBackRestTest/Common/JobTest.pm @@ -440,7 +440,8 @@ sub run my $strBuildAutoH = ($self->{oTest}->{&TEST_VM} ne VM_CO6 ? "#define HAVE_STATIC_ASSERT\n" : '') . "#define HAVE_BUILTIN_TYPES_COMPATIBLE_P\n" . - (vmWithLz4($self->{oTest}->{&TEST_VM}) ? '#define HAVE_LIBLZ4' : '') . "\n"; + (vmWithLz4($self->{oTest}->{&TEST_VM}) ? '#define HAVE_LIBLZ4' : '') . "\n" . + (vmWithZst($self->{oTest}->{&TEST_VM}) ? '#define HAVE_LIBZST' : '') . "\n"; buildPutDiffers($self->{oStorageTest}, "$self->{strGCovPath}/" . BUILD_AUTO_H, $strBuildAutoH); @@ -519,6 +520,7 @@ sub run "TESTFLAGS=${strTestFlags}\n" . "LDFLAGS=-lcrypto -lssl -lxml2 -lz" . (vmWithLz4($self->{oTest}->{&TEST_VM}) ? ' -llz4' : '') . + (vmWithZst($self->{oTest}->{&TEST_VM}) ? ' -lzstd' : '') . (vmCoverageC($self->{oTest}->{&TEST_VM}) && $self->{bCoverageUnit} ? " -lgcov" : '') . (vmWithBackTrace($self->{oTest}->{&TEST_VM}) && $self->{bBackTrace} ? ' -lbacktrace' : '') . "\n" . diff --git a/test/lib/pgBackRestTest/Common/VmTest.pm b/test/lib/pgBackRestTest/Common/VmTest.pm index 91716fb28..d8edb02a1 100644 --- a/test/lib/pgBackRestTest/Common/VmTest.pm +++ b/test/lib/pgBackRestTest/Common/VmTest.pm @@ -51,6 +51,8 @@ use constant VMDEF_WITH_BACKTRACE => 'with-bac push @EXPORT, qw(VMDEF_WITH_BACKTRACE); use constant VMDEF_WITH_LZ4 => 'with-lz4'; push @EXPORT, qw(VMDEF_WITH_LZ4); +use constant VMDEF_WITH_ZST => 'with-zst'; + push @EXPORT, qw(VMDEF_WITH_ZST); #################################################################################################################################### # Valid OS base List @@ -139,6 +141,8 @@ my $oyVm = &VMDEF_COVERAGE_C => true, &VMDEF_PGSQL_BIN => '/usr/lib/postgresql/{[version]}/bin', + &VMDEF_WITH_ZST => true, + &VM_DB => [ PG_VERSION_10, @@ -191,6 +195,7 @@ my $oyVm = &VMDEF_PGSQL_BIN => '/usr/pgsql-{[version]}/bin', &VMDEF_DEBUG_INTEGRATION => false, + &VMDEF_WITH_ZST => true, &VM_DB => [ @@ -220,6 +225,7 @@ my $oyVm = &VMDEF_COVERAGE_C => true, &VMDEF_DEBUG_INTEGRATION => false, + &VMDEF_WITH_ZST => true, &VM_DB => [ @@ -399,6 +405,7 @@ my $oyVm = &VMDEF_PGSQL_BIN => '/usr/lib/postgresql/{[version]}/bin', &VMDEF_WITH_BACKTRACE => true, + &VMDEF_WITH_ZST => true, &VM_DB => [ @@ -575,6 +582,18 @@ sub vmWithLz4 push @EXPORT, qw(vmWithLz4); +#################################################################################################################################### +# Does the VM support liblzst? +#################################################################################################################################### +sub vmWithZst +{ + my $strVm = shift; + + return (defined($oyVm->{$strVm}{&VMDEF_WITH_ZST}) ? $oyVm->{$strVm}{&VMDEF_WITH_ZST} : false); +} + +push @EXPORT, qw(vmWithZst); + #################################################################################################################################### # Will integration tests be run in debug mode? #################################################################################################################################### diff --git a/test/lib/pgBackRestTest/Env/Host/HostBackupTest.pm b/test/lib/pgBackRestTest/Env/Host/HostBackupTest.pm index eaec720a9..c11aa953e 100644 --- a/test/lib/pgBackRestTest/Env/Host/HostBackupTest.pm +++ b/test/lib/pgBackRestTest/Env/Host/HostBackupTest.pm @@ -99,6 +99,8 @@ use constant GZ => 'gz'; push @EXPORT, qw(GZ); use constant LZ4 => 'lz4'; push @EXPORT, qw(LZ4); +use constant ZST => 'zst'; + push @EXPORT, qw(ZST); #################################################################################################################################### # new diff --git a/test/lib/pgBackRestTest/Module/Mock/MockAllTest.pm b/test/lib/pgBackRestTest/Module/Mock/MockAllTest.pm index afc526398..18fdd3b14 100644 --- a/test/lib/pgBackRestTest/Module/Mock/MockAllTest.pm +++ b/test/lib/pgBackRestTest/Module/Mock/MockAllTest.pm @@ -209,10 +209,10 @@ sub run {vm => VM1, remote => true, s3 => false, encrypt => true, delta => false, compress => GZ}, {vm => VM2, remote => false, s3 => false, encrypt => true, delta => true, compress => GZ}, {vm => VM2, remote => true, s3 => true, encrypt => false, delta => false, compress => GZ}, - {vm => VM3, remote => false, s3 => false, encrypt => false, delta => true, compress => GZ}, + {vm => VM3, remote => false, s3 => false, encrypt => false, delta => true, compress => ZST}, {vm => VM3, remote => true, s3 => true, encrypt => true, delta => false, compress => LZ4}, {vm => VM4, remote => false, s3 => false, encrypt => false, delta => false, compress => LZ4}, - {vm => VM4, remote => true, s3 => true, encrypt => true, delta => true, compress => GZ}, + {vm => VM4, remote => true, s3 => true, encrypt => true, delta => true, compress => ZST}, ) { # Only run tests for this vm diff --git a/test/lib/pgBackRestTest/Module/Mock/MockArchiveStopTest.pm b/test/lib/pgBackRestTest/Module/Mock/MockArchiveStopTest.pm index ec2ace8eb..af3dcae2e 100644 --- a/test/lib/pgBackRestTest/Module/Mock/MockArchiveStopTest.pm +++ b/test/lib/pgBackRestTest/Module/Mock/MockArchiveStopTest.pm @@ -49,7 +49,7 @@ sub run {vm => VM2, remote => true, s3 => false, encrypt => true, compress => GZ, error => 0}, {vm => VM3, remote => false, s3 => false, encrypt => true, compress => NONE, error => 0}, {vm => VM3, remote => true, s3 => true, encrypt => false, compress => LZ4, error => 1}, - {vm => VM4, remote => false, s3 => true, encrypt => true, compress => GZ, error => 0}, + {vm => VM4, remote => false, s3 => true, encrypt => true, compress => ZST, error => 0}, {vm => VM4, remote => true, s3 => false, encrypt => false, compress => NONE, error => 0}, ) { diff --git a/test/lib/pgBackRestTest/Module/Mock/MockArchiveTest.pm b/test/lib/pgBackRestTest/Module/Mock/MockArchiveTest.pm index e5d53b69a..a9a405bb2 100644 --- a/test/lib/pgBackRestTest/Module/Mock/MockArchiveTest.pm +++ b/test/lib/pgBackRestTest/Module/Mock/MockArchiveTest.pm @@ -88,8 +88,8 @@ sub run {vm => VM2, remote => false, s3 => true, encrypt => false, compress => GZ}, {vm => VM2, remote => true, s3 => false, encrypt => true, compress => GZ}, {vm => VM3, remote => false, s3 => false, encrypt => true, compress => LZ4}, - {vm => VM3, remote => true, s3 => true, encrypt => false, compress => GZ}, - {vm => VM4, remote => false, s3 => true, encrypt => true, compress => GZ}, + {vm => VM3, remote => true, s3 => true, encrypt => false, compress => ZST}, + {vm => VM4, remote => false, s3 => true, encrypt => true, compress => ZST}, {vm => VM4, remote => true, s3 => false, encrypt => false, compress => LZ4}, ) { diff --git a/test/lib/pgBackRestTest/Module/Mock/MockStanzaTest.pm b/test/lib/pgBackRestTest/Module/Mock/MockStanzaTest.pm index 8700ff0d7..0f4489365 100644 --- a/test/lib/pgBackRestTest/Module/Mock/MockStanzaTest.pm +++ b/test/lib/pgBackRestTest/Module/Mock/MockStanzaTest.pm @@ -45,10 +45,10 @@ sub run {vm => VM1, remote => true, s3 => true, encrypt => false, compress => GZ}, {vm => VM2, remote => false, s3 => true, encrypt => true, compress => GZ}, {vm => VM2, remote => true, s3 => false, encrypt => false, compress => GZ}, - {vm => VM3, remote => false, s3 => false, encrypt => false, compress => GZ}, + {vm => VM3, remote => false, s3 => false, encrypt => false, compress => ZST}, {vm => VM3, remote => true, s3 => true, encrypt => true, compress => LZ4}, {vm => VM4, remote => false, s3 => true, encrypt => false, compress => LZ4}, - {vm => VM4, remote => true, s3 => false, encrypt => true, compress => GZ}, + {vm => VM4, remote => true, s3 => false, encrypt => true, compress => ZST}, ) { # Only run tests for this vm diff --git a/test/lib/pgBackRestTest/Module/Real/RealAllTest.pm b/test/lib/pgBackRestTest/Module/Real/RealAllTest.pm index d3b8aca57..730f43769 100644 --- a/test/lib/pgBackRestTest/Module/Real/RealAllTest.pm +++ b/test/lib/pgBackRestTest/Module/Real/RealAllTest.pm @@ -64,7 +64,9 @@ sub run foreach my $strBackupDestination ( $bS3 || $bHostBackup ? (HOST_BACKUP) : $bHostStandby ? (HOST_DB_MASTER, HOST_DB_STANDBY) : (HOST_DB_MASTER)) { - my $strCompressType = $bHostBackup && !$bHostStandby ? (vmWithLz4($self->vm()) && $bLz4Compress ? LZ4 : GZ) : NONE; + my $strCompressType = + $bHostBackup && !$bHostStandby ? + (vmWithLz4($self->vm()) && $bLz4Compress ? LZ4 : vmWithZst($self->vm()) ? ZST : GZ) : NONE; my $bRepoEncrypt = ($strCompressType ne NONE && !$bS3) ? true : false; # If compression was used then switch it for the next test that uses compression diff --git a/test/patch/debian-package.patch b/test/patch/debian-package.patch new file mode 100644 index 000000000..6c319ed78 --- /dev/null +++ b/test/patch/debian-package.patch @@ -0,0 +1,12 @@ +--- control ++++ control +@@ -13,7 +13,8 @@ + pkg-config, + txt2man, + zlib1g-dev, +- liblz4-dev ++ liblz4-dev, ++ libzstd-dev, + Standards-Version: 4.4.1 + Homepage: https://www.pgbackrest.org/ + Vcs-Git: https://salsa.debian.org/postgresql/pgbackrest.git diff --git a/test/src/module/common/compressTest.c b/test/src/module/common/compressTest.c index 5b646f263..22a1cfec5 100644 --- a/test/src/module/common/compressTest.c +++ b/test/src/module/common/compressTest.c @@ -154,7 +154,7 @@ testSuite(CompressType type, const char *decompressCmd) bufUsedSet(decompressed, bufSize(decompressed)); TEST_ASSIGN( - compressed, testCompress(compressFilter(type, 3), decompressed, bufSize(decompressed), 1024), + compressed, testCompress(compressFilter(type, 3), decompressed, bufSize(decompressed), 32), "zero data - compress large in/small out buffer"); TEST_RESULT_BOOL( @@ -241,6 +241,45 @@ testRun(void) #endif // HAVE_LIBLZ4 } + // ***************************************************************************************************************************** + if (testBegin("zst")) + { +#ifdef HAVE_LIBZST + // Run standard test suite + testSuite(compressTypeZst, "zstd -dc"); + + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("zstError()"); + + TEST_RESULT_UINT(zstError(0), 0, "check success"); + TEST_ERROR(zstError((size_t)-12), FormatError, "zst error: [-12] Version not supported"); + + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("zstDecompressToLog() and zstCompressToLog()"); + + ZstCompress *compress = (ZstCompress *)ioFilterDriver(zstCompressNew(14)); + + compress->inputSame = true; + compress->inputOffset = 49; + compress->flushing = true; + + TEST_RESULT_STR_Z( + zstCompressToLog(compress), "{level: 14, inputSame: true, inputOffset: 49, flushing: true}", "format object"); + + ZstDecompress *decompress = (ZstDecompress *)ioFilterDriver(zstDecompressNew()); + + decompress->inputSame = true; + decompress->done = true; + decompress->inputOffset = 999; + + TEST_RESULT_STR_Z( + zstDecompressToLog(decompress), "{inputSame: true, inputOffset: 999, frameDone false, done: true}", + "format object"); +#else + TEST_ERROR(compressTypePresent(compressTypeZst), OptionInvalidValueError, "pgBackRest not compiled with zst support"); +#endif // HAVE_LIBZST + } + // Test everything in the helper that is not tested in the individual compression type tests // ***************************************************************************************************************************** if (testBegin("helper")) @@ -255,7 +294,7 @@ testRun(void) TEST_TITLE("compressTypePresent()"); TEST_RESULT_VOID(compressTypePresent(compressTypeNone), "type none always present"); - TEST_ERROR(compressTypePresent(compressTypeZst), OptionInvalidValueError, "pgBackRest not compiled with zst support"); + TEST_ERROR(compressTypePresent(compressTypeXz), OptionInvalidValueError, "pgBackRest not compiled with xz support"); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("compressTypeFromName()"); diff --git a/test/travis.pl b/test/travis.pl index b30bebae6..561bd1441 100755 --- a/test/travis.pl +++ b/test/travis.pl @@ -186,7 +186,7 @@ eval # Extra packages required when testing without containers if ($strVm eq VM_NONE) { - $strPackage .= " valgrind liblz4-dev liblz4-tool"; + $strPackage .= " valgrind liblz4-dev liblz4-tool zstd libzstd-dev"; } # Else packages needed for integration tests on containers else