Skip to content

Added msgpack serializer support #55

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 46 additions & 1 deletion config.m4
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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])
Expand Down Expand Up @@ -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])
Expand Down Expand Up @@ -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],
Expand Down
5 changes: 3 additions & 2 deletions memcached.ini
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably need to double-check all the use cases for serialization, make sure msgpack handles them well. I seem to recall some bumps using JSON encoding certain types of objects (maybe just ones with binary contents?)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you write some tests for the use-cases?

memcached.serializer = "igbinary"
60 changes: 59 additions & 1 deletion php_memcached.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's where the existing typo disabled igbinary even if you had it configured, I believe.

} else if (!strcmp(new_value, "igbinary")) {
MEMC_G(serializer) = SERIALIZER_IGBINARY;
#endif // IGBINARY
Expand All @@ -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;
}
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spaces for indentation?

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:
{
Expand Down Expand Up @@ -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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation?

#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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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();
Expand Down
6 changes: 5 additions & 1 deletion php_memcached.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
16 changes: 16 additions & 0 deletions tests/experimental/serializer_msgpack.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
--TEST--
Serialize msgpack
--SKIPIF--
<?php
if (!extension_loaded("memcached")) print "skip";
if (!extension_loaded('msgpack')) echo "skip no msgpack loaded";
if (!Memcached::HAVE_MSGPACK) echo "skip msgpack support not enabled";
?>
--REDIRECTTEST--

$path = implode(DIRECTORY_SEPARATOR, array('tests', 'experimental', 'serializer'));

return array(
'TESTS' => $path,
'ENV' => array('TEST_MEMC_SERIALIZER' => 'Memcached::SERIALIZER_MSGPACK'),
);