diff --git a/config.m4 b/config.m4 index 045758aa..a6ec61a0 100644 --- a/config.m4 +++ b/config.m4 @@ -17,6 +17,9 @@ PHP_ARG_ENABLE(memcached-igbinary, whether to enable memcached igbinary serializ PHP_ARG_ENABLE(memcached-json, whether to enable memcached json serializer support, [ --enable-memcached-json Enable memcached json serializer support], no, no) +PHP_ARG_ENABLE(memcached-msgpack, whether to enable memcached msgpack serializer support, +[ --enable-memcached-msgpack Enable memcached msgpack serializer support], no, no) + PHP_ARG_ENABLE(memcached-sasl, whether to disable memcached sasl support, [ --disable-memcached-sasl Disable memcached sasl support], no, no) @@ -188,6 +191,33 @@ if test "$PHP_MEMCACHED" != "no"; then fi fi + if test "$PHP_MEMCACHED_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/session/php_msgpack.h"; then + msgpack_inc_path="$phpincludedir" + elif test -f "$phpincludedir/ext/msgpack/php_msgpack.h"; then + msgpack_inc_path="$phpincludedir" + else + for i in php php4 php5 php6; 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 memcached session support]) if test "$PHP_MEMCACHED_SESSION" != "no"; then AC_MSG_RESULT([enabled]) @@ -216,6 +246,21 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_RESULT([disabled]) fi + AC_MSG_CHECKING([for memcached msgpack support]) + if test "$PHP_MEMCACHED_MSGPACK" != "no"; then + AC_MSG_RESULT([enabled]) + AC_DEFINE(HAVE_MEMCACHED_MSGPACK,1,[Whether memcache msgpack serializer is enabled]) + MSGPACK_INCLUDES="-I$msgpack_inc_path" + ifdef([PHP_ADD_EXTENSION_DEP], + [ + PHP_ADD_EXTENSION_DEP(memcached, msgpack) + ]) + else + MSGPACK_INCLUDES="" + AC_MSG_RESULT([disabled]) + fi + + if test "$PHP_MEMCACHED_SASL" != "no"; then AC_CHECK_HEADERS([sasl/sasl.h], [memcached_enable_sasl="yes"], [memcached_enable_sasl="no"]) AC_MSG_CHECKING([whether to enable sasl support]) @@ -254,7 +299,7 @@ if test "$PHP_MEMCACHED" != "no"; then PHP_MEMCACHED_FILES="${PHP_MEMCACHED_FILES} php_memcached_session.c" fi - PHP_NEW_EXTENSION(memcached, $PHP_MEMCACHED_FILES, $ext_shared,,$SESSION_INCLUDES $IGBINARY_INCLUDES) + PHP_NEW_EXTENSION(memcached, $PHP_MEMCACHED_FILES, $ext_shared,,$SESSION_INCLUDES $IGBINARY_INCLUDES $MSGPACK_INCLUDES) PHP_ADD_BUILD_DIR($ext_builddir/fastlz, 1) ifdef([PHP_ADD_EXTENSION_DEP], diff --git a/memcached.ini b/memcached.ini index f4bd68c0..17143e14 100644 --- a/memcached.ini +++ b/memcached.ini @@ -69,7 +69,7 @@ memcached.compression_factor = "1.3" memcached.compression_threshold = 2000 ; Set the default serializer for new memcached objects. -; valid values are: php, igbinary, json, json_array +; valid values are: php, igbinary, json, json_array, msgpack ; ; json - standard php JSON encoding. This serializer ; is fast and compact but only works on UTF-8 @@ -78,6 +78,7 @@ memcached.compression_threshold = 2000 ; json_array - as json, but decodes into arrays ; php - the standard php serializer ; igbinary - a binary serializer +; msgpack - a cross-language binary serializer ; -; The default is igbinary if available and php otherwise. +; The default is igbinary if available, then msgpack if available, then php otherwise. memcached.serializer = "igbinary" diff --git a/php_memcached.c b/php_memcached.c index d1d07246..9dccb05a 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -89,6 +89,10 @@ typedef unsigned long int uint32_t; # include "ext/igbinary/igbinary.h" #endif +#ifdef HAVE_MEMCACHED_MSGPACK +# include "ext/msgpack/php_msgpack.h" +#endif + /* * This is needed because PHP 5.3.[01] does not install JSON_parser.h by default. This * constant will move into php_json.h in the future anyway. @@ -124,6 +128,7 @@ typedef unsigned long int uint32_t; #define MEMC_VAL_IS_SERIALIZED 4 #define MEMC_VAL_IS_IGBINARY 5 #define MEMC_VAL_IS_JSON 6 +#define MEMC_VAL_IS_MSGPACK 7 #define MEMC_VAL_COMPRESSED (1<<4) #define MEMC_VAL_COMPRESSION_ZLIB (1<<5) @@ -264,7 +269,7 @@ static PHP_INI_MH(OnUpdateSerializer) MEMC_G(serializer) = SERIALIZER_DEFAULT; } else if (!strcmp(new_value, "php")) { MEMC_G(serializer) = SERIALIZER_PHP; -#ifdef HAVE_MEMCACHE_IGBINARY +#ifdef HAVE_MEMCACHED_IGBINARY } else if (!strcmp(new_value, "igbinary")) { MEMC_G(serializer) = SERIALIZER_IGBINARY; #endif // IGBINARY @@ -274,6 +279,10 @@ static PHP_INI_MH(OnUpdateSerializer) } else if (!strcmp(new_value, "json_array")) { MEMC_G(serializer) = SERIALIZER_JSON_ARRAY; #endif // JSON +#ifdef HAVE_MEMCACHED_MSGPACK + } else if (!strcmp(new_value, "msgpack")) { + MEMC_G(serializer) = SERIALIZER_MSGPACK; +#endif // msgpack } else { return FAILURE; } @@ -2305,6 +2314,12 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML } else if (Z_LVAL_P(value) == SERIALIZER_JSON_ARRAY) { m_obj->serializer = SERIALIZER_JSON_ARRAY; } else +#endif + /* msgpack serializer */ +#ifdef HAVE_MEMCACHED_MSGPACK + if (Z_LVAL_P(value) == SERIALIZER_MSGPACK) { + m_obj->serializer = SERIALIZER_MSGPACK; + } else #endif /* php serializer */ if (Z_LVAL_P(value) == SERIALIZER_PHP) { @@ -2787,6 +2802,20 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_JSON); break; } +#endif +#ifdef HAVE_MEMCACHED_MSGPACK + case SERIALIZER_MSGPACK: + php_msgpack_serialize(&buf, value TSRMLS_CC); + if(!buf.c) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not serialize value with msgpack"); + smart_str_free(&buf); + return NULL; + } + p = buf.c; + l = buf.len; + buf_used = 1; + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_MSGPACK); + break; #endif default: { @@ -3019,6 +3048,15 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload #endif break; + case MEMC_VAL_IS_MSGPACK: +#ifdef HAVE_MEMCACHED_MSGPACK + php_msgpack_unserialize(value, payload, payload_len TSRMLS_CC); +#else + php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value, no msgpack support"); + goto my_error; +#endif + break; + default: php_error_docref(NULL TSRMLS_CC, E_WARNING, "unknown payload type"); goto my_error; @@ -3603,6 +3641,9 @@ static const zend_module_dep memcached_deps[] = { #ifdef HAVE_MEMCACHED_IGBINARY ZEND_MOD_REQUIRED("igbinary") #endif +#ifdef HAVE_MEMCACHED_MSGPACK + ZEND_MOD_REQUIRED("msgpack") +#endif #ifdef HAVE_SPL ZEND_MOD_REQUIRED("spl") #endif @@ -3668,6 +3709,15 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(HAVE_JSON, 0); #endif + /* + * Indicate whether msgpack serializer is available + */ +#ifdef HAVE_MEMCACHED_MSGPACK + REGISTER_MEMC_CLASS_CONST_LONG(HAVE_MSGPACK, 1); +#else + REGISTER_MEMC_CLASS_CONST_LONG(HAVE_MSGPACK, 0); +#endif + #ifdef HAVE_MEMCACHED_SESSION REGISTER_MEMC_CLASS_CONST_LONG(HAVE_SESSION, 1); #else @@ -3782,6 +3832,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_IGBINARY, SERIALIZER_IGBINARY); REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_JSON, SERIALIZER_JSON); REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_JSON_ARRAY, SERIALIZER_JSON_ARRAY); + REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_MSGPACK, SERIALIZER_MSGPACK); /* * Compression types @@ -3907,6 +3958,13 @@ PHP_MINFO_FUNCTION(memcached) #else php_info_print_table_row(2, "json support", "no"); #endif + +#ifdef HAVE_MEMCACHED_MSGPACK + php_info_print_table_row(2, "msgpack support", "yes"); +#else + php_info_print_table_row(2, "msgpack support", "no"); +#endif + php_info_print_table_end(); DISPLAY_INI_ENTRIES(); diff --git a/php_memcached.h b/php_memcached.h index 2bd5c83e..43f8a501 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -42,14 +42,18 @@ enum memcached_serializer { SERIALIZER_IGBINARY = 2, SERIALIZER_JSON = 3, SERIALIZER_JSON_ARRAY = 4, + SERIALIZER_MSGPACK = 5, }; #ifdef HAVE_MEMCACHED_IGBINARY #define SERIALIZER_DEFAULT SERIALIZER_IGBINARY #define SERIALIZER_DEFAULT_NAME "igbinary" +#elif HAVE_MEMCACHED_MSGPACK +#define SERIALIZER_DEFAULT SERIALIZER_MSGPACK +#define SERIALIZER_DEFAULT_NAME "msgpack" #else #define SERIALIZER_DEFAULT SERIALIZER_PHP #define SERIALIZER_DEFAULT_NAME "php" -#endif /* HAVE_MEMCACHED_IGBINARY */ +#endif /* HAVE_MEMCACHED_IGBINARY / HAVE_MEMCACHED_MSGPACK */ #if LIBMEMCACHED_WITH_SASL_SUPPORT # if defined(HAVE_SASL_SASL_H) diff --git a/tests/experimental/serializer_msgpack.phpt b/tests/experimental/serializer_msgpack.phpt new file mode 100644 index 00000000..aa68d0ca --- /dev/null +++ b/tests/experimental/serializer_msgpack.phpt @@ -0,0 +1,16 @@ +--TEST-- +Serialize msgpack +--SKIPIF-- + +--REDIRECTTEST-- + +$path = implode(DIRECTORY_SEPARATOR, array('tests', 'experimental', 'serializer')); + +return array( + 'TESTS' => $path, + 'ENV' => array('TEST_MEMC_SERIALIZER' => 'Memcached::SERIALIZER_MSGPACK'), +);