Skip to content

Instantly share code, notes, and snippets.

@rlerdorf
Created April 25, 2023 04:13
Show Gist options
  • Save rlerdorf/b0e06c139bc7e1f7dd93b9da6a9c8160 to your computer and use it in GitHub Desktop.
Save rlerdorf/b0e06c139bc7e1f7dd93b9da6a9c8160 to your computer and use it in GitHub Desktop.
diff --git a/php_memcached.c b/php_memcached.c
index 8e4fa41..252f0c1 100644
--- a/php_memcached.c
+++ b/php_memcached.c
@@ -37,6 +37,8 @@
#endif
#include <zlib.h>
+#include <zstd.h>
+
#ifdef HAVE_JSON_API
# include "ext/json/php_json.h"
#endif
@@ -107,6 +109,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))
@@ -278,6 +281,8 @@ 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;
+ } else if (!strcmp(ZSTR_VAL(new_value), "zstd")) {
+ MEMC_G(compression_type) = COMPRESSION_TYPE_ZSTD;
} else {
return FAILURE;
}
@@ -897,6 +902,17 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str
}
break;
+ case COMPRESSION_TYPE_ZSTD:
+ {
+ compressed_size = ZSTD_compress((void *)buffer, buffer_size, ZSTR_VAL(payload), ZSTR_LEN(payload), 3);
+
+ if (!ZSTD_isError(compressed_size)) {
+ compress_status = 1;
+ compression_type_flag = MEMC_VAL_COMPRESSION_ZSTD;
+ }
+ }
+ break;
+
case COMPRESSION_TYPE_ZLIB:
{
compressed_size = buffer_size;
@@ -3002,6 +3018,7 @@ 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 ||
+ lval == COMPRESSION_TYPE_ZSTD ||
lval == COMPRESSION_TYPE_ZLIB) {
memc_user_data->compression_type = lval;
} else {
@@ -3606,16 +3623,17 @@ 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) {
+ if (!is_fastlz && !is_zlib && !is_zstd) {
php_error_docref(NULL, E_WARNING, "could not decompress value: unrecognised compression type");
return NULL;
}
@@ -3627,7 +3645,21 @@ zend_string *s_decompress_value (const char *payload, size_t payload_len, uint32
buffer = zend_string_alloc (stored_length, 0);
- if (is_fastlz) {
+ 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 if (is_fastlz) {
decompress_status = ((length = fastlz_decompress(payload, payload_len, &buffer->val, buffer->len)) > 0);
}
else if (is_zlib) {
@@ -4180,6 +4212,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.
diff --git a/php_memcached_private.h b/php_memcached_private.h
index 3e1f358..ae74dbc 100644
--- a/php_memcached_private.h
+++ b/php_memcached_private.h
@@ -94,7 +94,8 @@ typedef enum {
typedef enum {
COMPRESSION_TYPE_ZLIB = 1,
- COMPRESSION_TYPE_FASTLZ = 2
+ COMPRESSION_TYPE_FASTLZ = 2,
+ COMPRESSION_TYPE_ZSTD = 3
} php_memc_compression_type;
typedef struct {
diff --git a/tests/compression_conditions.phpt b/tests/compression_conditions.phpt
index 749ebe8..960058b 100644
--- a/tests/compression_conditions.phpt
+++ b/tests/compression_conditions.phpt
@@ -21,6 +21,8 @@ function get_compression($name) {
return Memcached::COMPRESSION_ZLIB;
case 'fastlz':
return Memcached::COMPRESSION_FASTLZ;
+ case 'zstd':
+ return Memcached::COMPRESSION_ZSTD;
default:
echo "Strange compression type: $name\n";
return 0;
diff --git a/tests/compression_types.phpt b/tests/compression_types.phpt
index ce07aed..809dbb1 100644
--- a/tests/compression_types.phpt
+++ b/tests/compression_types.phpt
@@ -15,6 +15,8 @@ function get_compression($name) {
return Memcached::COMPRESSION_ZLIB;
case 'fastlz':
return Memcached::COMPRESSION_FASTLZ;
+ case 'zstd':
+ return Memcached::COMPRESSION_ZSTD;
default:
echo "Strange compression type: $name\n";
return 0;
@@ -54,6 +56,11 @@ fetch_with_compression($m, 'hello6', $data, '', 'fastlz');
fetch_with_compression($m, 'hello7', $data, 'zlib', '');
fetch_with_compression($m, 'hello8', $data, 'fastlz', '');
fetch_with_compression($m, 'hello9', $data, '', '');
+fetch_with_compression($m, 'hello10', $data, 'zstd', 'zstd');
+fetch_with_compression($m, 'hello11', $data, 'zstd', 'fastlz');
+fetch_with_compression($m, 'hello12', $data, 'fastlz', 'zstd');
+fetch_with_compression($m, 'hello13', $data, '', 'zstd');
+fetch_with_compression($m, 'hello14', $data, 'zstd', '');
?>
--EXPECT--
set=[zlib] get=[zlib]
@@ -74,3 +81,13 @@ set=[fastlz] get=[]
bool(true)
set=[] get=[]
bool(true)
+set=[zstd] get=[zstd]
+bool(true)
+set=[zstd] get=[fastlz]
+bool(true)
+set=[fastlz] get=[zstd]
+bool(true)
+set=[] get=[zstd]
+bool(true)
+set=[zstd] get=[]
+bool(true)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment