mirror of
https://github.com/phpredis/phpredis.git
synced 2026-06-19 07:35:31 +00:00
rebase msgpack pull request (#801) on develop branch
This commit is contained in:
committed by
Pavlo Yatsukhnenko
parent
6a1685d33b
commit
d5b8f83340
@@ -85,6 +85,7 @@ typedef enum _PUBSUB_TYPE {
|
||||
#define REDIS_SERIALIZER_NONE 0
|
||||
#define REDIS_SERIALIZER_PHP 1
|
||||
#define REDIS_SERIALIZER_IGBINARY 2
|
||||
#define REDIS_SERIALIZER_MSGPACK 3
|
||||
/* compression */
|
||||
#define REDIS_COMPRESSION_NONE 0
|
||||
#define REDIS_COMPRESSION_LZF 1
|
||||
|
||||
@@ -3,10 +3,10 @@ dnl config.m4 for extension redis
|
||||
|
||||
PHP_ARG_ENABLE(redis, whether to enable redis support,
|
||||
dnl Make sure that the comment is aligned:
|
||||
[ --enable-redis Enable redis support])
|
||||
[ --enable-redis Enable redis support])
|
||||
|
||||
PHP_ARG_ENABLE(redis-session, whether to enable sessions,
|
||||
[ --disable-redis-session Disable session support], yes, no)
|
||||
PHP_ARG_ENABLE(redis-session, whether to disable sessions,
|
||||
[ --disable-redis-session Disable session support], yes, no)
|
||||
|
||||
PHP_ARG_ENABLE(redis-igbinary, whether to enable igbinary serializer support,
|
||||
[ --enable-redis-igbinary Enable igbinary serializer support], no, no)
|
||||
@@ -16,6 +16,10 @@ PHP_ARG_ENABLE(redis-lzf, whether to enable lzf compression,
|
||||
|
||||
PHP_ARG_WITH(liblzf, use system liblzf,
|
||||
[ --with-liblzf[=DIR] Use system liblzf], no, no)
|
||||
[ --enable-redis-igbinary Enable igbinary serializer support], no, no)
|
||||
|
||||
PHP_ARG_ENABLE(redis-msgpack, whether to enable msgpack serializer support,
|
||||
[ --enable-redis-msgpack Enable msgpack serializer support], no, no)
|
||||
|
||||
if test "$PHP_REDIS" != "no"; then
|
||||
|
||||
@@ -35,7 +39,7 @@ dnl Check for igbinary
|
||||
elif test -f "$phpincludedir/ext/igbinary/igbinary.h"; then
|
||||
igbinary_inc_path="$phpincludedir"
|
||||
else
|
||||
for i in php php4 php5 php6; do
|
||||
for i in php php4 php5 php6 php7; do
|
||||
if test -f "$prefix/include/$i/ext/igbinary/igbinary.h"; then
|
||||
igbinary_inc_path="$prefix/include/$i"
|
||||
fi
|
||||
@@ -102,6 +106,48 @@ dnl Check for igbinary
|
||||
AC_DEFINE_UNQUOTED(GIT_REVISION, ["$(git log -1 --format=%H)"], [ ])
|
||||
fi
|
||||
|
||||
dnl Check for msgpack
|
||||
if test "$PHP_REDIS_MSGPACK" != "no"; then
|
||||
AC_MSG_CHECKING([for msgpack includes])
|
||||
msgpack_inc_path=""
|
||||
|
||||
if test -f "$abs_srcdir/include/php/ext/msgpack/php_msgpack.h"; then
|
||||
msgpack_inc_path="$abs_srcdir/include/php"
|
||||
elif test -f "$abs_srcdir/ext/msgpack/php_msgpack.h"; then
|
||||
msgpack_inc_path="$abs_srcdir"
|
||||
elif test -f "$phpincludedir/ext/msgpack/php_msgpack.h"; then
|
||||
msgpack_inc_path="$phpincludedir"
|
||||
else
|
||||
for i in php php4 php5 php6 php7; do
|
||||
if test -f "$prefix/include/$i/ext/msgpack/php_msgpack.h"; then
|
||||
msgpack_inc_path="$prefix/include/$i"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if test "$msgpack_inc_path" = ""; then
|
||||
AC_MSG_ERROR([Cannot find php_msgpack.h])
|
||||
else
|
||||
AC_MSG_RESULT([$msgpack_inc_path])
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for redis msgpack support])
|
||||
if test "$PHP_REDIS_MSGPACK" != "no"; then
|
||||
AC_MSG_RESULT([enabled])
|
||||
AC_DEFINE(HAVE_REDIS_MSGPACK,1,[Whether redis msgpack serializer is enabled])
|
||||
MSGPACK_INCLUDES="-I$msgpack_inc_path"
|
||||
MSGPACK_EXT_DIR="$msgpack_inc_path/ext"
|
||||
ifdef([PHP_ADD_EXTENSION_DEP],
|
||||
[
|
||||
PHP_ADD_EXTENSION_DEP(redis, msgpack)
|
||||
])
|
||||
PHP_ADD_INCLUDE($MSGPACK_EXT_DIR)
|
||||
else
|
||||
MSGPACK_INCLUDES=""
|
||||
AC_MSG_RESULT([disabled])
|
||||
fi
|
||||
|
||||
dnl # --with-redis -> check with-path
|
||||
dnl SEARCH_PATH="/usr/local /usr" # you might want to change this
|
||||
dnl SEARCH_FOR="/include/redis.h" # you most likely want to change this
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
#ifdef HAVE_REDIS_IGBINARY
|
||||
#include "igbinary/igbinary.h"
|
||||
#endif
|
||||
#ifdef HAVE_REDIS_MSGPACK
|
||||
#include "msgpack/php_msgpack.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_REDIS_LZF
|
||||
#include <lzf.h>
|
||||
@@ -1894,6 +1897,7 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAMETERS,
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
numElems = atoi(inbuf+1);
|
||||
zval z_multi_result;
|
||||
array_init(&z_multi_result); /* pre-allocate array for multi's results. */
|
||||
@@ -1910,6 +1914,67 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAMETERS,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* redis_sock_read_multibulk_reply_vals
|
||||
*
|
||||
* This is identical to redis_sock_read_multibulk_reply except that it unserializes vals only, rather than rely on
|
||||
* the chosen unserializer to silently return 0 after a failed attempt (which msgpack does not do).
|
||||
*
|
||||
* Perhaps not the optimal solution, but the easiest way to resolve the problem of failed attempts to
|
||||
* unserialize a key that hadn't been serialized to begin with in blpop, brpop.
|
||||
*
|
||||
*/
|
||||
PHP_REDIS_API int redis_sock_read_multibulk_reply_vals(INTERNAL_FUNCTION_PARAMETERS,
|
||||
RedisSock *redis_sock, zval *z_tab,
|
||||
void *ctx)
|
||||
{
|
||||
char inbuf[1024];
|
||||
int numElems, err_len;
|
||||
|
||||
if(-1 == redis_check_eof(redis_sock, 0 TSRMLS_CC)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(php_stream_gets(redis_sock->stream, inbuf, 1024) == NULL) {
|
||||
REDIS_STREAM_CLOSE_MARK_FAILED(redis_sock);
|
||||
zend_throw_exception(redis_exception_ce, "read error on connection", 0
|
||||
TSRMLS_CC);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(inbuf[0] != '*') {
|
||||
IF_MULTI_OR_PIPELINE() {
|
||||
add_next_index_bool(z_tab, 0);
|
||||
} else {
|
||||
if (inbuf[0] == '-') {
|
||||
err_len = strlen(inbuf+1) - 2;
|
||||
redis_sock_set_err(redis_sock, inbuf+1, err_len);
|
||||
}
|
||||
RETVAL_FALSE;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
numElems = atoi(inbuf+1);
|
||||
zval zv, *z_multi_result = &zv;
|
||||
#if (PHP_MAJOR_VERSION < 7)
|
||||
MAKE_STD_ZVAL(z_multi_result);
|
||||
#endif
|
||||
array_init(z_multi_result); /* pre-allocate array for multi's results. */
|
||||
|
||||
redis_mbulk_reply_loop(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock,
|
||||
z_multi_result, numElems, UNSERIALIZE_VALS);
|
||||
|
||||
IF_MULTI_OR_PIPELINE() {
|
||||
add_next_index_zval(z_tab, z_multi_result);
|
||||
} else {
|
||||
RETVAL_ZVAL(z_multi_result, 0, 1);
|
||||
}
|
||||
/*zval_copy_ctor(return_value); */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Like multibulk reply, but don't touch the values, they won't be unserialized
|
||||
* (this is used by HKEYS). */
|
||||
PHP_REDIS_API int
|
||||
@@ -2195,6 +2260,17 @@ redis_serialize(RedisSock *redis_sock, zval *z, char **val, size_t *val_len
|
||||
PHP_VAR_SERIALIZE_DESTROY(ht);
|
||||
|
||||
return 1;
|
||||
|
||||
case REDIS_SERIALIZER_MSGPACK:
|
||||
#ifdef HAVE_REDIS_MSGPACK
|
||||
php_msgpack_serialize(&sstr, z TSRMLS_CC);
|
||||
*val = estrndup(sstr.s->val, sstr.s->len);
|
||||
*val_len = sstr.s->len;
|
||||
smart_str_free(&sstr);
|
||||
|
||||
return 1;
|
||||
#endif
|
||||
break;
|
||||
case REDIS_SERIALIZER_IGBINARY:
|
||||
#ifdef HAVE_REDIS_IGBINARY
|
||||
if(igbinary_serialize(&val8, (size_t *)&sz, z TSRMLS_CC) == 0) {
|
||||
@@ -2205,6 +2281,7 @@ redis_serialize(RedisSock *redis_sock, zval *z, char **val, size_t *val_len
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2227,6 +2304,19 @@ redis_unserialize(RedisSock* redis_sock, const char *val, int val_len,
|
||||
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
|
||||
break;
|
||||
|
||||
case REDIS_SERIALIZER_MSGPACK:
|
||||
#ifdef HAVE_REDIS_MSGPACK
|
||||
/*
|
||||
* Would like to be able to check to see if a string is msgpack'd (like with igbinary, below),
|
||||
* but I don't believe there's an easy way to do that as there's no consistent header or
|
||||
* other simple indication of packed-ness in msgpacked binary sequences, as far as I know.
|
||||
*/
|
||||
|
||||
php_msgpack_unserialize(z_ret, (char *)val, (size_t)val_len TSRMLS_CC);
|
||||
ret = 1;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case REDIS_SERIALIZER_IGBINARY:
|
||||
#ifdef HAVE_REDIS_IGBINARY
|
||||
/*
|
||||
@@ -2257,6 +2347,7 @@ redis_unserialize(RedisSock* redis_sock, const char *val, int val_len,
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -693,6 +693,10 @@ static void add_class_constants(zend_class_entry *ce, int is_cluster TSRMLS_DC)
|
||||
zend_declare_class_constant_long(ce, ZEND_STRL("FAILOVER_DISTRIBUTE_SLAVES"), REDIS_FAILOVER_DISTRIBUTE_SLAVES TSRMLS_CC);
|
||||
}
|
||||
|
||||
#ifdef HAVE_REDIS_MSGPACK
|
||||
zend_declare_class_constant_long(ce, ZEND_STRL("SERIALIZER_MSGPACK"), REDIS_SERIALIZER_MSGPACK TSRMLS_CC);
|
||||
#endif
|
||||
|
||||
zend_declare_class_constant_stringl(ce, "AFTER", 5, "after", 5 TSRMLS_CC);
|
||||
zend_declare_class_constant_stringl(ce, "BEFORE", 6, "before", 6 TSRMLS_CC);
|
||||
}
|
||||
|
||||
@@ -3886,6 +3886,9 @@ void redis_setoption_handler(INTERNAL_FUNCTION_PARAMETERS,
|
||||
if (val_long == REDIS_SERIALIZER_NONE || val_long == REDIS_SERIALIZER_PHP
|
||||
#ifdef HAVE_REDIS_IGBINARY
|
||||
|| val_long == REDIS_SERIALIZER_IGBINARY
|
||||
#endif
|
||||
#ifdef HAVE_REDIS_MSGPACK
|
||||
|| val_long == REDIS_SERIALIZER_MSGPACK
|
||||
#endif
|
||||
) {
|
||||
redis_sock->serializer = val_long;
|
||||
|
||||
+21
-1
@@ -4223,6 +4223,17 @@ class Redis_Test extends TestSuite
|
||||
}
|
||||
}
|
||||
|
||||
public function testSerializerMsgPack() {
|
||||
if(defined('Redis::SERIALIZER_MSGPACK')) {
|
||||
$this->checkSerializer(Redis::SERIALIZER_MSGPACK);
|
||||
|
||||
// with prefix
|
||||
$this->redis->setOption(Redis::OPT_PREFIX, "test:");
|
||||
$this->checkSerializer(Redis::SERIALIZER_MSGPACK);
|
||||
$this->redis->setOption(Redis::OPT_PREFIX, "");
|
||||
}
|
||||
}
|
||||
|
||||
private function checkSerializer($mode) {
|
||||
|
||||
$this->redis->del('key');
|
||||
@@ -4716,6 +4727,10 @@ class Redis_Test extends TestSuite
|
||||
$arr_serializers[] = Redis::SERIALIZER_IGBINARY;
|
||||
}
|
||||
|
||||
if(defined('Redis::SERIALIZER_MSGPACK')) {
|
||||
$arr_serializers[] = Redis::SERIALIZER_MSGPACK;
|
||||
}
|
||||
|
||||
foreach($arr_serializers as $mode) {
|
||||
$arr_enc = [];
|
||||
$arr_dec = [];
|
||||
@@ -4735,11 +4750,16 @@ class Redis_Test extends TestSuite
|
||||
1,1.5,'one',['this','is','an','array']
|
||||
];
|
||||
|
||||
$serializers = [Redis::SERIALIZER_PHP];
|
||||
$serializers = Array(Redis::SERIALIZER_PHP);
|
||||
|
||||
if(defined('Redis::SERIALIZER_IGBINARY')) {
|
||||
$serializers[] = Redis::SERIALIZER_IGBINARY;
|
||||
}
|
||||
|
||||
if(defined('Redis::SERIALIZER_MSGPACK')) {
|
||||
$serializers[] = Redis::SERIALIZER_MSGPACK;
|
||||
}
|
||||
|
||||
foreach($serializers as $mode) {
|
||||
$vals_enc = [];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user