mirror of
https://github.com/php-win-ext/phpredis.git
synced 2026-03-24 00:52:16 +01:00
Separate compression and create utility methods
This commit splits compression and serialization into two distinct parts and adds some utility functions so the user can compress/uncompress or pack/unpack data explicily. See #1939
This commit is contained in:
137
library.c
137
library.c
@@ -2820,19 +2820,7 @@ static uint8_t crc8(unsigned char *input, size_t len) {
|
||||
#endif
|
||||
|
||||
PHP_REDIS_API int
|
||||
redis_pack(RedisSock *redis_sock, zval *z, char **val, size_t *val_len)
|
||||
{
|
||||
char *buf;
|
||||
int valfree;
|
||||
size_t len;
|
||||
|
||||
valfree = redis_serialize(redis_sock, z, &buf, &len);
|
||||
if (redis_sock->compression == REDIS_COMPRESSION_NONE) {
|
||||
*val = buf;
|
||||
*val_len = len;
|
||||
return valfree;
|
||||
}
|
||||
|
||||
redis_compress(RedisSock *redis_sock, char **dst, size_t *dstlen, char *buf, size_t len) {
|
||||
switch (redis_sock->compression) {
|
||||
case REDIS_COMPRESSION_LZF:
|
||||
#ifdef HAVE_REDIS_LZF
|
||||
@@ -2845,9 +2833,8 @@ redis_pack(RedisSock *redis_sock, zval *z, char **val, size_t *val_len)
|
||||
size = len + MIN(UINT_MAX - len, MAX(LZF_MARGIN, len / 25));
|
||||
data = emalloc(size);
|
||||
if ((res = lzf_compress(buf, len, data, size)) > 0) {
|
||||
if (valfree) efree(buf);
|
||||
*val = data;
|
||||
*val_len = res;
|
||||
*dst = data;
|
||||
*dstlen = res;
|
||||
return 1;
|
||||
}
|
||||
efree(data);
|
||||
@@ -2877,10 +2864,8 @@ redis_pack(RedisSock *redis_sock, zval *z, char **val, size_t *val_len)
|
||||
data = emalloc(size);
|
||||
size = ZSTD_compress(data, size, buf, len, level);
|
||||
if (!ZSTD_isError(size)) {
|
||||
if (valfree) efree(buf);
|
||||
data = erealloc(data, size);
|
||||
*val = data;
|
||||
*val_len = size;
|
||||
*dst = erealloc(data, size);
|
||||
*dstlen = size;
|
||||
return 1;
|
||||
}
|
||||
efree(data);
|
||||
@@ -2928,22 +2913,21 @@ redis_pack(RedisSock *redis_sock, zval *z, char **val, size_t *val_len)
|
||||
break;
|
||||
}
|
||||
|
||||
if (valfree) efree(buf);
|
||||
*val = lz4buf;
|
||||
*val_len = lz4len + REDIS_LZ4_HDR_SIZE;
|
||||
*dst = lz4buf;
|
||||
*dstlen = lz4len + REDIS_LZ4_HDR_SIZE;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
*val = buf;
|
||||
*val_len = len;
|
||||
return valfree;
|
||||
|
||||
*dst = buf;
|
||||
*dstlen = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
PHP_REDIS_API int
|
||||
redis_unpack(RedisSock *redis_sock, const char *val, int val_len, zval *z_ret)
|
||||
{
|
||||
redis_uncompress(RedisSock *redis_sock, char **dst, size_t *dstlen, const char *src, size_t len) {
|
||||
switch (redis_sock->compression) {
|
||||
case REDIS_COMPRESSION_LZF:
|
||||
#ifdef HAVE_REDIS_LZF
|
||||
@@ -2952,24 +2936,27 @@ redis_unpack(RedisSock *redis_sock, const char *val, int val_len, zval *z_ret)
|
||||
int i;
|
||||
uint32_t res;
|
||||
|
||||
if (val_len == 0)
|
||||
if (len == 0)
|
||||
break;
|
||||
|
||||
/* start from two-times bigger buffer and
|
||||
* increase it exponentially if needed */
|
||||
errno = E2BIG;
|
||||
for (i = 2; errno == E2BIG; i *= 2) {
|
||||
data = emalloc(i * val_len);
|
||||
if ((res = lzf_decompress(val, val_len, data, i * val_len)) == 0) {
|
||||
data = emalloc(i * len);
|
||||
if ((res = lzf_decompress(src, len, data, i * len)) == 0) {
|
||||
/* errno != E2BIG will brake for loop */
|
||||
efree(data);
|
||||
continue;
|
||||
} else if (redis_unserialize(redis_sock, data, res, z_ret) == 0) {
|
||||
ZVAL_STRINGL(z_ret, data, res);
|
||||
}
|
||||
efree(data);
|
||||
|
||||
*dst = data;
|
||||
*dstlen = res;
|
||||
return 1;
|
||||
}
|
||||
|
||||
efree(data);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
@@ -2977,25 +2964,21 @@ redis_unpack(RedisSock *redis_sock, const char *val, int val_len, zval *z_ret)
|
||||
#ifdef HAVE_REDIS_ZSTD
|
||||
{
|
||||
char *data;
|
||||
unsigned long long len;
|
||||
unsigned long long zlen;
|
||||
|
||||
len = ZSTD_getFrameContentSize(val, val_len);
|
||||
zlen = ZSTD_getFrameContentSize(src, len);
|
||||
if (zlen == ZSTD_CONTENTSIZE_ERROR || zlen == ZSTD_CONTENTSIZE_UNKNOWN || zlen > INT_MAX)
|
||||
break;
|
||||
|
||||
if (len != ZSTD_CONTENTSIZE_ERROR && len != ZSTD_CONTENTSIZE_UNKNOWN && len <= INT_MAX)
|
||||
{
|
||||
size_t zlen;
|
||||
|
||||
data = emalloc(len);
|
||||
zlen = ZSTD_decompress(data, len, val, val_len);
|
||||
if (ZSTD_isError(zlen) || zlen != len) {
|
||||
efree(data);
|
||||
break;
|
||||
} else if (redis_unserialize(redis_sock, data, zlen, z_ret) == 0) {
|
||||
ZVAL_STRINGL(z_ret, data, zlen);
|
||||
}
|
||||
data = emalloc(zlen);
|
||||
*dstlen = ZSTD_decompress(data, zlen, src, len);
|
||||
if (ZSTD_isError(*dstlen) || *dstlen != zlen) {
|
||||
efree(data);
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
|
||||
*dst = data;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
@@ -3008,12 +2991,12 @@ redis_unpack(RedisSock *redis_sock, const char *val, int val_len, zval *z_ret)
|
||||
|
||||
/* We must have at least enough bytes for our header, and can't have more than
|
||||
* INT_MAX + our header size. */
|
||||
if (val_len < REDIS_LZ4_HDR_SIZE || val_len > INT_MAX + REDIS_LZ4_HDR_SIZE)
|
||||
if (len < REDIS_LZ4_HDR_SIZE || len > INT_MAX + REDIS_LZ4_HDR_SIZE)
|
||||
break;
|
||||
|
||||
/* Operate on copies in case our CRC fails */
|
||||
const char *copy = val;
|
||||
size_t copylen = val_len;
|
||||
const char *copy = src;
|
||||
size_t copylen = len;
|
||||
|
||||
/* Read in our header bytes */
|
||||
memcpy(&lz4crc, copy, sizeof(uint8_t));
|
||||
@@ -3028,23 +3011,59 @@ redis_unpack(RedisSock *redis_sock, const char *val, int val_len, zval *z_ret)
|
||||
/* Finally attempt decompression */
|
||||
data = emalloc(datalen);
|
||||
if (LZ4_decompress_safe(copy, data, copylen, datalen) > 0) {
|
||||
if (redis_unserialize(redis_sock, data, datalen, z_ret) == 0) {
|
||||
ZVAL_STRINGL(z_ret, data, datalen);
|
||||
}
|
||||
efree(data);
|
||||
*dst = data;
|
||||
*dstlen = datalen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
efree(data);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
return redis_unserialize(redis_sock, val, val_len, z_ret);
|
||||
|
||||
*dst = (char*)src;
|
||||
*dstlen = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
PHP_REDIS_API int
|
||||
redis_serialize(RedisSock *redis_sock, zval *z, char **val, size_t *val_len
|
||||
)
|
||||
redis_pack(RedisSock *redis_sock, zval *z, char **val, size_t *val_len) {
|
||||
size_t tmplen;
|
||||
int tmpfree;
|
||||
char *tmp;
|
||||
|
||||
/* First serialize */
|
||||
tmpfree = redis_serialize(redis_sock, z, &tmp, &tmplen);
|
||||
|
||||
/* Now attempt compression */
|
||||
if (redis_compress(redis_sock, val, val_len, tmp, tmplen)) {
|
||||
if (tmpfree) efree(tmp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return tmpfree;
|
||||
}
|
||||
|
||||
PHP_REDIS_API int
|
||||
redis_unpack(RedisSock *redis_sock, const char *src, int srclen, zval *zdst) {
|
||||
size_t len;
|
||||
char *buf;
|
||||
|
||||
/* Uncompress, then unserialize */
|
||||
if (redis_uncompress(redis_sock, &buf, &len, src, srclen)) {
|
||||
if (!redis_unserialize(redis_sock, buf, len, zdst)) {
|
||||
ZVAL_STRINGL(zdst, buf, len);
|
||||
}
|
||||
efree(buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return redis_unserialize(redis_sock, buf, len, zdst);
|
||||
}
|
||||
|
||||
PHP_REDIS_API int
|
||||
redis_serialize(RedisSock *redis_sock, zval *z, char **val, size_t *val_len)
|
||||
{
|
||||
php_serialize_data_t ht;
|
||||
|
||||
|
||||
@@ -121,6 +121,11 @@ redis_key_prefix(RedisSock *redis_sock, char **key, size_t *key_len);
|
||||
PHP_REDIS_API int
|
||||
redis_unserialize(RedisSock *redis_sock, const char *val, int val_len, zval *z_ret);
|
||||
|
||||
PHP_REDIS_API int
|
||||
redis_compress(RedisSock *redis_sock, char **dst, size_t *dstlen, char *buf, size_t len);
|
||||
PHP_REDIS_API int
|
||||
redis_uncompress(RedisSock *redis_sock, char **dst, size_t *dstlen, const char *src, size_t len);
|
||||
|
||||
PHP_REDIS_API int redis_pack(RedisSock *redis_sock, zval *z, char **val, size_t *val_len);
|
||||
PHP_REDIS_API int redis_unpack(RedisSock *redis_sock, const char *val, int val_len, zval *z_ret);
|
||||
|
||||
|
||||
@@ -165,9 +165,15 @@ PHP_METHOD(Redis, role);
|
||||
PHP_METHOD(Redis, getLastError);
|
||||
PHP_METHOD(Redis, clearLastError);
|
||||
PHP_METHOD(Redis, _prefix);
|
||||
PHP_METHOD(Redis, _pack);
|
||||
PHP_METHOD(Redis, _unpack);
|
||||
|
||||
PHP_METHOD(Redis, _serialize);
|
||||
PHP_METHOD(Redis, _unserialize);
|
||||
|
||||
PHP_METHOD(Redis, _compress);
|
||||
PHP_METHOD(Redis, _uncompress);
|
||||
|
||||
PHP_METHOD(Redis, mset);
|
||||
PHP_METHOD(Redis, msetnx);
|
||||
PHP_METHOD(Redis, rpoplpush);
|
||||
|
||||
49
redis.c
49
redis.c
@@ -286,6 +286,10 @@ static zend_function_entry redis_functions[] = {
|
||||
PHP_ME(Redis, _prefix, arginfo_key, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Redis, _serialize, arginfo_value, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Redis, _unserialize, arginfo_value, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Redis, _pack, arginfo_value, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Redis, _unpack, arginfo_value, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Redis, _compress, arginfo_value, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Redis, _uncompress, arginfo_value, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Redis, acl, arginfo_acl, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Redis, append, arginfo_key_value, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Redis, auth, arginfo_auth, ZEND_ACC_PUBLIC)
|
||||
@@ -3294,6 +3298,51 @@ PHP_METHOD(Redis, _unserialize) {
|
||||
redis_exception_ce);
|
||||
}
|
||||
|
||||
PHP_METHOD(Redis, _compress) {
|
||||
RedisSock *redis_sock;
|
||||
|
||||
// Grab socket
|
||||
if ((redis_sock = redis_sock_get_instance(getThis(), 0)) == NULL) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
redis_compress_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock);
|
||||
}
|
||||
|
||||
PHP_METHOD(Redis, _uncompress) {
|
||||
RedisSock *redis_sock;
|
||||
|
||||
// Grab socket
|
||||
if ((redis_sock = redis_sock_get_instance(getThis(), 0)) == NULL) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
redis_uncompress_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock,
|
||||
redis_exception_ce);
|
||||
}
|
||||
|
||||
PHP_METHOD(Redis, _pack) {
|
||||
RedisSock *redis_sock;
|
||||
|
||||
// Grab socket
|
||||
if ((redis_sock = redis_sock_get_instance(getThis(), 0)) == NULL) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
redis_pack_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock);
|
||||
}
|
||||
|
||||
PHP_METHOD(Redis, _unpack) {
|
||||
RedisSock *redis_sock;
|
||||
|
||||
// Grab socket
|
||||
if ((redis_sock = redis_sock_get_instance(getThis(), 0)) == NULL) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
redis_unpack_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock);
|
||||
}
|
||||
|
||||
/* {{{ proto Redis::getLastError() */
|
||||
PHP_METHOD(Redis, getLastError) {
|
||||
zval *object;
|
||||
|
||||
@@ -110,6 +110,10 @@ zend_function_entry redis_cluster_functions[] = {
|
||||
PHP_ME(RedisCluster, _redir, arginfo_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(RedisCluster, _serialize, arginfo_value, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(RedisCluster, _unserialize, arginfo_value, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(RedisCluster, _compress, arginfo_value, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(RedisCluster, _uncompress, arginfo_value, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(RedisCluster, _pack, arginfo_value, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(RedisCluster, _unpack, arginfo_value, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(RedisCluster, acl, arginfo_acl_cl, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(RedisCluster, append, arginfo_key_value, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(RedisCluster, bgrewriteaof, arginfo_key_or_address, ZEND_ACC_PUBLIC)
|
||||
@@ -1970,6 +1974,27 @@ PHP_METHOD(RedisCluster, _unserialize) {
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
PHP_METHOD(RedisCluster, _compress) {
|
||||
redisCluster *c = GET_CONTEXT();
|
||||
redis_compress_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, c->flags);
|
||||
}
|
||||
|
||||
PHP_METHOD(RedisCluster, _uncompress) {
|
||||
redisCluster *c = GET_CONTEXT();
|
||||
redis_uncompress_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, c->flags,
|
||||
redis_cluster_exception_ce);
|
||||
}
|
||||
|
||||
PHP_METHOD(RedisCluster, _pack) {
|
||||
redisCluster *c = GET_CONTEXT();
|
||||
redis_pack_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, c->flags);
|
||||
}
|
||||
|
||||
PHP_METHOD(RedisCluster, _unpack) {
|
||||
redisCluster *c = GET_CONTEXT();
|
||||
redis_unpack_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, c->flags);
|
||||
}
|
||||
|
||||
/* {{{ proto array RedisCluster::_masters() */
|
||||
PHP_METHOD(RedisCluster, _masters) {
|
||||
redisCluster *c = GET_CONTEXT();
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
redis_##name##_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, c->flags, &cmd, \
|
||||
&cmd_len, &slot)
|
||||
|
||||
/* Append information required to handle MULTI commands to the tail of our MULTI
|
||||
/* Append information required to handle MULTI commands to the tail of our MULTI
|
||||
* linked list. */
|
||||
#define CLUSTER_ENQUEUE_RESPONSE(c, slot, cb, ctx) \
|
||||
clusterFoldItem *_item; \
|
||||
@@ -69,8 +69,8 @@
|
||||
CLUSTER_ENQUEUE_RESPONSE(c, slot, resp_func, ctx); \
|
||||
RETURN_ZVAL(getThis(), 1, 0); \
|
||||
} \
|
||||
resp_func(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, ctx);
|
||||
|
||||
resp_func(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, ctx);
|
||||
|
||||
/* More generic processing, where only the keyword differs */
|
||||
#define CLUSTER_PROCESS_KW_CMD(kw, cmdfunc, resp_func, readcmd) \
|
||||
redisCluster *c = GET_CONTEXT(); \
|
||||
@@ -89,7 +89,7 @@
|
||||
CLUSTER_ENQUEUE_RESPONSE(c, slot, resp_func, ctx); \
|
||||
RETURN_ZVAL(getThis(), 1, 0); \
|
||||
} \
|
||||
resp_func(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, ctx);
|
||||
resp_func(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, ctx);
|
||||
|
||||
/* Create cluster context */
|
||||
zend_object *create_cluster_context(zend_class_entry *class_type);
|
||||
@@ -293,6 +293,10 @@ PHP_METHOD(RedisCluster, setoption);
|
||||
PHP_METHOD(RedisCluster, _prefix);
|
||||
PHP_METHOD(RedisCluster, _serialize);
|
||||
PHP_METHOD(RedisCluster, _unserialize);
|
||||
PHP_METHOD(RedisCluster, _compress);
|
||||
PHP_METHOD(RedisCluster, _uncompress);
|
||||
PHP_METHOD(RedisCluster, _pack);
|
||||
PHP_METHOD(RedisCluster, _unpack);
|
||||
PHP_METHOD(RedisCluster, _masters);
|
||||
PHP_METHOD(RedisCluster, _redir);
|
||||
|
||||
|
||||
@@ -4510,4 +4510,67 @@ void redis_unserialize_handler(INTERNAL_FUNCTION_PARAMETERS,
|
||||
RETURN_ZVAL(&z_ret, 0, 0);
|
||||
}
|
||||
|
||||
void redis_compress_handler(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock) {
|
||||
zend_string *zstr;
|
||||
size_t len;
|
||||
char *buf;
|
||||
int cmp_free;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &zstr) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
cmp_free = redis_compress(redis_sock, &buf, &len, ZSTR_VAL(zstr), ZSTR_LEN(zstr));
|
||||
RETVAL_STRINGL(buf, len);
|
||||
if (cmp_free) efree(buf);
|
||||
}
|
||||
|
||||
void redis_uncompress_handler(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
zend_class_entry *ex)
|
||||
{
|
||||
zend_string *zstr;
|
||||
size_t len;
|
||||
char *buf;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &zstr) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
} else if (ZSTR_LEN(zstr) == 0 || redis_sock->compression == REDIS_COMPRESSION_NONE) {
|
||||
RETURN_STR_COPY(zstr);
|
||||
}
|
||||
|
||||
if (!redis_uncompress(redis_sock, &buf, &len, ZSTR_VAL(zstr), ZSTR_LEN(zstr))) {
|
||||
zend_throw_exception(ex, "Invalid compressed data or uncompression error", 0);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
RETVAL_STRINGL(buf, len);
|
||||
efree(buf);
|
||||
}
|
||||
|
||||
void redis_pack_handler(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock) {
|
||||
int valfree;
|
||||
size_t len;
|
||||
char *val;
|
||||
zval *zv;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zv) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
valfree = redis_pack(redis_sock, zv, &val, &len);
|
||||
RETVAL_STRINGL(val, len);
|
||||
if (valfree) efree(val);
|
||||
}
|
||||
|
||||
void redis_unpack_handler(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock) {
|
||||
zend_string *str;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (redis_unpack(redis_sock, ZSTR_VAL(str), ZSTR_LEN(str), return_value) == 0) {
|
||||
RETURN_STR_COPY(str);
|
||||
}
|
||||
}
|
||||
/* vim: set tabstop=4 softtabstop=4 expandtab shiftwidth=4: */
|
||||
|
||||
@@ -52,7 +52,7 @@ int redis_kv_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_key_str_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_key_key_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
@@ -96,11 +96,11 @@ typedef int (*zrange_cb)(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *,char**,int*,int*,short*,void**);
|
||||
|
||||
int redis_zrange_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, int *withscores, short *slot,
|
||||
char *kw, char **cmd, int *cmd_len, int *withscores, short *slot,
|
||||
void **ctx);
|
||||
|
||||
int redis_zrangebyscore_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, int *withscores, short *slot,
|
||||
char *kw, char **cmd, int *cmd_len, int *withscores, short *slot,
|
||||
void **ctx);
|
||||
|
||||
int redis_zdiff_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
@@ -143,7 +143,7 @@ int redis_georadiusbymember_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_s
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
/* Commands which need a unique construction mechanism. This is either because
|
||||
* they don't share a signature with any other command, or because there is
|
||||
* they don't share a signature with any other command, or because there is
|
||||
* specific processing we do (e.g. verifying subarguments) that make them
|
||||
* unique */
|
||||
|
||||
@@ -174,7 +174,7 @@ int redis_hmset_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
int redis_hstrlen_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_bitop_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
int redis_bitop_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_bitcount_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
@@ -313,21 +313,28 @@ int redis_sentinel_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
int redis_sentinel_str_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
/* Commands that don't communicate with Redis at all (such as getOption,
|
||||
/* Commands that don't communicate with Redis at all (such as getOption,
|
||||
* setOption, _prefix, _serialize, etc). These can be handled in one place
|
||||
* with the method of grabbing our RedisSock* object in different ways
|
||||
* with the method of grabbing our RedisSock* object in different ways
|
||||
* depending if this is a Redis object or a RedisCluster object. */
|
||||
|
||||
void redis_getoption_handler(INTERNAL_FUNCTION_PARAMETERS,
|
||||
void redis_getoption_handler(INTERNAL_FUNCTION_PARAMETERS,
|
||||
RedisSock *redis_sock, redisCluster *c);
|
||||
void redis_setoption_handler(INTERNAL_FUNCTION_PARAMETERS,
|
||||
void redis_setoption_handler(INTERNAL_FUNCTION_PARAMETERS,
|
||||
RedisSock *redis_sock, redisCluster *c);
|
||||
void redis_prefix_handler(INTERNAL_FUNCTION_PARAMETERS,
|
||||
void redis_prefix_handler(INTERNAL_FUNCTION_PARAMETERS,
|
||||
RedisSock *redis_sock);
|
||||
void redis_serialize_handler(INTERNAL_FUNCTION_PARAMETERS,
|
||||
void redis_serialize_handler(INTERNAL_FUNCTION_PARAMETERS,
|
||||
RedisSock *redis_sock);
|
||||
void redis_unserialize_handler(INTERNAL_FUNCTION_PARAMETERS,
|
||||
void redis_unserialize_handler(INTERNAL_FUNCTION_PARAMETERS,
|
||||
RedisSock *redis_sock, zend_class_entry *ex);
|
||||
void redis_compress_handler(INTERNAL_FUNCTION_PARAMETERS,
|
||||
RedisSock *redis_sock);
|
||||
void redis_uncompress_handler(INTERNAL_FUNCTION_PARAMETERS,
|
||||
RedisSock *redis_sock, zend_class_entry *ex);
|
||||
|
||||
void redis_pack_handler(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
void redis_unpack_handler(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -5089,6 +5089,71 @@ class Redis_Test extends TestSuite
|
||||
}
|
||||
}
|
||||
|
||||
public function testCompressHelpers() {
|
||||
$compressors = self::getAvailableCompression();
|
||||
|
||||
$vals = ['foo', 12345, random_bytes(128), ''];
|
||||
|
||||
$oldcmp = $this->redis->getOption(Redis::OPT_COMPRESSION);
|
||||
|
||||
foreach ($compressors as $cmp) {
|
||||
foreach ($vals as $val) {
|
||||
$this->redis->setOption(Redis::OPT_COMPRESSION, $cmp);
|
||||
$this->redis->set('cmpkey', $val);
|
||||
|
||||
/* Get the value raw */
|
||||
$this->redis->setOption(Redis::OPT_COMPRESSION, Redis::COMPRESSION_NONE);
|
||||
$raw = $this->redis->get('cmpkey');
|
||||
$this->redis->setOption(Redis::OPT_COMPRESSION, $cmp);
|
||||
|
||||
$this->assertEquals($raw, $this->redis->_compress($val));
|
||||
|
||||
$uncompressed = $this->redis->get('cmpkey');
|
||||
$this->assertEquals($uncompressed, $this->redis->_uncompress($raw));
|
||||
}
|
||||
}
|
||||
|
||||
$this->redis->setOption(Redis::OPT_COMPRESSION, $oldcmp);
|
||||
}
|
||||
|
||||
public function testPackHelpers() {
|
||||
list ($oldser, $oldcmp) = [
|
||||
$this->redis->getOption(Redis::OPT_SERIALIZER),
|
||||
$this->redis->getOption(Redis::OPT_COMPRESSION)
|
||||
];
|
||||
|
||||
foreach ($this->serializers as $ser) {
|
||||
$compressors = self::getAvailableCompression();
|
||||
foreach ($compressors as $cmp) {
|
||||
$this->redis->setOption(Redis::OPT_SERIALIZER, $ser);
|
||||
$this->redis->setOption(Redis::OPT_COMPRESSION, $cmp);
|
||||
|
||||
foreach (['foo', 12345, random_bytes(128), '', ['an', 'array']] as $v) {
|
||||
/* Can only attempt the array if we're serializing */
|
||||
if (is_array($v) && $ser == Redis::SERIALIZER_NONE)
|
||||
continue;
|
||||
|
||||
$this->redis->set('packkey', $v);
|
||||
|
||||
/* Get the value raw */
|
||||
$this->redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_NONE);
|
||||
$this->redis->setOption(Redis::OPT_COMPRESSION, Redis::COMPRESSION_NONE);
|
||||
$raw = $this->redis->get('packkey');
|
||||
$this->redis->setOption(Redis::OPT_SERIALIZER, $ser);
|
||||
$this->redis->setOption(Redis::OPT_COMPRESSION, $cmp);
|
||||
|
||||
$this->assertEquals($raw, $this->redis->_pack($v));
|
||||
|
||||
$unpacked = $this->redis->get('packkey');
|
||||
$this->assertEquals($unpacked, $this->redis->_unpack($raw));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->redis->setOption(Redis::OPT_SERIALIZER, $oldser);
|
||||
$this->redis->setOption(Redis::OPT_COMPRESSION, $oldcmp);
|
||||
}
|
||||
|
||||
public function testPrefix() {
|
||||
// no prefix
|
||||
$this->redis->setOption(Redis::OPT_PREFIX, '');
|
||||
|
||||
@@ -39,6 +39,18 @@ class TestSuite
|
||||
public function getPort() { return $this->i_port; }
|
||||
public function getAuth() { return $this->auth; }
|
||||
|
||||
public static function getAvailableCompression() {
|
||||
$result[] = Redis::COMPRESSION_NONE;
|
||||
if (defined('Redis::COMPRESSION_LZF'))
|
||||
$result[] = Redis::COMPRESSION_LZF;
|
||||
if (defined('Redis::COMPRESSION_LZ4'))
|
||||
$result[] = Redis::COMPRESSION_LZ4;
|
||||
if (defined('Redis::COMPRESSION_ZSTD'))
|
||||
$result[] = Redis::COMPRESSION_ZSTD;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fully qualified host path,
|
||||
* which may be used directly for php.ini parameters like session.save_path
|
||||
|
||||
Reference in New Issue
Block a user