-
Notifications
You must be signed in to change notification settings - Fork 326
zstd support #539
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
zstd support #539
Changes from all commits
84a73c0
d78dff7
91dfd11
0869f85
72da554
c3c285f
a8a0d12
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,6 +37,10 @@ | |
#endif | ||
#include <zlib.h> | ||
|
||
#ifdef HAVE_ZSTD_H | ||
#include <zstd.h> | ||
#endif | ||
|
||
#ifdef HAVE_JSON_API | ||
# include "ext/json/php_json.h" | ||
#endif | ||
|
@@ -77,6 +81,7 @@ static int php_memc_list_entry(void) { | |
#define MEMC_OPT_COMPRESSION_TYPE -1004 | ||
#define MEMC_OPT_STORE_RETRY_COUNT -1005 | ||
#define MEMC_OPT_USER_FLAGS -1006 | ||
#define MEMC_OPT_COMPRESSION_LEVEL -1007 | ||
|
||
/**************************************** | ||
Custom result codes | ||
|
@@ -107,6 +112,7 @@ static int php_memc_list_entry(void) { | |
#define MEMC_VAL_COMPRESSED (1<<0) | ||
#define MEMC_VAL_COMPRESSION_ZLIB (1<<1) | ||
#define MEMC_VAL_COMPRESSION_FASTLZ (1<<2) | ||
#define MEMC_VAL_COMPRESSION_ZSTD (1<<3) | ||
|
||
#define MEMC_VAL_GET_FLAGS(internal_flags) (((internal_flags) & MEMC_MASK_INTERNAL) >> 4) | ||
#define MEMC_VAL_SET_FLAG(internal_flags, internal_flag) ((internal_flags) |= (((internal_flag) << 4) & MEMC_MASK_INTERNAL)) | ||
|
@@ -152,6 +158,7 @@ typedef struct { | |
|
||
zend_long serializer; | ||
zend_long compression_type; | ||
zend_long compression_level; | ||
|
||
zend_long store_retry_count; | ||
zend_long set_udf_flags; | ||
|
@@ -278,6 +285,10 @@ static PHP_INI_MH(OnUpdateCompressionType) | |
MEMC_G(compression_type) = COMPRESSION_TYPE_FASTLZ; | ||
} else if (!strcmp(ZSTR_VAL(new_value), "zlib")) { | ||
MEMC_G(compression_type) = COMPRESSION_TYPE_ZLIB; | ||
#ifdef HAVE_ZSTD_H | ||
} else if (!strcmp(ZSTR_VAL(new_value), "zstd")) { | ||
MEMC_G(compression_type) = COMPRESSION_TYPE_ZSTD; | ||
#endif | ||
} else { | ||
return FAILURE; | ||
} | ||
|
@@ -408,6 +419,7 @@ PHP_INI_BEGIN() | |
|
||
MEMC_INI_ENTRY("compression_type", "fastlz", OnUpdateCompressionType, compression_name) | ||
MEMC_INI_ENTRY("compression_factor", "1.3", OnUpdateReal, compression_factor) | ||
MEMC_INI_ENTRY("compression_level", "3", OnUpdateLong, compression_level) | ||
MEMC_INI_ENTRY("compression_threshold", "2000", OnUpdateLong, compression_threshold) | ||
MEMC_INI_ENTRY("serializer", SERIALIZER_DEFAULT_NAME, OnUpdateSerializer, serializer_name) | ||
MEMC_INI_ENTRY("store_retry_count", "0", OnUpdateLong, store_retry_count) | ||
|
@@ -897,6 +909,19 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str | |
} | ||
break; | ||
|
||
#ifdef HAVE_ZSTD_H | ||
case COMPRESSION_TYPE_ZSTD: | ||
{ | ||
compressed_size = ZSTD_compress((void *)buffer, buffer_size, ZSTR_VAL(payload), ZSTR_LEN(payload), MEMC_G(compression_level)); | ||
|
||
if (!ZSTD_isError(compressed_size)) { | ||
compress_status = 1; | ||
compression_type_flag = MEMC_VAL_COMPRESSION_ZSTD; | ||
} | ||
} | ||
break; | ||
#endif | ||
|
||
case COMPRESSION_TYPE_ZLIB: | ||
{ | ||
compressed_size = buffer_size; | ||
|
@@ -2939,6 +2964,9 @@ static PHP_METHOD(Memcached, getOption) | |
case MEMC_OPT_COMPRESSION_TYPE: | ||
RETURN_LONG(memc_user_data->compression_type); | ||
|
||
case MEMC_OPT_COMPRESSION_LEVEL: | ||
RETURN_LONG(memc_user_data->compression_level); | ||
|
||
case MEMC_OPT_COMPRESSION: | ||
RETURN_BOOL(memc_user_data->compression_enabled); | ||
|
||
|
@@ -3001,6 +3029,9 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) | |
case MEMC_OPT_COMPRESSION_TYPE: | ||
lval = zval_get_long(value); | ||
if (lval == COMPRESSION_TYPE_FASTLZ || | ||
#ifdef HAVE_ZSTD_H | ||
lval == COMPRESSION_TYPE_ZSTD || | ||
#endif | ||
lval == COMPRESSION_TYPE_ZLIB) { | ||
memc_user_data->compression_type = lval; | ||
} else { | ||
|
@@ -3608,16 +3639,24 @@ zend_string *s_decompress_value (const char *payload, size_t payload_len, uint32 | |
uint32_t stored_length; | ||
unsigned long length; | ||
zend_bool decompress_status = 0; | ||
zend_bool is_fastlz = 0, is_zlib = 0; | ||
zend_bool is_fastlz = 0, is_zlib = 0, is_zstd = 0; | ||
|
||
if (payload_len < sizeof (uint32_t)) { | ||
return NULL; | ||
} | ||
|
||
is_fastlz = MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_FASTLZ); | ||
is_zstd = MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_ZSTD); | ||
is_zlib = MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_ZLIB); | ||
|
||
if (!is_fastlz && !is_zlib) { | ||
#ifndef HAVE_ZSTD_H | ||
if (is_zstd) { | ||
php_error_docref(NULL, E_WARNING, "could not decompress value: value was compressed with zstd but zstd support has not been compiled in"); | ||
return NULL; | ||
} | ||
#endif | ||
|
||
if (!is_fastlz && !is_zlib && !is_zstd) { | ||
php_error_docref(NULL, E_WARNING, "could not decompress value: unrecognised compression type"); | ||
rlerdorf marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return NULL; | ||
} | ||
|
@@ -3629,6 +3668,23 @@ zend_string *s_decompress_value (const char *payload, size_t payload_len, uint32 | |
|
||
buffer = zend_string_alloc (stored_length, 0); | ||
|
||
#ifdef HAVE_ZSTD_H | ||
if (is_zstd) { | ||
length = ZSTD_getFrameContentSize(payload, payload_len); | ||
if (length == ZSTD_CONTENTSIZE_ERROR) { | ||
php_error_docref(NULL, E_WARNING, "value was not compressed by zstd"); | ||
zend_string_release (buffer); | ||
return NULL; | ||
} else if (length == ZSTD_CONTENTSIZE_UNKNOWN) { | ||
php_error_docref(NULL, E_WARNING, "zstd streaming decompression not supported"); | ||
zend_string_release (buffer); | ||
return NULL; | ||
} | ||
decompress_status = !ZSTD_isError(ZSTD_decompress(&buffer->val, buffer->len, payload, payload_len)); | ||
|
||
} | ||
else | ||
#endif | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (for existing block below) -- I am refreshing myself on the other compression routines, but it looks like they are hard requirements to compile the php-memcached package and so they're never conditional on the libraries. Is that because PHP always offers these routines? (I'll catch up on reading, asking out loud for transparency) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, both zlib and fastlz are mandatory. If the system fastlz is not available it will use a bundled copy. In theory we could do the same with zstd, but it is pretty widely available in every distro these days, so we could also just make it a hard requirement. |
||
if (is_fastlz) { | ||
decompress_status = ((length = fastlz_decompress(payload, payload_len, &buffer->val, buffer->len)) > 0); | ||
} | ||
|
@@ -3955,6 +4011,7 @@ PHP_GINIT_FUNCTION(php_memcached) | |
php_memcached_globals->memc.compression_threshold = 2000; | ||
php_memcached_globals->memc.compression_type = COMPRESSION_TYPE_FASTLZ; | ||
php_memcached_globals->memc.compression_factor = 1.30; | ||
php_memcached_globals->memc.compression_level = 3; | ||
php_memcached_globals->memc.store_retry_count = 2; | ||
|
||
php_memcached_globals->memc.sasl_initialised = 0; | ||
|
@@ -4000,6 +4057,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) | |
|
||
REGISTER_MEMC_CLASS_CONST_LONG(OPT_COMPRESSION, MEMC_OPT_COMPRESSION); | ||
REGISTER_MEMC_CLASS_CONST_LONG(OPT_COMPRESSION_TYPE, MEMC_OPT_COMPRESSION_TYPE); | ||
REGISTER_MEMC_CLASS_CONST_LONG(OPT_COMPRESSION_LEVEL, MEMC_OPT_COMPRESSION_LEVEL); | ||
REGISTER_MEMC_CLASS_CONST_LONG(OPT_PREFIX_KEY, MEMC_OPT_PREFIX_KEY); | ||
REGISTER_MEMC_CLASS_CONST_LONG(OPT_SERIALIZER, MEMC_OPT_SERIALIZER); | ||
|
||
|
@@ -4015,6 +4073,15 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) | |
REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_IGBINARY, 0); | ||
#endif | ||
|
||
/* | ||
* Indicate whether zstd compression is available | ||
*/ | ||
#ifdef HAVE_ZSTD_H | ||
REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_ZSTD, 1); | ||
#else | ||
REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_ZSTD, 0); | ||
#endif | ||
|
||
/* | ||
* Indicate whether json serializer is available | ||
*/ | ||
|
@@ -4186,6 +4253,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) | |
*/ | ||
REGISTER_MEMC_CLASS_CONST_LONG(COMPRESSION_FASTLZ, COMPRESSION_TYPE_FASTLZ); | ||
REGISTER_MEMC_CLASS_CONST_LONG(COMPRESSION_ZLIB, COMPRESSION_TYPE_ZLIB); | ||
REGISTER_MEMC_CLASS_CONST_LONG(COMPRESSION_ZSTD, COMPRESSION_TYPE_ZSTD); | ||
|
||
/* | ||
* Flags. | ||
|
@@ -4351,6 +4419,12 @@ PHP_MINFO_FUNCTION(memcached) | |
php_info_print_table_row(2, "msgpack support", "no"); | ||
#endif | ||
|
||
#ifdef HAVE_ZSTD_H | ||
php_info_print_table_row(2, "zstd support", "yes"); | ||
#else | ||
php_info_print_table_row(2, "zstd support", "no"); | ||
#endif | ||
|
||
php_info_print_table_end(); | ||
|
||
DISPLAY_INI_ENTRIES(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like the scenario here is setting the compression type to zstd, but it's not compiled in, you get an invalid argument error. Seems reasonable!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not planning anything else for the moment. There is some interesting stuff that could be done around training zstd and using dictionary compression, but that is probably overkill here.