rebase msgpack pull request (#801) on develop branch

This commit is contained in:
B. Gortney
2016-12-14 11:32:00 -05:00
committed by Pavlo Yatsukhnenko
parent 6a1685d33b
commit d5b8f83340
6 changed files with 170 additions and 5 deletions
+1
View File
@@ -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
Executable → Regular
+50 -4
View File
@@ -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
+91
View File
@@ -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;
}
+4
View File
@@ -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);
}
+3
View File
@@ -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
View File
@@ -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 = [];