From ada08ebfe056514f9e67d84ec7690a8bb5987fc1 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Fri, 5 Sep 2014 19:42:54 +0200 Subject: [PATCH 001/345] allow to use system FastLZ --- config.m4 | 21 ++++++++++++++++++--- php_memcached.c | 5 ++++- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/config.m4 b/config.m4 index b484f29f..94a0e7d3 100644 --- a/config.m4 +++ b/config.m4 @@ -26,6 +26,9 @@ PHP_ARG_ENABLE(memcached-sasl, whether to enable memcached sasl support, PHP_ARG_ENABLE(memcached-protocol, whether to enable memcached protocol support, [ --enable-memcached-protocol Enable memcached protocoll support], no, no) +PHP_ARG_WITH(system-fastlz, wheter to use system FastLZ bibrary, +[ --with-system-fastlz Use system FastLZ bibrary], no, no) + if test -z "$PHP_ZLIB_DIR"; then PHP_ARG_WITH(zlib-dir, for ZLIB, [ --with-zlib-dir[=DIR] Set the path to ZLIB install prefix.], no) @@ -336,7 +339,17 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_RESULT([no]) fi - PHP_MEMCACHED_FILES="php_memcached.c php_libmemcached_compat.c fastlz/fastlz.c g_fmt.c" + PHP_MEMCACHED_FILES="php_memcached.c php_libmemcached_compat.c g_fmt.c" + + if test "$PHP_SYSTEM_FASTLZ" != "no"; then + AC_CHECK_HEADERS([fastlz.h], [ac_cv_have_fastlz="yes"], [ac_cv_have_fastlz="no"]) + PHP_CHECK_LIBRARY(fastlz, fastlz_compress, + [PHP_ADD_LIBRARY(fastlz, 1, MEMCACHED_SHARED_LIBADD)], + [AC_MSG_ERROR(FastLZ library not found)]) + else + ac_cv_have_fastlz="no" + PHP_MEMCACHED_FILES="${PHP_MEMCACHED_FILES} fastlz/fastlz.c" + fi if test "$PHP_MEMCACHED_SESSION" != "no"; then PHP_MEMCACHED_FILES="${PHP_MEMCACHED_FILES} php_memcached_session.c" @@ -390,8 +403,10 @@ if test "$PHP_MEMCACHED" != "no"; then PHP_SUBST(MEMCACHED_SHARED_LIBADD) PHP_NEW_EXTENSION(memcached, $PHP_MEMCACHED_FILES, $ext_shared,,$SESSION_INCLUDES $IGBINARY_INCLUDES $LIBEVENT_INCLUDES $MSGPACK_INCLUDES) - PHP_ADD_BUILD_DIR($ext_builddir/fastlz, 1) - + if test "ac_cv_have_fastlz" != "yes"; then + PHP_ADD_BUILD_DIR($ext_builddir/fastlz, 1) + fi + ifdef([PHP_ADD_EXTENSION_DEP], [ PHP_ADD_EXTENSION_DEP(memcached, spl, true) diff --git a/php_memcached.c b/php_memcached.c index b21ecd42..2bd39d10 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -30,8 +30,11 @@ #ifdef HAVE_MEMCACHED_SESSION # include "php_memcached_session.h" #endif - +#ifdef HAVE_FASTLZ_H +#include +#else #include "fastlz/fastlz.h" +#endif #include #ifdef HAVE_JSON_API From 7270cf3032f0f816ab60f42e9d657f01bc874fea Mon Sep 17 00:00:00 2001 From: Anthony Ryan Date: Sun, 28 Sep 2014 01:01:56 -0400 Subject: [PATCH 002/345] Fix a typo in the arguments help Just noticed this when skimming through the code. --- config.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.m4 b/config.m4 index 94a0e7d3..107f8cbe 100644 --- a/config.m4 +++ b/config.m4 @@ -26,7 +26,7 @@ PHP_ARG_ENABLE(memcached-sasl, whether to enable memcached sasl support, PHP_ARG_ENABLE(memcached-protocol, whether to enable memcached protocol support, [ --enable-memcached-protocol Enable memcached protocoll support], no, no) -PHP_ARG_WITH(system-fastlz, wheter to use system FastLZ bibrary, +PHP_ARG_WITH(system-fastlz, whether to use system FastLZ bibrary, [ --with-system-fastlz Use system FastLZ bibrary], no, no) if test -z "$PHP_ZLIB_DIR"; then From d9c085b0ca2e1a7fbb496eaa1c580a0bb6e09072 Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 22 Oct 2014 16:20:59 +0100 Subject: [PATCH 003/345] Added test for bug #155 --- tests/gh_155.phpt | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 tests/gh_155.phpt diff --git a/tests/gh_155.phpt b/tests/gh_155.phpt new file mode 100644 index 00000000..c1f02bc6 --- /dev/null +++ b/tests/gh_155.phpt @@ -0,0 +1,41 @@ +--TEST-- +Test for bug 155 +--SKIPIF-- + +--FILE-- +setOption(Memcached::OPT_BINARY_PROTOCOL,true); +$m->addServer(MEMC_SERVER_HOST, MEMC_SERVER_PORT); + +$key = 'bug_155_' . uniqid(); + +$m->set ($key, 'test', time() + 86400); + +$m->get ($key); +echo "GET: " . $m->getResultMessage() . PHP_EOL; + +$m->touch ($key, time() + 86400); +echo "TOUCH: " . $m->getResultMessage() . PHP_EOL; + +$m->touch ($key, time() + 86400); +echo "TOUCH: " . $m->getResultMessage() . PHP_EOL; + +$m->get ($key); +echo "GET: " . $m->getResultMessage() . PHP_EOL; + +$m->get ($key); +echo "GET: " . $m->getResultMessage() . PHP_EOL; + +echo "DONE" . PHP_EOL; + +--EXPECT-- +GET: SUCCESS +TOUCH: SUCCESS +TOUCH: SUCCESS +GET: SUCCESS +GET: SUCCESS +DONE \ No newline at end of file From c157d8a3d0a2e57a3ef1bfbff0509545bf5482c6 Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 22 Oct 2014 16:22:01 +0100 Subject: [PATCH 004/345] Added bug #155 test to package.xml --- package.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/package.xml b/package.xml index 9a4ff054..0ebc86f9 100644 --- a/package.xml +++ b/package.xml @@ -134,6 +134,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> + From 657e373c9219782e317cefd5b8d7d50da1a9780c Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Wed, 26 Nov 2014 09:23:01 +0100 Subject: [PATCH 005/345] Foreign serializers like msgpack and igbinary may crash on randomly initialized zval because they check of IS_ARRAY, IS_OBJECT (or any type) on certain circumstances. --- php_memcached.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 2bd39d10..c1bce93b 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -838,7 +838,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke memcpy (res_key, tmp_key, res_key_len >= MEMCACHED_MAX_KEY ? MEMCACHED_MAX_KEY - 1 : res_key_len); res_key [res_key_len] = '\0'; - MAKE_STD_ZVAL(value); + ALLOC_INIT_ZVAL(value); if (php_memc_zval_from_payload(value, payload, payload_len, flags, m_obj->serializer TSRMLS_CC) < 0) { zval_ptr_dtor(&value); @@ -1057,7 +1057,7 @@ PHP_METHOD(Memcached, fetch) res_key_len = memcached_result_key_length(&result); cas = memcached_result_cas(&result); - MAKE_STD_ZVAL(value); + ALLOC_INIT_ZVAL(value); if (php_memc_zval_from_payload(value, payload, payload_len, flags, m_obj->serializer TSRMLS_CC) < 0) { memcached_result_free(&result); @@ -1114,7 +1114,7 @@ PHP_METHOD(Memcached, fetchAll) res_key_len = memcached_result_key_length(&result); cas = memcached_result_cas(&result); - MAKE_STD_ZVAL(value); + ALLOC_INIT_ZVAL(value); if (php_memc_zval_from_payload(value, payload, payload_len, flags, m_obj->serializer TSRMLS_CC) < 0) { memcached_result_free(&result); @@ -3663,7 +3663,7 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, res_key_len = memcached_result_key_length(result); cas = memcached_result_cas(result); - MAKE_STD_ZVAL(value); + ALLOC_INIT_ZVAL(value); i_obj = (php_memc_t *) zend_object_store_get_object(zmemc_obj TSRMLS_CC); From 949195d28b4e4bf06a690b50379a22312f4f80a5 Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Tue, 3 Feb 2015 08:02:42 -0800 Subject: [PATCH 006/345] PHP7 Support --- php_memcached.c | 1197 +++++++++++++++++++-------------------- php_memcached.h | 2 +- php_memcached_private.h | 2 +- php_memcached_server.c | 478 ++++++++-------- php_memcached_server.h | 4 +- php_memcached_session.c | 78 +-- 6 files changed, 838 insertions(+), 923 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index c1bce93b..33570992 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -122,14 +122,6 @@ php_memc_t* i_obj = NULL; \ struct memc_obj* m_obj = NULL; -#define MEMC_METHOD_FETCH_OBJECT \ - i_obj = (php_memc_t *) zend_object_store_get_object( object TSRMLS_CC ); \ - m_obj = i_obj->obj; \ - if (!m_obj) { \ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Memcached constructor was not called"); \ - return; \ - } - #ifndef DVAL_TO_LVAL #ifdef _WIN64 # define DVAL_TO_LVAL(d, l) \ @@ -150,12 +142,6 @@ #define RETURN_FROM_GET RETURN_FALSE -#if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION < 3) -#define zend_parse_parameters_none() \ - zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") -#endif - - /**************************************** Structures and definitions ****************************************/ @@ -165,8 +151,6 @@ enum memcached_compression_type { }; typedef struct { - zend_object zo; - struct memc_obj { memcached_st *memc; zend_bool compression; @@ -182,8 +166,22 @@ typedef struct { zend_bool is_pristine; int rescode; int memc_errno; + zend_object zo; } php_memc_t; +static inline php_memc_t *php_memc_fetch_object(zend_object *obj) { + return (php_memc_t *)((char *)(obj) - XtOffsetOf(php_memc_t, zo)); +} +#define Z_MEMC_OBJ_P(zv) php_memc_fetch_object(Z_OBJ_P(zv)); + +#define MEMC_METHOD_FETCH_OBJECT \ + i_obj = Z_MEMC_OBJ_P(object); \ + m_obj = i_obj->obj; \ + if (!m_obj) { \ + php_error_docref(NULL, E_WARNING, "Memcached constructor was not called"); \ + return; \ + } + #ifdef HAVE_MEMCACHED_PROTOCOL typedef struct { @@ -244,41 +242,41 @@ static PHP_INI_MH(OnUpdateCompressionType) { if (!new_value) { MEMC_G(compression_type_real) = COMPRESSION_TYPE_FASTLZ; - } else if (!strcmp(new_value, "fastlz")) { + } else if (!strcmp(new_value->val, "fastlz")) { MEMC_G(compression_type_real) = COMPRESSION_TYPE_FASTLZ; - } else if (!strcmp(new_value, "zlib")) { + } else if (!strcmp(new_value->val, "zlib")) { MEMC_G(compression_type_real) = COMPRESSION_TYPE_ZLIB; } else { return FAILURE; } - return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC); + return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } static PHP_INI_MH(OnUpdateSerializer) { if (!new_value) { MEMC_G(serializer) = SERIALIZER_DEFAULT; - } else if (!strcmp(new_value, "php")) { + } else if (!strcmp(new_value->val, "php")) { MEMC_G(serializer) = SERIALIZER_PHP; #ifdef HAVE_MEMCACHED_IGBINARY - } else if (!strcmp(new_value, "igbinary")) { + } else if (!strcmp(new_value->val, "igbinary")) { MEMC_G(serializer) = SERIALIZER_IGBINARY; #endif // IGBINARY #ifdef HAVE_JSON_API - } else if (!strcmp(new_value, "json")) { + } else if (!strcmp(new_value->val, "json")) { MEMC_G(serializer) = SERIALIZER_JSON; - } else if (!strcmp(new_value, "json_array")) { + } else if (!strcmp(new_value->val, "json_array")) { MEMC_G(serializer) = SERIALIZER_JSON_ARRAY; #endif // JSON #ifdef HAVE_MEMCACHED_MSGPACK - } else if (!strcmp(new_value, "msgpack")) { + } else if (!strcmp(new_value->val, "msgpack")) { MEMC_G(serializer) = SERIALIZER_MSGPACK; #endif // msgpack } else { return FAILURE; } - return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC); + return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } /* {{{ INI entries */ @@ -316,9 +314,9 @@ PHP_INI_END() /**************************************** Forward declarations ****************************************/ -static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status TSRMLS_DC); -static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type TSRMLS_DC); -static int php_memc_zval_from_payload(zval *value, const char *payload, size_t payload_len, uint32_t flags, enum memcached_serializer serializer TSRMLS_DC); +static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status); +static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type); +static int php_memc_zval_from_payload(zval *value, const char *payload, size_t payload_len, uint32_t flags, enum memcached_serializer serializer); static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool by_key); @@ -326,68 +324,66 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); -static memcached_return php_memc_do_cache_callback(zval *memc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, char *key, size_t key_len, zval *value TSRMLS_DC); -static int php_memc_do_result_callback(zval *memc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, memcached_result_st *result TSRMLS_DC); +static memcached_return php_memc_do_cache_callback(zval *memc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string *key, zval *value); +static int php_memc_do_result_callback(zval *memc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, memcached_result_st *result); static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context); static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context); static memcached_return php_memc_do_version_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context); -static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent TSRMLS_DC); +static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent); /**************************************** Method implementations ****************************************/ -char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC) +char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) { char *buffer = NULL; - if (fci->object_ptr) { - spprintf (&buffer, 0, "%s::%s", Z_OBJCE_P (fci->object_ptr)->name, fci_cache->function_handler->common.function_name); + if (fci->object) { + spprintf (&buffer, 0, "%s::%s", fci->object->ce->name->val, fci_cache->function_handler->common.function_name); } else { - if (Z_TYPE_P (fci->function_name) == IS_OBJECT) { - spprintf (&buffer, 0, "%s", Z_OBJCE_P (fci->function_name)->name); + if (Z_TYPE (fci->function_name) == IS_OBJECT) { + spprintf (&buffer, 0, "%s", Z_OBJCE (fci->function_name)->name->val); } else { - spprintf (&buffer, 0, "%s", Z_STRVAL_P (fci->function_name)); + spprintf (&buffer, 0, "%s", Z_STRVAL (fci->function_name)); } } return buffer; } -static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache, char *persistent_id, int persistent_id_len TSRMLS_DC) +static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache, zend_string *persistent_id) { - zend_bool retval = 1; - zval pid_z; - zval *retval_ptr, *pid_z_ptr = &pid_z; - zval **params[2]; + zend_bool ret = 1; + zval retval; + zval params[2]; - INIT_ZVAL(pid_z); if (persistent_id) { - ZVAL_STRINGL(pid_z_ptr, persistent_id, persistent_id_len, 1); + ZVAL_STR(¶ms[1], persistent_id); + } else { + ZVAL_NULL(¶ms[1]); } /* Call the cb */ - params[0] = &object; - params[1] = &pid_z_ptr; + ZVAL_COPY_VALUE(¶ms[0], object); fci->params = params; fci->param_count = 2; - fci->retval_ptr_ptr = &retval_ptr; + fci->retval = &retval; fci->no_separation = 1; - if (zend_call_function(fci, fci_cache TSRMLS_CC) == FAILURE) { - char *buf = php_memc_printable_func (fci, fci_cache TSRMLS_CC); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to invoke 'on_new' callback %s()", buf); + if (zend_call_function(fci, fci_cache) == FAILURE) { + char *buf = php_memc_printable_func (fci, fci_cache); + php_error_docref(NULL, E_WARNING, "Failed to invoke 'on_new' callback %s()", buf); efree (buf); - retval = 0; + ret = 0; } - zval_dtor(pid_z_ptr); - if (retval_ptr) { - zval_ptr_dtor(&retval_ptr); - } - return retval; + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(&retval); + return ret; } static int le_memc, le_memc_sess; @@ -404,32 +400,28 @@ static PHP_METHOD(Memcached, __construct) zval *object = getThis(); php_memc_t *i_obj; struct memc_obj *m_obj = NULL; - char *persistent_id = NULL, *conn_str = NULL; - int persistent_id_len, conn_str_len; + zend_string *persistent_id = NULL; + zend_string *conn_str = NULL; zend_bool is_persistent = 0; - - char *plist_key = NULL; - int plist_key_len = 0; - + zend_string *plist_key = NULL; zend_fcall_info fci = {0}; zend_fcall_info_cache fci_cache; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!f!s", &persistent_id, &persistent_id_len, &fci, &fci_cache, &conn_str, &conn_str_len) == FAILURE) { - ZVAL_NULL(object); + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!f!S", &persistent_id, &fci, &fci_cache, &conn_str) == FAILURE) { + ZEND_CTOR_MAKE_NULL(); return; } - i_obj = (php_memc_t *) zend_object_store_get_object(object TSRMLS_CC); + i_obj = Z_MEMC_OBJ_P(object); i_obj->is_pristine = 0; - if (persistent_id && *persistent_id) { - zend_rsrc_list_entry *le = NULL; + if (persistent_id && persistent_id->len) { + zend_resource *le; is_persistent = 1; - plist_key_len = spprintf(&plist_key, 0, "memcached:id=%s", persistent_id); - plist_key_len += 1; - - if (zend_hash_find(&EG(persistent_list), plist_key, plist_key_len, (void *)&le) == SUCCESS) { + plist_key = zend_string_alloc(sizeof("memcached:id=") + persistent_id->len - 1, 0); + snprintf(plist_key->val, plist_key->len+1, "memcached:id=%s", persistent_id->val); + if ((le = zend_hash_find_ptr(&EG(persistent_list), plist_key)) != NULL) { if (le->type == php_memc_list_entry()) { m_obj = (struct memc_obj *) le->ptr; } @@ -443,27 +435,27 @@ static PHP_METHOD(Memcached, __construct) m_obj = pecalloc(1, sizeof(*m_obj), is_persistent); if (m_obj == NULL) { if (plist_key) { - efree(plist_key); + zend_string_release(plist_key); } - php_error_docref(NULL TSRMLS_CC, E_ERROR, "out of memory: cannot allocate handle"); + php_error_docref(NULL, E_ERROR, "out of memory: cannot allocate handle"); /* not reached */ } if (conn_str) { - m_obj->memc = php_memc_create_str(conn_str, conn_str_len); + m_obj->memc = php_memc_create_str(conn_str->val, conn_str->len); if (!m_obj->memc) { char error_buffer[1024]; if (plist_key) { - efree(plist_key); + zend_string_release(plist_key); } #ifdef HAVE_LIBMEMCACHED_CHECK_CONFIGURATION - if (libmemcached_check_configuration(conn_str, conn_str_len, error_buffer, sizeof(error_buffer)) != MEMCACHED_SUCCESS) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "configuration error %s", error_buffer); + if (libmemcached_check_configuration(conn_str->val, conn_str->len, error_buffer, sizeof(error_buffer)) != MEMCACHED_SUCCESS) { + php_error_docref(NULL, E_ERROR, "configuration error %s", error_buffer); } else { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "could not allocate libmemcached structure"); + php_error_docref(NULL, E_ERROR, "could not allocate libmemcached structure"); } #else - php_error_docref(NULL TSRMLS_CC, E_ERROR, "could not allocate libmemcached structure"); + php_error_docref(NULL, E_ERROR, "could not allocate libmemcached structure"); #endif /* not reached */ } @@ -471,9 +463,9 @@ static PHP_METHOD(Memcached, __construct) m_obj->memc = memcached_create(NULL); if (m_obj->memc == NULL) { if (plist_key) { - efree(plist_key); + zend_string_release(plist_key); } - php_error_docref(NULL TSRMLS_CC, E_ERROR, "could not allocate libmemcached structure"); + php_error_docref(NULL, E_ERROR, "could not allocate libmemcached structure"); /* not reached */ } } @@ -487,15 +479,15 @@ static PHP_METHOD(Memcached, __construct) i_obj->is_pristine = 1; if (fci.size) { /* will be 0 when not available */ - if (!php_memcached_on_new_callback(object, &fci, &fci_cache, persistent_id, persistent_id_len TSRMLS_CC) || EG(exception)) { + if (!php_memcached_on_new_callback(object, &fci, &fci_cache, persistent_id) || EG(exception)) { /* error calling or exception thrown from callback */ if (plist_key) { - efree(plist_key); + zend_string_release(plist_key); } i_obj->obj = NULL; if (is_persistent) { - php_memc_destroy(m_obj, is_persistent TSRMLS_CC); + php_memc_destroy(m_obj, is_persistent); } return; @@ -503,23 +495,23 @@ static PHP_METHOD(Memcached, __construct) } if (is_persistent) { - zend_rsrc_list_entry le; + zend_resource le; le.type = php_memc_list_entry(); le.ptr = m_obj; - if (zend_hash_update(&EG(persistent_list), (char *)plist_key, - plist_key_len, (void *)&le, sizeof(le), NULL) == FAILURE) { + GC_REFCOUNT(&le) = 1; + if (zend_hash_update_mem(&EG(persistent_list), plist_key, &le, sizeof(le)) == NULL) { if (plist_key) { - efree(plist_key); + zend_string_release(plist_key); } - php_error_docref(NULL TSRMLS_CC, E_ERROR, "could not register persistent entry"); + php_error_docref(NULL, E_ERROR, "could not register persistent entry"); /* not reached */ } } } if (plist_key) { - efree(plist_key); + zend_string_release(plist_key); } } /* }}} */ @@ -543,10 +535,8 @@ PHP_METHOD(Memcached, getByKey) /* {{{ -- php_memc_get_impl */ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { - char *key = NULL; - int key_len = 0; - char *server_key = NULL; - int server_key_len = 0; + zend_string *key; + zend_string *server_key; const char *payload = NULL; size_t payload_len = 0; uint32_t flags = 0; @@ -562,12 +552,12 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|f!zz", &server_key, - &server_key_len, &key, &key_len, &fci, &fcc, &cas_token, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|f!zz", &server_key, &key, + &fci, &fcc, &cas_token, &udf_flags) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|f!zz", &key, &key_len, + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|f!zz", &key, &fci, &fcc, &cas_token, &udf_flags) == FAILURE) { return; } @@ -576,13 +566,13 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || strchr(key, ' ')) { + if (key->len == 0 || strchr(key->val, ' ')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FROM_GET; } - keys[0] = key; - key_lens[0] = key_len; + keys[0] = key->val; + key_lens[0] = key->len; uint64_t orig_cas_flag; orig_cas_flag = memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS); @@ -590,17 +580,17 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) /* * Enable CAS support, but only if it is currently disabled. */ - if (cas_token && PZVAL_IS_REF(cas_token) && orig_cas_flag == 0) { + if (cas_token && Z_IS_REF(cas_token) && orig_cas_flag == 0) { memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); } - status = memcached_mget_by_key(m_obj->memc, server_key, server_key_len, keys, key_lens, 1); + status = memcached_mget_by_key(m_obj->memc, server_key->val, server_key->len, keys, key_lens, 1); - if (cas_token && PZVAL_IS_REF(cas_token) && orig_cas_flag == 0) { + if (cas_token && Z_IS_REF(cas_token) && orig_cas_flag == 0) { memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); } - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { RETURN_FROM_GET; } @@ -622,10 +612,10 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) } if (status == MEMCACHED_NOTFOUND && fci.size != 0) { - status = php_memc_do_cache_callback(getThis(), &fci, &fcc, key, key_len, return_value TSRMLS_CC); + status = php_memc_do_cache_callback(getThis(), &fci, &fcc, key, return_value); } - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { memcached_result_free(&result); RETURN_FROM_GET; } @@ -651,18 +641,22 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) cas = memcached_result_cas(&result); } - if (php_memc_zval_from_payload(return_value, payload, payload_len, flags, m_obj->serializer TSRMLS_CC) < 0) { + if (php_memc_zval_from_payload(return_value, payload, payload_len, flags, m_obj->serializer) < 0) { memcached_result_free(&result); i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FROM_GET; } if (cas_token) { + ZVAL_DEREF(cas_token); + SEPARATE_ZVAL(cas_token); zval_dtor(cas_token); ZVAL_DOUBLE(cas_token, (double)cas); } if (udf_flags) { + ZVAL_DEREF(udf_flags); + SEPARATE_ZVAL(udf_flags); zval_dtor(udf_flags); ZVAL_LONG(udf_flags, MEMC_VAL_GET_USER_FLAGS(flags)); } @@ -691,10 +685,9 @@ PHP_METHOD(Memcached, getMultiByKey) static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { zval *keys = NULL; - char *server_key = NULL; - int server_key_len = 0; + zend_string *server_key; size_t num_keys = 0; - zval **entry = NULL; + zval *entry = NULL; const char *payload = NULL; size_t payload_len = 0; const char **mkeys = NULL; @@ -706,7 +699,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke zval *cas_tokens = NULL; zval *udf_flags = NULL; uint64_t orig_cas_flag = 0; - zval *value; + zval value; long get_flags = 0; int i = 0; zend_bool preserve_order; @@ -715,12 +708,12 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa/|zlz", &server_key, - &server_key_len, &keys, &cas_tokens, &get_flags, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|zlz", &server_key, + &keys, &cas_tokens, &get_flags, &udf_flags) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/|zlz", &keys, &cas_tokens, &get_flags, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|zlz", &keys, &cas_tokens, &get_flags, &udf_flags) == FAILURE) { return; } } @@ -738,24 +731,21 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke * Create the array of keys for libmemcached. If none of the keys were valid * (strings), set bad key result code and return. */ - for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(keys)); - zend_hash_get_current_data(Z_ARRVAL_P(keys), (void**)&entry) == SUCCESS; - zend_hash_move_forward(Z_ARRVAL_P(keys))) { - - if (Z_TYPE_PP(entry) != IS_STRING) { + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(keys), entry) { + if (Z_TYPE_P(entry) != IS_STRING) { convert_to_string_ex(entry); } - if (Z_TYPE_PP(entry) == IS_STRING && Z_STRLEN_PP(entry) > 0) { - mkeys[i] = Z_STRVAL_PP(entry); - mkeys_len[i] = Z_STRLEN_PP(entry); + if (Z_TYPE_P(entry) == IS_STRING && Z_STRLEN_P(entry) > 0) { + mkeys[i] = Z_STRVAL_P(entry); + mkeys_len[i] = Z_STRLEN_P(entry); if (preserve_order) { - add_assoc_null_ex(return_value, mkeys[i], mkeys_len[i] + 1); + add_assoc_null_ex(return_value, mkeys[i], mkeys_len[i]); } i++; } - } + } ZEND_HASH_FOREACH_END(); if (i == 0) { i_obj->rescode = MEMCACHED_NOTFOUND; @@ -767,21 +757,21 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke /* * Enable CAS support, but only if it is currently disabled. */ - if (cas_tokens && PZVAL_IS_REF(cas_tokens)) { + if (cas_tokens && Z_IS_REF(cas_tokens)) { orig_cas_flag = memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS); if (orig_cas_flag == 0) { memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); } } - status = memcached_mget_by_key(m_obj->memc, server_key, server_key_len, mkeys, mkeys_len, i); + status = memcached_mget_by_key(m_obj->memc, server_key->val, server_key->len, mkeys, mkeys_len, i); /* Handle error, but ignore, there might still be some result */ - php_memc_handle_error(i_obj, status TSRMLS_CC); + php_memc_handle_error(i_obj, status); /* * Restore the CAS support flag, but only if we had to turn it on. */ - if (cas_tokens && PZVAL_IS_REF(cas_tokens) && orig_cas_flag == 0) { + if (cas_tokens && Z_IS_REF(cas_tokens) && orig_cas_flag == 0) { memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); } @@ -793,15 +783,16 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke * returned as doubles, because we cannot store potential 64-bit values in longs. */ if (cas_tokens) { - if (PZVAL_IS_REF(cas_tokens)) { + if (Z_IS_REF(cas_tokens)) { /* cas_tokens was passed by reference, we'll create an array for it. */ + ZVAL_DEREF(cas_tokens); + SEPARATE_ZVAL(cas_tokens); zval_dtor(cas_tokens); array_init(cas_tokens); } else { /* Not passed by reference, we allow this (eg.: if you specify null to not enable cas but you want to use the udf_flags parameter). We destruct it and set it to null for the peace of mind. */ - zval_dtor(cas_tokens); cas_tokens = NULL; } } @@ -811,6 +802,8 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke * returned as longs. */ if (udf_flags) { + ZVAL_DEREF(udf_flags); + SEPARATE_ZVAL(udf_flags); zval_dtor(udf_flags); array_init(udf_flags); } @@ -821,7 +814,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke if (status != MEMCACHED_SUCCESS) { status = MEMCACHED_SOME_ERRORS; - php_memc_handle_error(i_obj, status TSRMLS_CC); + php_memc_handle_error(i_obj, status); continue; } @@ -838,13 +831,11 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke memcpy (res_key, tmp_key, res_key_len >= MEMCACHED_MAX_KEY ? MEMCACHED_MAX_KEY - 1 : res_key_len); res_key [res_key_len] = '\0'; - ALLOC_INIT_ZVAL(value); - - if (php_memc_zval_from_payload(value, payload, payload_len, flags, m_obj->serializer TSRMLS_CC) < 0) { + if (php_memc_zval_from_payload(&value, payload, payload_len, flags, m_obj->serializer) < 0) { zval_ptr_dtor(&value); if (EG(exception)) { status = MEMC_RES_PAYLOAD_FAILURE; - php_memc_handle_error(i_obj, status TSRMLS_CC); + php_memc_handle_error(i_obj, status); memcached_quit(m_obj->memc); break; @@ -855,7 +846,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke continue; } - add_assoc_zval_ex(return_value, res_key, res_key_len+1, value); + add_assoc_zval_ex(return_value, res_key, res_key_len+1, &value); if (cas_tokens) { cas = memcached_result_cas(&result); add_assoc_double_ex(cas_tokens, res_key, res_key_len+1, (double)cas); @@ -870,10 +861,14 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke if (EG(exception)) { /* XXX: cas_tokens should only be set on success, currently we're destructive */ if (cas_tokens) { + ZVAL_DEREF(cas_tokens); + SEPARATE_ZVAL(cas_tokens); zval_dtor(cas_tokens); ZVAL_NULL(cas_tokens); } if (udf_flags) { + ZVAL_DEREF(udf_flags); + SEPARATE_ZVAL(udf_flags); zval_dtor(udf_flags); ZVAL_NULL(udf_flags); } @@ -903,11 +898,10 @@ PHP_METHOD(Memcached, getDelayedByKey) static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { zval *keys = NULL; - char *server_key = NULL; - int server_key_len = 0; + zend_string *server_key; zend_bool with_cas = 0; size_t num_keys = 0; - zval **entry = NULL; + zval *entry = NULL; const char **mkeys = NULL; size_t *mkeys_len = NULL; uint64_t orig_cas_flag = 0; @@ -918,12 +912,12 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa/|bf!", &server_key, - &server_key_len, &keys, &with_cas, &fci, &fcc) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|bf!", &server_key, + &keys, &with_cas, &fci, &fcc) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/|bf!", &keys, &with_cas, + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|bf!", &keys, &with_cas, &fci, &fcc) == FAILURE) { return; } @@ -940,20 +934,17 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ mkeys = safe_emalloc(num_keys, sizeof(*mkeys), 0); mkeys_len = safe_emalloc(num_keys, sizeof(*mkeys_len), 0); - for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(keys)); - zend_hash_get_current_data(Z_ARRVAL_P(keys), (void**)&entry) == SUCCESS; - zend_hash_move_forward(Z_ARRVAL_P(keys))) { - - if (Z_TYPE_PP(entry) != IS_STRING) { + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(keys), entry) { + if (Z_TYPE_P(entry) != IS_STRING) { convert_to_string_ex(entry); } if (Z_TYPE_PP(entry) == IS_STRING && Z_STRLEN_PP(entry) > 0) { - mkeys[i] = Z_STRVAL_PP(entry); - mkeys_len[i] = Z_STRLEN_PP(entry); + mkeys[i] = Z_STRVAL_P(entry); + mkeys_len[i] = Z_STRLEN_P(entry); i++; } - } + } ZEND_HASH_FOREACH_END(); if (i == 0) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; @@ -976,7 +967,7 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ /* * Issue the request, but collect results only if the result callback is provided. */ - status = memcached_mget_by_key(m_obj->memc, server_key, server_key_len, mkeys, mkeys_len, i); + status = memcached_mget_by_key(m_obj->memc, server_key->val, server_key->len, mkeys, mkeys_len, i); /* * Restore the CAS support flag, but only if we had to turn it on. @@ -987,7 +978,7 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ efree(mkeys); efree(mkeys_len); - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { zval_dtor(return_value); RETURN_FALSE; } @@ -1001,7 +992,7 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ memcached_result_create(m_obj->memc, &result); while ((memcached_fetch_result(m_obj->memc, &result, &status)) != NULL) { - if (php_memc_do_result_callback(getThis(), &fci, &fcc, &result TSRMLS_CC) < 0) { + if (php_memc_do_result_callback(getThis(), &fci, &fcc, &result) < 0) { status = MEMCACHED_FAILURE; break; } @@ -1012,7 +1003,7 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ if (status == MEMCACHED_END) { status = MEMCACHED_SUCCESS; } - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { RETURN_FALSE; } } @@ -1029,7 +1020,7 @@ PHP_METHOD(Memcached, fetch) size_t res_key_len = 0; const char *payload = NULL; size_t payload_len = 0; - zval *value; + zval value; uint32_t flags = 0; uint64_t cas = 0; memcached_result_st result; @@ -1045,7 +1036,7 @@ PHP_METHOD(Memcached, fetch) memcached_result_create(m_obj->memc, &result); if ((memcached_fetch_result(m_obj->memc, &result, &status)) == NULL) { - php_memc_handle_error(i_obj, status TSRMLS_CC); + php_memc_handle_error(i_obj, status); memcached_result_free(&result); RETURN_FALSE; } @@ -1057,9 +1048,7 @@ PHP_METHOD(Memcached, fetch) res_key_len = memcached_result_key_length(&result); cas = memcached_result_cas(&result); - ALLOC_INIT_ZVAL(value); - - if (php_memc_zval_from_payload(value, payload, payload_len, flags, m_obj->serializer TSRMLS_CC) < 0) { + if (php_memc_zval_from_payload(&value, payload, payload_len, flags, m_obj->serializer) < 0) { memcached_result_free(&result); zval_ptr_dtor(&value); i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; @@ -1067,14 +1056,14 @@ PHP_METHOD(Memcached, fetch) } array_init(return_value); - add_assoc_stringl_ex(return_value, ZEND_STRS("key"), res_key, res_key_len, 1); - add_assoc_zval_ex(return_value, ZEND_STRS("value"), value); + add_assoc_stringl_ex(return_value, ZEND_STRL("key"), (char *)res_key, res_key_len); + add_assoc_zval_ex(return_value, ZEND_STRL("value"), &value); if (cas != 0) { /* XXX: also check against ULLONG_MAX or memc_behavior */ - add_assoc_double_ex(return_value, ZEND_STRS("cas"), (double)cas); + add_assoc_double_ex(return_value, ZEND_STRL("cas"), (double)cas); } if (MEMC_VAL_GET_USER_FLAGS(flags) != 0) { - add_assoc_long_ex(return_value, ZEND_STRS("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); + add_assoc_long_ex(return_value, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); } memcached_result_free(&result); @@ -1089,7 +1078,7 @@ PHP_METHOD(Memcached, fetchAll) size_t res_key_len = 0; const char *payload = NULL; size_t payload_len = 0; - zval *value, *entry; + zval value, entry; uint32_t flags; uint64_t cas = 0; memcached_result_st result; @@ -1114,9 +1103,7 @@ PHP_METHOD(Memcached, fetchAll) res_key_len = memcached_result_key_length(&result); cas = memcached_result_cas(&result); - ALLOC_INIT_ZVAL(value); - - if (php_memc_zval_from_payload(value, payload, payload_len, flags, m_obj->serializer TSRMLS_CC) < 0) { + if (php_memc_zval_from_payload(&value, payload, payload_len, flags, m_obj->serializer) < 0) { memcached_result_free(&result); zval_ptr_dtor(&value); zval_dtor(return_value); @@ -1124,23 +1111,22 @@ PHP_METHOD(Memcached, fetchAll) RETURN_FALSE; } - MAKE_STD_ZVAL(entry); - array_init(entry); - add_assoc_stringl_ex(entry, ZEND_STRS("key"), res_key, res_key_len, 1); - add_assoc_zval_ex(entry, ZEND_STRS("value"), value); + array_init(&entry); + add_assoc_stringl_ex(&entry, ZEND_STRL("key"), (char *)res_key, res_key_len); + add_assoc_zval_ex(&entry, ZEND_STRL("value"), &value); if (cas != 0) { /* XXX: also check against ULLONG_MAX or memc_behavior */ - add_assoc_double_ex(entry, ZEND_STRS("cas"), (double)cas); + add_assoc_double_ex(&entry, ZEND_STRL("cas"), (double)cas); } if (MEMC_VAL_GET_USER_FLAGS(flags) != 0) { - add_assoc_long_ex(entry, ZEND_STRS("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); + add_assoc_long_ex(&entry, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); } - add_next_index_zval(return_value, entry); + add_next_index_zval(return_value, &entry); } memcached_result_free(&result); - if (status != MEMCACHED_END && php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (status != MEMCACHED_END && php_memc_handle_error(i_obj, status) < 0) { zval_dtor(return_value); RETURN_FALSE; } @@ -1227,13 +1213,11 @@ PHP_METHOD(Memcached, setMultiByKey) static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { zval *entries; - char *server_key = NULL; - int server_key_len = 0; + zend_string *server_key; time_t expiration = 0; long udf_flags = 0; - zval **entry; - char *str_key; - uint str_key_len; + zval *entry; + zend_string *str_key = NULL; ulong num_key; char *payload; size_t payload_len; @@ -1241,15 +1225,16 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke uint32_t retry = 0; memcached_return status; char tmp_key[MEMCACHED_MAX_KEY]; + int tmp_len = 0; MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa|ll", &server_key, - &server_key_len, &entries, &expiration, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa|ll", &server_key, + &entries, &expiration, &udf_flags) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|ll", &entries, &expiration, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|ll", &entries, &expiration, &udf_flags) == FAILURE) { return; } } @@ -1263,24 +1248,21 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke */ if (udf_flags > 0) { if ((uint32_t) udf_flags > MEMC_VAL_USER_FLAGS_MAX) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %u", MEMC_VAL_USER_FLAGS_MAX); + php_error_docref(NULL, E_WARNING, "udf_flags will be limited to %u", MEMC_VAL_USER_FLAGS_MAX); } } - for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(entries)); - zend_hash_get_current_data(Z_ARRVAL_P(entries), (void**)&entry) == SUCCESS; - zend_hash_move_forward(Z_ARRVAL_P(entries))) { - int key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(entries), &str_key, &str_key_len, &num_key, 0, NULL); - - if (key_type == HASH_KEY_IS_LONG) { + ZEND_HASH_FOREACH_KEY_VAL (Z_ARRVAL_P(entries), num_key, str_key, entry) { + if (str_key) { + str_key = zend_string_init(str_key->val, str_key->len, 0); + } else if (num_key || num_key == 0) { /* Array keys are unsigned, but php integers are signed. * Keys must be converted to signed strings that match * php integers. */ assert(sizeof(tmp_key) >= sizeof(ZEND_TOSTR(LONG_MIN))); - - str_key_len = sprintf(tmp_key, "%ld", (long)num_key) + 1; - str_key = (char *)tmp_key; - } else if (key_type != HASH_KEY_IS_STRING) { + tmp_len = sprintf(tmp_key, "%ld", (long)num_key); + str_key = zend_string_init(tmp_key, tmp_len, 0); + } else { continue; } @@ -1293,26 +1275,31 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) udf_flags)); } - payload = php_memc_zval_to_payload(*entry, &payload_len, &flags, m_obj->serializer, m_obj->compression_type TSRMLS_CC); + payload = php_memc_zval_to_payload(entry, &payload_len, &flags, m_obj->serializer, m_obj->compression_type); if (payload == NULL) { i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; + zend_string_release(str_key); RETURN_FALSE; } retry: if (!by_key) { - status = memcached_set(m_obj->memc, str_key, str_key_len-1, payload, payload_len, expiration, flags); + status = memcached_set(m_obj->memc, str_key->val, str_key->len, payload, payload_len, expiration, flags); + zend_string_release(str_key); } else { - status = memcached_set_by_key(m_obj->memc, server_key, server_key_len, str_key, str_key_len-1, payload, payload_len, expiration, flags); + status = memcached_set_by_key(m_obj->memc, server_key->val, server_key->len, str_key->val, str_key->len, payload, payload_len, expiration, flags); + zend_string_release(str_key); } - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { PHP_MEMC_FAILOVER_RETRY + zend_string_release(str_key); efree(payload); RETURN_FALSE; } + zend_string_release(str_key); efree(payload); - } + } ZEND_HASH_FOREACH_END(); RETURN_TRUE; } @@ -1382,16 +1369,12 @@ PHP_METHOD(Memcached, replaceByKey) } /* }}} */ - /* {{{ -- php_memc_store_impl */ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool by_key) { - char *key = NULL; - int key_len = 0; - char *server_key = NULL; - int server_key_len = 0; - char *s_value = NULL; - int s_value_len = 0; + zend_string *key; + zend_string *server_key; + zend_string *s_value; zval s_zvalue; zval *value; long expiration = 0; @@ -1405,41 +1388,33 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool if (by_key) { if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss", &server_key, - &server_key_len, &key, &key_len, &s_value, &s_value_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSS", &server_key, &key, &s_value) == FAILURE) { return; } - INIT_ZVAL(s_zvalue); value = &s_zvalue; - ZVAL_STRINGL(value, s_value, s_value_len, 0); + ZVAL_STR(value, s_value); } else if (op == MEMC_OP_TOUCH) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &server_key, - &server_key_len, &key, &key_len, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|l", &server_key, &key, &expiration) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssz|ll", &server_key, - &server_key_len, &key, &key_len, &value, &expiration, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSz|ll", &server_key, &key, &value, &expiration, &udf_flags) == FAILURE) { return; } } } else { if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &key, &key_len, - &s_value, &s_value_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &key, &s_value) == FAILURE) { return; } - INIT_ZVAL(s_zvalue); value = &s_zvalue; - ZVAL_STRINGL(value, s_value, s_value_len, 0); + ZVAL_STR(value, s_value); } else if (op == MEMC_OP_TOUCH) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &key, - &key_len, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &key, &expiration) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|ll", &key, &key_len, - &value, &expiration, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|ll", &key, &value, &expiration, &udf_flags) == FAILURE) { return; } } @@ -1448,7 +1423,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || strchr(key, ' ')) { + if (key->len == 0 || strchr(key->val, ' ')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1460,7 +1435,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool * append/prepend new data, and store it again. */ if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot append/prepend with compression turned on"); + php_error_docref(NULL, E_WARNING, "cannot append/prepend with compression turned on"); return; } MEMC_VAL_SET_FLAG(flags, MEMC_VAL_COMPRESSED); @@ -1472,7 +1447,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool */ if (udf_flags > 0) { if ((uint32_t) udf_flags > MEMC_VAL_USER_FLAGS_MAX) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %u", MEMC_VAL_USER_FLAGS_MAX); + php_error_docref(NULL, E_WARNING, "udf_flags will be limited to %u", MEMC_VAL_USER_FLAGS_MAX); } MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) udf_flags)); } @@ -1480,11 +1455,11 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool if (op == MEMC_OP_TOUCH) { #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000016 if (memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "using touch command with binary protocol is not recommended with libmemcached versions below 1.0.16"); + php_error_docref(NULL, E_WARNING, "using touch command with binary protocol is not recommended with libmemcached versions below 1.0.16"); } #endif } else { - payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type TSRMLS_CC); + payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type); if (payload == NULL) { i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FALSE; @@ -1493,56 +1468,56 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool retry: switch (op) { case MEMC_OP_SET: - if (!server_key) { - status = memcached_set(m_obj->memc, key, key_len, payload, payload_len, expiration, flags); + if (!server_key->val) { + status = memcached_set(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); } else { - status = memcached_set_by_key(m_obj->memc, server_key, server_key_len, key, - key_len, payload, payload_len, expiration, flags); + status = memcached_set_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + key->len, payload, payload_len, expiration, flags); } break; #ifdef HAVE_MEMCACHED_TOUCH case MEMC_OP_TOUCH: - if (!server_key) { - status = memcached_touch(m_obj->memc, key, key_len, expiration); + if (!server_key->val) { + status = memcached_touch(m_obj->memc, key->val, key->len, expiration); } else { - status = memcached_touch_by_key(m_obj->memc, server_key, server_key_len, key, - key_len, expiration); + status = memcached_touch_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + key->len, expiration); } break; #endif case MEMC_OP_ADD: - if (!server_key) { - status = memcached_add(m_obj->memc, key, key_len, payload, payload_len, expiration, flags); + if (!server_key->val) { + status = memcached_add(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); } else { - status = memcached_add_by_key(m_obj->memc, server_key, server_key_len, key, - key_len, payload, payload_len, expiration, flags); + status = memcached_add_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + key->len, payload, payload_len, expiration, flags); } break; case MEMC_OP_REPLACE: - if (!server_key) { - status = memcached_replace(m_obj->memc, key, key_len, payload, payload_len, expiration, flags); + if (!server_key->val) { + status = memcached_replace(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); } else { - status = memcached_replace_by_key(m_obj->memc, server_key, server_key_len, key, - key_len, payload, payload_len, expiration, flags); + status = memcached_replace_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + key->len, payload, payload_len, expiration, flags); } break; case MEMC_OP_APPEND: - if (!server_key) { - status = memcached_append(m_obj->memc, key, key_len, payload, payload_len, expiration, flags); + if (!server_key->val) { + status = memcached_append(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); } else { - status = memcached_append_by_key(m_obj->memc, server_key, server_key_len, key, - key_len, payload, payload_len, expiration, flags); + status = memcached_append_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + key->len, payload, payload_len, expiration, flags); } break; case MEMC_OP_PREPEND: - if (!server_key) { - status = memcached_prepend(m_obj->memc, key, key_len, payload, payload_len, expiration, flags); + if (!server_key->val) { + status = memcached_prepend(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); } else { - status = memcached_prepend_by_key(m_obj->memc, server_key, server_key_len, key, - key_len, payload, payload_len, expiration, flags); + status = memcached_prepend_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + key->len, payload, payload_len, expiration, flags); } break; @@ -1553,7 +1528,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool break; } - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { PHP_MEMC_FAILOVER_RETRY RETVAL_FALSE; } else { @@ -1571,10 +1546,8 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { double cas_d; uint64_t cas; - char *key = NULL; - int key_len = 0; - char *server_key = NULL; - int server_key_len = 0; + zend_string *key; + zend_string *server_key; zval *value; time_t expiration = 0; long udf_flags = 0; @@ -1585,13 +1558,13 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dssz|ll", &cas_d, &server_key, - &server_key_len, &key, &key_len, &value, &expiration, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "dSSz|ll", &cas_d, &server_key, &key, + &value, &expiration, &udf_flags) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dsz|ll", &cas_d, &key, &key_len, - &value, &expiration, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "dSz|ll", &cas_d, &key, &value, + &expiration, &udf_flags) == FAILURE) { return; } } @@ -1599,7 +1572,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || strchr(key, ' ')) { + if (key->len == 0 || strchr(key->val, ' ')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1616,24 +1589,24 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) */ if (udf_flags > 0) { if ((uint32_t) udf_flags > MEMC_VAL_USER_FLAGS_MAX) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %u", MEMC_VAL_USER_FLAGS_MAX); + php_error_docref(NULL, E_WARNING, "udf_flags will be limited to %u", MEMC_VAL_USER_FLAGS_MAX); } MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) udf_flags)); } - payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type TSRMLS_CC); + payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type); if (payload == NULL) { i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FALSE; } if (by_key) { - status = memcached_cas_by_key(m_obj->memc, server_key, server_key_len, key, key_len, payload, payload_len, expiration, flags, cas); + status = memcached_cas_by_key(m_obj->memc, server_key->val, server_key->len, key->val, key->len, payload, payload_len, expiration, flags, cas); } else { - status = memcached_cas(m_obj->memc, key, key_len, payload, payload_len, expiration, flags, cas); + status = memcached_cas(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags, cas); } efree(payload); - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { RETURN_FALSE; } @@ -1692,40 +1665,34 @@ PHP_METHOD(Memcached, deleteMultiByKey) /* {{{ -- php_memc_delete_impl */ static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { - char *key = NULL; - int key_len = 0; - char *server_key = NULL; - int server_key_len = 0; + zend_string *key, *server_key; time_t expiration = 0; memcached_return status; MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &server_key, - &server_key_len, &key, &key_len, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|l", &server_key, &key, &expiration) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &key, &key_len, - &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &key, &expiration) == FAILURE) { return; } - server_key = key; - server_key_len = key_len; + server_key = zend_string_copy(key); } MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || strchr(key, ' ')) { + if (key->len == 0 || strchr(key->val, ' ')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } - status = memcached_delete_by_key(m_obj->memc, server_key, server_key_len, key, - key_len, expiration); + status = memcached_delete_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + key->len, expiration); - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { RETURN_FALSE; } @@ -1737,21 +1704,19 @@ static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { zval *entries; - char *server_key = NULL; - int server_key_len = 0; + zend_string *server_key; time_t expiration = 0; - zval **entry; + zval *entry; memcached_return status; MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa/|l", &server_key, - &server_key_len, &entries, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|l", &server_key, &entries, &expiration) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/|l", &entries, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|l", &entries, &expiration) == FAILURE) { return; } } @@ -1760,31 +1725,28 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by i_obj->rescode = MEMCACHED_SUCCESS; array_init(return_value); - for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(entries)); - zend_hash_get_current_data(Z_ARRVAL_P(entries), (void**)&entry) == SUCCESS; - zend_hash_move_forward(Z_ARRVAL_P(entries))) { - - if (Z_TYPE_PP(entry) != IS_STRING) { + ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P(entries), entry) { + if (Z_TYPE_P(entry) != IS_STRING) { convert_to_string_ex(entry); } - if (Z_STRLEN_PP(entry) == 0) { + if (Z_STRLEN_P(entry) == 0) { continue; } - if (!by_key) { - server_key = Z_STRVAL_PP(entry); - server_key_len = Z_STRLEN_PP(entry); + if (by_key) { + status = memcached_delete_by_key(m_obj->memc, server_key->val, server_key->len, Z_STRVAL_P(entry), Z_STRLEN_P(entry), expiration); + } else { + status = memcached_delete_by_key(m_obj->memc, Z_STRVAL_P(entry), Z_STRLEN_P(entry), Z_STRVAL_P(entry), Z_STRLEN_P(entry), expiration); } - status = memcached_delete_by_key(m_obj->memc, server_key, server_key_len, Z_STRVAL_PP(entry), Z_STRLEN_PP(entry), expiration); - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { - add_assoc_long(return_value, Z_STRVAL_PP(entry), status); + if (php_memc_handle_error(i_obj, status) < 0) { + add_assoc_long(return_value, Z_STRVAL_P(entry), status); } else { - add_assoc_bool(return_value, Z_STRVAL_PP(entry), 1); + add_assoc_bool(return_value, Z_STRVAL_P(entry), 1); } - } + } ZEND_HASH_FOREACH_END(); return; } @@ -1793,8 +1755,7 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by /* {{{ -- php_memc_incdec_impl */ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, zend_bool incr) { - char *key, *server_key; - int key_len, server_key_len; + zend_string *key, *server_key; long offset = 1; uint64_t value, initial = 0; time_t expiry = 0; @@ -1805,11 +1766,11 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, MEMC_METHOD_INIT_VARS; if (!by_key) { - if (zend_parse_parameters(n_args TSRMLS_CC, "s|lll", &key, &key_len, &offset, &initial, &expiry) == FAILURE) { + if (zend_parse_parameters(n_args, "S|lll", &key, &offset, &initial, &expiry) == FAILURE) { return; } } else { - if (zend_parse_parameters(n_args TSRMLS_CC, "ss|lll", &server_key, &server_key_len, &key, &key_len, &offset, &initial, &expiry) == FAILURE) { + if (zend_parse_parameters(n_args, "SS|lll", &server_key, &key, &offset, &initial, &expiry) == FAILURE) { return; } } @@ -1817,13 +1778,13 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || strchr(key, ' ')) { + if (key->len == 0 || strchr(key->val, ' ')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } if (offset < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "offset has to be > 0"); + php_error_docref(NULL, E_WARNING, "offset has to be > 0"); RETURN_FALSE; } @@ -1831,38 +1792,38 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, if ((!by_key && n_args < 3) || (by_key && n_args < 4)) { if (by_key) { if (incr) { - status = memcached_increment_by_key(m_obj->memc, server_key, server_key_len, key, key_len, (unsigned int)offset, &value); + status = memcached_increment_by_key(m_obj->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, &value); } else { - status = memcached_decrement_by_key(m_obj->memc, server_key, server_key_len, key, key_len, (unsigned int)offset, &value); + status = memcached_decrement_by_key(m_obj->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, &value); } } else { if (incr) { - status = memcached_increment(m_obj->memc, key, key_len, (unsigned int)offset, &value); + status = memcached_increment(m_obj->memc, key->val, key->len, (unsigned int)offset, &value); } else { - status = memcached_decrement(m_obj->memc, key, key_len, (unsigned int)offset, &value); + status = memcached_decrement(m_obj->memc, key->val, key->len, (unsigned int)offset, &value); } } } else { if (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Initial value is only supported with binary protocol"); + php_error_docref(NULL, E_WARNING, "Initial value is only supported with binary protocol"); RETURN_FALSE; } if (by_key) { if (incr) { - status = memcached_increment_with_initial_by_key(m_obj->memc, server_key, server_key_len, key, key_len, (unsigned int)offset, initial, expiry, &value); + status = memcached_increment_with_initial_by_key(m_obj->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, initial, expiry, &value); } else { - status = memcached_decrement_with_initial_by_key(m_obj->memc, server_key, server_key_len, key, key_len, (unsigned int)offset, initial, expiry, &value); + status = memcached_decrement_with_initial_by_key(m_obj->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, initial, expiry, &value); } } else { if (incr) { - status = memcached_increment_with_initial(m_obj->memc, key, key_len, (unsigned int)offset, initial, expiry, &value); + status = memcached_increment_with_initial(m_obj->memc, key->val, key->len, (unsigned int)offset, initial, expiry, &value); } else { - status = memcached_decrement_with_initial(m_obj->memc, key, key_len, (unsigned int)offset, initial, expiry, &value); + status = memcached_decrement_with_initial(m_obj->memc, key->val, key->len, (unsigned int)offset, initial, expiry, &value); } } } - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { PHP_MEMC_FAILOVER_RETRY RETURN_FALSE; } @@ -1907,14 +1868,12 @@ PHP_METHOD(Memcached, incrementByKey) Adds the given memcache server to the list */ PHP_METHOD(Memcached, addServer) { - char *host; - int host_len; + zend_string *host; long port, weight = 0; memcached_return status; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|l", &host, &host_len, - &port, &weight) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sl|l", &host, &port, &weight) == FAILURE) { return; } @@ -1922,18 +1881,18 @@ PHP_METHOD(Memcached, addServer) i_obj->rescode = MEMCACHED_SUCCESS; #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000002 - if (host[0] == '/') { /* unix domain socket */ - status = memcached_server_add_unix_socket_with_weight(m_obj->memc, host, weight); + if (host->val[0] == '/') { /* unix domain socket */ + status = memcached_server_add_unix_socket_with_weight(m_obj->memc, host->val, weight); } else if (memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_USE_UDP)) { - status = memcached_server_add_udp_with_weight(m_obj->memc, host, port, weight); + status = memcached_server_add_udp_with_weight(m_obj->memc, host->val, port, weight); } else { - status = memcached_server_add_with_weight(m_obj->memc, host, port, weight); + status = memcached_server_add_with_weight(m_obj->memc, host->val, port, weight); } #else - status = memcached_server_add_with_weight(m_obj->memc, host, port, weight); + status = memcached_server_add_with_weight(m_obj->memc, host->val, port, weight); #endif - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { RETURN_FALSE; } @@ -1946,45 +1905,46 @@ PHP_METHOD(Memcached, addServer) PHP_METHOD(Memcached, addServers) { zval *servers; - zval **entry; - zval **z_host, **z_port, **z_weight = NULL; + zval *entry; + zval *z_host, *z_port, *z_weight = NULL; uint32_t weight = 0; + HashPosition pos; int entry_size, i = 0; memcached_server_st *list = NULL; memcached_return status; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &servers) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/", &servers) == FAILURE) { return; } MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(servers)), i = 0; - zend_hash_get_current_data(Z_ARRVAL_P(servers), (void **)&entry) == SUCCESS; - zend_hash_move_forward(Z_ARRVAL_P(servers)), i++) { - - if (Z_TYPE_PP(entry) != IS_ARRAY) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "server list entry #%d is not an array", i+1); + ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P(servers), entry) { + if (Z_TYPE_P(entry) != IS_ARRAY) { + php_error_docref(NULL, E_WARNING, "server list entry #%d is not an array", i+1); + i++; continue; } - entry_size = zend_hash_num_elements(Z_ARRVAL_PP(entry)); + entry_size = zend_hash_num_elements(Z_ARRVAL_P(entry)); if (entry_size > 1) { - zend_hash_internal_pointer_reset(Z_ARRVAL_PP(entry)); + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(entry), &pos); /* Check that we have a host */ - if (zend_hash_get_current_data(Z_ARRVAL_PP(entry), (void **)&z_host) == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not get server host for entry #%d", i+1); + if ((z_host = zend_hash_get_current_data_ex(Z_ARRVAL_P(entry), &pos)) == NULL) { + php_error_docref(NULL, E_WARNING, "could not get server host for entry #%d", i+1); + i++; continue; } /* Check that we have a port */ - if (zend_hash_move_forward(Z_ARRVAL_PP(entry)) == FAILURE || - zend_hash_get_current_data(Z_ARRVAL_PP(entry), (void **)&z_port) == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not get server port for entry #%d", i+1); + if (zend_hash_move_forward_ex(Z_ARRVAL_P(entry), &pos) == FAILURE || + (z_port = zend_hash_get_current_data_ex(Z_ARRVAL_P(entry), &pos)) == NULL) { + php_error_docref(NULL, E_WARNING, "could not get server port for entry #%d", i+1); + i++; continue; } @@ -1994,30 +1954,31 @@ PHP_METHOD(Memcached, addServers) weight = 0; if (entry_size > 2) { /* Try to get weight */ - if (zend_hash_move_forward(Z_ARRVAL_PP(entry)) == FAILURE || - zend_hash_get_current_data(Z_ARRVAL_PP(entry), (void **)&z_weight) == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not get server weight for entry #%d", i+1); + if (zend_hash_move_forward_ex(Z_ARRVAL_P(entry), &pos) == FAILURE || + (z_weight = zend_hash_get_current_data_ex(Z_ARRVAL_P(entry), &pos)) == NULL) { + php_error_docref(NULL, E_WARNING, "could not get server weight for entry #%d", i+1); } convert_to_long_ex(z_weight); - weight = Z_LVAL_PP(z_weight); + weight = Z_LVAL_P(z_weight); } - list = memcached_server_list_append_with_weight(list, Z_STRVAL_PP(z_host), - Z_LVAL_PP(z_port), weight, &status); + list = memcached_server_list_append_with_weight(list, Z_STRVAL_P(z_host), + Z_LVAL_P(z_port), weight, &status); - if (php_memc_handle_error(i_obj, status TSRMLS_CC) == 0) { + if (php_memc_handle_error(i_obj, status) == 0) { + i++; continue; } } - + i++; /* catch-all for all errors */ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not add entry #%d to the server list", i+1); - } + php_error_docref(NULL, E_WARNING, "could not add entry #%d to the server list", i+1); + } ZEND_HASH_FOREACH_END(); status = memcached_server_push(m_obj->memc, list); memcached_server_list_free(list); - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { RETURN_FALSE; } @@ -2025,7 +1986,6 @@ PHP_METHOD(Memcached, addServers) } /* }}} */ - /* {{{ Memcached::getServerList() Returns the list of the memcache servers in use */ PHP_METHOD(Memcached, getServerList) @@ -2051,32 +2011,31 @@ PHP_METHOD(Memcached, getServerList) Returns the server identified by the given server key */ PHP_METHOD(Memcached, getServerByKey) { - char *server_key; - int server_key_len; + zend_string *server_key; php_memcached_instance_st server_instance; memcached_return error; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &server_key, &server_key_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &server_key) == FAILURE) { return; } MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (server_key_len == 0 || strchr(server_key, ' ')) { + if (server_key->len == 0 || strchr(server_key->val, ' ')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } - server_instance = memcached_server_by_key(m_obj->memc, server_key, server_key_len, &error); + server_instance = memcached_server_by_key(m_obj->memc, server_key->val, server_key->len, &error); if (server_instance == NULL) { - php_memc_handle_error(i_obj, error TSRMLS_CC); + php_memc_handle_error(i_obj, error); RETURN_FALSE; } array_init(return_value); - add_assoc_string(return_value, "host", (char*) memcached_server_name(server_instance), 1); + add_assoc_string(return_value, "host", (char*) memcached_server_name(server_instance)); add_assoc_long(return_value, "port", memcached_server_port(server_instance)); add_assoc_long(return_value, "weight", 0); } @@ -2144,7 +2103,7 @@ PHP_METHOD(Memcached, getLastErrorMessage) MEMC_METHOD_FETCH_OBJECT; - RETURN_STRING(memcached_last_error_message(m_obj->memc), 1); + RETURN_STRING(memcached_last_error_message(m_obj->memc)); } /* }}} */ @@ -2201,7 +2160,7 @@ PHP_METHOD(Memcached, getLastDisconnectedServer) } array_init(return_value); - add_assoc_string(return_value, "host", (char*) memcached_server_name(server_instance), 1); + add_assoc_string(return_value, "host", (char*) memcached_server_name(server_instance)); add_assoc_long(return_value, "port", memcached_server_port(server_instance)); } /* }}} */ @@ -2228,7 +2187,7 @@ PHP_METHOD(Memcached, getStats) } stats = memcached_stat(m_obj->memc, NULL, &status); - php_memc_handle_error(i_obj, status TSRMLS_CC); + php_memc_handle_error(i_obj, status); if (stats == NULL) { RETURN_FALSE; } else if (status != MEMCACHED_SUCCESS && status != MEMCACHED_SOME_ERRORS) { @@ -2266,7 +2225,7 @@ PHP_METHOD(Memcached, getVersion) array_init(return_value); status = memcached_version(m_obj->memc); - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { zval_dtor(return_value); RETURN_FALSE; } @@ -2284,7 +2243,7 @@ static memcached_return php_memc_dump_func_callback(const memcached_st *ptr __at const char *key, size_t key_length, void *context) { zval *ctx = (zval*) context; - add_next_index_string(ctx, (char*) key, 1); + add_next_index_string(ctx, (char*) key); return MEMCACHED_SUCCESS; } @@ -2300,7 +2259,7 @@ PHP_METHOD(Memcached, getAllKeys) array_init(return_value); rc = memcached_dump(m_obj->memc, callback, return_value, 1); - if (php_memc_handle_error(i_obj, rc TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, rc) < 0) { zval_dtor(return_value); RETURN_FALSE; } @@ -2315,7 +2274,7 @@ static PHP_METHOD(Memcached, flush) memcached_return status; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &delay) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &delay) == FAILURE) { return; } @@ -2323,7 +2282,7 @@ static PHP_METHOD(Memcached, flush) i_obj->rescode = MEMCACHED_SUCCESS; status = memcached_flush(m_obj->memc, delay); - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { RETURN_FALSE; } @@ -2340,7 +2299,7 @@ static PHP_METHOD(Memcached, getOption) memcached_behavior flag; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &option) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &option) == FAILURE) { return; } @@ -2361,9 +2320,9 @@ static PHP_METHOD(Memcached, getOption) result = memcached_callback_get(m_obj->memc, MEMCACHED_CALLBACK_PREFIX_KEY, &retval); if (retval == MEMCACHED_SUCCESS && result) { #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX == 0x00049000 - RETURN_STRINGL(result, strlen(result) - 1, 1); + RETURN_STRINGL(result, strlen(result) - 1); #else - RETURN_STRING(result, 1); + RETURN_STRING(result); #endif } else { RETURN_EMPTY_STRING(); @@ -2381,7 +2340,7 @@ static PHP_METHOD(Memcached, getOption) case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE: case MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE: if (memcached_server_count(m_obj->memc) == 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "no servers defined"); + php_error_docref(NULL, E_WARNING, "no servers defined"); return; } @@ -2396,7 +2355,7 @@ static PHP_METHOD(Memcached, getOption) } /* }}} */ -static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRMLS_DC) +static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value) { memcached_return rc = MEMCACHED_FAILURE; memcached_behavior flag; @@ -2443,7 +2402,7 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML } if (memcached_callback_set(m_obj->memc, MEMCACHED_CALLBACK_PREFIX_KEY, key) == MEMCACHED_BAD_KEY_PROVIDED) { i_obj->rescode = MEMCACHED_INVALID_ARGUMENTS; - php_error_docref(NULL TSRMLS_CC, E_WARNING, "bad key provided"); + php_error_docref(NULL, E_WARNING, "bad key provided"); return 0; } } @@ -2455,8 +2414,8 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML convert_to_long(value); rc = memcached_behavior_set(m_obj->memc, flag, (uint64_t) Z_LVAL_P(value)); - if (php_memc_handle_error(i_obj, rc TSRMLS_CC) < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "error setting memcached option: %s", memcached_strerror (m_obj->memc, rc)); + if (php_memc_handle_error(i_obj, rc) < 0) { + php_error_docref(NULL, E_WARNING, "error setting memcached option: %s", memcached_strerror (m_obj->memc, rc)); return 0; } @@ -2505,7 +2464,7 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML } else { m_obj->serializer = SERIALIZER_PHP; i_obj->rescode = MEMCACHED_INVALID_ARGUMENTS; - php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid serializer provided"); + php_error_docref(NULL, E_WARNING, "invalid serializer provided"); return 0; } break; @@ -2535,8 +2494,8 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML } } - if (php_memc_handle_error(i_obj, rc TSRMLS_CC) < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "error setting memcached option: %s", memcached_strerror (m_obj->memc, rc)); + if (php_memc_handle_error(i_obj, rc) < 0) { + php_error_docref(NULL, E_WARNING, "error setting memcached option: %s", memcached_strerror (m_obj->memc, rc)); return 0; } break; @@ -2545,9 +2504,9 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value TSRML } static -uint32_t *s_zval_to_uint32_array (zval *input, size_t *num_elements TSRMLS_DC) +uint32_t *s_zval_to_uint32_array (zval *input, size_t *num_elements) { - zval **ppzval; + zval *pzval; uint32_t *retval; size_t i = 0; @@ -2559,20 +2518,17 @@ uint32_t *s_zval_to_uint32_array (zval *input, size_t *num_elements TSRMLS_DC) retval = ecalloc(*num_elements, sizeof(uint32_t)); - for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(input)); - zend_hash_get_current_data(Z_ARRVAL_P(input), (void **) &ppzval) == SUCCESS; - zend_hash_move_forward(Z_ARRVAL_P(input)), i++) { - + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(input), pzval) { long value = 0; - if (Z_TYPE_PP(ppzval) == IS_LONG) { - value = Z_LVAL_PP(ppzval); + if (Z_TYPE_P(pzval) == IS_LONG) { + value = Z_LVAL_P(pzval); } else { - zval tmp_zval, *tmp_pzval; - tmp_zval = **ppzval; - zval_copy_ctor(&tmp_zval); - tmp_pzval = &tmp_zval; + zval *tmp_zval, *tmp_pzval; + tmp_zval = pzval; + zval_copy_ctor(tmp_zval); + tmp_pzval = tmp_zval; convert_to_long(tmp_pzval); value = (Z_LVAL_P(tmp_pzval) > 0) ? Z_LVAL_P(tmp_pzval) : 0; @@ -2580,13 +2536,14 @@ uint32_t *s_zval_to_uint32_array (zval *input, size_t *num_elements TSRMLS_DC) } if (value < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "the map must contain positive integers"); + php_error_docref(NULL, E_WARNING, "the map must contain positive integers"); efree (retval); *num_elements = 0; return NULL; } retval [i] = (uint32_t) value; - } + i++; + } ZEND_HASH_FOREACH_END(); return retval; } @@ -2605,35 +2562,35 @@ PHP_METHOD(Memcached, setBucket) memcached_return rc; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aa!l", &zserver_map, &zforward_map, &replicas) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "aa!l", &zserver_map, &zforward_map, &replicas) == FAILURE) { return; } MEMC_METHOD_FETCH_OBJECT; if (zend_hash_num_elements (Z_ARRVAL_P(zserver_map)) == 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "server map cannot be empty"); + php_error_docref(NULL, E_WARNING, "server map cannot be empty"); RETURN_FALSE; } if (zforward_map && zend_hash_num_elements (Z_ARRVAL_P(zserver_map)) != zend_hash_num_elements (Z_ARRVAL_P(zforward_map))) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "forward_map length must match the server_map length"); + php_error_docref(NULL, E_WARNING, "forward_map length must match the server_map length"); RETURN_FALSE; } if (replicas < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "replicas must be larger than zero"); + php_error_docref(NULL, E_WARNING, "replicas must be larger than zero"); RETURN_FALSE; } - server_map = s_zval_to_uint32_array (zserver_map, &server_map_len TSRMLS_CC); + server_map = s_zval_to_uint32_array (zserver_map, &server_map_len); if (!server_map) { RETURN_FALSE; } if (zforward_map) { - forward_map = s_zval_to_uint32_array (zforward_map, &forward_map_len TSRMLS_CC); + forward_map = s_zval_to_uint32_array (zforward_map, &forward_map_len); if (!forward_map) { efree (server_map); @@ -2643,7 +2600,7 @@ PHP_METHOD(Memcached, setBucket) rc = memcached_bucket_set (m_obj->memc, server_map, forward_map, (uint32_t) server_map_len, replicas); - if (php_memc_handle_error(i_obj, rc TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, rc) < 0) { retval = 0;; } @@ -2662,38 +2619,33 @@ static PHP_METHOD(Memcached, setOptions) { zval *options; zend_bool ok = 1; - uint key_len; - char *key; + zend_string *key; ulong key_index; - zval **value; + zval *value; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &options) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &options) == FAILURE) { return; } MEMC_METHOD_FETCH_OBJECT; - for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(options)); - zend_hash_get_current_data(Z_ARRVAL_P(options), (void *) &value) == SUCCESS; - zend_hash_move_forward(Z_ARRVAL_P(options))) { - - if (zend_hash_get_current_key_ex(Z_ARRVAL_P(options), &key, &key_len, &key_index, 0, NULL) == HASH_KEY_IS_LONG) { - zval copy = **value; - zval_copy_ctor(©); - INIT_PZVAL(©); + ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(options), key_index, key, value) { + if (key) { + php_error_docref(NULL, E_WARNING, "invalid configuration option"); + ok = 0; + } else { + zval copy; + ZVAL_DUP(©, value); - if (!php_memc_set_option(i_obj, (long) key_index, © TSRMLS_CC)) { + if (!php_memc_set_option(i_obj, (long) key_index, ©)) { ok = 0; } zval_dtor(©); - } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid configuration option"); - ok = 0; } - } + } ZEND_HASH_FOREACH_END(); RETURN_BOOL(ok); } @@ -2707,13 +2659,13 @@ static PHP_METHOD(Memcached, setOption) zval *value; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz/", &option, &value) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "lz/", &option, &value) == FAILURE) { return; } MEMC_METHOD_FETCH_OBJECT; - RETURN_BOOL(php_memc_set_option(i_obj, option, value TSRMLS_CC)); + RETURN_BOOL(php_memc_set_option(i_obj, option, value)); } /* }}} */ @@ -2724,29 +2676,27 @@ static PHP_METHOD(Memcached, setSaslAuthData) { MEMC_METHOD_INIT_VARS; memcached_return status; + zend_string *user, *pass; - char *user, *pass; - int user_len, pass_len; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &user, &user_len, &pass, &pass_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &user, &pass) == FAILURE) { return; } if (!MEMC_G(use_sasl)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "SASL support (memcached.use_sasl) isn't enabled in php.ini"); + php_error_docref(NULL, E_WARNING, "SASL support (memcached.use_sasl) isn't enabled in php.ini"); RETURN_FALSE; } MEMC_METHOD_FETCH_OBJECT; if (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "SASL is only supported with binary protocol"); + php_error_docref(NULL, E_WARNING, "SASL is only supported with binary protocol"); RETURN_FALSE; } m_obj->has_sasl_data = 1; - status = memcached_set_sasl_auth_data(m_obj->memc, user, pass); + status = memcached_set_sasl_auth_data(m_obj->memc, user->val, pass->val); - if (php_memc_handle_error(i_obj, status TSRMLS_CC) < 0) { + if (php_memc_handle_error(i_obj, status) < 0) { RETURN_FALSE; } RETURN_TRUE; @@ -2784,7 +2734,7 @@ static PHP_METHOD(Memcached, getResultMessage) switch (i_obj->rescode) { case MEMC_RES_PAYLOAD_FAILURE: - RETURN_STRING("PAYLOAD FAILURE", 1); + RETURN_STRING("PAYLOAD FAILURE"); break; case MEMCACHED_ERRNO: @@ -2795,11 +2745,11 @@ static PHP_METHOD(Memcached, getResultMessage) int str_len; str_len = spprintf(&str, 0, "%s: %s", memcached_strerror(m_obj->memc, (memcached_return)i_obj->rescode), strerror(i_obj->memc_errno)); - RETURN_STRINGL(str, str_len, 0); + RETURN_STRINGL(str, str_len); } /* Fall through */ default: - RETURN_STRING(memcached_strerror(m_obj->memc, (memcached_return)i_obj->rescode), 1); + RETURN_STRING(memcached_strerror(m_obj->memc, (memcached_return)i_obj->rescode)); break; } @@ -2843,7 +2793,7 @@ static PHP_METHOD(Memcached, isPristine) ****************************************/ /* {{{ constructor/destructor */ -static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent TSRMLS_DC) +static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent) { #if HAVE_MEMCACHED_SASL if (m_obj->has_sasl_data) { @@ -2857,56 +2807,47 @@ static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent TSRMLS pefree(m_obj, persistent); } -static void php_memc_free_storage(php_memc_t *i_obj TSRMLS_DC) +static void php_memc_free_storage(zend_object *obj) { - zend_object_std_dtor(&i_obj->zo TSRMLS_CC); - + php_memc_t *i_obj = php_memc_fetch_object(obj); + if (i_obj->obj && !i_obj->is_persistent) { - php_memc_destroy(i_obj->obj, 0 TSRMLS_CC); + php_memc_destroy(i_obj->obj, 0); } + zend_object_std_dtor(&i_obj->zo); i_obj->obj = NULL; efree(i_obj); } -zend_object_value php_memc_new(zend_class_entry *ce TSRMLS_DC) +zend_object *php_memc_new(zend_class_entry *ce) { - zend_object_value retval; - php_memc_t *i_obj; - - i_obj = ecalloc(1, sizeof(*i_obj)); - zend_object_std_init( &i_obj->zo, ce TSRMLS_CC ); -#if PHP_VERSION_ID >= 50400 - object_properties_init( (zend_object *) i_obj, ce); -#else - { - zval *tmp; - zend_hash_copy(i_obj->zo.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); - } -#endif - - retval.handle = zend_objects_store_put(i_obj, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)php_memc_free_storage, NULL TSRMLS_CC); - retval.handlers = &memcached_object_handlers; - - return retval; + php_memc_t *i_obj = ecalloc(1, sizeof(php_memc_t) + sizeof(zval) * (ce->default_properties_count - 1)); + + zend_object_std_init(&i_obj->zo, ce); + object_properties_init(&i_obj->zo, ce); + + i_obj->zo.handlers = &memcached_object_handlers; + + return &i_obj->zo; } #ifdef HAVE_MEMCACHED_PROTOCOL static -void php_memc_server_free_storage(php_memc_server_t *intern TSRMLS_DC) +void php_memc_server_free_storage(php_memc_server_t *intern) { - zend_object_std_dtor(&intern->zo TSRMLS_CC); + zend_object_std_dtor(&intern->zo); efree (intern); } -zend_object_value php_memc_server_new(zend_class_entry *ce TSRMLS_DC) +zend_object_value php_memc_server_new(zend_class_entry *ce) { zend_object_value retval; php_memc_server_t *intern; zval *tmp; intern = ecalloc(1, sizeof(php_memc_server_t)); - zend_object_std_init (&intern->zo, ce TSRMLS_CC); + zend_object_std_init (&intern->zo, ce); #if PHP_VERSION_ID >= 50400 object_properties_init( (zend_object *) intern, ce); #else @@ -2915,7 +2856,7 @@ zend_object_value php_memc_server_new(zend_class_entry *ce TSRMLS_DC) intern->handler = php_memc_proto_handler_new (); - retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)php_memc_server_free_storage, NULL TSRMLS_CC); + retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)php_memc_server_free_storage, NULL); retval.handlers = &memcached_server_object_handlers; return retval; @@ -2924,20 +2865,20 @@ zend_object_value php_memc_server_new(zend_class_entry *ce TSRMLS_DC) ZEND_RSRC_DTOR_FUNC(php_memc_dtor) { - if (rsrc->ptr) { - struct memc_obj *m_obj = (struct memc_obj *)rsrc->ptr; - php_memc_destroy(m_obj, 1 TSRMLS_CC); - rsrc->ptr = NULL; + if (res->ptr) { + struct memc_obj *m_obj = (struct memc_obj *)res->ptr; + php_memc_destroy(m_obj, 1); + res->ptr = NULL; } } ZEND_RSRC_DTOR_FUNC(php_memc_sess_dtor) { - if (rsrc->ptr) { - memcached_sess *memc_sess = (memcached_sess *)rsrc->ptr; + if (res->ptr) { + memcached_sess *memc_sess = (memcached_sess *)res->ptr; memcached_free(memc_sess->memc_sess); - pefree(rsrc->ptr, 1); - rsrc->ptr = NULL; + pefree(res->ptr, 1); + res->ptr = NULL; } } /* }}} */ @@ -2946,18 +2887,17 @@ ZEND_RSRC_DTOR_FUNC(php_memc_sess_dtor) static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) { struct callbackContext* context = (struct callbackContext*) in_context; - zval *array; + zval array; - MAKE_STD_ZVAL(array); - array_init(array); - add_assoc_string(array, "host", (char*) memcached_server_name(instance), 1); - add_assoc_long(array, "port", memcached_server_port(instance)); + array_init(&array); + add_assoc_string(&array, "host", (char*) memcached_server_name(instance)); + add_assoc_long(&array, "port", memcached_server_port(instance)); /* * API does not allow to get at this field. add_assoc_long(array, "weight", instance->weight); */ - add_next_index_zval(context->return_value, array); + add_next_index_zval(context->return_value, &array); return MEMCACHED_SUCCESS; } @@ -2966,38 +2906,37 @@ static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, php_ char *hostport = NULL; int hostport_len; struct callbackContext* context = (struct callbackContext*) in_context; - zval *entry; - hostport_len = spprintf(&hostport, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance)); - - MAKE_STD_ZVAL(entry); - array_init(entry); - - add_assoc_long(entry, "pid", context->stats[context->i].pid); - add_assoc_long(entry, "uptime", context->stats[context->i].uptime); - add_assoc_long(entry, "threads", context->stats[context->i].threads); - add_assoc_long(entry, "time", context->stats[context->i].time); - add_assoc_long(entry, "pointer_size", context->stats[context->i].pointer_size); - add_assoc_long(entry, "rusage_user_seconds", context->stats[context->i].rusage_user_seconds); - add_assoc_long(entry, "rusage_user_microseconds", context->stats[context->i].rusage_user_microseconds); - add_assoc_long(entry, "rusage_system_seconds", context->stats[context->i].rusage_system_seconds); - add_assoc_long(entry, "rusage_system_microseconds", context->stats[context->i].rusage_system_microseconds); - add_assoc_long(entry, "curr_items", context->stats[context->i].curr_items); - add_assoc_long(entry, "total_items", context->stats[context->i].total_items); - add_assoc_long(entry, "limit_maxbytes", context->stats[context->i].limit_maxbytes); - add_assoc_long(entry, "curr_connections", context->stats[context->i].curr_connections); - add_assoc_long(entry, "total_connections", context->stats[context->i].total_connections); - add_assoc_long(entry, "connection_structures", context->stats[context->i].connection_structures); - add_assoc_long(entry, "bytes", context->stats[context->i].bytes); - add_assoc_long(entry, "cmd_get", context->stats[context->i].cmd_get); - add_assoc_long(entry, "cmd_set", context->stats[context->i].cmd_set); - add_assoc_long(entry, "get_hits", context->stats[context->i].get_hits); - add_assoc_long(entry, "get_misses", context->stats[context->i].get_misses); - add_assoc_long(entry, "evictions", context->stats[context->i].evictions); - add_assoc_long(entry, "bytes_read", context->stats[context->i].bytes_read); - add_assoc_long(entry, "bytes_written", context->stats[context->i].bytes_written); - add_assoc_stringl(entry, "version", context->stats[context->i].version, strlen(context->stats[context->i].version), 1); - - add_assoc_zval_ex(context->return_value, hostport, hostport_len+1, entry); + zval entry; + hostport_len = spprintf(&hostport, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance) - 1); + + array_init(&entry); + + add_assoc_long(&entry, "pid", context->stats[context->i].pid); + add_assoc_long(&entry, "uptime", context->stats[context->i].uptime); + add_assoc_long(&entry, "threads", context->stats[context->i].threads); + add_assoc_long(&entry, "time", context->stats[context->i].time); + add_assoc_long(&entry, "pointer_size", context->stats[context->i].pointer_size); + add_assoc_long(&entry, "rusage_user_seconds", context->stats[context->i].rusage_user_seconds); + add_assoc_long(&entry, "rusage_user_microseconds", context->stats[context->i].rusage_user_microseconds); + add_assoc_long(&entry, "rusage_system_seconds", context->stats[context->i].rusage_system_seconds); + add_assoc_long(&entry, "rusage_system_microseconds", context->stats[context->i].rusage_system_microseconds); + add_assoc_long(&entry, "curr_items", context->stats[context->i].curr_items); + add_assoc_long(&entry, "total_items", context->stats[context->i].total_items); + add_assoc_long(&entry, "limit_maxbytes", context->stats[context->i].limit_maxbytes); + add_assoc_long(&entry, "curr_connections", context->stats[context->i].curr_connections); + add_assoc_long(&entry, "total_connections", context->stats[context->i].total_connections); + add_assoc_long(&entry, "connection_structures", context->stats[context->i].connection_structures); + add_assoc_long(&entry, "bytes", context->stats[context->i].bytes); + add_assoc_long(&entry, "cmd_get", context->stats[context->i].cmd_get); + add_assoc_long(&entry, "cmd_set", context->stats[context->i].cmd_set); + add_assoc_long(&entry, "get_hits", context->stats[context->i].get_hits); + add_assoc_long(&entry, "get_misses", context->stats[context->i].get_misses); + add_assoc_long(&entry, "evictions", context->stats[context->i].evictions); + add_assoc_long(&entry, "bytes_read", context->stats[context->i].bytes_read); + add_assoc_long(&entry, "bytes_written", context->stats[context->i].bytes_written); + add_assoc_stringl(&entry, "version", context->stats[context->i].version, strlen(context->stats[context->i].version)); + + add_assoc_zval_ex(context->return_value, hostport, hostport_len+1, &entry); efree(hostport); /* Increment the server count in our context structure. Failure to do so will cause only the stats for the last server to get displayed. */ @@ -3012,7 +2951,7 @@ static memcached_return php_memc_do_version_callback(const memcached_st *ptr, ph int hostport_len, version_len; struct callbackContext* context = (struct callbackContext*) in_context; - hostport_len = spprintf(&hostport, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance)); + hostport_len = spprintf(&hostport, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance) - 1); #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000009 version_len = snprintf(version, sizeof(version), "%d.%d.%d", memcached_server_major_version(instance), @@ -3025,12 +2964,12 @@ static memcached_return php_memc_do_version_callback(const memcached_st *ptr, ph instance->micro_version); #endif - add_assoc_stringl_ex(context->return_value, hostport, hostport_len+1, version, version_len, 1); + add_assoc_stringl_ex(context->return_value, hostport, hostport_len+1, version, version_len); efree(hostport); return MEMCACHED_SUCCESS; } -static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status TSRMLS_DC) +static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status) { int result = 0; @@ -3077,7 +3016,7 @@ static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status TSRM } static -char *s_compress_value (enum memcached_compression_type compression_type, const char *payload, size_t *payload_len, uint32_t *flags TSRMLS_DC) +char *s_compress_value (enum memcached_compression_type compression_type, const char *payload, size_t *payload_len, uint32_t *flags) { /* status */ zend_bool compress_status = 0; @@ -3117,7 +3056,7 @@ char *s_compress_value (enum memcached_compression_type compression_type, const *payload_len = compressed_size + sizeof(uint32_t); if (!compress_status) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not compress value"); + php_error_docref(NULL, E_WARNING, "could not compress value"); MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); efree (buffer); @@ -3135,7 +3074,7 @@ char *s_compress_value (enum memcached_compression_type compression_type, const } static -zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, smart_str *buf, uint32_t *flags TSRMLS_DC) +zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, smart_str *buf, uint32_t *flags) { switch (serializer) { @@ -3144,8 +3083,8 @@ zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, */ #ifdef HAVE_MEMCACHED_IGBINARY case SERIALIZER_IGBINARY: - if (igbinary_serialize((uint8_t **) &buf->c, &buf->len, value TSRMLS_CC) != 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not serialize value with igbinary"); + if (igbinary_serialize((uint8_t **) &buf->c, &buf->len, value) != 0) { + php_error_docref(NULL, E_WARNING, "could not serialize value with igbinary"); return 0; } MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_IGBINARY); @@ -3160,9 +3099,9 @@ zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, case SERIALIZER_JSON_ARRAY: { #if HAVE_JSON_API_5_2 - php_json_encode(buf, value TSRMLS_CC); + php_json_encode(buf, value); #elif HAVE_JSON_API_5_3 - php_json_encode(buf, value, 0 TSRMLS_CC); /* options */ + php_json_encode(buf, value, 0); /* options */ #endif MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_JSON); } @@ -3174,9 +3113,9 @@ zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, */ #ifdef HAVE_MEMCACHED_MSGPACK case SERIALIZER_MSGPACK: - php_msgpack_serialize(buf, value TSRMLS_CC); + php_msgpack_serialize(buf, value); if (!buf->c) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not serialize value with msgpack"); + php_error_docref(NULL, E_WARNING, "could not serialize value with msgpack"); return 0; } MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_MSGPACK); @@ -3190,11 +3129,11 @@ zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, { php_serialize_data_t var_hash; PHP_VAR_SERIALIZE_INIT(var_hash); - php_var_serialize(buf, &value, &var_hash TSRMLS_CC); + php_var_serialize(buf, value, &var_hash); PHP_VAR_SERIALIZE_DESTROY(var_hash); - if (!buf->c) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not serialize value"); + if (!buf->s) { + php_error_docref(NULL, E_WARNING, "could not serialize value"); return 0; } MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_SERIALIZED); @@ -3203,14 +3142,14 @@ zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, } /* Check for exceptions caused by serializers */ - if (EG(exception) && buf->len) { + if (EG(exception) && buf->s->len) { return 0; } return 1; } static -char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type TSRMLS_DC) +char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type) { const char *pl; size_t pl_len = 0; @@ -3240,26 +3179,28 @@ char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_DOUBLE); break; - case IS_BOOL: - if (Z_BVAL_P(value)) { - pl_len = 1; - tmp[0] = '1'; - tmp[1] = '\0'; - } else { - pl_len = 0; - tmp[0] = '\0'; - } + case IS_TRUE: + pl_len = 1; + tmp[0] = '1'; + tmp[1] = '\0'; + pl = tmp; + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_BOOL); + break; + + case IS_FALSE: + pl_len = 0; + tmp[0] = '\0'; pl = tmp; MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_BOOL); break; default: - if (!s_serialize_value (serializer, value, &buf, flags TSRMLS_CC)) { + if (!s_serialize_value (serializer, value, &buf, flags)) { smart_str_free (&buf); return NULL; } - pl = buf.c; - pl_len = buf.len; + pl = buf.s->val; + pl_len = buf.s->len; break; } @@ -3272,7 +3213,7 @@ char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags if (MEMC_VAL_HAS_FLAG(*flags, MEMC_VAL_COMPRESSED)) { /* status */ *payload_len = pl_len; - payload = s_compress_value (compression_type, pl, payload_len, flags TSRMLS_CC); + payload = s_compress_value (compression_type, pl, payload_len, flags); } /* If compression failed or value is below threshold we just use plain value */ @@ -3281,14 +3222,14 @@ char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags payload = estrndup(pl, pl_len); } - if (buf.len) { + if (buf.s) { smart_str_free(&buf); } return payload; } static -char *s_decompress_value (const char *payload, size_t *payload_len, uint32_t flags TSRMLS_DC) +char *s_decompress_value (const char *payload, size_t *payload_len, uint32_t flags) { char *buffer = NULL; uint32_t len; @@ -3329,7 +3270,7 @@ char *s_decompress_value (const char *payload, size_t *payload_len, uint32_t fla } if (!decompress_status) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not decompress value"); + php_error_docref(NULL, E_WARNING, "could not decompress value"); efree(buffer); return NULL; } @@ -3339,7 +3280,7 @@ char *s_decompress_value (const char *payload, size_t *payload_len, uint32_t fla } static -zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_type, zval *value, const char *payload, size_t payload_len TSRMLS_DC) +zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_type, zval *value, const char *payload, size_t payload_len) { switch (val_type) { case MEMC_VAL_IS_SERIALIZED: @@ -3348,10 +3289,10 @@ zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_typ php_unserialize_data_t var_hash; PHP_VAR_UNSERIALIZE_INIT(var_hash); - if (!php_var_unserialize(&value, (const unsigned char **)&payload_tmp, (const unsigned char *)payload_tmp + payload_len, &var_hash TSRMLS_CC)) { + if (!php_var_unserialize(value, (const unsigned char **)&payload_tmp, (const unsigned char *)payload_tmp + payload_len, &var_hash)) { ZVAL_FALSE(value); PHP_VAR_UNSERIALIZE_DESTROY(var_hash); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value"); + php_error_docref(NULL, E_WARNING, "could not unserialize value"); return 0; } PHP_VAR_UNSERIALIZE_DESTROY(var_hash); @@ -3360,14 +3301,14 @@ zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_typ case MEMC_VAL_IS_IGBINARY: #ifdef HAVE_MEMCACHED_IGBINARY - if (igbinary_unserialize((uint8_t *)payload, payload_len, &value TSRMLS_CC)) { + if (igbinary_unserialize((uint8_t *)payload, payload_len, &value)) { ZVAL_FALSE(value); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value with igbinary"); + php_error_docref(NULL, E_WARNING, "could not unserialize value with igbinary"); return 0; } #else ZVAL_FALSE(value); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value, no igbinary support"); + php_error_docref(NULL, E_WARNING, "could not unserialize value, no igbinary support"); return 0; #endif break; @@ -3375,23 +3316,23 @@ zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_typ case MEMC_VAL_IS_JSON: #ifdef HAVE_JSON_API # if HAVE_JSON_API_5_2 - php_json_decode(value, payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY) TSRMLS_CC); + php_json_decode(value, payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY)); # elif HAVE_JSON_API_5_3 - php_json_decode(value, payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY), JSON_PARSER_DEFAULT_DEPTH TSRMLS_CC); + php_json_decode(value, payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY), JSON_PARSER_DEFAULT_DEPTH); # endif #else ZVAL_FALSE(value); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value, no json support"); + php_error_docref(NULL, E_WARNING, "could not unserialize value, no json support"); return 0; #endif break; case MEMC_VAL_IS_MSGPACK: #ifdef HAVE_MEMCACHED_MSGPACK - php_msgpack_unserialize(value, payload, payload_len TSRMLS_CC); + php_msgpack_unserialize(value, payload, payload_len); #else ZVAL_FALSE(value); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not unserialize value, no msgpack support"); + php_error_docref(NULL, E_WARNING, "could not unserialize value, no msgpack support"); return 0; #endif break; @@ -3400,7 +3341,7 @@ zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_typ } /* The caller MUST free the payload */ -static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_t payload_len, uint32_t flags, enum memcached_serializer serializer TSRMLS_DC) +static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_t payload_len, uint32_t flags, enum memcached_serializer serializer) { /* A NULL payload is completely valid if length is 0, it is simply empty. @@ -3411,7 +3352,7 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ if (payload_in == NULL && payload_len > 0) { ZVAL_FALSE(value); - php_error_docref(NULL TSRMLS_CC, E_WARNING, + php_error_docref(NULL, E_WARNING, "Could not handle non-existing value of length %zu", payload_len); return -1; } else if (payload_in == NULL) { @@ -3424,7 +3365,7 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ } if (MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSED)) { - char *datas = s_decompress_value (payload_in, &payload_len, flags TSRMLS_CC); + char *datas = s_decompress_value (payload_in, &payload_len, flags); if (!datas) { ZVAL_FALSE(value); return -1; @@ -3438,10 +3379,10 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ switch (MEMC_VAL_GET_TYPE(flags)) { case MEMC_VAL_IS_STRING: if (payload_emalloc) { - ZVAL_STRINGL(value, pl, payload_len, 0); + ZVAL_STRINGL(value, pl, payload_len); payload_emalloc = 0; } else { - ZVAL_STRINGL(value, pl, payload_len, 1); + ZVAL_STRINGL(value, pl, payload_len); } break; @@ -3451,7 +3392,7 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ char conv_buf [128]; if (payload_len >= 128) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not read long value, too big"); + php_error_docref(NULL, E_WARNING, "could not read long value, too big"); retval = -1; } else { @@ -3469,7 +3410,7 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ char conv_buf [128]; if (payload_len >= 128) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not read double value, too big"); + php_error_docref(NULL, E_WARNING, "could not read double value, too big"); retval = -1; } else { @@ -3497,14 +3438,14 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ case MEMC_VAL_IS_IGBINARY: case MEMC_VAL_IS_JSON: case MEMC_VAL_IS_MSGPACK: - if (!s_unserialize_value (serializer, MEMC_VAL_GET_TYPE(flags), value, pl, payload_len TSRMLS_CC)) { + if (!s_unserialize_value (serializer, MEMC_VAL_GET_TYPE(flags), value, pl, payload_len)) { retval = -1; } break; default: ZVAL_FALSE(value); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "unknown payload type"); + php_error_docref(NULL, E_WARNING, "unknown payload type"); retval = -1; break; } @@ -3528,17 +3469,20 @@ zend_class_entry *php_memc_get_exception(void) } PHP_MEMCACHED_API -zend_class_entry *php_memc_get_exception_base(int root TSRMLS_DC) +zend_class_entry *php_memc_get_exception_base(int root) { #if HAVE_SPL if (!root) { if (!spl_ce_RuntimeException) { - zend_class_entry **pce; - - if (zend_hash_find(CG(class_table), "runtimeexception", - sizeof("RuntimeException"), (void **) &pce) == SUCCESS) { - spl_ce_RuntimeException = *pce; - return *pce; + zend_class_entry *pce; + zval *pce_z; + + if ((pce_z = zend_hash_str_find(CG(class_table), + "runtimeexception", + sizeof("RuntimeException") - 1)) != NULL) { + pce = Z_CE_P(pce_z); + spl_ce_RuntimeException = pce; + return pce; } } else { return spl_ce_RuntimeException; @@ -3548,20 +3492,19 @@ zend_class_entry *php_memc_get_exception_base(int root TSRMLS_DC) #if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION < 2) return zend_exception_get_default(); #else - return zend_exception_get_default(TSRMLS_C); + return zend_exception_get_default(); #endif } static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_info *fci, - zend_fcall_info_cache *fcc, char *key, - size_t key_len, zval *value TSRMLS_DC) + zend_fcall_info_cache *fcc, zend_string *key, zval *value) { char *payload = NULL; size_t payload_len = 0; - zval **params[4]; - zval *retval; - zval *z_key; - zval *z_expiration; + zval params[4]; + zval retval; + zval z_key; + zval z_expiration; uint32_t flags = 0; memcached_return rc; @@ -3569,40 +3512,38 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i memcached_return status = MEMCACHED_SUCCESS; int result; - MAKE_STD_ZVAL(z_key); - MAKE_STD_ZVAL(z_expiration); - ZVAL_STRINGL(z_key, key, key_len, 1); + ZVAL_STR(&z_key, key); ZVAL_NULL(value); - ZVAL_LONG(z_expiration, 0); + ZVAL_LONG(&z_expiration, 0); - params[0] = &zmemc_obj; - params[1] = &z_key; - params[2] = &value; - params[3] = &z_expiration; + ZVAL_COPY(¶ms[0], zmemc_obj); + ZVAL_COPY(¶ms[1], &z_key); + ZVAL_COPY(¶ms[2], value); + ZVAL_COPY(¶ms[3], &z_expiration); - fci->retval_ptr_ptr = &retval; + fci->retval = &retval; fci->params = params; - fci->param_count = sizeof(params) / sizeof(params[0]); + fci->param_count = 4; - result = zend_call_function(fci, fcc TSRMLS_CC); - if (result == SUCCESS && retval) { - i_obj = (php_memc_t *) zend_object_store_get_object(zmemc_obj TSRMLS_CC); + result = zend_call_function(fci, fcc); + if (result == SUCCESS && Z_TYPE(retval) != IS_UNDEF) { + i_obj = (php_memc_t *) Z_OBJ_P(zmemc_obj); struct memc_obj *m_obj = i_obj->obj; - if (zend_is_true(retval)) { + if (zend_is_true(&retval)) { time_t expiration; - if (Z_TYPE_P(z_expiration) != IS_LONG) { - convert_to_long(z_expiration); + if (Z_TYPE(z_expiration) != IS_LONG) { + convert_to_long(&z_expiration); } - expiration = Z_LVAL_P(z_expiration); + expiration = Z_LVAL(z_expiration); - payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type TSRMLS_CC); + payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type); if (payload == NULL) { status = (memcached_return)MEMC_RES_PAYLOAD_FAILURE; } else { - rc = memcached_set(m_obj->memc, key, key_len, payload, payload_len, expiration, flags); + rc = memcached_set(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED) { status = rc; } @@ -3616,14 +3557,16 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i } else { if (result == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not invoke cache callback"); + zval_ptr_dtor(&z_key); + zval_ptr_dtor(&z_expiration); + php_error_docref(NULL, E_WARNING, "could not invoke cache callback"); } status = MEMCACHED_FAILURE; zval_dtor(value); ZVAL_NULL(value); } - if (retval) { + if (&retval) { zval_ptr_dtor(&retval); } @@ -3635,24 +3578,23 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, - memcached_result_st *result TSRMLS_DC) + memcached_result_st *result) { const char *res_key = NULL; size_t res_key_len = 0; const char *payload = NULL; size_t payload_len = 0; - zval *value, *retval = NULL; + zval value; + zval retval; uint64_t cas = 0; - zval **params[2]; - zval *z_result; + zval params[2]; + zval z_result; uint32_t flags = 0; int rc = 0; php_memc_t *i_obj = NULL; - params[0] = &zmemc_obj; - params[1] = &z_result; - - fci->retval_ptr_ptr = &retval; + ZVAL_COPY(¶ms[0], zmemc_obj); + fci->retval = &retval; fci->params = params; fci->param_count = 2; @@ -3663,35 +3605,35 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, res_key_len = memcached_result_key_length(result); cas = memcached_result_cas(result); - ALLOC_INIT_ZVAL(value); - - i_obj = (php_memc_t *) zend_object_store_get_object(zmemc_obj TSRMLS_CC); + i_obj = Z_MEMC_OBJ_P(zmemc_obj); - if (php_memc_zval_from_payload(value, payload, payload_len, flags, i_obj->obj->serializer TSRMLS_CC) < 0) { + if (php_memc_zval_from_payload(&value, payload, payload_len, flags, i_obj->obj->serializer) < 0) { zval_ptr_dtor(&value); i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; return -1; } - MAKE_STD_ZVAL(z_result); - array_init(z_result); - add_assoc_stringl_ex(z_result, ZEND_STRS("key"), res_key, res_key_len, 1); - add_assoc_zval_ex(z_result, ZEND_STRS("value"), value); + array_init(&z_result); + ZVAL_COPY(¶ms[1], &z_result); + add_assoc_stringl_ex(&z_result, ZEND_STRL("key"), (char *)res_key, res_key_len); + add_assoc_zval_ex(&z_result, ZEND_STRL("value"), &value); if (cas != 0) { - add_assoc_double_ex(z_result, ZEND_STRS("cas"), (double)cas); + add_assoc_double_ex(&z_result, ZEND_STRL("cas"), (double)cas); } if (MEMC_VAL_GET_USER_FLAGS(flags) != 0) { - add_assoc_long_ex(z_result, ZEND_STRS("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); + add_assoc_long_ex(&z_result, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); } - if (zend_call_function(fci, fcc TSRMLS_CC) == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not invoke result callback"); + if (zend_call_function(fci, fcc) == FAILURE) { + php_error_docref(NULL, E_WARNING, "could not invoke result callback"); rc = -1; } - if (retval) { + if (&retval) { zval_ptr_dtor(&retval); } + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); zval_ptr_dtor(&z_result); return rc; @@ -3716,13 +3658,12 @@ PHP_METHOD(MemcachedServer, run) { int i; zend_bool rc; - char *address; - int address_len; + zend *address; php_memc_server_t *intern; - intern = (php_memc_server_t *) zend_object_store_get_object(getThis() TSRMLS_CC); + intern = Z_MEMC_OBJ_P(getThis()); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &address, &address_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &address) == FAILURE) { return; } @@ -3743,7 +3684,7 @@ PHP_METHOD(MemcachedServer, on) zend_fcall_info_cache fci_cache; zend_bool rc = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lf!", &event, &fci, &fci_cache) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "lf!", &event, &fci, &fci_cache) == FAILURE) { return; } @@ -4245,9 +4186,9 @@ zend_module_entry memcached_module_entry = { /* {{{ php_memc_register_constants */ static void php_memc_register_constants(INIT_FUNC_ARGS) { - #define REGISTER_MEMC_CLASS_CONST_LONG(name, value) zend_declare_class_constant_long(php_memc_get_ce() , ZEND_STRS( #name ) - 1, value TSRMLS_CC) - #define REGISTER_MEMC_CLASS_CONST_BOOL(name, value) zend_declare_class_constant_bool(php_memc_get_ce() , ZEND_STRS( #name ) - 1, value TSRMLS_CC) - #define REGISTER_MEMC_CLASS_CONST_NULL(name) zend_declare_class_constant_null(php_memc_get_ce() , ZEND_STRS( #name ) - 1 TSRMLS_CC) + #define REGISTER_MEMC_CLASS_CONST_LONG(name, value) zend_declare_class_constant_long(php_memc_get_ce() , ZEND_STRS( #name ) - 1, value) + #define REGISTER_MEMC_CLASS_CONST_BOOL(name, value) zend_declare_class_constant_bool(php_memc_get_ce() , ZEND_STRS( #name ) - 1, value) + #define REGISTER_MEMC_CLASS_CONST_NULL(name) zend_declare_class_constant_null(php_memc_get_ce() , ZEND_STRS( #name ) - 1) /* * Class options @@ -4489,13 +4430,15 @@ PHP_MINIT_FUNCTION(memcached) zend_class_entry ce; memcpy(&memcached_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + memcached_object_handlers.offset = XtOffsetOf(php_memc_t, zo); memcached_object_handlers.clone_obj = NULL; + memcached_object_handlers.free_obj = php_memc_free_storage; le_memc = zend_register_list_destructors_ex(NULL, php_memc_dtor, "Memcached persistent connection", module_number); le_memc_sess = zend_register_list_destructors_ex(NULL, php_memc_sess_dtor, "Memcached Sessions persistent connection", module_number); INIT_CLASS_ENTRY(ce, "Memcached", memcached_class_methods); - memcached_ce = zend_register_internal_class(&ce TSRMLS_CC); + memcached_ce = zend_register_internal_class(&ce); memcached_ce->create_object = php_memc_new; #ifdef HAVE_MEMCACHED_PROTOCOL @@ -4503,12 +4446,12 @@ PHP_MINIT_FUNCTION(memcached) memcached_server_object_handlers.clone_obj = NULL; INIT_CLASS_ENTRY(ce, "MemcachedServer", memcached_server_class_methods); - memcached_server_ce = zend_register_internal_class(&ce TSRMLS_CC); + memcached_server_ce = zend_register_internal_class(&ce); memcached_server_ce->create_object = php_memc_server_new; #endif INIT_CLASS_ENTRY(ce, "MemcachedException", NULL); - memcached_exception_ce = zend_register_internal_class_ex(&ce, php_memc_get_exception_base(0 TSRMLS_CC), NULL TSRMLS_CC); + memcached_exception_ce = zend_register_internal_class_ex(&ce, php_memc_get_exception_base(0)); /* TODO * possibly declare custom exception property here */ @@ -4523,7 +4466,7 @@ PHP_MINIT_FUNCTION(memcached) #if HAVE_MEMCACHED_SASL if (MEMC_G(use_sasl)) { if (sasl_client_init(NULL) != SASL_OK) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "Failed to initialize SASL library"); + php_error_docref(NULL, E_ERROR, "Failed to initialize SASL library"); return FAILURE; } } diff --git a/php_memcached.h b/php_memcached.h index bce8e37b..da4d6b92 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -36,7 +36,7 @@ PHP_MEMCACHED_API zend_class_entry *php_memc_get_ce(void); PHP_MEMCACHED_API zend_class_entry *php_memc_get_exception(void); -PHP_MEMCACHED_API zend_class_entry *php_memc_get_exception_base(int root TSRMLS_DC); +PHP_MEMCACHED_API zend_class_entry *php_memc_get_exception_base(int root); extern zend_module_entry memcached_module_entry; #define phpext_memcached_ptr &memcached_module_entry diff --git a/php_memcached_private.h b/php_memcached_private.h index 0ec2d76e..2929818e 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include #include diff --git a/php_memcached_server.c b/php_memcached_server.c index 42ccc8ee..eb225db0 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -60,7 +60,7 @@ typedef struct { } php_memc_client_t; static -long s_invoke_php_callback (php_memc_server_cb_t *cb, zval ***params, ssize_t param_count TSRMLS_DC) +long s_invoke_php_callback (php_memc_server_cb_t *cb, zval ***params, ssize_t param_count) { long retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; zval *retval_ptr = NULL; @@ -72,9 +72,9 @@ long s_invoke_php_callback (php_memc_server_cb_t *cb, zval ***params, ssize_t pa cb->fci.no_separation = 1; cb->fci.retval_ptr_ptr = &retval_ptr; - if (zend_call_function(&(cb->fci), &(cb->fci_cache) TSRMLS_CC) == FAILURE) { - char *buf = php_memc_printable_func (&(cb->fci), &(cb->fci_cache) TSRMLS_CC); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to invoke callback %s()", buf); + if (zend_call_function(&(cb->fci), &(cb->fci_cache)) == FAILURE) { + char *buf = php_memc_printable_func (&(cb->fci), &(cb->fci_cache)); + php_error_docref(NULL, E_WARNING, "Failed to invoke callback %s()", buf); efree (buf); } if (retval_ptr) { @@ -91,10 +91,8 @@ protocol_binary_response_status s_add_handler(const void *cookie, const void *ke uint32_t data_len, uint32_t flags, uint32_t exptime, uint64_t *result_cas) { protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zcookie, *zkey, *zvalue, *zflags, *zexptime, *zresult_cas; - zval **params [6]; - - TSRMLS_FETCH(); + zval zcookie, zkey, zvalue, zflags, zexptime, zresult_cas; + zval params[6]; if (!MEMC_HAS_CB(MEMC_SERVER_ON_ADD)) { return retval; @@ -102,32 +100,29 @@ protocol_binary_response_status s_add_handler(const void *cookie, const void *ke MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); - MAKE_STD_ZVAL(zkey); - ZVAL_STRINGL(zkey, key, key_len, 1); - - MAKE_STD_ZVAL(zvalue); - ZVAL_STRINGL(zvalue, data, data_len, 1); - - MAKE_STD_ZVAL(zflags); - ZVAL_LONG(zflags, flags); - - MAKE_STD_ZVAL(zexptime); - ZVAL_LONG(zexptime, exptime); + ZVAL_STRINGL(&zkey, key, key_len); + ZVAL_STRINGL(&zvalue, data, data_len); + ZVAL_LONG(&zflags, flags); + ZVAL_LONG(&zexptime, exptime); + ZVAL_NULL(&zresult_cas); - MAKE_STD_ZVAL(zresult_cas); - ZVAL_NULL(zresult_cas); + ZVAL_COPY(¶ms[0], &zcookie); + ZVAL_COPY(¶ms[1], &zkey); + ZVAL_COPY(¶ms[2], &zvalue); + ZVAL_COPY(¶ms[3], &zflags); + ZVAL_COPY(¶ms[4], &zexptime); + ZVAL_COPY(¶ms[5], &zresult_cas); - params [0] = &zcookie; - params [1] = &zkey; - params [2] = &zvalue; - params [3] = &zflags; - params [4] = &zexptime; - params [5] = &zresult_cas; - - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_ADD), params, 6 TSRMLS_CC); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_ADD), params, 6); MEMC_MAKE_RESULT_CAS(zresult_cas, *result_cas); + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(¶ms[2]); + zval_ptr_dtor(¶ms[3]); + zval_ptr_dtor(¶ms[4]); + zval_ptr_dtor(¶ms[5]); zval_ptr_dtor (&zcookie); zval_ptr_dtor (&zkey); zval_ptr_dtor (&zvalue); @@ -143,10 +138,8 @@ protocol_binary_response_status s_append_prepend_handler (php_memc_event_t event const void *data, uint32_t data_len, uint64_t cas, uint64_t *result_cas) { protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zcookie, *zkey, *zvalue, *zcas, *zresult_cas; - zval **params [5]; - - TSRMLS_FETCH(); + zval zcookie, zkey, zvalue, zcas, zresult_cas; + zval params[5]; if (!MEMC_HAS_CB(event)) { return retval; @@ -154,28 +147,26 @@ protocol_binary_response_status s_append_prepend_handler (php_memc_event_t event MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); - MAKE_STD_ZVAL(zkey); - ZVAL_STRINGL(zkey, key, key_len, 1); - - MAKE_STD_ZVAL(zvalue); - ZVAL_STRINGL(zvalue, data, data_len, 1); + ZVAL_STRINGL(&zkey, key, key_len); + ZVAL_STRINGL(&zvalue, data, data_len); + ZVAL_DOUBLE(&zcas, cas); + ZVAL_NULL(&zresult_cas); - MAKE_STD_ZVAL(zcas); - ZVAL_DOUBLE(zcas, cas); + ZVAL_COPY(¶ms[0], &zcookie); + ZVAL_COPY(¶ms[1], &zkey); + ZVAL_COPY(¶ms[2], &zvalue); + ZVAL_COPY(¶ms[3], &zcas); + ZVAL_COPY(¶ms[4], &zresult_cas); - MAKE_STD_ZVAL(zresult_cas); - ZVAL_NULL(zresult_cas); - - params [0] = &zcookie; - params [1] = &zkey; - params [2] = &zvalue; - params [3] = &zcas; - params [4] = &zresult_cas; - - retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 5 TSRMLS_CC); + retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 5); MEMC_MAKE_RESULT_CAS(zresult_cas, *result_cas); + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(¶ms[2]); + zval_ptr_dtor(¶ms[3]); + zval_ptr_dtor(¶ms[4]); zval_ptr_dtor (&zcookie); zval_ptr_dtor (&zkey); zval_ptr_dtor (&zvalue); @@ -206,10 +197,8 @@ protocol_binary_response_status s_incr_decr_handler (php_memc_event_t event, con uint64_t initial, uint32_t expiration, uint64_t *result, uint64_t *result_cas) { protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zcookie, *zkey, *zdelta, *zinital, *zexpiration, *zresult, *zresult_cas; - zval **params [7]; - - TSRMLS_FETCH(); + zval zcookie, zkey, zdelta, zinital, zexpiration, zresult, zresult_cas; + zval params[7]; if (!MEMC_HAS_CB(event)) { return retval; @@ -217,41 +206,37 @@ protocol_binary_response_status s_incr_decr_handler (php_memc_event_t event, con MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); - MAKE_STD_ZVAL(zkey); - ZVAL_STRINGL(zkey, key, key_len, 1); - - MAKE_STD_ZVAL(zdelta); - ZVAL_LONG(zdelta, (long) delta); - - MAKE_STD_ZVAL(zinital); - ZVAL_LONG(zinital, (long) initial); - - MAKE_STD_ZVAL(zexpiration); - ZVAL_LONG(zexpiration, (long) expiration); + ZVAL_STRINGL(&zkey, key, key_len); + ZVAL_LONG(&zdelta, (long) delta); + ZVAL_LONG(&zinital, (long) initial); + ZVAL_LONG(&zexpiration, (long) expiration); + ZVAL_LONG(&zresult, 0); + ZVAL_NULL(&zresult_cas); - MAKE_STD_ZVAL(zresult); - ZVAL_LONG(zresult, 0); + ZVAL_COPY(¶ms[0], &zcookie); + ZVAL_COPY(¶ms[1], &zkey); + ZVAL_COPY(¶ms[2], &zdelta); + ZVAL_COPY(¶ms[3], &zinital); + ZVAL_COPY(¶ms[4], &zexpiration); + ZVAL_COPY(¶ms[5], &zresult); + ZVAL_COPY(¶ms[6], &zresult_cas); - MAKE_STD_ZVAL(zresult_cas); - ZVAL_NULL(zresult_cas); + retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 7); - params [0] = &zcookie; - params [1] = &zkey; - params [2] = &zdelta; - params [3] = &zinital; - params [4] = &zexpiration; - params [5] = &zresult; - params [6] = &zresult_cas; - - retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 7 TSRMLS_CC); - - if (Z_TYPE_P(zresult) != IS_LONG) { - convert_to_long (zresult); + if (Z_TYPE(zresult) != IS_LONG) { + convert_to_long (&zresult); } - *result = (uint64_t) Z_LVAL_P(zresult); + *result = (uint64_t) Z_LVAL(zresult); MEMC_MAKE_RESULT_CAS(zresult_cas, *result_cas); + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(¶ms[2]); + zval_ptr_dtor(¶ms[3]); + zval_ptr_dtor(¶ms[4]); + zval_ptr_dtor(¶ms[5]); + zval_ptr_dtor(¶ms[6]); zval_ptr_dtor (&zcookie); zval_ptr_dtor (&zkey); zval_ptr_dtor (&zdelta); @@ -284,10 +269,8 @@ protocol_binary_response_status s_delete_handler (const void *cookie, const void uint16_t key_len, uint64_t cas) { protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zcookie, *zkey, *zcas; - zval **params [3]; - - TSRMLS_FETCH(); + zval zcookie, zkey, zcas; + zval params[3]; if (!MEMC_HAS_CB(MEMC_SERVER_ON_DELETE)) { return retval; @@ -295,21 +278,21 @@ protocol_binary_response_status s_delete_handler (const void *cookie, const void MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); - MAKE_STD_ZVAL(zkey); - ZVAL_STRINGL(zkey, key, key_len, 1); - - MAKE_STD_ZVAL(zcas); - ZVAL_DOUBLE(zcas, (double) cas); - - params [0] = &zcookie; - params [1] = &zkey; - params [2] = &zcas; - - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_DELETE), params, 3 TSRMLS_CC); - - zval_ptr_dtor (&zcookie); - zval_ptr_dtor (&zkey); - zval_ptr_dtor (&zcas); + ZVAL_STRINGL(&zkey, key, key_len); + ZVAL_DOUBLE(&zcas, (double) cas); + + ZVAL_COPY(¶ms[0], &zcookie); + ZVAL_COPY(¶ms[1], &zkey); + ZVAL_COPY(¶ms[2], &zcas); + + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_DELETE), params, 3); + + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(¶ms[2]); + zval_ptr_dtor(&zcookie); + zval_ptr_dtor(&zkey); + zval_ptr_dtor(&zcas); return retval; } @@ -317,10 +300,8 @@ static protocol_binary_response_status s_flush_handler(const void *cookie, uint32_t when) { protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zcookie, *zwhen; - zval **params [2]; - - TSRMLS_FETCH(); + zval zcookie, zwhen; + zval params[2]; if (!MEMC_HAS_CB(MEMC_SERVER_ON_FLUSH)) { return retval; @@ -328,16 +309,15 @@ protocol_binary_response_status s_flush_handler(const void *cookie, uint32_t whe MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); - MAKE_STD_ZVAL(zwhen); - ZVAL_LONG(zwhen, (long) when); - - params [0] = &zcookie; - params [1] = &zwhen; + ZVAL_COPY(¶ms[0], &zcookie); + ZVAL_COPY(¶ms[1], &zwhen) - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_FLUSH), params, 2 TSRMLS_CC); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_FLUSH), params, 2); - zval_ptr_dtor (&zcookie); - zval_ptr_dtor (&zwhen); + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(&zcookie); + zval_ptr_dtor(&zwhen); return retval; } @@ -346,10 +326,8 @@ protocol_binary_response_status s_get_handler (const void *cookie, const void *k memcached_binary_protocol_get_response_handler response_handler) { protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zcookie, *zkey, *zvalue, *zflags, *zresult_cas; - zval **params [5]; - - TSRMLS_FETCH(); + zval zcookie, zkey, zvalue, zflags, zresult_cas; + zval params[5]; if (!MEMC_HAS_CB(MEMC_SERVER_ON_GET)) { return retval; @@ -357,52 +335,50 @@ protocol_binary_response_status s_get_handler (const void *cookie, const void *k MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); - MAKE_STD_ZVAL(zkey); - ZVAL_STRINGL(zkey, key, key_len, 1); - - MAKE_STD_ZVAL(zvalue); - ZVAL_NULL(zvalue); - - MAKE_STD_ZVAL(zflags); - ZVAL_NULL(zflags); - - MAKE_STD_ZVAL(zresult_cas); - ZVAL_NULL(zresult_cas); + ZVAL_COPY(¶ms[0], &zcookie); + ZVAL_COPY(¶ms[1], &zkey); + ZVAL_COPY(¶ms[2], &zvalue); + ZVAL_COPY(¶ms[3], &zflags); + ZVAL_COPY(¶ms[4], &zresult_cas); - params [0] = &zcookie; - params [1] = &zkey; - params [2] = &zvalue; - params [3] = &zflags; - params [4] = &zresult_cas; - - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_GET), params, 5 TSRMLS_CC); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_GET), params, 5); /* Succeeded in getting the key */ if (retval == PROTOCOL_BINARY_RESPONSE_SUCCESS) { uint32_t flags = 0; uint64_t result_cas = 0; - if (Z_TYPE_P (zvalue) == IS_NULL) { - zval_ptr_dtor (&zcookie); - zval_ptr_dtor (&zkey); - zval_ptr_dtor (&zvalue); - zval_ptr_dtor (&zflags); - zval_ptr_dtor (&zresult_cas); + if (Z_TYPE(zvalue) == IS_NULL) { + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(¶ms[2]); + zval_ptr_dtor(¶ms[3]); + zval_ptr_dtor(¶ms[4]); + zval_ptr_dtor(&zcookie); + zval_ptr_dtor(&zkey); + zval_ptr_dtor(&zvalue); + zval_ptr_dtor(&zflags); + zval_ptr_dtor(&zresult_cas); return PROTOCOL_BINARY_RESPONSE_KEY_ENOENT; } - if (Z_TYPE_P (zvalue) != IS_STRING) { - convert_to_string (zvalue); + if (Z_TYPE(zvalue) != IS_STRING) { + convert_to_string (&zvalue); } - if (Z_TYPE_P (zflags) == IS_LONG) { - flags = Z_LVAL_P (zflags); + if (Z_TYPE(zflags) == IS_LONG) { + flags = Z_LVAL(zflags); } MEMC_MAKE_RESULT_CAS(zresult_cas, result_cas); - retval = response_handler(cookie, key, key_len, Z_STRVAL_P(zvalue), Z_STRLEN_P(zvalue), flags, result_cas); + retval = response_handler(cookie, key, key_len, Z_STRVAL(zvalue), Z_STRLEN(zvalue), flags, result_cas); } + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(¶ms[2]); + zval_ptr_dtor(¶ms[3]); + zval_ptr_dtor(¶ms[4]); zval_ptr_dtor (&zcookie); zval_ptr_dtor (&zkey); zval_ptr_dtor (&zvalue); @@ -415,10 +391,8 @@ static protocol_binary_response_status s_noop_handler(const void *cookie) { protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zcookie; - zval **params [1]; - - TSRMLS_FETCH(); + zval zcookie; + zval params[1]; if (!MEMC_HAS_CB(MEMC_SERVER_ON_NOOP)) { return retval; @@ -426,10 +400,11 @@ protocol_binary_response_status s_noop_handler(const void *cookie) MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); - params [0] = &zcookie; + ZVAL_COPY(¶ms[0], &zcookie); - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_NOOP), params, 1 TSRMLS_CC); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_NOOP), params, 1); + zval_ptr_dtor(¶ms[0]); zval_ptr_dtor (&zcookie); return retval; } @@ -437,11 +412,9 @@ protocol_binary_response_status s_noop_handler(const void *cookie) static protocol_binary_response_status s_quit_handler(const void *cookie) { - zval **params [1]; + zval params[1]; protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zcookie; - - TSRMLS_FETCH(); + zval zcookie; if (!MEMC_HAS_CB(MEMC_SERVER_ON_QUIT)) { return retval; @@ -449,9 +422,11 @@ protocol_binary_response_status s_quit_handler(const void *cookie) MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); - params [0] = &zcookie; - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_QUIT), params, 1 TSRMLS_CC); + ZVAL_COPY(¶ms[0], &zcookie); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_QUIT), params, 1); + + zval_ptr_dtor(¶ms[0]); zval_ptr_dtor (&zcookie); return retval; } @@ -463,10 +438,8 @@ protocol_binary_response_status s_set_replace_handler (php_memc_event_t event, c uint32_t data_len, uint32_t flags, uint32_t expiration, uint64_t cas, uint64_t *result_cas) { protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zcookie, *zkey, *zdata, *zflags, *zexpiration, *zcas, *zresult_cas; - zval **params [7]; - - TSRMLS_FETCH(); + zval zcookie, zkey, zdata, zflags, zexpiration, zcas, zresult_cas; + zval params[7]; if (!MEMC_HAS_CB(event)) { return retval; @@ -474,36 +447,32 @@ protocol_binary_response_status s_set_replace_handler (php_memc_event_t event, c MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); - MAKE_STD_ZVAL(zkey); - ZVAL_STRINGL(zkey, key, key_len, 1); - - MAKE_STD_ZVAL(zdata); - ZVAL_STRINGL(zdata, ((char *) data), (int) data_len, 1); - - MAKE_STD_ZVAL(zflags); - ZVAL_LONG(zflags, (long) flags); - - MAKE_STD_ZVAL(zexpiration); - ZVAL_LONG(zexpiration, (long) expiration); - - MAKE_STD_ZVAL(zcas); - ZVAL_DOUBLE(zcas, (double) cas); + ZVAL_STRINGL(&zkey, key, key_len); + ZVAL_STRINGL(&zdata, ((char *) data), (int) data_len); + ZVAL_LONG(&zflags, (long) flags); + ZVAL_LONG(&zexpiration, (long) expiration); + ZVAL_DOUBLE(&zcas, (double) cas); + ZVAL_NULL(&zresult_cas); - MAKE_STD_ZVAL(zresult_cas); - ZVAL_NULL(zresult_cas); + ZVAL_COPY(¶ms[0], &zcookie); + ZVAL_COPY(¶ms[1], &zkey); + ZVAL_COPY(¶ms[2], &zdata); + ZVAL_COPY(¶ms[3], &zflags); + ZVAL_COPY(¶ms[4], &zexpiration); + ZVAL_COPY(¶ms[5], &zcas); + ZVAL_COPY(¶ms[6], &zresult_cas); - params [0] = &zcookie; - params [1] = &zkey; - params [2] = &zdata; - params [3] = &zflags; - params [4] = &zexpiration; - params [5] = &zcas; - params [6] = &zresult_cas; - - retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 7 TSRMLS_CC); + retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 7); MEMC_MAKE_RESULT_CAS(zresult_cas, *result_cas); + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(¶ms[2]); + zval_ptr_dtor(¶ms[3]); + zval_ptr_dtor(¶ms[4]); + zval_ptr_dtor(¶ms[5]); + zval_ptr_dtor(¶ms[6]); zval_ptr_dtor (&zcookie); zval_ptr_dtor (&zkey); zval_ptr_dtor (&zdata); @@ -535,11 +504,9 @@ static protocol_binary_response_status s_stat_handler (const void *cookie, const void *key, uint16_t key_len, memcached_binary_protocol_stat_response_handler response_handler) { - zval **params [3]; + zval params[3]; protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zcookie, *zkey, *zbody; - - TSRMLS_FETCH(); + zval zcookie, zkey, zbody; if (!MEMC_HAS_CB(MEMC_SERVER_ON_STAT)) { return retval; @@ -547,29 +514,30 @@ protocol_binary_response_status s_stat_handler (const void *cookie, const void * MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); - MAKE_STD_ZVAL(zkey); - ZVAL_STRINGL(zkey, key, key_len, 1); + ZVAL_STRINGL(&zkey, key, key_len); + ZVAL_NULL(&zbody); - MAKE_STD_ZVAL(zbody); - ZVAL_NULL(zbody); + ZVAL_COPY(¶ms[0], &zcookie); + ZVAL_COPY(¶ms[1], &zkey); + ZVAL_COPY(¶ms[2], &zbody); - params [0] = &zcookie; - params [1] = &zkey; - params [2] = &zbody; - - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_STAT), params, 3 TSRMLS_CC); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_STAT), params, 3); if (retval == PROTOCOL_BINARY_RESPONSE_SUCCESS) { - if (Z_TYPE_P (zbody) == IS_NULL) { + if (Z_TYPE(zbody) == IS_NULL) { retval = response_handler(cookie, NULL, 0, NULL, 0); } else { - if (Z_TYPE_P (zbody) != IS_STRING) { - convert_to_string (zbody); + if (Z_TYPE(zbody) != IS_STRING) { + convert_to_string(&zbody); } - retval = response_handler(cookie, key, key_len, Z_STRVAL_P (zbody), (uint32_t) Z_STRLEN_P (zbody)); + retval = response_handler(cookie, key, key_len, Z_STRVAL(zbody), (uint32_t) Z_STRLEN(zbody)); } } + + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(¶ms[2]); zval_ptr_dtor (&zcookie); zval_ptr_dtor (&zkey); zval_ptr_dtor (&zbody); @@ -580,11 +548,9 @@ static protocol_binary_response_status s_version_handler (const void *cookie, memcached_binary_protocol_version_response_handler response_handler) { - zval **params [2]; + zval params[2]; protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *zcookie, *zversion; - - TSRMLS_FETCH(); + zval zcookie, zversion; if (!MEMC_HAS_CB(MEMC_SERVER_ON_VERSION)) { return retval; @@ -592,21 +558,23 @@ protocol_binary_response_status s_version_handler (const void *cookie, MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); - MAKE_STD_ZVAL(zversion); - ZVAL_NULL(zversion); + ZVAL_NULL(&zversion); - params [0] = &zcookie; - params [1] = &zversion; + ZVAL_COPY(¶ms[0], &zcookie); + ZVAL_COPY(¶ms[1], &zversion); - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_VERSION), params, 2 TSRMLS_CC); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_VERSION), params, 2); if (retval == PROTOCOL_BINARY_RESPONSE_SUCCESS) { - if (Z_TYPE_P (zversion) != IS_STRING) { - convert_to_string (zversion); + if (Z_TYPE(zversion) != IS_STRING) { + convert_to_string(&zversion); } retval = response_handler (cookie, Z_STRVAL_P(zversion), (uint32_t) Z_STRLEN_P(zversion)); } + + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); zval_ptr_dtor (&zcookie); zval_ptr_dtor (&zversion); return retval; @@ -623,36 +591,33 @@ void s_handle_memcached_event (evutil_socket_t fd, short what, void *arg) php_memc_client_t *client = (php_memc_client_t *) arg; memcached_protocol_event_t events; - TSRMLS_FETCH(); - if (!client->on_connect_invoked) { if (MEMC_HAS_CB(MEMC_SERVER_ON_CONNECT)) { - zval *zremoteip, *zremoteport; - zval **params [2]; + zval zremoteip, zremoteport; + zval params[2]; protocol_binary_response_status retval; struct sockaddr_in addr_in; socklen_t addr_in_len = sizeof(addr_in); - MAKE_STD_ZVAL(zremoteip); - MAKE_STD_ZVAL(zremoteport); - if (getpeername (fd, (struct sockaddr *) &addr_in, &addr_in_len) == 0) { - ZVAL_STRING(zremoteip, inet_ntoa (addr_in.sin_addr), 1); - ZVAL_LONG(zremoteport, ntohs (addr_in.sin_port)); + ZVAL_STRING(&zremoteip, inet_ntoa (addr_in.sin_addr), 1); + ZVAL_LONG(&zremoteport, ntohs (addr_in.sin_port)); } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "getpeername failed: %s", strerror (errno)); - ZVAL_NULL(zremoteip); - ZVAL_NULL(zremoteport); + php_error_docref(NULL, E_WARNING, "getpeername failed: %s", strerror (errno)); + ZVAL_NULL(&zremoteip); + ZVAL_NULL(&zremoteport); } - params [0] = &zremoteip; - params [1] = &zremoteport; + ZVAL_COPY(¶ms[0], &zremoteip); + ZVAL_COPY(¶ms[1], &zremoteport); - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_CONNECT), params, 2 TSRMLS_CC); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_CONNECT), params, 2); - zval_ptr_dtor (&zremoteip); - zval_ptr_dtor (&zremoteport); + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(&zremoteip); + zval_ptr_dtor(&zremoteport); if (retval != PROTOCOL_BINARY_RESPONSE_SUCCESS) { memcached_protocol_client_destroy (client->protocol_client); @@ -683,7 +648,7 @@ void s_handle_memcached_event (evutil_socket_t fd, short what, void *arg) rc = event_base_once (client->event_base, fd, flags, s_handle_memcached_event, client, NULL); if (rc != 0) { - php_error_docref (NULL TSRMLS_CC, E_WARNING, "Failed to schedule events"); + php_error_docref (NULL, E_WARNING, "Failed to schedule events"); } } @@ -698,14 +663,12 @@ void s_accept_cb (evutil_socket_t fd, short what, void *arg) php_memc_proto_handler_t *handler = (php_memc_proto_handler_t *) arg; - TSRMLS_FETCH(); - /* Accept the connection */ addr_len = sizeof (addr); sock = accept (fd, (struct sockaddr *) &addr, &addr_len); if (sock == -1) { - php_error_docref (NULL TSRMLS_CC, E_WARNING, "Failed to accept the client: %s", strerror (errno)); + php_error_docref (NULL, E_WARNING, "Failed to accept the client: %s", strerror (errno)); return; } @@ -715,7 +678,7 @@ void s_accept_cb (evutil_socket_t fd, short what, void *arg) client->on_connect_invoked = 0; if (!client->protocol_client) { - php_error_docref (NULL TSRMLS_CC, E_WARNING, "Failed to allocate protocol client"); + php_error_docref (NULL, E_WARNING, "Failed to allocate protocol client"); efree (client); evutil_closesocket (sock); return; @@ -725,7 +688,7 @@ void s_accept_cb (evutil_socket_t fd, short what, void *arg) rc = event_base_once (handler->event_base, sock, EV_READ, s_handle_memcached_event, client, NULL); if (rc != 0) { - php_error_docref (NULL TSRMLS_CC, E_WARNING, "Failed to add event for client"); + php_error_docref (NULL, E_WARNING, "Failed to add event for client"); memcached_protocol_client_destroy (client->protocol_client); efree (client); evutil_closesocket (sock); @@ -771,59 +734,55 @@ evutil_socket_t s_create_listening_socket (const char *spec) int rc; - TSRMLS_FETCH(); - addr_len = sizeof (struct sockaddr); rc = evutil_parse_sockaddr_port (spec, (struct sockaddr *) &addr, &addr_len); if (rc != 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse bind address"); + php_error_docref(NULL, E_WARNING, "Failed to parse bind address"); return -1; } sock = socket (AF_INET, SOCK_STREAM, 0); if (sock < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "socket failed: %s", strerror (errno)); + php_error_docref(NULL, E_WARNING, "socket failed: %s", strerror (errno)); return -1; } rc = bind (sock, (struct sockaddr *) &addr, addr_len); if (rc < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "bind failed: %s", strerror (errno)); + php_error_docref(NULL, E_WARNING, "bind failed: %s", strerror (errno)); return -1; } rc = listen (sock, 1024); if (rc < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "listen failed: %s", strerror (errno)); + php_error_docref(NULL, E_WARNING, "listen failed: %s", strerror (errno)); return -1; } rc = evutil_make_socket_nonblocking (sock); if (rc != 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to make socket non-blocking: %s", strerror (errno)); + php_error_docref(NULL, E_WARNING, "failed to make socket non-blocking: %s", strerror (errno)); return -1; } rc = evutil_make_listen_socket_reuseable (sock); if (rc != 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to make socket reuseable: %s", strerror (errno)); + php_error_docref(NULL, E_WARNING, "failed to make socket reuseable: %s", strerror (errno)); return -1; } rc = evutil_make_socket_closeonexec (sock); if (rc != 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to make socket closeonexec: %s", strerror (errno)); + php_error_docref(NULL, E_WARNING, "failed to make socket closeonexec: %s", strerror (errno)); return -1; } return sock; } -zend_bool php_memc_proto_handler_run (php_memc_proto_handler_t *handler, const char *address) +zend_bool php_memc_proto_handler_run (php_memc_proto_handler_t *handler, zend_string *address) { struct event *accept_event; - evutil_socket_t sock = s_create_listening_socket (address); - - TSRMLS_FETCH(); + evutil_socket_t sock = s_create_listening_socket (address->val); if (sock == -1) { return 0; @@ -831,22 +790,22 @@ zend_bool php_memc_proto_handler_run (php_memc_proto_handler_t *handler, const c handler->event_base = event_base_new(); if (!handler->event_base) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "failed to allocate memory: %s", strerror (errno)); + php_error_docref(NULL, E_ERROR, "failed to allocate memory: %s", strerror (errno)); } accept_event = event_new (handler->event_base, sock, EV_READ | EV_PERSIST, s_accept_cb, handler); if (!accept_event) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "failed to allocate memory: %s", strerror (errno)); + php_error_docref(NULL, E_ERROR, "failed to allocate memory: %s", strerror (errno)); } event_add (accept_event, NULL); switch (event_base_dispatch (handler->event_base)) { case -1: - php_error_docref(NULL TSRMLS_CC, E_ERROR, "event_base_dispatch() failed: %s", strerror (errno)); + php_error_docref(NULL, E_ERROR, "event_base_dispatch() failed: %s", strerror (errno)); return 0; break; case 1: - php_error_docref(NULL TSRMLS_CC, E_ERROR, "no events registered"); + php_error_docref(NULL, E_ERROR, "no events registered"); return 0; break; @@ -865,4 +824,11 @@ void php_memc_proto_handler_destroy (php_memc_proto_handler_t **ptr) efree (handler); *ptr = NULL; -} \ No newline at end of file +} +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim: noet sw=4 ts=4 fdm=marker: + */ diff --git a/php_memcached_server.h b/php_memcached_server.h index 31676c53..285c608d 100644 --- a/php_memcached_server.h +++ b/php_memcached_server.h @@ -33,8 +33,8 @@ php_memc_proto_handler_t *php_memc_proto_handler_new (); void php_memc_proto_handler_destroy (php_memc_proto_handler_t **ptr); -zend_bool php_memc_proto_handler_run (php_memc_proto_handler_t *h, const char *address); +zend_bool php_memc_proto_handler_run (php_memc_proto_handler_t *h, zend_string *address); #endif -#endif \ No newline at end of file +#endif diff --git a/php_memcached_session.c b/php_memcached_session.c index a3ef5678..118805aa 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -27,7 +27,7 @@ ps_module ps_mod_memcached = { PS_MOD(memcached) }; -static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC) +static int php_memc_sess_lock(memcached_st *memc, const char *key) { char *lock_key = NULL; int lock_key_len = 0; @@ -72,7 +72,7 @@ static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC) write_retry_attempts--; continue; } - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Write of lock failed"); + php_error_docref(NULL, E_WARNING, "Write of lock failed"); break; } @@ -85,7 +85,7 @@ static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC) return -1; } -static void php_memc_sess_unlock(memcached_st *memc TSRMLS_DC) +static void php_memc_sess_unlock(memcached_st *memc) { if (MEMC_G(sess_locked)) { memcached_delete(memc, MEMC_G(sess_lock_key), MEMC_G(sess_lock_key_len), 0); @@ -103,13 +103,14 @@ PS_OPEN_FUNC(memcached) int plist_key_len = 0; if (!strncmp((char *)save_path, "PERSISTENT=", sizeof("PERSISTENT=") - 1)) { - zend_rsrc_list_entry *le = NULL; + zend_resource *le = NULL; + zval *le_z = NULL; char *e; p = (char *)save_path + sizeof("PERSISTENT=") - 1; if (!*p) { error: - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid persistent id for session storage"); + php_error_docref(NULL, E_WARNING, "Invalid persistent id for session storage"); return FAILURE; } if ((e = strchr(p, ' '))) { @@ -118,7 +119,9 @@ PS_OPEN_FUNC(memcached) goto error; } plist_key_len++; - if (zend_hash_find(&EG(persistent_list), plist_key, plist_key_len, (void *)&le) == SUCCESS) { + + if ((le_z = zend_hash_str_find(&EG(persistent_list), plist_key, plist_key_len)) != NULL) { + le = Z_RES_P(le_z); if (le->type == php_memc_sess_list_entry()) { memc_sess = (memcached_sess *) le->ptr; PS_SET_MOD_DATA(memc_sess); @@ -146,7 +149,7 @@ PS_OPEN_FUNC(memcached) efree(plist_key); } memcached_free(memc_sess->memc_sess); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to enable memcached consistent hashing"); + php_error_docref(NULL, E_WARNING, "failed to enable memcached consistent hashing"); return FAILURE; } } @@ -160,7 +163,7 @@ PS_OPEN_FUNC(memcached) efree(plist_key); } memcached_free(memc_sess->memc_sess); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "bad memcached key prefix in memcached.sess_prefix"); + php_error_docref(NULL, E_WARNING, "bad memcached key prefix in memcached.sess_prefix"); return FAILURE; } @@ -169,10 +172,10 @@ PS_OPEN_FUNC(memcached) } } else { memcached_server_list_free(servers); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not allocate libmemcached structure"); + php_error_docref(NULL, E_WARNING, "could not allocate libmemcached structure"); } } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to parse session.save_path"); + php_error_docref(NULL, E_WARNING, "failed to parse session.save_path"); } } else { memc_sess->memc_sess = php_memc_create_str(p, strlen(p)); @@ -180,12 +183,12 @@ PS_OPEN_FUNC(memcached) #ifdef HAVE_LIBMEMCACHED_CHECK_CONFIGURATION char error_buffer[1024]; if (libmemcached_check_configuration(p, strlen(p), error_buffer, sizeof(error_buffer)) != MEMCACHED_SUCCESS) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "session.save_path configuration error %s", error_buffer); + php_error_docref(NULL, E_WARNING, "session.save_path configuration error %s", error_buffer); } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to initialize memcached session storage"); + php_error_docref(NULL, E_WARNING, "failed to initialize memcached session storage"); } #else - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to initialize memcached session storage"); + php_error_docref(NULL, E_WARNING, "failed to initialize memcached session storage"); #endif } else { @@ -193,21 +196,25 @@ PS_OPEN_FUNC(memcached) PS_SET_MOD_DATA(memc_sess); if (plist_key) { - zend_rsrc_list_entry le; + zend_resource le; + zend_string *tmp_key; le.type = php_memc_sess_list_entry(); le.ptr = memc_sess; - if (zend_hash_update(&EG(persistent_list), (char *)plist_key, plist_key_len, (void *)&le, sizeof(le), NULL) == FAILURE) { + tmp_key = zend_string_init(plist_key, plist_key_len, 0); + if (zend_hash_update_mem(&EG(persistent_list), tmp_key, (void *)&le, sizeof(le)) == NULL) { + zend_string_release(tmp_key); efree(plist_key); - php_error_docref(NULL TSRMLS_CC, E_ERROR, "could not register persistent entry"); + php_error_docref(NULL, E_ERROR, "could not register persistent entry"); } + zend_string_release(tmp_key); efree(plist_key); } if (MEMC_G(sess_binary_enabled)) { if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, (uint64_t) 1) == MEMCACHED_FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached session binary protocol"); + php_error_docref(NULL, E_WARNING, "failed to set memcached session binary protocol"); return FAILURE; } } @@ -220,11 +227,11 @@ PS_OPEN_FUNC(memcached) if (MEMC_G(sess_sasl_username) && MEMC_G(sess_sasl_password)) { /* Force binary protocol */ if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, (uint64_t) 1) == MEMCACHED_FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached session binary protocol"); + php_error_docref(NULL, E_WARNING, "failed to set memcached session binary protocol"); return FAILURE; } if (memcached_set_sasl_auth_data(memc_sess->memc_sess, MEMC_G(sess_sasl_username), MEMC_G(sess_sasl_password)) == MEMCACHED_FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached session sasl credentials"); + php_error_docref(NULL, E_WARNING, "failed to set memcached session sasl credentials"); return FAILURE; } MEMC_G(sess_sasl_data) = 1; @@ -235,23 +242,23 @@ PS_OPEN_FUNC(memcached) #endif if (MEMC_G(sess_number_of_replicas) > 0) { if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, (uint64_t) MEMC_G(sess_number_of_replicas)) == MEMCACHED_FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached session number of replicas"); + php_error_docref(NULL, E_WARNING, "failed to set memcached session number of replicas"); return FAILURE; } if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ, (uint64_t) MEMC_G(sess_randomize_replica_read)) == MEMCACHED_FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached session randomize replica read"); + php_error_docref(NULL, E_WARNING, "failed to set memcached session randomize replica read"); } } if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, (uint64_t) MEMC_G(sess_connect_timeout)) == MEMCACHED_FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached connection timeout"); + php_error_docref(NULL, E_WARNING, "failed to set memcached connection timeout"); return FAILURE; } #ifdef HAVE_MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS /* Allow libmemcached remove failed servers */ if (MEMC_G(sess_remove_failed_enabled)) { if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS, (uint64_t) 1) == MEMCACHED_FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set: remove failed servers"); + php_error_docref(NULL, E_WARNING, "failed to set: remove failed servers"); return FAILURE; } } @@ -272,7 +279,7 @@ PS_CLOSE_FUNC(memcached) memcached_sess *memc_sess = PS_GET_MOD_DATA(); if (MEMC_G(sess_locking_enabled)) { - php_memc_sess_unlock(memc_sess->memc_sess TSRMLS_CC); + php_memc_sess_unlock(memc_sess->memc_sess); } if (memc_sess->memc_sess) { if (!memc_sess->is_persistent) { @@ -294,7 +301,7 @@ PS_READ_FUNC(memcached) { char *payload = NULL; size_t payload_len = 0; - int key_len = strlen(key); + int key_len = key->len; uint32_t flags = 0; memcached_return status; memcached_sess *memc_sess = PS_GET_MOD_DATA(); @@ -302,23 +309,22 @@ PS_READ_FUNC(memcached) key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock." if (!key_length || key_length >= MEMCACHED_MAX_KEY) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The session id is too long or contains illegal characters"); + php_error_docref(NULL, E_WARNING, "The session id is too long or contains illegal characters"); PS(invalid_session_id) = 1; return FAILURE; } if (MEMC_G(sess_locking_enabled)) { - if (php_memc_sess_lock(memc_sess->memc_sess, key TSRMLS_CC) < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to clear session lock record"); + if (php_memc_sess_lock(memc_sess->memc_sess, key->val) < 0) { + php_error_docref(NULL, E_WARNING, "Unable to clear session lock record"); return FAILURE; } } - payload = memcached_get(memc_sess->memc_sess, key, key_len, &payload_len, &flags, &status); + payload = memcached_get(memc_sess->memc_sess, key->val, key_len, &payload_len, &flags, &status); if (status == MEMCACHED_SUCCESS) { - *val = estrndup(payload, payload_len); - *vallen = payload_len; + *val = zend_string_init(payload, payload_len, 1); free(payload); return SUCCESS; } else { @@ -328,7 +334,7 @@ PS_READ_FUNC(memcached) PS_WRITE_FUNC(memcached) { - int key_len = strlen(key); + int key_len = key->len; time_t expiration = 0; long write_try_attempts = 1; memcached_return status; @@ -337,7 +343,7 @@ PS_WRITE_FUNC(memcached) key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock." if (!key_length || key_length >= MEMCACHED_MAX_KEY) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The session id is too long or contains illegal characters"); + php_error_docref(NULL, E_WARNING, "The session id is too long or contains illegal characters"); PS(invalid_session_id) = 1; return FAILURE; } @@ -352,7 +358,7 @@ PS_WRITE_FUNC(memcached) } do { - status = memcached_set(memc_sess->memc_sess, key, key_len, val, vallen, expiration, 0); + status = memcached_set(memc_sess->memc_sess, key->val, key_len, val->val, val->len, expiration, 0); if (status == MEMCACHED_SUCCESS) { return SUCCESS; } else { @@ -367,9 +373,9 @@ PS_DESTROY_FUNC(memcached) { memcached_sess *memc_sess = PS_GET_MOD_DATA(); - memcached_delete(memc_sess->memc_sess, key, strlen(key), 0); + memcached_delete(memc_sess->memc_sess, key->val, key->len, 0); if (MEMC_G(sess_locking_enabled)) { - php_memc_sess_unlock(memc_sess->memc_sess TSRMLS_CC); + php_memc_sess_unlock(memc_sess->memc_sess); } return SUCCESS; From 399b86bdcdd67039d271da9bbbe46cebe1749ffe Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Tue, 3 Feb 2015 12:35:55 -0800 Subject: [PATCH 007/345] More tests pass now --- php_memcached.c | 54 ++++++++++++++++++++++++++--------------- php_memcached_session.c | 2 -- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 33570992..58fb66d4 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -536,7 +536,7 @@ PHP_METHOD(Memcached, getByKey) static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { zend_string *key; - zend_string *server_key; + zend_string *server_key = NULL; const char *payload = NULL; size_t payload_len = 0; uint32_t flags = 0; @@ -584,8 +584,11 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); } - status = memcached_mget_by_key(m_obj->memc, server_key->val, server_key->len, keys, key_lens, 1); - + if (by_key) { + status = memcached_mget_by_key(m_obj->memc, server_key->val, server_key->len, keys, key_lens, 1); + } else { + status = memcached_mget(m_obj->memc, keys, key_lens, 1); + } if (cas_token && Z_IS_REF(cas_token) && orig_cas_flag == 0) { memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); } @@ -685,7 +688,7 @@ PHP_METHOD(Memcached, getMultiByKey) static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { zval *keys = NULL; - zend_string *server_key; + zend_string *server_key = NULL; size_t num_keys = 0; zval *entry = NULL; const char *payload = NULL; @@ -764,7 +767,11 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke } } - status = memcached_mget_by_key(m_obj->memc, server_key->val, server_key->len, mkeys, mkeys_len, i); + if (by_key) { + status = memcached_mget_by_key(m_obj->memc, server_key->val, server_key->len, mkeys, mkeys_len, i); + } else { + status = memcached_mget(m_obj->memc, mkeys, mkeys_len, i); + } /* Handle error, but ignore, there might still be some result */ php_memc_handle_error(i_obj, status); @@ -898,7 +905,7 @@ PHP_METHOD(Memcached, getDelayedByKey) static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { zval *keys = NULL; - zend_string *server_key; + zend_string *server_key = NULL; zend_bool with_cas = 0; size_t num_keys = 0; zval *entry = NULL; @@ -967,8 +974,11 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ /* * Issue the request, but collect results only if the result callback is provided. */ - status = memcached_mget_by_key(m_obj->memc, server_key->val, server_key->len, mkeys, mkeys_len, i); - + if (by_key) { + status = memcached_mget_by_key(m_obj->memc, server_key->val, server_key->len, mkeys, mkeys_len, i); + } else { + status = memcached_mget(m_obj->memc, mkeys, mkeys_len, i); + } /* * Restore the CAS support flag, but only if we had to turn it on. */ @@ -1213,7 +1223,7 @@ PHP_METHOD(Memcached, setMultiByKey) static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { zval *entries; - zend_string *server_key; + zend_string *server_key = NULL; time_t expiration = 0; long udf_flags = 0; zval *entry; @@ -1373,7 +1383,7 @@ PHP_METHOD(Memcached, replaceByKey) static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool by_key) { zend_string *key; - zend_string *server_key; + zend_string *server_key = NULL; zend_string *s_value; zval s_zvalue; zval *value; @@ -1468,7 +1478,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool retry: switch (op) { case MEMC_OP_SET: - if (!server_key->val) { + if (!server_key) { status = memcached_set(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); } else { status = memcached_set_by_key(m_obj->memc, server_key->val, server_key->len, key->val, @@ -1477,7 +1487,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool break; #ifdef HAVE_MEMCACHED_TOUCH case MEMC_OP_TOUCH: - if (!server_key->val) { + if (!server_key) { status = memcached_touch(m_obj->memc, key->val, key->len, expiration); } else { status = memcached_touch_by_key(m_obj->memc, server_key->val, server_key->len, key->val, @@ -1486,7 +1496,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool break; #endif case MEMC_OP_ADD: - if (!server_key->val) { + if (!server_key) { status = memcached_add(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); } else { status = memcached_add_by_key(m_obj->memc, server_key->val, server_key->len, key->val, @@ -1495,7 +1505,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool break; case MEMC_OP_REPLACE: - if (!server_key->val) { + if (!server_key) { status = memcached_replace(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); } else { status = memcached_replace_by_key(m_obj->memc, server_key->val, server_key->len, key->val, @@ -1504,7 +1514,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool break; case MEMC_OP_APPEND: - if (!server_key->val) { + if (!server_key) { status = memcached_append(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); } else { status = memcached_append_by_key(m_obj->memc, server_key->val, server_key->len, key->val, @@ -1513,7 +1523,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool break; case MEMC_OP_PREPEND: - if (!server_key->val) { + if (!server_key) { status = memcached_prepend(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); } else { status = memcached_prepend_by_key(m_obj->memc, server_key->val, server_key->len, key->val, @@ -1547,7 +1557,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) double cas_d; uint64_t cas; zend_string *key; - zend_string *server_key; + zend_string *server_key = NULL; zval *value; time_t expiration = 0; long udf_flags = 0; @@ -1689,8 +1699,12 @@ static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) RETURN_FALSE; } - status = memcached_delete_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + if (by_key) { + status = memcached_delete_by_key(m_obj->memc, server_key->val, server_key->len, key->val, key->len, expiration); + } else { + status = memcached_delete(m_obj->memc, key->val, key->len, expiration); + } if (php_memc_handle_error(i_obj, status) < 0) { RETURN_FALSE; @@ -1704,7 +1718,7 @@ static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { zval *entries; - zend_string *server_key; + zend_string *server_key = NULL; time_t expiration = 0; zval *entry; @@ -1755,7 +1769,7 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by /* {{{ -- php_memc_incdec_impl */ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, zend_bool incr) { - zend_string *key, *server_key; + zend_string *key, *server_key = NULL; long offset = 1; uint64_t value, initial = 0; time_t expiry = 0; diff --git a/php_memcached_session.c b/php_memcached_session.c index 118805aa..1d2dbe32 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -310,7 +310,6 @@ PS_READ_FUNC(memcached) key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock." if (!key_length || key_length >= MEMCACHED_MAX_KEY) { php_error_docref(NULL, E_WARNING, "The session id is too long or contains illegal characters"); - PS(invalid_session_id) = 1; return FAILURE; } @@ -344,7 +343,6 @@ PS_WRITE_FUNC(memcached) key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock." if (!key_length || key_length >= MEMCACHED_MAX_KEY) { php_error_docref(NULL, E_WARNING, "The session id is too long or contains illegal characters"); - PS(invalid_session_id) = 1; return FAILURE; } From 479b6e2ef455e1a2679553a5538ba605f594363b Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Tue, 3 Feb 2015 12:57:34 -0800 Subject: [PATCH 008/345] Fix 4 more tests --- php_memcached.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 58fb66d4..eda04625 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -580,7 +580,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) /* * Enable CAS support, but only if it is currently disabled. */ - if (cas_token && Z_IS_REF(cas_token) && orig_cas_flag == 0) { + if (cas_token && Z_ISREF_P(cas_token) && orig_cas_flag == 0) { memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); } @@ -589,7 +589,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) } else { status = memcached_mget(m_obj->memc, keys, key_lens, 1); } - if (cas_token && Z_IS_REF(cas_token) && orig_cas_flag == 0) { + if (cas_token && Z_ISREF_P(cas_token) && orig_cas_flag == 0) { memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); } @@ -760,7 +760,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke /* * Enable CAS support, but only if it is currently disabled. */ - if (cas_tokens && Z_IS_REF(cas_tokens)) { + if (cas_tokens && Z_ISREF_P(cas_tokens)) { orig_cas_flag = memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS); if (orig_cas_flag == 0) { memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); @@ -778,7 +778,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke /* * Restore the CAS support flag, but only if we had to turn it on. */ - if (cas_tokens && Z_IS_REF(cas_tokens) && orig_cas_flag == 0) { + if (cas_tokens && Z_ISREF_P(cas_tokens) && orig_cas_flag == 0) { memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); } @@ -790,7 +790,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke * returned as doubles, because we cannot store potential 64-bit values in longs. */ if (cas_tokens) { - if (Z_IS_REF(cas_tokens)) { + if (Z_ISREF_P(cas_tokens)) { /* cas_tokens was passed by reference, we'll create an array for it. */ ZVAL_DEREF(cas_tokens); SEPARATE_ZVAL(cas_tokens); From 3a93af390d0430dcae00b860b65e8ec5eddf82e9 Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Tue, 3 Feb 2015 13:32:52 -0800 Subject: [PATCH 009/345] minor cleanup --- php_memcached.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index eda04625..9e381584 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2861,12 +2861,8 @@ zend_object_value php_memc_server_new(zend_class_entry *ce) zval *tmp; intern = ecalloc(1, sizeof(php_memc_server_t)); - zend_object_std_init (&intern->zo, ce); -#if PHP_VERSION_ID >= 50400 - object_properties_init( (zend_object *) intern, ce); -#else - zend_hash_copy(intern->zo.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); -#endif + zend_object_std_init(&intern->zo, ce); + object_properties_init(&intern->zo, ce); intern->handler = php_memc_proto_handler_new (); From a3279a8478483f750274bc1e74fe5d1a540aa354 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Wed, 4 Feb 2015 17:30:29 +0800 Subject: [PATCH 010/345] Various bug fixes --- php_libmemcached_compat.c | 3 +- php_memcached.c | 73 ++++++++++++++++++++++----------------- php_memcached.h | 1 + tests/version.phpt | 4 +-- 4 files changed, 47 insertions(+), 34 deletions(-) diff --git a/php_libmemcached_compat.c b/php_libmemcached_compat.c index f238709e..f49b162b 100644 --- a/php_libmemcached_compat.c +++ b/php_libmemcached_compat.c @@ -49,4 +49,5 @@ memcached_st *php_memc_create_str (const char *str, size_t str_len) } return memc; #endif -} \ No newline at end of file +} + diff --git a/php_memcached.c b/php_memcached.c index 9e381584..500110af 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -366,7 +366,7 @@ static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fc } /* Call the cb */ - ZVAL_COPY_VALUE(¶ms[0], object); + ZVAL_COPY(¶ms[0], object); fci->params = params; fci->param_count = 2; @@ -420,7 +420,7 @@ static PHP_METHOD(Memcached, __construct) is_persistent = 1; plist_key = zend_string_alloc(sizeof("memcached:id=") + persistent_id->len - 1, 0); - snprintf(plist_key->val, plist_key->len+1, "memcached:id=%s", persistent_id->val); + snprintf(plist_key->val, plist_key->len + 1, "memcached:id=%s", persistent_id->val); if ((le = zend_hash_find_ptr(&EG(persistent_list), plist_key)) != NULL) { if (le->type == php_memc_list_entry()) { m_obj = (struct memc_obj *) le->ptr; @@ -500,7 +500,8 @@ static PHP_METHOD(Memcached, __construct) le.type = php_memc_list_entry(); le.ptr = m_obj; GC_REFCOUNT(&le) = 1; - if (zend_hash_update_mem(&EG(persistent_list), plist_key, &le, sizeof(le)) == NULL) { + /* plist_key is not a persistent allocated key, thus we use str_update here */ + if (zend_hash_str_update_mem(&EG(persistent_list), plist_key->val, plist_key->len, &le, sizeof(le)) == NULL) { if (plist_key) { zend_string_release(plist_key); } @@ -853,13 +854,13 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke continue; } - add_assoc_zval_ex(return_value, res_key, res_key_len+1, &value); + add_assoc_zval_ex(return_value, res_key, res_key_len, &value); if (cas_tokens) { cas = memcached_result_cas(&result); - add_assoc_double_ex(cas_tokens, res_key, res_key_len+1, (double)cas); + add_assoc_double_ex(cas_tokens, res_key, res_key_len, (double)cas); } if (udf_flags) { - add_assoc_long_ex(udf_flags, res_key, res_key_len+1, MEMC_VAL_GET_USER_FLAGS(flags)); + add_assoc_long_ex(udf_flags, res_key, res_key_len, MEMC_VAL_GET_USER_FLAGS(flags)); } } @@ -946,7 +947,7 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ convert_to_string_ex(entry); } - if (Z_TYPE_PP(entry) == IS_STRING && Z_STRLEN_PP(entry) > 0) { + if (Z_TYPE_P(entry) == IS_STRING && Z_STRLEN_P(entry) > 0) { mkeys[i] = Z_STRVAL_P(entry); mkeys_len[i] = Z_STRLEN_P(entry); i++; @@ -1227,7 +1228,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke time_t expiration = 0; long udf_flags = 0; zval *entry; - zend_string *str_key = NULL; + zend_string *skey, *str_key = NULL; ulong num_key; char *payload; size_t payload_len; @@ -1262,9 +1263,9 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke } } - ZEND_HASH_FOREACH_KEY_VAL (Z_ARRVAL_P(entries), num_key, str_key, entry) { - if (str_key) { - str_key = zend_string_init(str_key->val, str_key->len, 0); + ZEND_HASH_FOREACH_KEY_VAL (Z_ARRVAL_P(entries), num_key, skey, entry) { + if (skey) { + str_key = skey; } else if (num_key || num_key == 0) { /* Array keys are unsigned, but php integers are signed. * Keys must be converted to signed strings that match @@ -1288,26 +1289,36 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke payload = php_memc_zval_to_payload(entry, &payload_len, &flags, m_obj->serializer, m_obj->compression_type); if (payload == NULL) { i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; - zend_string_release(str_key); + if (!skey) { + zend_string_release(str_key); + } RETURN_FALSE; } retry: if (!by_key) { status = memcached_set(m_obj->memc, str_key->val, str_key->len, payload, payload_len, expiration, flags); - zend_string_release(str_key); + if (!skey) { + zend_string_release(str_key); + } } else { status = memcached_set_by_key(m_obj->memc, server_key->val, server_key->len, str_key->val, str_key->len, payload, payload_len, expiration, flags); - zend_string_release(str_key); + if (!skey) { + zend_string_release(str_key); + } } if (php_memc_handle_error(i_obj, status) < 0) { PHP_MEMC_FAILOVER_RETRY - zend_string_release(str_key); + if (!skey) { + zend_string_release(str_key); + } efree(payload); RETURN_FALSE; } - zend_string_release(str_key); + if (!skey) { + zend_string_release(str_key); + } efree(payload); } ZEND_HASH_FOREACH_END(); @@ -2334,7 +2345,7 @@ static PHP_METHOD(Memcached, getOption) result = memcached_callback_get(m_obj->memc, MEMCACHED_CALLBACK_PREFIX_KEY, &retval); if (retval == MEMCACHED_SUCCESS && result) { #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX == 0x00049000 - RETURN_STRINGL(result, strlen(result) - 1); + RETURN_STRINGL(result, strlen(result)); #else RETURN_STRING(result); #endif @@ -2831,7 +2842,6 @@ static void php_memc_free_storage(zend_object *obj) zend_object_std_dtor(&i_obj->zo); i_obj->obj = NULL; - efree(i_obj); } zend_object *php_memc_new(zend_class_entry *ce) @@ -2946,7 +2956,7 @@ static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, php_ add_assoc_long(&entry, "bytes_written", context->stats[context->i].bytes_written); add_assoc_stringl(&entry, "version", context->stats[context->i].version, strlen(context->stats[context->i].version)); - add_assoc_zval_ex(context->return_value, hostport, hostport_len+1, &entry); + add_assoc_zval_ex(context->return_value, hostport, hostport_len, &entry); efree(hostport); /* Increment the server count in our context structure. Failure to do so will cause only the stats for the last server to get displayed. */ @@ -2974,7 +2984,7 @@ static memcached_return php_memc_do_version_callback(const memcached_st *ptr, ph instance->micro_version); #endif - add_assoc_stringl_ex(context->return_value, hostport, hostport_len+1, version, version_len); + add_assoc_stringl_ex(context->return_value, hostport, hostport_len, version, version_len); efree(hostport); return MEMCACHED_SUCCESS; } @@ -3206,7 +3216,7 @@ char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags default: if (!s_serialize_value (serializer, value, &buf, flags)) { - smart_str_free (&buf); + smart_str_free(&buf); return NULL; } pl = buf.s->val; @@ -3388,12 +3398,7 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ switch (MEMC_VAL_GET_TYPE(flags)) { case MEMC_VAL_IS_STRING: - if (payload_emalloc) { - ZVAL_STRINGL(value, pl, payload_len); - payload_emalloc = 0; - } else { - ZVAL_STRINGL(value, pl, payload_len); - } + ZVAL_STRINGL(value, pl, payload_len); break; case MEMC_VAL_IS_LONG: @@ -3514,6 +3519,7 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i zval params[4]; zval retval; zval z_key; + zval z_val; zval z_expiration; uint32_t flags = 0; @@ -3523,8 +3529,10 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i int result; ZVAL_STR(&z_key, key); - ZVAL_NULL(value); - ZVAL_LONG(&z_expiration, 0); + ZVAL_NULL(&z_val); + ZVAL_NEW_REF(value, &z_val); + ZVAL_NEW_REF(&z_expiration, &z_val); + ZVAL_LONG(Z_REFVAL(z_expiration), 0); ZVAL_COPY(¶ms[0], zmemc_obj); ZVAL_COPY(¶ms[1], &z_key); @@ -3536,9 +3544,12 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i fci->param_count = 4; result = zend_call_function(fci, fcc); + ZVAL_UNREF(value); + ZVAL_UNREF(&z_expiration); if (result == SUCCESS && Z_TYPE(retval) != IS_UNDEF) { - i_obj = (php_memc_t *) Z_OBJ_P(zmemc_obj); - struct memc_obj *m_obj = i_obj->obj; + struct memc_obj *m_obj; + i_obj = Z_MEMC_OBJ_P(zmemc_obj) + m_obj = i_obj->obj; if (zend_is_true(&retval)) { time_t expiration; diff --git a/php_memcached.h b/php_memcached.h index da4d6b92..2ce8e730 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -21,6 +21,7 @@ #include "php.h" #include "main/php_config.h" +#include "Zend/zend_smart_str.h" #ifdef HAVE_CONFIG_H # include "config.h" diff --git a/tests/version.phpt b/tests/version.phpt index f9adcc52..8ffe275a 100644 --- a/tests/version.phpt +++ b/tests/version.phpt @@ -13,6 +13,6 @@ echo "OK" . PHP_EOL; --EXPECTF-- array(1) { ["%s:%d"]=> - string(6) "%d.%d.%d" + string(%d) "%d.%d.%d" } -OK \ No newline at end of file +OK From 35a543f0cb7a9825b8b19ddcf2ff44435a208355 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Wed, 4 Feb 2015 17:48:36 +0800 Subject: [PATCH 011/345] Fixed memory leak --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 500110af..be745c26 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1699,7 +1699,7 @@ static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &key, &expiration) == FAILURE) { return; } - server_key = zend_string_copy(key); + server_key = key; } MEMC_METHOD_FETCH_OBJECT; From cbcbece3619bd067d64094cc04f7d6a676a28b66 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Wed, 4 Feb 2015 17:54:26 +0800 Subject: [PATCH 012/345] Fixed getStat --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index be745c26..6a9776ab 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2927,7 +2927,7 @@ static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, php_ int hostport_len; struct callbackContext* context = (struct callbackContext*) in_context; zval entry; - hostport_len = spprintf(&hostport, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance) - 1); + hostport_len = spprintf(&hostport, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance)); array_init(&entry); From 6851bdd95f2a0f776fc55b4be8a43e2993a1268e Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Wed, 4 Feb 2015 18:01:11 +0800 Subject: [PATCH 013/345] Fixed memory leak --- php_memcached.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 6a9776ab..99eed2f1 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2548,16 +2548,9 @@ uint32_t *s_zval_to_uint32_array (zval *input, size_t *num_elements) if (Z_TYPE_P(pzval) == IS_LONG) { value = Z_LVAL_P(pzval); - } - else { - zval *tmp_zval, *tmp_pzval; - tmp_zval = pzval; - zval_copy_ctor(tmp_zval); - tmp_pzval = tmp_zval; - convert_to_long(tmp_pzval); - - value = (Z_LVAL_P(tmp_pzval) > 0) ? Z_LVAL_P(tmp_pzval) : 0; - zval_dtor(tmp_pzval); + } else { + value = zval_get_long(pzval); + value = value > 0? value : 0; } if (value < 0) { From 229c6842225876c8f8bfca8706616db516451bc8 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Wed, 4 Feb 2015 18:34:34 +0800 Subject: [PATCH 014/345] Better implementation --- php_memcached.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 99eed2f1..ef49c8ec 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3513,7 +3513,7 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i zval retval; zval z_key; zval z_val; - zval z_expiration; + zval *expiration, z_expiration; uint32_t flags = 0; memcached_return rc; @@ -3523,41 +3523,37 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i ZVAL_STR(&z_key, key); ZVAL_NULL(&z_val); - ZVAL_NEW_REF(value, &z_val); - ZVAL_NEW_REF(&z_expiration, &z_val); + ZVAL_NEW_REF(&z_val, value); + ZVAL_NEW_REF(&z_expiration, value); ZVAL_LONG(Z_REFVAL(z_expiration), 0); ZVAL_COPY(¶ms[0], zmemc_obj); ZVAL_COPY(¶ms[1], &z_key); - ZVAL_COPY(¶ms[2], value); - ZVAL_COPY(¶ms[3], &z_expiration); + ZVAL_COPY_VALUE(¶ms[2], &z_val); + ZVAL_COPY_VALUE(¶ms[3], &z_expiration); fci->retval = &retval; fci->params = params; fci->param_count = 4; result = zend_call_function(fci, fcc); - ZVAL_UNREF(value); - ZVAL_UNREF(&z_expiration); + ZVAL_DUP(value, Z_REFVAL(z_val)); + expiration = Z_REFVAL(z_expiration); if (result == SUCCESS && Z_TYPE(retval) != IS_UNDEF) { struct memc_obj *m_obj; i_obj = Z_MEMC_OBJ_P(zmemc_obj) m_obj = i_obj->obj; if (zend_is_true(&retval)) { - time_t expiration; + time_t expir; - if (Z_TYPE(z_expiration) != IS_LONG) { - convert_to_long(&z_expiration); - } - - expiration = Z_LVAL(z_expiration); + expir = zval_get_long(expiration); payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type); if (payload == NULL) { status = (memcached_return)MEMC_RES_PAYLOAD_FAILURE; } else { - rc = memcached_set(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); + rc = memcached_set(m_obj->memc, key->val, key->len, payload, payload_len, expir, flags); if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED) { status = rc; } @@ -3571,8 +3567,6 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i } else { if (result == FAILURE) { - zval_ptr_dtor(&z_key); - zval_ptr_dtor(&z_expiration); php_error_docref(NULL, E_WARNING, "could not invoke cache callback"); } status = MEMCACHED_FAILURE; @@ -3585,6 +3579,7 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i } zval_ptr_dtor(&z_key); + zval_ptr_dtor(&z_val); zval_ptr_dtor(&z_expiration); return status; From 1b2c2251f954d785c6ef9e05a8153eba69b96573 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Wed, 4 Feb 2015 20:52:34 +0800 Subject: [PATCH 015/345] Fixed memleak, and use the recently added object_size api --- php_memcached.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index ef49c8ec..3a25a1a6 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -546,6 +546,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) size_t key_lens[1] = { 0 }; zval *cas_token = NULL; zval *udf_flags = NULL; + uint64_t orig_cas_flag; zend_fcall_info fci = empty_fcall_info; zend_fcall_info_cache fcc = empty_fcall_info_cache; memcached_result_st result; @@ -575,7 +576,6 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) keys[0] = key->val; key_lens[0] = key->len; - uint64_t orig_cas_flag; orig_cas_flag = memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS); /* @@ -612,6 +612,8 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) * ourselves. */ if (cas_token) { + ZVAL_DEREF(cas_token); + zval_ptr_dtor(cas_token); ZVAL_DOUBLE(cas_token, 0.0); } @@ -653,8 +655,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) if (cas_token) { ZVAL_DEREF(cas_token); - SEPARATE_ZVAL(cas_token); - zval_dtor(cas_token); + zval_ptr_dtor(cas_token); ZVAL_DOUBLE(cas_token, (double)cas); } @@ -2839,7 +2840,7 @@ static void php_memc_free_storage(zend_object *obj) zend_object *php_memc_new(zend_class_entry *ce) { - php_memc_t *i_obj = ecalloc(1, sizeof(php_memc_t) + sizeof(zval) * (ce->default_properties_count - 1)); + php_memc_t *i_obj = ecalloc(1, sizeof(php_memc_t) + zend_object_properties_size(ce)); zend_object_std_init(&i_obj->zo, ce); object_properties_init(&i_obj->zo, ce); From e4f8f395f979a80e52ed04b32e6ce62eb2c9b298 Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Wed, 4 Feb 2015 08:16:57 -0800 Subject: [PATCH 016/345] Down to 18 failed tests now --- php_memcached.h | 1 - 1 file changed, 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index 2ce8e730..da4d6b92 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -21,7 +21,6 @@ #include "php.h" #include "main/php_config.h" -#include "Zend/zend_smart_str.h" #ifdef HAVE_CONFIG_H # include "config.h" From 1bb38ab0f7f58d2a7e91b90769e427a5066db4db Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Wed, 4 Feb 2015 09:37:06 -0800 Subject: [PATCH 017/345] Oops, need this for the inline stuff --- php_memcached.h | 1 + 1 file changed, 1 insertion(+) diff --git a/php_memcached.h b/php_memcached.h index da4d6b92..b96ef37a 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -20,6 +20,7 @@ #define PHP_MEMCACHED_H #include "php.h" +#include "Zend/zend_smart_str.h" #include "main/php_config.h" #ifdef HAVE_CONFIG_H From a9f703c3849a1056f356bdfc21ae1f3280fe2907 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Thu, 5 Feb 2015 11:15:51 +0800 Subject: [PATCH 018/345] Use strpprintf --- php_memcached.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 3a25a1a6..a1ea6835 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2760,11 +2760,9 @@ static PHP_METHOD(Memcached, getResultMessage) case MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE: case MEMCACHED_UNKNOWN_READ_FAILURE: if (i_obj->memc_errno) { - char *str; - int str_len; - str_len = spprintf(&str, 0, "%s: %s", memcached_strerror(m_obj->memc, (memcached_return)i_obj->rescode), - strerror(i_obj->memc_errno)); - RETURN_STRINGL(str, str_len); + zend_string *str = strpprintf(0, "%s: %s", + memcached_strerror(m_obj->memc, (memcached_return)i_obj->rescode), strerror(i_obj->memc_errno)); + RETURN_STR(str); } /* Fall through */ default: From 0021b5c08344b84cfe9504dc9b5cbfaac331942b Mon Sep 17 00:00:00 2001 From: Yasuo Ohgaki Date: Thu, 12 Feb 2015 13:28:52 +0900 Subject: [PATCH 019/345] Use new session save handler --- php_memcached_session.c | 62 +++++++++++++++++++++++++++++++++++++-- php_memcached_session.h | 5 +++- tests/session_basic2.phpt | 47 +++++++++++++++++++++++++++++ tests/session_basic3.phpt | 47 +++++++++++++++++++++++++++++ 4 files changed, 157 insertions(+), 4 deletions(-) create mode 100644 tests/session_basic2.phpt create mode 100644 tests/session_basic3.phpt diff --git a/php_memcached_session.c b/php_memcached_session.c index 1d2dbe32..4d1a2572 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -24,7 +24,7 @@ extern ZEND_DECLARE_MODULE_GLOBALS(php_memcached) #define MEMC_SESS_LOCK_EXPIRATION 30 ps_module ps_mod_memcached = { - PS_MOD(memcached) + PS_MOD_UPDATE_TIMESTAMP(memcached) }; static int php_memc_sess_lock(memcached_st *memc, const char *key) @@ -346,8 +346,8 @@ PS_WRITE_FUNC(memcached) return FAILURE; } - if (PS(gc_maxlifetime) > 0) { - expiration = PS(gc_maxlifetime); + if (maxlifetime > 0) { + expiration = maxlifetime; } /* Set the number of write retry attempts to the number of replicas times the number of attempts to remove a server plus the initial write */ @@ -383,4 +383,60 @@ PS_GC_FUNC(memcached) { return SUCCESS; } + +PS_CREATE_SID_FUNC(memcached) +{ + zend_string *sid; + int maxfail = 3; + memcached_sess *memc_sess = PS_GET_MOD_DATA(); + + do { + sid = php_session_create_id((void**)&memc_sess); + if (!sid) { + if (--maxfail < 0) { + return NULL; + } else { + continue; + } + } + /* Check collision */ + /* FIXME: mod_data(memc_sess) should not be NULL (User handler could be NULL) */ + if (memc_sess && memcached_exist(memc_sess->memc_sess, sid->val, sid->len) == MEMCACHED_SUCCESS) { + if (sid) { + zend_string_release(sid); + sid = NULL; + } + if (--maxfail < 0) { + return NULL; + } + } + } while(!sid); + + return sid; +} + +PS_VALIDATE_SID_FUNC(memcached) +{ + memcached_sess *memc_sess = PS_GET_MOD_DATA(); + + if (memcached_exist(memc_sess->memc_sess, key->val, key->len) == MEMCACHED_SUCCESS) { + return SUCCESS; + } else { + return FAILURE; + } +} + +PS_UPDATE_TIMESTAMP_FUNC(memcached) +{ + memcached_sess *memc_sess = PS_GET_MOD_DATA(); + time_t expiration = 0; + + if (maxlifetime > 0) { + expiration = maxlifetime; + } + if (memcached_touch(memc_sess->memc_sess, key->val, key->len, expiration) == MEMCACHED_FAILURE) { + return FAILURE; + } + return SUCCESS; +} /* }}} */ diff --git a/php_memcached_session.h b/php_memcached_session.h index 97fe2005..4118362f 100644 --- a/php_memcached_session.h +++ b/php_memcached_session.h @@ -24,7 +24,7 @@ extern ps_module ps_mod_memcached; #define ps_memcached_ptr &ps_mod_memcached -PS_FUNCS(memcached); +PS_FUNCS_UPDATE_TIMESTAMP(memcached); PS_OPEN_FUNC(memcached); PS_CLOSE_FUNC(memcached); @@ -32,5 +32,8 @@ PS_READ_FUNC(memcached); PS_WRITE_FUNC(memcached); PS_DESTROY_FUNC(memcached); PS_GC_FUNC(memcached); +PS_CREATE_SID_FUNC(memcached); +PS_VALIDATE_SID_FUNC(memcached); +PS_UPDATE_TIMESTAMP_FUNC(memcached); #endif /* PHP_MEMCACHED_SESSION_H */ diff --git a/tests/session_basic2.phpt b/tests/session_basic2.phpt new file mode 100644 index 00000000..f99063a8 --- /dev/null +++ b/tests/session_basic2.phpt @@ -0,0 +1,47 @@ +--TEST-- +Session basic open, write, destroy +--SKIPIF-- + +--INI-- +memcached.sess_locking = on +memcached.sess_lock_wait = 150000 +memcached.sess_prefix = "memc.sess.key." +session.save_handler = memcached + +--FILE-- +TRUE); +$_SESSION['foo'] = 1; +session_write_close(); + +$_SESSION = NULL; + +var_dump($_SESSION); +session_start(); +var_dump($_SESSION); +session_write_close(); + +session_start(); +session_destroy(); + +session_start(); +var_dump($_SESSION); +session_write_close(); + + +--EXPECT-- +NULL +array(1) { + ["foo"]=> + int(1) +} +array(0) { +} diff --git a/tests/session_basic3.phpt b/tests/session_basic3.phpt new file mode 100644 index 00000000..fc4e7ae7 --- /dev/null +++ b/tests/session_basic3.phpt @@ -0,0 +1,47 @@ +--TEST-- +Session basic open, write, destroy +--SKIPIF-- + +--INI-- +memcached.sess_locking = on +memcached.sess_lock_wait = 150000 +memcached.sess_prefix = "memc.sess.key." +session.save_handler = memcached + +--FILE-- +TRUE); +$_SESSION['foo'] = 1; +session_write_close(); + +$_SESSION = NULL; + +var_dump($_SESSION); +session_start(); +var_dump($_SESSION); +session_write_close(); + +session_start(); +session_destroy(); + +session_start(); +var_dump($_SESSION); +session_write_close(); + + +--EXPECT-- +NULL +array(1) { + ["foo"]=> + int(1) +} +array(0) { +} From aa3bc57ac8807442ec707e6cd167ca246d2437e3 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Thu, 12 Feb 2015 15:53:32 +0800 Subject: [PATCH 020/345] Fixed mem issue (double free) --- php_memcached.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index a1ea6835..28675f14 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1299,14 +1299,8 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke retry: if (!by_key) { status = memcached_set(m_obj->memc, str_key->val, str_key->len, payload, payload_len, expiration, flags); - if (!skey) { - zend_string_release(str_key); - } } else { status = memcached_set_by_key(m_obj->memc, server_key->val, server_key->len, str_key->val, str_key->len, payload, payload_len, expiration, flags); - if (!skey) { - zend_string_release(str_key); - } } if (php_memc_handle_error(i_obj, status) < 0) { From 4187e2277fa7469b0b8a67045083dde1950cecc0 Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Wed, 22 Apr 2015 23:37:53 -0700 Subject: [PATCH 021/345] No more ZEND_CTOR_MAKE_NULL --- php_memcached.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 28675f14..1063b229 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -407,8 +407,7 @@ static PHP_METHOD(Memcached, __construct) zend_fcall_info fci = {0}; zend_fcall_info_cache fci_cache; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!f!S", &persistent_id, &fci, &fci_cache, &conn_str) == FAILURE) { - ZEND_CTOR_MAKE_NULL(); + if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "|S!f!S", &persistent_id, &fci, &fci_cache, &conn_str) == FAILURE) { return; } From 650b67c64ca8ac8bd140492fd1078015cb8eaa0b Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Sat, 27 Jun 2015 18:28:31 +0200 Subject: [PATCH 022/345] Update php_memcached.c --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 1063b229..9195bfcd 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3119,7 +3119,7 @@ zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, #ifdef HAVE_MEMCACHED_MSGPACK case SERIALIZER_MSGPACK: php_msgpack_serialize(buf, value); - if (!buf->c) { + if (!buf->s) { php_error_docref(NULL, E_WARNING, "could not serialize value with msgpack"); return 0; } From 2af8314b36a4842c76c53be02550653a57445cf1 Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Mon, 31 Aug 2015 17:47:08 +0100 Subject: [PATCH 023/345] moar tests passing --- php_memcached.c | 26 ++++++++++++------------- tests/clone.phpt | 5 ++++- tests/experimental/cas_invalid_key.phpt | 4 ++-- tests/experimental/delete_bykey.phpt | 4 ++-- 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 3a25a1a6..caf268cc 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -170,7 +170,7 @@ typedef struct { } php_memc_t; static inline php_memc_t *php_memc_fetch_object(zend_object *obj) { - return (php_memc_t *)((char *)(obj) - XtOffsetOf(php_memc_t, zo)); + return (php_memc_t *)((char *)obj - XtOffsetOf(php_memc_t, zo)); } #define Z_MEMC_OBJ_P(zv) php_memc_fetch_object(Z_OBJ_P(zv)); @@ -356,20 +356,17 @@ char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_ static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache, zend_string *persistent_id) { zend_bool ret = 1; - zval retval; - zval params[2]; + zval retval, id; if (persistent_id) { - ZVAL_STR(¶ms[1], persistent_id); + ZVAL_STR(&id, persistent_id); } else { - ZVAL_NULL(¶ms[1]); + ZVAL_NULL(&id); } - /* Call the cb */ - ZVAL_COPY(¶ms[0], object); + ZVAL_UNDEF(&retval); - fci->params = params; - fci->param_count = 2; + zend_fcall_info_argn(fci, 2, object, &id); fci->retval = &retval; fci->no_separation = 1; @@ -379,10 +376,12 @@ static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fc efree (buf); ret = 0; } + + if (Z_TYPE(retval) != IS_UNDEF) + zval_ptr_dtor(&retval); + + zend_fcall_info_args_clear(fci, 1); - zval_ptr_dtor(¶ms[0]); - zval_ptr_dtor(¶ms[1]); - zval_ptr_dtor(&retval); return ret; } @@ -408,7 +407,6 @@ static PHP_METHOD(Memcached, __construct) zend_fcall_info_cache fci_cache; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!f!S", &persistent_id, &fci, &fci_cache, &conn_str) == FAILURE) { - ZEND_CTOR_MAKE_NULL(); return; } @@ -3304,6 +3302,7 @@ zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_typ PHP_VAR_UNSERIALIZE_INIT(var_hash); if (!php_var_unserialize(value, (const unsigned char **)&payload_tmp, (const unsigned char *)payload_tmp + payload_len, &var_hash)) { + zval_ptr_dtor(value); ZVAL_FALSE(value); PHP_VAR_UNSERIALIZE_DESTROY(var_hash); php_error_docref(NULL, E_WARNING, "could not unserialize value"); @@ -3538,6 +3537,7 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i fci->param_count = 4; result = zend_call_function(fci, fcc); + ZVAL_DUP(value, Z_REFVAL(z_val)); expiration = Z_REFVAL(z_expiration); if (result == SUCCESS && Z_TYPE(retval) != IS_UNDEF) { diff --git a/tests/clone.phpt b/tests/clone.phpt index a0c49cd7..0b41c50c 100644 --- a/tests/clone.phpt +++ b/tests/clone.phpt @@ -12,4 +12,7 @@ $m = clone $m; echo "GOT HERE"; --EXPECTF-- -Fatal error: Trying to clone an uncloneable object of class Memcached in %s on line %d \ No newline at end of file +Fatal error: Uncaught Error: Trying to clone an uncloneable object of class Memcached in %s:6 +Stack trace: +#0 {main} + thrown in %s on line 6 diff --git a/tests/experimental/cas_invalid_key.phpt b/tests/experimental/cas_invalid_key.phpt index c01d2c8d..3a69e40e 100644 --- a/tests/experimental/cas_invalid_key.phpt +++ b/tests/experimental/cas_invalid_key.phpt @@ -11,11 +11,11 @@ error_reporting(0); var_dump($m->cas(0, '', true, 10)); echo $m->getResultMessage(), "\n"; -var_dump($m->cas(0, ' äö jas kjjhask d ', true, 10)); +var_dump($m->cas(0, ' äö jas kjjhask d ', true, 10)); # no spaces allowed echo $m->getResultMessage(), "\n"; --EXPECTF-- bool(false) A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE bool(false) -%rCLIENT ERROR|NOT FOUND%r +A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE diff --git a/tests/experimental/delete_bykey.phpt b/tests/experimental/delete_bykey.phpt index 87219539..9a198f15 100644 --- a/tests/experimental/delete_bykey.phpt +++ b/tests/experimental/delete_bykey.phpt @@ -21,7 +21,7 @@ var_dump($m->deleteByKey('keffe', '')); echo $m->getResultMessage(), "\n"; var_dump($m->deleteByKey('', 'keffe')); echo $m->getResultMessage(), "\n"; -var_dump($m->deleteByKey('keffe', 'äöåasäö åaösdäf asdf')); +var_dump($m->deleteByKey('keffe', 'äöåasäö åaösdäf asdf')); # no spaces allowed echo $m->getResultMessage(), "\n"; --EXPECTF-- string(3) "foo" @@ -37,4 +37,4 @@ A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE bool(false) NOT FOUND bool(false) -%rPROTOCOL ERROR|NOT FOUND|WRITE FAILURE|CLIENT ERROR%r +A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE From 20636b2ae39a9c17d0e5b955770746a82b2bf4bb Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Mon, 31 Aug 2015 18:22:15 +0100 Subject: [PATCH 024/345] down to four failures ... --- php_memcached.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index caf268cc..0c278505 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3582,6 +3582,7 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i zval_ptr_dtor(&z_key); zval_ptr_dtor(&z_val); zval_ptr_dtor(&z_expiration); + zval_ptr_dtor(zmemc_obj); return status; } @@ -3603,9 +3604,7 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, int rc = 0; php_memc_t *i_obj = NULL; - ZVAL_COPY(¶ms[0], zmemc_obj); fci->retval = &retval; - fci->params = params; fci->param_count = 2; payload = memcached_result_value(result); @@ -3624,7 +3623,6 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, } array_init(&z_result); - ZVAL_COPY(¶ms[1], &z_result); add_assoc_stringl_ex(&z_result, ZEND_STRL("key"), (char *)res_key, res_key_len); add_assoc_zval_ex(&z_result, ZEND_STRL("value"), &value); if (cas != 0) { @@ -3634,16 +3632,19 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, add_assoc_long_ex(&z_result, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); } + ZVAL_UNDEF(&retval); + zend_fcall_info_argn(fci, 2, zmemc_obj, &z_result); + if (zend_call_function(fci, fcc) == FAILURE) { php_error_docref(NULL, E_WARNING, "could not invoke result callback"); rc = -1; } - if (&retval) { + if (Z_TYPE(retval) != IS_UNDEF) { zval_ptr_dtor(&retval); } - zval_ptr_dtor(¶ms[0]); - zval_ptr_dtor(¶ms[1]); + + zend_fcall_info_args_clear(fci, 1); zval_ptr_dtor(&z_result); return rc; From a335533ec8a4b6390196f5a1310f95aba8d37efc Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Mon, 31 Aug 2015 19:08:15 +0100 Subject: [PATCH 025/345] another test expecting the wrong thing, it seems --- tests/experimental/get.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/experimental/get.phpt b/tests/experimental/get.phpt index 34537fc4..67e0b8f3 100644 --- a/tests/experimental/get.phpt +++ b/tests/experimental/get.phpt @@ -30,4 +30,4 @@ A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE string(4) "asdf" SUCCESS bool(false) -NOT FOUND +A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE From 08cb8ff24caea581e97287de7c3427b67b20b1e6 Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Tue, 1 Sep 2015 18:15:02 +0100 Subject: [PATCH 026/345] bring travis up --- .travis.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index d529cf50..04f90cec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,7 @@ language: php php: - - 5.5 - #- 5.4 - #- 5.3 + - 7.0 + env: - LIBMEMCACHED_VERSION=1.0.17 - LIBMEMCACHED_VERSION=1.0.16 From 3a8c8fd7a016460d683fc68591072fce0a5c0c04 Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Tue, 1 Sep 2015 18:30:46 +0100 Subject: [PATCH 027/345] disable stuff not available for 7 yet --- .travis/travis.sh | 10 +++++----- php_memcached.c | 2 +- tests/bad_construct.phpt | 13 ++++++++----- tests/experimental/get_bykey_cas.phpt | 2 +- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index f90cae9f..bda8646e 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -155,11 +155,11 @@ function run_memcached_tests() { pushd "${PHP_MEMCACHED_BUILD_DIR}/memcached-${PHP_MEMCACHED_VERSION}" # We have one xfail test, we run it separately - php run-tests.php -d extension=msgpack.so -d extension=igbinary.so -d extension=memcached.so -n ./tests/expire.phpt + php run-tests.php -d extension=memcached.so -n ./tests/expire.phpt rm ./tests/expire.phpt # Run normal tests - php run-tests.php -d extension=msgpack.so -d extension=igbinary.so -d extension=memcached.so -n ./tests/*.phpt + php run-tests.php -d extension=memcached.so -n ./tests/*.phpt retval=$? for i in `ls tests/*.out 2>/dev/null`; do echo "-- START ${i}"; @@ -213,14 +213,14 @@ case $ACTION in install_libmemcached # Install igbinary extension - install_igbinary + # install_igbinary # install msgpack - install_msgpack + # install_msgpack # install SASL if test "x$ENABLE_SASL" = "xyes"; then - install_sasl + # install_sasl fi ;; diff --git a/php_memcached.c b/php_memcached.c index 1cd97550..926db8a4 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -406,7 +406,7 @@ static PHP_METHOD(Memcached, __construct) zend_fcall_info fci = {0}; zend_fcall_info_cache fci_cache; - if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "|S!f!S", &persistent_id, &fci, &fci_cache, &conn_str) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!f!S", &persistent_id, &fci, &fci_cache, &conn_str) == FAILURE) { return; } diff --git a/tests/bad_construct.phpt b/tests/bad_construct.phpt index 06bc7236..ab3079cf 100644 --- a/tests/bad_construct.phpt +++ b/tests/bad_construct.phpt @@ -4,7 +4,7 @@ Memcached construct with bad arguments --FILE-- setOption (Memcached::OPT_BINARY_PROTOCOL, true)); echo "OK" . PHP_EOL; --EXPECTF-- -Memcached::__construct() expects parameter %s -NULL +Warning: Memcached::__construct() expects parameter 1 to be string, object given in %s on line 3 +Memcached::__construct() expects parameter 1 to be string, object given +object(Memcached)#1 (0) { +} -Warning: Memcached::setOption(): Memcached constructor was not called in %s on line %d +Warning: Memcached::setOption(): Memcached constructor was not called in %s on line 14 NULL -OK \ No newline at end of file +OK + diff --git a/tests/experimental/get_bykey_cas.phpt b/tests/experimental/get_bykey_cas.phpt index ad94013e..6990927b 100644 --- a/tests/experimental/get_bykey_cas.phpt +++ b/tests/experimental/get_bykey_cas.phpt @@ -59,7 +59,7 @@ string(4) "asdf" float(%d) SUCCESS bool(false) -NULL +float(0) NOT FOUND bool(false) NULL From aaed3531e56d9d785e158645fdd47ebe6a7cd31c Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Tue, 1 Sep 2015 18:34:27 +0100 Subject: [PATCH 028/345] some stabbing in the dark, why not --- .travis/travis.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index bda8646e..04f2603a 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -128,8 +128,9 @@ function build_php_memcached() { sasl_flag="--enable-memcached-sasl" fi - ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag --enable-memcached-json --enable-memcached-igbinary --enable-memcached-msgpack - make + # ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag --enable-memcached-json --enable-memcached-igbinary --enable-memcached-msgpack + ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag + make make install popd } @@ -220,7 +221,7 @@ case $ACTION in # install SASL if test "x$ENABLE_SASL" = "xyes"; then - # install_sasl + install_sasl fi ;; From d354bf6551bc070e0c6374df8cadbc2c9e9f13df Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Tue, 1 Sep 2015 19:07:42 +0100 Subject: [PATCH 029/345] update test to skip in appropriate versions (make travis more useful) --- tests/gh_155.phpt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/gh_155.phpt b/tests/gh_155.phpt index c1f02bc6..2e7f5643 100644 --- a/tests/gh_155.phpt +++ b/tests/gh_155.phpt @@ -1,7 +1,12 @@ --TEST-- Test for bug 155 --SKIPIF-- - + --FILE-- Date: Tue, 1 Sep 2015 19:12:52 +0100 Subject: [PATCH 030/345] omg, I'm a fumbling idiot --- tests/gh_155.phpt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/gh_155.phpt b/tests/gh_155.phpt index 2e7f5643..643085ae 100644 --- a/tests/gh_155.phpt +++ b/tests/gh_155.phpt @@ -2,10 +2,9 @@ Test for bug 155 --SKIPIF-- --FILE-- Date: Tue, 1 Sep 2015 20:45:47 +0100 Subject: [PATCH 031/345] fix json support --- .travis/travis.sh | 5 +++-- config.m4 | 30 +++--------------------------- php_memcached.c | 21 +++------------------ 3 files changed, 9 insertions(+), 47 deletions(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index 04f2603a..f045e594 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -73,6 +73,7 @@ function install_igbinary() { function install_msgpack() { git clone https://github.com/msgpack/msgpack-php.git pushd msgpack-php + git checkout php7 phpize ./configure make @@ -128,8 +129,8 @@ function build_php_memcached() { sasl_flag="--enable-memcached-sasl" fi - # ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag --enable-memcached-json --enable-memcached-igbinary --enable-memcached-msgpack - ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag + # ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag --enable-memcached-igbinary --enable-memcached-msgpack + ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag --enable-memcached-json make make install popd diff --git a/config.m4 b/config.m4 index 107f8cbe..ec1e4ae8 100644 --- a/config.m4 +++ b/config.m4 @@ -127,7 +127,7 @@ if test "$PHP_MEMCACHED" != "no"; then PHP_MEMCACHED_VERSION_MASK=`echo ${PHP_MEMCACHED_VERSION_ORIG} | awk 'BEGIN { FS = "."; } { printf "%d", ($1 * 1000 + $2) * 1000 + $3;}'` - if test $PHP_MEMCACHED_VERSION_MASK -ge 5003000; then + if test $PHP_MEMCACHED_VERSION_MASK -ge 7000000; then if test -f "$abs_srcdir/include/php/ext/json/php_json.h"; then json_inc_path="$abs_srcdir/include/php" elif test -f "$abs_srcdir/ext/json/php_json.h"; then @@ -145,33 +145,9 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_ERROR([Cannot find php_json.h]) else AC_DEFINE(HAVE_JSON_API,1,[Whether JSON API is available]) - AC_DEFINE(HAVE_JSON_API_5_3,1,[Whether JSON API for PHP 5.3 is available]) - AC_MSG_RESULT([$json_inc_path]) fi - elif test $PHP_MEMCACHED_VERSION_MASK -ge 5002009; then - dnl Check JSON for PHP 5.2.9+ - if test -f "$abs_srcdir/include/php/ext/json/php_json.h"; then - json_inc_path="$abs_srcdir/include/php" - elif test -f "$abs_srcdir/ext/json/php_json.h"; then - json_inc_path="$abs_srcdir" - elif test -f "$phpincludedir/ext/json/php_json.h"; then - json_inc_path="$phpincludedir" - else - for i in php php4 php5 php6; do - if test -f "$prefix/include/$i/ext/json/php_json.h"; then - json_inc_path="$prefix/include/$i" - fi - done - fi - if test "$json_inc_path" = ""; then - AC_MSG_ERROR([Cannot find php_json.h]) - else - AC_DEFINE(HAVE_JSON_API,1,[Whether JSON API is available]) - AC_DEFINE(HAVE_JSON_API_5_2,1,[Whether JSON API for PHP 5.2 is available]) - AC_MSG_RESULT([$json_inc_path]) - fi - else - AC_MSG_RESULT([the PHP version does not support JSON serialization API]) + else + AC_MSG_RESULT([this version of memcached is only suitable for PHP7+]) fi fi diff --git a/php_memcached.c b/php_memcached.c index 926db8a4..9f65e52f 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -37,7 +37,7 @@ #endif #include -#ifdef HAVE_JSON_API +#ifdef HAVE_JSON # include "ext/json/php_json.h" #endif @@ -49,13 +49,6 @@ # 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. - */ -#ifndef JSON_PARSER_DEFAULT_DEPTH -#define JSON_PARSER_DEFAULT_DEPTH 512 -#endif /**************************************** Custom options @@ -3102,11 +3095,7 @@ zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, case SERIALIZER_JSON: case SERIALIZER_JSON_ARRAY: { -#if HAVE_JSON_API_5_2 - php_json_encode(buf, value); -#elif HAVE_JSON_API_5_3 - php_json_encode(buf, value, 0); /* options */ -#endif + php_json_encode(buf, value, 0); MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_JSON); } break; @@ -3320,11 +3309,7 @@ zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_typ case MEMC_VAL_IS_JSON: #ifdef HAVE_JSON_API -# if HAVE_JSON_API_5_2 - php_json_decode(value, payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY)); -# elif HAVE_JSON_API_5_3 - php_json_decode(value, payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY), JSON_PARSER_DEFAULT_DEPTH); -# endif + php_json_decode(value, payload, payload_len, ,(serializer == SERIALIZER_JSON_ARRAY), JSON_PARSER_DEFAULT_DEPTH); #else ZVAL_FALSE(value); php_error_docref(NULL, E_WARNING, "could not unserialize value, no json support"); From b04d020aa7accfa51b1f552bcb9a2f44e45d1a7c Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Tue, 1 Sep 2015 20:52:00 +0100 Subject: [PATCH 032/345] minor woops --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 9f65e52f..fb68274a 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -37,7 +37,7 @@ #endif #include -#ifdef HAVE_JSON +#ifdef HAVE_JSON_API # include "ext/json/php_json.h" #endif From 2f5a5b06b1296f081148eafa1d08c89b2b035ab8 Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Tue, 1 Sep 2015 21:25:01 +0100 Subject: [PATCH 033/345] woops --- config.m4 | 1 + php_memcached.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/config.m4 b/config.m4 index ec1e4ae8..a4bbda4e 100644 --- a/config.m4 +++ b/config.m4 @@ -145,6 +145,7 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_ERROR([Cannot find php_json.h]) else AC_DEFINE(HAVE_JSON_API,1,[Whether JSON API is available]) + AC_MSG_RESULT([$json_inc_path]) fi else AC_MSG_RESULT([this version of memcached is only suitable for PHP7+]) diff --git a/php_memcached.c b/php_memcached.c index fb68274a..a6c338b8 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3309,7 +3309,7 @@ zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_typ case MEMC_VAL_IS_JSON: #ifdef HAVE_JSON_API - php_json_decode(value, payload, payload_len, ,(serializer == SERIALIZER_JSON_ARRAY), JSON_PARSER_DEFAULT_DEPTH); + php_json_decode(value, (char*) payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY), PHP_JSON_PARSER_DEFAULT_DEPTH); #else ZVAL_FALSE(value); php_error_docref(NULL, E_WARNING, "could not unserialize value, no json support"); From a24e439cb6f9c38d1a51c0df2cf6dab79e0a14bc Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Wed, 2 Sep 2015 08:06:48 +0100 Subject: [PATCH 034/345] tidy configure stuff for json --- .travis/travis.sh | 4 ++-- config.m4 | 54 +++++++++++++++-------------------------------- tests/types.inc | 5 +++-- 3 files changed, 22 insertions(+), 41 deletions(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index f045e594..e6733526 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -129,8 +129,8 @@ function build_php_memcached() { sasl_flag="--enable-memcached-sasl" fi - # ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag --enable-memcached-igbinary --enable-memcached-msgpack - ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag --enable-memcached-json + # ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag --enable-memcached-json --enable-memcached-msgpack --enable-memcached-igbinary + ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag make make install popd diff --git a/config.m4 b/config.m4 index a4bbda4e..48efd176 100644 --- a/config.m4 +++ b/config.m4 @@ -106,49 +106,29 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_RESULT([$session_inc_path]) fi fi - + if test "$PHP_MEMCACHED_JSON" != "no"; then AC_MSG_CHECKING([for json includes]) json_inc_path="" - - tmp_version=$PHP_VERSION - if test -z "$tmp_version"; then - if test -z "$PHP_CONFIG"; then - AC_MSG_ERROR([php-config not found]) - fi - PHP_MEMCACHED_VERSION_ORIG=`$PHP_CONFIG --version`; - else - PHP_MEMCACHED_VERSION_ORIG=$tmp_version - fi - if test -z $PHP_MEMCACHED_VERSION_ORIG; then - AC_MSG_ERROR([failed to detect PHP version, please report]) + if test -f "$abs_srcdir/include/php/ext/json/php_json.h"; then + json_inc_path="$abs_srcdir/include/php" + elif test -f "$abs_srcdir/ext/json/php_json.h"; then + json_inc_path="$abs_srcdir" + elif test -f "$phpincludedir/ext/json/php_json.h"; then + json_inc_path="$phpincludedir" + else + for i in php php4 php5 php6; do + if test -f "$prefix/include/$i/ext/json/php_json.h"; then + json_inc_path="$prefix/include/$i" + fi + done fi - - PHP_MEMCACHED_VERSION_MASK=`echo ${PHP_MEMCACHED_VERSION_ORIG} | awk 'BEGIN { FS = "."; } { printf "%d", ($1 * 1000 + $2) * 1000 + $3;}'` - - if test $PHP_MEMCACHED_VERSION_MASK -ge 7000000; then - if test -f "$abs_srcdir/include/php/ext/json/php_json.h"; then - json_inc_path="$abs_srcdir/include/php" - elif test -f "$abs_srcdir/ext/json/php_json.h"; then - json_inc_path="$abs_srcdir" - elif test -f "$phpincludedir/ext/json/php_json.h"; then - json_inc_path="$phpincludedir" - else - for i in php php4 php5 php6; do - if test -f "$prefix/include/$i/ext/json/php_json.h"; then - json_inc_path="$prefix/include/$i" - fi - done - fi - if test "$json_inc_path" = ""; then - AC_MSG_ERROR([Cannot find php_json.h]) - else - AC_DEFINE(HAVE_JSON_API,1,[Whether JSON API is available]) - AC_MSG_RESULT([$json_inc_path]) - fi + if test "$json_inc_path" = ""; then + AC_MSG_ERROR([Cannot find php_json.h]) else - AC_MSG_RESULT([this version of memcached is only suitable for PHP7+]) + AC_DEFINE(HAVE_JSON_API,1,[Whether JSON API is available]) + AC_MSG_RESULT([$json_inc_path]) fi fi diff --git a/tests/types.inc b/tests/types.inc index 5e0ad5d3..9532c8fc 100644 --- a/tests/types.inc +++ b/tests/types.inc @@ -54,11 +54,12 @@ function memc_types_test ($m, $options) if ($value == $actual && get_class($value) == get_class($actual)) continue; } - echo "=== $types[0] ===\n"; + echo "=== {$key} ===\n"; echo "Expected: "; - var_dump($types[1]); + var_dump($value); echo "Actual: "; var_dump($actual); + } } From d68098e61dc5d6501b3dbf08a3bf87837f4992cf Mon Sep 17 00:00:00 2001 From: Alex Samorukov Date: Thu, 12 Nov 2015 23:11:50 +0100 Subject: [PATCH 035/345] check if session was allocated on PS_OPEN_FUNC --- php_memcached_session.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/php_memcached_session.c b/php_memcached_session.c index a3ef5678..a4e89aed 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -270,6 +270,11 @@ PS_OPEN_FUNC(memcached) PS_CLOSE_FUNC(memcached) { memcached_sess *memc_sess = PS_GET_MOD_DATA(); + + if (!memc_sess) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); + return FAILURE; + } if (MEMC_G(sess_locking_enabled)) { php_memc_sess_unlock(memc_sess->memc_sess TSRMLS_CC); @@ -300,6 +305,11 @@ PS_READ_FUNC(memcached) memcached_sess *memc_sess = PS_GET_MOD_DATA(); size_t key_length; + if (!memc_sess) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); + return FAILURE; + } + key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock." if (!key_length || key_length >= MEMCACHED_MAX_KEY) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "The session id is too long or contains illegal characters"); @@ -334,6 +344,11 @@ PS_WRITE_FUNC(memcached) memcached_return status; memcached_sess *memc_sess = PS_GET_MOD_DATA(); size_t key_length; + + if (!memc_sess) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); + return FAILURE; + } key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock." if (!key_length || key_length >= MEMCACHED_MAX_KEY) { @@ -367,6 +382,11 @@ PS_DESTROY_FUNC(memcached) { memcached_sess *memc_sess = PS_GET_MOD_DATA(); + if (!memc_sess) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); + return FAILURE; + } + memcached_delete(memc_sess->memc_sess, key, strlen(key), 0); if (MEMC_G(sess_locking_enabled)) { php_memc_sess_unlock(memc_sess->memc_sess TSRMLS_CC); From 23db27a09ba3b35756305aa5bf487a9e530e9166 Mon Sep 17 00:00:00 2001 From: Alex Samorukov Date: Thu, 12 Nov 2015 23:20:44 +0100 Subject: [PATCH 036/345] check if session was allocated on PS_OPEN_FUNC --- php_memcached_session.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/php_memcached_session.c b/php_memcached_session.c index 1d2dbe32..b04cd925 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -277,6 +277,11 @@ PS_OPEN_FUNC(memcached) PS_CLOSE_FUNC(memcached) { memcached_sess *memc_sess = PS_GET_MOD_DATA(); + + if (!memc_sess) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); + return FAILURE; + } if (MEMC_G(sess_locking_enabled)) { php_memc_sess_unlock(memc_sess->memc_sess); @@ -307,6 +312,11 @@ PS_READ_FUNC(memcached) memcached_sess *memc_sess = PS_GET_MOD_DATA(); size_t key_length; + if (!memc_sess) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); + return FAILURE; + } + key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock." if (!key_length || key_length >= MEMCACHED_MAX_KEY) { php_error_docref(NULL, E_WARNING, "The session id is too long or contains illegal characters"); @@ -339,6 +349,11 @@ PS_WRITE_FUNC(memcached) memcached_return status; memcached_sess *memc_sess = PS_GET_MOD_DATA(); size_t key_length; + + if (!memc_sess) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); + return FAILURE; + } key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock." if (!key_length || key_length >= MEMCACHED_MAX_KEY) { @@ -371,6 +386,11 @@ PS_DESTROY_FUNC(memcached) { memcached_sess *memc_sess = PS_GET_MOD_DATA(); + if (!memc_sess) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); + return FAILURE; + } + memcached_delete(memc_sess->memc_sess, key->val, key->len, 0); if (MEMC_G(sess_locking_enabled)) { php_memc_sess_unlock(memc_sess->memc_sess); From fb8ce9e3cbfdacb50dc8b916e8502bb9e58d2e20 Mon Sep 17 00:00:00 2001 From: Will Gallego Date: Tue, 17 Nov 2015 20:52:04 +0000 Subject: [PATCH 037/345] removing unused var, fixing smart_str use w/ igbinary --- php_memcached.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index a6c338b8..a96a2aed 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3080,7 +3080,7 @@ zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, */ #ifdef HAVE_MEMCACHED_IGBINARY case SERIALIZER_IGBINARY: - if (igbinary_serialize((uint8_t **) &buf->c, &buf->len, value) != 0) { + if (igbinary_serialize((uint8_t **) &(buf->s), &buf->s->len, value) != 0) { php_error_docref(NULL, E_WARNING, "could not serialize value with igbinary"); return 0; } @@ -3575,7 +3575,6 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, zval value; zval retval; uint64_t cas = 0; - zval params[2]; zval z_result; uint32_t flags = 0; int rc = 0; From b5a58cd207ca50df9288ba124c37fda65e1e1d4b Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Wed, 16 Dec 2015 13:42:28 +0000 Subject: [PATCH 038/345] remove duplicate class constant registration --- php_memcached.c | 1 - 1 file changed, 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index a6c338b8..72637d1c 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -4319,7 +4319,6 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(RES_MEMORY_ALLOCATION_FAILURE, MEMCACHED_MEMORY_ALLOCATION_FAILURE); REGISTER_MEMC_CLASS_CONST_LONG(RES_CONNECTION_SOCKET_CREATE_FAILURE, MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE); - REGISTER_MEMC_CLASS_CONST_LONG(RES_BAD_KEY_PROVIDED, MEMCACHED_BAD_KEY_PROVIDED); REGISTER_MEMC_CLASS_CONST_LONG(RES_E2BIG, MEMCACHED_E2BIG); REGISTER_MEMC_CLASS_CONST_LONG(RES_KEY_TOO_BIG, MEMCACHED_KEY_TOO_BIG); REGISTER_MEMC_CLASS_CONST_LONG(RES_SERVER_TEMPORARILY_DISABLED, MEMCACHED_SERVER_TEMPORARILY_DISABLED); From bd321830676d7e313b4b39bec6fbeb6ec9f9f7d8 Mon Sep 17 00:00:00 2001 From: Yasuo Ohgaki Date: Sat, 16 Jan 2016 06:19:50 +0900 Subject: [PATCH 039/345] Fixed session read return value --- php_memcached_session.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/php_memcached_session.c b/php_memcached_session.c index 4d1a2572..59b12467 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -326,6 +326,8 @@ PS_READ_FUNC(memcached) *val = zend_string_init(payload, payload_len, 1); free(payload); return SUCCESS; + } else if (status = MEMCACHED_NOTFOUND) { + *val = ZSTR_EMPTY_ALLOC(); } else { return FAILURE; } From 9e11ffa8e5d5e6b1256dc44b7f043e7114122170 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 16 Jan 2016 21:40:35 +0000 Subject: [PATCH 040/345] Revert the user flags and move into Memcached::getLastUserFlags --- php_memcached.c | 194 +++++++++++++++++++++--------------------- tests/user-flags.phpt | 72 +++++++++++----- 2 files changed, 148 insertions(+), 118 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index a6c338b8..1339f308 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -58,6 +58,7 @@ #define MEMC_OPT_SERIALIZER -1003 #define MEMC_OPT_COMPRESSION_TYPE -1004 #define MEMC_OPT_STORE_RETRY_COUNT -1005 +#define MEMC_OPT_USER_FLAGS -1006 /**************************************** Custom result codes @@ -153,8 +154,10 @@ typedef struct { zend_bool has_sasl_data; #endif long store_retry_count; + zend_long set_udf_flags; } *obj; + zval last_udf_flags; zend_bool is_persistent; zend_bool is_pristine; int rescode; @@ -466,6 +469,9 @@ static PHP_METHOD(Memcached, __construct) m_obj->compression = 1; m_obj->store_retry_count = MEMC_G(store_retry_count); + m_obj->set_udf_flags = -1; + array_init(&i_obj->last_udf_flags); + i_obj->obj = m_obj; i_obj->is_pristine = 1; @@ -508,7 +514,23 @@ static PHP_METHOD(Memcached, __construct) } /* }}} */ -/* {{{ Memcached::get(string key [, mixed callback [, double &cas_token [, int &udf_flags ] ] ]) +/* {{{ Memcached::getLastUserFlags() + Returns the user flags from last fetch operation */ +PHP_METHOD(Memcached, getLastUserFlags) +{ + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + RETVAL_ZVAL(&i_obj->last_udf_flags, 1, 0); +} +/* }}} */ + + +/* {{{ Memcached::get(string key [, mixed callback [, double &cas_token ] ]) Returns a value for the given key or false */ PHP_METHOD(Memcached, get) { @@ -516,7 +538,7 @@ PHP_METHOD(Memcached, get) } /* }}} */ -/* {{{ Memcached::getByKey(string server_key, string key [, mixed callback [, double &cas_token [, int &udf_flags ] ] ]) +/* {{{ Memcached::getByKey(string server_key, string key [, mixed callback [, double &cas_token ] ]) Returns a value for key from the server identified by the server key or false */ PHP_METHOD(Memcached, getByKey) { @@ -536,7 +558,6 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) const char* keys[1] = { NULL }; size_t key_lens[1] = { 0 }; zval *cas_token = NULL; - zval *udf_flags = NULL; uint64_t orig_cas_flag; zend_fcall_info fci = empty_fcall_info; zend_fcall_info_cache fcc = empty_fcall_info_cache; @@ -545,13 +566,11 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|f!zz", &server_key, &key, - &fci, &fcc, &cas_token, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|f!z", &server_key, &key, &fci, &fcc, &cas_token) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|f!zz", &key, - &fci, &fcc, &cas_token, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|f!z", &key, &fci, &fcc, &cas_token) == FAILURE) { return; } } @@ -559,7 +578,9 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key->len == 0 || strchr(key->val, ' ')) { + zend_hash_clean(Z_ARRVAL(i_obj->last_udf_flags)); + + if (key->len == 0) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FROM_GET; } @@ -650,18 +671,13 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) ZVAL_DOUBLE(cas_token, (double)cas); } - if (udf_flags) { - ZVAL_DEREF(udf_flags); - SEPARATE_ZVAL(udf_flags); - zval_dtor(udf_flags); - ZVAL_LONG(udf_flags, MEMC_VAL_GET_USER_FLAGS(flags)); - } - + /* Parse user flags */ + add_assoc_long_ex(&i_obj->last_udf_flags, key->val, key->len, MEMC_VAL_GET_USER_FLAGS(flags)); memcached_result_free(&result); } /* }}} */ -/* {{{ Memcached::getMulti(array keys [, array &cas_tokens [, array &udf_flags ] ]) +/* {{{ Memcached::getMulti(array keys [, array &cas_tokens ]) Returns values for the given keys or false */ PHP_METHOD(Memcached, getMulti) { @@ -669,7 +685,7 @@ PHP_METHOD(Memcached, getMulti) } /* }}} */ -/* {{{ Memcached::getMultiByKey(string server_key, array keys [, array &cas_tokens [, array &udf_flags ] ]) +/* {{{ Memcached::getMultiByKey(string server_key, array keys [, array &cas_tokens ]) Returns values for the given keys from the server identified by the server key or false */ PHP_METHOD(Memcached, getMultiByKey) { @@ -693,7 +709,6 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke uint32_t flags; uint64_t cas = 0; zval *cas_tokens = NULL; - zval *udf_flags = NULL; uint64_t orig_cas_flag = 0; zval value; long get_flags = 0; @@ -704,12 +719,12 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|zlz", &server_key, - &keys, &cas_tokens, &get_flags, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|zl", &server_key, + &keys, &cas_tokens, &get_flags) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|zlz", &keys, &cas_tokens, &get_flags, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|zl", &keys, &cas_tokens, &get_flags) == FAILURE) { return; } } @@ -717,6 +732,9 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; + /* clean flags */ + zend_hash_clean(Z_ARRVAL(i_obj->last_udf_flags)); + preserve_order = (get_flags & MEMC_GET_PRESERVE_ORDER); num_keys = zend_hash_num_elements(Z_ARRVAL_P(keys)); mkeys = safe_emalloc(num_keys, sizeof(*mkeys), 0); @@ -801,12 +819,6 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke * Iterate through the result set and create the result array. The flags are * returned as longs. */ - if (udf_flags) { - ZVAL_DEREF(udf_flags); - SEPARATE_ZVAL(udf_flags); - zval_dtor(udf_flags); - array_init(udf_flags); - } memcached_result_create(m_obj->memc, &result); while ((memcached_fetch_result(m_obj->memc, &result, &status)) != NULL) { @@ -851,9 +863,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke cas = memcached_result_cas(&result); add_assoc_double_ex(cas_tokens, res_key, res_key_len, (double)cas); } - if (udf_flags) { - add_assoc_long_ex(udf_flags, res_key, res_key_len, MEMC_VAL_GET_USER_FLAGS(flags)); - } + add_assoc_long_ex(&i_obj->last_udf_flags, res_key, res_key_len, MEMC_VAL_GET_USER_FLAGS(flags)); } memcached_result_free(&result); @@ -866,12 +876,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke zval_dtor(cas_tokens); ZVAL_NULL(cas_tokens); } - if (udf_flags) { - ZVAL_DEREF(udf_flags); - SEPARATE_ZVAL(udf_flags); - zval_dtor(udf_flags); - ZVAL_NULL(udf_flags); - } + zend_hash_clean(Z_ARRVAL(i_obj->last_udf_flags)); zval_dtor(return_value); RETURN_FALSE; } @@ -1136,7 +1141,7 @@ PHP_METHOD(Memcached, fetchAll) } /* }}} */ -/* {{{ Memcached::set(string key, mixed value [, int expiration [, int udf_flags ] ]) +/* {{{ Memcached::set(string key, mixed value [, int expiration ]) Sets the value for the given key */ PHP_METHOD(Memcached, set) { @@ -1144,7 +1149,7 @@ PHP_METHOD(Memcached, set) } /* }}} */ -/* {{{ Memcached::setByKey(string server_key, string key, mixed value [, int expiration [, int udf_flags ] ]) +/* {{{ Memcached::setByKey(string server_key, string key, mixed value [, int expiration ]) Sets the value for the given key on the server identified by the server key */ PHP_METHOD(Memcached, setByKey) { @@ -1171,7 +1176,7 @@ PHP_METHOD(Memcached, touchByKey) #endif -/* {{{ Memcached::setMulti(array items [, int expiration [, int udf_flags ] ]) +/* {{{ Memcached::setMulti(array items [, int expiration ]) Sets the keys/values specified in the items array */ PHP_METHOD(Memcached, setMulti) { @@ -1179,7 +1184,7 @@ PHP_METHOD(Memcached, setMulti) } /* }}} */ -/* {{{ Memcached::setMultiByKey(string server_key, array items [, int expiration [, int udf_flags ] ]) +/* {{{ Memcached::setMultiByKey(string server_key, array items [, int expiration ]) Sets the keys/values specified in the items array on the server identified by the given server key */ PHP_METHOD(Memcached, setMultiByKey) { @@ -1218,7 +1223,6 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke zval *entries; zend_string *server_key = NULL; time_t expiration = 0; - long udf_flags = 0; zval *entry; zend_string *skey, *str_key = NULL; ulong num_key; @@ -1233,11 +1237,11 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke if (by_key) { if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa|ll", &server_key, - &entries, &expiration, &udf_flags) == FAILURE) { + &entries, &expiration) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|ll", &entries, &expiration, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|ll", &entries, &expiration) == FAILURE) { return; } } @@ -1245,16 +1249,6 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - /* - * php_memcached uses 16 bits internally to store type, compression and serialization info. - * We use 16 upper bits to store user defined flags. - */ - if (udf_flags > 0) { - if ((uint32_t) udf_flags > MEMC_VAL_USER_FLAGS_MAX) { - php_error_docref(NULL, E_WARNING, "udf_flags will be limited to %u", MEMC_VAL_USER_FLAGS_MAX); - } - } - ZEND_HASH_FOREACH_KEY_VAL (Z_ARRVAL_P(entries), num_key, skey, entry) { if (skey) { str_key = skey; @@ -1274,8 +1268,8 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke MEMC_VAL_SET_FLAG(flags, MEMC_VAL_COMPRESSED); } - if (udf_flags > 0) { - MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) udf_flags)); + if (m_obj->set_udf_flags >= 0) { + MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) m_obj->set_udf_flags)); } payload = php_memc_zval_to_payload(entry, &payload_len, &flags, m_obj->serializer, m_obj->compression_type); @@ -1312,7 +1306,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke } /* }}} */ -/* {{{ Memcached::add(string key, mixed value [, int expiration [, int udf_flags ] ]) +/* {{{ Memcached::add(string key, mixed value [, int expiration ]) Sets the value for the given key, failing if the key already exists */ PHP_METHOD(Memcached, add) { @@ -1320,7 +1314,7 @@ PHP_METHOD(Memcached, add) } /* }}} */ -/* {{{ Memcached::addByKey(string server_key, string key, mixed value [, int expiration [, int udf_flags ] ]) +/* {{{ Memcached::addByKey(string server_key, string key, mixed value [, int expiration ]) Sets the value for the given key on the server identified by the sever key, failing if the key already exists */ PHP_METHOD(Memcached, addByKey) { @@ -1360,7 +1354,7 @@ PHP_METHOD(Memcached, prependByKey) } /* }}} */ -/* {{{ Memcached::replace(string key, mixed value [, int expiration [, int udf_flags ] ]) +/* {{{ Memcached::replace(string key, mixed value [, int expiration ]) Replaces the value for the given key, failing if the key doesn't exist */ PHP_METHOD(Memcached, replace) { @@ -1368,7 +1362,7 @@ PHP_METHOD(Memcached, replace) } /* }}} */ -/* {{{ Memcached::replaceByKey(string server_key, string key, mixed value [, int expiration [, int udf_flags ] ]) +/* {{{ Memcached::replaceByKey(string server_key, string key, mixed value [, int expiration ]) Replaces the value for the given key on the server identified by the server key, failing if the key doesn't exist */ PHP_METHOD(Memcached, replaceByKey) { @@ -1385,7 +1379,6 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool zval s_zvalue; zval *value; long expiration = 0; - long udf_flags = 0; char *payload = NULL; size_t payload_len; uint32_t flags = 0; @@ -1405,7 +1398,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSz|ll", &server_key, &key, &value, &expiration, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSz|l", &server_key, &key, &value, &expiration) == FAILURE) { return; } } @@ -1421,7 +1414,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|ll", &key, &value, &expiration, &udf_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|l", &key, &value, &expiration) == FAILURE) { return; } } @@ -1430,7 +1423,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key->len == 0 || strchr(key->val, ' ')) { + if (key->len == 0) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1452,11 +1445,8 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool * php_memcached uses 16 bits internally to store type, compression and serialization info. * We use 16 upper bits to store user defined flags. */ - if (udf_flags > 0) { - if ((uint32_t) udf_flags > MEMC_VAL_USER_FLAGS_MAX) { - php_error_docref(NULL, E_WARNING, "udf_flags will be limited to %u", MEMC_VAL_USER_FLAGS_MAX); - } - MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) udf_flags)); + if (m_obj->set_udf_flags >= 0) { + MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) m_obj->set_udf_flags)); } if (op == MEMC_OP_TOUCH) { @@ -1557,7 +1547,6 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) zend_string *server_key = NULL; zval *value; time_t expiration = 0; - long udf_flags = 0; char *payload; size_t payload_len; uint32_t flags = 0; @@ -1566,12 +1555,12 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) if (by_key) { if (zend_parse_parameters(ZEND_NUM_ARGS(), "dSSz|ll", &cas_d, &server_key, &key, - &value, &expiration, &udf_flags) == FAILURE) { + &value, &expiration) == FAILURE) { return; } } else { if (zend_parse_parameters(ZEND_NUM_ARGS(), "dSz|ll", &cas_d, &key, &value, - &expiration, &udf_flags) == FAILURE) { + &expiration) == FAILURE) { return; } } @@ -1579,7 +1568,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key->len == 0 || strchr(key->val, ' ')) { + if (key->len == 0) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1594,11 +1583,8 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) * php_memcached uses 16 bits internally to store type, compression and serialization info. * We use 16 upper bits to store user defined flags. */ - if (udf_flags > 0) { - if ((uint32_t) udf_flags > MEMC_VAL_USER_FLAGS_MAX) { - php_error_docref(NULL, E_WARNING, "udf_flags will be limited to %u", MEMC_VAL_USER_FLAGS_MAX); - } - MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) udf_flags)); + if (m_obj->set_udf_flags > 0) { + MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) m_obj->set_udf_flags)); } payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type); @@ -1621,7 +1607,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) } /* }}} */ -/* {{{ Memcached::cas(double cas_token, string key, mixed value [, int expiration [, int udf_flags ] ]) +/* {{{ Memcached::cas(double cas_token, string key, mixed value [, int expiration ]) Sets the value for the given key, failing if the cas_token doesn't match the one in memcache */ PHP_METHOD(Memcached, cas) { @@ -1629,7 +1615,7 @@ PHP_METHOD(Memcached, cas) } /* }}} */ -/* {{{ Memcached::casByKey(double cas_token, string server_key, string key, mixed value [, int expiration [, int udf_flags ] ]) +/* {{{ Memcached::casByKey(double cas_token, string server_key, string key, mixed value [, int expiration ]) Sets the value for the given key on the server identified by the server_key, failing if the cas_token doesn't match the one in memcache */ PHP_METHOD(Memcached, casByKey) { @@ -2344,6 +2330,10 @@ static PHP_METHOD(Memcached, getOption) RETURN_LONG((long)m_obj->serializer); break; + case MEMC_OPT_USER_FLAGS: + RETURN_LONG(m_obj->set_udf_flags); + break; + case MEMC_OPT_STORE_RETRY_COUNT: RETURN_LONG((long)m_obj->store_retry_count); break; @@ -2481,6 +2471,21 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value) break; } + case MEMC_OPT_USER_FLAGS: + convert_to_long(value); + + if (Z_LVAL_P(value) < 0) { + m_obj->set_udf_flags = -1; + return 1; + } + + if (Z_LVAL_P(value) > MEMC_VAL_USER_FLAGS_MAX) { + php_error_docref(NULL, E_WARNING, "MEMC_OPT_USER_FLAGS must be < %u", MEMC_VAL_USER_FLAGS_MAX); + return 0; + } + m_obj->set_udf_flags = Z_LVAL_P(value); + break; + case MEMC_OPT_STORE_RETRY_COUNT: convert_to_long(value); m_obj->store_retry_count = Z_LVAL_P(value); @@ -2805,23 +2810,23 @@ static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent) if (m_obj->memc) { memcached_free(m_obj->memc); } - pefree(m_obj, persistent); } static void php_memc_free_storage(zend_object *obj) { php_memc_t *i_obj = php_memc_fetch_object(obj); - + if (i_obj->obj && !i_obj->is_persistent) { php_memc_destroy(i_obj->obj, 0); } + zval_ptr_dtor(&i_obj->last_udf_flags); zend_object_std_dtor(&i_obj->zo); i_obj->obj = NULL; } -zend_object *php_memc_new(zend_class_entry *ce) +static zend_object *php_memc_new(zend_class_entry *ce) { php_memc_t *i_obj = ecalloc(1, sizeof(php_memc_t) + zend_object_properties_size(ce)); @@ -3514,7 +3519,7 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i fci->param_count = 4; result = zend_call_function(fci, fcc); - + ZVAL_DUP(value, Z_REFVAL(z_val)); expiration = Z_REFVAL(z_expiration); if (result == SUCCESS && Z_TYPE(retval) != IS_UNDEF) { @@ -3552,7 +3557,7 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i ZVAL_NULL(value); } - if (&retval) { + if (!Z_ISUNDEF(retval)) { zval_ptr_dtor(&retval); } @@ -3712,7 +3717,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_get, 0, 0, 1) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, cache_cb) ZEND_ARG_INFO(2, cas_token) - ZEND_ARG_INFO(1, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getByKey, 0, 0, 2) @@ -3720,14 +3724,12 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_getByKey, 0, 0, 2) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, cache_cb) ZEND_ARG_INFO(2, cas_token) - ZEND_ARG_INFO(1, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getMulti, 0, 0, 1) ZEND_ARG_ARRAY_INFO(0, keys, 0) ZEND_ARG_INFO(2, cas_tokens) ZEND_ARG_INFO(0, flags) - ZEND_ARG_INFO(1, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getMultiByKey, 0, 0, 2) @@ -3735,7 +3737,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_getMultiByKey, 0, 0, 2) ZEND_ARG_ARRAY_INFO(0, keys, 0) ZEND_ARG_INFO(2, cas_tokens) ZEND_ARG_INFO(0, flags) - ZEND_ARG_INFO(1, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getDelayed, 0, 0, 1) @@ -3761,7 +3762,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_set, 0, 0, 2) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(0, expiration) - ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_setByKey, 0, 0, 3) @@ -3769,7 +3769,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_setByKey, 0, 0, 3) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(0, expiration) - ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_touch, 0, 0, 2) @@ -3786,21 +3785,21 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_setMulti, 0, 0, 1) ZEND_ARG_ARRAY_INFO(0, items, 0) ZEND_ARG_INFO(0, expiration) - ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_setMultiByKey, 0, 0, 2) ZEND_ARG_INFO(0, server_key) ZEND_ARG_ARRAY_INFO(0, items, 0) ZEND_ARG_INFO(0, expiration) - ZEND_ARG_INFO(0, udf_flags) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_getLastUserFlags, 0, 0, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_add, 0, 0, 2) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(0, expiration) - ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_addByKey, 0, 0, 3) @@ -3808,14 +3807,12 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_addByKey, 0, 0, 3) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(0, expiration) - ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_replace, 0, 0, 2) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(0, expiration) - ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_replaceByKey, 0, 0, 3) @@ -3823,7 +3820,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_replaceByKey, 0, 0, 3) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(0, expiration) - ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_append, 0, 0, 2) @@ -3857,7 +3853,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_cas, 0, 0, 3) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(0, expiration) - ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_casByKey, 0, 0, 4) @@ -3866,7 +3861,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_casByKey, 0, 0, 4) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(0, expiration) - ZEND_ARG_INFO(0, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_delete, 0, 0, 1) @@ -4029,6 +4023,8 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(setMulti, arginfo_setMulti) MEMC_ME(setMultiByKey, arginfo_setMultiByKey) + MEMC_ME(getLastUserFlags, arginfo_getLastUserFlags) + MEMC_ME(cas, arginfo_cas) MEMC_ME(casByKey, arginfo_casByKey) MEMC_ME(add, arginfo_add) @@ -4187,6 +4183,8 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(OPT_COMPRESSION_TYPE, MEMC_OPT_COMPRESSION_TYPE); REGISTER_MEMC_CLASS_CONST_LONG(OPT_PREFIX_KEY, MEMC_OPT_PREFIX_KEY); REGISTER_MEMC_CLASS_CONST_LONG(OPT_SERIALIZER, MEMC_OPT_SERIALIZER); + + REGISTER_MEMC_CLASS_CONST_LONG(OPT_USER_FLAGS, MEMC_OPT_USER_FLAGS); REGISTER_MEMC_CLASS_CONST_LONG(OPT_STORE_RETRY_COUNT, MEMC_OPT_STORE_RETRY_COUNT); /* diff --git a/tests/user-flags.phpt b/tests/user-flags.phpt index 2ed44c9a..137ff1e8 100644 --- a/tests/user-flags.phpt +++ b/tests/user-flags.phpt @@ -22,46 +22,78 @@ define ('FLAG_4', 4); define ('FLAG_32', 32); define ('FLAG_64', 64); define ('FLAG_TOO_LARGE', pow(2, 16)); -$x = 0; include dirname (__FILE__) . '/config.inc'; $m = memc_get_instance (array (Memcached::OPT_BINARY_PROTOCOL => true)); $key = uniqid ('udf_test_'); -echo "stored with flags" . PHP_EOL; +// Set with flags off +$m->set ($key, '1', 10); +$m->get($key); +var_dump($m->getLastUserFlags()); -$m->set ($key, '1', 10, FLAG_1 | FLAG_4 | FLAG_64); -$udf_flags = 0; -$value = $m->get ($key, null, $x, $udf_flags); +// Set flags on +$m->setOption(Memcached::OPT_USER_FLAGS, FLAG_1); +$m->set ($key, '1', 10); +$m->get($key); +check_flags($m->getLastUserFlags()[$key], array(FLAG_1)); -check_flags ($udf_flags, array (FLAG_1, FLAG_4, FLAG_64)); +// Multiple flags +$m->setOption(Memcached::OPT_USER_FLAGS, FLAG_1 | FLAG_2 | FLAG_4); +$m->set ($key, '1', 10); +$m->get($key); +check_flags($m->getLastUserFlags()[$key], array(FLAG_1, FLAG_2, FLAG_4)); -echo "stored without flags" . PHP_EOL; -$m->set ($key, '1'); -$value = $m->get ($key, null, $x, $udf_flags); +// Even more flags +$m->setOption(Memcached::OPT_USER_FLAGS, FLAG_1 | FLAG_2 | FLAG_4 | FLAG_32 | FLAG_64); +$m->set ($key, '1', 10); +$m->get($key); +check_flags($m->getLastUserFlags()[$key], array(FLAG_1, FLAG_2, FLAG_4, FLAG_32, FLAG_64)); -var_dump ($udf_flags == 0); -$m->set ($key, '1', 10, FLAG_TOO_LARGE); +// User flags with get multi +$values = array( + uniqid ('udf_test_multi_') => "first", + uniqid ('udf_test_multi_') => "second", + uniqid ('udf_test_multi_') => "third", +); +$m->setOption(Memcached::OPT_USER_FLAGS, FLAG_2 | FLAG_4); +$m->setMulti($values); +$m->getMulti(array_keys($values)); +$flags = $m->getLastUserFlags(); + +foreach (array_keys($values) as $key) { + check_flags($flags[$key], array(FLAG_2, FLAG_4)); +} + +// User flags with compression on +$m->setOption(Memcached::OPT_USER_FLAGS, FLAG_1 | FLAG_2 | FLAG_4); $m->setOption(Memcached::OPT_COMPRESSION, true); $m->setOption(Memcached::OPT_COMPRESSION_TYPE, Memcached::COMPRESSION_FASTLZ); -$m->set ($key, str_repeat ("abcdef1234567890", 200), 10, FLAG_1 | FLAG_4 | FLAG_64); +$m->set ($key, '1', 10); +$m->get($key); +check_flags($m->getLastUserFlags()[$key], array(FLAG_1, FLAG_2, FLAG_4)); -$udf_flags = 0; -$value_back = $m->get($key, null, null, $udf_flags); -check_flags ($udf_flags, array (FLAG_1, FLAG_4, FLAG_64)); +// Too large flags +$m->setOption(Memcached::OPT_USER_FLAGS, FLAG_TOO_LARGE); echo "DONE TEST\n"; ?> --EXPECTF-- -stored with flags +array(1) { + ["udf_test_%s"]=> + int(0) +} +Flags OK Flags OK -stored without flags -bool(true) - -Warning: Memcached::set(): udf_flags will be limited to 65535 in %s on line %d Flags OK +Flags OK +Flags OK +Flags OK +Flags OK + +Warning: Memcached::setOption(): MEMC_OPT_USER_FLAGS must be < 65535 in %s on line %d DONE TEST \ No newline at end of file From 9d5f3b956a7d0575c748cb2a4526171f63cee058 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 16 Jan 2016 21:53:07 +0000 Subject: [PATCH 041/345] Use cache with travis --- .travis.yml | 4 ++++ .travis/travis.sh | 28 +++++++++++++++++++++------- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 04f90cec..188bedba 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,3 +24,7 @@ before_script: script: - ./.travis/travis.sh script $LIBMEMCACHED_VERSION + +cache: + directories: + - $HOME/cache \ No newline at end of file diff --git a/.travis/travis.sh b/.travis/travis.sh index e6733526..e87a372f 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -44,6 +44,12 @@ function validate_package_xml() { function install_libmemcached() { + if test -d "${LIBMEMCACHED_PREFIX}" + then + echo "Using cached libmemcached: ${LIBMEMCACHED_PREFIX}" + return + fi + wget "https://launchpad.net/libmemcached/1.0/${LIBMEMCACHED_VERSION}/+download/libmemcached-${LIBMEMCACHED_VERSION}.tar.gz" -O libmemcached-${LIBMEMCACHED_VERSION}.tar.gz tar xvfz libmemcached-${LIBMEMCACHED_VERSION}.tar.gz @@ -83,17 +89,25 @@ function install_msgpack() { function install_sasl() { - wget http://memcached.googlecode.com/files/memcached-1.4.15.tar.gz -O memcached-1.4.15.tar.gz - tar xfz memcached-1.4.15.tar.gz + local prefix="${HOME}/cache/memcached" + + if test -f "${prefix}/bin/memcached" + then + echo "Using cached memcached-sasl: ${prefix}/bin/memcached" + return + fi + + wget http://www.memcached.org/files/memcached-1.4.25.tar.gz -O memcached-1.4.25.tar.gz + tar xfz memcached-1.4.25.tar.gz - pushd memcached-1.4.15 - ./configure --enable-sasl --prefix="${HOME}/memcached" + pushd memcached-1.4.25 + ./configure --enable-sasl --prefix="${prefix}" make make install popd sudo apt-get install sasl2-bin - export SASL_CONF_PATH="${HOME}/sasl2" + export SASL_CONF_PATH="${HOME}/cache/sasl2" # Create config path mkdir "${SASL_CONF_PATH}" @@ -109,7 +123,7 @@ EOF echo "test" | /usr/sbin/saslpasswd2 -c memcached -a memcached -f "${SASL_CONF_PATH}/sasldb2" # Run memcached on port 11212 with SASL support - "${HOME}/memcached/bin/memcached" -S -d -p 11212 + "${prefix}/bin/memcached" -S -d -p 11212 } function build_php_memcached() { @@ -192,7 +206,7 @@ fi PHP_MEMCACHED_VERSION=$(php -r '$sxe = simplexml_load_file ("package.xml"); echo (string) $sxe->version->release;') # Libmemcached install dir -LIBMEMCACHED_PREFIX="${HOME}/libmemcached-${LIBMEMCACHED_VERSION}" +LIBMEMCACHED_PREFIX="${HOME}/cache/libmemcached-${LIBMEMCACHED_VERSION}" # Where to do the build PHP_MEMCACHED_BUILD_DIR="/tmp/php-memcached-build" From 852d60cbc726532310abf598c6ea391b0c6407c4 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 16 Jan 2016 22:00:30 +0000 Subject: [PATCH 042/345] More travis updates --- .travis.yml | 11 ++++++++++- .travis/travis.sh | 1 - 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 188bedba..c60ed89c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,11 @@ env: - LIBMEMCACHED_VERSION=0.53 - LIBMEMCACHED_VERSION=0.49 - LIBMEMCACHED_VERSION=0.44 +addons: + apt: + packages: + - sasl2-bin + - libsasl2-dev services: - memcached # will start memcached @@ -25,6 +30,10 @@ before_script: script: - ./.travis/travis.sh script $LIBMEMCACHED_VERSION +sudo: false + cache: directories: - - $HOME/cache \ No newline at end of file + - $HOME/cache + + \ No newline at end of file diff --git a/.travis/travis.sh b/.travis/travis.sh index e87a372f..923eb518 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -106,7 +106,6 @@ function install_sasl() { make install popd - sudo apt-get install sasl2-bin export SASL_CONF_PATH="${HOME}/cache/sasl2" # Create config path From f3bfce3ec85e7aa8a25a28de1bc04bb0263df993 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 16 Jan 2016 22:17:21 +0000 Subject: [PATCH 043/345] Run our own memcached --- .travis.yml | 4 +--- .travis/travis.sh | 40 ++++++++++++++++++++++++++++------------ 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index c60ed89c..30e5c3e1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,7 @@ php: - 7.0 env: + - LIBMEMCACHED_VERSION=1.0.18 - LIBMEMCACHED_VERSION=1.0.17 - LIBMEMCACHED_VERSION=1.0.16 - LIBMEMCACHED_VERSION=1.0.15 @@ -21,9 +22,6 @@ addons: - sasl2-bin - libsasl2-dev -services: - - memcached # will start memcached - before_script: - ./.travis/travis.sh before_script $LIBMEMCACHED_VERSION diff --git a/.travis/travis.sh b/.travis/travis.sh index 923eb518..a80e0cf3 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -1,5 +1,7 @@ #!/bin/bash +MEMCACHED_VERSION="1.4.25" + function version_compare() { DPKG=`which dpkg` @@ -87,27 +89,35 @@ function install_msgpack() { popd } -function install_sasl() { - +function install_memcached() { local prefix="${HOME}/cache/memcached" - if test -f "${prefix}/bin/memcached" + if test -d "$prefix" then - echo "Using cached memcached-sasl: ${prefix}/bin/memcached" + echo "Using cached memcached: ${prefix}" return fi - wget http://www.memcached.org/files/memcached-1.4.25.tar.gz -O memcached-1.4.25.tar.gz - tar xfz memcached-1.4.25.tar.gz + wget http://www.memcached.org/files/memcached-${MEMCACHED_VERSION}.tar.gz -O memcached-${MEMCACHED_VERSION}.tar.gz + tar xfz memcached-${MEMCACHED_VERSION}.tar.gz - pushd memcached-1.4.25 + pushd memcached-${MEMCACHED_VERSION} ./configure --enable-sasl --prefix="${prefix}" make make install popd +} + +function install_sasl_config() { export SASL_CONF_PATH="${HOME}/cache/sasl2" + if test -f "${SASL_CONF_PATH}/memcached.conf" + then + echo "Using cached SASL configuration: ${SASL_CONF_PATH}/memcached.conf" + return + fi + # Create config path mkdir "${SASL_CONF_PATH}" @@ -120,6 +130,13 @@ EOF # Create password echo "test" | /usr/sbin/saslpasswd2 -c memcached -a memcached -f "${SASL_CONF_PATH}/sasldb2" +} + +function run_memcached() { + local prefix="${HOME}/cache/memcached" + + # Run normal memcached + "${prefix}/bin/memcached" -d -p 11211 # Run memcached on port 11212 with SASL support "${prefix}/bin/memcached" -S -d -p 11212 @@ -232,11 +249,10 @@ case $ACTION in # install msgpack # install_msgpack - - # install SASL - if test "x$ENABLE_SASL" = "xyes"; then - install_sasl - fi + + install_memcached + install_sasl_config + run_memcached ;; script) From dcdd3b88c57f6ee2fc43d20f1ec7ad7444c42be5 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 16 Jan 2016 22:22:25 +0000 Subject: [PATCH 044/345] Allow specifying memcached version --- .travis/travis.sh | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index a80e0cf3..78ae9ffb 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -1,7 +1,5 @@ #!/bin/bash -MEMCACHED_VERSION="1.4.25" - function version_compare() { DPKG=`which dpkg` @@ -90,7 +88,7 @@ function install_msgpack() { } function install_memcached() { - local prefix="${HOME}/cache/memcached" + local prefix="${HOME}/cache/memcached-${MEMCACHED_VERSION}" if test -d "$prefix" then @@ -133,7 +131,7 @@ EOF } function run_memcached() { - local prefix="${HOME}/cache/memcached" + local prefix="${HOME}/cache/memcached-${MEMCACHED_VERSION}" # Run normal memcached "${prefix}/bin/memcached" -d -p 11211 @@ -207,6 +205,7 @@ function run_memcached_tests() { # Command line arguments ACTION=$1 LIBMEMCACHED_VERSION=$2 +MEMCACHED_VERSION="1.4.25" if test "x$ACTION" = "x"; then echo "Usage: $0 " @@ -218,6 +217,10 @@ if test "x$LIBMEMCACHED_VERSION" = "x"; then exit 1 fi +if test "x$3" != "x"; then + MEMCACHED_VERSION=$3 +fi + # the extension version PHP_MEMCACHED_VERSION=$(php -r '$sxe = simplexml_load_file ("package.xml"); echo (string) $sxe->version->release;') From 5eb3bfd4fe8a6532ad80fc784020e70fabfedfec Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Jan 2016 04:05:32 +0000 Subject: [PATCH 045/345] Fixes to keys and tests --- php_memcached.c | 14 +++++++------- tests/keys.phpt | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index c7fb08ba..f5a9ea22 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -424,6 +424,7 @@ static PHP_METHOD(Memcached, __construct) } i_obj->is_persistent = is_persistent; + array_init(&i_obj->last_udf_flags); if (!m_obj) { m_obj = pecalloc(1, sizeof(*m_obj), is_persistent); @@ -470,7 +471,6 @@ static PHP_METHOD(Memcached, __construct) m_obj->store_retry_count = MEMC_G(store_retry_count); m_obj->set_udf_flags = -1; - array_init(&i_obj->last_udf_flags); i_obj->obj = m_obj; i_obj->is_pristine = 1; @@ -580,7 +580,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) zend_hash_clean(Z_ARRVAL(i_obj->last_udf_flags)); - if (key->len == 0) { + if (key->len == 0 || (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) && strchr(key->val, ' '))) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FROM_GET; } @@ -1423,7 +1423,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key->len == 0) { + if (key->len == 0 || (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) && strchr(key->val, ' '))) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1568,7 +1568,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key->len == 0) { + if (key->len == 0 || (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) && strchr(key->val, ' '))) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1677,7 +1677,7 @@ static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key->len == 0 || strchr(key->val, ' ')) { + if (key->len == 0 || (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) && strchr(key->val, ' '))) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1775,7 +1775,7 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key->len == 0 || strchr(key->val, ' ')) { + if (key->len == 0 || (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) && strchr(key->val, ' '))) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -2020,7 +2020,7 @@ PHP_METHOD(Memcached, getServerByKey) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (server_key->len == 0 || strchr(server_key->val, ' ')) { + if (server_key->len == 0 || (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) && strchr(server_key->val, ' '))) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } diff --git a/tests/keys.phpt b/tests/keys.phpt index 0ed90896..89632f5d 100644 --- a/tests/keys.phpt +++ b/tests/keys.phpt @@ -13,7 +13,7 @@ $binary = memc_get_instance (array ( $ascii = memc_get_instance (); var_dump ($binary->set ('binary key with spaces', 'this is a test')); -var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); +var_dump ($binary->getResultCode () == Memcached::RES_SUCCESS); var_dump ($ascii->set ('ascii key with spaces', 'this is a test')); var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); @@ -24,7 +24,7 @@ var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); echo "OK" . PHP_EOL; --EXPECT-- -bool(false) +bool(true) bool(true) bool(false) bool(true) From 029784c6870fcd812e58f56c4a17a51e198eb2fc Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Jan 2016 04:17:19 +0000 Subject: [PATCH 046/345] Show diff --- .travis/travis.sh | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index 78ae9ffb..a80ca77a 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -181,7 +181,7 @@ EOF function run_memcached_tests() { export NO_INTERACTION=1 export REPORT_EXIT_STATUS=1 - export TEST_PHP_EXECUTABLE=`which php` + export TEST_PHP_EXECUTABLE=$(which php) pushd "${PHP_MEMCACHED_BUILD_DIR}/memcached-${PHP_MEMCACHED_VERSION}" # We have one xfail test, we run it separately @@ -189,14 +189,8 @@ function run_memcached_tests() { rm ./tests/expire.phpt # Run normal tests - php run-tests.php -d extension=memcached.so -n ./tests/*.phpt + php run-tests.php --show-diff -d extension=memcached.so -n ./tests/*.phpt retval=$? - for i in `ls tests/*.out 2>/dev/null`; do - echo "-- START ${i}"; - cat $i; - echo ""; - echo "-- END"; - done popd return $retval; From 00d99deb90d8bcd667f7ea2d008218d8e82ab601 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Jan 2016 04:42:16 +0000 Subject: [PATCH 047/345] Should fix sasl --- .travis/travis.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index a80ca77a..b2ef1fb7 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -137,7 +137,7 @@ function run_memcached() { "${prefix}/bin/memcached" -d -p 11211 # Run memcached on port 11212 with SASL support - "${prefix}/bin/memcached" -S -d -p 11212 + MEMCACHED_SASL_PWDB="${SASL_CONF_PATH}/sasldb2" "${prefix}/bin/memcached" -S -d -p 11212 } function build_php_memcached() { From 238a403ea87036c18982dfcb1d7d3fea26cb367b Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Jan 2016 04:45:59 +0000 Subject: [PATCH 048/345] Should fix sasl --- .travis/travis.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index b2ef1fb7..d841a4b3 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -88,7 +88,7 @@ function install_msgpack() { } function install_memcached() { - local prefix="${HOME}/cache/memcached-${MEMCACHED_VERSION}" + local prefix="${HOME}/cache/memcached-sasl-${MEMCACHED_VERSION}" if test -d "$prefix" then @@ -100,7 +100,7 @@ function install_memcached() { tar xfz memcached-${MEMCACHED_VERSION}.tar.gz pushd memcached-${MEMCACHED_VERSION} - ./configure --enable-sasl --prefix="${prefix}" + ./configure --enable-sasl --enable-sasl-pwdb --prefix="${prefix}" make make install popd @@ -137,7 +137,8 @@ function run_memcached() { "${prefix}/bin/memcached" -d -p 11211 # Run memcached on port 11212 with SASL support - MEMCACHED_SASL_PWDB="${SASL_CONF_PATH}/sasldb2" "${prefix}/bin/memcached" -S -d -p 11212 + export MEMCACHED_SASL_PWDB="${SASL_CONF_PATH}/sasldb2" + "${prefix}/bin/memcached" -S -d -p 11212 } function build_php_memcached() { From 5a1d092b7fafbb80bc3e6eb47ead104b10ae1ad6 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Jan 2016 04:49:03 +0000 Subject: [PATCH 049/345] Run right memcached --- .travis/travis.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index d841a4b3..3d2af8ae 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -131,7 +131,7 @@ EOF } function run_memcached() { - local prefix="${HOME}/cache/memcached-${MEMCACHED_VERSION}" + local prefix="${HOME}/cache/memcached-sasl-${MEMCACHED_VERSION}" # Run normal memcached "${prefix}/bin/memcached" -d -p 11211 From 37f261879742d52a329e9c172ef2cce6f1a34684 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Jan 2016 05:00:55 +0000 Subject: [PATCH 050/345] Memcached log --- .travis/travis.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index 3d2af8ae..96f6bc31 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -137,8 +137,11 @@ function run_memcached() { "${prefix}/bin/memcached" -d -p 11211 # Run memcached on port 11212 with SASL support + echo "SASL users:" + sasldblistusers2 -f "${SASL_CONF_PATH}/sasldb2" + export MEMCACHED_SASL_PWDB="${SASL_CONF_PATH}/sasldb2" - "${prefix}/bin/memcached" -S -d -p 11212 + "${prefix}/bin/memcached" -S -d -v -p 11212 > /tmp/memcached-sasl.log 2>&1 } function build_php_memcached() { @@ -194,6 +197,7 @@ function run_memcached_tests() { retval=$? popd + cat /tmp/memcached-sasl.log return $retval; } From 7e5f0922420ce5d4d472dcafd3e9569eec92fb8b Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Jan 2016 05:26:00 +0000 Subject: [PATCH 051/345] SASL is tricky --- .travis/travis.sh | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index 96f6bc31..3924efd6 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -106,41 +106,32 @@ function install_memcached() { popd } -function install_sasl_config() { +function run_memcached() { + local prefix="${HOME}/cache/memcached-sasl-${MEMCACHED_VERSION}" - export SASL_CONF_PATH="${HOME}/cache/sasl2" + export SASL_CONF_PATH="/tmp/sasl2" - if test -f "${SASL_CONF_PATH}/memcached.conf" + if test -d "${SASL_CONF_PATH}" then - echo "Using cached SASL configuration: ${SASL_CONF_PATH}/memcached.conf" - return + rm -rf "${SASL_CONF_PATH}" fi - # Create config path mkdir "${SASL_CONF_PATH}" + export MEMCACHED_SASL_PWDB="${SASL_CONF_PATH}/sasldb2" # Create configuration cat< "${SASL_CONF_PATH}/memcached.conf" mech_list: PLAIN plainlog_level: 5 -sasldb_path: ${SASL_CONF_PATH}/sasldb2 +sasldb_path: ${MEMCACHED_SASL_PWDB} EOF - # Create password - echo "test" | /usr/sbin/saslpasswd2 -c memcached -a memcached -f "${SASL_CONF_PATH}/sasldb2" -} - -function run_memcached() { - local prefix="${HOME}/cache/memcached-sasl-${MEMCACHED_VERSION}" + echo "test" | /usr/sbin/saslpasswd2 -c memcached -a memcached -f "${MEMCACHED_SASL_PWDB}" # Run normal memcached "${prefix}/bin/memcached" -d -p 11211 # Run memcached on port 11212 with SASL support - echo "SASL users:" - sasldblistusers2 -f "${SASL_CONF_PATH}/sasldb2" - - export MEMCACHED_SASL_PWDB="${SASL_CONF_PATH}/sasldb2" "${prefix}/bin/memcached" -S -d -v -p 11212 > /tmp/memcached-sasl.log 2>&1 } @@ -253,7 +244,6 @@ case $ACTION in # install_msgpack install_memcached - install_sasl_config run_memcached ;; From 1aab3f70f7c6a8cac480e1244b7eafbb75bc9c40 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Jan 2016 05:28:33 +0000 Subject: [PATCH 052/345] Remove debug logging --- .travis/travis.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index 3924efd6..a6240d83 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -132,7 +132,7 @@ EOF "${prefix}/bin/memcached" -d -p 11211 # Run memcached on port 11212 with SASL support - "${prefix}/bin/memcached" -S -d -v -p 11212 > /tmp/memcached-sasl.log 2>&1 + "${prefix}/bin/memcached" -S -d -v -p 11212 } function build_php_memcached() { @@ -187,8 +187,6 @@ function run_memcached_tests() { php run-tests.php --show-diff -d extension=memcached.so -n ./tests/*.phpt retval=$? popd - - cat /tmp/memcached-sasl.log return $retval; } From e6946ee636b6db6dae60b0c9067a9def42b4cbbc Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Jan 2016 05:30:26 +0000 Subject: [PATCH 053/345] Remove debug logging --- .travis/travis.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index a6240d83..131e38bf 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -132,7 +132,7 @@ EOF "${prefix}/bin/memcached" -d -p 11211 # Run memcached on port 11212 with SASL support - "${prefix}/bin/memcached" -S -d -v -p 11212 + "${prefix}/bin/memcached" -S -d -p 11212 } function build_php_memcached() { From fd8fead6bd02f5aa28ac622b45dd2642763507af Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 18 Jan 2016 05:41:18 +0000 Subject: [PATCH 054/345] Remove really old libmemcached versions. If anyone is using this old version they should be worried --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 30e5c3e1..fb0d0fbe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,9 +13,9 @@ env: - LIBMEMCACHED_VERSION=1.0.7 - LIBMEMCACHED_VERSION=1.0.6 - LIBMEMCACHED_VERSION=1.0.2 - - LIBMEMCACHED_VERSION=0.53 - - LIBMEMCACHED_VERSION=0.49 - - LIBMEMCACHED_VERSION=0.44 + #- LIBMEMCACHED_VERSION=0.53 + #- LIBMEMCACHED_VERSION=0.49 + #- LIBMEMCACHED_VERSION=0.44 addons: apt: packages: From 582f4a030d15832475ea5baa70d2e92e298ec3c1 Mon Sep 17 00:00:00 2001 From: Mikko Date: Thu, 21 Jan 2016 00:02:11 +0000 Subject: [PATCH 055/345] Fix tests --- tests/session_basic2.phpt | 2 +- tests/session_basic3.phpt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/session_basic2.phpt b/tests/session_basic2.phpt index f99063a8..6ec4060e 100644 --- a/tests/session_basic2.phpt +++ b/tests/session_basic2.phpt @@ -18,7 +18,7 @@ ini_set ('session.save_path', MEMC_SERVER_HOST . ':' . MEMC_SERVER_PORT); error_reporting(0); -session_start(['lazy_write'=>TRUE); +session_start(['lazy_write'=>TRUE]); $_SESSION['foo'] = 1; session_write_close(); diff --git a/tests/session_basic3.phpt b/tests/session_basic3.phpt index fc4e7ae7..b8e4f5f8 100644 --- a/tests/session_basic3.phpt +++ b/tests/session_basic3.phpt @@ -18,7 +18,7 @@ ini_set ('session.save_path', MEMC_SERVER_HOST . ':' . MEMC_SERVER_PORT); error_reporting(0); -session_start(['read_only'=>TRUE); +session_start(['read_only'=>TRUE]); $_SESSION['foo'] = 1; session_write_close(); From 7ac4e83c6cf4aa8e16f8088534096293ee8e254d Mon Sep 17 00:00:00 2001 From: Mikko Date: Thu, 21 Jan 2016 00:32:09 +0000 Subject: [PATCH 056/345] Add to package.xml --- package.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.xml b/package.xml index 0ebc86f9..e42b8037 100644 --- a/package.xml +++ b/package.xml @@ -100,6 +100,8 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + From 7cb0c48c8da8fbcfdd04350338d6ebef15ddcd14 Mon Sep 17 00:00:00 2001 From: Mikko Date: Thu, 21 Jan 2016 13:42:17 +0000 Subject: [PATCH 057/345] Fixes to session --- config.m4 | 22 +++++++++++++++++++++ php_memcached.c | 19 +++++++++++++++++++ php_memcached_private.h | 2 ++ php_memcached_session.c | 42 +++++++++++++++++++---------------------- 4 files changed, 62 insertions(+), 23 deletions(-) diff --git a/config.m4 b/config.m4 index 48efd176..e6a2dfd0 100644 --- a/config.m4 +++ b/config.m4 @@ -296,6 +296,28 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_RESULT([no]) fi + ORIG_CFLAGS="$CFLAGS" + ORIG_LIBS="$LIBS" + + CFLAGS="$CFLAGS $PHP_LIBMEMCACHED_INCLUDES" + LIBS="$LIBS $PHP_LIBMEMCACHED_LIBS" + + AC_CACHE_CHECK([whether memcached_exist is defined], ac_cv_have_memcached_exist, [ + AC_TRY_LINK( + [ #include ], + [ memcached_exist (NULL, NULL, 0); ], + [ ac_cv_have_memcached_exist="yes" ], + [ ac_cv_have_memcached_exist="no" ] + ) + ]) + + CFLAGS="$ORIG_CFLAGS" + LIBS="$ORIG_LIBS" + + if test "$ac_cv_have_memcached_exist" = "yes"; then + AC_DEFINE(HAVE_MEMCACHED_EXIST, [1], [Whether memcached_exist is defined]) + fi + PHP_MEMCACHED_FILES="php_memcached.c php_libmemcached_compat.c g_fmt.c" if test "$PHP_SYSTEM_FASTLZ" != "no"; then diff --git a/php_memcached.c b/php_memcached.c index f5a9ea22..6f4ae3b1 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -332,6 +332,25 @@ static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent); ****************************************/ +memcached_return php_memcached_exist (memcached_st *memc, zend_string *key) +{ +#ifdef HAVE_MEMCACHED_EXIST + return memcached_exist (memc, key->val, key->len); +#else + memcached_return rc = MEMCACHED_SUCCESS; + uint32_t flags = 0; + size_t value_length = 0; + char *value = NULL; + + value = memcached_get (memc, key->val, key->len, &value_length, &flags, &rc); + if (value) { + free (value); + } + return rc; +#endif +} + + char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) { char *buffer = NULL; diff --git a/php_memcached_private.h b/php_memcached_private.h index 2929818e..ffca963d 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -192,6 +192,8 @@ int php_memc_sess_list_entry(void); char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC); +memcached_return php_memcached_exist (memcached_st *memc, zend_string *key); + #endif /* PHP_MEMCACHED_PRIVATE_H */ /* diff --git a/php_memcached_session.c b/php_memcached_session.c index 5f66e411..85baad03 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -277,7 +277,7 @@ PS_OPEN_FUNC(memcached) PS_CLOSE_FUNC(memcached) { memcached_sess *memc_sess = PS_GET_MOD_DATA(); - + if (!memc_sess) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); return FAILURE; @@ -336,8 +336,9 @@ PS_READ_FUNC(memcached) *val = zend_string_init(payload, payload_len, 1); free(payload); return SUCCESS; - } else if (status = MEMCACHED_NOTFOUND) { + } else if (status == MEMCACHED_NOTFOUND) { *val = ZSTR_EMPTY_ALLOC(); + return SUCCESS; } else { return FAILURE; } @@ -351,7 +352,7 @@ PS_WRITE_FUNC(memcached) memcached_return status; memcached_sess *memc_sess = PS_GET_MOD_DATA(); size_t key_length; - + if (!memc_sess) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); return FAILURE; @@ -409,39 +410,34 @@ PS_GC_FUNC(memcached) PS_CREATE_SID_FUNC(memcached) { zend_string *sid; - int maxfail = 3; + int retries = 3; memcached_sess *memc_sess = PS_GET_MOD_DATA(); + time_t expiration = PS(gc_maxlifetime); - do { + if (!memc_sess) { + return NULL; + } + + while (retries-- > 0) { sid = php_session_create_id((void**)&memc_sess); - if (!sid) { - if (--maxfail < 0) { - return NULL; - } else { - continue; + + if (sid) { + if (memcached_add(memc_sess->memc_sess, sid->val, sid->len, "0", 0, expiration, 0) == MEMCACHED_SUCCESS) { + return sid; } - } - /* Check collision */ - /* FIXME: mod_data(memc_sess) should not be NULL (User handler could be NULL) */ - if (memc_sess && memcached_exist(memc_sess->memc_sess, sid->val, sid->len) == MEMCACHED_SUCCESS) { - if (sid) { + else { zend_string_release(sid); - sid = NULL; - } - if (--maxfail < 0) { - return NULL; } } - } while(!sid); - - return sid; + } + return NULL; } PS_VALIDATE_SID_FUNC(memcached) { memcached_sess *memc_sess = PS_GET_MOD_DATA(); - if (memcached_exist(memc_sess->memc_sess, key->val, key->len) == MEMCACHED_SUCCESS) { + if (php_memcached_exist(memc_sess->memc_sess, key) == MEMCACHED_SUCCESS) { return SUCCESS; } else { return FAILURE; From dc5b22a8dace7373c1ef9d2946e89a660ed35b20 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 29 Jan 2016 14:58:50 +0000 Subject: [PATCH 058/345] Cleaning up driver for php7. WIP --- php_memcached.c | 1141 ++++++++++++++++++-------------------- php_memcached_private.h | 83 +-- php_memcached_session.c | 628 +++++++++++---------- php_memcached_session.h | 3 + tests/cachecallback.phpt | 4 + tests/cas.phpt | 43 +- tests/cas_multi.phpt | 31 +- tests/multi_order.phpt | 3 +- tests/no-not-found.phpt | 3 +- tests/rescode.phpt | 1 + tests/set_large.phpt | 3 +- tests/user-flags.phpt | 28 +- 12 files changed, 967 insertions(+), 1004 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 6f4ae3b1..23e9bde3 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -49,6 +49,12 @@ # include "ext/msgpack/php_msgpack.h" #endif +#ifdef ZTS +#define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, memc_ini.v) +#else +#define MEMC_G(v) (php_memcached_globals.memc_ini.v) +#endif + /**************************************** Custom options @@ -106,7 +112,7 @@ "get" operation flags ****************************************/ #define MEMC_GET_PRESERVE_ORDER (1<<0) - +#define MEMC_GET_EXTENDED (2<<0) /**************************************** Helper macros @@ -136,6 +142,47 @@ #define RETURN_FROM_GET RETURN_FALSE +typedef memcached_return (*memc_store_fn)( + memcached_st *, + const char *key, size_t key_len, + const char *payload, size_t payload_len, + time_t expiration, uint32_t flags); + +typedef memcached_return (*memc_store_by_key_fn)( + memcached_st *, + const char *server_key, size_t server_key_len, + const char *key, size_t key_len, + const char *payload, size_t payload_len, + time_t expiration, uint32_t flags); + +static memc_store_fn php_memc_store_funcs[] = { + &memcached_set, + &memcached_add, + &memcached_replace, + &memcached_prepend, + &memcached_append +}; + +void s_call_store_func(int op, memcached_st *memc, const char *key, size_t key_len, const char *payload, size_t payload_len, time_t expiration, uint32_t flags) +{ + (*php_memc_store_funcs[op])(memc, key, key_len,payload, payload_len, expiration, flags); +} + + +static memc_store_by_key_fn php_memc_store_by_keys_funcs[] = { + &memcached_set_by_key, + &memcached_add_by_key, + &memcached_replace_by_key, + &memcached_prepend_by_key, + &memcached_append_by_key +}; + +void s_call_store_by_key_func(int op, memcached_st *memc, const char *server_key, size_t server_key_len, const char *key, size_t key_len, const char *payload, size_t payload_len, time_t expiration, uint32_t flags) +{ + (*php_memc_store_by_keys_funcs[op])(memc, server_key, server_key_len, key, key_len,payload, payload_len, expiration, flags); +} + + /**************************************** Structures and definitions ****************************************/ @@ -157,7 +204,6 @@ typedef struct { zend_long set_udf_flags; } *obj; - zval last_udf_flags; zend_bool is_persistent; zend_bool is_pristine; int rescode; @@ -220,14 +266,6 @@ struct callbackContext static zend_class_entry *spl_ce_RuntimeException = NULL; #endif -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 3) -const zend_fcall_info empty_fcall_info = { 0, NULL, NULL, NULL, NULL, 0, NULL, NULL, 0 }; -#undef ZEND_BEGIN_ARG_INFO_EX -#define ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args) \ - static zend_arg_info name[] = { \ - { NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args }, -#endif - ZEND_DECLARE_MODULE_GLOBALS(php_memcached) #ifdef COMPILE_DL_MEMCACHED @@ -275,44 +313,54 @@ static PHP_INI_MH(OnUpdateSerializer) return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } +#define MEMC_INI_ENTRY(key, default_value, update_fn, gkey) \ + STD_PHP_INI_ENTRY("memcached.##key", default_value, PHP_INI_ALL, update_fn, memc_ini.gkey, zend_php_memcached_globals, php_memcached_globals) + +#define MEMC_SESSION_INI_ENTRY(key, default_value, update_fn, gkey) \ + STD_PHP_INI_ENTRY("memcached.session.##key", default_value, PHP_INI_ALL, update_fn, session_ini.gkey, zend_php_memcached_globals, php_memcached_globals) + + /* {{{ INI entries */ PHP_INI_BEGIN() + #ifdef HAVE_MEMCACHED_SESSION - STD_PHP_INI_ENTRY("memcached.sess_locking", "1", PHP_INI_ALL, OnUpdateBool, sess_locking_enabled, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.sess_consistent_hash", "0", PHP_INI_ALL, OnUpdateBool, sess_consistent_hash_enabled, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.sess_binary", "0", PHP_INI_ALL, OnUpdateBool, sess_binary_enabled, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.sess_lock_wait", "150000", PHP_INI_ALL, OnUpdateLongGEZero,sess_lock_wait, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.sess_lock_max_wait", "0", PHP_INI_ALL, OnUpdateLongGEZero, sess_lock_max_wait, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.sess_lock_expire", "0", PHP_INI_ALL, OnUpdateLongGEZero, sess_lock_expire, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.sess_prefix", "memc.sess.key.", PHP_INI_ALL, OnUpdateString, sess_prefix, zend_php_memcached_globals, php_memcached_globals) - - STD_PHP_INI_ENTRY("memcached.sess_number_of_replicas", "0", PHP_INI_ALL, OnUpdateLongGEZero, sess_number_of_replicas, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.sess_randomize_replica_read", "0", PHP_INI_ALL, OnUpdateBool, sess_randomize_replica_read, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.sess_remove_failed", "0", PHP_INI_ALL, OnUpdateBool, sess_remove_failed_enabled, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.sess_connect_timeout", "1000", PHP_INI_ALL, OnUpdateLong, sess_connect_timeout, zend_php_memcached_globals, php_memcached_globals) -#if HAVE_MEMCACHED_SASL - STD_PHP_INI_ENTRY("memcached.sess_sasl_username", "", PHP_INI_ALL, OnUpdateString, sess_sasl_username, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.sess_sasl_password", "", PHP_INI_ALL, OnUpdateString, sess_sasl_password, zend_php_memcached_globals, php_memcached_globals) + MEMC_SESSION_INI_ENTRY("lock_enabled", "1", OnUpdateBool, lock_enabled) + MEMC_SESSION_INI_ENTRY("lock_wait_min", "1000", OnUpdateLongGEZero, lock_wait_min) + MEMC_SESSION_INI_ENTRY("lock_wait_max", "2000", OnUpdateLongGEZero, lock_wait_max) + MEMC_SESSION_INI_ENTRY("lock_retries", "5", OnUpdateLongGEZero, lock_retries) + MEMC_SESSION_INI_ENTRY("lock_expiration", "0", OnUpdateLongGEZero, lock_expiration) + MEMC_SESSION_INI_ENTRY("compression", "1", OnUpdateBool, compression_enabled) + MEMC_SESSION_INI_ENTRY("binary_protocol", "1", OnUpdateBool, binary_protocol_enabled) + MEMC_SESSION_INI_ENTRY("consistent_hash", "1", OnUpdateBool, consistent_hash_enabled) + MEMC_SESSION_INI_ENTRY("number_of_replicas", "0", OnUpdateLongGEZero, number_of_replicas) + MEMC_SESSION_INI_ENTRY("randomize_replica_read", "0", OnUpdateLongGEZero, randomize_replica_read_enabled) + MEMC_SESSION_INI_ENTRY("remove_failed_servers", "0", OnUpdateBool, remove_failed_servers_enabled) + MEMC_SESSION_INI_ENTRY("server_failure_limit", "0", OnUpdateLongGEZero, server_failure_limit) + MEMC_SESSION_INI_ENTRY("connect_timeout", "0", OnUpdateLongGEZero, connect_timeout) + MEMC_SESSION_INI_ENTRY("sasl_username", "", OnUpdateString, sasl_username) + MEMC_SESSION_INI_ENTRY("sasl_password", "", OnUpdateString, sasl_password) + MEMC_SESSION_INI_ENTRY("prefix", "memc.sess.", OnUpdateString, prefix) + MEMC_SESSION_INI_ENTRY("persistent", "0", OnUpdateBool, persistent_enabled) #endif -#endif - STD_PHP_INI_ENTRY("memcached.compression_type", "fastlz", PHP_INI_ALL, OnUpdateCompressionType, compression_type, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.compression_factor", "1.3", PHP_INI_ALL, OnUpdateReal, compression_factor, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.compression_threshold", "2000", PHP_INI_ALL, OnUpdateLong, compression_threshold, zend_php_memcached_globals, php_memcached_globals) - STD_PHP_INI_ENTRY("memcached.serializer", SERIALIZER_DEFAULT_NAME, PHP_INI_ALL, OnUpdateSerializer, serializer_name, zend_php_memcached_globals, php_memcached_globals) -#if HAVE_MEMCACHED_SASL - STD_PHP_INI_ENTRY("memcached.use_sasl", "0", PHP_INI_SYSTEM, OnUpdateBool, use_sasl, zend_php_memcached_globals, php_memcached_globals) -#endif - STD_PHP_INI_ENTRY("memcached.store_retry_count", "2", PHP_INI_ALL, OnUpdateLong, store_retry_count, zend_php_memcached_globals, php_memcached_globals) + MEMC_INI_ENTRY("compression_type", "fastlz", OnUpdateCompressionType, compression_type) + MEMC_INI_ENTRY("compression_factor", "1.3", OnUpdateReal, compression_factor) + MEMC_INI_ENTRY("compression_threshold", "2000", OnUpdateLong, compression_threshold) + MEMC_INI_ENTRY("serializer", SERIALIZER_DEFAULT_NAME, OnUpdateSerializer, serializer_name) + MEMC_INI_ENTRY("use_sasl", "0", OnUpdateBool, sasl_enabled) + MEMC_INI_ENTRY("store_retry_count", "2", OnUpdateLong, store_retry_count) + PHP_INI_END() /* }}} */ +#undef MEMC_INI_ENTRY +#undef MEMC_SESSION_INI_ENTRY + /**************************************** Forward declarations ****************************************/ static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status); -static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type); -static int php_memc_zval_from_payload(zval *value, const char *payload, size_t payload_len, uint32_t flags, enum memcached_serializer serializer); + static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool by_key); @@ -327,6 +375,14 @@ static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, php_ static memcached_return php_memc_do_version_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context); static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent); + +static + zend_bool s_memcached_result_to_zval(memcached_result_st *result, zval *return_value); + +static + zend_string *s_zval_to_payload(zval *value, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type); + + /**************************************** Method implementations ****************************************/ @@ -391,7 +447,7 @@ static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fc efree (buf); ret = 0; } - + if (Z_TYPE(retval) != IS_UNDEF) zval_ptr_dtor(&retval); @@ -400,7 +456,7 @@ static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fc return ret; } -static int le_memc, le_memc_sess; +static int le_memc; static int php_memc_list_entry(void) { @@ -443,7 +499,6 @@ static PHP_METHOD(Memcached, __construct) } i_obj->is_persistent = is_persistent; - array_init(&i_obj->last_udf_flags); if (!m_obj) { m_obj = pecalloc(1, sizeof(*m_obj), is_persistent); @@ -533,217 +588,211 @@ static PHP_METHOD(Memcached, __construct) } /* }}} */ -/* {{{ Memcached::getLastUserFlags() - Returns the user flags from last fetch operation */ -PHP_METHOD(Memcached, getLastUserFlags) +static +void s_uint64_to_zval (zval *target, uint64_t value) { - MEMC_METHOD_INIT_VARS; + if (value >= LONG_MAX) { + char *buffer; + spprintf (&buffer, 0, "%" PRIu64, value); + ZVAL_STRING (target, buffer); + efree(buffer); + } + else { + ZVAL_LONG (target, (zend_long) value); + } +} - if (zend_parse_parameters_none() == FAILURE) { +typedef struct { + + size_t num_valid_keys; + + const char **mkeys; + size_t *mkeys_len; + + zend_string **strings; + +} php_memcached_keys; + +static +void s_hash_to_keys(php_memcached_keys *keys_out, HashTable *hash_in, zend_bool preserve_order, zval *return_value) +{ + size_t idx = 0, alloc_count; + zval *zv; + + keys_out->num_valid_keys = 0; + + alloc_count = zend_hash_num_elements(hash_in); + if (!alloc_count) { return; } + keys_out->mkeys = ecalloc (alloc_count, sizeof (char *)); + keys_out->mkeys_len = ecalloc (alloc_count, sizeof (size_t)); + keys_out->strings = ecalloc (alloc_count, sizeof (zend_string *)); - MEMC_METHOD_FETCH_OBJECT; - RETVAL_ZVAL(&i_obj->last_udf_flags, 1, 0); -} -/* }}} */ + ZEND_HASH_FOREACH_VAL(hash_in, zv) { + zend_string *key = zval_get_string(zv); + if (preserve_order && return_value) { + add_assoc_null_ex(return_value, key->val, key->len); + } -/* {{{ Memcached::get(string key [, mixed callback [, double &cas_token ] ]) - Returns a value for the given key or false */ -PHP_METHOD(Memcached, get) -{ - php_memc_get_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); + if (key->len > 0 && key->len < MEMCACHED_MAX_KEY) { + keys_out->mkeys[idx] = key->val; + keys_out->mkeys_len[idx] = key->len; + + keys_out->strings[idx] = key; + idx++; + } + else { + zend_string_release (key); + } + + } ZEND_HASH_FOREACH_END(); + + if (!idx) { + efree (keys_out->mkeys); + efree (keys_out->mkeys_len); + efree (keys_out->strings); + } + keys_out->num_valid_keys = idx; } -/* }}} */ -/* {{{ Memcached::getByKey(string server_key, string key [, mixed callback [, double &cas_token ] ]) - Returns a value for key from the server identified by the server key or false */ -PHP_METHOD(Memcached, getByKey) +static +void s_clear_keys(php_memcached_keys *keys) { - php_memc_get_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); + size_t i; + for (i = 0; i < keys->num_valid_keys; i++) { + zend_string_release (keys->strings[i]); + } + efree(keys->strings); + efree(keys->mkeys); + efree(keys->mkeys_len); } -/* }}} */ -/* {{{ -- php_memc_get_impl */ -static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) +static +memcached_return s_memcached_get_multi(memcached_st *memc, HashTable *hash_keys, zend_string *server_key, zend_long get_flags, zval *return_value) { - zend_string *key; - zend_string *server_key = NULL; - const char *payload = NULL; - size_t payload_len = 0; - uint32_t flags = 0; - uint64_t cas = 0; - const char* keys[1] = { NULL }; - size_t key_lens[1] = { 0 }; - zval *cas_token = NULL; + php_memcached_keys keys = { 0 }; + zval values; + + memcached_return rc, status = MEMCACHED_SUCCESS; + + size_t num_keys; uint64_t orig_cas_flag; - zend_fcall_info fci = empty_fcall_info; - zend_fcall_info_cache fcc = empty_fcall_info_cache; memcached_result_st result; - memcached_return status = MEMCACHED_SUCCESS; - MEMC_METHOD_INIT_VARS; - if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|f!z", &server_key, &key, &fci, &fcc, &cas_token) == FAILURE) { - return; - } - } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|f!z", &key, &fci, &fcc, &cas_token) == FAILURE) { - return; - } - } + zend_bool extended = (get_flags & MEMC_GET_EXTENDED); + zend_bool preserve_order = (get_flags & MEMC_GET_PRESERVE_ORDER); - MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; - - zend_hash_clean(Z_ARRVAL(i_obj->last_udf_flags)); + array_init(&values); + s_hash_to_keys(&keys, hash_keys, preserve_order, &values); - if (key->len == 0 || (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) && strchr(key->val, ' '))) { - i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; - RETURN_FROM_GET; + if (!keys.num_valid_keys) { + zval_ptr_dtor(&values); + return MEMCACHED_NO_KEY_PROVIDED; } - keys[0] = key->val; - key_lens[0] = key->len; + orig_cas_flag = memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS); - orig_cas_flag = memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS); - - /* - * Enable CAS support, but only if it is currently disabled. - */ - if (cas_token && Z_ISREF_P(cas_token) && orig_cas_flag == 0) { - memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); + if (extended && !orig_cas_flag) { + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); } - if (by_key) { - status = memcached_mget_by_key(m_obj->memc, server_key->val, server_key->len, keys, key_lens, 1); + if (server_key) { + status = memcached_mget_by_key(memc, server_key->val, server_key->len, keys.mkeys, keys.mkeys_len, keys.num_valid_keys); } else { - status = memcached_mget(m_obj->memc, keys, key_lens, 1); - } - if (cas_token && Z_ISREF_P(cas_token) && orig_cas_flag == 0) { - memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); + status = memcached_mget(memc, keys.mkeys, keys.mkeys_len, keys.num_valid_keys); } - if (php_memc_handle_error(i_obj, status) < 0) { - RETURN_FROM_GET; + s_clear_keys(&keys); + + if (extended && !orig_cas_flag) { + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 0); } - status = MEMCACHED_SUCCESS; - memcached_result_create(m_obj->memc, &result); + memcached_result_create(memc, &result); + while ((memcached_fetch_result(memc, &result, &rc)) != NULL) { - if (memcached_fetch_result(m_obj->memc, &result, &status) == NULL) { - /* This is for historical reasons */ - if (status == MEMCACHED_END) - status = MEMCACHED_NOTFOUND; + const char *res_key = NULL; + size_t res_key_len = 0; + zval value; - /* - * If the result wasn't found, and we have the read-through callback, invoke - * it to get the value. The CAS token will be 0, because we cannot generate it - * ourselves. - */ - if (cas_token) { - ZVAL_DEREF(cas_token); - zval_ptr_dtor(cas_token); - ZVAL_DOUBLE(cas_token, 0.0); + /* For some reason instead of success it's end */ + if (rc == MEMCACHED_END) { + rc = MEMCACHED_SUCCESS; } - if (status == MEMCACHED_NOTFOUND && fci.size != 0) { - status = php_memc_do_cache_callback(getThis(), &fci, &fcc, key, return_value); + if (rc != MEMCACHED_SUCCESS) { + status = rc; + continue; } - if (php_memc_handle_error(i_obj, status) < 0) { - memcached_result_free(&result); - RETURN_FROM_GET; - } + ZVAL_UNDEF(&value); + if (!s_memcached_result_to_zval(&result, &value)) { + if (EG(exception)) { + status = MEMC_RES_PAYLOAD_FAILURE; - /* if we have a callback, all processing is done */ - if (fci.size != 0) { - memcached_result_free(&result); - return; + memcached_result_free(&result); + memcached_quit(memc); + zval_ptr_dtor (&values); + break; + } + status = MEMCACHED_SOME_ERRORS; + continue; } - } - /* Fetch all remaining results */ - memcached_result_st dummy_result; - memcached_return dummy_status = MEMCACHED_SUCCESS; - memcached_result_create(m_obj->memc, &dummy_result); - while (memcached_fetch_result(m_obj->memc, &dummy_result, &dummy_status) != NULL) {} - memcached_result_free(&dummy_result); + res_key = memcached_result_key_value(&result); + res_key_len = memcached_result_key_length(&result); - payload = memcached_result_value(&result); - payload_len = memcached_result_length(&result); - flags = memcached_result_flags(&result); - if (cas_token) { - cas = memcached_result_cas(&result); - } + if (extended) { + uint32_t flags; + uint64_t cas; + zval cas_token, node; - if (php_memc_zval_from_payload(return_value, payload, payload_len, flags, m_obj->serializer) < 0) { - memcached_result_free(&result); - i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; - RETURN_FROM_GET; - } + cas = memcached_result_cas(&result); + flags = memcached_result_flags(&result); - if (cas_token) { - ZVAL_DEREF(cas_token); - zval_ptr_dtor(cas_token); - ZVAL_DOUBLE(cas_token, (double)cas); - } + s_uint64_to_zval (&cas_token, cas); - /* Parse user flags */ - add_assoc_long_ex(&i_obj->last_udf_flags, key->val, key->len, MEMC_VAL_GET_USER_FLAGS(flags)); + array_init (&node); + add_assoc_zval (&node, "value", &value); + add_assoc_zval (&node, "cas", &cas_token); + add_assoc_long (&node, "flags", (zend_long) MEMC_VAL_GET_USER_FLAGS(flags)); + + add_assoc_zval_ex(&values, res_key, res_key_len, &node); + } + else { + add_assoc_zval_ex(&values, res_key, res_key_len, &value); + } + } memcached_result_free(&result); -} -/* }}} */ -/* {{{ Memcached::getMulti(array keys [, array &cas_tokens ]) - Returns values for the given keys or false */ -PHP_METHOD(Memcached, getMulti) -{ - php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); + if (Z_TYPE(values) != IS_UNDEF) { + ZVAL_ZVAL(return_value, &values, 0, 0); + } + return status; } -/* }}} */ -/* {{{ Memcached::getMultiByKey(string server_key, array keys [, array &cas_tokens ]) - Returns values for the given keys from the server identified by the server key or false */ -PHP_METHOD(Memcached, getMultiByKey) -{ - php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); -} -/* }}} */ -/* {{{ -- php_memc_getMulti_impl */ -static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) +static +void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { - zval *keys = NULL; + zend_long get_flags = 0; + zend_string *key; zend_string *server_key = NULL; - size_t num_keys = 0; - zval *entry = NULL; - const char *payload = NULL; - size_t payload_len = 0; - const char **mkeys = NULL; - size_t *mkeys_len = NULL; - const char *tmp_key = NULL; - size_t res_key_len = 0; - uint32_t flags; - uint64_t cas = 0; - zval *cas_tokens = NULL; - uint64_t orig_cas_flag = 0; - zval value; - long get_flags = 0; - int i = 0; - zend_bool preserve_order; - memcached_result_st result; memcached_return status = MEMCACHED_SUCCESS; + zend_fcall_info fci = empty_fcall_info; + zend_fcall_info_cache fcc = empty_fcall_info_cache; + HashTable keys; + zval values, tmp; MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|zl", &server_key, - &keys, &cas_tokens, &get_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|f!l", &server_key, &key, &fci, &fcc, &get_flags) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|zl", &keys, &cas_tokens, &get_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|f!l", &key, &fci, &fcc, &get_flags) == FAILURE) { return; } } @@ -751,157 +800,110 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - /* clean flags */ - zend_hash_clean(Z_ARRVAL(i_obj->last_udf_flags)); + zend_hash_init (&keys, 1, 0, NULL, 0); + ZVAL_STR(&tmp, key); + zend_hash_add(&keys, key, &tmp); - preserve_order = (get_flags & MEMC_GET_PRESERVE_ORDER); - num_keys = zend_hash_num_elements(Z_ARRVAL_P(keys)); - mkeys = safe_emalloc(num_keys, sizeof(*mkeys), 0); - mkeys_len = safe_emalloc(num_keys, sizeof(*mkeys_len), 0); - array_init(return_value); + ZVAL_UNDEF(&values); + status = s_memcached_get_multi(m_obj->memc, &keys, server_key, get_flags, &values); + zend_hash_destroy (&keys); - /* - * Create the array of keys for libmemcached. If none of the keys were valid - * (strings), set bad key result code and return. - */ - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(keys), entry) { - if (Z_TYPE_P(entry) != IS_STRING) { - convert_to_string_ex(entry); - } - - if (Z_TYPE_P(entry) == IS_STRING && Z_STRLEN_P(entry) > 0) { - mkeys[i] = Z_STRVAL_P(entry); - mkeys_len[i] = Z_STRLEN_P(entry); - - if (preserve_order) { - add_assoc_null_ex(return_value, mkeys[i], mkeys_len[i]); - } - i++; - } - } ZEND_HASH_FOREACH_END(); - - if (i == 0) { - i_obj->rescode = MEMCACHED_NOTFOUND; - efree(mkeys); - efree(mkeys_len); - return; + if (EG(exception)) { + zval_ptr_dtor(&values); + RETURN_FROM_GET; } - /* - * Enable CAS support, but only if it is currently disabled. - */ - if (cas_tokens && Z_ISREF_P(cas_tokens)) { - orig_cas_flag = memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS); - if (orig_cas_flag == 0) { - memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); + if (status == MEMCACHED_SUCCESS) { + zval *zv = zend_hash_find (Z_ARRVAL(values), key); + if (zv) { + RETVAL_ZVAL(zv, 1, 0); + zval_ptr_dtor(&values); + return; + } + else { + status = MEMCACHED_NOTFOUND; } } - if (by_key) { - status = memcached_mget_by_key(m_obj->memc, server_key->val, server_key->len, mkeys, mkeys_len, i); - } else { - status = memcached_mget(m_obj->memc, mkeys, mkeys_len, i); + if (Z_TYPE(values) != IS_UNDEF) { + zval_ptr_dtor(&values); } - /* Handle error, but ignore, there might still be some result */ - php_memc_handle_error(i_obj, status); - /* - * Restore the CAS support flag, but only if we had to turn it on. - */ - if (cas_tokens && Z_ISREF_P(cas_tokens) && orig_cas_flag == 0) { - memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); + if (status == MEMCACHED_NOTFOUND && fci.size > 0) { + // try to invoke cache cb + status = php_memc_do_cache_callback(getThis(), &fci, &fcc, key, return_value); } - efree(mkeys); - efree(mkeys_len); - - /* - * Iterate through the result set and create the result array. The CAS tokens are - * returned as doubles, because we cannot store potential 64-bit values in longs. - */ - if (cas_tokens) { - if (Z_ISREF_P(cas_tokens)) { - /* cas_tokens was passed by reference, we'll create an array for it. */ - ZVAL_DEREF(cas_tokens); - SEPARATE_ZVAL(cas_tokens); - zval_dtor(cas_tokens); - array_init(cas_tokens); - } else { - /* Not passed by reference, we allow this (eg.: if you specify null - to not enable cas but you want to use the udf_flags parameter). - We destruct it and set it to null for the peace of mind. */ - cas_tokens = NULL; - } + if (php_memc_handle_error(i_obj, status) < 0) { + RETURN_FROM_GET; } +} - /* - * Iterate through the result set and create the result array. The flags are - * returned as longs. - */ - - memcached_result_create(m_obj->memc, &result); - while ((memcached_fetch_result(m_obj->memc, &result, &status)) != NULL) { - char res_key [MEMCACHED_MAX_KEY]; - - if (status != MEMCACHED_SUCCESS) { - status = MEMCACHED_SOME_ERRORS; - php_memc_handle_error(i_obj, status); - continue; - } - - payload = memcached_result_value(&result); - payload_len = memcached_result_length(&result); - flags = memcached_result_flags(&result); - tmp_key = memcached_result_key_value(&result); - res_key_len = memcached_result_key_length(&result); - - /* - * This may be a bug in libmemcached, the key is not null terminated - * whe using the binary protocol. - */ - memcpy (res_key, tmp_key, res_key_len >= MEMCACHED_MAX_KEY ? MEMCACHED_MAX_KEY - 1 : res_key_len); - res_key [res_key_len] = '\0'; +/* {{{ Memcached::get(string key [, mixed callback [, int get_flags = 0]) + Returns a value for the given key or false */ +PHP_METHOD(Memcached, get) +{ + php_memc_get_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); +} +/* }}} */ - if (php_memc_zval_from_payload(&value, payload, payload_len, flags, m_obj->serializer) < 0) { - zval_ptr_dtor(&value); - if (EG(exception)) { - status = MEMC_RES_PAYLOAD_FAILURE; - php_memc_handle_error(i_obj, status); - memcached_quit(m_obj->memc); +/* {{{ Memcached::getByKey(string server_key, string key [, mixed callback [, int get_flags = 0]) + Returns a value for key from the server identified by the server key or false */ +PHP_METHOD(Memcached, getByKey) +{ + php_memc_get_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); +} +/* }}} */ - break; - } - status = MEMCACHED_SOME_ERRORS; - i_obj->rescode = MEMCACHED_SOME_ERRORS; +/* {{{ -- php_memc_getMulti_impl */ +static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) +{ + zval *keys = NULL; + zend_string *server_key = NULL; + zend_bool extended_results = 0; + memcached_return rc; + zend_long flags = 0; + MEMC_METHOD_INIT_VARS; - continue; + if (by_key) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|l", &server_key, + &keys, &flags) == FAILURE) { + return; } - - add_assoc_zval_ex(return_value, res_key, res_key_len, &value); - if (cas_tokens) { - cas = memcached_result_cas(&result); - add_assoc_double_ex(cas_tokens, res_key, res_key_len, (double)cas); + } else { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|l", &keys, &flags) == FAILURE) { + return; } - add_assoc_long_ex(&i_obj->last_udf_flags, res_key, res_key_len, MEMC_VAL_GET_USER_FLAGS(flags)); } - memcached_result_free(&result); + MEMC_METHOD_FETCH_OBJECT; + + rc = s_memcached_get_multi(m_obj->memc, Z_ARRVAL_P(keys), server_key, flags, return_value); + php_memc_handle_error(i_obj, rc); if (EG(exception)) { - /* XXX: cas_tokens should only be set on success, currently we're destructive */ - if (cas_tokens) { - ZVAL_DEREF(cas_tokens); - SEPARATE_ZVAL(cas_tokens); - zval_dtor(cas_tokens); - ZVAL_NULL(cas_tokens); - } - zend_hash_clean(Z_ARRVAL(i_obj->last_udf_flags)); zval_dtor(return_value); RETURN_FALSE; } } /* }}} */ +/* {{{ Memcached::getMulti(array keys[, long flags = 0 ]) + Returns values for the given keys or false */ +PHP_METHOD(Memcached, getMulti) +{ + php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); +} +/* }}} */ + +/* {{{ Memcached::getMultiByKey(string server_key, array keys[, long flags = 0 ]) + Returns values for the given keys from the server identified by the server key or false */ +PHP_METHOD(Memcached, getMultiByKey) +{ + php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); +} +/* }}} */ + /* {{{ Memcached::getDelayed(array keys [, bool with_cas [, mixed callback ] ]) Sends a request for the given keys and returns immediately */ PHP_METHOD(Memcached, getDelayed) @@ -1075,9 +1077,8 @@ PHP_METHOD(Memcached, fetch) res_key_len = memcached_result_key_length(&result); cas = memcached_result_cas(&result); - if (php_memc_zval_from_payload(&value, payload, payload_len, flags, m_obj->serializer) < 0) { + if (!s_memcached_result_to_zval(&result, &value)) { memcached_result_free(&result); - zval_ptr_dtor(&value); i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FALSE; } @@ -1130,9 +1131,8 @@ PHP_METHOD(Memcached, fetchAll) res_key_len = memcached_result_key_length(&result); cas = memcached_result_cas(&result); - if (php_memc_zval_from_payload(&value, payload, payload_len, flags, m_obj->serializer) < 0) { + if (!s_memcached_result_to_zval(&result, &value)) { memcached_result_free(&result); - zval_ptr_dtor(&value); zval_dtor(return_value); i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FALSE; @@ -1242,11 +1242,10 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke zval *entries; zend_string *server_key = NULL; time_t expiration = 0; - zval *entry; + zval *value; zend_string *skey, *str_key = NULL; ulong num_key; - char *payload; - size_t payload_len; + zend_string *payload; uint32_t flags = 0; uint32_t retry = 0; memcached_return status; @@ -1268,7 +1267,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - ZEND_HASH_FOREACH_KEY_VAL (Z_ARRVAL_P(entries), num_key, skey, entry) { + ZEND_HASH_FOREACH_KEY_VAL (Z_ARRVAL_P(entries), num_key, skey, value) { if (skey) { str_key = skey; } else if (num_key || num_key == 0) { @@ -1291,7 +1290,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) m_obj->set_udf_flags)); } - payload = php_memc_zval_to_payload(entry, &payload_len, &flags, m_obj->serializer, m_obj->compression_type); + payload = s_zval_to_payload(value, &flags, m_obj->serializer, m_obj->compression_type); if (payload == NULL) { i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; if (!skey) { @@ -1302,9 +1301,9 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke retry: if (!by_key) { - status = memcached_set(m_obj->memc, str_key->val, str_key->len, payload, payload_len, expiration, flags); + status = memcached_set(m_obj->memc, str_key->val, str_key->len, payload->val, payload->len, expiration, flags); } else { - status = memcached_set_by_key(m_obj->memc, server_key->val, server_key->len, str_key->val, str_key->len, payload, payload_len, expiration, flags); + status = memcached_set_by_key(m_obj->memc, server_key->val, server_key->len, str_key->val, str_key->len, payload->val, payload->len, expiration, flags); } if (php_memc_handle_error(i_obj, status) < 0) { @@ -1312,13 +1311,13 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke if (!skey) { zend_string_release(str_key); } - efree(payload); + zend_string_release(payload); RETURN_FALSE; } if (!skey) { zend_string_release(str_key); } - efree(payload); + zend_string_release(payload); } ZEND_HASH_FOREACH_END(); RETURN_TRUE; @@ -1395,11 +1394,10 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool zend_string *key; zend_string *server_key = NULL; zend_string *s_value; - zval s_zvalue; + zval s_zvalue; zval *value; - long expiration = 0; - char *payload = NULL; - size_t payload_len; + zend_long expiration = 0; + zend_string *payload = NULL; uint32_t flags = 0; uint32_t retry = 0; memcached_return status; @@ -1474,8 +1472,9 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool php_error_docref(NULL, E_WARNING, "using touch command with binary protocol is not recommended with libmemcached versions below 1.0.16"); } #endif - } else { - payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type); + } + else { + payload = s_zval_to_payload(value, &flags, m_obj->serializer, m_obj->compression_type); if (payload == NULL) { i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FALSE; @@ -1485,10 +1484,10 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool switch (op) { case MEMC_OP_SET: if (!server_key) { - status = memcached_set(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); + status = memcached_set(m_obj->memc, key->val, key->len, payload->val, payload->len, expiration, flags); } else { status = memcached_set_by_key(m_obj->memc, server_key->val, server_key->len, key->val, - key->len, payload, payload_len, expiration, flags); + key->len, payload->val, payload->len, expiration, flags); } break; #ifdef HAVE_MEMCACHED_TOUCH @@ -1503,37 +1502,37 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool #endif case MEMC_OP_ADD: if (!server_key) { - status = memcached_add(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); + status = memcached_add(m_obj->memc, key->val, key->len, payload->val, payload->len, expiration, flags); } else { status = memcached_add_by_key(m_obj->memc, server_key->val, server_key->len, key->val, - key->len, payload, payload_len, expiration, flags); + key->len, payload->val, payload->len, expiration, flags); } break; case MEMC_OP_REPLACE: if (!server_key) { - status = memcached_replace(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); + status = memcached_replace(m_obj->memc, key->val, key->len, payload->val, payload->len, expiration, flags); } else { status = memcached_replace_by_key(m_obj->memc, server_key->val, server_key->len, key->val, - key->len, payload, payload_len, expiration, flags); + key->len, payload->val, payload->len, expiration, flags); } break; case MEMC_OP_APPEND: if (!server_key) { - status = memcached_append(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); + status = memcached_append(m_obj->memc, key->val, key->len, payload->val, payload->len, expiration, flags); } else { status = memcached_append_by_key(m_obj->memc, server_key->val, server_key->len, key->val, - key->len, payload, payload_len, expiration, flags); + key->len, payload->val, payload->len, expiration, flags); } break; case MEMC_OP_PREPEND: if (!server_key) { - status = memcached_prepend(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags); + status = memcached_prepend(m_obj->memc, key->val, key->len, payload->val, payload->len, expiration, flags); } else { status = memcached_prepend_by_key(m_obj->memc, server_key->val, server_key->len, key->val, - key->len, payload, payload_len, expiration, flags); + key->len, payload->val, payload->len, expiration, flags); } break; @@ -1552,7 +1551,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool } if (payload) { - efree(payload); + zend_string_release(payload); } } /* }}} */ @@ -1566,8 +1565,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) zend_string *server_key = NULL; zval *value; time_t expiration = 0; - char *payload; - size_t payload_len; + zend_string *payload; uint32_t flags = 0; memcached_return status; MEMC_METHOD_INIT_VARS; @@ -1602,22 +1600,22 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) * php_memcached uses 16 bits internally to store type, compression and serialization info. * We use 16 upper bits to store user defined flags. */ - if (m_obj->set_udf_flags > 0) { + if (m_obj->set_udf_flags >= 0) { MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) m_obj->set_udf_flags)); } - payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type); + payload = s_zval_to_payload(value, &flags, m_obj->serializer, m_obj->compression_type); if (payload == NULL) { i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FALSE; } if (by_key) { - status = memcached_cas_by_key(m_obj->memc, server_key->val, server_key->len, key->val, key->len, payload, payload_len, expiration, flags, cas); + status = memcached_cas_by_key(m_obj->memc, server_key->val, server_key->len, key->val, key->len, payload->val, payload->len, expiration, flags, cas); } else { - status = memcached_cas(m_obj->memc, key->val, key->len, payload, payload_len, expiration, flags, cas); + status = memcached_cas(m_obj->memc, key->val, key->len, payload->val, payload->len, expiration, flags, cas); } - efree(payload); + zend_string_release(payload); if (php_memc_handle_error(i_obj, status) < 0) { RETURN_FALSE; } @@ -2710,7 +2708,7 @@ static PHP_METHOD(Memcached, setSaslAuthData) return; } - if (!MEMC_G(use_sasl)) { + if (!MEMC_G(sasl_enabled)) { php_error_docref(NULL, E_WARNING, "SASL support (memcached.use_sasl) isn't enabled in php.ini"); RETURN_FALSE; } @@ -2839,8 +2837,6 @@ static void php_memc_free_storage(zend_object *obj) if (i_obj->obj && !i_obj->is_persistent) { php_memc_destroy(i_obj->obj, 0); } - - zval_ptr_dtor(&i_obj->last_udf_flags); zend_object_std_dtor(&i_obj->zo); i_obj->obj = NULL; } @@ -2893,15 +2889,6 @@ ZEND_RSRC_DTOR_FUNC(php_memc_dtor) } } -ZEND_RSRC_DTOR_FUNC(php_memc_sess_dtor) -{ - if (res->ptr) { - memcached_sess *memc_sess = (memcached_sess *)res->ptr; - memcached_free(memc_sess->memc_sess); - pefree(res->ptr, 1); - res->ptr = NULL; - } -} /* }}} */ /* {{{ internal API functions */ @@ -3037,61 +3024,74 @@ static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status) } static -char *s_compress_value (enum memcached_compression_type compression_type, const char *payload, size_t *payload_len, uint32_t *flags) +zend_bool s_compress_value (enum memcached_compression_type compression_type, zend_string **payload_in, uint32_t *flags) { /* status */ zend_bool compress_status = 0; + zend_string *payload = *payload_in; /* Additional 5% for the data */ - size_t buffer_size = (size_t) (((double) *payload_len * 1.05) + 1.0); - char *buffer = emalloc(sizeof(uint32_t) + buffer_size); + size_t buffer_size = (size_t) (((double) payload->len * 1.05) + 1.0); + char *buffer = emalloc(buffer_size); /* Store compressed size here */ size_t compressed_size = 0; - uint32_t plen = *payload_len; - - /* Copy the uin32_t at the beginning */ - memcpy(buffer, &plen, sizeof(uint32_t)); - buffer += sizeof(uint32_t); + uint32_t original_size = payload->len; switch (compression_type) { case COMPRESSION_TYPE_FASTLZ: - compress_status = ((compressed_size = fastlz_compress(payload, *payload_len, buffer)) > 0); - MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_FASTLZ); + { + compressed_size = fastlz_compress(payload->val, payload->len, buffer); + + if (compressed_size > 0) { + compress_status = 1; + MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_FASTLZ); + } + } break; case COMPRESSION_TYPE_ZLIB: - /* ZLIB returns the compressed size in this buffer */ + { compressed_size = buffer_size; + int status = compress((Bytef *) buffer, &compressed_size, (Bytef *) payload->val, payload->len); - compress_status = (compress((Bytef *)buffer, &compressed_size, (Bytef *)payload, *payload_len) == Z_OK); - MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_ZLIB); + if (status == Z_OK) { + compress_status = 1; + MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_ZLIB); + } + } break; default: compress_status = 0; break; } - buffer -= sizeof(uint32_t); - *payload_len = compressed_size + sizeof(uint32_t); if (!compress_status) { php_error_docref(NULL, E_WARNING, "could not compress value"); MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); - efree (buffer); - *payload_len = 0; - return NULL; + return 0; } - else if (*payload_len > (compressed_size * MEMC_G(compression_factor))) { + /* This means the value was too small to be compressed, still a success */ + if (compressed_size > (payload->len * MEMC_G(compression_factor))) { + efree(buffer); MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); - efree (buffer); - *payload_len = 0; - return NULL; + return 1; } - return buffer; + + payload = zend_string_realloc(payload, compressed_size + sizeof(uint32_t), 0); + + /* Copy the uin32_t at the beginning */ + memcpy(payload->val, &original_size, sizeof(uint32_t)); + memcpy(payload->val + sizeof (uint32_t), buffer, compressed_size); + efree(buffer); + + zend_string_forget_hash_val(payload); + *payload_in = payload; + return 1; } static @@ -3166,149 +3166,142 @@ zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, } static -char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type) +zend_string *s_zval_to_payload(zval *value, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type) { - const char *pl; - size_t pl_len = 0; - - char *payload = NULL; - smart_str buf = {0}; - char tmp[40] = {0}; + zend_string *payload; switch (Z_TYPE_P(value)) { case IS_STRING: - pl = Z_STRVAL_P(value); - pl_len = Z_STRLEN_P(value); + payload = zval_get_string(value); MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_STRING); + MEMC_VAL_HAS_FLAG(*flags, MEMC_VAL_COMPRESSED); break; case IS_LONG: - pl_len = sprintf(tmp, "%ld", Z_LVAL_P(value)); - pl = tmp; + { + smart_str buffer = {0}; + smart_str_append_long (&buffer, Z_LVAL_P(value)); + smart_str_0(&buffer); + payload = buffer.s; + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_LONG); + } break; case IS_DOUBLE: - php_memcached_g_fmt(tmp, Z_DVAL_P(value)); - pl = tmp; - pl_len = strlen(tmp); + { + char buffer[40]; + php_memcached_g_fmt(buffer, Z_DVAL_P(value)); + payload = zend_string_init (buffer, strlen (buffer), 0); MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_DOUBLE); + } break; case IS_TRUE: - pl_len = 1; - tmp[0] = '1'; - tmp[1] = '\0'; - pl = tmp; + payload = zend_string_init ("1", 1, 0); MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_BOOL); break; case IS_FALSE: - pl_len = 0; - tmp[0] = '\0'; - pl = tmp; + payload = zend_string_alloc (0, 0); MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_BOOL); break; default: - if (!s_serialize_value (serializer, value, &buf, flags)) { - smart_str_free(&buf); + { + smart_str buffer = {0}; + + if (!s_serialize_value (serializer, value, &buffer, flags)) { + smart_str_free(&buffer); return NULL; } - pl = buf.s->val; - pl_len = buf.s->len; + payload = buffer.s; + MEMC_VAL_HAS_FLAG(*flags, MEMC_VAL_COMPRESSED); + } break; } + zend_string_forget_hash_val(payload); /* turn off compression for values below the threshold */ - if (MEMC_VAL_HAS_FLAG(*flags, MEMC_VAL_COMPRESSED) && pl_len < MEMC_G(compression_threshold)) { + if (payload->len == 0 || payload->len < MEMC_G(compression_threshold)) { MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); } /* If we have compression flag, compress the value */ if (MEMC_VAL_HAS_FLAG(*flags, MEMC_VAL_COMPRESSED)) { /* status */ - *payload_len = pl_len; - payload = s_compress_value (compression_type, pl, payload_len, flags); - } - - /* If compression failed or value is below threshold we just use plain value */ - if (!payload || !MEMC_VAL_HAS_FLAG(*flags, MEMC_VAL_COMPRESSED)) { - *payload_len = (uint32_t) pl_len; - payload = estrndup(pl, pl_len); + if (!s_compress_value (compression_type, &payload, flags)) { + zend_string_release(payload); + return NULL; + } } - if (buf.s) { - smart_str_free(&buf); - } return payload; } static -char *s_decompress_value (const char *payload, size_t *payload_len, uint32_t flags) +zend_string *s_decompress_value (const char *payload, size_t payload_len, uint32_t flags) { - char *buffer = NULL; - uint32_t len; + zend_string *buffer; + + uint32_t stored_length; unsigned long length; zend_bool decompress_status = 0; + zend_bool is_fastlz = 0, is_zlib = 0; - /* Stored with newer memcached extension? */ - if (MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_FASTLZ) || MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_ZLIB)) { - /* This is copied from Ilia's patch */ - memcpy(&len, payload, sizeof(uint32_t)); - buffer = emalloc(len + 1); - *payload_len -= sizeof(uint32_t); - payload += sizeof(uint32_t); - length = len; - - if (MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_FASTLZ)) { - decompress_status = ((length = fastlz_decompress(payload, *payload_len, buffer, len)) > 0); - } else if (MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_ZLIB)) { - decompress_status = (uncompress((Bytef *)buffer, &length, (Bytef *)payload, *payload_len) == Z_OK); - } + if (payload_len < sizeof (uint32_t)) { + return NULL; } - /* Fall back to 'old style decompression' */ - if (!decompress_status) { - unsigned int factor = 1, maxfactor = 16; - int status; - - do { - length = (unsigned long)*payload_len * (1 << factor++); - buffer = erealloc(buffer, length + 1); - memset(buffer, 0, length + 1); - status = uncompress((Bytef *)buffer, (uLongf *)&length, (const Bytef *)payload, *payload_len); - } while ((status==Z_BUF_ERROR) && (factor < maxfactor)); - - if (status == Z_OK) { - decompress_status = 1; - } + is_fastlz = MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_FASTLZ); + is_zlib = MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_ZLIB); + + if (!is_fastlz && !is_zlib) { + php_error_docref(NULL, E_WARNING, "could not decompress value: unrecognised encryption type"); + return NULL; + } + + memcpy(&stored_length, payload, sizeof (uint32_t)); + + payload += sizeof (uint32_t); + payload_len -= sizeof (uint32_t); + + buffer = zend_string_alloc (stored_length, 0); + + if (is_fastlz) { + decompress_status = ((length = fastlz_decompress(payload, payload_len, &buffer->val, buffer->len)) > 0); + } + else if (is_zlib) { + decompress_status = (uncompress((Bytef *) buffer->val, &buffer->len, (Bytef *)payload, payload_len) == Z_OK); } if (!decompress_status) { php_error_docref(NULL, E_WARNING, "could not decompress value"); - efree(buffer); + zend_string_release (buffer); return NULL; } - buffer [length] = '\0'; - *payload_len = length; + + zend_string_forget_hash_val(buffer); return buffer; } static -zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_type, zval *value, const char *payload, size_t payload_len) +zend_bool s_unserialize_value (int val_type, zend_string *payload, zval *return_value) { switch (val_type) { case MEMC_VAL_IS_SERIALIZED: { - const char *payload_tmp = payload; php_unserialize_data_t var_hash; + const unsigned char *p, *max; + + p = (const unsigned char *) payload->val; + max = p + payload->len; PHP_VAR_UNSERIALIZE_INIT(var_hash); - if (!php_var_unserialize(value, (const unsigned char **)&payload_tmp, (const unsigned char *)payload_tmp + payload_len, &var_hash)) { - zval_ptr_dtor(value); - ZVAL_FALSE(value); + if (!php_var_unserialize(return_value, &p, max, &var_hash)) { + zval_ptr_dtor(return_value); + ZVAL_FALSE(return_value); PHP_VAR_UNSERIALIZE_DESTROY(var_hash); php_error_docref(NULL, E_WARNING, "could not unserialize value"); return 0; @@ -3319,13 +3312,13 @@ zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_typ case MEMC_VAL_IS_IGBINARY: #ifdef HAVE_MEMCACHED_IGBINARY - if (igbinary_unserialize((uint8_t *)payload, payload_len, &value)) { - ZVAL_FALSE(value); + if (igbinary_unserialize((uint8_t *) payload->val, payload->len, &value)) { + ZVAL_FALSE(return_value); php_error_docref(NULL, E_WARNING, "could not unserialize value with igbinary"); return 0; } #else - ZVAL_FALSE(value); + ZVAL_FALSE(return_value); php_error_docref(NULL, E_WARNING, "could not unserialize value, no igbinary support"); return 0; #endif @@ -3333,9 +3326,9 @@ zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_typ case MEMC_VAL_IS_JSON: #ifdef HAVE_JSON_API - php_json_decode(value, (char*) payload, payload_len, (serializer == SERIALIZER_JSON_ARRAY), PHP_JSON_PARSER_DEFAULT_DEPTH); + php_json_decode(return_value, payload->val, payload->len, (serializer == SERIALIZER_JSON_ARRAY), PHP_JSON_PARSER_DEFAULT_DEPTH); #else - ZVAL_FALSE(value); + ZVAL_FALSE(return_value); php_error_docref(NULL, E_WARNING, "could not unserialize value, no json support"); return 0; #endif @@ -3343,9 +3336,9 @@ zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_typ case MEMC_VAL_IS_MSGPACK: #ifdef HAVE_MEMCACHED_MSGPACK - php_msgpack_unserialize(value, payload, payload_len); + php_msgpack_unserialize(return_value, payload->val, payload->len); #else - ZVAL_FALSE(value); + ZVAL_FALSE(return_value); php_error_docref(NULL, E_WARNING, "could not unserialize value, no msgpack support"); return 0; #endif @@ -3354,117 +3347,85 @@ zend_bool s_unserialize_value (enum memcached_serializer serializer, int val_typ return 1; } -/* The caller MUST free the payload */ -static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_t payload_len, uint32_t flags, enum memcached_serializer serializer) +static +zend_bool s_memcached_result_to_zval(memcached_result_st *result, zval *return_value) { - /* - A NULL payload is completely valid if length is 0, it is simply empty. - */ - int retval = 0; - zend_bool payload_emalloc = 0; - char *pl = NULL; - - if (payload_in == NULL && payload_len > 0) { - ZVAL_FALSE(value); - php_error_docref(NULL, E_WARNING, - "Could not handle non-existing value of length %zu", payload_len); - return -1; - } else if (payload_in == NULL) { - if (MEMC_VAL_GET_TYPE(flags) == MEMC_VAL_IS_BOOL) { - ZVAL_FALSE(value); - } else { - ZVAL_EMPTY_STRING(value); - } + zend_string *data; + const char *payload; + size_t payload_len; + uint32_t flags; + zend_bool retval = 1; + + payload = memcached_result_value(result); + payload_len = memcached_result_length(result); + flags = memcached_result_flags(result); + + if (!payload && payload_len > 0) { + php_error_docref(NULL, E_WARNING, "Could not handle non-existing value of length %zu", payload_len); return 0; } if (MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSED)) { - char *datas = s_decompress_value (payload_in, &payload_len, flags); - if (!datas) { - ZVAL_FALSE(value); - return -1; + data = s_decompress_value (payload, payload_len, flags); + if (!data) { + return 0; } - pl = datas; - payload_emalloc = 1; } else { - pl = (char *) payload_in; + data = zend_string_init(payload, payload_len, 0); } switch (MEMC_VAL_GET_TYPE(flags)) { + case MEMC_VAL_IS_STRING: - ZVAL_STRINGL(value, pl, payload_len); + ZVAL_STR_COPY(return_value, data); break; case MEMC_VAL_IS_LONG: - { - long lval; - char conv_buf [128]; - - if (payload_len >= 128) { - php_error_docref(NULL, E_WARNING, "could not read long value, too big"); - retval = -1; - } - else { - memcpy (conv_buf, pl, payload_len); - conv_buf [payload_len] = '\0'; - - lval = strtol(conv_buf, NULL, 10); - ZVAL_LONG(value, lval); - } - } + ZVAL_LONG(return_value, strtol(data->val, NULL, 10)); break; case MEMC_VAL_IS_DOUBLE: { - char conv_buf [128]; - - if (payload_len >= 128) { - php_error_docref(NULL, E_WARNING, "could not read double value, too big"); - retval = -1; + if (payload_len == 8 && memcmp(data->val, "Infinity", 8) == 0) { + ZVAL_DOUBLE(return_value, php_get_inf()); + } + else if (payload_len == 9 && memcmp(data->val, "-Infinity", 9) == 0) { + ZVAL_DOUBLE(return_value, -php_get_inf()); + } + else if (payload_len == 3 && memcmp(data->val, "NaN", 3) == 0) { + ZVAL_DOUBLE(return_value, php_get_nan()); } else { - memcpy (conv_buf, pl, payload_len); - conv_buf [payload_len] = '\0'; - - if (payload_len == 8 && memcmp(conv_buf, "Infinity", 8) == 0) { - ZVAL_DOUBLE(value, php_get_inf()); - } else if (payload_len == 9 && memcmp(conv_buf, "-Infinity", 9) == 0) { - ZVAL_DOUBLE(value, -php_get_inf()); - } else if (payload_len == 3 && memcmp(conv_buf, "NaN", 3) == 0) { - ZVAL_DOUBLE(value, php_get_nan()); - } else { - ZVAL_DOUBLE(value, zend_strtod(conv_buf, NULL)); - } + ZVAL_DOUBLE(return_value, zend_strtod(data->val, NULL)); } } break; case MEMC_VAL_IS_BOOL: - ZVAL_BOOL(value, payload_len > 0 && pl[0] == '1'); + ZVAL_BOOL(return_value, payload_len > 0 && data->val[0] == '1'); break; case MEMC_VAL_IS_SERIALIZED: case MEMC_VAL_IS_IGBINARY: case MEMC_VAL_IS_JSON: case MEMC_VAL_IS_MSGPACK: - if (!s_unserialize_value (serializer, MEMC_VAL_GET_TYPE(flags), value, pl, payload_len)) { - retval = -1; - } + retval = s_unserialize_value (MEMC_VAL_GET_TYPE(flags), data, return_value); break; default: - ZVAL_FALSE(value); php_error_docref(NULL, E_WARNING, "unknown payload type"); - retval = -1; + retval = 0; break; } + zend_string_release(data); - if (payload_emalloc) { - efree(pl); + if (!retval) { + zval_ptr_dtor(return_value); } return retval; } + PHP_MEMCACHED_API zend_class_entry *php_memc_get_ce(void) { @@ -3508,8 +3469,7 @@ zend_class_entry *php_memc_get_exception_base(int root) static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string *key, zval *value) { - char *payload = NULL; - size_t payload_len = 0; + zend_string *payload = NULL; zval params[4]; zval retval; zval z_key; @@ -3550,16 +3510,19 @@ static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_i time_t expir; expir = zval_get_long(expiration); + payload = s_zval_to_payload(value, &flags, m_obj->serializer, m_obj->compression_type); - payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type); if (payload == NULL) { status = (memcached_return)MEMC_RES_PAYLOAD_FAILURE; } else { - rc = memcached_set(m_obj->memc, key->val, key->len, payload, payload_len, expir, flags); + if (m_obj->set_udf_flags >= 0) { + MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) m_obj->set_udf_flags)); + } + rc = memcached_set(m_obj->memc, key->val, key->len, payload->val, payload->len, expir, flags); if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED) { status = rc; } - efree(payload); + zend_string_release(payload); } } else { status = MEMCACHED_NOTFOUND; @@ -3616,8 +3579,7 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, i_obj = Z_MEMC_OBJ_P(zmemc_obj); - if (php_memc_zval_from_payload(&value, payload, payload_len, flags, i_obj->obj->serializer) < 0) { - zval_ptr_dtor(&value); + if (!s_memcached_result_to_zval(result, &value)) { i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; return -1; } @@ -3734,27 +3696,23 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_get, 0, 0, 1) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, cache_cb) - ZEND_ARG_INFO(2, cas_token) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getByKey, 0, 0, 2) ZEND_ARG_INFO(0, server_key) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, cache_cb) - ZEND_ARG_INFO(2, cas_token) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getMulti, 0, 0, 1) ZEND_ARG_ARRAY_INFO(0, keys, 0) - ZEND_ARG_INFO(2, cas_tokens) - ZEND_ARG_INFO(0, flags) + ZEND_ARG_INFO(0, get_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getMultiByKey, 0, 0, 2) ZEND_ARG_INFO(0, server_key) ZEND_ARG_ARRAY_INFO(0, keys, 0) - ZEND_ARG_INFO(2, cas_tokens) - ZEND_ARG_INFO(0, flags) + ZEND_ARG_INFO(0, get_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getDelayed, 0, 0, 1) @@ -3811,9 +3769,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_setMultiByKey, 0, 0, 2) ZEND_ARG_INFO(0, expiration) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_getLastUserFlags, 0, 0, 0) -ZEND_END_ARG_INFO() - ZEND_BEGIN_ARG_INFO_EX(arginfo_add, 0, 0, 2) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) @@ -4041,8 +3996,6 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(setMulti, arginfo_setMulti) MEMC_ME(setMultiByKey, arginfo_setMultiByKey) - MEMC_ME(getLastUserFlags, arginfo_getLastUserFlags) - MEMC_ME(cas, arginfo_cas) MEMC_ME(casByKey, arginfo_casByKey) MEMC_ME(add, arginfo_add) @@ -4136,35 +4089,36 @@ static PHP_GINIT_FUNCTION(php_memcached) { #ifdef HAVE_MEMCACHED_SESSION - php_memcached_globals->sess_locking_enabled = 1; - php_memcached_globals->sess_binary_enabled = 1; - php_memcached_globals->sess_consistent_hash_enabled = 0; - php_memcached_globals->sess_number_of_replicas = 0; - php_memcached_globals->sess_remove_failed_enabled = 0; - php_memcached_globals->sess_prefix = NULL; - php_memcached_globals->sess_lock_wait = 0; - php_memcached_globals->sess_lock_max_wait = 0; - php_memcached_globals->sess_lock_expire = 0; - php_memcached_globals->sess_locked = 0; - php_memcached_globals->sess_lock_key = NULL; - php_memcached_globals->sess_lock_key_len = 0; - php_memcached_globals->sess_randomize_replica_read = 0; - php_memcached_globals->sess_connect_timeout = 1000; -#if HAVE_MEMCACHED_SASL - php_memcached_globals->sess_sasl_username = NULL; - php_memcached_globals->sess_sasl_password = NULL; - php_memcached_globals->sess_sasl_data = 0; -#endif + + php_memcached_globals->session_ini.lock_enabled = 0; + php_memcached_globals->session_ini.lock_wait_max = 2000; + php_memcached_globals->session_ini.lock_wait_min = 1000; + php_memcached_globals->session_ini.lock_retries = 5; + php_memcached_globals->session_ini.lock_expiration = 30; + php_memcached_globals->session_ini.compression_enabled = 1; + php_memcached_globals->session_ini.binary_protocol_enabled = 1; + php_memcached_globals->session_ini.consistent_hash_enabled = 1; + php_memcached_globals->session_ini.number_of_replicas = 0; + php_memcached_globals->session_ini.server_failure_limit = 1; + php_memcached_globals->session_ini.randomize_replica_read_enabled = 1; + php_memcached_globals->session_ini.remove_failed_servers_enabled = 1; + php_memcached_globals->session_ini.connect_timeout = 1000; + php_memcached_globals->session_ini.prefix = NULL; + php_memcached_globals->session_ini.persistent_enabled = 0; + php_memcached_globals->session_ini.sasl_username = NULL; + php_memcached_globals->session_ini.sasl_password = NULL; + #endif - php_memcached_globals->serializer_name = NULL; - php_memcached_globals->serializer = SERIALIZER_DEFAULT; - php_memcached_globals->compression_type = NULL; - php_memcached_globals->compression_type_real = COMPRESSION_TYPE_FASTLZ; - php_memcached_globals->compression_factor = 1.30; + php_memcached_globals->memc_ini.serializer_name = NULL; + php_memcached_globals->memc_ini.serializer = SERIALIZER_DEFAULT; + php_memcached_globals->memc_ini.compression_type = NULL; + php_memcached_globals->memc_ini.compression_threshold = 2000; + php_memcached_globals->memc_ini.compression_type_real = COMPRESSION_TYPE_FASTLZ; + php_memcached_globals->memc_ini.compression_factor = 1.30; + php_memcached_globals->memc_ini.store_retry_count = 2; #if HAVE_MEMCACHED_SASL - php_memcached_globals->use_sasl = 0; + php_memcached_globals->memc_ini.sasl_enabled = 0; #endif - php_memcached_globals->store_retry_count = 2; } zend_module_entry memcached_module_entry = { @@ -4374,6 +4328,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) * Flags. */ REGISTER_MEMC_CLASS_CONST_LONG(GET_PRESERVE_ORDER, MEMC_GET_PRESERVE_ORDER); + REGISTER_MEMC_CLASS_CONST_LONG(GET_EXTENDED, MEMC_GET_EXTENDED); #ifdef HAVE_MEMCACHED_PROTOCOL /* @@ -4422,11 +4377,6 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) } /* }}} */ -int php_memc_sess_list_entry(void) -{ - return le_memc_sess; -} - /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(memcached) { @@ -4438,7 +4388,6 @@ PHP_MINIT_FUNCTION(memcached) memcached_object_handlers.free_obj = php_memc_free_storage; le_memc = zend_register_list_destructors_ex(NULL, php_memc_dtor, "Memcached persistent connection", module_number); - le_memc_sess = zend_register_list_destructors_ex(NULL, php_memc_sess_dtor, "Memcached Sessions persistent connection", module_number); INIT_CLASS_ENTRY(ce, "Memcached", memcached_class_methods); memcached_ce = zend_register_internal_class(&ce); @@ -4462,12 +4411,12 @@ PHP_MINIT_FUNCTION(memcached) php_memc_register_constants(INIT_FUNC_ARGS_PASSTHRU); #ifdef HAVE_MEMCACHED_SESSION - php_session_register_module(ps_memcached_ptr); + php_memc_session_minit(module_number); #endif REGISTER_INI_ENTRIES(); #if HAVE_MEMCACHED_SASL - if (MEMC_G(use_sasl)) { + if (MEMC_G(sasl_enabled)) { if (sasl_client_init(NULL) != SASL_OK) { php_error_docref(NULL, E_ERROR, "Failed to initialize SASL library"); return FAILURE; @@ -4482,7 +4431,7 @@ PHP_MINIT_FUNCTION(memcached) PHP_MSHUTDOWN_FUNCTION(memcached) { #if HAVE_MEMCACHED_SASL - if (MEMC_G(use_sasl)) { + if (MEMC_G(sasl_enabled)) { sasl_done(); } #endif diff --git a/php_memcached_private.h b/php_memcached_private.h index ffca963d..46565e70 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -129,46 +129,60 @@ typedef struct { #endif ZEND_BEGIN_MODULE_GLOBALS(php_memcached) + #ifdef HAVE_MEMCACHED_SESSION - zend_bool sess_locking_enabled; - long sess_lock_wait; - long sess_lock_max_wait; - long sess_lock_expire; - char* sess_prefix; - zend_bool sess_locked; - char* sess_lock_key; - int sess_lock_key_len; - - int sess_number_of_replicas; - zend_bool sess_randomize_replica_read; - zend_bool sess_remove_failed_enabled; - long sess_connect_timeout; - zend_bool sess_consistent_hash_enabled; - zend_bool sess_binary_enabled; + /* Session related variables */ + struct { + zend_bool lock_enabled; + zend_long lock_wait_max; + zend_long lock_wait_min; + zend_long lock_retries; + zend_long lock_expiration; + + zend_bool compression_enabled; + zend_bool binary_protocol_enabled; + zend_bool consistent_hash_enabled; + + zend_long server_failure_limit; + zend_long number_of_replicas; + zend_bool randomize_replica_read_enabled; + zend_bool remove_failed_servers_enabled; + + zend_long connect_timeout; + + char *prefix; + zend_bool persistent_enabled; + + char *sasl_username; + char *sasl_password; + } session_ini; -#if HAVE_MEMCACHED_SASL - char *sess_sasl_username; - char *sess_sasl_password; - zend_bool sess_sasl_data; -#endif #endif - char *serializer_name; - enum memcached_serializer serializer; - char *compression_type; - int compression_type_real; - int compression_threshold; + struct { + char *serializer_name; + char *compression_type; + zend_long compression_threshold; + double compression_factor; + zend_long store_retry_count; - double compression_factor; #if HAVE_MEMCACHED_SASL - zend_bool use_sasl; + zend_bool sasl_enabled; #endif + + /* Converted values*/ + enum memcached_serializer serializer; + zend_long compression_type_real; + } memc_ini; + + + #ifdef HAVE_MEMCACHED_PROTOCOL struct { php_memc_server_cb_t callbacks [MEMC_SERVER_ON_MAX]; } server; #endif - long store_retry_count; + ZEND_END_MODULE_GLOBALS(php_memcached) PHP_RINIT_FUNCTION(memcached); @@ -177,19 +191,6 @@ PHP_MINIT_FUNCTION(memcached); PHP_MSHUTDOWN_FUNCTION(memcached); PHP_MINFO_FUNCTION(memcached); -#ifdef ZTS -#define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, v) -#else -#define MEMC_G(v) (php_memcached_globals.v) -#endif - -typedef struct { - memcached_st *memc_sess; - zend_bool is_persistent; -} memcached_sess; - -int php_memc_sess_list_entry(void); - char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC); memcached_return php_memcached_exist (memcached_st *memc, zend_string *key); diff --git a/php_memcached_session.c b/php_memcached_session.c index 85baad03..8c6454a1 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -18,6 +18,8 @@ #include "php_memcached_private.h" #include "php_memcached_session.h" +#include "Zend/zend_smart_str_public.h" + extern ZEND_DECLARE_MODULE_GLOBALS(php_memcached) #define MEMC_SESS_DEFAULT_LOCK_WAIT 150000 @@ -27,278 +29,350 @@ ps_module ps_mod_memcached = { PS_MOD_UPDATE_TIMESTAMP(memcached) }; -static int php_memc_sess_lock(memcached_st *memc, const char *key) +typedef struct { + zend_bool is_persistent; + zend_bool has_sasl_data; + zend_bool is_locked; + zend_string *lock_key; +} php_memcached_user_data; + +#ifndef MIN +# define MIN(a,b) (((a)<(b))?(a):(b)) +#endif + +#ifndef MAX +# define MAX(a,b) (((a)>(b))?(a):(b)) +#endif + +#ifdef ZTS +#define MEMC_SESS_INI(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, session_ini.v) +#else +#define MEMC_SESS_INI(v) (php_memcached_globals.session_ini.v) +#endif + +#define MEMC_SESS_STR_INI(vv) ((MEMC_SESS_INI(vv) && *MEMC_SESS_INI(vv)) ? MEMC_SESS_INI(vv) : NULL) + +static + int le_memc_sess; + +static +int s_memc_sess_list_entry(void) { - char *lock_key = NULL; - int lock_key_len = 0; - unsigned long attempts; - long write_retry_attempts = 0; - long lock_maxwait = MEMC_G(sess_lock_max_wait); - long lock_wait = MEMC_G(sess_lock_wait); - long lock_expire = MEMC_G(sess_lock_expire); - time_t expiration; - memcached_return status; - /* set max timeout for session_start = max_execution_time. (c) Andrei Darashenka, Richter & Poweleit GmbH */ - if (lock_maxwait <= 0) { - lock_maxwait = zend_ini_long(ZEND_STRS("max_execution_time"), 0); - if (lock_maxwait <= 0) { - lock_maxwait = MEMC_SESS_LOCK_EXPIRATION; - } - } - if (lock_wait == 0) { - lock_wait = MEMC_SESS_DEFAULT_LOCK_WAIT; + return le_memc_sess; +} + +static +void s_destroy_mod_data(memcached_st *memc) +{ + php_memcached_user_data *user_data = memcached_get_user_data(memc); + + if (user_data->has_sasl_data) { + memcached_destroy_sasl_auth_data(memc); } - if (lock_expire <= 0) { - lock_expire = lock_maxwait; + + memcached_free(memc); + pefree(memc, user_data->is_persistent); + pefree(user_data, user_data->is_persistent); +} + +ZEND_RSRC_DTOR_FUNC(php_memc_sess_dtor) +{ + if (res->ptr) { + s_destroy_mod_data((memcached_st *) res->ptr); + res->ptr = NULL; } - expiration = lock_expire + 1; - attempts = (unsigned long)((1000000.0 / lock_wait) * lock_maxwait); +} - /* Set the number of write retry attempts to the number of replicas times the number of attempts to remove a server */ - if (MEMC_G(sess_remove_failed_enabled)) { - write_retry_attempts = MEMC_G(sess_number_of_replicas) * ( memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT) + 1); +int php_memc_session_minit(int module_number) +{ + le_memc_sess = + zend_register_list_destructors_ex(NULL, php_memc_sess_dtor, "Memcached Sessions persistent connection", module_number); + + php_session_register_module(ps_memcached_ptr); + return SUCCESS; +} + +static +time_t s_lock_expiration() +{ + zend_long max_execution_time; + + if (MEMC_SESS_INI(lock_expiration) > 0) { + return time(NULL) + MEMC_SESS_INI(lock_expiration); } + else { + zend_long max_execution_time = zend_ini_long(ZEND_STRS("max_execution_time"), 0); + if (max_execution_time > 0) { + return time(NULL) + max_execution_time; + } + } + return 0; +} + +static +zend_bool s_lock_session(memcached_st *memc, zend_string *sid) +{ + char *lock_key; + size_t lock_key_len; + time_t expiration; + zend_long wait_time, retries; + php_memcached_user_data *user_data = memcached_get_user_data(memc); + + lock_key_len = spprintf(&lock_key, 0, "lock.%s", sid->val); + expiration = s_lock_expiration(); + + wait_time = MEMC_SESS_INI(lock_wait_min); + retries = MEMC_SESS_INI(lock_retries); - lock_key_len = spprintf(&lock_key, 0, "lock.%s", key); do { - status = memcached_add(memc, lock_key, lock_key_len, "1", sizeof("1")-1, expiration, 0); - if (status == MEMCACHED_SUCCESS) { - MEMC_G(sess_locked) = 1; - MEMC_G(sess_lock_key) = lock_key; - MEMC_G(sess_lock_key_len) = lock_key_len; - return 0; - } else if (status != MEMCACHED_NOTSTORED && status != MEMCACHED_DATA_EXISTS) { - if (write_retry_attempts > 0) { - write_retry_attempts--; - continue; - } - php_error_docref(NULL, E_WARNING, "Write of lock failed"); + memcached_return rc = + memcached_add(memc, lock_key, lock_key_len, "1", sizeof ("1") - 1, expiration, 0); + + switch (rc) { + + case MEMCACHED_SUCCESS: + user_data->lock_key = zend_string_init(lock_key, lock_key_len, user_data->is_persistent); + user_data->is_locked = 1; + break; + + case MEMCACHED_NOTSTORED: + case MEMCACHED_DATA_EXISTS: + usleep(wait_time * 1000); + wait_time = MIN(MEMC_SESS_INI(lock_wait_max), wait_time * 2); break; - } - if (lock_wait > 0) { - usleep(lock_wait); + default: + php_error_docref(NULL, E_WARNING, "Failed to write session lock: %s", memcached_strerror (memc, rc)); + break; } - } while(--attempts > 0); + } while (!user_data->is_locked && retries-- > 0); efree(lock_key); - return -1; + return user_data->is_locked; } -static void php_memc_sess_unlock(memcached_st *memc) +static +void s_unlock_session(memcached_st *memc) { - if (MEMC_G(sess_locked)) { - memcached_delete(memc, MEMC_G(sess_lock_key), MEMC_G(sess_lock_key_len), 0); - MEMC_G(sess_locked) = 0; - efree(MEMC_G(sess_lock_key)); - MEMC_G(sess_lock_key_len) = 0; + php_memcached_user_data *user_data = memcached_get_user_data(memc); + + if (user_data->is_locked) { + memcached_delete(memc, user_data->lock_key->val, user_data->lock_key->len, 0); + user_data->is_locked = 0; + zend_string_release (user_data->lock_key); } } -PS_OPEN_FUNC(memcached) +static +zend_bool s_configure_from_ini_values(memcached_st *memc) { - memcached_sess *memc_sess = PS_GET_MOD_DATA(); - memcached_return status; - char *p, *plist_key = NULL; - int plist_key_len = 0; - - if (!strncmp((char *)save_path, "PERSISTENT=", sizeof("PERSISTENT=") - 1)) { - zend_resource *le = NULL; - zval *le_z = NULL; - char *e; - - p = (char *)save_path + sizeof("PERSISTENT=") - 1; - if (!*p) { -error: - php_error_docref(NULL, E_WARNING, "Invalid persistent id for session storage"); - return FAILURE; - } - if ((e = strchr(p, ' '))) { - plist_key_len = spprintf(&plist_key, 0, "memcached_sessions:id=%.*s", (int)(e - p), p); - } else { - goto error; - } - plist_key_len++; - - if ((le_z = zend_hash_str_find(&EG(persistent_list), plist_key, plist_key_len)) != NULL) { - le = Z_RES_P(le_z); - if (le->type == php_memc_sess_list_entry()) { - memc_sess = (memcached_sess *) le->ptr; - PS_SET_MOD_DATA(memc_sess); - return SUCCESS; - } - } - p = e + 1; - memc_sess = pecalloc(sizeof(*memc_sess), 1, 1); - memc_sess->is_persistent = 1; - } else { - p = (char *)save_path; - memc_sess = ecalloc(sizeof(*memc_sess), 1); - memc_sess->is_persistent = 0; - } - - if (!strstr(p, "--SERVER")) { - memcached_server_st *servers = memcached_servers_parse(p); - if (servers) { - memc_sess->memc_sess = memcached_create(NULL); - if (memc_sess->memc_sess) { - if (MEMC_G(sess_consistent_hash_enabled)) { - if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED, (uint64_t) 1) == MEMCACHED_FAILURE) { - PS_SET_MOD_DATA(NULL); - if (plist_key) { - efree(plist_key); - } - memcached_free(memc_sess->memc_sess); - php_error_docref(NULL, E_WARNING, "failed to enable memcached consistent hashing"); - return FAILURE; - } - } + memcached_return rc; - status = memcached_server_push(memc_sess->memc_sess, servers); - memcached_server_list_free(servers); - - if (MEMC_G(sess_prefix) && MEMC_G(sess_prefix)[0] != 0 && memcached_callback_set(memc_sess->memc_sess, MEMCACHED_CALLBACK_PREFIX_KEY, MEMC_G(sess_prefix)) != MEMCACHED_SUCCESS) { - PS_SET_MOD_DATA(NULL); - if (plist_key) { - efree(plist_key); - } - memcached_free(memc_sess->memc_sess); - php_error_docref(NULL, E_WARNING, "bad memcached key prefix in memcached.sess_prefix"); - return FAILURE; - } +#define check_set_behavior(behavior, value) \ + if ((rc = memcached_behavior_set(memc, (behavior), (value))) != MEMCACHED_SUCCESS) { \ + php_error_docref(NULL, E_WARNING, "failed to initialise session memcached configuration: %s", memcached_strerror(memc, rc)); \ + return 0; \ + } - if (status == MEMCACHED_SUCCESS) { - goto success; - } - } else { - memcached_server_list_free(servers); - php_error_docref(NULL, E_WARNING, "could not allocate libmemcached structure"); - } - } else { - php_error_docref(NULL, E_WARNING, "failed to parse session.save_path"); - } - } else { - memc_sess->memc_sess = php_memc_create_str(p, strlen(p)); - if (!memc_sess->memc_sess) { -#ifdef HAVE_LIBMEMCACHED_CHECK_CONFIGURATION - char error_buffer[1024]; - if (libmemcached_check_configuration(p, strlen(p), error_buffer, sizeof(error_buffer)) != MEMCACHED_SUCCESS) { - php_error_docref(NULL, E_WARNING, "session.save_path configuration error %s", error_buffer); - } else { - php_error_docref(NULL, E_WARNING, "failed to initialize memcached session storage"); - } -#else - php_error_docref(NULL, E_WARNING, "failed to initialize memcached session storage"); -#endif + if (MEMC_SESS_INI(binary_protocol_enabled)) { + check_set_behavior(MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1); + } - } else { -success: - PS_SET_MOD_DATA(memc_sess); + if (MEMC_SESS_INI(consistent_hash_enabled)) { + check_set_behavior(MEMCACHED_BEHAVIOR_KETAMA, 1); + } - if (plist_key) { - zend_resource le; - zend_string *tmp_key; + if (MEMC_SESS_INI(server_failure_limit)) { + check_set_behavior(MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, MEMC_SESS_INI(server_failure_limit)); + } - le.type = php_memc_sess_list_entry(); - le.ptr = memc_sess; + if (MEMC_SESS_INI(number_of_replicas)) { + check_set_behavior(MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, MEMC_SESS_INI(number_of_replicas)); + } - tmp_key = zend_string_init(plist_key, plist_key_len, 0); - if (zend_hash_update_mem(&EG(persistent_list), tmp_key, (void *)&le, sizeof(le)) == NULL) { - zend_string_release(tmp_key); - efree(plist_key); - php_error_docref(NULL, E_ERROR, "could not register persistent entry"); - } - zend_string_release(tmp_key); - efree(plist_key); - } + if (MEMC_SESS_INI(randomize_replica_read_enabled)) { + check_set_behavior(MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ, 1); + } + + if (MEMC_SESS_INI(remove_failed_servers_enabled)) { + check_set_behavior(MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS, 1); + } + + if (MEMC_SESS_INI(connect_timeout)) { + check_set_behavior(MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, MEMC_SESS_INI(connect_timeout)); + } + + if (MEMC_SESS_STR_INI(prefix)) { + memcached_callback_set(memc, MEMCACHED_CALLBACK_NAMESPACE, MEMC_SESS_STR_INI(prefix)); + } - if (MEMC_G(sess_binary_enabled)) { - if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, (uint64_t) 1) == MEMCACHED_FAILURE) { - php_error_docref(NULL, E_WARNING, "failed to set memcached session binary protocol"); - return FAILURE; - } - } #ifdef HAVE_MEMCACHED_SASL - if (MEMC_G(use_sasl)) { - /* - * Enable SASL support if username and password are set - * - */ - if (MEMC_G(sess_sasl_username) && MEMC_G(sess_sasl_password)) { - /* Force binary protocol */ - if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, (uint64_t) 1) == MEMCACHED_FAILURE) { - php_error_docref(NULL, E_WARNING, "failed to set memcached session binary protocol"); - return FAILURE; - } - if (memcached_set_sasl_auth_data(memc_sess->memc_sess, MEMC_G(sess_sasl_username), MEMC_G(sess_sasl_password)) == MEMCACHED_FAILURE) { - php_error_docref(NULL, E_WARNING, "failed to set memcached session sasl credentials"); - return FAILURE; - } - MEMC_G(sess_sasl_data) = 1; - } - } + if (MEMC_SESS_STR_INI(sasl_username) && MEMC_SESS_STR_INI(sasl_password)) { + php_memcached_user_data *user_data; + check_set_behavior(MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1); + if (memcached_set_sasl_auth_data(memc, MEMC_SESS_STR_INI(sasl_username), MEMC_SESS_STR_INI(sasl_password)) == MEMCACHED_FAILURE) { + php_error_docref(NULL, E_WARNING, "failed to set memcached session sasl credentials"); + return 0; + } + user_data = memcached_get_user_data(memc); + user_data->has_sasl_data = 1; + } #endif - if (MEMC_G(sess_number_of_replicas) > 0) { - if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, (uint64_t) MEMC_G(sess_number_of_replicas)) == MEMCACHED_FAILURE) { - php_error_docref(NULL, E_WARNING, "failed to set memcached session number of replicas"); - return FAILURE; - } - if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ, (uint64_t) MEMC_G(sess_randomize_replica_read)) == MEMCACHED_FAILURE) { - php_error_docref(NULL, E_WARNING, "failed to set memcached session randomize replica read"); - } - } - if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, (uint64_t) MEMC_G(sess_connect_timeout)) == MEMCACHED_FAILURE) { - php_error_docref(NULL, E_WARNING, "failed to set memcached connection timeout"); - return FAILURE; - } -#ifdef HAVE_MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS - /* Allow libmemcached remove failed servers */ - if (MEMC_G(sess_remove_failed_enabled)) { - if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS, (uint64_t) 1) == MEMCACHED_FAILURE) { - php_error_docref(NULL, E_WARNING, "failed to set: remove failed servers"); - return FAILURE; +#undef safe_set_behavior + + return 1; +} + +static +void *s_pemalloc_fn(const memcached_st *memc, size_t size, void *context) +{ + zend_bool *is_persistent = memcached_get_user_data(memc); + + return + pemalloc(size, *is_persistent); +} + +static +void s_pefree_fn(const memcached_st *memc, void *mem, void *context) +{ + zend_bool *is_persistent = memcached_get_user_data(memc); + + return + pefree(mem, *is_persistent); +} + +static +void *s_perealloc_fn(const memcached_st *memc, void *mem, const size_t size, void *context) +{ + zend_bool *is_persistent = memcached_get_user_data(memc); + + return + perealloc(mem, size, *is_persistent); +} + +static +void *s_pecalloc_fn(const memcached_st *memc, size_t nelem, const size_t elsize, void *context) +{ + zend_bool *is_persistent = memcached_get_user_data(memc); + + return + pecalloc(nelem, elsize, *is_persistent); +} + + +static +memcached_st *s_init_mod_data (const memcached_server_list_st servers, zend_bool is_persistent) +{ + void *buffer; + php_memcached_user_data *user_data; + memcached_st *memc; + + buffer = pecalloc(1, sizeof(memcached_st), is_persistent); + memc = memcached_create (buffer); + + if (!memc) { + php_error_docref(NULL, E_ERROR, "failed to allocate memcached structure"); + /* not reached */ + } + + memcached_set_memory_allocators(memc, s_pemalloc_fn, s_pefree_fn, s_perealloc_fn, s_pecalloc_fn, NULL); + + user_data = pecalloc(1, sizeof(php_memcached_user_data), is_persistent); + user_data->is_persistent = is_persistent; + user_data->has_sasl_data = 0; + user_data->lock_key = NULL; + user_data->is_locked = 0; + + memcached_set_user_data(memc, user_data); + memcached_server_push (memc, servers); + return memc; +} + +PS_OPEN_FUNC(memcached) +{ + memcached_st *memc = NULL; + char *plist_key = NULL; + size_t plist_key_len = 0; + memcached_server_list_st servers; + + // First parse servers + servers = memcached_servers_parse(save_path); + + if (!servers) { + php_error_docref(NULL, E_WARNING, "failed to parse session.save_path"); + PS_SET_MOD_DATA(NULL); + return FAILURE; + } + + if (MEMC_SESS_INI(persistent_enabled)) { + zend_resource *le_p; + + plist_key_len = spprintf(&plist_key, 0, "memc-session:%s", save_path); + + if ((le_p = zend_hash_str_find_ptr(&EG(persistent_list), plist_key, plist_key_len)) != NULL) { + if (le_p->type == s_memc_sess_list_entry()) { + memc = (memcached_st *) le_p->ptr; + + if (!s_configure_from_ini_values(memc)) { + // Remove existing plist entry + zend_hash_str_del(&EG(persistent_list), plist_key, plist_key_len); + memc = NULL; + } + else { + efree(plist_key); + PS_SET_MOD_DATA(memc); + return SUCCESS; } } -#endif - return SUCCESS; } } + memc = s_init_mod_data(servers, MEMC_SESS_INI(persistent_enabled)); + memcached_server_list_free(servers); + if (plist_key) { + zend_resource le; + + le.type = s_memc_sess_list_entry(); + le.ptr = memc; + + GC_REFCOUNT(&le) = 1; + + /* plist_key is not a persistent allocated key, thus we use str_update here */ + if (zend_hash_str_update_mem(&EG(persistent_list), plist_key, plist_key_len, &le, sizeof(le)) == NULL) { + php_error_docref(NULL, E_ERROR, "Could not register persistent entry for the memcached session"); + /* not reached */ + } efree(plist_key); } - PS_SET_MOD_DATA(NULL); - return FAILURE; + PS_SET_MOD_DATA(memc); + return SUCCESS; } PS_CLOSE_FUNC(memcached) { - memcached_sess *memc_sess = PS_GET_MOD_DATA(); + memcached_st *memc = PS_GET_MOD_DATA(); + php_memcached_user_data *user_data; - if (!memc_sess) { + if (!memc) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); return FAILURE; } - if (MEMC_G(sess_locking_enabled)) { - php_memc_sess_unlock(memc_sess->memc_sess); + user_data = memcached_get_user_data(memc); + + if (user_data->is_locked) { + s_unlock_session(memc); } - if (memc_sess->memc_sess) { - if (!memc_sess->is_persistent) { -#ifdef HAVE_MEMCACHED_SASL - if (MEMC_G(sess_sasl_data)) { - memcached_destroy_sasl_auth_data(memc_sess->memc_sess); - } -#endif - memcached_free(memc_sess->memc_sess); - efree(memc_sess); - } - PS_SET_MOD_DATA(NULL); + + if (!user_data->is_persistent) { + s_destroy_mod_data(memc); } + PS_SET_MOD_DATA(NULL); return SUCCESS; } @@ -306,35 +380,27 @@ PS_READ_FUNC(memcached) { char *payload = NULL; size_t payload_len = 0; - int key_len = key->len; uint32_t flags = 0; memcached_return status; - memcached_sess *memc_sess = PS_GET_MOD_DATA(); - size_t key_length; + memcached_st *memc = PS_GET_MOD_DATA(); - if (!memc_sess) { + if (!memc) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); return FAILURE; } - key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock." - if (!key_length || key_length >= MEMCACHED_MAX_KEY) { - php_error_docref(NULL, E_WARNING, "The session id is too long or contains illegal characters"); - return FAILURE; - } - - if (MEMC_G(sess_locking_enabled)) { - if (php_memc_sess_lock(memc_sess->memc_sess, key->val) < 0) { + if (MEMC_SESS_INI(lock_enabled)) { + if (!s_lock_session(memc, key)) { php_error_docref(NULL, E_WARNING, "Unable to clear session lock record"); return FAILURE; } } - payload = memcached_get(memc_sess->memc_sess, key->val, key_len, &payload_len, &flags, &status); + payload = memcached_get(memc, key->val, key->len, &payload_len, &flags, &status); if (status == MEMCACHED_SUCCESS) { - *val = zend_string_init(payload, payload_len, 1); - free(payload); + *val = zend_string_init(payload, payload_len, 0); + efree(payload); return SUCCESS; } else if (status == MEMCACHED_NOTFOUND) { *val = ZSTR_EMPTY_ALLOC(); @@ -346,59 +412,53 @@ PS_READ_FUNC(memcached) PS_WRITE_FUNC(memcached) { - int key_len = key->len; - time_t expiration = 0; - long write_try_attempts = 1; - memcached_return status; - memcached_sess *memc_sess = PS_GET_MOD_DATA(); + zend_long retries = 1; + memcached_st *memc = PS_GET_MOD_DATA(); size_t key_length; + time_t expiration; - if (!memc_sess) { + if (!memc) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); return FAILURE; } - key_length = strlen(MEMC_G(sess_prefix)) + key_len + 5; // prefix + "lock." - if (!key_length || key_length >= MEMCACHED_MAX_KEY) { - php_error_docref(NULL, E_WARNING, "The session id is too long or contains illegal characters"); - return FAILURE; - } + /* Set the number of write retry attempts to the number of replicas times the number of attempts to remove a server plus the initial write */ + if (MEMC_SESS_INI(remove_failed_servers_enabled)) { + zend_long replicas, failure_limit; - if (maxlifetime > 0) { - expiration = maxlifetime; - } + replicas = memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS); + failure_limit = memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT); - /* Set the number of write retry attempts to the number of replicas times the number of attempts to remove a server plus the initial write */ - if (MEMC_G(sess_remove_failed_enabled)) { - write_try_attempts = 1 + MEMC_G(sess_number_of_replicas) * ( memcached_behavior_get(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT) + 1); + retries = 1 + replicas * (failure_limit + 1); } + expiration = time(NULL) + maxlifetime; + do { - status = memcached_set(memc_sess->memc_sess, key->val, key_len, val->val, val->len, expiration, 0); - if (status == MEMCACHED_SUCCESS) { + if (memcached_set(memc, key->val, key->len, val->val, val->len, expiration, 0) == MEMCACHED_SUCCESS) { return SUCCESS; - } else { - write_try_attempts--; } - } while (write_try_attempts > 0); + } while (--retries > 0); return FAILURE; } PS_DESTROY_FUNC(memcached) { - memcached_sess *memc_sess = PS_GET_MOD_DATA(); + php_memcached_user_data *user_data; + memcached_st *memc = PS_GET_MOD_DATA(); - if (!memc_sess) { + if (!memc) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); return FAILURE; } - memcached_delete(memc_sess->memc_sess, key->val, key->len, 0); - if (MEMC_G(sess_locking_enabled)) { - php_memc_sess_unlock(memc_sess->memc_sess); - } + memcached_delete(memc, key->val, key->len, 0); + user_data = memcached_get_user_data(memc); + if (user_data->is_locked) { + s_unlock_session(memc); + } return SUCCESS; } @@ -410,34 +470,31 @@ PS_GC_FUNC(memcached) PS_CREATE_SID_FUNC(memcached) { zend_string *sid; - int retries = 3; - memcached_sess *memc_sess = PS_GET_MOD_DATA(); - time_t expiration = PS(gc_maxlifetime); + memcached_st *memc = PS_GET_MOD_DATA(); - if (!memc_sess) { - return NULL; + if (!memc) { + sid = php_session_create_id(NULL); } + else { + int retries = 3; + while (retries-- > 0) { + sid = php_session_create_id((void **) &memc); - while (retries-- > 0) { - sid = php_session_create_id((void**)&memc_sess); - - if (sid) { - if (memcached_add(memc_sess->memc_sess, sid->val, sid->len, "0", 0, expiration, 0) == MEMCACHED_SUCCESS) { - return sid; - } - else { - zend_string_release(sid); + if (memcached_add (memc, sid->val, sid->len, NULL, 0, s_lock_expiration(), 0) == MEMCACHED_SUCCESS) { + break; } + zend_string_release(sid); + sid = NULL; } } - return NULL; + return sid; } PS_VALIDATE_SID_FUNC(memcached) { - memcached_sess *memc_sess = PS_GET_MOD_DATA(); + memcached_st *memc = PS_GET_MOD_DATA(); - if (php_memcached_exist(memc_sess->memc_sess, key) == MEMCACHED_SUCCESS) { + if (php_memcached_exist(memc, key) == MEMCACHED_SUCCESS) { return SUCCESS; } else { return FAILURE; @@ -446,13 +503,10 @@ PS_VALIDATE_SID_FUNC(memcached) PS_UPDATE_TIMESTAMP_FUNC(memcached) { - memcached_sess *memc_sess = PS_GET_MOD_DATA(); - time_t expiration = 0; + memcached_st *memc = PS_GET_MOD_DATA(); + time_t expiration = time(NULL) + maxlifetime; - if (maxlifetime > 0) { - expiration = maxlifetime; - } - if (memcached_touch(memc_sess->memc_sess, key->val, key->len, expiration) == MEMCACHED_FAILURE) { + if (memcached_touch(memc, key->val, key->len, expiration) == MEMCACHED_FAILURE) { return FAILURE; } return SUCCESS; diff --git a/php_memcached_session.h b/php_memcached_session.h index 4118362f..13ce363c 100644 --- a/php_memcached_session.h +++ b/php_memcached_session.h @@ -36,4 +36,7 @@ PS_CREATE_SID_FUNC(memcached); PS_VALIDATE_SID_FUNC(memcached); PS_UPDATE_TIMESTAMP_FUNC(memcached); +/* Called from php_memcached.c */ +int php_memc_session_minit(int module_number); + #endif /* PHP_MEMCACHED_SESSION_H */ diff --git a/tests/cachecallback.phpt b/tests/cachecallback.phpt index 9fe8f4f8..31a736b7 100644 --- a/tests/cachecallback.phpt +++ b/tests/cachecallback.phpt @@ -13,6 +13,10 @@ $first_key = uniqid ('cache_test_'); $second_key = uniqid ('cache_test_'); $third_key = uniqid ('cache_test_'); +$m->delete($first_key); +$m->delete($second_key); +$m->delete($third_key); + var_dump ( $m->get ($first_key, function (Memcached $memc, $key, &$value, &$expiration) { $value = "hello"; diff --git a/tests/cas.phpt b/tests/cas.phpt index e9990798..c1c1752f 100644 --- a/tests/cas.phpt +++ b/tests/cas.phpt @@ -8,47 +8,12 @@ include dirname (__FILE__) . '/config.inc'; $m = memc_get_instance (); $m->delete('cas_test'); -$cas_token = null; +$cas_token = 0; -$m->set('cas_test', 10); -$v = $m->get('cas_test', null, $cas_token); - -if (is_null($cas_token)) { - echo "Null cas token for key: cas_test value: 10\n"; - return; -} - -$v = $m->cas($cas_token, 'cas_test', 11); -if (!$v) { - echo "Error setting key: cas_test value: 11 with CAS: $cas_token\n"; - return; -} - -$v = $m->get('cas_test'); - -if ($v !== 11) { - echo "Wanted cas_test to be 11, value is: "; - var_dump($v); -} - -$v = $m->get('cas_test', null, 2); -if ($v != 11) { - echo "Failed to get the value with \$cas_token passed by value (2)\n"; - return; -} - -$v = $m->get('cas_test', null, null); -if ($v != 11) { - echo "Failed to get the value with \$cas_token passed by value (null)\n"; - return; -} - -$v = $m->get('cas_test', null, $data = array(2, 4)); -if ($v != 11 || $data !== array(2, 4)) { - echo "Failed to get the value with \$cas_token passed by value (\$data = array(2, 4))\n"; - return; -} +$m->set('cas_test', 'hello'); +$cas_token = $m->get('cas_test', null, Memcached::GET_EXTENDED)['cas']; +$v = $m->cas($cas_token, 'cas_test', 0); echo "OK\n"; ?> --EXPECT-- diff --git a/tests/cas_multi.phpt b/tests/cas_multi.phpt index 240ecadd..499742be 100644 --- a/tests/cas_multi.phpt +++ b/tests/cas_multi.phpt @@ -16,25 +16,22 @@ foreach ($data as $key => $v) { $m->delete($key); } -$cas_tokens = array(); $m->setMulti($data, 10); -$actual = $m->getMulti(array_keys($data), $cas_tokens); +$actual = $m->getMulti(array_keys($data), Memcached::GET_EXTENDED); -foreach ($data as $key => $v) { - if (is_null($cas_tokens[$key])) { +foreach ($actual as $key => $v) { + if (is_null($v['cas'])) { echo "missing cas token(s)\n"; echo "data: "; var_dump($data); echo "actual data: "; var_dump($actual); - echo "cas tokens: "; - var_dump($cas_tokens); return; } - $v = $m->cas($cas_tokens[$key], $key, 11); + $v = $m->cas($v['cas'], $key, 11); if (!$v) { - echo "Error setting key: $key value: 11 with CAS: ", $cas_tokens[$key], "\n"; + echo "Error setting key: $key value: 11 with CAS: ", $v['cas'], "\n"; return; } $v = $m->get($key); @@ -54,24 +51,6 @@ if (array_keys($actual) !== array_keys($data)) { return; } -$actual = $m->getMulti(array_keys($data), 2); -if (array_keys($actual) !== array_keys($data)) { - echo "Failed to getMulti \$cas_token passed by value (2)\n"; - return; -} - -$actual = $m->getMulti(array_keys($data), null); -if (array_keys($actual) !== array_keys($data)) { - echo "Failed to getMulti \$cas_token passed by value (null)\n"; - return; -} - -$actual = $m->getMulti(array_keys($data), $cas_tokens = array(2, 4)); -if (array_keys($actual) !== array_keys($data) || $cas_tokens !== array(2, 4)) { - echo "Failed to getMulti \$cas_token passed by value (\$cas_tokens = array(2, 4))\n"; - return; -} - echo "OK\n"; ?> diff --git a/tests/multi_order.phpt b/tests/multi_order.phpt index 4fd5f5b4..876ddc66 100644 --- a/tests/multi_order.phpt +++ b/tests/multi_order.phpt @@ -21,10 +21,9 @@ foreach ($data as $k => $v) { $m->set($k, $v, 3600); } -$null = null; $keys = array_keys($data); $keys[] = 'zoo'; -$got = $m->getMulti($keys, $null, Memcached::GET_PRESERVE_ORDER); +$got = $m->getMulti($keys, Memcached::GET_PRESERVE_ORDER); foreach ($got as $k => $v) { echo "$k $v\n"; diff --git a/tests/no-not-found.phpt b/tests/no-not-found.phpt index de96d3e4..06ae85e9 100644 --- a/tests/no-not-found.phpt +++ b/tests/no-not-found.phpt @@ -11,8 +11,7 @@ $memcached->addServer('localhost', 5555); // Server should not exist $result = $memcached->get('foo_not_exists'); var_dump ($result === Memcached::GET_ERROR_RETURN_VALUE); -$cas = 7; -$result = $memcached->get('foo_not_exists', null, $cas); +$result = $memcached->get('foo_not_exists'); var_dump ($result === Memcached::GET_ERROR_RETURN_VALUE); echo "OK\n"; diff --git a/tests/rescode.phpt b/tests/rescode.phpt index fbda4f78..5b835d44 100644 --- a/tests/rescode.phpt +++ b/tests/rescode.phpt @@ -23,6 +23,7 @@ $m->delete('bar_foo'); echo $m->getResultCode(), "\n"; echo $m->getResultMessage(), "\n"; +$m->set ('asdf_a', 'aa'); $m->getMulti(array('asdf_a', 'jkhjkhjkb', 'nbahsdgc')); echo $m->getResultMessage(), "\n"; $code = $m->getResultCode(); diff --git a/tests/set_large.phpt b/tests/set_large.phpt index d9353a8e..bf1098ef 100644 --- a/tests/set_large.phpt +++ b/tests/set_large.phpt @@ -9,8 +9,9 @@ $m = memc_get_instance (); $key = 'foobarbazDEADC0DE'; $value = str_repeat("foo bar", 1024 * 1024); -$m->set($key, $value, 360); +var_dump($m->set($key, $value, 360)); var_dump($m->get($key) === $value); ?> --EXPECT-- bool(true) +bool(true) diff --git a/tests/user-flags.phpt b/tests/user-flags.phpt index 137ff1e8..7b02ea2d 100644 --- a/tests/user-flags.phpt +++ b/tests/user-flags.phpt @@ -16,6 +16,10 @@ function check_flags ($flags, $expected_flags) echo "Flags OK" . PHP_EOL; } +function get_flags($m, $key) { + return $m->get($key, null, Memcached::GET_EXTENDED)['flags']; +} + define ('FLAG_1', 1); define ('FLAG_2', 2); define ('FLAG_4', 4); @@ -30,26 +34,26 @@ $key = uniqid ('udf_test_'); // Set with flags off $m->set ($key, '1', 10); -$m->get($key); -var_dump($m->getLastUserFlags()); +$v = $m->get($key, null, Memcached::GET_EXTENDED); +var_dump($v); // Set flags on $m->setOption(Memcached::OPT_USER_FLAGS, FLAG_1); $m->set ($key, '1', 10); $m->get($key); -check_flags($m->getLastUserFlags()[$key], array(FLAG_1)); +check_flags(get_flags($m, $key), array(FLAG_1)); // Multiple flags $m->setOption(Memcached::OPT_USER_FLAGS, FLAG_1 | FLAG_2 | FLAG_4); $m->set ($key, '1', 10); $m->get($key); -check_flags($m->getLastUserFlags()[$key], array(FLAG_1, FLAG_2, FLAG_4)); +check_flags(get_flags($m, $key), array(FLAG_1, FLAG_2, FLAG_4)); // Even more flags $m->setOption(Memcached::OPT_USER_FLAGS, FLAG_1 | FLAG_2 | FLAG_4 | FLAG_32 | FLAG_64); $m->set ($key, '1', 10); $m->get($key); -check_flags($m->getLastUserFlags()[$key], array(FLAG_1, FLAG_2, FLAG_4, FLAG_32, FLAG_64)); +check_flags(get_flags($m, $key), array(FLAG_1, FLAG_2, FLAG_4, FLAG_32, FLAG_64)); // User flags with get multi $values = array( @@ -61,10 +65,10 @@ $values = array( $m->setOption(Memcached::OPT_USER_FLAGS, FLAG_2 | FLAG_4); $m->setMulti($values); $m->getMulti(array_keys($values)); -$flags = $m->getLastUserFlags(); +$flags = $m->getMulti(array_keys($values), Memcached::GET_EXTENDED); foreach (array_keys($values) as $key) { - check_flags($flags[$key], array(FLAG_2, FLAG_4)); + check_flags($flags[$key]['flags'], array(FLAG_2, FLAG_4)); } // User flags with compression on @@ -74,7 +78,7 @@ $m->setOption(Memcached::OPT_COMPRESSION_TYPE, Memcached::COMPRESSION_FASTLZ); $m->set ($key, '1', 10); $m->get($key); -check_flags($m->getLastUserFlags()[$key], array(FLAG_1, FLAG_2, FLAG_4)); +check_flags(get_flags($m, $key), array(FLAG_1, FLAG_2, FLAG_4)); // Too large flags @@ -83,8 +87,12 @@ $m->setOption(Memcached::OPT_USER_FLAGS, FLAG_TOO_LARGE); echo "DONE TEST\n"; ?> --EXPECTF-- -array(1) { - ["udf_test_%s"]=> +array(3) { + ["value"]=> + string(1) "1" + ["cas"]=> + int(%d) + ["flags"]=> int(0) } Flags OK From c15d792ec3b646df6fa06c39328441f107120e9e Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 30 Jan 2016 11:41:57 +0000 Subject: [PATCH 059/345] Clean up session code, start on the whole i_obj/m_obj confusion --- php_memcached.c | 255 ++++++++++++++++------------------ php_memcached_session.c | 49 ++++--- tests/callback_exception.phpt | 3 +- tests/cas.phpt | 5 +- 4 files changed, 155 insertions(+), 157 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 23e9bde3..e91a5600 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -122,67 +122,8 @@ php_memc_t* i_obj = NULL; \ struct memc_obj* m_obj = NULL; -#ifndef DVAL_TO_LVAL -#ifdef _WIN64 -# define DVAL_TO_LVAL(d, l) \ - if ((d) > LONG_MAX) { \ - (l) = (long)(unsigned long)(__int64) (d); \ - } else { \ - (l) = (long) (d); \ - } -#else -# define DVAL_TO_LVAL(d, l) \ - if ((d) > LONG_MAX) { \ - (l) = (unsigned long) (d); \ - } else { \ - (l) = (long) (d); \ - } -#endif -#endif - #define RETURN_FROM_GET RETURN_FALSE -typedef memcached_return (*memc_store_fn)( - memcached_st *, - const char *key, size_t key_len, - const char *payload, size_t payload_len, - time_t expiration, uint32_t flags); - -typedef memcached_return (*memc_store_by_key_fn)( - memcached_st *, - const char *server_key, size_t server_key_len, - const char *key, size_t key_len, - const char *payload, size_t payload_len, - time_t expiration, uint32_t flags); - -static memc_store_fn php_memc_store_funcs[] = { - &memcached_set, - &memcached_add, - &memcached_replace, - &memcached_prepend, - &memcached_append -}; - -void s_call_store_func(int op, memcached_st *memc, const char *key, size_t key_len, const char *payload, size_t payload_len, time_t expiration, uint32_t flags) -{ - (*php_memc_store_funcs[op])(memc, key, key_len,payload, payload_len, expiration, flags); -} - - -static memc_store_by_key_fn php_memc_store_by_keys_funcs[] = { - &memcached_set_by_key, - &memcached_add_by_key, - &memcached_replace_by_key, - &memcached_prepend_by_key, - &memcached_append_by_key -}; - -void s_call_store_by_key_func(int op, memcached_st *memc, const char *server_key, size_t server_key_len, const char *key, size_t key_len, const char *payload, size_t payload_len, time_t expiration, uint32_t flags) -{ - (*php_memc_store_by_keys_funcs[op])(memc, server_key, server_key_len, key, key_len,payload, payload_len, expiration, flags); -} - - /**************************************** Structures and definitions ****************************************/ @@ -314,10 +255,10 @@ static PHP_INI_MH(OnUpdateSerializer) } #define MEMC_INI_ENTRY(key, default_value, update_fn, gkey) \ - STD_PHP_INI_ENTRY("memcached.##key", default_value, PHP_INI_ALL, update_fn, memc_ini.gkey, zend_php_memcached_globals, php_memcached_globals) + STD_PHP_INI_ENTRY("memcached."key, default_value, PHP_INI_ALL, update_fn, memc_ini.gkey, zend_php_memcached_globals, php_memcached_globals) #define MEMC_SESSION_INI_ENTRY(key, default_value, update_fn, gkey) \ - STD_PHP_INI_ENTRY("memcached.session.##key", default_value, PHP_INI_ALL, update_fn, session_ini.gkey, zend_php_memcached_globals, php_memcached_globals) + STD_PHP_INI_ENTRY("memcached.session."key, default_value, PHP_INI_ALL, update_fn, session_ini.gkey, zend_php_memcached_globals, php_memcached_globals) /* {{{ INI entries */ @@ -349,7 +290,6 @@ PHP_INI_BEGIN() MEMC_INI_ENTRY("serializer", SERIALIZER_DEFAULT_NAME, OnUpdateSerializer, serializer_name) MEMC_INI_ENTRY("use_sasl", "0", OnUpdateBool, sasl_enabled) MEMC_INI_ENTRY("store_retry_count", "2", OnUpdateLong, store_retry_count) - PHP_INI_END() /* }}} */ @@ -472,7 +412,6 @@ static PHP_METHOD(Memcached, __construct) struct memc_obj *m_obj = NULL; zend_string *persistent_id = NULL; zend_string *conn_str = NULL; - zend_bool is_persistent = 0; zend_string *plist_key = NULL; zend_fcall_info fci = {0}; zend_fcall_info_cache fci_cache; @@ -483,102 +422,103 @@ static PHP_METHOD(Memcached, __construct) i_obj = Z_MEMC_OBJ_P(object); i_obj->is_pristine = 0; + i_obj->is_persistent = 0; if (persistent_id && persistent_id->len) { zend_resource *le; - is_persistent = 1; plist_key = zend_string_alloc(sizeof("memcached:id=") + persistent_id->len - 1, 0); snprintf(plist_key->val, plist_key->len + 1, "memcached:id=%s", persistent_id->val); + if ((le = zend_hash_find_ptr(&EG(persistent_list), plist_key)) != NULL) { if (le->type == php_memc_list_entry()) { m_obj = (struct memc_obj *) le->ptr; + + i_obj->obj = m_obj; + i_obj->is_persistent = 1; + zend_string_release (plist_key); + return; } } - i_obj->obj = m_obj; + i_obj->is_persistent = 1; } - i_obj->is_persistent = is_persistent; + m_obj = pecalloc(1, sizeof(*m_obj), i_obj->is_persistent); + if (m_obj == NULL) { + if (plist_key) { + zend_string_release(plist_key); + } + php_error_docref(NULL, E_ERROR, "out of memory: cannot allocate handle"); + /* not reached */ + } - if (!m_obj) { - m_obj = pecalloc(1, sizeof(*m_obj), is_persistent); - if (m_obj == NULL) { + if (conn_str) { + m_obj->memc = php_memc_create_str(conn_str->val, conn_str->len); + if (!m_obj->memc) { + char error_buffer[1024]; if (plist_key) { zend_string_release(plist_key); } - php_error_docref(NULL, E_ERROR, "out of memory: cannot allocate handle"); - /* not reached */ - } - - if (conn_str) { - m_obj->memc = php_memc_create_str(conn_str->val, conn_str->len); - if (!m_obj->memc) { - char error_buffer[1024]; - if (plist_key) { - zend_string_release(plist_key); - } #ifdef HAVE_LIBMEMCACHED_CHECK_CONFIGURATION - if (libmemcached_check_configuration(conn_str->val, conn_str->len, error_buffer, sizeof(error_buffer)) != MEMCACHED_SUCCESS) { - php_error_docref(NULL, E_ERROR, "configuration error %s", error_buffer); - } else { - php_error_docref(NULL, E_ERROR, "could not allocate libmemcached structure"); - } -#else + if (libmemcached_check_configuration(conn_str->val, conn_str->len, error_buffer, sizeof(error_buffer)) != MEMCACHED_SUCCESS) { + php_error_docref(NULL, E_ERROR, "configuration error %s", error_buffer); + } else { php_error_docref(NULL, E_ERROR, "could not allocate libmemcached structure"); -#endif - /* not reached */ } - } else { - m_obj->memc = memcached_create(NULL); - if (m_obj->memc == NULL) { - if (plist_key) { - zend_string_release(plist_key); - } - php_error_docref(NULL, E_ERROR, "could not allocate libmemcached structure"); - /* not reached */ +#else + php_error_docref(NULL, E_ERROR, "could not allocate libmemcached structure"); +#endif + /* not reached */ + } + } else { + m_obj->memc = memcached_create(NULL); + if (m_obj->memc == NULL) { + if (plist_key) { + zend_string_release(plist_key); } + php_error_docref(NULL, E_ERROR, "could not allocate libmemcached structure"); + /* not reached */ } + } - m_obj->serializer = MEMC_G(serializer); - m_obj->compression_type = MEMC_G(compression_type_real); - m_obj->compression = 1; - m_obj->store_retry_count = MEMC_G(store_retry_count); - - m_obj->set_udf_flags = -1; - - i_obj->obj = m_obj; - i_obj->is_pristine = 1; + m_obj->serializer = MEMC_G(serializer); + m_obj->compression_type = MEMC_G(compression_type_real); + m_obj->compression = 1; + m_obj->store_retry_count = MEMC_G(store_retry_count); + m_obj->set_udf_flags = -1; - if (fci.size) { /* will be 0 when not available */ - if (!php_memcached_on_new_callback(object, &fci, &fci_cache, persistent_id) || EG(exception)) { - /* error calling or exception thrown from callback */ - if (plist_key) { - zend_string_release(plist_key); - } + i_obj->obj = m_obj; + i_obj->is_pristine = 1; - i_obj->obj = NULL; - if (is_persistent) { - php_memc_destroy(m_obj, is_persistent); - } + if (fci.size) { /* will be 0 when not available */ + if (!php_memcached_on_new_callback(object, &fci, &fci_cache, persistent_id) || EG(exception)) { + /* error calling or exception thrown from callback */ + if (plist_key) { + zend_string_release(plist_key); + } - return; + i_obj->obj = NULL; + if (i_obj->is_persistent) { + php_memc_destroy(m_obj, i_obj->is_persistent); } + + return; } + } - if (is_persistent) { - zend_resource le; + if (i_obj->is_persistent) { + zend_resource le; - le.type = php_memc_list_entry(); - le.ptr = m_obj; - GC_REFCOUNT(&le) = 1; - /* plist_key is not a persistent allocated key, thus we use str_update here */ - if (zend_hash_str_update_mem(&EG(persistent_list), plist_key->val, plist_key->len, &le, sizeof(le)) == NULL) { - if (plist_key) { - zend_string_release(plist_key); - } - php_error_docref(NULL, E_ERROR, "could not register persistent entry"); - /* not reached */ + le.type = php_memc_list_entry(); + le.ptr = m_obj; + GC_REFCOUNT(&le) = 1; + /* plist_key is not a persistent allocated key, thus we use str_update here */ + if (zend_hash_str_update_mem(&EG(persistent_list), plist_key->val, plist_key->len, &le, sizeof(le)) == NULL) { + if (plist_key) { + zend_string_release(plist_key); } + php_error_docref(NULL, E_ERROR, "could not register persistent entry"); + /* not reached */ } } @@ -593,7 +533,12 @@ void s_uint64_to_zval (zval *target, uint64_t value) { if (value >= LONG_MAX) { char *buffer; +#ifdef PRIu64 spprintf (&buffer, 0, "%" PRIu64, value); +#else + /* Best effort */ + spprintf (&buffer, 0, "%llu", value); +#endif ZVAL_STRING (target, buffer); efree(buffer); } @@ -602,6 +547,41 @@ void s_uint64_to_zval (zval *target, uint64_t value) } } +static +uint64_t s_zval_to_uint64 (zval *cas) +{ + switch (Z_TYPE_P (cas)) { + case IS_LONG: + return (uint64_t) zval_get_long (cas); + break; + + case IS_DOUBLE: + if (Z_DVAL_P (cas) < 0.0) + return 0; + + return (uint64_t) zval_get_double (cas); + break; + + case IS_STRING: + { + uint64_t val; + char *end; + + errno = 0; + val = (uint64_t) strtoull (Z_STRVAL_P (cas), &end, 0); + + if (*end || (errno == ERANGE && val == UINT64_MAX) || (errno != 0 && val == 0)) { + php_error_docref(NULL, E_ERROR, "Failed to unmarshall cas token"); + return 0; + } + return val; + } + break; + } + return 0; +} + + typedef struct { size_t num_valid_keys; @@ -674,10 +654,7 @@ memcached_return s_memcached_get_multi(memcached_st *memc, HashTable *hash_keys, { php_memcached_keys keys = { 0 }; zval values; - memcached_return rc, status = MEMCACHED_SUCCESS; - - size_t num_keys; uint64_t orig_cas_flag; memcached_result_st result; @@ -860,7 +837,6 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke { zval *keys = NULL; zend_string *server_key = NULL; - zend_bool extended_results = 0; memcached_return rc; zend_long flags = 0; MEMC_METHOD_INIT_VARS; @@ -1559,7 +1535,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool /* {{{ -- php_memc_cas_impl */ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { - double cas_d; + zval *zv_cas; uint64_t cas; zend_string *key; zend_string *server_key = NULL; @@ -1571,12 +1547,12 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "dSSz|ll", &cas_d, &server_key, &key, + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zSSz|ll", &zv_cas, &server_key, &key, &value, &expiration) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "dSz|ll", &cas_d, &key, &value, + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zSz|ll", &zv_cas, &key, &value, &expiration) == FAILURE) { return; } @@ -1590,7 +1566,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) RETURN_FALSE; } - DVAL_TO_LVAL(cas_d, cas); + cas = s_zval_to_uint64(zv_cas); if (m_obj->compression) { MEMC_VAL_SET_FLAG(flags, MEMC_VAL_COMPRESSED); @@ -1615,6 +1591,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) } else { status = memcached_cas(m_obj->memc, key->val, key->len, payload->val, payload->len, expiration, flags, cas); } + zend_string_release(payload); if (php_memc_handle_error(i_obj, status) < 0) { RETURN_FALSE; @@ -4122,7 +4099,8 @@ PHP_GINIT_FUNCTION(php_memcached) } zend_module_entry memcached_module_entry = { - STANDARD_MODULE_HEADER, + STANDARD_MODULE_HEADER_EX, NULL, + memcached_deps, "memcached", NULL, PHP_MINIT(memcached), @@ -4139,6 +4117,7 @@ zend_module_entry memcached_module_entry = { }; /* }}} */ + /* {{{ php_memc_register_constants */ static void php_memc_register_constants(INIT_FUNC_ARGS) { @@ -4409,12 +4388,12 @@ PHP_MINIT_FUNCTION(memcached) */ php_memc_register_constants(INIT_FUNC_ARGS_PASSTHRU); + REGISTER_INI_ENTRIES(); #ifdef HAVE_MEMCACHED_SESSION php_memc_session_minit(module_number); #endif - REGISTER_INI_ENTRIES(); #if HAVE_MEMCACHED_SASL if (MEMC_G(sasl_enabled)) { if (sasl_client_init(NULL) != SASL_OK) { diff --git a/php_memcached_session.c b/php_memcached_session.c index 8c6454a1..1a398ab7 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -95,8 +95,6 @@ int php_memc_session_minit(int module_number) static time_t s_lock_expiration() { - zend_long max_execution_time; - if (MEMC_SESS_INI(lock_expiration) > 0) { return time(NULL) + MEMC_SESS_INI(lock_expiration); } @@ -109,9 +107,19 @@ time_t s_lock_expiration() return 0; } +static +time_t s_session_expiration(zend_long maxlifetime) +{ + if (maxlifetime > 0) { + return time(NULL) + maxlifetime; + } + return 0; +} + static zend_bool s_lock_session(memcached_st *memc, zend_string *sid) { + memcached_return rc; char *lock_key; size_t lock_key_len; time_t expiration; @@ -125,8 +133,7 @@ zend_bool s_lock_session(memcached_st *memc, zend_string *sid) retries = MEMC_SESS_INI(lock_retries); do { - memcached_return rc = - memcached_add(memc, lock_key, lock_key_len, "1", sizeof ("1") - 1, expiration, 0); + rc = memcached_add(memc, lock_key, lock_key_len, "1", sizeof ("1") - 1, expiration, 0); switch (rc) { @@ -137,8 +144,10 @@ zend_bool s_lock_session(memcached_st *memc, zend_string *sid) case MEMCACHED_NOTSTORED: case MEMCACHED_DATA_EXISTS: - usleep(wait_time * 1000); - wait_time = MIN(MEMC_SESS_INI(lock_wait_max), wait_time * 2); + if (retries > 0) { + usleep(wait_time * 1000); + wait_time = MIN(MEMC_SESS_INI(lock_wait_max), wait_time * 2); + } break; default: @@ -164,13 +173,13 @@ void s_unlock_session(memcached_st *memc) } static -zend_bool s_configure_from_ini_values(memcached_st *memc) +zend_bool s_configure_from_ini_values(memcached_st *memc, zend_bool silent) { memcached_return rc; #define check_set_behavior(behavior, value) \ if ((rc = memcached_behavior_set(memc, (behavior), (value))) != MEMCACHED_SUCCESS) { \ - php_error_docref(NULL, E_WARNING, "failed to initialise session memcached configuration: %s", memcached_strerror(memc, rc)); \ + if (!silent) { php_error_docref(NULL, E_WARNING, "failed to initialise session memcached configuration: %s", memcached_strerror(memc, rc)); } \ return 0; \ } @@ -280,7 +289,7 @@ memcached_st *s_init_mod_data (const memcached_server_list_st servers, zend_bool memcached_set_memory_allocators(memc, s_pemalloc_fn, s_pefree_fn, s_perealloc_fn, s_pecalloc_fn, NULL); - user_data = pecalloc(1, sizeof(php_memcached_user_data), is_persistent); + user_data = pecalloc(1, sizeof(php_memcached_user_data), is_persistent); user_data->is_persistent = is_persistent; user_data->has_sasl_data = 0; user_data->lock_key = NULL; @@ -316,7 +325,7 @@ PS_OPEN_FUNC(memcached) if (le_p->type == s_memc_sess_list_entry()) { memc = (memcached_st *) le_p->ptr; - if (!s_configure_from_ini_values(memc)) { + if (!s_configure_from_ini_values(memc, 1)) { // Remove existing plist entry zend_hash_str_del(&EG(persistent_list), plist_key, plist_key_len); memc = NULL; @@ -333,6 +342,14 @@ PS_OPEN_FUNC(memcached) memc = s_init_mod_data(servers, MEMC_SESS_INI(persistent_enabled)); memcached_server_list_free(servers); + if (!s_configure_from_ini_values(memc, 0)) { + if (plist_key) { + efree(plist_key); + } + PS_SET_MOD_DATA(NULL); + return FAILURE; + } + if (plist_key) { zend_resource le; @@ -358,7 +375,7 @@ PS_CLOSE_FUNC(memcached) php_memcached_user_data *user_data; if (!memc) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); + php_error_docref(NULL, E_WARNING, "Session is not allocated, check session.save_path value"); return FAILURE; } @@ -385,7 +402,7 @@ PS_READ_FUNC(memcached) memcached_st *memc = PS_GET_MOD_DATA(); if (!memc) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); + php_error_docref(NULL, E_WARNING, "Session is not allocated, check session.save_path value"); return FAILURE; } @@ -414,8 +431,7 @@ PS_WRITE_FUNC(memcached) { zend_long retries = 1; memcached_st *memc = PS_GET_MOD_DATA(); - size_t key_length; - time_t expiration; + time_t expiration = s_session_expiration(maxlifetime); if (!memc) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not allocated, check session.save_path value"); @@ -432,8 +448,6 @@ PS_WRITE_FUNC(memcached) retries = 1 + replicas * (failure_limit + 1); } - expiration = time(NULL) + maxlifetime; - do { if (memcached_set(memc, key->val, key->len, val->val, val->len, expiration, 0) == MEMCACHED_SUCCESS) { return SUCCESS; @@ -504,7 +518,7 @@ PS_VALIDATE_SID_FUNC(memcached) PS_UPDATE_TIMESTAMP_FUNC(memcached) { memcached_st *memc = PS_GET_MOD_DATA(); - time_t expiration = time(NULL) + maxlifetime; + time_t expiration = s_session_expiration(maxlifetime); if (memcached_touch(memc, key->val, key->len, expiration) == MEMCACHED_FAILURE) { return FAILURE; @@ -512,3 +526,4 @@ PS_UPDATE_TIMESTAMP_FUNC(memcached) return SUCCESS; } /* }}} */ + diff --git a/tests/callback_exception.phpt b/tests/callback_exception.phpt index 8f71d5f8..fa149077 100644 --- a/tests/callback_exception.phpt +++ b/tests/callback_exception.phpt @@ -37,7 +37,8 @@ try { } try { - + $m = new Memcached(null, 'throw_something'); + echo "fail\n"; } catch (Exception $e) { echo "fail\n"; } diff --git a/tests/cas.phpt b/tests/cas.phpt index c1c1752f..60090c97 100644 --- a/tests/cas.phpt +++ b/tests/cas.phpt @@ -8,12 +8,15 @@ include dirname (__FILE__) . '/config.inc'; $m = memc_get_instance (); $m->delete('cas_test'); -$cas_token = 0; $m->set('cas_test', 'hello'); $cas_token = $m->get('cas_test', null, Memcached::GET_EXTENDED)['cas']; $v = $m->cas($cas_token, 'cas_test', 0); +if ($v != true) { + echo "CAS failed"; +} + echo "OK\n"; ?> --EXPECT-- From bdd0911a9bdde9c3f1f4ab14e69055dbd5b643ad Mon Sep 17 00:00:00 2001 From: Mikko Date: Sun, 31 Jan 2016 16:07:48 +0000 Subject: [PATCH 060/345] Update to a simpler object structure, make session config match old setting names, key validation removed etc --- php_memcached.c | 1026 +++++++++++++----------- php_memcached_private.h | 3 + php_memcached_session.c | 17 + tests/bug_16084.phpt | 18 +- tests/callback_exception.phpt | 3 +- tests/getserverlist.phpt | 21 +- tests/invoke_callback.phpt | 5 +- tests/keys.phpt | 1 + tests/session_badconf_emptyprefix.phpt | 17 +- tests/session_badconf_prefix.phpt | 21 +- tests/session_badconf_servers.phpt | 4 - tests/session_basic.phpt | 6 +- tests/session_basic2.phpt | 6 +- tests/session_basic3.phpt | 12 +- 14 files changed, 631 insertions(+), 529 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index e91a5600..1dbe0bab 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -55,6 +55,8 @@ #define MEMC_G(v) (php_memcached_globals.memc_ini.v) #endif +#include + /**************************************** Custom options @@ -117,10 +119,7 @@ /**************************************** Helper macros ****************************************/ -#define MEMC_METHOD_INIT_VARS \ - zval* object = getThis(); \ - php_memc_t* i_obj = NULL; \ - struct memc_obj* m_obj = NULL; + #define RETURN_FROM_GET RETURN_FALSE @@ -133,37 +132,48 @@ enum memcached_compression_type { }; typedef struct { - struct memc_obj { - memcached_st *memc; - zend_bool compression; - enum memcached_serializer serializer; - enum memcached_compression_type compression_type; + + zend_bool is_persistent; + zend_bool compression; + enum memcached_serializer serializer; + enum memcached_compression_type compression_type; + + zend_long store_retry_count; + zend_long set_udf_flags; + #if HAVE_MEMCACHED_SASL - zend_bool has_sasl_data; + zend_bool has_sasl_data; #endif - long store_retry_count; - zend_long set_udf_flags; - } *obj; - zend_bool is_persistent; +} php_memc_user_data_t; + + +typedef struct { + memcached_st *memc; zend_bool is_pristine; int rescode; int memc_errno; zend_object zo; -} php_memc_t; +} php_memc_object_t; -static inline php_memc_t *php_memc_fetch_object(zend_object *obj) { - return (php_memc_t *)((char *)obj - XtOffsetOf(php_memc_t, zo)); +static inline php_memc_object_t *php_memc_fetch_object(zend_object *obj) { + return (php_memc_object_t *)((char *)obj - XtOffsetOf(php_memc_object_t, zo)); } #define Z_MEMC_OBJ_P(zv) php_memc_fetch_object(Z_OBJ_P(zv)); -#define MEMC_METHOD_FETCH_OBJECT \ - i_obj = Z_MEMC_OBJ_P(object); \ - m_obj = i_obj->obj; \ - if (!m_obj) { \ - php_error_docref(NULL, E_WARNING, "Memcached constructor was not called"); \ - return; \ - } +#define MEMC_METHOD_INIT_VARS \ + zval* object = getThis(); \ + php_memc_object_t* intern = NULL; \ + php_memc_user_data_t* memc_user_data = NULL; + +#define MEMC_METHOD_FETCH_OBJECT \ + intern = Z_MEMC_OBJ_P(object); \ + if (!intern->memc) { \ + php_error_docref(NULL, E_WARNING, "Memcached constructor was not called"); \ + return; \ + } \ + memc_user_data = (php_memc_user_data_t *) memcached_get_user_data(intern->memc); + #ifdef HAVE_MEMCACHED_PROTOCOL @@ -194,15 +204,6 @@ static zend_object_handlers memcached_server_object_handlers; static zend_class_entry *memcached_server_ce = NULL; #endif -struct callbackContext -{ - zval *array; - zval *entry; - memcached_stat_st *stats; /* for use with functions that need stats */ - void *return_value; - unsigned int i; /* for use with structures mapped against servers */ -}; - #if HAVE_SPL static zend_class_entry *spl_ce_RuntimeException = NULL; #endif @@ -254,22 +255,51 @@ static PHP_INI_MH(OnUpdateSerializer) return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } +static +PHP_INI_MH(OnUpdateDeprecatedLockValue) +{ + if (new_value->len > 0 && strcmp(new_value->val, "not set")) { + php_error_docref(NULL, E_DEPRECATED, "memcached.sess_lock_wait and memcached.sess_lock_max_wait are deprecated. Please update your configuration to use memcached.sess_lock_wait_min, memcached.sess_lock_wait_max and memcached.sess_lock_retries"); + } + return FAILURE; +} + +static +PHP_INI_MH(OnUpdateSessionPrefixString) +{ + if (new_value && new_value->len > 0) { + char *ptr = new_value->val; + + while (*ptr != '\0') { + if (isspace (*ptr++)) { + php_error_docref(NULL, E_WARNING, "memcached.sess_prefix cannot contain whitespace characters"); + return FAILURE; + } + } + if (new_value->len > MEMCACHED_MAX_KEY) { + php_error_docref(NULL, E_WARNING, "memcached.sess_prefix too long (max: %d)", MEMCACHED_MAX_KEY - 1); + return FAILURE; + } + } + return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); +} + #define MEMC_INI_ENTRY(key, default_value, update_fn, gkey) \ STD_PHP_INI_ENTRY("memcached."key, default_value, PHP_INI_ALL, update_fn, memc_ini.gkey, zend_php_memcached_globals, php_memcached_globals) #define MEMC_SESSION_INI_ENTRY(key, default_value, update_fn, gkey) \ - STD_PHP_INI_ENTRY("memcached.session."key, default_value, PHP_INI_ALL, update_fn, session_ini.gkey, zend_php_memcached_globals, php_memcached_globals) + STD_PHP_INI_ENTRY("memcached.sess_"key, default_value, PHP_INI_ALL, update_fn, session_ini.gkey, zend_php_memcached_globals, php_memcached_globals) /* {{{ INI entries */ PHP_INI_BEGIN() #ifdef HAVE_MEMCACHED_SESSION - MEMC_SESSION_INI_ENTRY("lock_enabled", "1", OnUpdateBool, lock_enabled) + MEMC_SESSION_INI_ENTRY("locking", "1", OnUpdateBool, lock_enabled) MEMC_SESSION_INI_ENTRY("lock_wait_min", "1000", OnUpdateLongGEZero, lock_wait_min) MEMC_SESSION_INI_ENTRY("lock_wait_max", "2000", OnUpdateLongGEZero, lock_wait_max) MEMC_SESSION_INI_ENTRY("lock_retries", "5", OnUpdateLongGEZero, lock_retries) - MEMC_SESSION_INI_ENTRY("lock_expiration", "0", OnUpdateLongGEZero, lock_expiration) + MEMC_SESSION_INI_ENTRY("lock_expire", "0", OnUpdateLongGEZero, lock_expiration) MEMC_SESSION_INI_ENTRY("compression", "1", OnUpdateBool, compression_enabled) MEMC_SESSION_INI_ENTRY("binary_protocol", "1", OnUpdateBool, binary_protocol_enabled) MEMC_SESSION_INI_ENTRY("consistent_hash", "1", OnUpdateBool, consistent_hash_enabled) @@ -280,8 +310,13 @@ PHP_INI_BEGIN() MEMC_SESSION_INI_ENTRY("connect_timeout", "0", OnUpdateLongGEZero, connect_timeout) MEMC_SESSION_INI_ENTRY("sasl_username", "", OnUpdateString, sasl_username) MEMC_SESSION_INI_ENTRY("sasl_password", "", OnUpdateString, sasl_password) - MEMC_SESSION_INI_ENTRY("prefix", "memc.sess.", OnUpdateString, prefix) + MEMC_SESSION_INI_ENTRY("prefix", "memc.sess.", OnUpdateSessionPrefixString, prefix) MEMC_SESSION_INI_ENTRY("persistent", "0", OnUpdateBool, persistent_enabled) + + /* Deprecated */ + STD_PHP_INI_ENTRY("memcached.sess_lock_wait", "not set", PHP_INI_ALL, OnUpdateDeprecatedLockValue, no_effect, zend_php_memcached_globals, php_memcached_globals) + STD_PHP_INI_ENTRY("memcached.sess_lock_max_wait", "not set", PHP_INI_ALL, OnUpdateDeprecatedLockValue, no_effect, zend_php_memcached_globals, php_memcached_globals) + #endif MEMC_INI_ENTRY("compression_type", "fastlz", OnUpdateCompressionType, compression_type) @@ -299,7 +334,7 @@ PHP_INI_END() /**************************************** Forward declarations ****************************************/ -static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status); +static int php_memc_handle_error(php_memc_object_t *intern, memcached_return status); static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); @@ -308,14 +343,27 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); -static memcached_return php_memc_do_cache_callback(zval *memc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string *key, zval *value); -static int php_memc_do_result_callback(zval *memc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, memcached_result_st *result); -static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context); -static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context); -static memcached_return php_memc_do_version_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context); -static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent); + +/* Invoke PHP functions */ +static + memcached_return s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string *key, zval *value); + +static + int s_invoke_result_callback(zval *zmemc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, memcached_result_st *result); + +/* Callback functions for different server list iterations */ +static + memcached_return s_server_cursor_list_servers_cb(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context); + +static + memcached_return s_server_cursor_version_cb(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context); + +/* Callback for dumping all keys to zval */ +static + void php_memc_destroy(memcached_st *memc, php_memc_user_data_t *memc_user_data); + static zend_bool s_memcached_result_to_zval(memcached_result_st *result, zval *return_value); @@ -364,7 +412,8 @@ char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_ return buffer; } -static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache, zend_string *persistent_id) +static +zend_bool s_invoke_new_instance_cb(zval *object, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache, zend_string *persistent_id) { zend_bool ret = 1; zval retval, id; @@ -388,17 +437,23 @@ static zend_bool php_memcached_on_new_callback(zval *object, zend_fcall_info *fc ret = 0; } - if (Z_TYPE(retval) != IS_UNDEF) + if (Z_TYPE(retval) != IS_UNDEF) { zval_ptr_dtor(&retval); + } - zend_fcall_info_args_clear(fci, 1); + if (EG(exception)) { + ret = 0; + } + zend_fcall_info_args_clear(fci, 1); return ret; } -static int le_memc; +static + int le_memc; -static int php_memc_list_entry(void) +static +int php_memc_list_entry(void) { return le_memc; } @@ -407,22 +462,23 @@ static int php_memc_list_entry(void) Creates a Memcached object, optionally using persistent memcache connection */ static PHP_METHOD(Memcached, __construct) { - zval *object = getThis(); - php_memc_t *i_obj; - struct memc_obj *m_obj = NULL; + php_memc_object_t *intern; + php_memc_user_data_t *memc_user_data; + zend_string *persistent_id = NULL; zend_string *conn_str = NULL; zend_string *plist_key = NULL; zend_fcall_info fci = {0}; zend_fcall_info_cache fci_cache; + zend_bool is_persistent = 0; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!f!S", &persistent_id, &fci, &fci_cache, &conn_str) == FAILURE) { return; } - i_obj = Z_MEMC_OBJ_P(object); - i_obj->is_pristine = 0; - i_obj->is_persistent = 0; + intern = Z_MEMC_OBJ_P(getThis()); + intern->is_pristine = 1; if (persistent_id && persistent_id->len) { zend_resource *le; @@ -432,18 +488,74 @@ static PHP_METHOD(Memcached, __construct) if ((le = zend_hash_find_ptr(&EG(persistent_list), plist_key)) != NULL) { if (le->type == php_memc_list_entry()) { - m_obj = (struct memc_obj *) le->ptr; - - i_obj->obj = m_obj; - i_obj->is_persistent = 1; + intern->memc = le->ptr; + intern->is_pristine = 0; zend_string_release (plist_key); return; } } - i_obj->is_persistent = 1; + is_persistent = 1; + } + + if (conn_str && conn_str->len > 0) { + intern->memc = memcached (conn_str->val, conn_str->len); + } + else { + intern->memc = memcached (NULL, 0); + } + + if (!intern->memc) { + // TODO: handle allocation fail + } + + memc_user_data = pecalloc (1, sizeof(*memc_user_data), is_persistent); + memc_user_data->serializer = MEMC_G(serializer); + memc_user_data->compression_type = MEMC_G(compression_type_real); + memc_user_data->compression = 1; + memc_user_data->store_retry_count = MEMC_G(store_retry_count); + memc_user_data->set_udf_flags = -1; + memc_user_data->is_persistent = is_persistent; + + memcached_set_user_data(intern->memc, memc_user_data); + + if (fci.size) { + if (!s_invoke_new_instance_cb(getThis(), &fci, &fci_cache, persistent_id) || EG(exception)) { + /* error calling or exception thrown from callback */ + if (plist_key) { + zend_string_release(plist_key); + } + /* + Setting intern->memc null prevents object destruction from freeing the memcached_st + We free it manually here because it might be persistent and has not been + registered to persistent_list yet + */ + php_memc_destroy(intern->memc, memc_user_data); + intern->memc = NULL; + return; + } } - m_obj = pecalloc(1, sizeof(*m_obj), i_obj->is_persistent); + if (plist_key) { + zend_resource le; + + le.type = php_memc_list_entry(); + le.ptr = intern->memc; + + GC_REFCOUNT(&le) = 1; + + /* plist_key is not a persistent allocated key, thus we use str_update here */ + if (zend_hash_str_update_mem(&EG(persistent_list), plist_key->val, plist_key->len, &le, sizeof(le)) == NULL) { + zend_string_release(plist_key); + php_error_docref(NULL, E_ERROR, "could not register persistent entry"); + /* not reached */ + } + zend_string_release(plist_key); + } + + + +#if 0 + m_obj = pecalloc(1, sizeof(*m_obj), intern->is_persistent); if (m_obj == NULL) { if (plist_key) { zend_string_release(plist_key); @@ -453,8 +565,8 @@ static PHP_METHOD(Memcached, __construct) } if (conn_str) { - m_obj->memc = php_memc_create_str(conn_str->val, conn_str->len); - if (!m_obj->memc) { + intern->memc = php_memc_create_str(conn_str->val, conn_str->len); + if (!intern->memc) { char error_buffer[1024]; if (plist_key) { zend_string_release(plist_key); @@ -471,8 +583,8 @@ static PHP_METHOD(Memcached, __construct) /* not reached */ } } else { - m_obj->memc = memcached_create(NULL); - if (m_obj->memc == NULL) { + intern->memc = memcached_create(NULL); + if (intern->memc == NULL) { if (plist_key) { zend_string_release(plist_key); } @@ -481,14 +593,10 @@ static PHP_METHOD(Memcached, __construct) } } - m_obj->serializer = MEMC_G(serializer); - m_obj->compression_type = MEMC_G(compression_type_real); - m_obj->compression = 1; - m_obj->store_retry_count = MEMC_G(store_retry_count); - m_obj->set_udf_flags = -1; - i_obj->obj = m_obj; - i_obj->is_pristine = 1; + + intern->obj = m_obj; + intern->is_pristine = 1; if (fci.size) { /* will be 0 when not available */ if (!php_memcached_on_new_callback(object, &fci, &fci_cache, persistent_id) || EG(exception)) { @@ -497,16 +605,16 @@ static PHP_METHOD(Memcached, __construct) zend_string_release(plist_key); } - i_obj->obj = NULL; - if (i_obj->is_persistent) { - php_memc_destroy(m_obj, i_obj->is_persistent); + intern->obj = NULL; + if (intern->is_persistent) { + php_memc_destroy(m_obj, intern->is_persistent); } return; } } - if (i_obj->is_persistent) { + if (intern->is_persistent) { zend_resource le; le.type = php_memc_list_entry(); @@ -525,6 +633,7 @@ static PHP_METHOD(Memcached, __construct) if (plist_key) { zend_string_release(plist_key); } +#endif } /* }}} */ @@ -775,14 +884,14 @@ void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; + intern->rescode = MEMCACHED_SUCCESS; zend_hash_init (&keys, 1, 0, NULL, 0); ZVAL_STR(&tmp, key); zend_hash_add(&keys, key, &tmp); ZVAL_UNDEF(&values); - status = s_memcached_get_multi(m_obj->memc, &keys, server_key, get_flags, &values); + status = s_memcached_get_multi(intern->memc, &keys, server_key, get_flags, &values); zend_hash_destroy (&keys); if (EG(exception)) { @@ -808,10 +917,10 @@ void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) if (status == MEMCACHED_NOTFOUND && fci.size > 0) { // try to invoke cache cb - status = php_memc_do_cache_callback(getThis(), &fci, &fcc, key, return_value); + status = s_invoke_cache_callback(object, &fci, &fcc, key, return_value); } - if (php_memc_handle_error(i_obj, status) < 0) { + if (php_memc_handle_error(intern, status) < 0) { RETURN_FROM_GET; } } @@ -854,8 +963,8 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke MEMC_METHOD_FETCH_OBJECT; - rc = s_memcached_get_multi(m_obj->memc, Z_ARRVAL_P(keys), server_key, flags, return_value); - php_memc_handle_error(i_obj, rc); + rc = s_memcached_get_multi(intern->memc, Z_ARRVAL_P(keys), server_key, flags, return_value); + php_memc_handle_error(intern, rc); if (EG(exception)) { zval_dtor(return_value); @@ -926,7 +1035,7 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; + intern->rescode = MEMCACHED_SUCCESS; /* * Create the array of keys for libmemcached. If none of the keys were valid @@ -949,7 +1058,7 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ } ZEND_HASH_FOREACH_END(); if (i == 0) { - i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; + intern->rescode = MEMCACHED_BAD_KEY_PROVIDED; efree(mkeys); efree(mkeys_len); zval_dtor(return_value); @@ -960,9 +1069,9 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ * Enable CAS support, but only if it is currently disabled. */ if (with_cas) { - orig_cas_flag = memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS); + orig_cas_flag = memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS); if (orig_cas_flag == 0) { - memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); + memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); } } @@ -970,20 +1079,20 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ * Issue the request, but collect results only if the result callback is provided. */ if (by_key) { - status = memcached_mget_by_key(m_obj->memc, server_key->val, server_key->len, mkeys, mkeys_len, i); + status = memcached_mget_by_key(intern->memc, server_key->val, server_key->len, mkeys, mkeys_len, i); } else { - status = memcached_mget(m_obj->memc, mkeys, mkeys_len, i); + status = memcached_mget(intern->memc, mkeys, mkeys_len, i); } /* * Restore the CAS support flag, but only if we had to turn it on. */ if (with_cas && orig_cas_flag == 0) { - memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); + memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); } efree(mkeys); efree(mkeys_len); - if (php_memc_handle_error(i_obj, status) < 0) { + if (php_memc_handle_error(intern, status) < 0) { zval_dtor(return_value); RETURN_FALSE; } @@ -995,9 +1104,9 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ */ memcached_result_st result; - memcached_result_create(m_obj->memc, &result); - while ((memcached_fetch_result(m_obj->memc, &result, &status)) != NULL) { - if (php_memc_do_result_callback(getThis(), &fci, &fcc, &result) < 0) { + memcached_result_create(intern->memc, &result); + while ((memcached_fetch_result(intern->memc, &result, &status)) != NULL) { + if (s_invoke_result_callback(getThis(), &fci, &fcc, &result) < 0) { status = MEMCACHED_FAILURE; break; } @@ -1008,7 +1117,7 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ if (status == MEMCACHED_END) { status = MEMCACHED_SUCCESS; } - if (php_memc_handle_error(i_obj, status) < 0) { + if (php_memc_handle_error(intern, status) < 0) { RETURN_FALSE; } } @@ -1037,11 +1146,11 @@ PHP_METHOD(Memcached, fetch) } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; + intern->rescode = MEMCACHED_SUCCESS; - memcached_result_create(m_obj->memc, &result); - if ((memcached_fetch_result(m_obj->memc, &result, &status)) == NULL) { - php_memc_handle_error(i_obj, status); + memcached_result_create(intern->memc, &result); + if ((memcached_fetch_result(intern->memc, &result, &status)) == NULL) { + php_memc_handle_error(intern, status); memcached_result_free(&result); RETURN_FALSE; } @@ -1055,7 +1164,7 @@ PHP_METHOD(Memcached, fetch) if (!s_memcached_result_to_zval(&result, &value)) { memcached_result_free(&result); - i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; + intern->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FALSE; } @@ -1094,12 +1203,12 @@ PHP_METHOD(Memcached, fetchAll) } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; + intern->rescode = MEMCACHED_SUCCESS; array_init(return_value); - memcached_result_create(m_obj->memc, &result); + memcached_result_create(intern->memc, &result); - while ((memcached_fetch_result(m_obj->memc, &result, &status)) != NULL) { + while ((memcached_fetch_result(intern->memc, &result, &status)) != NULL) { payload = memcached_result_value(&result); payload_len = memcached_result_length(&result); flags = memcached_result_flags(&result); @@ -1110,7 +1219,7 @@ PHP_METHOD(Memcached, fetchAll) if (!s_memcached_result_to_zval(&result, &value)) { memcached_result_free(&result); zval_dtor(return_value); - i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; + intern->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FALSE; } @@ -1129,7 +1238,7 @@ PHP_METHOD(Memcached, fetchAll) memcached_result_free(&result); - if (status != MEMCACHED_END && php_memc_handle_error(i_obj, status) < 0) { + if (status != MEMCACHED_END && php_memc_handle_error(intern, status) < 0) { zval_dtor(return_value); RETURN_FALSE; } @@ -1188,8 +1297,8 @@ PHP_METHOD(Memcached, setMultiByKey) /* }}} */ #define PHP_MEMC_FAILOVER_RETRY \ - if (!by_key && retry < m_obj->store_retry_count) { \ - switch (i_obj->rescode) { \ + if (!by_key && retry < memc_user_data->store_retry_count) { \ + switch (intern->rescode) { \ case MEMCACHED_HOST_LOOKUP_FAILURE: \ case MEMCACHED_CONNECTION_FAILURE: \ case MEMCACHED_CONNECTION_BIND_FAILURE: \ @@ -1203,9 +1312,9 @@ PHP_METHOD(Memcached, setMultiByKey) case MEMCACHED_FAIL_UNIX_SOCKET: \ case MEMCACHED_SERVER_MARKED_DEAD: \ case MEMCACHED_SERVER_TEMPORARILY_DISABLED: \ - if (memcached_server_count(m_obj->memc) > 0) { \ + if (memcached_server_count(intern->memc) > 0) { \ retry++; \ - i_obj->rescode = 0; \ + intern->rescode = 0; \ goto retry; \ } \ break; \ @@ -1241,7 +1350,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; + intern->rescode = MEMCACHED_SUCCESS; ZEND_HASH_FOREACH_KEY_VAL (Z_ARRVAL_P(entries), num_key, skey, value) { if (skey) { @@ -1258,17 +1367,17 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke } flags = 0; - if (m_obj->compression) { + if (memc_user_data->compression) { MEMC_VAL_SET_FLAG(flags, MEMC_VAL_COMPRESSED); } - if (m_obj->set_udf_flags >= 0) { - MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) m_obj->set_udf_flags)); + if (memc_user_data->set_udf_flags >= 0) { + MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) memc_user_data->set_udf_flags)); } - payload = s_zval_to_payload(value, &flags, m_obj->serializer, m_obj->compression_type); + payload = s_zval_to_payload(value, &flags, memc_user_data->serializer, memc_user_data->compression_type); if (payload == NULL) { - i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; + intern->rescode = MEMC_RES_PAYLOAD_FAILURE; if (!skey) { zend_string_release(str_key); } @@ -1277,12 +1386,12 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke retry: if (!by_key) { - status = memcached_set(m_obj->memc, str_key->val, str_key->len, payload->val, payload->len, expiration, flags); + status = memcached_set(intern->memc, str_key->val, str_key->len, payload->val, payload->len, expiration, flags); } else { - status = memcached_set_by_key(m_obj->memc, server_key->val, server_key->len, str_key->val, str_key->len, payload->val, payload->len, expiration, flags); + status = memcached_set_by_key(intern->memc, server_key->val, server_key->len, str_key->val, str_key->len, payload->val, payload->len, expiration, flags); } - if (php_memc_handle_error(i_obj, status) < 0) { + if (php_memc_handle_error(intern, status) < 0) { PHP_MEMC_FAILOVER_RETRY if (!skey) { zend_string_release(str_key); @@ -1414,14 +1523,9 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; + intern->rescode = MEMCACHED_SUCCESS; - if (key->len == 0 || (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) && strchr(key->val, ' '))) { - i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; - RETURN_FALSE; - } - - if (m_obj->compression) { + if (memc_user_data->compression) { /* * When compression is enabled, we cannot do appends/prepends because that would * corrupt the compressed values. It is up to the user to fetch the value, @@ -1438,21 +1542,21 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool * php_memcached uses 16 bits internally to store type, compression and serialization info. * We use 16 upper bits to store user defined flags. */ - if (m_obj->set_udf_flags >= 0) { - MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) m_obj->set_udf_flags)); + if (memc_user_data->set_udf_flags >= 0) { + MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) memc_user_data->set_udf_flags)); } if (op == MEMC_OP_TOUCH) { #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000016 - if (memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { + if (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { php_error_docref(NULL, E_WARNING, "using touch command with binary protocol is not recommended with libmemcached versions below 1.0.16"); } #endif } else { - payload = s_zval_to_payload(value, &flags, m_obj->serializer, m_obj->compression_type); + payload = s_zval_to_payload(value, &flags, memc_user_data->serializer, memc_user_data->compression_type); if (payload == NULL) { - i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; + intern->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FALSE; } } @@ -1460,54 +1564,54 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool switch (op) { case MEMC_OP_SET: if (!server_key) { - status = memcached_set(m_obj->memc, key->val, key->len, payload->val, payload->len, expiration, flags); + status = memcached_set(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags); } else { - status = memcached_set_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + status = memcached_set_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, payload->val, payload->len, expiration, flags); } break; #ifdef HAVE_MEMCACHED_TOUCH case MEMC_OP_TOUCH: if (!server_key) { - status = memcached_touch(m_obj->memc, key->val, key->len, expiration); + status = memcached_touch(intern->memc, key->val, key->len, expiration); } else { - status = memcached_touch_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + status = memcached_touch_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, expiration); } break; #endif case MEMC_OP_ADD: if (!server_key) { - status = memcached_add(m_obj->memc, key->val, key->len, payload->val, payload->len, expiration, flags); + status = memcached_add(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags); } else { - status = memcached_add_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + status = memcached_add_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, payload->val, payload->len, expiration, flags); } break; case MEMC_OP_REPLACE: if (!server_key) { - status = memcached_replace(m_obj->memc, key->val, key->len, payload->val, payload->len, expiration, flags); + status = memcached_replace(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags); } else { - status = memcached_replace_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + status = memcached_replace_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, payload->val, payload->len, expiration, flags); } break; case MEMC_OP_APPEND: if (!server_key) { - status = memcached_append(m_obj->memc, key->val, key->len, payload->val, payload->len, expiration, flags); + status = memcached_append(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags); } else { - status = memcached_append_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + status = memcached_append_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, payload->val, payload->len, expiration, flags); } break; case MEMC_OP_PREPEND: if (!server_key) { - status = memcached_prepend(m_obj->memc, key->val, key->len, payload->val, payload->len, expiration, flags); + status = memcached_prepend(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags); } else { - status = memcached_prepend_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + status = memcached_prepend_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, payload->val, payload->len, expiration, flags); } break; @@ -1519,7 +1623,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool break; } - if (php_memc_handle_error(i_obj, status) < 0) { + if (php_memc_handle_error(intern, status) < 0) { PHP_MEMC_FAILOVER_RETRY RETVAL_FALSE; } else { @@ -1559,16 +1663,11 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; - - if (key->len == 0 || (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) && strchr(key->val, ' '))) { - i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; - RETURN_FALSE; - } + intern->rescode = MEMCACHED_SUCCESS; cas = s_zval_to_uint64(zv_cas); - if (m_obj->compression) { + if (memc_user_data->compression) { MEMC_VAL_SET_FLAG(flags, MEMC_VAL_COMPRESSED); } @@ -1576,24 +1675,24 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) * php_memcached uses 16 bits internally to store type, compression and serialization info. * We use 16 upper bits to store user defined flags. */ - if (m_obj->set_udf_flags >= 0) { - MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) m_obj->set_udf_flags)); + if (memc_user_data->set_udf_flags >= 0) { + MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) memc_user_data->set_udf_flags)); } - payload = s_zval_to_payload(value, &flags, m_obj->serializer, m_obj->compression_type); + payload = s_zval_to_payload(value, &flags, memc_user_data->serializer, memc_user_data->compression_type); if (payload == NULL) { - i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; + intern->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FALSE; } if (by_key) { - status = memcached_cas_by_key(m_obj->memc, server_key->val, server_key->len, key->val, key->len, payload->val, payload->len, expiration, flags, cas); + status = memcached_cas_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, payload->val, payload->len, expiration, flags, cas); } else { - status = memcached_cas(m_obj->memc, key->val, key->len, payload->val, payload->len, expiration, flags, cas); + status = memcached_cas(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags, cas); } zend_string_release(payload); - if (php_memc_handle_error(i_obj, status) < 0) { + if (php_memc_handle_error(intern, status) < 0) { RETURN_FALSE; } @@ -1669,21 +1768,16 @@ static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; - - if (key->len == 0 || (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) && strchr(key->val, ' '))) { - i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; - RETURN_FALSE; - } + intern->rescode = MEMCACHED_SUCCESS; if (by_key) { - status = memcached_delete_by_key(m_obj->memc, server_key->val, server_key->len, key->val, + status = memcached_delete_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, expiration); } else { - status = memcached_delete(m_obj->memc, key->val, key->len, expiration); + status = memcached_delete(intern->memc, key->val, key->len, expiration); } - if (php_memc_handle_error(i_obj, status) < 0) { + if (php_memc_handle_error(intern, status) < 0) { RETURN_FALSE; } @@ -1713,7 +1807,7 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; + intern->rescode = MEMCACHED_SUCCESS; array_init(return_value); ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P(entries), entry) { @@ -1726,13 +1820,13 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by } if (by_key) { - status = memcached_delete_by_key(m_obj->memc, server_key->val, server_key->len, Z_STRVAL_P(entry), Z_STRLEN_P(entry), expiration); + status = memcached_delete_by_key(intern->memc, server_key->val, server_key->len, Z_STRVAL_P(entry), Z_STRLEN_P(entry), expiration); } else { - status = memcached_delete_by_key(m_obj->memc, Z_STRVAL_P(entry), Z_STRLEN_P(entry), Z_STRVAL_P(entry), Z_STRLEN_P(entry), expiration); + status = memcached_delete_by_key(intern->memc, Z_STRVAL_P(entry), Z_STRLEN_P(entry), Z_STRVAL_P(entry), Z_STRLEN_P(entry), expiration); } - if (php_memc_handle_error(i_obj, status) < 0) { + if (php_memc_handle_error(intern, status) < 0) { add_assoc_long(return_value, Z_STRVAL_P(entry), status); } else { add_assoc_bool(return_value, Z_STRVAL_P(entry), 1); @@ -1767,12 +1861,7 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; - - if (key->len == 0 || (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) && strchr(key->val, ' '))) { - i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; - RETURN_FALSE; - } + intern->rescode = MEMCACHED_SUCCESS; if (offset < 0) { php_error_docref(NULL, E_WARNING, "offset has to be > 0"); @@ -1783,38 +1872,38 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, if ((!by_key && n_args < 3) || (by_key && n_args < 4)) { if (by_key) { if (incr) { - status = memcached_increment_by_key(m_obj->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, &value); + status = memcached_increment_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, &value); } else { - status = memcached_decrement_by_key(m_obj->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, &value); + status = memcached_decrement_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, &value); } } else { if (incr) { - status = memcached_increment(m_obj->memc, key->val, key->len, (unsigned int)offset, &value); + status = memcached_increment(intern->memc, key->val, key->len, (unsigned int)offset, &value); } else { - status = memcached_decrement(m_obj->memc, key->val, key->len, (unsigned int)offset, &value); + status = memcached_decrement(intern->memc, key->val, key->len, (unsigned int)offset, &value); } } } else { - if (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { + if (!memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { php_error_docref(NULL, E_WARNING, "Initial value is only supported with binary protocol"); RETURN_FALSE; } if (by_key) { if (incr) { - status = memcached_increment_with_initial_by_key(m_obj->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, initial, expiry, &value); + status = memcached_increment_with_initial_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, initial, expiry, &value); } else { - status = memcached_decrement_with_initial_by_key(m_obj->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, initial, expiry, &value); + status = memcached_decrement_with_initial_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, initial, expiry, &value); } } else { if (incr) { - status = memcached_increment_with_initial(m_obj->memc, key->val, key->len, (unsigned int)offset, initial, expiry, &value); + status = memcached_increment_with_initial(intern->memc, key->val, key->len, (unsigned int)offset, initial, expiry, &value); } else { - status = memcached_decrement_with_initial(m_obj->memc, key->val, key->len, (unsigned int)offset, initial, expiry, &value); + status = memcached_decrement_with_initial(intern->memc, key->val, key->len, (unsigned int)offset, initial, expiry, &value); } } } - if (php_memc_handle_error(i_obj, status) < 0) { + if (php_memc_handle_error(intern, status) < 0) { PHP_MEMC_FAILOVER_RETRY RETURN_FALSE; } @@ -1869,21 +1958,21 @@ PHP_METHOD(Memcached, addServer) } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; + intern->rescode = MEMCACHED_SUCCESS; #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000002 if (host->val[0] == '/') { /* unix domain socket */ - status = memcached_server_add_unix_socket_with_weight(m_obj->memc, host->val, weight); - } else if (memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_USE_UDP)) { - status = memcached_server_add_udp_with_weight(m_obj->memc, host->val, port, weight); + status = memcached_server_add_unix_socket_with_weight(intern->memc, host->val, weight); + } else if (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_USE_UDP)) { + status = memcached_server_add_udp_with_weight(intern->memc, host->val, port, weight); } else { - status = memcached_server_add_with_weight(m_obj->memc, host->val, port, weight); + status = memcached_server_add_with_weight(intern->memc, host->val, port, weight); } #else - status = memcached_server_add_with_weight(m_obj->memc, host->val, port, weight); + status = memcached_server_add_with_weight(intern->memc, host->val, port, weight); #endif - if (php_memc_handle_error(i_obj, status) < 0) { + if (php_memc_handle_error(intern, status) < 0) { RETURN_FALSE; } @@ -1910,7 +1999,7 @@ PHP_METHOD(Memcached, addServers) } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; + intern->rescode = MEMCACHED_SUCCESS; ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P(servers), entry) { if (Z_TYPE_P(entry) != IS_ARRAY) { @@ -1957,7 +2046,7 @@ PHP_METHOD(Memcached, addServers) list = memcached_server_list_append_with_weight(list, Z_STRVAL_P(z_host), Z_LVAL_P(z_port), weight, &status); - if (php_memc_handle_error(i_obj, status) == 0) { + if (php_memc_handle_error(intern, status) == 0) { i++; continue; } @@ -1967,9 +2056,9 @@ PHP_METHOD(Memcached, addServers) php_error_docref(NULL, E_WARNING, "could not add entry #%d to the server list", i+1); } ZEND_HASH_FOREACH_END(); - status = memcached_server_push(m_obj->memc, list); + status = memcached_server_push(intern->memc, list); memcached_server_list_free(list); - if (php_memc_handle_error(i_obj, status) < 0) { + if (php_memc_handle_error(intern, status) < 0) { RETURN_FALSE; } @@ -1981,7 +2070,6 @@ PHP_METHOD(Memcached, addServers) Returns the list of the memcache servers in use */ PHP_METHOD(Memcached, getServerList) { - struct callbackContext context = {0}; memcached_server_function callbacks[1]; MEMC_METHOD_INIT_VARS; @@ -1991,10 +2079,9 @@ PHP_METHOD(Memcached, getServerList) MEMC_METHOD_FETCH_OBJECT; - callbacks[0] = php_memc_do_serverlist_callback; + callbacks[0] = s_server_cursor_list_servers_cb; array_init(return_value); - context.return_value = return_value; - memcached_server_cursor(m_obj->memc, callbacks, &context, 1); + memcached_server_cursor(intern->memc, callbacks, return_value, 1); } /* }}} */ @@ -2012,16 +2099,11 @@ PHP_METHOD(Memcached, getServerByKey) } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; - - if (server_key->len == 0 || (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) && strchr(server_key->val, ' '))) { - i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; - RETURN_FALSE; - } + intern->rescode = MEMCACHED_SUCCESS; - server_instance = memcached_server_by_key(m_obj->memc, server_key->val, server_key->len, &error); + server_instance = memcached_server_by_key(intern->memc, server_key->val, server_key->len, &error); if (server_instance == NULL) { - php_memc_handle_error(i_obj, error); + php_memc_handle_error(intern, error); RETURN_FALSE; } @@ -2044,7 +2126,7 @@ PHP_METHOD(Memcached, resetServerList) MEMC_METHOD_FETCH_OBJECT; - memcached_servers_reset(m_obj->memc); + memcached_servers_reset(intern->memc); RETURN_TRUE; } /* }}} */ @@ -2061,7 +2143,7 @@ PHP_METHOD(Memcached, quit) MEMC_METHOD_FETCH_OBJECT; - memcached_quit(m_obj->memc); + memcached_quit(intern->memc); RETURN_TRUE; } /* }}} */ @@ -2077,7 +2159,7 @@ PHP_METHOD(Memcached, flushBuffers) } MEMC_METHOD_FETCH_OBJECT; - RETURN_BOOL(memcached_flush_buffers(m_obj->memc) == MEMCACHED_SUCCESS); + RETURN_BOOL(memcached_flush_buffers(intern->memc) == MEMCACHED_SUCCESS); } /* }}} */ @@ -2094,7 +2176,7 @@ PHP_METHOD(Memcached, getLastErrorMessage) MEMC_METHOD_FETCH_OBJECT; - RETURN_STRING(memcached_last_error_message(m_obj->memc)); + RETURN_STRING(memcached_last_error_message(intern->memc)); } /* }}} */ @@ -2110,7 +2192,7 @@ PHP_METHOD(Memcached, getLastErrorCode) MEMC_METHOD_FETCH_OBJECT; - RETURN_LONG(memcached_last_error(m_obj->memc)); + RETURN_LONG(memcached_last_error(intern->memc)); } /* }}} */ @@ -2126,7 +2208,7 @@ PHP_METHOD(Memcached, getLastErrorErrno) MEMC_METHOD_FETCH_OBJECT; - RETURN_LONG(memcached_last_error_errno(m_obj->memc)); + RETURN_LONG(memcached_last_error_errno(intern->memc)); } /* }}} */ #endif @@ -2145,7 +2227,7 @@ PHP_METHOD(Memcached, getLastDisconnectedServer) MEMC_METHOD_FETCH_OBJECT; - server_instance = memcached_server_get_last_disconnect(m_obj->memc); + server_instance = memcached_server_get_last_disconnect(intern->memc); if (server_instance == NULL) { RETURN_FALSE; } @@ -2156,14 +2238,81 @@ PHP_METHOD(Memcached, getLastDisconnectedServer) } /* }}} */ +#include + +static +zend_bool s_long_value(const char *str, zend_long *value) +{ + char *end = (char *) str; + + errno = 0; + *value = strtol(str, &end, 10); + + if (errno || str == end || *end != '\0') { + return 0; + } + return 1; +} + +static +zend_bool s_double_value(const char *str, double *value) +{ + char *end = (char *) str; + + errno = 0; + *value = strtod(str, &end); + + if (errno || str == end || *end != '\0') { + return 0; + } + return 1; +} + +static +memcached_return s_stat_execute_cb (php_memcached_instance_st instance, const char *key, size_t key_length, const char *value, size_t value_length, void *context) +{ + char *server_key; + size_t server_key_len; + zend_long long_val; + double d_val; + char *buffer; + + zval *return_value = (zval *) context; + zval *server_values; + + server_key_len = spprintf (&server_key, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance)); + server_values = zend_hash_str_find(Z_ARRVAL_P(return_value), server_key, server_key_len); + + if (!server_values) { + zval zv; + array_init(&zv); + + server_values = &zv; + add_assoc_zval_ex(return_value, server_key, server_key_len, server_values); + } + + spprintf (&buffer, 0, "%.*s", value_length, value); + + /* Check type */ + if (s_long_value (buffer, &long_val)) { + add_assoc_long(server_values, key, long_val); + } + else if (s_double_value (buffer, &d_val)) { + add_assoc_double(server_values, key, d_val); + } + else { + add_assoc_stringl_ex(server_values, key, key_length, value, value_length); + } + efree (buffer); + efree (server_key); + return MEMCACHED_SUCCESS; +} + /* {{{ Memcached::getStats() Returns statistics for the memcache servers */ PHP_METHOD(Memcached, getStats) { - memcached_stat_st *stats; memcached_return status; - struct callbackContext context = {0}; - memcached_server_function callbacks[1]; MEMC_METHOD_INIT_VARS; if (zend_parse_parameters_none() == FAILURE) { @@ -2172,29 +2321,12 @@ PHP_METHOD(Memcached, getStats) MEMC_METHOD_FETCH_OBJECT; - if (memcached_server_count(m_obj->memc) == 0) { - array_init(return_value); - return; - } - - stats = memcached_stat(m_obj->memc, NULL, &status); - php_memc_handle_error(i_obj, status); - if (stats == NULL) { - RETURN_FALSE; - } else if (status != MEMCACHED_SUCCESS && status != MEMCACHED_SOME_ERRORS) { - memcached_stat_free(m_obj->memc, stats); + array_init(return_value); + status = memcached_stat_execute(intern->memc, NULL, s_stat_execute_cb, return_value); + if (php_memc_handle_error(intern, status) < 0) { + zval_ptr_dtor(return_value); RETURN_FALSE; } - - array_init(return_value); - - callbacks[0] = php_memc_do_stats_callback; - context.i = 0; - context.stats = stats; - context.return_value = return_value; - memcached_server_cursor(m_obj->memc, callbacks, &context, 1); - - memcached_stat_free(m_obj->memc, stats); } /* }}} */ @@ -2202,8 +2334,7 @@ PHP_METHOD(Memcached, getStats) Returns the version of each memcached server in the pool */ PHP_METHOD(Memcached, getVersion) { - memcached_return status = MEMCACHED_SUCCESS; - struct callbackContext context = {0}; + memcached_return rc; memcached_server_function callbacks[1]; MEMC_METHOD_INIT_VARS; @@ -2213,28 +2344,29 @@ PHP_METHOD(Memcached, getVersion) MEMC_METHOD_FETCH_OBJECT; - array_init(return_value); - - status = memcached_version(m_obj->memc); - if (php_memc_handle_error(i_obj, status) < 0) { - zval_dtor(return_value); + rc = memcached_version(intern->memc); + if (php_memc_handle_error(intern, rc) < 0) { RETURN_FALSE; } - callbacks[0] = php_memc_do_version_callback; - context.return_value = return_value; + callbacks[0] = s_server_cursor_version_cb; - memcached_server_cursor(m_obj->memc, callbacks, &context, 1); + array_init(return_value); + rc = memcached_server_cursor(intern->memc, callbacks, return_value, 1); + if (php_memc_handle_error(intern, rc) < 0) { + zval_dtor(return_value); + RETURN_FALSE; + } } /* }}} */ /* {{{ Memcached::getAllKeys() Returns the keys stored on all the servers */ -static memcached_return php_memc_dump_func_callback(const memcached_st *ptr __attribute__((unused)), \ - const char *key, size_t key_length, void *context) +static +memcached_return s_dump_keys_cb(const memcached_st *ptr, const char *key, size_t key_length, void *in_context) { - zval *ctx = (zval*) context; - add_next_index_string(ctx, (char*) key); + zval *return_value = (zval*) in_context; + add_next_index_stringl(return_value, key, key_length); return MEMCACHED_SUCCESS; } @@ -2245,12 +2377,17 @@ PHP_METHOD(Memcached, getAllKeys) memcached_dump_func callback[1]; MEMC_METHOD_INIT_VARS; - callback[0] = php_memc_dump_func_callback; + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + callback[0] = s_dump_keys_cb; MEMC_METHOD_FETCH_OBJECT; array_init(return_value); - rc = memcached_dump(m_obj->memc, callback, return_value, 1); - if (php_memc_handle_error(i_obj, rc) < 0) { + + rc = memcached_dump(intern->memc, callback, return_value, 1); + if (php_memc_handle_error(intern, rc) < 0) { zval_dtor(return_value); RETURN_FALSE; } @@ -2270,10 +2407,10 @@ static PHP_METHOD(Memcached, flush) } MEMC_METHOD_FETCH_OBJECT; - i_obj->rescode = MEMCACHED_SUCCESS; + intern->rescode = MEMCACHED_SUCCESS; - status = memcached_flush(m_obj->memc, delay); - if (php_memc_handle_error(i_obj, status) < 0) { + status = memcached_flush(intern->memc, delay); + if (php_memc_handle_error(intern, status) < 0) { RETURN_FALSE; } @@ -2298,17 +2435,17 @@ static PHP_METHOD(Memcached, getOption) switch (option) { case MEMC_OPT_COMPRESSION_TYPE: - RETURN_LONG(m_obj->compression_type); + RETURN_LONG(memc_user_data->compression_type); case MEMC_OPT_COMPRESSION: - RETURN_BOOL(m_obj->compression); + RETURN_BOOL(memc_user_data->compression); case MEMC_OPT_PREFIX_KEY: { memcached_return retval; char *result; - result = memcached_callback_get(m_obj->memc, MEMCACHED_CALLBACK_PREFIX_KEY, &retval); + result = memcached_callback_get(intern->memc, MEMCACHED_CALLBACK_PREFIX_KEY, &retval); if (retval == MEMCACHED_SUCCESS && result) { #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX == 0x00049000 RETURN_STRINGL(result, strlen(result)); @@ -2321,20 +2458,20 @@ static PHP_METHOD(Memcached, getOption) } case MEMC_OPT_SERIALIZER: - RETURN_LONG((long)m_obj->serializer); + RETURN_LONG((long)memc_user_data->serializer); break; case MEMC_OPT_USER_FLAGS: - RETURN_LONG(m_obj->set_udf_flags); + RETURN_LONG(memc_user_data->set_udf_flags); break; case MEMC_OPT_STORE_RETRY_COUNT: - RETURN_LONG((long)m_obj->store_retry_count); + RETURN_LONG((long)memc_user_data->store_retry_count); break; case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE: case MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE: - if (memcached_server_count(m_obj->memc) == 0) { + if (memcached_server_count(intern->memc) == 0) { php_error_docref(NULL, E_WARNING, "no servers defined"); return; } @@ -2344,32 +2481,33 @@ static PHP_METHOD(Memcached, getOption) * Assume that it's a libmemcached behavior option. */ flag = (memcached_behavior) option; - result = memcached_behavior_get(m_obj->memc, flag); + result = memcached_behavior_get(intern->memc, flag); RETURN_LONG((long)result); } } /* }}} */ -static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value) +static +int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) { memcached_return rc = MEMCACHED_FAILURE; memcached_behavior flag; - struct memc_obj *m_obj = i_obj->obj; + php_memc_user_data_t *memc_user_data = memcached_get_user_data(intern->memc); switch (option) { case MEMC_OPT_COMPRESSION: convert_to_long(value); - m_obj->compression = Z_LVAL_P(value) ? 1 : 0; + memc_user_data->compression = Z_LVAL_P(value) ? 1 : 0; break; case MEMC_OPT_COMPRESSION_TYPE: convert_to_long(value); if (Z_LVAL_P(value) == COMPRESSION_TYPE_FASTLZ || Z_LVAL_P(value) == COMPRESSION_TYPE_ZLIB) { - m_obj->compression_type = Z_LVAL_P(value); + memc_user_data->compression_type = Z_LVAL_P(value); } else { /* invalid compression type */ - i_obj->rescode = MEMCACHED_INVALID_ARGUMENTS; + intern->rescode = MEMCACHED_INVALID_ARGUMENTS; return 0; } break; @@ -2395,8 +2533,8 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value) key = Z_STRVAL_P(value); #endif } - if (memcached_callback_set(m_obj->memc, MEMCACHED_CALLBACK_PREFIX_KEY, key) == MEMCACHED_BAD_KEY_PROVIDED) { - i_obj->rescode = MEMCACHED_INVALID_ARGUMENTS; + if (memcached_callback_set(intern->memc, MEMCACHED_CALLBACK_PREFIX_KEY, key) == MEMCACHED_BAD_KEY_PROVIDED) { + intern->rescode = MEMCACHED_INVALID_ARGUMENTS; php_error_docref(NULL, E_WARNING, "bad key provided"); return 0; } @@ -2407,10 +2545,10 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value) flag = (memcached_behavior) option; convert_to_long(value); - rc = memcached_behavior_set(m_obj->memc, flag, (uint64_t) Z_LVAL_P(value)); + rc = memcached_behavior_set(intern->memc, flag, (uint64_t) Z_LVAL_P(value)); - if (php_memc_handle_error(i_obj, rc) < 0) { - php_error_docref(NULL, E_WARNING, "error setting memcached option: %s", memcached_strerror (m_obj->memc, rc)); + if (php_memc_handle_error(intern, rc) < 0) { + php_error_docref(NULL, E_WARNING, "error setting memcached option: %s", memcached_strerror (intern->memc, rc)); return 0; } @@ -2421,12 +2559,12 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value) */ if (!Z_LVAL_P(value)) { #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX > 0x00037000 - (void)memcached_behavior_set_key_hash(m_obj->memc, MEMCACHED_HASH_DEFAULT); - (void)memcached_behavior_set_distribution_hash(m_obj->memc, MEMCACHED_HASH_DEFAULT); - (void)memcached_behavior_set_distribution(m_obj->memc, MEMCACHED_DISTRIBUTION_MODULA); + (void)memcached_behavior_set_key_hash(intern->memc, MEMCACHED_HASH_DEFAULT); + (void)memcached_behavior_set_distribution_hash(intern->memc, MEMCACHED_HASH_DEFAULT); + (void)memcached_behavior_set_distribution(intern->memc, MEMCACHED_DISTRIBUTION_MODULA); #else - m_obj->memc->hash = 0; - m_obj->memc->distribution = 0; + intern->memc->hash = 0; + intern->memc->distribution = 0; #endif } break; @@ -2437,28 +2575,28 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value) /* igbinary serializer */ #ifdef HAVE_MEMCACHED_IGBINARY if (Z_LVAL_P(value) == SERIALIZER_IGBINARY) { - m_obj->serializer = SERIALIZER_IGBINARY; + memc_user_data->serializer = SERIALIZER_IGBINARY; } else #endif #ifdef HAVE_JSON_API if (Z_LVAL_P(value) == SERIALIZER_JSON) { - m_obj->serializer = SERIALIZER_JSON; + memc_user_data->serializer = SERIALIZER_JSON; } else if (Z_LVAL_P(value) == SERIALIZER_JSON_ARRAY) { - m_obj->serializer = SERIALIZER_JSON_ARRAY; + memc_user_data->serializer = SERIALIZER_JSON_ARRAY; } else #endif /* msgpack serializer */ #ifdef HAVE_MEMCACHED_MSGPACK if (Z_LVAL_P(value) == SERIALIZER_MSGPACK) { - m_obj->serializer = SERIALIZER_MSGPACK; + memc_user_data->serializer = SERIALIZER_MSGPACK; } else #endif /* php serializer */ if (Z_LVAL_P(value) == SERIALIZER_PHP) { - m_obj->serializer = SERIALIZER_PHP; + memc_user_data->serializer = SERIALIZER_PHP; } else { - m_obj->serializer = SERIALIZER_PHP; - i_obj->rescode = MEMCACHED_INVALID_ARGUMENTS; + memc_user_data->serializer = SERIALIZER_PHP; + intern->rescode = MEMCACHED_INVALID_ARGUMENTS; php_error_docref(NULL, E_WARNING, "invalid serializer provided"); return 0; } @@ -2469,7 +2607,7 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value) convert_to_long(value); if (Z_LVAL_P(value) < 0) { - m_obj->set_udf_flags = -1; + memc_user_data->set_udf_flags = -1; return 1; } @@ -2477,12 +2615,12 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value) php_error_docref(NULL, E_WARNING, "MEMC_OPT_USER_FLAGS must be < %u", MEMC_VAL_USER_FLAGS_MAX); return 0; } - m_obj->set_udf_flags = Z_LVAL_P(value); + memc_user_data->set_udf_flags = Z_LVAL_P(value); break; case MEMC_OPT_STORE_RETRY_COUNT: convert_to_long(value); - m_obj->store_retry_count = Z_LVAL_P(value); + memc_user_data->store_retry_count = Z_LVAL_P(value); break; default: @@ -2497,15 +2635,15 @@ static int php_memc_set_option(php_memc_t *i_obj, long option, zval *value) convert_to_long(value); if (flag < MEMCACHED_BEHAVIOR_MAX) { - rc = memcached_behavior_set(m_obj->memc, flag, (uint64_t) Z_LVAL_P(value)); + rc = memcached_behavior_set(intern->memc, flag, (uint64_t) Z_LVAL_P(value)); } else { rc = MEMCACHED_INVALID_ARGUMENTS; } } - if (php_memc_handle_error(i_obj, rc) < 0) { - php_error_docref(NULL, E_WARNING, "error setting memcached option: %s", memcached_strerror (m_obj->memc, rc)); + if (php_memc_handle_error(intern, rc) < 0) { + php_error_docref(NULL, E_WARNING, "error setting memcached option: %s", memcached_strerror (intern->memc, rc)); return 0; } break; @@ -2601,9 +2739,9 @@ PHP_METHOD(Memcached, setBucket) } } - rc = memcached_bucket_set (m_obj->memc, server_map, forward_map, (uint32_t) server_map_len, replicas); + rc = memcached_bucket_set (intern->memc, server_map, forward_map, (uint32_t) server_map_len, replicas); - if (php_memc_handle_error(i_obj, rc) < 0) { + if (php_memc_handle_error(intern, rc) < 0) { retval = 0;; } @@ -2642,7 +2780,7 @@ static PHP_METHOD(Memcached, setOptions) zval copy; ZVAL_DUP(©, value); - if (!php_memc_set_option(i_obj, (long) key_index, ©)) { + if (!php_memc_set_option(intern, (long) key_index, ©)) { ok = 0; } @@ -2668,7 +2806,7 @@ static PHP_METHOD(Memcached, setOption) MEMC_METHOD_FETCH_OBJECT; - RETURN_BOOL(php_memc_set_option(i_obj, option, value)); + RETURN_BOOL(php_memc_set_option(intern, option, value)); } /* }}} */ @@ -2692,14 +2830,14 @@ static PHP_METHOD(Memcached, setSaslAuthData) MEMC_METHOD_FETCH_OBJECT; - if (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { + if (!memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { php_error_docref(NULL, E_WARNING, "SASL is only supported with binary protocol"); RETURN_FALSE; } - m_obj->has_sasl_data = 1; - status = memcached_set_sasl_auth_data(m_obj->memc, user->val, pass->val); + memc_user_data->has_sasl_data = 1; + status = memcached_set_sasl_auth_data(intern->memc, user->val, pass->val); - if (php_memc_handle_error(i_obj, status) < 0) { + if (php_memc_handle_error(intern, status) < 0) { RETURN_FALSE; } RETURN_TRUE; @@ -2719,7 +2857,7 @@ static PHP_METHOD(Memcached, getResultCode) MEMC_METHOD_FETCH_OBJECT; - RETURN_LONG(i_obj->rescode); + RETURN_LONG(intern->rescode); } /* }}} */ @@ -2735,7 +2873,7 @@ static PHP_METHOD(Memcached, getResultMessage) MEMC_METHOD_FETCH_OBJECT; - switch (i_obj->rescode) { + switch (intern->rescode) { case MEMC_RES_PAYLOAD_FAILURE: RETURN_STRING("PAYLOAD FAILURE"); break; @@ -2743,14 +2881,14 @@ static PHP_METHOD(Memcached, getResultMessage) case MEMCACHED_ERRNO: case MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE: case MEMCACHED_UNKNOWN_READ_FAILURE: - if (i_obj->memc_errno) { + if (intern->memc_errno) { zend_string *str = strpprintf(0, "%s: %s", - memcached_strerror(m_obj->memc, (memcached_return)i_obj->rescode), strerror(i_obj->memc_errno)); + memcached_strerror(intern->memc, (memcached_return)intern->rescode), strerror(intern->memc_errno)); RETURN_STR(str); } /* Fall through */ default: - RETURN_STRING(memcached_strerror(m_obj->memc, (memcached_return)i_obj->rescode)); + RETURN_STRING(memcached_strerror(intern->memc, (memcached_return)intern->rescode)); break; } @@ -2769,7 +2907,7 @@ static PHP_METHOD(Memcached, isPersistent) MEMC_METHOD_FETCH_OBJECT; - RETURN_BOOL(i_obj->is_persistent); + RETURN_BOOL(memc_user_data->is_persistent); } /* }}} */ @@ -2785,7 +2923,7 @@ static PHP_METHOD(Memcached, isPristine) MEMC_METHOD_FETCH_OBJECT; - RETURN_BOOL(i_obj->is_pristine); + RETURN_BOOL(intern->is_pristine); } /* }}} */ @@ -2794,40 +2932,47 @@ static PHP_METHOD(Memcached, isPristine) ****************************************/ /* {{{ constructor/destructor */ -static void php_memc_destroy(struct memc_obj *m_obj, zend_bool persistent) +static +void php_memc_destroy(memcached_st *memc, php_memc_user_data_t *memc_user_data) { #if HAVE_MEMCACHED_SASL - if (m_obj->has_sasl_data) { - memcached_destroy_sasl_auth_data(m_obj->memc); + if (memc_user_data->has_sasl_data) { + memcached_destroy_sasl_auth_data(memc); } #endif - if (m_obj->memc) { - memcached_free(m_obj->memc); - } - pefree(m_obj, persistent); + + memcached_set_memory_allocators(memc, NULL, NULL, NULL, NULL, NULL); + memcached_free(memc); + pefree(memc_user_data, memc_user_data->is_persistent); } -static void php_memc_free_storage(zend_object *obj) +static +void php_memc_object_free_storage(zend_object *object) { - php_memc_t *i_obj = php_memc_fetch_object(obj); + php_memc_object_t *intern = php_memc_fetch_object(object); - if (i_obj->obj && !i_obj->is_persistent) { - php_memc_destroy(i_obj->obj, 0); + if (intern->memc) { + php_memc_user_data_t *memc_user_data = memcached_get_user_data(intern->memc); + + if (!memc_user_data->is_persistent) { + php_memc_destroy(intern->memc, memc_user_data); + } } - zend_object_std_dtor(&i_obj->zo); - i_obj->obj = NULL; + + intern->memc = NULL; + zend_object_std_dtor(&intern->zo); } -static zend_object *php_memc_new(zend_class_entry *ce) +static +zend_object *php_memc_object_new(zend_class_entry *ce) { - php_memc_t *i_obj = ecalloc(1, sizeof(php_memc_t) + zend_object_properties_size(ce)); - - zend_object_std_init(&i_obj->zo, ce); - object_properties_init(&i_obj->zo, ce); - - i_obj->zo.handlers = &memcached_object_handlers; - - return &i_obj->zo; + php_memc_object_t *intern = ecalloc(1, sizeof(php_memc_object_t) + zend_object_properties_size(ce)); + + zend_object_std_init(&intern->zo, ce); + object_properties_init(&intern->zo, ce); + + intern->zo.handlers = &memcached_object_handlers; + return &intern->zo; } #ifdef HAVE_MEMCACHED_PROTOCOL @@ -2860,8 +3005,8 @@ zend_object_value php_memc_server_new(zend_class_entry *ce) ZEND_RSRC_DTOR_FUNC(php_memc_dtor) { if (res->ptr) { - struct memc_obj *m_obj = (struct memc_obj *)res->ptr; - php_memc_destroy(m_obj, 1); + memcached_st *memc = (memcached_st *) res->ptr; + php_memc_destroy(memc, memcached_get_user_data(memc)); res->ptr = NULL; } } @@ -2869,92 +3014,54 @@ ZEND_RSRC_DTOR_FUNC(php_memc_dtor) /* }}} */ /* {{{ internal API functions */ -static memcached_return php_memc_do_serverlist_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) +static +memcached_return s_server_cursor_list_servers_cb(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) { - struct callbackContext* context = (struct callbackContext*) in_context; zval array; + zval *return_value = (zval *) in_context; array_init(&array); - add_assoc_string(&array, "host", (char*) memcached_server_name(instance)); - add_assoc_long(&array, "port", memcached_server_port(instance)); + add_assoc_string(&array, "host", memcached_server_name(instance)); + add_assoc_long(&array, "port", memcached_server_port(instance)); + add_assoc_string(&array, "type", memcached_server_type(instance)); /* * API does not allow to get at this field. add_assoc_long(array, "weight", instance->weight); */ - add_next_index_zval(context->return_value, &array); + add_next_index_zval(return_value, &array); return MEMCACHED_SUCCESS; } -static memcached_return php_memc_do_stats_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) +static +memcached_return s_server_cursor_version_cb(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) { - char *hostport = NULL; - int hostport_len; - struct callbackContext* context = (struct callbackContext*) in_context; - zval entry; - hostport_len = spprintf(&hostport, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance)); - - array_init(&entry); - - add_assoc_long(&entry, "pid", context->stats[context->i].pid); - add_assoc_long(&entry, "uptime", context->stats[context->i].uptime); - add_assoc_long(&entry, "threads", context->stats[context->i].threads); - add_assoc_long(&entry, "time", context->stats[context->i].time); - add_assoc_long(&entry, "pointer_size", context->stats[context->i].pointer_size); - add_assoc_long(&entry, "rusage_user_seconds", context->stats[context->i].rusage_user_seconds); - add_assoc_long(&entry, "rusage_user_microseconds", context->stats[context->i].rusage_user_microseconds); - add_assoc_long(&entry, "rusage_system_seconds", context->stats[context->i].rusage_system_seconds); - add_assoc_long(&entry, "rusage_system_microseconds", context->stats[context->i].rusage_system_microseconds); - add_assoc_long(&entry, "curr_items", context->stats[context->i].curr_items); - add_assoc_long(&entry, "total_items", context->stats[context->i].total_items); - add_assoc_long(&entry, "limit_maxbytes", context->stats[context->i].limit_maxbytes); - add_assoc_long(&entry, "curr_connections", context->stats[context->i].curr_connections); - add_assoc_long(&entry, "total_connections", context->stats[context->i].total_connections); - add_assoc_long(&entry, "connection_structures", context->stats[context->i].connection_structures); - add_assoc_long(&entry, "bytes", context->stats[context->i].bytes); - add_assoc_long(&entry, "cmd_get", context->stats[context->i].cmd_get); - add_assoc_long(&entry, "cmd_set", context->stats[context->i].cmd_set); - add_assoc_long(&entry, "get_hits", context->stats[context->i].get_hits); - add_assoc_long(&entry, "get_misses", context->stats[context->i].get_misses); - add_assoc_long(&entry, "evictions", context->stats[context->i].evictions); - add_assoc_long(&entry, "bytes_read", context->stats[context->i].bytes_read); - add_assoc_long(&entry, "bytes_written", context->stats[context->i].bytes_written); - add_assoc_stringl(&entry, "version", context->stats[context->i].version, strlen(context->stats[context->i].version)); - - add_assoc_zval_ex(context->return_value, hostport, hostport_len, &entry); - efree(hostport); - - /* Increment the server count in our context structure. Failure to do so will cause only the stats for the last server to get displayed. */ - context->i++; - return MEMCACHED_SUCCESS; -} + char *address, *version; + size_t address_len, version_len; -static memcached_return php_memc_do_version_callback(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) -{ - char *hostport = NULL; - char version[16]; - int hostport_len, version_len; - struct callbackContext* context = (struct callbackContext*) in_context; + zval *return_value = (zval *) in_context; - hostport_len = spprintf(&hostport, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance) - 1); #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000009 - version_len = snprintf(version, sizeof(version), "%d.%d.%d", + version_len = spprintf(&version, sizeof(version), "%d.%d.%d", memcached_server_major_version(instance), memcached_server_minor_version(instance), memcached_server_micro_version(instance)); #else - version_len = snprintf(version, sizeof(version), "%d.%d.%d", + version_len = spprintf(&version, sizeof(version) - 1, "%d.%d.%d", instance->major_version, instance->minor_version, instance->micro_version); #endif - add_assoc_stringl_ex(context->return_value, hostport, hostport_len, version, version_len); - efree(hostport); + address_len = spprintf(&address, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance) - 1); + add_assoc_stringl_ex(return_value, address, address_len, version, version_len); + + efree(address); + efree(version); return MEMCACHED_SUCCESS; } -static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status) +static int php_memc_handle_error(php_memc_object_t *intern, memcached_return status) { int result = 0; @@ -2964,35 +3071,25 @@ static int php_memc_handle_error(php_memc_t *i_obj, memcached_return status) case MEMCACHED_DELETED: case MEMCACHED_STAT: result = 0; - i_obj->memc_errno = 0; + intern->memc_errno = 0; break; case MEMCACHED_END: case MEMCACHED_BUFFERED: - i_obj->rescode = status; - i_obj->memc_errno = 0; + intern->rescode = status; + intern->memc_errno = 0; result = 0; break; case MEMCACHED_SOME_ERRORS: - i_obj->rescode = status; -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000 - i_obj->memc_errno = memcached_last_error_errno(i_obj->obj->memc); -#else - i_obj->memc_errno = i_obj->obj->memc->cached_errno; /* Hnngghgh! */ - -#endif + intern->rescode = status; + intern->memc_errno = memcached_last_error_errno(intern->memc); result = 0; break; default: - i_obj->rescode = status; -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000 - i_obj->memc_errno = memcached_last_error_errno(i_obj->obj->memc); -#else - i_obj->memc_errno = i_obj->obj->memc->cached_errno; /* Hnngghgh! */ - -#endif + intern->rescode = status; + intern->memc_errno = memcached_last_error_errno(intern->memc); result = -1; break; } @@ -3443,94 +3540,87 @@ zend_class_entry *php_memc_get_exception_base(int root) #endif } -static memcached_return php_memc_do_cache_callback(zval *zmemc_obj, zend_fcall_info *fci, - zend_fcall_info_cache *fcc, zend_string *key, zval *value) +static +memcached_return s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string *key, zval *value) { - zend_string *payload = NULL; + memcached_return rc = MEMCACHED_SUCCESS; + int result; + zval params[4]; zval retval; - zval z_key; - zval z_val; - zval *expiration, z_expiration; + zval zv_key, ref_val; + zval ref_expiration, zv_expiration; - uint32_t flags = 0; - memcached_return rc; - php_memc_t* i_obj; - memcached_return status = MEMCACHED_SUCCESS; - int result; + /* Prepare params */ + ZVAL_STR(&zv_key, key); + + ZVAL_NULL(&ref_val); + ZVAL_NULL(&zv_expiration); - ZVAL_STR(&z_key, key); - ZVAL_NULL(&z_val); - ZVAL_NEW_REF(&z_val, value); - ZVAL_NEW_REF(&z_expiration, value); - ZVAL_LONG(Z_REFVAL(z_expiration), 0); + ZVAL_NEW_REF(&ref_val, value); + ZVAL_NEW_REF(&ref_expiration, &zv_expiration); - ZVAL_COPY(¶ms[0], zmemc_obj); - ZVAL_COPY(¶ms[1], &z_key); - ZVAL_COPY_VALUE(¶ms[2], &z_val); - ZVAL_COPY_VALUE(¶ms[3], &z_expiration); + ZVAL_COPY(¶ms[0], zobject); + ZVAL_COPY(¶ms[1], &zv_key); + ZVAL_COPY_VALUE(¶ms[2], &ref_val); + ZVAL_COPY_VALUE(¶ms[3], &ref_expiration); fci->retval = &retval; fci->params = params; fci->param_count = 4; result = zend_call_function(fci, fcc); + ZVAL_DUP(value, Z_REFVAL(ref_val)); - ZVAL_DUP(value, Z_REFVAL(z_val)); - expiration = Z_REFVAL(z_expiration); if (result == SUCCESS && Z_TYPE(retval) != IS_UNDEF) { - struct memc_obj *m_obj; - i_obj = Z_MEMC_OBJ_P(zmemc_obj) - m_obj = i_obj->obj; if (zend_is_true(&retval)) { - time_t expir; + time_t expiration; + zend_string *payload; + uint32_t flags = 0; + php_memc_object_t *intern; + php_memc_user_data_t *memc_user_data; - expir = zval_get_long(expiration); - payload = s_zval_to_payload(value, &flags, m_obj->serializer, m_obj->compression_type); + intern = Z_MEMC_OBJ_P(zobject); + memc_user_data = memcached_get_user_data(intern->memc); + + expiration = zval_get_long(Z_REFVAL(ref_expiration)); + payload = s_zval_to_payload(value, &flags, memc_user_data->serializer, memc_user_data->compression_type); if (payload == NULL) { - status = (memcached_return)MEMC_RES_PAYLOAD_FAILURE; + rc = (memcached_return) MEMC_RES_PAYLOAD_FAILURE; } else { - if (m_obj->set_udf_flags >= 0) { - MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) m_obj->set_udf_flags)); + if (memc_user_data->set_udf_flags >= 0) { + MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) memc_user_data->set_udf_flags)); } - rc = memcached_set(m_obj->memc, key->val, key->len, payload->val, payload->len, expir, flags); - if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED) { - status = rc; + rc = memcached_set(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags); + if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_BUFFERED) { + rc = MEMCACHED_SOME_ERRORS; } zend_string_release(payload); } } else { - status = MEMCACHED_NOTFOUND; + rc = MEMCACHED_NOTFOUND; zval_dtor(value); ZVAL_NULL(value); } - - } else { - if (result == FAILURE) { - php_error_docref(NULL, E_WARNING, "could not invoke cache callback"); - } - status = MEMCACHED_FAILURE; - zval_dtor(value); - ZVAL_NULL(value); } if (!Z_ISUNDEF(retval)) { zval_ptr_dtor(&retval); } - zval_ptr_dtor(&z_key); - zval_ptr_dtor(&z_val); - zval_ptr_dtor(&z_expiration); - zval_ptr_dtor(zmemc_obj); - - return status; + zval_ptr_dtor(&zv_key); + zval_ptr_dtor(&ref_val); + zval_ptr_dtor(&zv_expiration); + zval_ptr_dtor(&ref_expiration); + zval_ptr_dtor(zobject); + return rc; } -static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, - zend_fcall_info_cache *fcc, - memcached_result_st *result) + +static +int s_invoke_result_callback(zval *zmemc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, memcached_result_st *result) { const char *res_key = NULL; size_t res_key_len = 0; @@ -3542,7 +3632,7 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, zval z_result; uint32_t flags = 0; int rc = 0; - php_memc_t *i_obj = NULL; + php_memc_object_t *intern = NULL; fci->retval = &retval; fci->param_count = 2; @@ -3554,10 +3644,10 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, res_key_len = memcached_result_key_length(result); cas = memcached_result_cas(result); - i_obj = Z_MEMC_OBJ_P(zmemc_obj); + intern = Z_MEMC_OBJ_P(zmemc_obj); if (!s_memcached_result_to_zval(result, &value)) { - i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; + intern->rescode = MEMC_RES_PAYLOAD_FAILURE; return -1; } @@ -4085,6 +4175,8 @@ PHP_GINIT_FUNCTION(php_memcached) php_memcached_globals->session_ini.sasl_username = NULL; php_memcached_globals->session_ini.sasl_password = NULL; + php_memcached_globals->no_effect = 0; + #endif php_memcached_globals->memc_ini.serializer_name = NULL; php_memcached_globals->memc_ini.serializer = SERIALIZER_DEFAULT; @@ -4362,15 +4454,15 @@ PHP_MINIT_FUNCTION(memcached) zend_class_entry ce; memcpy(&memcached_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); - memcached_object_handlers.offset = XtOffsetOf(php_memc_t, zo); + memcached_object_handlers.offset = XtOffsetOf(php_memc_object_t, zo); memcached_object_handlers.clone_obj = NULL; - memcached_object_handlers.free_obj = php_memc_free_storage; + memcached_object_handlers.free_obj = php_memc_object_free_storage; le_memc = zend_register_list_destructors_ex(NULL, php_memc_dtor, "Memcached persistent connection", module_number); INIT_CLASS_ENTRY(ce, "Memcached", memcached_class_methods); memcached_ce = zend_register_internal_class(&ce); - memcached_ce->create_object = php_memc_new; + memcached_ce->create_object = php_memc_object_new; #ifdef HAVE_MEMCACHED_PROTOCOL memcpy(&memcached_server_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); diff --git a/php_memcached_private.h b/php_memcached_private.h index 46565e70..4a4dc4fe 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -176,6 +176,9 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) } memc_ini; + /* For deprecated values */ + zend_long no_effect; + #ifdef HAVE_MEMCACHED_PROTOCOL struct { diff --git a/php_memcached_session.c b/php_memcached_session.c index 1a398ab7..34bfc77c 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -297,6 +297,8 @@ memcached_st *s_init_mod_data (const memcached_server_list_st servers, zend_bool memcached_set_user_data(memc, user_data); memcached_server_push (memc, servers); + + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_VERIFY_KEY, 1); return memc; } @@ -501,6 +503,21 @@ PS_CREATE_SID_FUNC(memcached) sid = NULL; } } + + if (sid) { + if (sid->len + (sizeof ("lock.") - 1) > (MEMCACHED_MAX_KEY - 1)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session id is too long to be stored in memcached"); + zend_string_release (sid); + return NULL; + } + if (MEMC_SESS_STR_INI(prefix)) { + if (strlen (MEMC_SESS_STR_INI(prefix)) + sid->len + (sizeof ("lock.") - 1) > (MEMCACHED_MAX_KEY - 1)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session id with prefix is too long to be stored in memcached"); + zend_string_release (sid); + return NULL; + } + } + } return sid; } diff --git a/tests/bug_16084.phpt b/tests/bug_16084.phpt index c103b297..ba217a70 100644 --- a/tests/bug_16084.phpt +++ b/tests/bug_16084.phpt @@ -7,16 +7,14 @@ Memcached: Bug #16084 (Crash when addServers is called with an associative array $servers = array ( 0 => array ( 'KEYHERE' => 'localhost', 11211, 3 ), ); $m = new memcached(); var_dump($m->addServers($servers)); -var_dump($m->getServerList()); +$list = $m->getServerList(); + +var_dump ($list[0]["host"], $list[0]["port"]); +echo "OK"; + ?> --EXPECT-- bool(true) -array(1) { - [0]=> - array(2) { - ["host"]=> - string(9) "localhost" - ["port"]=> - int(11211) - } -} +string(9) "localhost" +int(11211) +OK diff --git a/tests/callback_exception.phpt b/tests/callback_exception.phpt index fa149077..176163e8 100644 --- a/tests/callback_exception.phpt +++ b/tests/callback_exception.phpt @@ -40,7 +40,7 @@ try { $m = new Memcached(null, 'throw_something'); echo "fail\n"; } catch (Exception $e) { - echo "fail\n"; + echo "success\n"; } echo "OK\n"; @@ -50,4 +50,5 @@ echo "OK\n"; success success empty_cb called +success OK diff --git a/tests/getserverlist.phpt b/tests/getserverlist.phpt index e4ef5968..88b7d27c 100644 --- a/tests/getserverlist.phpt +++ b/tests/getserverlist.phpt @@ -14,41 +14,52 @@ var_dump($m->getServerList()); $m = new memcached(); $m->addServer('127.0.0.1', 11211); var_dump($m->getServerList()); + +echo "OK"; ?> ---EXPECTF-- +--EXPECT-- array(0) { } array(1) { [0]=> - array(2) { + array(3) { ["host"]=> string(9) "localhost" ["port"]=> int(11211) + ["type"]=> + string(3) "TCP" } } array(2) { [0]=> - array(2) { + array(3) { ["host"]=> string(9) "localhost" ["port"]=> int(11211) + ["type"]=> + string(3) "TCP" } [1]=> - array(2) { + array(3) { ["host"]=> string(9) "localhost" ["port"]=> int(11211) + ["type"]=> + string(3) "TCP" } } array(1) { [0]=> - array(2) { + array(3) { ["host"]=> string(9) "127.0.0.1" ["port"]=> int(11211) + ["type"]=> + string(3) "TCP" } } +OK \ No newline at end of file diff --git a/tests/invoke_callback.phpt b/tests/invoke_callback.phpt index 55cbec1e..83e15ca2 100644 --- a/tests/invoke_callback.phpt +++ b/tests/invoke_callback.phpt @@ -12,6 +12,7 @@ function my_func(Memcached $obj, $persistent_id = null) $obj->addServer(MEMC_SERVER_HOST, MEMC_SERVER_PORT); } +$m = new Memcached('hi', 'my_func'); $m = new Memcached('hi', 'my_func'); var_dump($m->getServerList()); @@ -21,11 +22,13 @@ echo "OK\n"; --EXPECTF-- array(1) { [0]=> - array(2) { + array(3) { ["host"]=> string(9) "127.0.0.1" ["port"]=> int(11211) + ["type"]=> + string(3) "TCP" } } OK diff --git a/tests/keys.phpt b/tests/keys.phpt index 89632f5d..927dc507 100644 --- a/tests/keys.phpt +++ b/tests/keys.phpt @@ -11,6 +11,7 @@ $binary = memc_get_instance (array ( )); $ascii = memc_get_instance (); +$ascii->setOption(Memcached::OPT_VERIFY_KEY, 1); var_dump ($binary->set ('binary key with spaces', 'this is a test')); var_dump ($binary->getResultCode () == Memcached::RES_SUCCESS); diff --git a/tests/session_badconf_emptyprefix.phpt b/tests/session_badconf_emptyprefix.phpt index 74d681dd..825bb8e2 100644 --- a/tests/session_badconf_emptyprefix.phpt +++ b/tests/session_badconf_emptyprefix.phpt @@ -7,25 +7,22 @@ if (!Memcached::HAVE_SESSION) print "skip"; ?> --INI-- memcached.sess_locking = on -memcached.sess_lock_wait = 150000 memcached.sess_prefix = "memc.sess.key." -session.save_handler = memcached +session.save_handler = "memcached" --FILE-- --INI-- -memcached.sess_locking = on -memcached.sess_lock_wait = 150000 -memcached.sess_prefix = "memc.sess.key." session.save_handler = memcached - --FILE-- --INI-- -memcached.sess_locking = on -memcached.sess_lock_wait = 150000 -memcached.sess_prefix = "memc.sess.key." session.save_handler = memcached - --FILE-- --INI-- -memcached.sess_locking = on -memcached.sess_lock_wait = 150000 -memcached.sess_prefix = "memc.sess.key." session.save_handler = memcached - --FILE-- --INI-- -memcached.sess_locking = on -memcached.sess_lock_wait = 150000 -memcached.sess_prefix = "memc.sess.key." session.save_handler = memcached - --FILE-- TRUE]); $_SESSION['foo'] = 1; diff --git a/tests/session_basic3.phpt b/tests/session_basic3.phpt index b8e4f5f8..21288571 100644 --- a/tests/session_basic3.phpt +++ b/tests/session_basic3.phpt @@ -6,26 +6,24 @@ if (!extension_loaded("memcached")) print "skip"; if (!Memcached::HAVE_SESSION) print "skip"; ?> --INI-- -memcached.sess_locking = on -memcached.sess_lock_wait = 150000 -memcached.sess_prefix = "memc.sess.key." session.save_handler = memcached - --FILE-- TRUE]); +session_start(); $_SESSION['foo'] = 1; session_write_close(); $_SESSION = NULL; var_dump($_SESSION); -session_start(); +session_start([ + 'read_and_close' => true +]); var_dump($_SESSION); session_write_close(); From ecc7d8115191d2e42f8edbe28c819b899c1774f6 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sun, 31 Jan 2016 16:11:05 +0000 Subject: [PATCH 061/345] Add tests, fix compilation error for non-sasl --- php_memcached.c | 2 ++ tests/get_flags.phpt | 65 +++++++++++++++++++++++++++++++++++ tests/session_lock.phpt | 58 +++++++++++++++++++++++++++++++ tests/session_regenerate.phpt | 26 ++++++++++++++ tests/stats.phpt | 23 +++++++++++++ 5 files changed, 174 insertions(+) create mode 100644 tests/get_flags.phpt create mode 100644 tests/session_lock.phpt create mode 100644 tests/session_regenerate.phpt create mode 100644 tests/stats.phpt diff --git a/php_memcached.c b/php_memcached.c index 1dbe0bab..dc7d2c28 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -323,7 +323,9 @@ PHP_INI_BEGIN() MEMC_INI_ENTRY("compression_factor", "1.3", OnUpdateReal, compression_factor) MEMC_INI_ENTRY("compression_threshold", "2000", OnUpdateLong, compression_threshold) MEMC_INI_ENTRY("serializer", SERIALIZER_DEFAULT_NAME, OnUpdateSerializer, serializer_name) +#if HAVE_MEMCACHED_SASL MEMC_INI_ENTRY("use_sasl", "0", OnUpdateBool, sasl_enabled) +#endif MEMC_INI_ENTRY("store_retry_count", "2", OnUpdateLong, store_retry_count) PHP_INI_END() /* }}} */ diff --git a/tests/get_flags.phpt b/tests/get_flags.phpt new file mode 100644 index 00000000..ef477fdc --- /dev/null +++ b/tests/get_flags.phpt @@ -0,0 +1,65 @@ +--TEST-- +Memcached::get/getMulti() flags +--SKIPIF-- + +--FILE-- +set ($key1, 'hello1', 20); +$m->set ($key2, 'hello2', 20); + +$value = $m->get($key1); +$extended = $m->get($key1, null, Memcached::GET_EXTENDED); + +var_dump ($value); +var_dump ($extended); + +$values = $m->getMulti(array ($key1, $key2), Memcached::GET_PRESERVE_ORDER); +$extended = $m->getMulti(array ($key1, $key2), Memcached::GET_EXTENDED | Memcached::GET_PRESERVE_ORDER); + +var_dump ($values); +var_dump ($extended); +echo "OK"; + +--EXPECTF-- +string(6) "hello1" +array(3) { + ["value"]=> + string(6) "hello1" + ["cas"]=> + int(%d) + ["flags"]=> + int(0) +} +array(2) { + ["memc.test.%s"]=> + string(6) "hello1" + ["memc.test.%s"]=> + string(6) "hello2" +} +array(2) { + ["memc.test.%s"]=> + array(3) { + ["value"]=> + string(6) "hello1" + ["cas"]=> + int(%d) + ["flags"]=> + int(0) + } + ["memc.test.%s"]=> + array(3) { + ["value"]=> + string(6) "hello2" + ["cas"]=> + int(%d) + ["flags"]=> + int(0) + } +} +OK \ No newline at end of file diff --git a/tests/session_lock.phpt b/tests/session_lock.phpt new file mode 100644 index 00000000..a328dd68 --- /dev/null +++ b/tests/session_lock.phpt @@ -0,0 +1,58 @@ +--TEST-- +Session lock +--SKIPIF-- + +--INI-- +memcached.sess_locking = true +memcached.sess_lock_wait_min = 500 +memcached.sess_lock_wait_max = 1000 +memcached.sess_lock_retries = 3 +memcached.sess_prefix = "memc.test." + +session.save_handler = memcached + +--FILE-- +addServer(MEMC_SERVER_HOST, MEMC_SERVER_PORT); + +ob_start(); +ini_set ('session.save_path', MEMC_SERVER_HOST . ':' . MEMC_SERVER_PORT); + +session_start(); +$session_id = session_id(); + +$_SESSION["test"] = "hello"; +session_write_close(); + +session_start(); +var_dump ($m->get ('memc.test.' . session_id())); +var_dump ($m->get ('memc.test.lock.' . session_id())); +session_write_close(); +var_dump ($m->get ('memc.test.lock.' . session_id())); + +// Test lock min / max +$m->set ('memc.test.lock.' . $session_id, '1'); + +$time_start = microtime(true); +session_start(); +$time = microtime(true) - $time_start; + +if (round ($time, 1) != 2.5) { + echo "Waited longer than expected: $time" . PHP_EOL; +} +echo "OK"; + +--EXPECTF-- +string(17) "test|s:5:"hello";" +string(1) "1" +bool(false) + +Warning: session_start(): Unable to clear session lock record in %s on line %d +OK diff --git a/tests/session_regenerate.phpt b/tests/session_regenerate.phpt new file mode 100644 index 00000000..794f46fc --- /dev/null +++ b/tests/session_regenerate.phpt @@ -0,0 +1,26 @@ +--TEST-- +Session regenerate +--SKIPIF-- + +--INI-- +session.save_handler = memcached +--FILE-- + +--FILE-- +getStats(); +$key = MEMC_SERVER_HOST . ':' . MEMC_SERVER_PORT; + +var_dump (count ($stats) === 1); +var_dump (isset ($stats[$key])); +var_dump (count ($stats[$key]) > 0); + +echo "OK"; +?> +--EXPECT-- +bool(true) +bool(true) +bool(true) +OK From 9ce59ef3c318e3c639c54cd433522834a436e56a Mon Sep 17 00:00:00 2001 From: Mikko Date: Sun, 31 Jan 2016 16:14:42 +0000 Subject: [PATCH 062/345] Add to package.xml --- package.xml | 4 ++++ tests/stats.phpt | 2 ++ 2 files changed, 6 insertions(+) diff --git a/package.xml b/package.xml index e42b8037..11879322 100644 --- a/package.xml +++ b/package.xml @@ -137,6 +137,10 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + + + diff --git a/tests/stats.phpt b/tests/stats.phpt index ddd2ac4b..72b8014c 100644 --- a/tests/stats.phpt +++ b/tests/stats.phpt @@ -13,6 +13,7 @@ $key = MEMC_SERVER_HOST . ':' . MEMC_SERVER_PORT; var_dump (count ($stats) === 1); var_dump (isset ($stats[$key])); var_dump (count ($stats[$key]) > 0); +var_dump (is_int ($stats[$key]['cmd_get'])); echo "OK"; ?> @@ -20,4 +21,5 @@ echo "OK"; bool(true) bool(true) bool(true) +bool(true) OK From 782077ce575601855a169452a948077444d318e1 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sun, 31 Jan 2016 23:11:11 +0000 Subject: [PATCH 063/345] Fix json serializer --- package.xml | 4 +- php_memcached.c | 187 ++++++++++++++++++------------------ php_memcached_private.h | 16 +-- php_memcached_session.c | 30 ++---- tests/types_json_multi.phpt | 2 +- 5 files changed, 112 insertions(+), 127 deletions(-) diff --git a/package.xml b/package.xml index 11879322..6c162a14 100644 --- a/package.xml +++ b/package.xml @@ -147,9 +147,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> - 5.2.0 - 6.0.0 - 6.0.0 + 7.0.0 1.4.0b1 diff --git a/php_memcached.c b/php_memcached.c index dc7d2c28..cf8116a8 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -50,9 +50,9 @@ #endif #ifdef ZTS -#define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, memc_ini.v) +#define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, memc.v) #else -#define MEMC_G(v) (php_memcached_globals.memc_ini.v) +#define MEMC_G(v) (php_memcached_globals.memc.v) #endif #include @@ -285,10 +285,10 @@ PHP_INI_MH(OnUpdateSessionPrefixString) } #define MEMC_INI_ENTRY(key, default_value, update_fn, gkey) \ - STD_PHP_INI_ENTRY("memcached."key, default_value, PHP_INI_ALL, update_fn, memc_ini.gkey, zend_php_memcached_globals, php_memcached_globals) + STD_PHP_INI_ENTRY("memcached."key, default_value, PHP_INI_ALL, update_fn, memc.gkey, zend_php_memcached_globals, php_memcached_globals) #define MEMC_SESSION_INI_ENTRY(key, default_value, update_fn, gkey) \ - STD_PHP_INI_ENTRY("memcached.sess_"key, default_value, PHP_INI_ALL, update_fn, session_ini.gkey, zend_php_memcached_globals, php_memcached_globals) + STD_PHP_INI_ENTRY("memcached.sess_"key, default_value, PHP_INI_ALL, update_fn, session.gkey, zend_php_memcached_globals, php_memcached_globals) /* {{{ INI entries */ @@ -298,7 +298,7 @@ PHP_INI_BEGIN() MEMC_SESSION_INI_ENTRY("locking", "1", OnUpdateBool, lock_enabled) MEMC_SESSION_INI_ENTRY("lock_wait_min", "1000", OnUpdateLongGEZero, lock_wait_min) MEMC_SESSION_INI_ENTRY("lock_wait_max", "2000", OnUpdateLongGEZero, lock_wait_max) - MEMC_SESSION_INI_ENTRY("lock_retries", "5", OnUpdateLongGEZero, lock_retries) + MEMC_SESSION_INI_ENTRY("lock_retries", "5", OnUpdateLong, lock_retries) MEMC_SESSION_INI_ENTRY("lock_expire", "0", OnUpdateLongGEZero, lock_expiration) MEMC_SESSION_INI_ENTRY("compression", "1", OnUpdateBool, compression_enabled) MEMC_SESSION_INI_ENTRY("binary_protocol", "1", OnUpdateBool, binary_protocol_enabled) @@ -323,9 +323,6 @@ PHP_INI_BEGIN() MEMC_INI_ENTRY("compression_factor", "1.3", OnUpdateReal, compression_factor) MEMC_INI_ENTRY("compression_threshold", "2000", OnUpdateLong, compression_threshold) MEMC_INI_ENTRY("serializer", SERIALIZER_DEFAULT_NAME, OnUpdateSerializer, serializer_name) -#if HAVE_MEMCACHED_SASL - MEMC_INI_ENTRY("use_sasl", "0", OnUpdateBool, sasl_enabled) -#endif MEMC_INI_ENTRY("store_retry_count", "2", OnUpdateLong, store_retry_count) PHP_INI_END() /* }}} */ @@ -367,7 +364,7 @@ static void php_memc_destroy(memcached_st *memc, php_memc_user_data_t *memc_user_data); static - zend_bool s_memcached_result_to_zval(memcached_result_st *result, zval *return_value); + zend_bool s_memcached_result_to_zval(memcached_st *memc, memcached_result_st *result, zval *return_value); static zend_string *s_zval_to_payload(zval *value, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type); @@ -377,6 +374,24 @@ static Method implementations ****************************************/ +zend_bool php_memc_init_sasl_if_needed() +{ +#if HAVE_MEMCACHED_SASL + if (MEMC_G(sasl_initialised)) { + return 1; + } + if (sasl_client_init(NULL) != SASL_OK) { + php_error_docref(NULL, E_ERROR, "Failed to initialize SASL library"); + return 0; + } + return 1; +#else + php_error_docref(NULL, E_ERROR, "Memcached not built with sasl support"); + return 0; +#endif +} + + memcached_return php_memcached_exist (memcached_st *memc, zend_string *key) { @@ -816,7 +831,7 @@ memcached_return s_memcached_get_multi(memcached_st *memc, HashTable *hash_keys, } ZVAL_UNDEF(&value); - if (!s_memcached_result_to_zval(&result, &value)) { + if (!s_memcached_result_to_zval(memc, &result, &value)) { if (EG(exception)) { status = MEMC_RES_PAYLOAD_FAILURE; @@ -1136,9 +1151,9 @@ PHP_METHOD(Memcached, fetch) size_t res_key_len = 0; const char *payload = NULL; size_t payload_len = 0; - zval value; uint32_t flags = 0; uint64_t cas = 0; + zval value, zv_cas; memcached_result_st result; memcached_return status = MEMCACHED_SUCCESS; MEMC_METHOD_INIT_VARS; @@ -1157,29 +1172,25 @@ PHP_METHOD(Memcached, fetch) RETURN_FALSE; } - payload = memcached_result_value(&result); - payload_len = memcached_result_length(&result); - flags = memcached_result_flags(&result); - res_key = memcached_result_key_value(&result); - res_key_len = memcached_result_key_length(&result); - cas = memcached_result_cas(&result); - - if (!s_memcached_result_to_zval(&result, &value)) { + if (!s_memcached_result_to_zval(intern->memc, &result, &value)) { memcached_result_free(&result); intern->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FALSE; } array_init(return_value); - add_assoc_stringl_ex(return_value, ZEND_STRL("key"), (char *)res_key, res_key_len); - add_assoc_zval_ex(return_value, ZEND_STRL("value"), &value); - if (cas != 0) { - /* XXX: also check against ULLONG_MAX or memc_behavior */ - add_assoc_double_ex(return_value, ZEND_STRL("cas"), (double)cas); - } - if (MEMC_VAL_GET_USER_FLAGS(flags) != 0) { - add_assoc_long_ex(return_value, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); - } + + flags = memcached_result_flags(&result); + res_key = memcached_result_key_value(&result); + res_key_len = memcached_result_key_length(&result); + cas = memcached_result_cas(&result); + + add_assoc_stringl_ex(return_value, ZEND_STRL("key"), (char *) res_key, res_key_len); + add_assoc_zval_ex(return_value, ZEND_STRL("value"), &value); + + s_uint64_to_zval (&zv_cas, cas); + add_assoc_zval_ex(return_value, ZEND_STRL("cas"), &zv_cas); + add_assoc_long_ex(return_value, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); memcached_result_free(&result); } @@ -1193,9 +1204,9 @@ PHP_METHOD(Memcached, fetchAll) size_t res_key_len = 0; const char *payload = NULL; size_t payload_len = 0; - zval value, entry; uint32_t flags; uint64_t cas = 0; + zval value, entry, zv_cas; memcached_result_st result; memcached_return status = MEMCACHED_SUCCESS; MEMC_METHOD_INIT_VARS; @@ -1211,30 +1222,27 @@ PHP_METHOD(Memcached, fetchAll) memcached_result_create(intern->memc, &result); while ((memcached_fetch_result(intern->memc, &result, &status)) != NULL) { - payload = memcached_result_value(&result); - payload_len = memcached_result_length(&result); - flags = memcached_result_flags(&result); - res_key = memcached_result_key_value(&result); - res_key_len = memcached_result_key_length(&result); - cas = memcached_result_cas(&result); - if (!s_memcached_result_to_zval(&result, &value)) { + if (!s_memcached_result_to_zval(intern->memc, &result, &value)) { memcached_result_free(&result); zval_dtor(return_value); intern->rescode = MEMC_RES_PAYLOAD_FAILURE; RETURN_FALSE; } + flags = memcached_result_flags(&result); + res_key = memcached_result_key_value(&result); + res_key_len = memcached_result_key_length(&result); + cas = memcached_result_cas(&result); + array_init(&entry); add_assoc_stringl_ex(&entry, ZEND_STRL("key"), (char *)res_key, res_key_len); - add_assoc_zval_ex(&entry, ZEND_STRL("value"), &value); - if (cas != 0) { - /* XXX: also check against ULLONG_MAX or memc_behavior */ - add_assoc_double_ex(&entry, ZEND_STRL("cas"), (double)cas); - } - if (MEMC_VAL_GET_USER_FLAGS(flags) != 0) { - add_assoc_long_ex(&entry, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); - } + add_assoc_zval_ex(&entry, ZEND_STRL("value"), &value); + + s_uint64_to_zval (&zv_cas, cas); + add_assoc_zval_ex(&entry, ZEND_STRL("cas"), &zv_cas); + add_assoc_long_ex(&entry, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); + add_next_index_zval(return_value, &entry); } @@ -2825,8 +2833,7 @@ static PHP_METHOD(Memcached, setSaslAuthData) return; } - if (!MEMC_G(sasl_enabled)) { - php_error_docref(NULL, E_WARNING, "SASL support (memcached.use_sasl) isn't enabled in php.ini"); + if (!php_memc_init_sasl_if_needed()) { RETURN_FALSE; } @@ -3363,7 +3370,7 @@ zend_string *s_decompress_value (const char *payload, size_t payload_len, uint32 } static -zend_bool s_unserialize_value (int val_type, zend_string *payload, zval *return_value) +zend_bool s_unserialize_value (memcached_st *memc, int val_type, zend_string *payload, zval *return_value) { switch (val_type) { case MEMC_VAL_IS_SERIALIZED: @@ -3402,7 +3409,10 @@ zend_bool s_unserialize_value (int val_type, zend_string *payload, zval *return_ case MEMC_VAL_IS_JSON: #ifdef HAVE_JSON_API - php_json_decode(return_value, payload->val, payload->len, (serializer == SERIALIZER_JSON_ARRAY), PHP_JSON_PARSER_DEFAULT_DEPTH); + { + php_memc_user_data_t *memc_user_data = memcached_get_user_data(memc); + php_json_decode(return_value, payload->val, payload->len, (memc_user_data->serializer == SERIALIZER_JSON_ARRAY), PHP_JSON_PARSER_DEFAULT_DEPTH); + } #else ZVAL_FALSE(return_value); php_error_docref(NULL, E_WARNING, "could not unserialize value, no json support"); @@ -3424,7 +3434,7 @@ zend_bool s_unserialize_value (int val_type, zend_string *payload, zval *return_ } static -zend_bool s_memcached_result_to_zval(memcached_result_st *result, zval *return_value) +zend_bool s_memcached_result_to_zval(memcached_st *memc, memcached_result_st *result, zval *return_value) { zend_string *data; const char *payload; @@ -3485,7 +3495,7 @@ zend_bool s_memcached_result_to_zval(memcached_result_st *result, zval *return_v case MEMC_VAL_IS_IGBINARY: case MEMC_VAL_IS_JSON: case MEMC_VAL_IS_MSGPACK: - retval = s_unserialize_value (MEMC_VAL_GET_TYPE(flags), data, return_value); + retval = s_unserialize_value (memc, MEMC_VAL_GET_TYPE(flags), data, return_value); break; default: @@ -3648,7 +3658,7 @@ int s_invoke_result_callback(zval *zmemc_obj, zend_fcall_info *fci, zend_fcall_i intern = Z_MEMC_OBJ_P(zmemc_obj); - if (!s_memcached_result_to_zval(result, &value)) { + if (!s_memcached_result_to_zval(intern->memc, result, &value)) { intern->rescode = MEMC_RES_PAYLOAD_FAILURE; return -1; } @@ -4159,37 +4169,35 @@ PHP_GINIT_FUNCTION(php_memcached) { #ifdef HAVE_MEMCACHED_SESSION - php_memcached_globals->session_ini.lock_enabled = 0; - php_memcached_globals->session_ini.lock_wait_max = 2000; - php_memcached_globals->session_ini.lock_wait_min = 1000; - php_memcached_globals->session_ini.lock_retries = 5; - php_memcached_globals->session_ini.lock_expiration = 30; - php_memcached_globals->session_ini.compression_enabled = 1; - php_memcached_globals->session_ini.binary_protocol_enabled = 1; - php_memcached_globals->session_ini.consistent_hash_enabled = 1; - php_memcached_globals->session_ini.number_of_replicas = 0; - php_memcached_globals->session_ini.server_failure_limit = 1; - php_memcached_globals->session_ini.randomize_replica_read_enabled = 1; - php_memcached_globals->session_ini.remove_failed_servers_enabled = 1; - php_memcached_globals->session_ini.connect_timeout = 1000; - php_memcached_globals->session_ini.prefix = NULL; - php_memcached_globals->session_ini.persistent_enabled = 0; - php_memcached_globals->session_ini.sasl_username = NULL; - php_memcached_globals->session_ini.sasl_password = NULL; + php_memcached_globals->session.lock_enabled = 0; + php_memcached_globals->session.lock_wait_max = 2000; + php_memcached_globals->session.lock_wait_min = 1000; + php_memcached_globals->session.lock_retries = 5; + php_memcached_globals->session.lock_expiration = 30; + php_memcached_globals->session.compression_enabled = 1; + php_memcached_globals->session.binary_protocol_enabled = 1; + php_memcached_globals->session.consistent_hash_enabled = 1; + php_memcached_globals->session.number_of_replicas = 0; + php_memcached_globals->session.server_failure_limit = 1; + php_memcached_globals->session.randomize_replica_read_enabled = 1; + php_memcached_globals->session.remove_failed_servers_enabled = 1; + php_memcached_globals->session.connect_timeout = 1000; + php_memcached_globals->session.prefix = NULL; + php_memcached_globals->session.persistent_enabled = 0; + php_memcached_globals->session.sasl_username = NULL; + php_memcached_globals->session.sasl_password = NULL; - php_memcached_globals->no_effect = 0; - -#endif - php_memcached_globals->memc_ini.serializer_name = NULL; - php_memcached_globals->memc_ini.serializer = SERIALIZER_DEFAULT; - php_memcached_globals->memc_ini.compression_type = NULL; - php_memcached_globals->memc_ini.compression_threshold = 2000; - php_memcached_globals->memc_ini.compression_type_real = COMPRESSION_TYPE_FASTLZ; - php_memcached_globals->memc_ini.compression_factor = 1.30; - php_memcached_globals->memc_ini.store_retry_count = 2; -#if HAVE_MEMCACHED_SASL - php_memcached_globals->memc_ini.sasl_enabled = 0; #endif + php_memcached_globals->memc.serializer_name = NULL; + php_memcached_globals->memc.serializer = SERIALIZER_DEFAULT; + php_memcached_globals->memc.compression_type = NULL; + php_memcached_globals->memc.compression_threshold = 2000; + php_memcached_globals->memc.compression_type_real = COMPRESSION_TYPE_FASTLZ; + php_memcached_globals->memc.compression_factor = 1.30; + php_memcached_globals->memc.store_retry_count = 2; + + php_memcached_globals->memc.sasl_initialised = 0; + php_memcached_globals->no_effect = 0; } zend_module_entry memcached_module_entry = { @@ -4385,11 +4393,11 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) /* * Serializer types. */ - REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_PHP, SERIALIZER_PHP); - REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_IGBINARY, SERIALIZER_IGBINARY); - REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_JSON, SERIALIZER_JSON); + REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_PHP, SERIALIZER_PHP); + 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); + REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_MSGPACK, SERIALIZER_MSGPACK); /* * Compression types @@ -4487,15 +4495,6 @@ PHP_MINIT_FUNCTION(memcached) #ifdef HAVE_MEMCACHED_SESSION php_memc_session_minit(module_number); #endif - -#if HAVE_MEMCACHED_SASL - if (MEMC_G(sasl_enabled)) { - if (sasl_client_init(NULL) != SASL_OK) { - php_error_docref(NULL, E_ERROR, "Failed to initialize SASL library"); - return FAILURE; - } - } -#endif return SUCCESS; } /* }}} */ @@ -4504,7 +4503,7 @@ PHP_MINIT_FUNCTION(memcached) PHP_MSHUTDOWN_FUNCTION(memcached) { #if HAVE_MEMCACHED_SASL - if (MEMC_G(sasl_enabled)) { + if (MEMC_G(sasl_initialised)) { sasl_done(); } #endif diff --git a/php_memcached_private.h b/php_memcached_private.h index 4a4dc4fe..c6c0b77c 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -155,8 +155,7 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) char *sasl_username; char *sasl_password; - } session_ini; - + } session; #endif struct { @@ -166,15 +165,14 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) double compression_factor; zend_long store_retry_count; -#if HAVE_MEMCACHED_SASL - zend_bool sasl_enabled; -#endif - /* Converted values*/ enum memcached_serializer serializer; zend_long compression_type_real; - } memc_ini; + /* Whether we have initialised sasl for this process */ + zend_bool sasl_initialised; + + } memc; /* For deprecated values */ zend_long no_effect; @@ -194,10 +192,12 @@ PHP_MINIT_FUNCTION(memcached); PHP_MSHUTDOWN_FUNCTION(memcached); PHP_MINFO_FUNCTION(memcached); -char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC); +char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_cache); memcached_return php_memcached_exist (memcached_st *memc, zend_string *key); +zend_bool php_memc_init_sasl_if_needed(); + #endif /* PHP_MEMCACHED_PRIVATE_H */ /* diff --git a/php_memcached_session.c b/php_memcached_session.c index 34bfc77c..bfb34e99 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -45,9 +45,9 @@ typedef struct { #endif #ifdef ZTS -#define MEMC_SESS_INI(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, session_ini.v) +#define MEMC_SESS_INI(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, session.v) #else -#define MEMC_SESS_INI(v) (php_memcached_globals.session_ini.v) +#define MEMC_SESS_INI(v) (php_memcached_globals.session.v) #endif #define MEMC_SESS_STR_INI(vv) ((MEMC_SESS_INI(vv) && *MEMC_SESS_INI(vv)) ? MEMC_SESS_INI(vv) : NULL) @@ -138,7 +138,7 @@ zend_bool s_lock_session(memcached_st *memc, zend_string *sid) switch (rc) { case MEMCACHED_SUCCESS: - user_data->lock_key = zend_string_init(lock_key, lock_key_len, user_data->is_persistent); + user_data->lock_key = zend_string_init(lock_key, lock_key_len, user_data->is_persistent); user_data->is_locked = 1; break; @@ -215,10 +215,13 @@ zend_bool s_configure_from_ini_values(memcached_st *memc, zend_bool silent) memcached_callback_set(memc, MEMCACHED_CALLBACK_NAMESPACE, MEMC_SESS_STR_INI(prefix)); } -#ifdef HAVE_MEMCACHED_SASL if (MEMC_SESS_STR_INI(sasl_username) && MEMC_SESS_STR_INI(sasl_password)) { php_memcached_user_data *user_data; + if (!php_memc_init_sasl_if_needed()) { + return 0; + } + check_set_behavior(MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1); if (memcached_set_sasl_auth_data(memc, MEMC_SESS_STR_INI(sasl_username), MEMC_SESS_STR_INI(sasl_password)) == MEMCACHED_FAILURE) { @@ -228,7 +231,6 @@ zend_bool s_configure_from_ini_values(memcached_st *memc, zend_bool silent) user_data = memcached_get_user_data(memc); user_data->has_sasl_data = 1; } -#endif #undef safe_set_behavior @@ -297,7 +299,6 @@ memcached_st *s_init_mod_data (const memcached_server_list_st servers, zend_bool memcached_set_user_data(memc, user_data); memcached_server_push (memc, servers); - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_VERIFY_KEY, 1); return memc; } @@ -307,6 +308,7 @@ PS_OPEN_FUNC(memcached) memcached_st *memc = NULL; char *plist_key = NULL; size_t plist_key_len = 0; + memcached_server_list_st servers; // First parse servers @@ -348,6 +350,7 @@ PS_OPEN_FUNC(memcached) if (plist_key) { efree(plist_key); } + s_destroy_mod_data(memc); PS_SET_MOD_DATA(NULL); return FAILURE; } @@ -503,21 +506,6 @@ PS_CREATE_SID_FUNC(memcached) sid = NULL; } } - - if (sid) { - if (sid->len + (sizeof ("lock.") - 1) > (MEMCACHED_MAX_KEY - 1)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session id is too long to be stored in memcached"); - zend_string_release (sid); - return NULL; - } - if (MEMC_SESS_STR_INI(prefix)) { - if (strlen (MEMC_SESS_STR_INI(prefix)) + sid->len + (sizeof ("lock.") - 1) > (MEMCACHED_MAX_KEY - 1)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session id with prefix is too long to be stored in memcached"); - zend_string_release (sid); - return NULL; - } - } - } return sid; } diff --git a/tests/types_json_multi.phpt b/tests/types_json_multi.phpt index 5535abb8..6a085039 100644 --- a/tests/types_json_multi.phpt +++ b/tests/types_json_multi.phpt @@ -3,7 +3,7 @@ Memcached multi store & multi fetch type and value correctness using JSON serial --SKIPIF-- --FILE-- Date: Mon, 1 Feb 2016 01:12:26 +0000 Subject: [PATCH 064/345] Fix serializers --- .travis/travis.sh | 18 +++++++++--------- php_memcached.c | 11 +++++++++-- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index 131e38bf..1eab43fb 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -67,8 +67,8 @@ function install_libmemcached() { } function install_igbinary() { - git clone https://github.com/igbinary/igbinary.git - pushd igbinary + git clone https://github.com/igbinary/igbinary7.git + pushd igbinary7 phpize ./configure make @@ -79,7 +79,7 @@ function install_igbinary() { function install_msgpack() { git clone https://github.com/msgpack/msgpack-php.git pushd msgpack-php - git checkout php7 + git checkout php7 phpize ./configure make @@ -152,9 +152,9 @@ function build_php_memcached() { sasl_flag="--enable-memcached-sasl" fi - # ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag --enable-memcached-json --enable-memcached-msgpack --enable-memcached-igbinary - ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag - make + # ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag + ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag --enable-memcached-json --enable-memcached-msgpack --enable-memcached-igbinary + make make install popd } @@ -184,7 +184,7 @@ function run_memcached_tests() { rm ./tests/expire.phpt # Run normal tests - php run-tests.php --show-diff -d extension=memcached.so -n ./tests/*.phpt + php run-tests.php --show-diff -d extension=modules/memcached.so -d extension=msgpack.so -d extension=igbinary.so -n ./tests/*.phpt retval=$? popd return $retval; @@ -236,10 +236,10 @@ case $ACTION in install_libmemcached # Install igbinary extension - # install_igbinary + install_igbinary # install msgpack - # install_msgpack + install_msgpack install_memcached run_memcached diff --git a/php_memcached.c b/php_memcached.c index cf8116a8..a8d9605b 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3187,11 +3187,18 @@ zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, */ #ifdef HAVE_MEMCACHED_IGBINARY case SERIALIZER_IGBINARY: - if (igbinary_serialize((uint8_t **) &(buf->s), &buf->s->len, value) != 0) { + { + uint8_t *buffer; + size_t buffer_len; + + if (igbinary_serialize(&buffer, &buffer_len, value) != 0) { php_error_docref(NULL, E_WARNING, "could not serialize value with igbinary"); return 0; } + smart_str_appendl (buf, buffer, buffer_len); + efree(buffer); MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_IGBINARY); + } break; #endif @@ -3395,7 +3402,7 @@ zend_bool s_unserialize_value (memcached_st *memc, int val_type, zend_string *pa case MEMC_VAL_IS_IGBINARY: #ifdef HAVE_MEMCACHED_IGBINARY - if (igbinary_unserialize((uint8_t *) payload->val, payload->len, &value)) { + if (igbinary_unserialize((uint8_t *) payload->val, payload->len, return_value)) { ZVAL_FALSE(return_value); php_error_docref(NULL, E_WARNING, "could not unserialize value with igbinary"); return 0; From cf4d0ead4fcccbfd86cfd2ff1e0278d9c463f470 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 1 Feb 2016 01:34:03 +0000 Subject: [PATCH 065/345] Update package.xml for release along with memcached.ini --- memcached.ini | 31 +++++++++++++------------------ package.xml | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 18 deletions(-) diff --git a/memcached.ini b/memcached.ini index 1996eb27..1aa9f266 100644 --- a/memcached.ini +++ b/memcached.ini @@ -4,19 +4,19 @@ ; the default is On memcached.sess_locking = On -; Session spin lock retry wait time in microseconds. -; Be carefull when setting this value. -; Valid values are integers, where 0 is interpreted as -; the default value. Negative values result in a reduces -; locking to a try lock. -; the default is 150000 -memcached.sess_lock_wait = 150000 - -; The maximum time, in seconds, to wait for a session lock -; before timing out. -; Setting to 0 results in default behavior, which is to -; use max_execution_time. -memcached.sess_lock_max_wait = 0; +; !! DEPRECATED AND REMOVED in 3.x !! +; memcached.sess_lock_wait = 150000 + +; !! DEPRECATED AND REMOVED in 3.x !! +; memcached.sess_lock_max_wait = 0; + +; The minimum time, in milliseconds, to wait between session lock attempts. +; This value is double on each lock retry until memcached.sess_lock_wait_max +; is reached +memcached.sess_lock_wait_min = 0; + +; The maximum time, in milliseconds, to wait between session lock attempts. +memcached.sess_lock_wait_max = 0; ; The time, in seconds, before a lock should release itself. ; Setting to 0 results in the default behaviour, which is to @@ -105,11 +105,6 @@ memcached.compression_threshold = 2000 ; The default is igbinary if available, then msgpack if available, then php otherwise. memcached.serializer = "igbinary" -; Use SASL authentication for connections -; valid values: On, Off -; the default is Off -memcached.use_sasl = Off - ; The amount of retries for failed store commands. ; This mechanism allows transparent fail-over to secondary servers when ; set/increment/decrement/setMulti operations fail on the desired server in a multi-server diff --git a/package.xml b/package.xml index 6c162a14..39175882 100644 --- a/package.xml +++ b/package.xml @@ -159,6 +159,42 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + + beta + beta + + + 3.0.0 + 3.0.0 + + 2016-02-01 + +PHP7 release of memcached extension. Note that support for libmemcached 0.x series has been discontinued +and the earliest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of +libmemcached. + +API + * set/get commands do not take cas or user flags parameters + * get and getMulti commands take Memcached::GET_EXTENDED flag to retrieve user flags and cas tokens + * Fixes getStats command to return all stats from all servers + * Fixes allKeys command behaviour + * Fixes error where cache callback for get command was not setting expiration time properly + * Added server type to server list + * Remove use_sasl ini-variable and initialise sasl as needed + +Session handler + * Session lock algorithm updated (new ini-values memcached.sess_lock_wait_min, memcached.sess_lock_wait_max and memcached.sess_lock_retries) + * Session extension uses PHP allocators (still some work to do on the rest of the extension) + * Ini-values take effect during session_start or session_regenerate_id + * Fixes crash with session_regenerate_id (work-around for PHP bug) + +Tests + * Fix several broken tests + + + + stablestable 2.2.02.2.0 From a93ff86f7c94b811a8bf5c69f8b576c2d08acc29 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 1 Feb 2016 01:37:36 +0000 Subject: [PATCH 066/345] More package.xml / version updates --- package.xml | 12 ++++++------ php_memcached.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package.xml b/package.xml index 39175882..29c617e7 100644 --- a/package.xml +++ b/package.xml @@ -21,14 +21,14 @@ http://pear.php.net/dtd/package-2.0.xsd"> mkoppanen@php.net yes - 2014-04-01 + 2016-02-01 - 2.2.0 - 2.2.0 + 3.0.0b1 + 3.0.0 - stable - stable + beta + beta PHP @@ -165,7 +165,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> beta - 3.0.0 + 3.0.0b1 3.0.0 2016-02-01 diff --git a/php_memcached.h b/php_memcached.h index b96ef37a..9e466cb4 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -27,7 +27,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "2.2.0" +#define PHP_MEMCACHED_VERSION "3.0.0b1" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 938f6bcf68ff5cf07884cbf4963336c3e8fe7f2f Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 1 Feb 2016 01:40:17 +0000 Subject: [PATCH 067/345] Update right place in package.xml --- package.xml | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/package.xml b/package.xml index 29c617e7..d2088a12 100644 --- a/package.xml +++ b/package.xml @@ -32,7 +32,27 @@ http://pear.php.net/dtd/package-2.0.xsd"> PHP -- Added the OPT_SERVER_TIMEOUT_LIMIT behaviour +PHP7 release of memcached extension. Note that support for libmemcached 0.x series has been discontinued +and the earliest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of +libmemcached. + +API + * set/get commands do not take cas or user flags parameters + * get and getMulti commands take Memcached::GET_EXTENDED flag to retrieve user flags and cas tokens + * Fixes getStats command to return all stats from all servers + * Fixes allKeys command behaviour + * Fixes error where cache callback for get command was not setting expiration time properly + * Added server type to server list + * Remove use_sasl ini-variable and initialise sasl as needed + +Session handler + * Session lock algorithm updated (new ini-values memcached.sess_lock_wait_min, memcached.sess_lock_wait_max and memcached.sess_lock_retries) + * Session extension uses PHP allocators (still some work to do on the rest of the extension) + * Ini-values take effect during session_start or session_regenerate_id + * Fixes crash with session_regenerate_id (work-around for PHP bug) + +Tests + * Fix several broken tests @@ -191,10 +211,8 @@ Session handler Tests * Fix several broken tests - - stablestable 2.2.02.2.0 From a930b41fa138a55b976c55e21157e57b09355343 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 6 Feb 2016 05:07:52 +0000 Subject: [PATCH 068/345] Fixes memory errors, broken code, bugs etc --- package.xml | 1 + php_libmemcached_compat.c | 40 +- php_libmemcached_compat.h | 2 +- php_memcached.c | 4235 +++++++++++++++---------------- php_memcached_private.h | 29 +- tests/getdelayed.phpt | 37 +- tests/incrdecr_invalid_key.phpt | 1 + 7 files changed, 2128 insertions(+), 2217 deletions(-) diff --git a/package.xml b/package.xml index d2088a12..9d3be440 100644 --- a/package.xml +++ b/package.xml @@ -202,6 +202,7 @@ API * Fixes error where cache callback for get command was not setting expiration time properly * Added server type to server list * Remove use_sasl ini-variable and initialise sasl as needed + * CAS tokens are returned as integers and in case of too large values they overflow to strings Session handler * Session lock algorithm updated (new ini-values memcached.sess_lock_wait_min, memcached.sess_lock_wait_max and memcached.sess_lock_retries) diff --git a/php_libmemcached_compat.c b/php_libmemcached_compat.c index f49b162b..bd35d8fe 100644 --- a/php_libmemcached_compat.c +++ b/php_libmemcached_compat.c @@ -18,36 +18,20 @@ #include "php_memcached_private.h" #include "php_libmemcached_compat.h" -memcached_st *php_memc_create_str (const char *str, size_t str_len) +memcached_return php_memcached_exist (memcached_st *memc, zend_string *key) { -#ifdef HAVE_LIBMEMCACHED_MEMCACHED - return memcached (str, str_len); +#ifdef HAVE_MEMCACHED_EXIST + return memcached_exist (memc, key->val, key->len); #else - memcached_return rc; - memcached_st *memc; - memcached_server_st *servers; - - memc = memcached_create(NULL); - - if (!memc) { - return NULL; - } - - servers = memcached_servers_parse (str); - - if (!servers) { - memcached_free (memc); - return NULL; + memcached_return rc = MEMCACHED_SUCCESS; + uint32_t flags = 0; + size_t value_length = 0; + char *value = NULL; + + value = memcached_get (memc, key->val, key->len, &value_length, &flags, &rc); + if (value) { + free (value); } - - rc = memcached_server_push (memc, servers); - memcached_server_free (servers); - - if (rc != MEMCACHED_SUCCESS) { - memcached_free (memc); - return NULL; - } - return memc; + return rc; #endif } - diff --git a/php_libmemcached_compat.h b/php_libmemcached_compat.h index ae400d9c..e740d310 100644 --- a/php_libmemcached_compat.h +++ b/php_libmemcached_compat.h @@ -20,7 +20,7 @@ /* this is the version(s) we support */ #include -memcached_st *php_memc_create_str (const char *str, size_t str_len); +memcached_return php_memcached_exist (memcached_st *memc, zend_string *key); #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x00052000 # define MEMCACHED_SERVER_TEMPORARILY_DISABLED (1024 << 2) diff --git a/php_memcached.c b/php_memcached.c index a8d9605b..c01b7f94 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -27,6 +27,9 @@ #include "php_memcached_server.h" #include "g_fmt.h" +#include +#include + #ifdef HAVE_MEMCACHED_SESSION # include "php_memcached_session.h" #endif @@ -55,8 +58,14 @@ #define MEMC_G(v) (php_memcached_globals.memc.v) #endif -#include + static + int le_memc; +static +int php_memc_list_entry(void) +{ + return le_memc; +} /**************************************** Custom options @@ -113,30 +122,34 @@ /**************************************** "get" operation flags ****************************************/ -#define MEMC_GET_PRESERVE_ORDER (1<<0) -#define MEMC_GET_EXTENDED (2<<0) +#define MEMC_GET_PRESERVE_ORDER 1 +#define MEMC_GET_EXTENDED 2 /**************************************** Helper macros ****************************************/ - - #define RETURN_FROM_GET RETURN_FALSE /**************************************** Structures and definitions ****************************************/ -enum memcached_compression_type { - COMPRESSION_TYPE_ZLIB = 1, - COMPRESSION_TYPE_FASTLZ = 2, -}; + +typedef enum { + MEMC_OP_SET, + MEMC_OP_TOUCH, + MEMC_OP_ADD, + MEMC_OP_REPLACE, + MEMC_OP_APPEND, + MEMC_OP_PREPEND +} php_memc_write_op; typedef struct { zend_bool is_persistent; - zend_bool compression; - enum memcached_serializer serializer; - enum memcached_compression_type compression_type; + zend_bool compression_enabled; + + zend_long serializer; + zend_long compression_type; zend_long store_retry_count; zend_long set_udf_flags; @@ -144,10 +157,8 @@ typedef struct { #if HAVE_MEMCACHED_SASL zend_bool has_sasl_data; #endif - } php_memc_user_data_t; - typedef struct { memcached_st *memc; zend_bool is_pristine; @@ -156,6 +167,22 @@ typedef struct { zend_object zo; } php_memc_object_t; +typedef struct { + size_t num_valid_keys; + + const char **mkeys; + size_t *mkeys_len; + + zend_string **strings; + +} php_memc_keys_t; + +typedef struct { + zval *object; + zend_fcall_info fci; + zend_fcall_info_cache fcc; +} php_memc_result_callback_ctx_t; + static inline php_memc_object_t *php_memc_fetch_object(zend_object *obj) { return (php_memc_object_t *)((char *)obj - XtOffsetOf(php_memc_object_t, zo)); } @@ -184,15 +211,6 @@ typedef struct { #endif -enum { - MEMC_OP_SET, - MEMC_OP_TOUCH, - MEMC_OP_ADD, - MEMC_OP_REPLACE, - MEMC_OP_APPEND, - MEMC_OP_PREPEND -}; - static zend_class_entry *memcached_ce = NULL; static zend_class_entry *memcached_exception_ce = NULL; @@ -217,11 +235,11 @@ ZEND_GET_MODULE(memcached) static PHP_INI_MH(OnUpdateCompressionType) { if (!new_value) { - MEMC_G(compression_type_real) = COMPRESSION_TYPE_FASTLZ; + MEMC_G(compression_type) = COMPRESSION_TYPE_FASTLZ; } else if (!strcmp(new_value->val, "fastlz")) { - MEMC_G(compression_type_real) = COMPRESSION_TYPE_FASTLZ; + MEMC_G(compression_type) = COMPRESSION_TYPE_FASTLZ; } else if (!strcmp(new_value->val, "zlib")) { - MEMC_G(compression_type_real) = COMPRESSION_TYPE_ZLIB; + MEMC_G(compression_type) = COMPRESSION_TYPE_ZLIB; } else { return FAILURE; } @@ -231,22 +249,22 @@ static PHP_INI_MH(OnUpdateCompressionType) static PHP_INI_MH(OnUpdateSerializer) { if (!new_value) { - MEMC_G(serializer) = SERIALIZER_DEFAULT; + MEMC_G(serializer_type) = SERIALIZER_DEFAULT; } else if (!strcmp(new_value->val, "php")) { - MEMC_G(serializer) = SERIALIZER_PHP; + MEMC_G(serializer_type) = SERIALIZER_PHP; #ifdef HAVE_MEMCACHED_IGBINARY } else if (!strcmp(new_value->val, "igbinary")) { - MEMC_G(serializer) = SERIALIZER_IGBINARY; + MEMC_G(serializer_type) = SERIALIZER_IGBINARY; #endif // IGBINARY #ifdef HAVE_JSON_API } else if (!strcmp(new_value->val, "json")) { - MEMC_G(serializer) = SERIALIZER_JSON; + MEMC_G(serializer_type) = SERIALIZER_JSON; } else if (!strcmp(new_value->val, "json_array")) { - MEMC_G(serializer) = SERIALIZER_JSON_ARRAY; + MEMC_G(serializer_type) = SERIALIZER_JSON_ARRAY; #endif // JSON #ifdef HAVE_MEMCACHED_MSGPACK } else if (!strcmp(new_value->val, "msgpack")) { - MEMC_G(serializer) = SERIALIZER_MSGPACK; + MEMC_G(serializer_type) = SERIALIZER_MSGPACK; #endif // msgpack } else { return FAILURE; @@ -300,7 +318,6 @@ PHP_INI_BEGIN() MEMC_SESSION_INI_ENTRY("lock_wait_max", "2000", OnUpdateLongGEZero, lock_wait_max) MEMC_SESSION_INI_ENTRY("lock_retries", "5", OnUpdateLong, lock_retries) MEMC_SESSION_INI_ENTRY("lock_expire", "0", OnUpdateLongGEZero, lock_expiration) - MEMC_SESSION_INI_ENTRY("compression", "1", OnUpdateBool, compression_enabled) MEMC_SESSION_INI_ENTRY("binary_protocol", "1", OnUpdateBool, binary_protocol_enabled) MEMC_SESSION_INI_ENTRY("consistent_hash", "1", OnUpdateBool, consistent_hash_enabled) MEMC_SESSION_INI_ENTRY("number_of_replicas", "0", OnUpdateLongGEZero, number_of_replicas) @@ -319,7 +336,7 @@ PHP_INI_BEGIN() #endif - MEMC_INI_ENTRY("compression_type", "fastlz", OnUpdateCompressionType, compression_type) + MEMC_INI_ENTRY("compression_type", "fastlz", OnUpdateCompressionType, compression_name) MEMC_INI_ENTRY("compression_factor", "1.3", OnUpdateReal, compression_factor) MEMC_INI_ENTRY("compression_threshold", "2000", OnUpdateLong, compression_threshold) MEMC_INI_ENTRY("serializer", SERIALIZER_DEFAULT_NAME, OnUpdateSerializer, serializer_name) @@ -333,8 +350,6 @@ PHP_INI_END() /**************************************** Forward declarations ****************************************/ -static int php_memc_handle_error(php_memc_object_t *intern, memcached_return status); - static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool by_key); @@ -345,10 +360,19 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ /* Invoke PHP functions */ static - memcached_return s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string *key, zval *value); + zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string *key, zval *value); + +/* Iterate result sets */ +typedef zend_bool (*php_memc_result_apply_fn)(php_memc_object_t *intern, zend_string *key, zval *value, zval *cas, uint32_t flags, void *context); + +static +memcached_return php_memc_result_apply(php_memc_object_t *intern, php_memc_result_apply_fn result_apply_fn, void *context); static - int s_invoke_result_callback(zval *zmemc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, memcached_result_st *result); +zend_bool php_memc_mget_apply(php_memc_object_t *intern, zend_string *server_key, + php_memc_keys_t *keys, php_memc_result_apply_fn result_apply_fn, + zend_bool with_cas, void *context); + /* Callback functions for different server list iterations */ static @@ -357,8 +381,8 @@ static static memcached_return s_server_cursor_version_cb(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context); -/* Callback for dumping all keys to zval */ - +static + zend_bool s_memc_write_zval (php_memc_object_t *intern, php_memc_write_op op, zend_string *server_key, zend_string *key, zval *value, time_t expiration); static void php_memc_destroy(memcached_st *memc, php_memc_user_data_t *memc_user_data); @@ -367,11 +391,17 @@ static zend_bool s_memcached_result_to_zval(memcached_st *memc, memcached_result_st *result, zval *return_value); static - zend_string *s_zval_to_payload(zval *value, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type); + zend_string *s_zval_to_payload(php_memc_object_t *intern, zval *value, uint32_t *flags); + +static + void s_hash_to_keys(php_memc_keys_t *keys_out, HashTable *hash_in, zend_bool preserve_order, zval *return_value); + +static + void s_clear_keys(php_memc_keys_t *keys); /**************************************** - Method implementations + Exported helper functions ****************************************/ zend_bool php_memc_init_sasl_if_needed() @@ -391,27 +421,6 @@ zend_bool php_memc_init_sasl_if_needed() #endif } - - -memcached_return php_memcached_exist (memcached_st *memc, zend_string *key) -{ -#ifdef HAVE_MEMCACHED_EXIST - return memcached_exist (memc, key->val, key->len); -#else - memcached_return rc = MEMCACHED_SUCCESS; - uint32_t flags = 0; - size_t value_length = 0; - char *value = NULL; - - value = memcached_get (memc, key->val, key->len, &value_length, &flags, &rc); - if (value) { - free (value); - } - return rc; -#endif -} - - char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) { char *buffer = NULL; @@ -429,1646 +438,1558 @@ char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_ return buffer; } + +/**************************************** + Handling error codes +****************************************/ + static -zend_bool s_invoke_new_instance_cb(zval *object, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache, zend_string *persistent_id) +zend_bool s_memcached_return_is_error(memcached_return status, zend_bool strict) { - zend_bool ret = 1; - zval retval, id; - - if (persistent_id) { - ZVAL_STR(&id, persistent_id); - } else { - ZVAL_NULL(&id); - } + zend_bool result = 0; - ZVAL_UNDEF(&retval); + switch (status) { + case MEMCACHED_SUCCESS: + case MEMCACHED_STORED: + case MEMCACHED_DELETED: + case MEMCACHED_STAT: + case MEMCACHED_END: + case MEMCACHED_BUFFERED: + result = 0; + break; - zend_fcall_info_argn(fci, 2, object, &id); - fci->retval = &retval; - fci->no_separation = 1; + case MEMCACHED_SOME_ERRORS: + result = strict; + break; - if (zend_call_function(fci, fci_cache) == FAILURE) { - char *buf = php_memc_printable_func (fci, fci_cache); - php_error_docref(NULL, E_WARNING, "Failed to invoke 'on_new' callback %s()", buf); - efree (buf); - ret = 0; + default: + result = 1; + break; } + return result; +} - if (Z_TYPE(retval) != IS_UNDEF) { - zval_ptr_dtor(&retval); - } +static +int s_memc_status_handle_result_code(php_memc_object_t *intern, memcached_return status) +{ + intern->rescode = status; + intern->memc_errno = 0; - if (EG(exception)) { - ret = 0; + if (s_memcached_return_is_error(status, 1)) { + intern->memc_errno = memcached_last_error_errno(intern->memc); + return FAILURE; } - - zend_fcall_info_args_clear(fci, 1); - return ret; + return SUCCESS; } static - int le_memc; +void s_memc_set_status(php_memc_object_t *intern, memcached_return status, int memc_errno) +{ + intern->rescode = status; + intern->memc_errno = memc_errno; +} static -int php_memc_list_entry(void) +zend_bool s_memc_status_has_error(php_memc_object_t *intern) { - return le_memc; + return s_memcached_return_is_error(intern->rescode, 1); } -/* {{{ Memcached::__construct([string persistent_id[, callback on_new[, string connection_str]]])) - Creates a Memcached object, optionally using persistent memcache connection */ -static PHP_METHOD(Memcached, __construct) +static +zend_bool s_memc_status_has_result_code(php_memc_object_t *intern, memcached_return status) { - php_memc_object_t *intern; - php_memc_user_data_t *memc_user_data; - - zend_string *persistent_id = NULL; - zend_string *conn_str = NULL; - zend_string *plist_key = NULL; - zend_fcall_info fci = {0}; - zend_fcall_info_cache fci_cache; + return intern->rescode == status; +} - zend_bool is_persistent = 0; +/**************************************** + Marshall cas tokens +****************************************/ - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!f!S", &persistent_id, &fci, &fci_cache, &conn_str) == FAILURE) { - return; +static +void s_uint64_to_zval (zval *target, uint64_t value) +{ + if (value >= ((uint64_t) LONG_MAX)) { + char *buffer; +#ifdef PRIu64 + spprintf (&buffer, 0, "%" PRIu64, value); +#else + /* Best effort */ + spprintf (&buffer, 0, "%llu", value); +#endif + ZVAL_STRING (target, buffer); + efree(buffer); + } + else { + ZVAL_LONG (target, (zend_long) value); } +} - intern = Z_MEMC_OBJ_P(getThis()); - intern->is_pristine = 1; +static +uint64_t s_zval_to_uint64 (zval *cas) +{ + switch (Z_TYPE_P (cas)) { + case IS_LONG: + return (uint64_t) zval_get_long (cas); + break; - if (persistent_id && persistent_id->len) { - zend_resource *le; + case IS_DOUBLE: + if (Z_DVAL_P (cas) < 0.0) + return 0; - plist_key = zend_string_alloc(sizeof("memcached:id=") + persistent_id->len - 1, 0); - snprintf(plist_key->val, plist_key->len + 1, "memcached:id=%s", persistent_id->val); + return (uint64_t) zval_get_double (cas); + break; - if ((le = zend_hash_find_ptr(&EG(persistent_list), plist_key)) != NULL) { - if (le->type == php_memc_list_entry()) { - intern->memc = le->ptr; - intern->is_pristine = 0; - zend_string_release (plist_key); - return; + case IS_STRING: + { + uint64_t val; + char *end; + + errno = 0; + val = (uint64_t) strtoull (Z_STRVAL_P (cas), &end, 0); + + if (*end || (errno == ERANGE && val == UINT64_MAX) || (errno != 0 && val == 0)) { + php_error_docref(NULL, E_ERROR, "Failed to unmarshall cas token"); + return 0; } + return val; } - is_persistent = 1; + break; } + return 0; +} - if (conn_str && conn_str->len > 0) { - intern->memc = memcached (conn_str->val, conn_str->len); - } - else { - intern->memc = memcached (NULL, 0); - } - if (!intern->memc) { - // TODO: handle allocation fail - } +/**************************************** + Iterate over memcached results and mget +****************************************/ - memc_user_data = pecalloc (1, sizeof(*memc_user_data), is_persistent); - memc_user_data->serializer = MEMC_G(serializer); - memc_user_data->compression_type = MEMC_G(compression_type_real); - memc_user_data->compression = 1; - memc_user_data->store_retry_count = MEMC_G(store_retry_count); - memc_user_data->set_udf_flags = -1; - memc_user_data->is_persistent = is_persistent; +static +memcached_return php_memc_result_apply(php_memc_object_t *intern, php_memc_result_apply_fn result_apply_fn, void *context) +{ + memcached_result_st result, *result_ptr; + memcached_return rc, status = MEMCACHED_SUCCESS; - memcached_set_user_data(intern->memc, memc_user_data); + memcached_result_create(intern->memc, &result); - if (fci.size) { - if (!s_invoke_new_instance_cb(getThis(), &fci, &fci_cache, persistent_id) || EG(exception)) { - /* error calling or exception thrown from callback */ - if (plist_key) { - zend_string_release(plist_key); - } - /* - Setting intern->memc null prevents object destruction from freeing the memcached_st - We free it manually here because it might be persistent and has not been - registered to persistent_list yet - */ - php_memc_destroy(intern->memc, memc_user_data); - intern->memc = NULL; - return; + do { + result_ptr = memcached_fetch_result(intern->memc, &result, &rc); + + if (s_memcached_return_is_error(rc, 0)) { + status = rc; } - } - if (plist_key) { - zend_resource le; + /* nothing returned */ + if (!result_ptr) { + break; + } + else { + zend_string *key; + zval zv_value, zv_cas; + zend_bool retval; - le.type = php_memc_list_entry(); - le.ptr = intern->memc; + uint64_t cas; + uint32_t flags; - GC_REFCOUNT(&le) = 1; + const char *res_key; + size_t res_key_len; + - /* plist_key is not a persistent allocated key, thus we use str_update here */ - if (zend_hash_str_update_mem(&EG(persistent_list), plist_key->val, plist_key->len, &le, sizeof(le)) == NULL) { - zend_string_release(plist_key); - php_error_docref(NULL, E_ERROR, "could not register persistent entry"); - /* not reached */ - } - zend_string_release(plist_key); - } + ZVAL_UNDEF(&zv_value); + if (!s_memcached_result_to_zval(intern->memc, &result, &zv_value)) { + if (Z_TYPE(zv_value) != IS_UNDEF) { + zval_ptr_dtor(&zv_value); + } + if (EG(exception)) { + status = MEMC_RES_PAYLOAD_FAILURE; + memcached_quit(intern->memc); + break; + } + status = MEMCACHED_SOME_ERRORS; + continue; + } + res_key = memcached_result_key_value(&result); + res_key_len = memcached_result_key_length(&result); + cas = memcached_result_cas(&result); + flags = memcached_result_flags(&result); -#if 0 - m_obj = pecalloc(1, sizeof(*m_obj), intern->is_persistent); - if (m_obj == NULL) { - if (plist_key) { - zend_string_release(plist_key); - } - php_error_docref(NULL, E_ERROR, "out of memory: cannot allocate handle"); - /* not reached */ - } + s_uint64_to_zval(&zv_cas, cas); - if (conn_str) { - intern->memc = php_memc_create_str(conn_str->val, conn_str->len); - if (!intern->memc) { - char error_buffer[1024]; - if (plist_key) { - zend_string_release(plist_key); - } -#ifdef HAVE_LIBMEMCACHED_CHECK_CONFIGURATION - if (libmemcached_check_configuration(conn_str->val, conn_str->len, error_buffer, sizeof(error_buffer)) != MEMCACHED_SUCCESS) { - php_error_docref(NULL, E_ERROR, "configuration error %s", error_buffer); - } else { - php_error_docref(NULL, E_ERROR, "could not allocate libmemcached structure"); - } -#else - php_error_docref(NULL, E_ERROR, "could not allocate libmemcached structure"); -#endif - /* not reached */ - } - } else { - intern->memc = memcached_create(NULL); - if (intern->memc == NULL) { - if (plist_key) { - zend_string_release(plist_key); + key = zend_string_init (res_key, res_key_len, 0); + retval = result_apply_fn(intern, key, &zv_value, &zv_cas, flags, context); + + zend_string_release (key); + zval_ptr_dtor(&zv_value); + zval_ptr_dtor(&zv_cas); + + /* Stop iterating on false */ + if (!retval) { + /* Make sure we clear our results */ + while (memcached_fetch_result(intern->memc, &result, &rc)) {} + break; } - php_error_docref(NULL, E_ERROR, "could not allocate libmemcached structure"); - /* not reached */ } - } + } while (result_ptr != NULL); + memcached_result_free(&result); + return status; +} +static +zend_bool php_memc_mget_apply(php_memc_object_t *intern, zend_string *server_key, php_memc_keys_t *keys, + php_memc_result_apply_fn result_apply_fn, zend_bool with_cas, void *context) +{ + memcached_return status; + memcached_result_st result; + int mget_status; + uint64_t orig_cas_flag = 0; - intern->obj = m_obj; - intern->is_pristine = 1; + // Reset status code + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); - if (fci.size) { /* will be 0 when not available */ - if (!php_memcached_on_new_callback(object, &fci, &fci_cache, persistent_id) || EG(exception)) { - /* error calling or exception thrown from callback */ - if (plist_key) { - zend_string_release(plist_key); - } + if (!keys->num_valid_keys) { + intern->rescode = MEMCACHED_BAD_KEY_PROVIDED; + return 0; + } - intern->obj = NULL; - if (intern->is_persistent) { - php_memc_destroy(m_obj, intern->is_persistent); - } + if (with_cas) { + orig_cas_flag = memcached_behavior_get (intern->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS); - return; + if (!orig_cas_flag) { + memcached_behavior_set (intern->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); } } - if (intern->is_persistent) { - zend_resource le; + if (server_key) { + status = memcached_mget_by_key(intern->memc, server_key->val, server_key->len, keys->mkeys, keys->mkeys_len, keys->num_valid_keys); + } else { + status = memcached_mget(intern->memc, keys->mkeys, keys->mkeys_len, keys->num_valid_keys); + } - le.type = php_memc_list_entry(); - le.ptr = m_obj; - GC_REFCOUNT(&le) = 1; - /* plist_key is not a persistent allocated key, thus we use str_update here */ - if (zend_hash_str_update_mem(&EG(persistent_list), plist_key->val, plist_key->len, &le, sizeof(le)) == NULL) { - if (plist_key) { - zend_string_release(plist_key); - } - php_error_docref(NULL, E_ERROR, "could not register persistent entry"); - /* not reached */ - } + /* Need to handle result code before restoring cas flags, would mess up errno */ + mget_status = s_memc_status_handle_result_code(intern, status); + + if (with_cas && !orig_cas_flag) { + memcached_behavior_set (intern->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); } - if (plist_key) { - zend_string_release(plist_key); + /* Return on failure codes */ + if (mget_status == FAILURE) { + return 0; } -#endif -} -/* }}} */ -static -void s_uint64_to_zval (zval *target, uint64_t value) -{ - if (value >= LONG_MAX) { - char *buffer; -#ifdef PRIu64 - spprintf (&buffer, 0, "%" PRIu64, value); -#else - /* Best effort */ - spprintf (&buffer, 0, "%llu", value); -#endif - ZVAL_STRING (target, buffer); - efree(buffer); + if (!result_apply_fn) { + /* no callback, for example getDelayed */ + return 1; } - else { - ZVAL_LONG (target, (zend_long) value); + + status = php_memc_result_apply(intern, result_apply_fn, context); + + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + return 0; } + + return 1; } +/**************************************** + Invoke callbacks +****************************************/ + static -uint64_t s_zval_to_uint64 (zval *cas) +zend_bool s_invoke_new_instance_cb(zval *object, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache, zend_string *persistent_id) { - switch (Z_TYPE_P (cas)) { - case IS_LONG: - return (uint64_t) zval_get_long (cas); - break; + zend_bool ret = 1; + zval retval, id; - case IS_DOUBLE: - if (Z_DVAL_P (cas) < 0.0) - return 0; + if (persistent_id) { + ZVAL_STR(&id, persistent_id); + } else { + ZVAL_NULL(&id); + } - return (uint64_t) zval_get_double (cas); - break; + ZVAL_UNDEF(&retval); - case IS_STRING: - { - uint64_t val; - char *end; + zend_fcall_info_argn(fci, 2, object, &id); + fci->retval = &retval; + fci->no_separation = 1; - errno = 0; - val = (uint64_t) strtoull (Z_STRVAL_P (cas), &end, 0); + if (zend_call_function(fci, fci_cache) == FAILURE) { + char *buf = php_memc_printable_func (fci, fci_cache); + php_error_docref(NULL, E_WARNING, "Failed to invoke 'on_new' callback %s()", buf); + efree (buf); + ret = 0; + } - if (*end || (errno == ERANGE && val == UINT64_MAX) || (errno != 0 && val == 0)) { - php_error_docref(NULL, E_ERROR, "Failed to unmarshall cas token"); - return 0; - } - return val; - } - break; + if (Z_TYPE(retval) != IS_UNDEF) { + zval_ptr_dtor(&retval); } - return 0; -} + if (EG(exception)) { + ret = 0; + } -typedef struct { + zend_fcall_info_args_clear(fci, 1); + return ret; +} - size_t num_valid_keys; +static +zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string *key, zval *value) +{ + memcached_return rc; + zend_bool status = 0; - const char **mkeys; - size_t *mkeys_len; + zval params[4]; + zval retval; + zval zv_key, ref_val; + zval ref_expiration, zv_expiration; + php_memc_object_t *intern = Z_MEMC_OBJ_P(zobject); - zend_string **strings; + /* Prepare params */ + ZVAL_STR(&zv_key, key); -} php_memcached_keys; + ZVAL_NULL(&ref_val); + ZVAL_NULL(&zv_expiration); -static -void s_hash_to_keys(php_memcached_keys *keys_out, HashTable *hash_in, zend_bool preserve_order, zval *return_value) -{ - size_t idx = 0, alloc_count; - zval *zv; + ZVAL_NEW_REF(&ref_val, value); + ZVAL_NEW_REF(&ref_expiration, &zv_expiration); - keys_out->num_valid_keys = 0; + ZVAL_COPY(¶ms[0], zobject); + ZVAL_COPY(¶ms[1], &zv_key); + ZVAL_COPY_VALUE(¶ms[2], &ref_val); + ZVAL_COPY_VALUE(¶ms[3], &ref_expiration); - alloc_count = zend_hash_num_elements(hash_in); - if (!alloc_count) { - return; - } - keys_out->mkeys = ecalloc (alloc_count, sizeof (char *)); - keys_out->mkeys_len = ecalloc (alloc_count, sizeof (size_t)); - keys_out->strings = ecalloc (alloc_count, sizeof (zend_string *)); + fci->retval = &retval; + fci->params = params; + fci->param_count = 4; - ZEND_HASH_FOREACH_VAL(hash_in, zv) { - zend_string *key = zval_get_string(zv); + ZVAL_UNDEF(&retval); - if (preserve_order && return_value) { - add_assoc_null_ex(return_value, key->val, key->len); + if (zend_call_function(fci, fcc) == SUCCESS) { + if (zend_is_true(&retval)) { + time_t expiration = zval_get_long(Z_REFVAL(ref_expiration)); + status = s_memc_write_zval (intern, MEMC_OP_SET, NULL, key, Z_REFVAL(ref_val), expiration); + ZVAL_DUP(value, Z_REFVAL(ref_val)); } + } + else { + s_memc_set_status(intern, MEMCACHED_NOTFOUND, 0); + } - if (key->len > 0 && key->len < MEMCACHED_MAX_KEY) { - keys_out->mkeys[idx] = key->val; - keys_out->mkeys_len[idx] = key->len; - keys_out->strings[idx] = key; - idx++; - } - else { - zend_string_release (key); - } - } ZEND_HASH_FOREACH_END(); + zval_ptr_dtor(zobject); + zval_ptr_dtor(&zv_key); + zval_ptr_dtor(&ref_val); + zval_ptr_dtor(&ref_expiration); - if (!idx) { - efree (keys_out->mkeys); - efree (keys_out->mkeys_len); - efree (keys_out->strings); + if (!Z_ISUNDEF(retval)) { + zval_ptr_dtor(&retval); } - keys_out->num_valid_keys = idx; + return status; } -static -void s_clear_keys(php_memcached_keys *keys) -{ - size_t i; - for (i = 0; i < keys->num_valid_keys; i++) { - zend_string_release (keys->strings[i]); - } - efree(keys->strings); - efree(keys->mkeys); - efree(keys->mkeys_len); -} +/**************************************** + Wrapper for setting from zval +****************************************/ static -memcached_return s_memcached_get_multi(memcached_st *memc, HashTable *hash_keys, zend_string *server_key, zend_long get_flags, zval *return_value) +zend_bool s_compress_value (php_memc_compression_type compression_type, zend_string **payload_in, uint32_t *flags) { - php_memcached_keys keys = { 0 }; - zval values; - memcached_return rc, status = MEMCACHED_SUCCESS; - uint64_t orig_cas_flag; - memcached_result_st result; + /* status */ + zend_bool compress_status = 0; + zend_string *payload = *payload_in; - zend_bool extended = (get_flags & MEMC_GET_EXTENDED); - zend_bool preserve_order = (get_flags & MEMC_GET_PRESERVE_ORDER); + /* Additional 5% for the data */ + size_t buffer_size = (size_t) (((double) payload->len * 1.05) + 1.0); + char *buffer = emalloc(buffer_size); - array_init(&values); - s_hash_to_keys(&keys, hash_keys, preserve_order, &values); + /* Store compressed size here */ + size_t compressed_size = 0; + uint32_t original_size = payload->len; - if (!keys.num_valid_keys) { - zval_ptr_dtor(&values); - return MEMCACHED_NO_KEY_PROVIDED; - } + switch (compression_type) { - orig_cas_flag = memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS); + case COMPRESSION_TYPE_FASTLZ: + { + compressed_size = fastlz_compress(payload->val, payload->len, buffer); - if (extended && !orig_cas_flag) { - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); - } + if (compressed_size > 0) { + compress_status = 1; + MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_FASTLZ); + } + } + break; - if (server_key) { - status = memcached_mget_by_key(memc, server_key->val, server_key->len, keys.mkeys, keys.mkeys_len, keys.num_valid_keys); - } else { - status = memcached_mget(memc, keys.mkeys, keys.mkeys_len, keys.num_valid_keys); - } + case COMPRESSION_TYPE_ZLIB: + { + compressed_size = buffer_size; + int status = compress((Bytef *) buffer, &compressed_size, (Bytef *) payload->val, payload->len); - s_clear_keys(&keys); + if (status == Z_OK) { + compress_status = 1; + MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_ZLIB); + } + } + break; - if (extended && !orig_cas_flag) { - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 0); + default: + compress_status = 0; + break; } - memcached_result_create(memc, &result); - while ((memcached_fetch_result(memc, &result, &rc)) != NULL) { - - const char *res_key = NULL; - size_t res_key_len = 0; - zval value; - - /* For some reason instead of success it's end */ - if (rc == MEMCACHED_END) { - rc = MEMCACHED_SUCCESS; - } - - if (rc != MEMCACHED_SUCCESS) { - status = rc; - continue; - } + if (!compress_status) { + php_error_docref(NULL, E_WARNING, "could not compress value"); + MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); + efree (buffer); + return 0; + } - ZVAL_UNDEF(&value); - if (!s_memcached_result_to_zval(memc, &result, &value)) { - if (EG(exception)) { - status = MEMC_RES_PAYLOAD_FAILURE; + /* This means the value was too small to be compressed, still a success */ + if (compressed_size > (payload->len * MEMC_G(compression_factor))) { + MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); + efree (buffer); + return 1; + } - memcached_result_free(&result); - memcached_quit(memc); - zval_ptr_dtor (&values); - break; - } - status = MEMCACHED_SOME_ERRORS; - continue; - } + payload = zend_string_realloc(payload, compressed_size + sizeof(uint32_t), 0); - res_key = memcached_result_key_value(&result); - res_key_len = memcached_result_key_length(&result); + /* Copy the uin32_t at the beginning */ + memcpy(payload->val, &original_size, sizeof(uint32_t)); + memcpy(payload->val + sizeof (uint32_t), buffer, compressed_size); + efree(buffer); - if (extended) { - uint32_t flags; - uint64_t cas; - zval cas_token, node; + zend_string_forget_hash_val(payload); + *payload_in = payload; + return 1; +} - cas = memcached_result_cas(&result); - flags = memcached_result_flags(&result); +static +zend_bool s_serialize_value (php_memc_serializer_type serializer, zval *value, smart_str *buf, uint32_t *flags) +{ + switch (serializer) { - s_uint64_to_zval (&cas_token, cas); + /* + Igbinary serialization + */ +#ifdef HAVE_MEMCACHED_IGBINARY + case SERIALIZER_IGBINARY: + { + uint8_t *buffer; + size_t buffer_len; - array_init (&node); - add_assoc_zval (&node, "value", &value); - add_assoc_zval (&node, "cas", &cas_token); - add_assoc_long (&node, "flags", (zend_long) MEMC_VAL_GET_USER_FLAGS(flags)); + if (igbinary_serialize(&buffer, &buffer_len, value) != 0) { + php_error_docref(NULL, E_WARNING, "could not serialize value with igbinary"); + return 0; + } + smart_str_appendl (buf, buffer, buffer_len); + efree(buffer); + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_IGBINARY); + } + break; +#endif - add_assoc_zval_ex(&values, res_key, res_key_len, &node); + /* + JSON serialization + */ +#ifdef HAVE_JSON_API + case SERIALIZER_JSON: + case SERIALIZER_JSON_ARRAY: + { + php_json_encode(buf, value, 0); + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_JSON); } - else { - add_assoc_zval_ex(&values, res_key, res_key_len, &value); + break; +#endif + + /* + msgpack serialization + */ +#ifdef HAVE_MEMCACHED_MSGPACK + case SERIALIZER_MSGPACK: + php_msgpack_serialize(buf, value); + if (!buf->s) { + php_error_docref(NULL, E_WARNING, "could not serialize value with msgpack"); + return 0; + } + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_MSGPACK); + break; +#endif + + /* + PHP serialization + */ + default: + { + php_serialize_data_t var_hash; + PHP_VAR_SERIALIZE_INIT(var_hash); + php_var_serialize(buf, value, &var_hash); + PHP_VAR_SERIALIZE_DESTROY(var_hash); + + if (!buf->s) { + php_error_docref(NULL, E_WARNING, "could not serialize value"); + return 0; + } + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_SERIALIZED); } + break; } - memcached_result_free(&result); - if (Z_TYPE(values) != IS_UNDEF) { - ZVAL_ZVAL(return_value, &values, 0, 0); + /* Check for exceptions caused by serializers */ + if (EG(exception) && buf->s->len) { + return 0; } - return status; + return 1; } - static -void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) +zend_string *s_zval_to_payload(php_memc_object_t *intern, zval *value, uint32_t *flags) { - zend_long get_flags = 0; - zend_string *key; - zend_string *server_key = NULL; - memcached_return status = MEMCACHED_SUCCESS; - zend_fcall_info fci = empty_fcall_info; - zend_fcall_info_cache fcc = empty_fcall_info_cache; - HashTable keys; - zval values, tmp; - MEMC_METHOD_INIT_VARS; + zend_string *payload; + php_memc_user_data_t *memc_user_data = memcached_get_user_data(intern->memc); + zend_bool should_compress = memc_user_data->compression_enabled; - if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|f!l", &server_key, &key, &fci, &fcc, &get_flags) == FAILURE) { - return; - } - } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|f!l", &key, &fci, &fcc, &get_flags) == FAILURE) { - return; + switch (Z_TYPE_P(value)) { + + case IS_STRING: + payload = zval_get_string(value); + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_STRING); + break; + + case IS_LONG: + { + smart_str buffer = {0}; + smart_str_append_long (&buffer, Z_LVAL_P(value)); + smart_str_0(&buffer); + payload = buffer.s; + + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_LONG); + should_compress = 0; } - } + break; - MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; + case IS_DOUBLE: + { + char buffer[40]; + php_memcached_g_fmt(buffer, Z_DVAL_P(value)); + payload = zend_string_init (buffer, strlen (buffer), 0); + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_DOUBLE); + should_compress = 0; + } + break; - zend_hash_init (&keys, 1, 0, NULL, 0); - ZVAL_STR(&tmp, key); - zend_hash_add(&keys, key, &tmp); + case IS_TRUE: + payload = zend_string_init ("1", 1, 0); + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_BOOL); + should_compress = 0; + break; - ZVAL_UNDEF(&values); - status = s_memcached_get_multi(intern->memc, &keys, server_key, get_flags, &values); - zend_hash_destroy (&keys); + case IS_FALSE: + payload = zend_string_alloc (0, 0); + MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_BOOL); + should_compress = 0; + break; - if (EG(exception)) { - zval_ptr_dtor(&values); - RETURN_FROM_GET; - } + default: + { + smart_str buffer = {0}; - if (status == MEMCACHED_SUCCESS) { - zval *zv = zend_hash_find (Z_ARRVAL(values), key); - if (zv) { - RETVAL_ZVAL(zv, 1, 0); - zval_ptr_dtor(&values); - return; - } - else { - status = MEMCACHED_NOTFOUND; + if (!s_serialize_value (memc_user_data->serializer, value, &buffer, flags)) { + smart_str_free(&buffer); + return NULL; + } + payload = buffer.s; } + break; } + zend_string_forget_hash_val(payload); - if (Z_TYPE(values) != IS_UNDEF) { - zval_ptr_dtor(&values); + /* turn off compression for values below the threshold */ + if (payload->len == 0 || payload->len < MEMC_G(compression_threshold)) { + should_compress = 0; } - if (status == MEMCACHED_NOTFOUND && fci.size > 0) { - // try to invoke cache cb - status = s_invoke_cache_callback(object, &fci, &fcc, key, return_value); + /* If we have compression flag, compress the value */ + if (should_compress) { + /* status */ + if (!s_compress_value (memc_user_data->compression_type, &payload, flags)) { + zend_string_release(payload); + return NULL; + } + MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSED); } - if (php_memc_handle_error(intern, status) < 0) { - RETURN_FROM_GET; + if (memc_user_data->set_udf_flags >= 0) { + MEMC_VAL_SET_USER_FLAGS(*flags, ((uint32_t) memc_user_data->set_udf_flags)); } -} -/* {{{ Memcached::get(string key [, mixed callback [, int get_flags = 0]) - Returns a value for the given key or false */ -PHP_METHOD(Memcached, get) -{ - php_memc_get_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); + return payload; } -/* }}} */ -/* {{{ Memcached::getByKey(string server_key, string key [, mixed callback [, int get_flags = 0]) - Returns a value for key from the server identified by the server key or false */ -PHP_METHOD(Memcached, getByKey) +static +zend_bool s_should_retry_write (php_memc_object_t *intern, memcached_return status) { - php_memc_get_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); + if (memcached_server_count (intern->memc) == 0) { + return 0; + } + + return s_memcached_return_is_error (status, 1); } -/* }}} */ -/* {{{ -- php_memc_getMulti_impl */ -static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) +static +zend_bool s_memc_write_zval (php_memc_object_t *intern, php_memc_write_op op, zend_string *server_key, zend_string *key, zval *value, time_t expiration) { - zval *keys = NULL; - zend_string *server_key = NULL; - memcached_return rc; - zend_long flags = 0; - MEMC_METHOD_INIT_VARS; + uint32_t flags = 0; + zend_string *payload = NULL; + memcached_return status; + php_memc_user_data_t *memc_user_data = memcached_get_user_data(intern->memc); + zend_long retries = memc_user_data->store_retry_count; - if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|l", &server_key, - &keys, &flags) == FAILURE) { - return; - } - } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|l", &keys, &flags) == FAILURE) { - return; + if (value) { + payload = s_zval_to_payload(intern, value, &flags); + + if (!payload) { + s_memc_set_status(intern, MEMC_RES_PAYLOAD_FAILURE, 0); + return 0; } } - MEMC_METHOD_FETCH_OBJECT; +#define memc_write_using_fn(fn_name) payload ? fn_name(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags) : MEMC_RES_PAYLOAD_FAILURE; +#define memc_write_using_fn_by_key(fn_name) payload ? fn_name(intern->memc, server_key->val, server_key->len, key->val, key->len, payload->val, payload->len, expiration, flags) : MEMC_RES_PAYLOAD_FAILURE; - rc = s_memcached_get_multi(intern->memc, Z_ARRVAL_P(keys), server_key, flags, return_value); - php_memc_handle_error(intern, rc); + if (server_key) { + switch (op) { + case MEMC_OP_SET: + status = memc_write_using_fn_by_key(memcached_set_by_key); + break; - if (EG(exception)) { - zval_dtor(return_value); - RETURN_FALSE; - } -} -/* }}} */ + case MEMC_OP_TOUCH: + status = memcached_touch_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, expiration); + break; + + case MEMC_OP_ADD: + status = memc_write_using_fn_by_key(memcached_add_by_key); + break; + + case MEMC_OP_REPLACE: + status = memc_write_using_fn_by_key(memcached_replace_by_key); + break; + + case MEMC_OP_APPEND: + status = memc_write_using_fn_by_key(memcached_append_by_key); + break; -/* {{{ Memcached::getMulti(array keys[, long flags = 0 ]) - Returns values for the given keys or false */ -PHP_METHOD(Memcached, getMulti) -{ - php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); -} -/* }}} */ + case MEMC_OP_PREPEND: + status = memc_write_using_fn_by_key(memcached_prepend_by_key); + break; + } -/* {{{ Memcached::getMultiByKey(string server_key, array keys[, long flags = 0 ]) - Returns values for the given keys from the server identified by the server key or false */ -PHP_METHOD(Memcached, getMultiByKey) -{ - php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); -} -/* }}} */ + if (status == MEMCACHED_END) { + status = MEMCACHED_SUCCESS; + } + } + else { +retry: + switch (op) { + case MEMC_OP_SET: + status = memc_write_using_fn(memcached_set); + break; -/* {{{ Memcached::getDelayed(array keys [, bool with_cas [, mixed callback ] ]) - Sends a request for the given keys and returns immediately */ -PHP_METHOD(Memcached, getDelayed) -{ - php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); -} -/* }}} */ - -/* {{{ Memcached::getDelayedByKey(string server_key, array keys [, bool with_cas [, mixed callback ] ]) - Sends a request for the given keys from the server identified by the server key and returns immediately */ -PHP_METHOD(Memcached, getDelayedByKey) -{ - php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); -} -/* }}} */ - -/* {{{ -- php_memc_getDelayed_impl */ -static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) -{ - zval *keys = NULL; - zend_string *server_key = NULL; - zend_bool with_cas = 0; - size_t num_keys = 0; - zval *entry = NULL; - const char **mkeys = NULL; - size_t *mkeys_len = NULL; - uint64_t orig_cas_flag = 0; - zend_fcall_info fci = empty_fcall_info; - zend_fcall_info_cache fcc = empty_fcall_info_cache; - int i = 0; - memcached_return status = MEMCACHED_SUCCESS; - MEMC_METHOD_INIT_VARS; + case MEMC_OP_TOUCH: + status = memcached_touch(intern->memc, key->val, key->len, expiration); + break; + + case MEMC_OP_ADD: + status = memc_write_using_fn(memcached_add); + break; + + case MEMC_OP_REPLACE: + status = memc_write_using_fn(memcached_replace); + break; + + case MEMC_OP_APPEND: + status = memc_write_using_fn(memcached_append); + break; - if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|bf!", &server_key, - &keys, &with_cas, &fci, &fcc) == FAILURE) { - return; + case MEMC_OP_PREPEND: + status = memc_write_using_fn(memcached_prepend); + break; } - } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|bf!", &keys, &with_cas, - &fci, &fcc) == FAILURE) { - return; + if (status == MEMCACHED_END) { + status = MEMCACHED_SUCCESS; } } - MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; - - /* - * Create the array of keys for libmemcached. If none of the keys were valid - * (strings), set bad key result code and return. - */ - num_keys = zend_hash_num_elements(Z_ARRVAL_P(keys)); - mkeys = safe_emalloc(num_keys, sizeof(*mkeys), 0); - mkeys_len = safe_emalloc(num_keys, sizeof(*mkeys_len), 0); - - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(keys), entry) { - if (Z_TYPE_P(entry) != IS_STRING) { - convert_to_string_ex(entry); - } - - if (Z_TYPE_P(entry) == IS_STRING && Z_STRLEN_P(entry) > 0) { - mkeys[i] = Z_STRVAL_P(entry); - mkeys_len[i] = Z_STRLEN_P(entry); - i++; - } - } ZEND_HASH_FOREACH_END(); - - if (i == 0) { - intern->rescode = MEMCACHED_BAD_KEY_PROVIDED; - efree(mkeys); - efree(mkeys_len); - zval_dtor(return_value); - RETURN_FALSE; + if (s_should_retry_write (intern, status) && retries-- > 0) { + goto retry; } - /* - * Enable CAS support, but only if it is currently disabled. - */ - if (with_cas) { - orig_cas_flag = memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS); - if (orig_cas_flag == 0) { - memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1); - } - } +#undef memc_write_using_fn +#undef memc_write_using_fn_by_key - /* - * Issue the request, but collect results only if the result callback is provided. - */ - if (by_key) { - status = memcached_mget_by_key(intern->memc, server_key->val, server_key->len, mkeys, mkeys_len, i); - } else { - status = memcached_mget(intern->memc, mkeys, mkeys_len, i); + if (payload) { + zend_string_release(payload); } - /* - * Restore the CAS support flag, but only if we had to turn it on. - */ - if (with_cas && orig_cas_flag == 0) { - memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + return 0; } + return 1; +} - efree(mkeys); - efree(mkeys_len); - if (php_memc_handle_error(intern, status) < 0) { - zval_dtor(return_value); - RETURN_FALSE; - } - if (fci.size != 0) { - /* - * We have a result callback. Iterate through the result set and invoke the - * callback for each one. - */ - memcached_result_st result; +/**************************************** + Methods +****************************************/ - memcached_result_create(intern->memc, &result); - while ((memcached_fetch_result(intern->memc, &result, &status)) != NULL) { - if (s_invoke_result_callback(getThis(), &fci, &fcc, &result) < 0) { - status = MEMCACHED_FAILURE; - break; - } - } - memcached_result_free(&result); - /* we successfully retrieved all rows */ - if (status == MEMCACHED_END) { - status = MEMCACHED_SUCCESS; - } - if (php_memc_handle_error(intern, status) < 0) { - RETURN_FALSE; - } - } +/* {{{ Memcached::__construct([string persistent_id[, callback on_new[, string connection_str]]])) + Creates a Memcached object, optionally using persistent memcache connection */ +static PHP_METHOD(Memcached, __construct) +{ + php_memc_object_t *intern; + php_memc_user_data_t *memc_user_data; - RETURN_TRUE; -} -/* }}} */ + zend_string *persistent_id = NULL; + zend_string *conn_str = NULL; + zend_string *plist_key = NULL; + zend_fcall_info fci = {0}; + zend_fcall_info_cache fci_cache; -/* {{{ Memcached::fetch() - Returns the next result from a previous delayed request */ -PHP_METHOD(Memcached, fetch) -{ - const char *res_key = NULL; - size_t res_key_len = 0; - const char *payload = NULL; - size_t payload_len = 0; - uint32_t flags = 0; - uint64_t cas = 0; - zval value, zv_cas; - memcached_result_st result; - memcached_return status = MEMCACHED_SUCCESS; - MEMC_METHOD_INIT_VARS; + zend_bool is_persistent = 0; - if (zend_parse_parameters_none() == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!f!S", &persistent_id, &fci, &fci_cache, &conn_str) == FAILURE) { return; } - MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; + intern = Z_MEMC_OBJ_P(getThis()); + intern->is_pristine = 1; - memcached_result_create(intern->memc, &result); - if ((memcached_fetch_result(intern->memc, &result, &status)) == NULL) { - php_memc_handle_error(intern, status); - memcached_result_free(&result); - RETURN_FALSE; + if (persistent_id && persistent_id->len) { + zend_resource *le; + + plist_key = zend_string_alloc(sizeof("memcached:id=") + persistent_id->len - 1, 0); + snprintf(plist_key->val, plist_key->len + 1, "memcached:id=%s", persistent_id->val); + + if ((le = zend_hash_find_ptr(&EG(persistent_list), plist_key)) != NULL) { + if (le->type == php_memc_list_entry()) { + intern->memc = le->ptr; + intern->is_pristine = 0; + zend_string_release (plist_key); + return; + } + } + is_persistent = 1; } - if (!s_memcached_result_to_zval(intern->memc, &result, &value)) { - memcached_result_free(&result); - intern->rescode = MEMC_RES_PAYLOAD_FAILURE; - RETURN_FALSE; + if (conn_str && conn_str->len > 0) { + intern->memc = memcached (conn_str->val, conn_str->len); + } + else { + intern->memc = memcached (NULL, 0); } - array_init(return_value); + if (!intern->memc) { + // TODO: handle allocation fail + } + + memc_user_data = pecalloc (1, sizeof(*memc_user_data), is_persistent); + memc_user_data->serializer = MEMC_G(serializer_type); + memc_user_data->compression_type = MEMC_G(compression_type); + memc_user_data->compression_enabled = 1; + memc_user_data->store_retry_count = MEMC_G(store_retry_count); + memc_user_data->set_udf_flags = -1; + memc_user_data->is_persistent = is_persistent; + + memcached_set_user_data(intern->memc, memc_user_data); + + if (fci.size) { + if (!s_invoke_new_instance_cb(getThis(), &fci, &fci_cache, persistent_id) || EG(exception)) { + /* error calling or exception thrown from callback */ + if (plist_key) { + zend_string_release(plist_key); + } + /* + Setting intern->memc null prevents object destruction from freeing the memcached_st + We free it manually here because it might be persistent and has not been + registered to persistent_list yet + */ + php_memc_destroy(intern->memc, memc_user_data); + intern->memc = NULL; + return; + } + } - flags = memcached_result_flags(&result); - res_key = memcached_result_key_value(&result); - res_key_len = memcached_result_key_length(&result); - cas = memcached_result_cas(&result); + if (plist_key) { + zend_resource le; - add_assoc_stringl_ex(return_value, ZEND_STRL("key"), (char *) res_key, res_key_len); - add_assoc_zval_ex(return_value, ZEND_STRL("value"), &value); + le.type = php_memc_list_entry(); + le.ptr = intern->memc; - s_uint64_to_zval (&zv_cas, cas); - add_assoc_zval_ex(return_value, ZEND_STRL("cas"), &zv_cas); - add_assoc_long_ex(return_value, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); + GC_REFCOUNT(&le) = 1; - memcached_result_free(&result); + /* plist_key is not a persistent allocated key, thus we use str_update here */ + if (zend_hash_str_update_mem(&EG(persistent_list), plist_key->val, plist_key->len, &le, sizeof(le)) == NULL) { + zend_string_release(plist_key); + php_error_docref(NULL, E_ERROR, "could not register persistent entry"); + /* not reached */ + } + zend_string_release(plist_key); + } } /* }}} */ -/* {{{ Memcached::fetchAll() - Returns all the results from a previous delayed request */ -PHP_METHOD(Memcached, fetchAll) + + +static +void s_hash_to_keys(php_memc_keys_t *keys_out, HashTable *hash_in, zend_bool preserve_order, zval *return_value) { - const char *res_key = NULL; - size_t res_key_len = 0; - const char *payload = NULL; - size_t payload_len = 0; - uint32_t flags; - uint64_t cas = 0; - zval value, entry, zv_cas; - memcached_result_st result; - memcached_return status = MEMCACHED_SUCCESS; - MEMC_METHOD_INIT_VARS; + size_t idx = 0, alloc_count; + zval *zv; - if (zend_parse_parameters_none() == FAILURE) { + keys_out->num_valid_keys = 0; + + alloc_count = zend_hash_num_elements(hash_in); + if (!alloc_count) { return; } + keys_out->mkeys = ecalloc (alloc_count, sizeof (char *)); + keys_out->mkeys_len = ecalloc (alloc_count, sizeof (size_t)); + keys_out->strings = ecalloc (alloc_count, sizeof (zend_string *)); - MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; + ZEND_HASH_FOREACH_VAL(hash_in, zv) { + zend_string *key = zval_get_string(zv); - array_init(return_value); - memcached_result_create(intern->memc, &result); + if (preserve_order && return_value) { + add_assoc_null_ex(return_value, key->val, key->len); + } - while ((memcached_fetch_result(intern->memc, &result, &status)) != NULL) { + if (key->len > 0 && key->len < MEMCACHED_MAX_KEY) { + keys_out->mkeys[idx] = key->val; + keys_out->mkeys_len[idx] = key->len; - if (!s_memcached_result_to_zval(intern->memc, &result, &value)) { - memcached_result_free(&result); - zval_dtor(return_value); - intern->rescode = MEMC_RES_PAYLOAD_FAILURE; - RETURN_FALSE; + keys_out->strings[idx] = key; + idx++; + } + else { + zend_string_release (key); } - flags = memcached_result_flags(&result); - res_key = memcached_result_key_value(&result); - res_key_len = memcached_result_key_length(&result); - cas = memcached_result_cas(&result); + } ZEND_HASH_FOREACH_END(); - array_init(&entry); - add_assoc_stringl_ex(&entry, ZEND_STRL("key"), (char *)res_key, res_key_len); - add_assoc_zval_ex(&entry, ZEND_STRL("value"), &value); + if (!idx) { + efree (keys_out->mkeys); + efree (keys_out->mkeys_len); + efree (keys_out->strings); + } + keys_out->num_valid_keys = idx; +} - s_uint64_to_zval (&zv_cas, cas); - add_assoc_zval_ex(&entry, ZEND_STRL("cas"), &zv_cas); - add_assoc_long_ex(&entry, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); +static +void s_key_to_keys(php_memc_keys_t *keys_out, zend_string *key) +{ + zval zv_keys; - add_next_index_zval(return_value, &entry); - } + array_init (&zv_keys); + add_next_index_stringl (&zv_keys, key->val, key->len); - memcached_result_free(&result); + s_hash_to_keys(keys_out, Z_ARRVAL(zv_keys), 0, NULL); + zval_ptr_dtor(&zv_keys); +} - if (status != MEMCACHED_END && php_memc_handle_error(intern, status) < 0) { - zval_dtor(return_value); - RETURN_FALSE; +static +void s_clear_keys(php_memc_keys_t *keys) +{ + size_t i; + for (i = 0; i < keys->num_valid_keys; i++) { + zend_string_release (keys->strings[i]); } + efree(keys->strings); + efree(keys->mkeys); + efree(keys->mkeys_len); } -/* }}} */ -/* {{{ Memcached::set(string key, mixed value [, int expiration ]) - Sets the value for the given key */ -PHP_METHOD(Memcached, set) -{ - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_SET, 0); -} -/* }}} */ +typedef struct { + zend_bool extended; + zval *return_value; +} php_memc_get_ctx_t; -/* {{{ Memcached::setByKey(string server_key, string key, mixed value [, int expiration ]) - Sets the value for the given key on the server identified by the server key */ -PHP_METHOD(Memcached, setByKey) +static +zend_bool s_get_apply_fn(php_memc_object_t *intern, zend_string *key, zval *value, zval *cas, uint32_t flags, void *in_context) { - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_SET, 1); + php_memc_get_ctx_t *context = (php_memc_get_ctx_t *) in_context; + + if (context->extended) { + Z_TRY_ADDREF_P(value); + Z_TRY_ADDREF_P(cas); + + array_init (context->return_value); + add_assoc_zval (context->return_value, "value", value); + add_assoc_zval (context->return_value, "cas", cas); + add_assoc_long (context->return_value, "flags", (zend_long) MEMC_VAL_GET_USER_FLAGS(flags)); + } + else { + ZVAL_ZVAL(context->return_value, value, 1, 0); + } + return 0; /* Stop after one */ } -/* }}} */ -#ifdef HAVE_MEMCACHED_TOUCH -/* {{{ Memcached::touch(string key, [, int expiration ]) - Sets a new expiration for the given key */ -PHP_METHOD(Memcached, touch) +static +void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_TOUCH, 0); + php_memc_get_ctx_t context = {}; + php_memc_keys_t keys = {0}; + zend_long get_flags = 0; + zend_string *key; + zend_string *server_key = NULL; + zend_bool extended, mget_status; + memcached_return status = MEMCACHED_SUCCESS; + zend_fcall_info fci = empty_fcall_info; + zend_fcall_info_cache fcc = empty_fcall_info_cache; + MEMC_METHOD_INIT_VARS; + + if (by_key) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|f!l", &server_key, &key, &fci, &fcc, &get_flags) == FAILURE) { + return; + } + } else { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|f!l", &key, &fci, &fcc, &get_flags) == FAILURE) { + return; + } + } + + MEMC_METHOD_FETCH_OBJECT; + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); + + context.extended = (get_flags & MEMC_GET_EXTENDED); + + ZVAL_UNDEF(return_value); + context.return_value = return_value; + + s_key_to_keys(&keys, key); + mget_status = php_memc_mget_apply(intern, server_key, &keys, s_get_apply_fn, context.extended, &context); + s_clear_keys(&keys); + + if (!mget_status) { + if (s_memc_status_has_result_code(intern, MEMCACHED_NOTFOUND) && fci.size > 0) { + status = s_invoke_cache_callback(object, &fci, &fcc, key, return_value); + + if (!status) { + zval_ptr_dtor(return_value); + RETURN_FROM_GET; + } + } + } + + if (s_memc_status_has_error(intern)) { + zval_ptr_dtor(return_value); + RETURN_FROM_GET; + } } -/* }}} */ -/* {{{ Memcached::touchbyKey(string key, [, int expiration ]) - Sets a new expiration for the given key */ -PHP_METHOD(Memcached, touchByKey) +/* {{{ Memcached::get(string key [, mixed callback [, int get_flags = 0]) + Returns a value for the given key or false */ +PHP_METHOD(Memcached, get) { - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_TOUCH, 1); + php_memc_get_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); } /* }}} */ -#endif - -/* {{{ Memcached::setMulti(array items [, int expiration ]) - Sets the keys/values specified in the items array */ -PHP_METHOD(Memcached, setMulti) +/* {{{ Memcached::getByKey(string server_key, string key [, mixed callback [, int get_flags = 0]) + Returns a value for key from the server identified by the server key or false */ +PHP_METHOD(Memcached, getByKey) { - php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); + php_memc_get_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); } /* }}} */ -/* {{{ Memcached::setMultiByKey(string server_key, array items [, int expiration ]) - Sets the keys/values specified in the items array on the server identified by the given server key */ -PHP_METHOD(Memcached, setMultiByKey) +static +zend_bool s_get_multi_apply_fn(php_memc_object_t *intern, zend_string *key, zval *value, zval *cas, uint32_t flags, void *in_context) { - php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); -} -/* }}} */ + php_memc_get_ctx_t *context = (php_memc_get_ctx_t *) in_context; + + Z_TRY_ADDREF_P(value); + + if (context->extended) { + zval node; + + Z_TRY_ADDREF_P(cas); + + array_init (&node); + add_assoc_zval (&node, "value", value); + add_assoc_zval (&node, "cas", cas); + add_assoc_long (&node, "flags", (zend_long) MEMC_VAL_GET_USER_FLAGS(flags)); -#define PHP_MEMC_FAILOVER_RETRY \ - if (!by_key && retry < memc_user_data->store_retry_count) { \ - switch (intern->rescode) { \ - case MEMCACHED_HOST_LOOKUP_FAILURE: \ - case MEMCACHED_CONNECTION_FAILURE: \ - case MEMCACHED_CONNECTION_BIND_FAILURE: \ - case MEMCACHED_WRITE_FAILURE: \ - case MEMCACHED_READ_FAILURE: \ - case MEMCACHED_UNKNOWN_READ_FAILURE: \ - case MEMCACHED_PROTOCOL_ERROR: \ - case MEMCACHED_SERVER_ERROR: \ - case MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE: \ - case MEMCACHED_TIMEOUT: \ - case MEMCACHED_FAIL_UNIX_SOCKET: \ - case MEMCACHED_SERVER_MARKED_DEAD: \ - case MEMCACHED_SERVER_TEMPORARILY_DISABLED: \ - if (memcached_server_count(intern->memc) > 0) { \ - retry++; \ - intern->rescode = 0; \ - goto retry; \ - } \ - break; \ - } \ + add_assoc_zval_ex(context->return_value, key->val, key->len, &node); } + else { + add_assoc_zval_ex(context->return_value, key->val, key->len, value); + } + return 1; +} -/* {{{ -- php_memc_setMulti_impl */ -static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) +/* {{{ -- php_memc_getMulti_impl */ +static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { - zval *entries; + php_memc_get_ctx_t context; + php_memc_keys_t keys_out; + + zval *keys = NULL; zend_string *server_key = NULL; - time_t expiration = 0; - zval *value; - zend_string *skey, *str_key = NULL; - ulong num_key; - zend_string *payload; - uint32_t flags = 0; - uint32_t retry = 0; - memcached_return status; - char tmp_key[MEMCACHED_MAX_KEY]; - int tmp_len = 0; + zend_long flags = 0; MEMC_METHOD_INIT_VARS; + zend_bool with_cas, retval, preserve_order, extended; + if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa|ll", &server_key, - &entries, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa|l", &server_key, + &keys, &flags) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|ll", &entries, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|l", &keys, &flags) == FAILURE) { return; } } MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); - ZEND_HASH_FOREACH_KEY_VAL (Z_ARRVAL_P(entries), num_key, skey, value) { - if (skey) { - str_key = skey; - } else if (num_key || num_key == 0) { - /* Array keys are unsigned, but php integers are signed. - * Keys must be converted to signed strings that match - * php integers. */ - assert(sizeof(tmp_key) >= sizeof(ZEND_TOSTR(LONG_MIN))); - tmp_len = sprintf(tmp_key, "%ld", (long)num_key); - str_key = zend_string_init(tmp_key, tmp_len, 0); - } else { - continue; - } + array_init(return_value); - flags = 0; - if (memc_user_data->compression) { - MEMC_VAL_SET_FLAG(flags, MEMC_VAL_COMPRESSED); - } + preserve_order = (flags & MEMC_GET_PRESERVE_ORDER); + s_hash_to_keys(&keys_out, Z_ARRVAL_P(keys), preserve_order, return_value); - if (memc_user_data->set_udf_flags >= 0) { - MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) memc_user_data->set_udf_flags)); - } + context.extended = (flags & MEMC_GET_EXTENDED); + context.return_value = return_value; - payload = s_zval_to_payload(value, &flags, memc_user_data->serializer, memc_user_data->compression_type); - if (payload == NULL) { - intern->rescode = MEMC_RES_PAYLOAD_FAILURE; - if (!skey) { - zend_string_release(str_key); - } - RETURN_FALSE; - } + retval = php_memc_mget_apply(intern, server_key, &keys_out, s_get_multi_apply_fn, context.extended, &context); -retry: - if (!by_key) { - status = memcached_set(intern->memc, str_key->val, str_key->len, payload->val, payload->len, expiration, flags); - } else { - status = memcached_set_by_key(intern->memc, server_key->val, server_key->len, str_key->val, str_key->len, payload->val, payload->len, expiration, flags); - } + s_clear_keys(&keys_out); - if (php_memc_handle_error(intern, status) < 0) { - PHP_MEMC_FAILOVER_RETRY - if (!skey) { - zend_string_release(str_key); - } - zend_string_release(payload); - RETURN_FALSE; - } - if (!skey) { - zend_string_release(str_key); - } - zend_string_release(payload); - } ZEND_HASH_FOREACH_END(); + if (!retval && (s_memc_status_has_result_code(intern, MEMCACHED_NOTFOUND) || s_memc_status_has_result_code(intern, MEMCACHED_SOME_ERRORS))) { + return; + } - RETURN_TRUE; + if (!retval || EG(exception)) { + zval_dtor(return_value); + RETURN_FROM_GET; + } } /* }}} */ -/* {{{ Memcached::add(string key, mixed value [, int expiration ]) - Sets the value for the given key, failing if the key already exists */ -PHP_METHOD(Memcached, add) +/* {{{ Memcached::getMulti(array keys[, long flags = 0 ]) + Returns values for the given keys or false */ +PHP_METHOD(Memcached, getMulti) { - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_ADD, 0); + php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); } /* }}} */ -/* {{{ Memcached::addByKey(string server_key, string key, mixed value [, int expiration ]) - Sets the value for the given key on the server identified by the sever key, failing if the key already exists */ -PHP_METHOD(Memcached, addByKey) +/* {{{ Memcached::getMultiByKey(string server_key, array keys[, long flags = 0 ]) + Returns values for the given keys from the server identified by the server key or false */ +PHP_METHOD(Memcached, getMultiByKey) { - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_ADD, 1); + php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); } /* }}} */ -/* {{{ Memcached::append(string key, mixed value) - Appends the value to existing one for the key */ -PHP_METHOD(Memcached, append) +/* {{{ Memcached::getDelayed(array keys [, bool with_cas [, mixed callback ] ]) + Sends a request for the given keys and returns immediately */ +PHP_METHOD(Memcached, getDelayed) { - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_APPEND, 0); + php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); } /* }}} */ -/* {{{ Memcached::appendByKey(string server_key, string key, mixed value) - Appends the value to existing one for the key on the server identified by the server key */ -PHP_METHOD(Memcached, appendByKey) +/* {{{ Memcached::getDelayedByKey(string server_key, array keys [, bool with_cas [, mixed callback ] ]) + Sends a request for the given keys from the server identified by the server key and returns immediately */ +PHP_METHOD(Memcached, getDelayedByKey) { - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_APPEND, 1); + php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); } /* }}} */ -/* {{{ Memcached::prepend(string key, mixed value) - Prepends the value to existing one for the key */ -PHP_METHOD(Memcached, prepend) -{ - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_PREPEND, 0); -} -/* }}} */ -/* {{{ Memcached::prependByKey(string server_key, string key, mixed value) - Prepends the value to existing one for the key on the server identified by the server key */ -PHP_METHOD(Memcached, prependByKey) +static +void s_create_result_array(zend_string *key, zval *value, zval *cas, uint32_t flags, zval *return_value) { - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_PREPEND, 1); -} -/* }}} */ + Z_TRY_ADDREF_P(value); + Z_TRY_ADDREF_P(cas); -/* {{{ Memcached::replace(string key, mixed value [, int expiration ]) - Replaces the value for the given key, failing if the key doesn't exist */ -PHP_METHOD(Memcached, replace) -{ - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_REPLACE, 0); + add_assoc_stringl_ex(return_value, ZEND_STRL("key"), key->val, key->len); + add_assoc_zval_ex(return_value, ZEND_STRL("value"), value); + + add_assoc_zval_ex(return_value, ZEND_STRL("cas"), cas); + add_assoc_long_ex(return_value, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); } -/* }}} */ -/* {{{ Memcached::replaceByKey(string server_key, string key, mixed value [, int expiration ]) - Replaces the value for the given key on the server identified by the server key, failing if the key doesn't exist */ -PHP_METHOD(Memcached, replaceByKey) +static +zend_bool s_result_callback_apply(php_memc_object_t *intern, zend_string *key, zval *value, zval *cas, uint32_t flags, void *in_context) { - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_REPLACE, 1); + zend_bool status = 1; + + zval retval, zv_result; + php_memc_result_callback_ctx_t *context = (php_memc_result_callback_ctx_t *) in_context; + + array_init(&zv_result); + s_create_result_array(key, value, cas, flags, &zv_result); + + zend_fcall_info_argn(&context->fci, 2, context->object, &zv_result); + + context->fci.retval = &retval; + context->fci.param_count = 2; + + ZVAL_UNDEF(&retval); + if (zend_call_function(&context->fci, &context->fcc) == FAILURE) { + if (Z_TYPE(retval) != IS_UNDEF) { + zval_ptr_dtor(&retval); + } + php_error_docref(NULL, E_WARNING, "could not invoke result callback"); + status = 0; + } + + if (Z_TYPE(retval) != IS_UNDEF) { + zval_ptr_dtor(&retval); + } + + zend_fcall_info_args_clear(&context->fci, 2); + zval_ptr_dtor(&zv_result); + return status; } -/* }}} */ -/* {{{ -- php_memc_store_impl */ -static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool by_key) +/* {{{ -- php_memc_getDelayed_impl */ +static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { - zend_string *key; + php_memc_keys_t keys_out = {0}; + + zval *keys = NULL; zend_string *server_key = NULL; - zend_string *s_value; - zval s_zvalue; - zval *value; - zend_long expiration = 0; - zend_string *payload = NULL; - uint32_t flags = 0; - uint32_t retry = 0; - memcached_return status; + zend_bool with_cas = 0; + + zend_fcall_info fci = empty_fcall_info; + zend_fcall_info_cache fcc = empty_fcall_info_cache; + memcached_return status = MEMCACHED_SUCCESS; MEMC_METHOD_INIT_VARS; + if (by_key) { - if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSS", &server_key, &key, &s_value) == FAILURE) { - return; - } - value = &s_zvalue; - ZVAL_STR(value, s_value); - } else if (op == MEMC_OP_TOUCH) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|l", &server_key, &key, &expiration) == FAILURE) { - return; - } - } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSz|l", &server_key, &key, &value, &expiration) == FAILURE) { - return; - } - } + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|bf!", &server_key, + &keys, &with_cas, &fci, &fcc) == FAILURE) { + return; + } } else { - if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &key, &s_value) == FAILURE) { - return; - } - value = &s_zvalue; - ZVAL_STR(value, s_value); - } else if (op == MEMC_OP_TOUCH) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &key, &expiration) == FAILURE) { - return; - } - } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|l", &key, &value, &expiration) == FAILURE) { - return; - } + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|bf!", &keys, &with_cas, + &fci, &fcc) == FAILURE) { + return; } } MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; - - if (memc_user_data->compression) { - /* - * When compression is enabled, we cannot do appends/prepends because that would - * corrupt the compressed values. It is up to the user to fetch the value, - * append/prepend new data, and store it again. - */ - if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) { - php_error_docref(NULL, E_WARNING, "cannot append/prepend with compression turned on"); - return; - } - MEMC_VAL_SET_FLAG(flags, MEMC_VAL_COMPRESSED); - } + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); - /* - * php_memcached uses 16 bits internally to store type, compression and serialization info. - * We use 16 upper bits to store user defined flags. - */ - if (memc_user_data->set_udf_flags >= 0) { - MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) memc_user_data->set_udf_flags)); - } + s_hash_to_keys(&keys_out, Z_ARRVAL_P(keys), 0, NULL); - if (op == MEMC_OP_TOUCH) { -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000016 - if (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { - php_error_docref(NULL, E_WARNING, "using touch command with binary protocol is not recommended with libmemcached versions below 1.0.16"); - } -#endif + if (fci.size > 0) { + php_memc_result_callback_ctx_t context = { + getThis(), fci, fcc + }; + status = php_memc_mget_apply(intern, server_key, &keys_out, &s_result_callback_apply, with_cas, (void *) &context); } else { - payload = s_zval_to_payload(value, &flags, memc_user_data->serializer, memc_user_data->compression_type); - if (payload == NULL) { - intern->rescode = MEMC_RES_PAYLOAD_FAILURE; - RETURN_FALSE; - } + status = php_memc_mget_apply(intern, server_key, &keys_out, NULL, with_cas, NULL); } -retry: - switch (op) { - case MEMC_OP_SET: - if (!server_key) { - status = memcached_set(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags); - } else { - status = memcached_set_by_key(intern->memc, server_key->val, server_key->len, key->val, - key->len, payload->val, payload->len, expiration, flags); - } - break; -#ifdef HAVE_MEMCACHED_TOUCH - case MEMC_OP_TOUCH: - if (!server_key) { - status = memcached_touch(intern->memc, key->val, key->len, expiration); - } else { - status = memcached_touch_by_key(intern->memc, server_key->val, server_key->len, key->val, - key->len, expiration); - } - break; -#endif - case MEMC_OP_ADD: - if (!server_key) { - status = memcached_add(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags); - } else { - status = memcached_add_by_key(intern->memc, server_key->val, server_key->len, key->val, - key->len, payload->val, payload->len, expiration, flags); - } - break; - - case MEMC_OP_REPLACE: - if (!server_key) { - status = memcached_replace(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags); - } else { - status = memcached_replace_by_key(intern->memc, server_key->val, server_key->len, key->val, - key->len, payload->val, payload->len, expiration, flags); - } - break; - - case MEMC_OP_APPEND: - if (!server_key) { - status = memcached_append(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags); - } else { - status = memcached_append_by_key(intern->memc, server_key->val, server_key->len, key->val, - key->len, payload->val, payload->len, expiration, flags); - } - break; - - case MEMC_OP_PREPEND: - if (!server_key) { - status = memcached_prepend(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags); - } else { - status = memcached_prepend_by_key(intern->memc, server_key->val, server_key->len, key->val, - key->len, payload->val, payload->len, expiration, flags); - } - break; - default: - /* not reached */ - status = 0; - assert(0); - break; - } + s_clear_keys(&keys_out); + RETURN_BOOL(status); +} +/* }}} */ - if (php_memc_handle_error(intern, status) < 0) { - PHP_MEMC_FAILOVER_RETRY - RETVAL_FALSE; - } else { - RETVAL_TRUE; - } +static +zend_bool s_fetch_apply(php_memc_object_t *intern, zend_string *key, zval *value, zval *cas, uint32_t flags, void *in_context) +{ + zval *return_value = (zval *) in_context; + s_create_result_array(key, value, cas, flags, return_value); - if (payload) { - zend_string_release(payload); - } + return 0; // stop iterating after one } -/* }}} */ -/* {{{ -- php_memc_cas_impl */ -static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) +/* {{{ Memcached::fetch() + Returns the next result from a previous delayed request */ +PHP_METHOD(Memcached, fetch) { - zval *zv_cas; - uint64_t cas; - zend_string *key; - zend_string *server_key = NULL; - zval *value; - time_t expiration = 0; - zend_string *payload; + const char *res_key = NULL; + size_t res_key_len = 0; + const char *payload = NULL; + size_t payload_len = 0; uint32_t flags = 0; - memcached_return status; + uint64_t cas = 0; + zval value, zv_cas; + memcached_result_st result; + memcached_return status = MEMCACHED_SUCCESS; MEMC_METHOD_INIT_VARS; - if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "zSSz|ll", &zv_cas, &server_key, &key, - &value, &expiration) == FAILURE) { - return; - } - } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "zSz|ll", &zv_cas, &key, &value, - &expiration) == FAILURE) { - return; - } + if (zend_parse_parameters_none() == FAILURE) { + return; } MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); - cas = s_zval_to_uint64(zv_cas); + array_init(return_value); + status = php_memc_result_apply(intern, s_fetch_apply, return_value); - if (memc_user_data->compression) { - MEMC_VAL_SET_FLAG(flags, MEMC_VAL_COMPRESSED); + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + zval_ptr_dtor(return_value); + RETURN_FROM_GET; } +} +/* }}} */ - /* - * php_memcached uses 16 bits internally to store type, compression and serialization info. - * We use 16 upper bits to store user defined flags. - */ - if (memc_user_data->set_udf_flags >= 0) { - MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) memc_user_data->set_udf_flags)); - } +static +zend_bool s_fetch_all_apply(php_memc_object_t *intern, zend_string *key, zval *value, zval *cas, uint32_t flags, void *in_context) +{ + zval zv; + zval *return_value = (zval *) in_context; - payload = s_zval_to_payload(value, &flags, memc_user_data->serializer, memc_user_data->compression_type); - if (payload == NULL) { - intern->rescode = MEMC_RES_PAYLOAD_FAILURE; - RETURN_FALSE; - } + array_init (&zv); + s_create_result_array(key, value, cas, flags, &zv); - if (by_key) { - status = memcached_cas_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, payload->val, payload->len, expiration, flags, cas); - } else { - status = memcached_cas(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags, cas); + add_next_index_zval(return_value, &zv); + return 1; +} + +/* {{{ Memcached::fetchAll() + Returns all the results from a previous delayed request */ +PHP_METHOD(Memcached, fetchAll) +{ + const char *res_key = NULL; + size_t res_key_len = 0; + const char *payload = NULL; + size_t payload_len = 0; + uint32_t flags; + uint64_t cas = 0; + zval value, entry, zv_cas; + memcached_result_st result; + memcached_return status = MEMCACHED_SUCCESS; + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; } - zend_string_release(payload); - if (php_memc_handle_error(intern, status) < 0) { + MEMC_METHOD_FETCH_OBJECT; + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); + + array_init(return_value); + status = php_memc_result_apply(intern, s_fetch_all_apply, return_value); + + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + zval_dtor(return_value); RETURN_FALSE; } - - RETURN_TRUE; } /* }}} */ -/* {{{ Memcached::cas(double cas_token, string key, mixed value [, int expiration ]) - Sets the value for the given key, failing if the cas_token doesn't match the one in memcache */ -PHP_METHOD(Memcached, cas) +/* {{{ Memcached::set(string key, mixed value [, int expiration ]) + Sets the value for the given key */ +PHP_METHOD(Memcached, set) { - php_memc_cas_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_SET, 0); } /* }}} */ -/* {{{ Memcached::casByKey(double cas_token, string server_key, string key, mixed value [, int expiration ]) - Sets the value for the given key on the server identified by the server_key, failing if the cas_token doesn't match the one in memcache */ -PHP_METHOD(Memcached, casByKey) +/* {{{ Memcached::setByKey(string server_key, string key, mixed value [, int expiration ]) + Sets the value for the given key on the server identified by the server key */ +PHP_METHOD(Memcached, setByKey) { - php_memc_cas_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_SET, 1); } /* }}} */ -/* {{{ Memcached::delete(string key [, int time ]) - Deletes the given key */ -PHP_METHOD(Memcached, delete) +#ifdef HAVE_MEMCACHED_TOUCH +/* {{{ Memcached::touch(string key, [, int expiration ]) + Sets a new expiration for the given key */ +PHP_METHOD(Memcached, touch) { - php_memc_delete_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_TOUCH, 0); } /* }}} */ -/* {{{ Memcached::deleteMulti(array keys [, int time ]) - Deletes the given keys */ -PHP_METHOD(Memcached, deleteMulti) +/* {{{ Memcached::touchbyKey(string key, [, int expiration ]) + Sets a new expiration for the given key */ +PHP_METHOD(Memcached, touchByKey) { - php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_TOUCH, 1); } /* }}} */ +#endif -/* {{{ Memcached::deleteByKey(string server_key, string key [, int time ]) - Deletes the given key from the server identified by the server key */ -PHP_METHOD(Memcached, deleteByKey) + +/* {{{ Memcached::setMulti(array items [, int expiration ]) + Sets the keys/values specified in the items array */ +PHP_METHOD(Memcached, setMulti) { - php_memc_delete_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); + php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); } /* }}} */ -/* {{{ Memcached::deleteMultiByKey(array keys [, int time ]) - Deletes the given key from the server identified by the server key */ -PHP_METHOD(Memcached, deleteMultiByKey) +/* {{{ Memcached::setMultiByKey(string server_key, array items [, int expiration ]) + Sets the keys/values specified in the items array on the server identified by the given server key */ +PHP_METHOD(Memcached, setMultiByKey) { - php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); + php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); } /* }}} */ -/* {{{ -- php_memc_delete_impl */ -static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) +/* {{{ -- php_memc_setMulti_impl */ +static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { - zend_string *key, *server_key; + zval *entries; + zend_string *server_key = NULL; time_t expiration = 0; + zval *value; + zend_string *skey, *str_key = NULL; + ulong num_key; + zend_string *payload; + uint32_t flags = 0; + uint32_t retry = 0; memcached_return status; + char tmp_key[MEMCACHED_MAX_KEY]; + int tmp_len = 0; MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|l", &server_key, &key, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa|ll", &server_key, + &entries, &expiration) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &key, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|ll", &entries, &expiration) == FAILURE) { return; } - server_key = key; } MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; - - if (by_key) { - status = memcached_delete_by_key(intern->memc, server_key->val, server_key->len, key->val, - key->len, expiration); - } else { - status = memcached_delete(intern->memc, key->val, key->len, expiration); - } + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); - if (php_memc_handle_error(intern, status) < 0) { - RETURN_FALSE; - } + ZEND_HASH_FOREACH_KEY_VAL (Z_ARRVAL_P(entries), num_key, skey, value) { - RETURN_TRUE; -} -/* }}} */ + zend_string *str_key; -/* {{{ -- php_memc_deleteMulti_impl */ -static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) -{ - zval *entries; - zend_string *server_key = NULL; - time_t expiration = 0; - zval *entry; - - memcached_return status; - MEMC_METHOD_INIT_VARS; - - if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|l", &server_key, &entries, &expiration) == FAILURE) { - return; - } - } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|l", &entries, &expiration) == FAILURE) { - return; + if (skey) { + str_key = skey; } - } - - MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; + else { + char tmp_key[64]; - array_init(return_value); - ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P(entries), entry) { - if (Z_TYPE_P(entry) != IS_STRING) { - convert_to_string_ex(entry); + tmp_len = snprintf(tmp_key, sizeof(tmp_key) - 1, "%ld", (long)num_key); + str_key = zend_string_init(tmp_key, tmp_len, 0); } - if (Z_STRLEN_P(entry) == 0) { - continue; + if (!s_memc_write_zval (intern, MEMC_OP_SET, server_key, str_key, value, expiration)) { + php_error_docref(NULL, E_WARNING, "failed to set key %s", str_key->val); } - if (by_key) { - status = memcached_delete_by_key(intern->memc, server_key->val, server_key->len, Z_STRVAL_P(entry), Z_STRLEN_P(entry), expiration); - } else { - status = memcached_delete_by_key(intern->memc, Z_STRVAL_P(entry), Z_STRLEN_P(entry), Z_STRVAL_P(entry), Z_STRLEN_P(entry), expiration); + if (!skey) { + zend_string_release (str_key); } - - if (php_memc_handle_error(intern, status) < 0) { - add_assoc_long(return_value, Z_STRVAL_P(entry), status); - } else { - add_assoc_bool(return_value, Z_STRVAL_P(entry), 1); - } } ZEND_HASH_FOREACH_END(); - return; + RETURN_BOOL(!s_memc_status_has_error(intern)); } /* }}} */ -/* {{{ -- php_memc_incdec_impl */ -static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, zend_bool incr) +/* {{{ Memcached::add(string key, mixed value [, int expiration ]) + Sets the value for the given key, failing if the key already exists */ +PHP_METHOD(Memcached, add) { - zend_string *key, *server_key = NULL; - long offset = 1; - uint64_t value, initial = 0; - time_t expiry = 0; - memcached_return status; - int n_args = ZEND_NUM_ARGS(); - uint32_t retry = 0; - - MEMC_METHOD_INIT_VARS; - - if (!by_key) { - if (zend_parse_parameters(n_args, "S|lll", &key, &offset, &initial, &expiry) == FAILURE) { - return; - } - } else { - if (zend_parse_parameters(n_args, "SS|lll", &server_key, &key, &offset, &initial, &expiry) == FAILURE) { - return; - } - } - - MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; - - if (offset < 0) { - php_error_docref(NULL, E_WARNING, "offset has to be > 0"); - RETURN_FALSE; - } + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_ADD, 0); +} +/* }}} */ -retry: - if ((!by_key && n_args < 3) || (by_key && n_args < 4)) { - if (by_key) { - if (incr) { - status = memcached_increment_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, &value); - } else { - status = memcached_decrement_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, &value); - } - } else { - if (incr) { - status = memcached_increment(intern->memc, key->val, key->len, (unsigned int)offset, &value); - } else { - status = memcached_decrement(intern->memc, key->val, key->len, (unsigned int)offset, &value); - } - } - } else { - if (!memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { - php_error_docref(NULL, E_WARNING, "Initial value is only supported with binary protocol"); - RETURN_FALSE; - } - if (by_key) { - if (incr) { - status = memcached_increment_with_initial_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, initial, expiry, &value); - } else { - status = memcached_decrement_with_initial_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, initial, expiry, &value); - } - } else { - if (incr) { - status = memcached_increment_with_initial(intern->memc, key->val, key->len, (unsigned int)offset, initial, expiry, &value); - } else { - status = memcached_decrement_with_initial(intern->memc, key->val, key->len, (unsigned int)offset, initial, expiry, &value); - } - } - } +/* {{{ Memcached::addByKey(string server_key, string key, mixed value [, int expiration ]) + Sets the value for the given key on the server identified by the sever key, failing if the key already exists */ +PHP_METHOD(Memcached, addByKey) +{ + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_ADD, 1); +} +/* }}} */ - if (php_memc_handle_error(intern, status) < 0) { - PHP_MEMC_FAILOVER_RETRY - RETURN_FALSE; - } +/* {{{ Memcached::append(string key, mixed value) + Appends the value to existing one for the key */ +PHP_METHOD(Memcached, append) +{ + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_APPEND, 0); +} +/* }}} */ - RETURN_LONG((long)value); +/* {{{ Memcached::appendByKey(string server_key, string key, mixed value) + Appends the value to existing one for the key on the server identified by the server key */ +PHP_METHOD(Memcached, appendByKey) +{ + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_APPEND, 1); } /* }}} */ -/* {{{ Memcached::increment(string key [, int delta [, initial_value [, expiry time ] ] ]) - Increments the value for the given key by delta, defaulting to 1 */ -PHP_METHOD(Memcached, increment) +/* {{{ Memcached::prepend(string key, mixed value) + Prepends the value to existing one for the key */ +PHP_METHOD(Memcached, prepend) { - php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1); + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_PREPEND, 0); } /* }}} */ -/* {{{ Memcached::decrement(string key [, int delta [, initial_value [, expiry time ] ] ]) - Decrements the value for the given key by delta, defaulting to 1 */ -PHP_METHOD(Memcached, decrement) +/* {{{ Memcached::prependByKey(string server_key, string key, mixed value) + Prepends the value to existing one for the key on the server identified by the server key */ +PHP_METHOD(Memcached, prependByKey) { - php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0); + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_PREPEND, 1); } /* }}} */ -/* {{{ Memcached::decrementByKey(string server_key, string key [, int delta [, initial_value [, expiry time ] ] ]) - Decrements by server the value for the given key by delta, defaulting to 1 */ -PHP_METHOD(Memcached, decrementByKey) +/* {{{ Memcached::replace(string key, mixed value [, int expiration ]) + Replaces the value for the given key, failing if the key doesn't exist */ +PHP_METHOD(Memcached, replace) { - php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 0); + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_REPLACE, 0); } /* }}} */ -/* {{{ Memcached::increment(string server_key, string key [, int delta [, initial_value [, expiry time ] ] ]) - Increments by server the value for the given key by delta, defaulting to 1 */ -PHP_METHOD(Memcached, incrementByKey) +/* {{{ Memcached::replaceByKey(string server_key, string key, mixed value [, int expiration ]) + Replaces the value for the given key on the server identified by the server key, failing if the key doesn't exist */ +PHP_METHOD(Memcached, replaceByKey) { - php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 1); + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_REPLACE, 1); } /* }}} */ -/* {{{ Memcached::addServer(string hostname, int port [, int weight ]) - Adds the given memcache server to the list */ -PHP_METHOD(Memcached, addServer) +/* {{{ -- php_memc_store_impl */ +static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool by_key) { - zend_string *host; - long port, weight = 0; + zend_string *key; + zend_string *server_key = NULL; + zend_string *s_value; + zval s_zvalue; + zval *value = NULL; + zend_long expiration = 0; + zend_string *payload = NULL; + uint32_t flags = 0; + uint32_t retry = 0; memcached_return status; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sl|l", &host, &port, &weight) == FAILURE) { - return; + if (by_key) { + if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSS", &server_key, &key, &s_value) == FAILURE) { + return; + } + value = &s_zvalue; + ZVAL_STR(value, s_value); + } else if (op == MEMC_OP_TOUCH) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|l", &server_key, &key, &expiration) == FAILURE) { + return; + } + } else { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSz|l", &server_key, &key, &value, &expiration) == FAILURE) { + return; + } + } + } else { + if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &key, &s_value) == FAILURE) { + return; + } + value = &s_zvalue; + ZVAL_STR(value, s_value); + } else if (op == MEMC_OP_TOUCH) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &key, &expiration) == FAILURE) { + return; + } + } else { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|l", &key, &value, &expiration) == FAILURE) { + return; + } + } } MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000002 - if (host->val[0] == '/') { /* unix domain socket */ - status = memcached_server_add_unix_socket_with_weight(intern->memc, host->val, weight); - } else if (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_USE_UDP)) { - status = memcached_server_add_udp_with_weight(intern->memc, host->val, port, weight); - } else { - status = memcached_server_add_with_weight(intern->memc, host->val, port, weight); + if (memc_user_data->compression_enabled) { + /* + * When compression is enabled, we cannot do appends/prepends because that would + * corrupt the compressed values. It is up to the user to fetch the value, + * append/prepend new data, and store it again. + */ + if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) { + php_error_docref(NULL, E_WARNING, "cannot append/prepend with compression turned on"); + RETURN_NULL(); + } } -#else - status = memcached_server_add_with_weight(intern->memc, host->val, port, weight); + + + if (op == MEMC_OP_TOUCH) { +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000016 + if (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { + php_error_docref(NULL, E_WARNING, "using touch command with binary protocol is not recommended with libmemcached versions below 1.0.16"); + } #endif + } - if (php_memc_handle_error(intern, status) < 0) { + if (!s_memc_write_zval (intern, op, server_key, key, value, expiration)) { RETURN_FALSE; } - RETURN_TRUE; } /* }}} */ -/* {{{ Memcached::addServers(array servers) - Adds the given memcache servers to the server list */ -PHP_METHOD(Memcached, addServers) +/* {{{ -- php_memc_cas_impl */ +static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { - zval *servers; - zval *entry; - zval *z_host, *z_port, *z_weight = NULL; - uint32_t weight = 0; - HashPosition pos; - int entry_size, i = 0; - memcached_server_st *list = NULL; - memcached_return status; - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/", &servers) == FAILURE) { - return; - } - - MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; + zval *zv_cas; + uint64_t cas; + zend_string *key; + zend_string *server_key = NULL; + zval *value; + time_t expiration = 0; + zend_string *payload; + uint32_t flags = 0; + memcached_return status; + MEMC_METHOD_INIT_VARS; - ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P(servers), entry) { - if (Z_TYPE_P(entry) != IS_ARRAY) { - php_error_docref(NULL, E_WARNING, "server list entry #%d is not an array", i+1); - i++; - continue; + if (by_key) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zSSz|ll", &zv_cas, &server_key, &key, + &value, &expiration) == FAILURE) { + return; } + } else { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zSz|ll", &zv_cas, &key, &value, + &expiration) == FAILURE) { + return; + } + } - entry_size = zend_hash_num_elements(Z_ARRVAL_P(entry)); - - if (entry_size > 1) { - zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(entry), &pos); - - /* Check that we have a host */ - if ((z_host = zend_hash_get_current_data_ex(Z_ARRVAL_P(entry), &pos)) == NULL) { - php_error_docref(NULL, E_WARNING, "could not get server host for entry #%d", i+1); - i++; - continue; - } - - /* Check that we have a port */ - if (zend_hash_move_forward_ex(Z_ARRVAL_P(entry), &pos) == FAILURE || - (z_port = zend_hash_get_current_data_ex(Z_ARRVAL_P(entry), &pos)) == NULL) { - php_error_docref(NULL, E_WARNING, "could not get server port for entry #%d", i+1); - i++; - continue; - } - - convert_to_string_ex(z_host); - convert_to_long_ex(z_port); - - weight = 0; - if (entry_size > 2) { - /* Try to get weight */ - if (zend_hash_move_forward_ex(Z_ARRVAL_P(entry), &pos) == FAILURE || - (z_weight = zend_hash_get_current_data_ex(Z_ARRVAL_P(entry), &pos)) == NULL) { - php_error_docref(NULL, E_WARNING, "could not get server weight for entry #%d", i+1); - } + MEMC_METHOD_FETCH_OBJECT; + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); - convert_to_long_ex(z_weight); - weight = Z_LVAL_P(z_weight); - } + cas = s_zval_to_uint64(zv_cas); - list = memcached_server_list_append_with_weight(list, Z_STRVAL_P(z_host), - Z_LVAL_P(z_port), weight, &status); + payload = s_zval_to_payload(intern, value, &flags); + if (payload == NULL) { + intern->rescode = MEMC_RES_PAYLOAD_FAILURE; + RETURN_FALSE; + } - if (php_memc_handle_error(intern, status) == 0) { - i++; - continue; - } - } - i++; - /* catch-all for all errors */ - php_error_docref(NULL, E_WARNING, "could not add entry #%d to the server list", i+1); - } ZEND_HASH_FOREACH_END(); + if (by_key) { + status = memcached_cas_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, payload->val, payload->len, expiration, flags, cas); + } else { + status = memcached_cas(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags, cas); + } - status = memcached_server_push(intern->memc, list); - memcached_server_list_free(list); - if (php_memc_handle_error(intern, status) < 0) { + zend_string_release(payload); + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { RETURN_FALSE; } @@ -2076,351 +1997,725 @@ PHP_METHOD(Memcached, addServers) } /* }}} */ -/* {{{ Memcached::getServerList() - Returns the list of the memcache servers in use */ -PHP_METHOD(Memcached, getServerList) +/* {{{ Memcached::cas(double cas_token, string key, mixed value [, int expiration ]) + Sets the value for the given key, failing if the cas_token doesn't match the one in memcache */ +PHP_METHOD(Memcached, cas) { - memcached_server_function callbacks[1]; - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - MEMC_METHOD_FETCH_OBJECT; - - callbacks[0] = s_server_cursor_list_servers_cb; - array_init(return_value); - memcached_server_cursor(intern->memc, callbacks, return_value, 1); + php_memc_cas_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); } /* }}} */ -/* {{{ Memcached::getServerByKey(string server_key) - Returns the server identified by the given server key */ -PHP_METHOD(Memcached, getServerByKey) +/* {{{ Memcached::casByKey(double cas_token, string server_key, string key, mixed value [, int expiration ]) + Sets the value for the given key on the server identified by the server_key, failing if the cas_token doesn't match the one in memcache */ +PHP_METHOD(Memcached, casByKey) { - zend_string *server_key; - php_memcached_instance_st server_instance; - memcached_return error; - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &server_key) == FAILURE) { - return; - } - - MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; - - server_instance = memcached_server_by_key(intern->memc, server_key->val, server_key->len, &error); - if (server_instance == NULL) { - php_memc_handle_error(intern, error); - RETURN_FALSE; - } - - array_init(return_value); - add_assoc_string(return_value, "host", (char*) memcached_server_name(server_instance)); - add_assoc_long(return_value, "port", memcached_server_port(server_instance)); - add_assoc_long(return_value, "weight", 0); + php_memc_cas_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); } /* }}} */ -/* {{{ Memcached::resetServerList() - Reset the server list in use */ -PHP_METHOD(Memcached, resetServerList) +/* {{{ Memcached::delete(string key [, int time ]) + Deletes the given key */ +PHP_METHOD(Memcached, delete) { - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - MEMC_METHOD_FETCH_OBJECT; - - memcached_servers_reset(intern->memc); - RETURN_TRUE; + php_memc_delete_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); } /* }}} */ -/* {{{ Memcached::quit() - Close any open connections */ -PHP_METHOD(Memcached, quit) +/* {{{ Memcached::deleteMulti(array keys [, int time ]) + Deletes the given keys */ +PHP_METHOD(Memcached, deleteMulti) { - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - MEMC_METHOD_FETCH_OBJECT; - - memcached_quit(intern->memc); - RETURN_TRUE; + php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); } /* }}} */ -/* {{{ Memcached::flushBuffers() - Flush and senf buffered commands */ -PHP_METHOD(Memcached, flushBuffers) +/* {{{ Memcached::deleteByKey(string server_key, string key [, int time ]) + Deletes the given key from the server identified by the server key */ +PHP_METHOD(Memcached, deleteByKey) { - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - MEMC_METHOD_FETCH_OBJECT; - RETURN_BOOL(memcached_flush_buffers(intern->memc) == MEMCACHED_SUCCESS); + php_memc_delete_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); } /* }}} */ -#ifdef HAVE_LIBMEMCACHED_CHECK_CONFIGURATION -/* {{{ Memcached::getLastErrorMessage() - Returns the last error message that occurred */ -PHP_METHOD(Memcached, getLastErrorMessage) +/* {{{ Memcached::deleteMultiByKey(array keys [, int time ]) + Deletes the given key from the server identified by the server key */ +PHP_METHOD(Memcached, deleteMultiByKey) { - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - MEMC_METHOD_FETCH_OBJECT; - - RETURN_STRING(memcached_last_error_message(intern->memc)); + php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); } /* }}} */ -/* {{{ Memcached::getLastErrorCode() - Returns the last error code that occurred */ -PHP_METHOD(Memcached, getLastErrorCode) +/* {{{ -- php_memc_delete_impl */ +static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { + zend_string *key, *server_key; + time_t expiration = 0; + memcached_return status; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters_none() == FAILURE) { - return; + if (by_key) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|l", &server_key, &key, &expiration) == FAILURE) { + return; + } + } else { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &key, &expiration) == FAILURE) { + return; + } + server_key = key; } MEMC_METHOD_FETCH_OBJECT; + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); - RETURN_LONG(memcached_last_error(intern->memc)); + if (by_key) { + status = memcached_delete_by_key(intern->memc, server_key->val, server_key->len, key->val, + key->len, expiration); + } else { + status = memcached_delete(intern->memc, key->val, key->len, expiration); + } + + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + RETURN_FALSE; + } + + RETURN_TRUE; } /* }}} */ -/* {{{ Memcached::getLastErrorErrno() - Returns the last error errno that occurred */ -PHP_METHOD(Memcached, getLastErrorErrno) +/* {{{ -- php_memc_deleteMulti_impl */ +static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { + zval *entries; + zend_string *server_key = NULL; + time_t expiration = 0; + zval *entry; + + memcached_return status; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters_none() == FAILURE) { - return; + if (by_key) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|l", &server_key, &entries, &expiration) == FAILURE) { + return; + } + } else { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|l", &entries, &expiration) == FAILURE) { + return; + } } MEMC_METHOD_FETCH_OBJECT; - - RETURN_LONG(memcached_last_error_errno(intern->memc)); -} -/* }}} */ -#endif - -/* {{{ Memcached::getLastDisconnectedServer() - Returns the last disconnected server - Was added in 0.34 according to libmemcached's Changelog */ -PHP_METHOD(Memcached, getLastDisconnectedServer) -{ - php_memcached_instance_st server_instance; - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - MEMC_METHOD_FETCH_OBJECT; - - server_instance = memcached_server_get_last_disconnect(intern->memc); - if (server_instance == NULL) { - RETURN_FALSE; - } + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); array_init(return_value); - add_assoc_string(return_value, "host", (char*) memcached_server_name(server_instance)); - add_assoc_long(return_value, "port", memcached_server_port(server_instance)); -} -/* }}} */ - -#include - -static -zend_bool s_long_value(const char *str, zend_long *value) -{ - char *end = (char *) str; - - errno = 0; - *value = strtol(str, &end, 10); - - if (errno || str == end || *end != '\0') { - return 0; - } - return 1; -} - -static -zend_bool s_double_value(const char *str, double *value) -{ - char *end = (char *) str; - - errno = 0; - *value = strtod(str, &end); - - if (errno || str == end || *end != '\0') { - return 0; - } - return 1; -} - -static -memcached_return s_stat_execute_cb (php_memcached_instance_st instance, const char *key, size_t key_length, const char *value, size_t value_length, void *context) -{ - char *server_key; - size_t server_key_len; - zend_long long_val; - double d_val; - char *buffer; - - zval *return_value = (zval *) context; - zval *server_values; + ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P(entries), entry) { + if (Z_TYPE_P(entry) != IS_STRING) { + convert_to_string_ex(entry); + } - server_key_len = spprintf (&server_key, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance)); - server_values = zend_hash_str_find(Z_ARRVAL_P(return_value), server_key, server_key_len); + if (Z_STRLEN_P(entry) == 0) { + continue; + } - if (!server_values) { - zval zv; - array_init(&zv); + if (by_key) { + status = memcached_delete_by_key(intern->memc, server_key->val, server_key->len, Z_STRVAL_P(entry), Z_STRLEN_P(entry), expiration); + } else { + status = memcached_delete_by_key(intern->memc, Z_STRVAL_P(entry), Z_STRLEN_P(entry), Z_STRVAL_P(entry), Z_STRLEN_P(entry), expiration); + } - server_values = &zv; - add_assoc_zval_ex(return_value, server_key, server_key_len, server_values); - } - spprintf (&buffer, 0, "%.*s", value_length, value); + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + add_assoc_long(return_value, Z_STRVAL_P(entry), status); + } else { + add_assoc_bool(return_value, Z_STRVAL_P(entry), 1); + } + } ZEND_HASH_FOREACH_END(); - /* Check type */ - if (s_long_value (buffer, &long_val)) { - add_assoc_long(server_values, key, long_val); - } - else if (s_double_value (buffer, &d_val)) { - add_assoc_double(server_values, key, d_val); - } - else { - add_assoc_stringl_ex(server_values, key, key_length, value, value_length); - } - efree (buffer); - efree (server_key); - return MEMCACHED_SUCCESS; + return; } +/* }}} */ -/* {{{ Memcached::getStats() - Returns statistics for the memcache servers */ -PHP_METHOD(Memcached, getStats) +/* {{{ -- php_memc_incdec_impl */ +static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, zend_bool incr) { + zend_string *key, *server_key = NULL; + long offset = 1; + uint64_t value = UINT64_MAX, initial = 0; + time_t expiry = 0; memcached_return status; + int n_args = ZEND_NUM_ARGS(); + MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters_none() == FAILURE) { - return; + if (!by_key) { + if (zend_parse_parameters(n_args, "S|lll", &key, &offset, &initial, &expiry) == FAILURE) { + return; + } + } else { + if (zend_parse_parameters(n_args, "SS|lll", &server_key, &key, &offset, &initial, &expiry) == FAILURE) { + return; + } } MEMC_METHOD_FETCH_OBJECT; + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); - array_init(return_value); - status = memcached_stat_execute(intern->memc, NULL, s_stat_execute_cb, return_value); - if (php_memc_handle_error(intern, status) < 0) { - zval_ptr_dtor(return_value); + if (offset < 0) { + php_error_docref(NULL, E_WARNING, "offset has to be > 0"); RETURN_FALSE; } -} -/* }}} */ -/* {{{ Memcached::getVersion() - Returns the version of each memcached server in the pool */ -PHP_METHOD(Memcached, getVersion) -{ - memcached_return rc; - memcached_server_function callbacks[1]; - MEMC_METHOD_INIT_VARS; + if ((!by_key && n_args < 3) || (by_key && n_args < 4)) { + if (by_key) { + if (incr) { + status = memcached_increment_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, &value); + } else { + status = memcached_decrement_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, &value); + } + } else { + if (incr) { + status = memcached_increment(intern->memc, key->val, key->len, (unsigned int)offset, &value); + } else { + status = memcached_decrement(intern->memc, key->val, key->len, (unsigned int)offset, &value); + } + } - if (zend_parse_parameters_none() == FAILURE) { - return; - } + } else { + zend_long retries = memc_user_data->store_retry_count; - MEMC_METHOD_FETCH_OBJECT; +retry_inc_dec: + if (!memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { + php_error_docref(NULL, E_WARNING, "Initial value is only supported with binary protocol"); + RETURN_FALSE; + } + if (by_key) { + if (incr) { + status = memcached_increment_with_initial_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, initial, expiry, &value); + } else { + status = memcached_decrement_with_initial_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, initial, expiry, &value); + } + } else { + if (incr) { + status = memcached_increment_with_initial(intern->memc, key->val, key->len, (unsigned int)offset, initial, expiry, &value); + } else { + status = memcached_decrement_with_initial(intern->memc, key->val, key->len, (unsigned int)offset, initial, expiry, &value); + } + } + if (s_should_retry_write(intern, status) && retries-- > 0) { + goto retry_inc_dec; + } + } - rc = memcached_version(intern->memc); - if (php_memc_handle_error(intern, rc) < 0) { + if (value == UINT64_MAX) { RETURN_FALSE; } - callbacks[0] = s_server_cursor_version_cb; - - array_init(return_value); - rc = memcached_server_cursor(intern->memc, callbacks, return_value, 1); - if (php_memc_handle_error(intern, rc) < 0) { - zval_dtor(return_value); + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { RETURN_FALSE; } + + RETURN_LONG((long)value); } /* }}} */ -/* {{{ Memcached::getAllKeys() - Returns the keys stored on all the servers */ -static -memcached_return s_dump_keys_cb(const memcached_st *ptr, const char *key, size_t key_length, void *in_context) +/* {{{ Memcached::increment(string key [, int delta [, initial_value [, expiry time ] ] ]) + Increments the value for the given key by delta, defaulting to 1 */ +PHP_METHOD(Memcached, increment) { - zval *return_value = (zval*) in_context; - add_next_index_stringl(return_value, key, key_length); - - return MEMCACHED_SUCCESS; + php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1); } +/* }}} */ -PHP_METHOD(Memcached, getAllKeys) +/* {{{ Memcached::decrement(string key [, int delta [, initial_value [, expiry time ] ] ]) + Decrements the value for the given key by delta, defaulting to 1 */ +PHP_METHOD(Memcached, decrement) { - memcached_return rc; - memcached_dump_func callback[1]; - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - callback[0] = s_dump_keys_cb; - MEMC_METHOD_FETCH_OBJECT; + php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0); +} +/* }}} */ - array_init(return_value); +/* {{{ Memcached::decrementByKey(string server_key, string key [, int delta [, initial_value [, expiry time ] ] ]) + Decrements by server the value for the given key by delta, defaulting to 1 */ +PHP_METHOD(Memcached, decrementByKey) +{ + php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 0); +} +/* }}} */ - rc = memcached_dump(intern->memc, callback, return_value, 1); - if (php_memc_handle_error(intern, rc) < 0) { - zval_dtor(return_value); - RETURN_FALSE; - } +/* {{{ Memcached::increment(string server_key, string key [, int delta [, initial_value [, expiry time ] ] ]) + Increments by server the value for the given key by delta, defaulting to 1 */ +PHP_METHOD(Memcached, incrementByKey) +{ + php_memc_incdec_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 1); } /* }}} */ -/* {{{ Memcached::flush([ int delay ]) - Flushes the data on all the servers */ -static PHP_METHOD(Memcached, flush) +/* {{{ Memcached::addServer(string hostname, int port [, int weight ]) + Adds the given memcache server to the list */ +PHP_METHOD(Memcached, addServer) { - time_t delay = 0; + zend_string *host; + long port, weight = 0; memcached_return status; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &delay) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sl|l", &host, &port, &weight) == FAILURE) { return; } MEMC_METHOD_FETCH_OBJECT; intern->rescode = MEMCACHED_SUCCESS; - status = memcached_flush(intern->memc, delay); - if (php_memc_handle_error(intern, status) < 0) { +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000002 + if (host->val[0] == '/') { /* unix domain socket */ + status = memcached_server_add_unix_socket_with_weight(intern->memc, host->val, weight); + } else if (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_USE_UDP)) { + status = memcached_server_add_udp_with_weight(intern->memc, host->val, port, weight); + } else { + status = memcached_server_add_with_weight(intern->memc, host->val, port, weight); + } +#else + status = memcached_server_add_with_weight(intern->memc, host->val, port, weight); +#endif + + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + RETURN_FALSE; + } + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ Memcached::addServers(array servers) + Adds the given memcache servers to the server list */ +PHP_METHOD(Memcached, addServers) +{ + zval *servers; + zval *entry; + zval *z_host, *z_port, *z_weight = NULL; + uint32_t weight = 0; + HashPosition pos; + int entry_size, i = 0; + memcached_server_st *list = NULL; + memcached_return status; + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/", &servers) == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); + + ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P(servers), entry) { + if (Z_TYPE_P(entry) != IS_ARRAY) { + php_error_docref(NULL, E_WARNING, "server list entry #%d is not an array", i+1); + i++; + continue; + } + + entry_size = zend_hash_num_elements(Z_ARRVAL_P(entry)); + + if (entry_size > 1) { + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(entry), &pos); + + /* Check that we have a host */ + if ((z_host = zend_hash_get_current_data_ex(Z_ARRVAL_P(entry), &pos)) == NULL) { + php_error_docref(NULL, E_WARNING, "could not get server host for entry #%d", i+1); + i++; + continue; + } + + /* Check that we have a port */ + if (zend_hash_move_forward_ex(Z_ARRVAL_P(entry), &pos) == FAILURE || + (z_port = zend_hash_get_current_data_ex(Z_ARRVAL_P(entry), &pos)) == NULL) { + php_error_docref(NULL, E_WARNING, "could not get server port for entry #%d", i+1); + i++; + continue; + } + + convert_to_string_ex(z_host); + convert_to_long_ex(z_port); + + weight = 0; + if (entry_size > 2) { + /* Try to get weight */ + if (zend_hash_move_forward_ex(Z_ARRVAL_P(entry), &pos) == FAILURE || + (z_weight = zend_hash_get_current_data_ex(Z_ARRVAL_P(entry), &pos)) == NULL) { + php_error_docref(NULL, E_WARNING, "could not get server weight for entry #%d", i+1); + } + + convert_to_long_ex(z_weight); + weight = Z_LVAL_P(z_weight); + } + + list = memcached_server_list_append_with_weight(list, Z_STRVAL_P(z_host), + Z_LVAL_P(z_port), weight, &status); + + if (s_memc_status_handle_result_code(intern, status) == SUCCESS) { + i++; + continue; + } + } + i++; + /* catch-all for all errors */ + php_error_docref(NULL, E_WARNING, "could not add entry #%d to the server list", i+1); + } ZEND_HASH_FOREACH_END(); + + status = memcached_server_push(intern->memc, list); + memcached_server_list_free(list); + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + RETURN_FALSE; + } + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ Memcached::getServerList() + Returns the list of the memcache servers in use */ +PHP_METHOD(Memcached, getServerList) +{ + memcached_server_function callbacks[1]; + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + + callbacks[0] = s_server_cursor_list_servers_cb; + array_init(return_value); + memcached_server_cursor(intern->memc, callbacks, return_value, 1); +} +/* }}} */ + +/* {{{ Memcached::getServerByKey(string server_key) + Returns the server identified by the given server key */ +PHP_METHOD(Memcached, getServerByKey) +{ + zend_string *server_key; + php_memcached_instance_st server_instance; + memcached_return error; + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &server_key) == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); + + server_instance = memcached_server_by_key(intern->memc, server_key->val, server_key->len, &error); + if (server_instance == NULL) { + s_memc_status_handle_result_code(intern, error); + RETURN_FALSE; + } + + array_init(return_value); + add_assoc_string(return_value, "host", (char*) memcached_server_name(server_instance)); + add_assoc_long(return_value, "port", memcached_server_port(server_instance)); + add_assoc_long(return_value, "weight", 0); +} +/* }}} */ + +/* {{{ Memcached::resetServerList() + Reset the server list in use */ +PHP_METHOD(Memcached, resetServerList) +{ + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + + memcached_servers_reset(intern->memc); + RETURN_TRUE; +} +/* }}} */ + +/* {{{ Memcached::quit() + Close any open connections */ +PHP_METHOD(Memcached, quit) +{ + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + + memcached_quit(intern->memc); + RETURN_TRUE; +} +/* }}} */ + +/* {{{ Memcached::flushBuffers() + Flush and senf buffered commands */ +PHP_METHOD(Memcached, flushBuffers) +{ + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + RETURN_BOOL(memcached_flush_buffers(intern->memc) == MEMCACHED_SUCCESS); +} +/* }}} */ + +#ifdef HAVE_LIBMEMCACHED_CHECK_CONFIGURATION +/* {{{ Memcached::getLastErrorMessage() + Returns the last error message that occurred */ +PHP_METHOD(Memcached, getLastErrorMessage) +{ + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + + RETURN_STRING(memcached_last_error_message(intern->memc)); +} +/* }}} */ + +/* {{{ Memcached::getLastErrorCode() + Returns the last error code that occurred */ +PHP_METHOD(Memcached, getLastErrorCode) +{ + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + + RETURN_LONG(memcached_last_error(intern->memc)); +} +/* }}} */ + +/* {{{ Memcached::getLastErrorErrno() + Returns the last error errno that occurred */ +PHP_METHOD(Memcached, getLastErrorErrno) +{ + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + + RETURN_LONG(memcached_last_error_errno(intern->memc)); +} +/* }}} */ +#endif + +/* {{{ Memcached::getLastDisconnectedServer() + Returns the last disconnected server + Was added in 0.34 according to libmemcached's Changelog */ +PHP_METHOD(Memcached, getLastDisconnectedServer) +{ + php_memcached_instance_st server_instance; + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + + server_instance = memcached_server_get_last_disconnect(intern->memc); + if (server_instance == NULL) { + RETURN_FALSE; + } + + array_init(return_value); + add_assoc_string(return_value, "host", (char*) memcached_server_name(server_instance)); + add_assoc_long(return_value, "port", memcached_server_port(server_instance)); +} +/* }}} */ + + + +static +zend_bool s_long_value(const char *str, zend_long *value) +{ + char *end = (char *) str; + + errno = 0; + *value = strtol(str, &end, 10); + + if (errno || str == end || *end != '\0') { + return 0; + } + return 1; +} + +static +zend_bool s_double_value(const char *str, double *value) +{ + char *end = (char *) str; + + errno = 0; + *value = strtod(str, &end); + + if (errno || str == end || *end != '\0') { + return 0; + } + return 1; +} + +static +memcached_return s_stat_execute_cb (php_memcached_instance_st instance, const char *key, size_t key_length, const char *value, size_t value_length, void *context) +{ + char *server_key; + size_t server_key_len; + zend_long long_val; + double d_val; + char *buffer; + + zval *return_value = (zval *) context; + zval *server_values; + + server_key_len = spprintf (&server_key, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance)); + server_values = zend_hash_str_find(Z_ARRVAL_P(return_value), server_key, server_key_len); + + if (!server_values) { + zval zv; + array_init(&zv); + + server_values = &zv; + add_assoc_zval_ex(return_value, server_key, server_key_len, server_values); + } + + spprintf (&buffer, 0, "%.*s", value_length, value); + + /* Check type */ + if (s_long_value (buffer, &long_val)) { + add_assoc_long(server_values, key, long_val); + } + else if (s_double_value (buffer, &d_val)) { + add_assoc_double(server_values, key, d_val); + } + else { + add_assoc_stringl_ex(server_values, key, key_length, value, value_length); + } + efree (buffer); + efree (server_key); + return MEMCACHED_SUCCESS; +} + +/* {{{ Memcached::getStats() + Returns statistics for the memcache servers */ +PHP_METHOD(Memcached, getStats) +{ + memcached_return status; + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + + array_init(return_value); + status = memcached_stat_execute(intern->memc, NULL, s_stat_execute_cb, return_value); + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + zval_ptr_dtor(return_value); + RETURN_FALSE; + } +} +/* }}} */ + +/* {{{ Memcached::getVersion() + Returns the version of each memcached server in the pool */ +PHP_METHOD(Memcached, getVersion) +{ + memcached_return status; + memcached_server_function callbacks[1]; + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + + status = memcached_version(intern->memc); + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + RETURN_FALSE; + } + + callbacks[0] = s_server_cursor_version_cb; + + array_init(return_value); + status = memcached_server_cursor(intern->memc, callbacks, return_value, 1); + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + zval_dtor(return_value); + RETURN_FALSE; + } +} +/* }}} */ + +/* {{{ Memcached::getAllKeys() + Returns the keys stored on all the servers */ +static +memcached_return s_dump_keys_cb(const memcached_st *ptr, const char *key, size_t key_length, void *in_context) +{ + zval *return_value = (zval*) in_context; + add_next_index_stringl(return_value, key, key_length); + + return MEMCACHED_SUCCESS; +} + +PHP_METHOD(Memcached, getAllKeys) +{ + memcached_return rc; + memcached_dump_func callback[1]; + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + callback[0] = s_dump_keys_cb; + MEMC_METHOD_FETCH_OBJECT; + + array_init(return_value); + + rc = memcached_dump(intern->memc, callback, return_value, 1); + if (s_memc_status_handle_result_code(intern, rc) == FAILURE) { + zval_dtor(return_value); + RETURN_FALSE; + } +} +/* }}} */ + +/* {{{ Memcached::flush([ int delay ]) + Flushes the data on all the servers */ +static PHP_METHOD(Memcached, flush) +{ + time_t delay = 0; + memcached_return status; + MEMC_METHOD_INIT_VARS; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &delay) == FAILURE) { + return; + } + + MEMC_METHOD_FETCH_OBJECT; + intern->rescode = MEMCACHED_SUCCESS; + + status = memcached_flush(intern->memc, delay); + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { RETURN_FALSE; } @@ -2448,7 +2743,7 @@ static PHP_METHOD(Memcached, getOption) RETURN_LONG(memc_user_data->compression_type); case MEMC_OPT_COMPRESSION: - RETURN_BOOL(memc_user_data->compression); + RETURN_BOOL(memc_user_data->compression_enabled); case MEMC_OPT_PREFIX_KEY: { @@ -2507,7 +2802,7 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) switch (option) { case MEMC_OPT_COMPRESSION: convert_to_long(value); - memc_user_data->compression = Z_LVAL_P(value) ? 1 : 0; + memc_user_data->compression_enabled = Z_LVAL_P(value) ? 1 : 0; break; case MEMC_OPT_COMPRESSION_TYPE: @@ -2557,7 +2852,7 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) convert_to_long(value); rc = memcached_behavior_set(intern->memc, flag, (uint64_t) Z_LVAL_P(value)); - if (php_memc_handle_error(intern, rc) < 0) { + if (s_memc_status_handle_result_code(intern, rc) == FAILURE) { php_error_docref(NULL, E_WARNING, "error setting memcached option: %s", memcached_strerror (intern->memc, rc)); return 0; } @@ -2652,7 +2947,7 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) } } - if (php_memc_handle_error(intern, rc) < 0) { + if (s_memc_status_handle_result_code(intern, rc) == FAILURE) { php_error_docref(NULL, E_WARNING, "error setting memcached option: %s", memcached_strerror (intern->memc, rc)); return 0; } @@ -2751,7 +3046,7 @@ PHP_METHOD(Memcached, setBucket) rc = memcached_bucket_set (intern->memc, server_map, forward_map, (uint32_t) server_map_len, replicas); - if (php_memc_handle_error(intern, rc) < 0) { + if (s_memc_status_handle_result_code(intern, rc) == FAILURE) { retval = 0;; } @@ -2790,546 +3085,286 @@ static PHP_METHOD(Memcached, setOptions) zval copy; ZVAL_DUP(©, value); - if (!php_memc_set_option(intern, (long) key_index, ©)) { - ok = 0; - } - - zval_dtor(©); - } - } ZEND_HASH_FOREACH_END(); - - RETURN_BOOL(ok); -} -/* }}} */ - -/* {{{ Memcached::setOption(int option, mixed value) - Sets the value for the given option constant */ -static PHP_METHOD(Memcached, setOption) -{ - long option; - zval *value; - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "lz/", &option, &value) == FAILURE) { - return; - } - - MEMC_METHOD_FETCH_OBJECT; - - RETURN_BOOL(php_memc_set_option(intern, option, value)); -} -/* }}} */ - -#ifdef HAVE_MEMCACHED_SASL -/* {{{ Memcached::setSaslAuthData(string user, string pass) - Sets sasl credentials */ -static PHP_METHOD(Memcached, setSaslAuthData) -{ - MEMC_METHOD_INIT_VARS; - memcached_return status; - zend_string *user, *pass; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &user, &pass) == FAILURE) { - return; - } - - if (!php_memc_init_sasl_if_needed()) { - RETURN_FALSE; - } - - MEMC_METHOD_FETCH_OBJECT; - - if (!memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { - php_error_docref(NULL, E_WARNING, "SASL is only supported with binary protocol"); - RETURN_FALSE; - } - memc_user_data->has_sasl_data = 1; - status = memcached_set_sasl_auth_data(intern->memc, user->val, pass->val); - - if (php_memc_handle_error(intern, status) < 0) { - RETURN_FALSE; - } - RETURN_TRUE; -} -/* }}} */ -#endif /* HAVE_MEMCACHED_SASL */ - -/* {{{ Memcached::getResultCode() - Returns the result code from the last operation */ -static PHP_METHOD(Memcached, getResultCode) -{ - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - MEMC_METHOD_FETCH_OBJECT; - - RETURN_LONG(intern->rescode); -} -/* }}} */ - -/* {{{ Memcached::getResultMessage() - Returns the result message from the last operation */ -static PHP_METHOD(Memcached, getResultMessage) -{ - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - MEMC_METHOD_FETCH_OBJECT; - - switch (intern->rescode) { - case MEMC_RES_PAYLOAD_FAILURE: - RETURN_STRING("PAYLOAD FAILURE"); - break; - - case MEMCACHED_ERRNO: - case MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE: - case MEMCACHED_UNKNOWN_READ_FAILURE: - if (intern->memc_errno) { - zend_string *str = strpprintf(0, "%s: %s", - memcached_strerror(intern->memc, (memcached_return)intern->rescode), strerror(intern->memc_errno)); - RETURN_STR(str); - } - /* Fall through */ - default: - RETURN_STRING(memcached_strerror(intern->memc, (memcached_return)intern->rescode)); - break; - } - -} -/* }}} */ - -/* {{{ Memcached::isPersistent() - Returns the true if instance uses a persistent connection */ -static PHP_METHOD(Memcached, isPersistent) -{ - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - MEMC_METHOD_FETCH_OBJECT; - - RETURN_BOOL(memc_user_data->is_persistent); -} -/* }}} */ - -/* {{{ Memcached::isPristine() - Returns the true if instance is recently created */ -static PHP_METHOD(Memcached, isPristine) -{ - MEMC_METHOD_INIT_VARS; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - MEMC_METHOD_FETCH_OBJECT; - - RETURN_BOOL(intern->is_pristine); -} -/* }}} */ - -/**************************************** - Internal support code -****************************************/ - -/* {{{ constructor/destructor */ -static -void php_memc_destroy(memcached_st *memc, php_memc_user_data_t *memc_user_data) -{ -#if HAVE_MEMCACHED_SASL - if (memc_user_data->has_sasl_data) { - memcached_destroy_sasl_auth_data(memc); - } -#endif - - memcached_set_memory_allocators(memc, NULL, NULL, NULL, NULL, NULL); - memcached_free(memc); - pefree(memc_user_data, memc_user_data->is_persistent); -} - -static -void php_memc_object_free_storage(zend_object *object) -{ - php_memc_object_t *intern = php_memc_fetch_object(object); - - if (intern->memc) { - php_memc_user_data_t *memc_user_data = memcached_get_user_data(intern->memc); - - if (!memc_user_data->is_persistent) { - php_memc_destroy(intern->memc, memc_user_data); - } - } - - intern->memc = NULL; - zend_object_std_dtor(&intern->zo); -} - -static -zend_object *php_memc_object_new(zend_class_entry *ce) -{ - php_memc_object_t *intern = ecalloc(1, sizeof(php_memc_object_t) + zend_object_properties_size(ce)); - - zend_object_std_init(&intern->zo, ce); - object_properties_init(&intern->zo, ce); - - intern->zo.handlers = &memcached_object_handlers; - return &intern->zo; -} - -#ifdef HAVE_MEMCACHED_PROTOCOL -static -void php_memc_server_free_storage(php_memc_server_t *intern) -{ - zend_object_std_dtor(&intern->zo); - efree (intern); -} - -zend_object_value php_memc_server_new(zend_class_entry *ce) -{ - zend_object_value retval; - php_memc_server_t *intern; - zval *tmp; - - intern = ecalloc(1, sizeof(php_memc_server_t)); - zend_object_std_init(&intern->zo, ce); - object_properties_init(&intern->zo, ce); - - intern->handler = php_memc_proto_handler_new (); - - retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)php_memc_server_free_storage, NULL); - retval.handlers = &memcached_server_object_handlers; - - return retval; -} -#endif - -ZEND_RSRC_DTOR_FUNC(php_memc_dtor) -{ - if (res->ptr) { - memcached_st *memc = (memcached_st *) res->ptr; - php_memc_destroy(memc, memcached_get_user_data(memc)); - res->ptr = NULL; - } -} - -/* }}} */ - -/* {{{ internal API functions */ -static -memcached_return s_server_cursor_list_servers_cb(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) -{ - zval array; - zval *return_value = (zval *) in_context; - - array_init(&array); - add_assoc_string(&array, "host", memcached_server_name(instance)); - add_assoc_long(&array, "port", memcached_server_port(instance)); - add_assoc_string(&array, "type", memcached_server_type(instance)); - /* - * API does not allow to get at this field. - add_assoc_long(array, "weight", instance->weight); - */ + if (!php_memc_set_option(intern, (long) key_index, ©)) { + ok = 0; + } - add_next_index_zval(return_value, &array); - return MEMCACHED_SUCCESS; + zval_dtor(©); + } + } ZEND_HASH_FOREACH_END(); + + RETURN_BOOL(ok); } +/* }}} */ -static -memcached_return s_server_cursor_version_cb(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) +/* {{{ Memcached::setOption(int option, mixed value) + Sets the value for the given option constant */ +static PHP_METHOD(Memcached, setOption) { - char *address, *version; - size_t address_len, version_len; - - zval *return_value = (zval *) in_context; + long option; + zval *value; + MEMC_METHOD_INIT_VARS; -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000009 - version_len = spprintf(&version, sizeof(version), "%d.%d.%d", - memcached_server_major_version(instance), - memcached_server_minor_version(instance), - memcached_server_micro_version(instance)); -#else - version_len = spprintf(&version, sizeof(version) - 1, "%d.%d.%d", - instance->major_version, - instance->minor_version, - instance->micro_version); -#endif + if (zend_parse_parameters(ZEND_NUM_ARGS(), "lz/", &option, &value) == FAILURE) { + return; + } - address_len = spprintf(&address, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance) - 1); - add_assoc_stringl_ex(return_value, address, address_len, version, version_len); + MEMC_METHOD_FETCH_OBJECT; - efree(address); - efree(version); - return MEMCACHED_SUCCESS; + RETURN_BOOL(php_memc_set_option(intern, option, value)); } +/* }}} */ -static int php_memc_handle_error(php_memc_object_t *intern, memcached_return status) +#ifdef HAVE_MEMCACHED_SASL +/* {{{ Memcached::setSaslAuthData(string user, string pass) + Sets sasl credentials */ +static PHP_METHOD(Memcached, setSaslAuthData) { - int result = 0; + MEMC_METHOD_INIT_VARS; + memcached_return status; + zend_string *user, *pass; - switch (status) { - case MEMCACHED_SUCCESS: - case MEMCACHED_STORED: - case MEMCACHED_DELETED: - case MEMCACHED_STAT: - result = 0; - intern->memc_errno = 0; - break; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &user, &pass) == FAILURE) { + return; + } - case MEMCACHED_END: - case MEMCACHED_BUFFERED: - intern->rescode = status; - intern->memc_errno = 0; - result = 0; - break; + if (!php_memc_init_sasl_if_needed()) { + RETURN_FALSE; + } - case MEMCACHED_SOME_ERRORS: - intern->rescode = status; - intern->memc_errno = memcached_last_error_errno(intern->memc); - result = 0; - break; + MEMC_METHOD_FETCH_OBJECT; - default: - intern->rescode = status; - intern->memc_errno = memcached_last_error_errno(intern->memc); - result = -1; - break; + if (!memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { + php_error_docref(NULL, E_WARNING, "SASL is only supported with binary protocol"); + RETURN_FALSE; } + memc_user_data->has_sasl_data = 1; + status = memcached_set_sasl_auth_data(intern->memc, user->val, pass->val); - return result; + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + RETURN_FALSE; + } + RETURN_TRUE; } +/* }}} */ +#endif /* HAVE_MEMCACHED_SASL */ -static -zend_bool s_compress_value (enum memcached_compression_type compression_type, zend_string **payload_in, uint32_t *flags) +/* {{{ Memcached::getResultCode() + Returns the result code from the last operation */ +static PHP_METHOD(Memcached, getResultCode) { - /* status */ - zend_bool compress_status = 0; - zend_string *payload = *payload_in; + MEMC_METHOD_INIT_VARS; - /* Additional 5% for the data */ - size_t buffer_size = (size_t) (((double) payload->len * 1.05) + 1.0); - char *buffer = emalloc(buffer_size); + if (zend_parse_parameters_none() == FAILURE) { + return; + } - /* Store compressed size here */ - size_t compressed_size = 0; - uint32_t original_size = payload->len; + MEMC_METHOD_FETCH_OBJECT; - switch (compression_type) { + RETURN_LONG(intern->rescode); +} +/* }}} */ - case COMPRESSION_TYPE_FASTLZ: - { - compressed_size = fastlz_compress(payload->val, payload->len, buffer); +/* {{{ Memcached::getResultMessage() + Returns the result message from the last operation */ +static PHP_METHOD(Memcached, getResultMessage) +{ + MEMC_METHOD_INIT_VARS; - if (compressed_size > 0) { - compress_status = 1; - MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_FASTLZ); - } - } - break; + if (zend_parse_parameters_none() == FAILURE) { + return; + } - case COMPRESSION_TYPE_ZLIB: - { - compressed_size = buffer_size; - int status = compress((Bytef *) buffer, &compressed_size, (Bytef *) payload->val, payload->len); + MEMC_METHOD_FETCH_OBJECT; - if (status == Z_OK) { - compress_status = 1; - MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_ZLIB); - } - } + switch (intern->rescode) { + case MEMC_RES_PAYLOAD_FAILURE: + RETURN_STRING("PAYLOAD FAILURE"); break; + case MEMCACHED_ERRNO: + case MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE: + case MEMCACHED_UNKNOWN_READ_FAILURE: + if (intern->memc_errno) { + zend_string *str = strpprintf(0, "%s: %s", + memcached_strerror(intern->memc, (memcached_return)intern->rescode), strerror(intern->memc_errno)); + RETURN_STR(str); + } + /* Fall through */ default: - compress_status = 0; + RETURN_STRING(memcached_strerror(intern->memc, (memcached_return)intern->rescode)); break; } - if (!compress_status) { - php_error_docref(NULL, E_WARNING, "could not compress value"); - MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); - efree (buffer); - return 0; - } +} +/* }}} */ - /* This means the value was too small to be compressed, still a success */ - if (compressed_size > (payload->len * MEMC_G(compression_factor))) { - efree(buffer); - MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); - return 1; - } +/* {{{ Memcached::isPersistent() + Returns the true if instance uses a persistent connection */ +static PHP_METHOD(Memcached, isPersistent) +{ + MEMC_METHOD_INIT_VARS; - payload = zend_string_realloc(payload, compressed_size + sizeof(uint32_t), 0); + if (zend_parse_parameters_none() == FAILURE) { + return; + } - /* Copy the uin32_t at the beginning */ - memcpy(payload->val, &original_size, sizeof(uint32_t)); - memcpy(payload->val + sizeof (uint32_t), buffer, compressed_size); - efree(buffer); + MEMC_METHOD_FETCH_OBJECT; - zend_string_forget_hash_val(payload); - *payload_in = payload; - return 1; + RETURN_BOOL(memc_user_data->is_persistent); } +/* }}} */ -static -zend_bool s_serialize_value (enum memcached_serializer serializer, zval *value, smart_str *buf, uint32_t *flags) +/* {{{ Memcached::isPristine() + Returns the true if instance is recently created */ +static PHP_METHOD(Memcached, isPristine) { - switch (serializer) { + MEMC_METHOD_INIT_VARS; - /* - Igbinary serialization - */ -#ifdef HAVE_MEMCACHED_IGBINARY - case SERIALIZER_IGBINARY: - { - uint8_t *buffer; - size_t buffer_len; + if (zend_parse_parameters_none() == FAILURE) { + return; + } - if (igbinary_serialize(&buffer, &buffer_len, value) != 0) { - php_error_docref(NULL, E_WARNING, "could not serialize value with igbinary"); - return 0; - } - smart_str_appendl (buf, buffer, buffer_len); - efree(buffer); - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_IGBINARY); - } - break; -#endif + MEMC_METHOD_FETCH_OBJECT; - /* - JSON serialization - */ -#ifdef HAVE_JSON_API - case SERIALIZER_JSON: - case SERIALIZER_JSON_ARRAY: - { - php_json_encode(buf, value, 0); - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_JSON); - } - break; -#endif + RETURN_BOOL(intern->is_pristine); +} +/* }}} */ - /* - msgpack serialization - */ -#ifdef HAVE_MEMCACHED_MSGPACK - case SERIALIZER_MSGPACK: - php_msgpack_serialize(buf, value); - if (!buf->s) { - php_error_docref(NULL, E_WARNING, "could not serialize value with msgpack"); - return 0; - } - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_MSGPACK); - break; +/**************************************** + Internal support code +****************************************/ + +/* {{{ constructor/destructor */ +static +void php_memc_destroy(memcached_st *memc, php_memc_user_data_t *memc_user_data) +{ +#if HAVE_MEMCACHED_SASL + if (memc_user_data->has_sasl_data) { + memcached_destroy_sasl_auth_data(memc); + } #endif - /* - PHP serialization - */ - default: - { - php_serialize_data_t var_hash; - PHP_VAR_SERIALIZE_INIT(var_hash); - php_var_serialize(buf, value, &var_hash); - PHP_VAR_SERIALIZE_DESTROY(var_hash); + memcached_free(memc); + pefree(memc_user_data, memc_user_data->is_persistent); +} - if (!buf->s) { - php_error_docref(NULL, E_WARNING, "could not serialize value"); - return 0; - } - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_SERIALIZED); +static +void php_memc_object_free_storage(zend_object *object) +{ + php_memc_object_t *intern = php_memc_fetch_object(object); + + if (intern->memc) { + php_memc_user_data_t *memc_user_data = memcached_get_user_data(intern->memc); + + if (!memc_user_data->is_persistent) { + php_memc_destroy(intern->memc, memc_user_data); } - break; } - /* Check for exceptions caused by serializers */ - if (EG(exception) && buf->s->len) { - return 0; - } - return 1; + intern->memc = NULL; + zend_object_std_dtor(&intern->zo); } static -zend_string *s_zval_to_payload(zval *value, uint32_t *flags, enum memcached_serializer serializer, enum memcached_compression_type compression_type) +zend_object *php_memc_object_new(zend_class_entry *ce) { - zend_string *payload; + php_memc_object_t *intern = ecalloc(1, sizeof(php_memc_object_t) + zend_object_properties_size(ce)); - switch (Z_TYPE_P(value)) { + zend_object_std_init(&intern->zo, ce); + object_properties_init(&intern->zo, ce); - case IS_STRING: - payload = zval_get_string(value); - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_STRING); - MEMC_VAL_HAS_FLAG(*flags, MEMC_VAL_COMPRESSED); - break; + intern->zo.handlers = &memcached_object_handlers; + return &intern->zo; +} - case IS_LONG: - { - smart_str buffer = {0}; - smart_str_append_long (&buffer, Z_LVAL_P(value)); - smart_str_0(&buffer); - payload = buffer.s; +#ifdef HAVE_MEMCACHED_PROTOCOL +static +void php_memc_server_free_storage(php_memc_server_t *intern) +{ + zend_object_std_dtor(&intern->zo); + efree (intern); +} - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_LONG); - } - break; +zend_object_value php_memc_server_new(zend_class_entry *ce) +{ + zend_object_value retval; + php_memc_server_t *intern; + zval *tmp; - case IS_DOUBLE: - { - char buffer[40]; - php_memcached_g_fmt(buffer, Z_DVAL_P(value)); - payload = zend_string_init (buffer, strlen (buffer), 0); - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_DOUBLE); - } - break; + intern = ecalloc(1, sizeof(php_memc_server_t)); + zend_object_std_init(&intern->zo, ce); + object_properties_init(&intern->zo, ce); - case IS_TRUE: - payload = zend_string_init ("1", 1, 0); - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_BOOL); - break; + intern->handler = php_memc_proto_handler_new (); - case IS_FALSE: - payload = zend_string_alloc (0, 0); - MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_BOOL); - break; + retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)php_memc_server_free_storage, NULL); + retval.handlers = &memcached_server_object_handlers; - default: - { - smart_str buffer = {0}; + return retval; +} +#endif - if (!s_serialize_value (serializer, value, &buffer, flags)) { - smart_str_free(&buffer); - return NULL; - } - payload = buffer.s; - MEMC_VAL_HAS_FLAG(*flags, MEMC_VAL_COMPRESSED); - } - break; +ZEND_RSRC_DTOR_FUNC(php_memc_dtor) +{ + if (res->ptr) { + memcached_st *memc = (memcached_st *) res->ptr; + php_memc_destroy(memc, memcached_get_user_data(memc)); + res->ptr = NULL; } - zend_string_forget_hash_val(payload); +} - /* turn off compression for values below the threshold */ - if (payload->len == 0 || payload->len < MEMC_G(compression_threshold)) { - MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); - } +/* }}} */ - /* If we have compression flag, compress the value */ - if (MEMC_VAL_HAS_FLAG(*flags, MEMC_VAL_COMPRESSED)) { - /* status */ - if (!s_compress_value (compression_type, &payload, flags)) { - zend_string_release(payload); - return NULL; - } - } +/* {{{ internal API functions */ +static +memcached_return s_server_cursor_list_servers_cb(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) +{ + zval array; + zval *return_value = (zval *) in_context; - return payload; + array_init(&array); + add_assoc_string(&array, "host", memcached_server_name(instance)); + add_assoc_long(&array, "port", memcached_server_port(instance)); + add_assoc_string(&array, "type", memcached_server_type(instance)); + /* + * API does not allow to get at this field. + add_assoc_long(array, "weight", instance->weight); + */ + + add_next_index_zval(return_value, &array); + return MEMCACHED_SUCCESS; +} + +static +memcached_return s_server_cursor_version_cb(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) +{ + char *address, *version; + size_t address_len, version_len; + + zval *return_value = (zval *) in_context; + +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000009 + version_len = spprintf(&version, sizeof(version), "%d.%d.%d", + memcached_server_major_version(instance), + memcached_server_minor_version(instance), + memcached_server_micro_version(instance)); +#else + version_len = spprintf(&version, sizeof(version) - 1, "%d.%d.%d", + instance->major_version, + instance->minor_version, + instance->micro_version); +#endif + + address_len = spprintf(&address, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance) - 1); + add_assoc_stringl_ex(return_value, address, address_len, version, version_len); + + efree(address); + efree(version); + return MEMCACHED_SUCCESS; } + static zend_string *s_decompress_value (const char *payload, size_t payload_len, uint32_t flags) { @@ -3559,145 +3594,6 @@ zend_class_entry *php_memc_get_exception_base(int root) #endif } -static -memcached_return s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string *key, zval *value) -{ - memcached_return rc = MEMCACHED_SUCCESS; - int result; - - zval params[4]; - zval retval; - zval zv_key, ref_val; - zval ref_expiration, zv_expiration; - - /* Prepare params */ - ZVAL_STR(&zv_key, key); - - ZVAL_NULL(&ref_val); - ZVAL_NULL(&zv_expiration); - - ZVAL_NEW_REF(&ref_val, value); - ZVAL_NEW_REF(&ref_expiration, &zv_expiration); - - ZVAL_COPY(¶ms[0], zobject); - ZVAL_COPY(¶ms[1], &zv_key); - ZVAL_COPY_VALUE(¶ms[2], &ref_val); - ZVAL_COPY_VALUE(¶ms[3], &ref_expiration); - - fci->retval = &retval; - fci->params = params; - fci->param_count = 4; - - result = zend_call_function(fci, fcc); - ZVAL_DUP(value, Z_REFVAL(ref_val)); - - if (result == SUCCESS && Z_TYPE(retval) != IS_UNDEF) { - - if (zend_is_true(&retval)) { - time_t expiration; - zend_string *payload; - uint32_t flags = 0; - php_memc_object_t *intern; - php_memc_user_data_t *memc_user_data; - - intern = Z_MEMC_OBJ_P(zobject); - memc_user_data = memcached_get_user_data(intern->memc); - - expiration = zval_get_long(Z_REFVAL(ref_expiration)); - payload = s_zval_to_payload(value, &flags, memc_user_data->serializer, memc_user_data->compression_type); - - if (payload == NULL) { - rc = (memcached_return) MEMC_RES_PAYLOAD_FAILURE; - } else { - if (memc_user_data->set_udf_flags >= 0) { - MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) memc_user_data->set_udf_flags)); - } - rc = memcached_set(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags); - if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_BUFFERED) { - rc = MEMCACHED_SOME_ERRORS; - } - zend_string_release(payload); - } - } else { - rc = MEMCACHED_NOTFOUND; - zval_dtor(value); - ZVAL_NULL(value); - } - } - - if (!Z_ISUNDEF(retval)) { - zval_ptr_dtor(&retval); - } - - zval_ptr_dtor(&zv_key); - zval_ptr_dtor(&ref_val); - zval_ptr_dtor(&zv_expiration); - zval_ptr_dtor(&ref_expiration); - zval_ptr_dtor(zobject); - return rc; -} - - -static -int s_invoke_result_callback(zval *zmemc_obj, zend_fcall_info *fci, zend_fcall_info_cache *fcc, memcached_result_st *result) -{ - const char *res_key = NULL; - size_t res_key_len = 0; - const char *payload = NULL; - size_t payload_len = 0; - zval value; - zval retval; - uint64_t cas = 0; - zval z_result; - uint32_t flags = 0; - int rc = 0; - php_memc_object_t *intern = NULL; - - fci->retval = &retval; - fci->param_count = 2; - - payload = memcached_result_value(result); - payload_len = memcached_result_length(result); - flags = memcached_result_flags(result); - res_key = memcached_result_key_value(result); - res_key_len = memcached_result_key_length(result); - cas = memcached_result_cas(result); - - intern = Z_MEMC_OBJ_P(zmemc_obj); - - if (!s_memcached_result_to_zval(intern->memc, result, &value)) { - intern->rescode = MEMC_RES_PAYLOAD_FAILURE; - return -1; - } - - array_init(&z_result); - add_assoc_stringl_ex(&z_result, ZEND_STRL("key"), (char *)res_key, res_key_len); - add_assoc_zval_ex(&z_result, ZEND_STRL("value"), &value); - if (cas != 0) { - add_assoc_double_ex(&z_result, ZEND_STRL("cas"), (double)cas); - } - if (MEMC_VAL_GET_USER_FLAGS(flags) != 0) { - add_assoc_long_ex(&z_result, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); - } - - ZVAL_UNDEF(&retval); - zend_fcall_info_argn(fci, 2, zmemc_obj, &z_result); - - if (zend_call_function(fci, fcc) == FAILURE) { - php_error_docref(NULL, E_WARNING, "could not invoke result callback"); - rc = -1; - } - - if (Z_TYPE(retval) != IS_UNDEF) { - zval_ptr_dtor(&retval); - } - - zend_fcall_info_args_clear(fci, 1); - zval_ptr_dtor(&z_result); - - return rc; -} -/* }}} */ #ifdef HAVE_MEMCACHED_PROTOCOL @@ -4181,7 +4077,6 @@ PHP_GINIT_FUNCTION(php_memcached) php_memcached_globals->session.lock_wait_min = 1000; php_memcached_globals->session.lock_retries = 5; php_memcached_globals->session.lock_expiration = 30; - php_memcached_globals->session.compression_enabled = 1; php_memcached_globals->session.binary_protocol_enabled = 1; php_memcached_globals->session.consistent_hash_enabled = 1; php_memcached_globals->session.number_of_replicas = 0; @@ -4196,10 +4091,10 @@ PHP_GINIT_FUNCTION(php_memcached) #endif php_memcached_globals->memc.serializer_name = NULL; - php_memcached_globals->memc.serializer = SERIALIZER_DEFAULT; - php_memcached_globals->memc.compression_type = NULL; + php_memcached_globals->memc.serializer_type = SERIALIZER_DEFAULT; + php_memcached_globals->memc.compression_name = NULL; php_memcached_globals->memc.compression_threshold = 2000; - php_memcached_globals->memc.compression_type_real = COMPRESSION_TYPE_FASTLZ; + php_memcached_globals->memc.compression_type = COMPRESSION_TYPE_FASTLZ; php_memcached_globals->memc.compression_factor = 1.30; php_memcached_globals->memc.store_retry_count = 2; diff --git a/php_memcached_private.h b/php_memcached_private.h index c6c0b77c..d19fe974 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -75,13 +75,24 @@ typedef unsigned long int uint32_t; /**************************************** Structures and definitions ****************************************/ -enum memcached_serializer { - SERIALIZER_PHP = 1, - SERIALIZER_IGBINARY = 2, - SERIALIZER_JSON = 3, +typedef enum { + SERIALIZER_PHP = 1, + SERIALIZER_IGBINARY = 2, + SERIALIZER_JSON = 3, SERIALIZER_JSON_ARRAY = 4, - SERIALIZER_MSGPACK = 5, -}; + SERIALIZER_MSGPACK = 5 +} php_memc_serializer_type; + +typedef enum { + COMPRESSION_TYPE_ZLIB = 1, + COMPRESSION_TYPE_FASTLZ = 2 +} php_memc_compression_type; + +typedef struct { + const char *name; + php_memc_serializer_type type; +} php_memc_serializer; + #ifdef HAVE_MEMCACHED_IGBINARY #define SERIALIZER_DEFAULT SERIALIZER_IGBINARY #define SERIALIZER_DEFAULT_NAME "igbinary" @@ -160,14 +171,14 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) struct { char *serializer_name; - char *compression_type; + char *compression_name; zend_long compression_threshold; double compression_factor; zend_long store_retry_count; /* Converted values*/ - enum memcached_serializer serializer; - zend_long compression_type_real; + php_memc_serializer_type serializer_type; + php_memc_compression_type compression_type; /* Whether we have initialised sasl for this process */ zend_bool sasl_initialised; diff --git a/tests/getdelayed.phpt b/tests/getdelayed.phpt index 7479e97b..c07acada 100644 --- a/tests/getdelayed.phpt +++ b/tests/getdelayed.phpt @@ -22,42 +22,61 @@ foreach ($data as $k => $v) { function myfunc() { $datas = func_get_args(); if (isset($datas[1])) { - unset($datas[1]['cas']); var_dump($datas[1]); } } -$m->getDelayed(array_keys($data), false, 'myfunc'); +$m->getDelayed(array_keys($data), true, 'myfunc'); ?> ---EXPECT-- -array(2) { +--EXPECTF-- +array(4) { ["key"]=> string(3) "foo" ["value"]=> string(8) "foo-data" + ["cas"]=> + int(%d) + ["flags"]=> + int(0) } -array(2) { +array(4) { ["key"]=> string(3) "bar" ["value"]=> string(8) "bar-data" + ["cas"]=> + int(%d) + ["flags"]=> + int(0) } -array(2) { +array(4) { ["key"]=> string(3) "baz" ["value"]=> string(8) "baz-data" + ["cas"]=> + int(%d) + ["flags"]=> + int(0) } -array(2) { +array(4) { ["key"]=> string(3) "lol" ["value"]=> string(8) "lol-data" + ["cas"]=> + int(%d) + ["flags"]=> + int(0) } -array(2) { +array(4) { ["key"]=> string(3) "kek" ["value"]=> string(8) "kek-data" -} + ["cas"]=> + int(%d) + ["flags"]=> + int(0) +} \ No newline at end of file diff --git a/tests/incrdecr_invalid_key.phpt b/tests/incrdecr_invalid_key.phpt index 8d4ab671..cd8c6b9b 100644 --- a/tests/incrdecr_invalid_key.phpt +++ b/tests/incrdecr_invalid_key.phpt @@ -9,6 +9,7 @@ $m = memc_get_instance (); var_dump($m->increment('', 1)); var_dump($m->decrement('', 1)); +?> --EXPECT-- bool(false) bool(false) From 27a22f3c0ab62f98d4e01e43caf2ad80840043fd Mon Sep 17 00:00:00 2001 From: Manabu Matsui Date: Mon, 8 Feb 2016 15:35:46 +0900 Subject: [PATCH 069/345] fix expiration --- php_memcached_session.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/php_memcached_session.c b/php_memcached_session.c index bfb34e99..6dcb4cbe 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -25,6 +25,8 @@ extern ZEND_DECLARE_MODULE_GLOBALS(php_memcached) #define MEMC_SESS_DEFAULT_LOCK_WAIT 150000 #define MEMC_SESS_LOCK_EXPIRATION 30 +#define REALTIME_MAXDELTA 60*60*24*30 + ps_module ps_mod_memcached = { PS_MOD_UPDATE_TIMESTAMP(memcached) }; @@ -92,16 +94,26 @@ int php_memc_session_minit(int module_number) return SUCCESS; } +static +time_t s_adjust_expiration(zend_long expiration) +{ + if (expiration <= REALTIME_MAXDELTA) { + return expiration; + } else { + return time(NULL) + expiration; + } +} + static time_t s_lock_expiration() { if (MEMC_SESS_INI(lock_expiration) > 0) { - return time(NULL) + MEMC_SESS_INI(lock_expiration); + return s_adjust_expiration(MEMC_SESS_INI(lock_expiration)); } else { zend_long max_execution_time = zend_ini_long(ZEND_STRS("max_execution_time"), 0); if (max_execution_time > 0) { - return time(NULL) + max_execution_time; + return s_adjust_expiration(max_execution_time); } } return 0; @@ -111,7 +123,7 @@ static time_t s_session_expiration(zend_long maxlifetime) { if (maxlifetime > 0) { - return time(NULL) + maxlifetime; + return s_adjust_expiration(maxlifetime); } return 0; } From 27fa80fb260ee7d71b3562051d5a16c3f1fd1da0 Mon Sep 17 00:00:00 2001 From: Paul Werelds Date: Fri, 12 Feb 2016 15:50:58 +0100 Subject: [PATCH 070/345] Adds a missed SASL presence constraint --- php_memcached_session.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/php_memcached_session.c b/php_memcached_session.c index 6dcb4cbe..61738559 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -68,9 +68,11 @@ void s_destroy_mod_data(memcached_st *memc) { php_memcached_user_data *user_data = memcached_get_user_data(memc); +#if HAVE_MEMCACHED_SASL if (user_data->has_sasl_data) { memcached_destroy_sasl_auth_data(memc); } +#endif memcached_free(memc); pefree(memc, user_data->is_persistent); From 4ff385988358f12c577ac1a7d9282600d6992b25 Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 17 Feb 2016 14:30:43 +0100 Subject: [PATCH 071/345] Update package.xml for release --- package.xml | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/package.xml b/package.xml index 9d3be440..8ec578a7 100644 --- a/package.xml +++ b/package.xml @@ -21,7 +21,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> mkoppanen@php.net yes - 2016-02-01 + 2016-02-17 3.0.0b1 3.0.0 @@ -33,17 +33,19 @@ http://pear.php.net/dtd/package-2.0.xsd"> PHP PHP7 release of memcached extension. Note that support for libmemcached 0.x series has been discontinued -and the earliest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of -libmemcached. +and the oldest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of +libmemcached. Please note that this is a beta release and reporting any issues would be highly appreciated +before we move closer to releasing stable version. API - * set/get commands do not take cas or user flags parameters + * set/get commands do not take cas or user flags parameters. * get and getMulti commands take Memcached::GET_EXTENDED flag to retrieve user flags and cas tokens * Fixes getStats command to return all stats from all servers * Fixes allKeys command behaviour * Fixes error where cache callback for get command was not setting expiration time properly * Added server type to server list * Remove use_sasl ini-variable and initialise sasl as needed + * CAS tokens are returned as integers and they overflow to strings as needed Session handler * Session lock algorithm updated (new ini-values memcached.sess_lock_wait_min, memcached.sess_lock_wait_max and memcached.sess_lock_retries) @@ -52,7 +54,7 @@ Session handler * Fixes crash with session_regenerate_id (work-around for PHP bug) Tests - * Fix several broken tests + * Fix several problematic tests @@ -161,6 +163,7 @@ Tests + @@ -188,21 +191,22 @@ Tests 3.0.0b1 3.0.0 - 2016-02-01 + 2016-02-17 PHP7 release of memcached extension. Note that support for libmemcached 0.x series has been discontinued -and the earliest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of -libmemcached. +and the oldest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of +libmemcached. Please note that this is a beta release and reporting any issues would be highly appreciated +before we move closer to releasing stable version. API - * set/get commands do not take cas or user flags parameters + * set/get commands do not take cas or user flags parameters. * get and getMulti commands take Memcached::GET_EXTENDED flag to retrieve user flags and cas tokens * Fixes getStats command to return all stats from all servers * Fixes allKeys command behaviour * Fixes error where cache callback for get command was not setting expiration time properly * Added server type to server list * Remove use_sasl ini-variable and initialise sasl as needed - * CAS tokens are returned as integers and in case of too large values they overflow to strings + * CAS tokens are returned as integers and they overflow to strings as needed Session handler * Session lock algorithm updated (new ini-values memcached.sess_lock_wait_min, memcached.sess_lock_wait_max and memcached.sess_lock_retries) @@ -211,7 +215,7 @@ Session handler * Fixes crash with session_regenerate_id (work-around for PHP bug) Tests - * Fix several broken tests + * Fix several problematic tests From 6ace07da69a5ebc021e56a9d2f52cdc8897b4f23 Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 17 Feb 2016 14:39:49 +0100 Subject: [PATCH 072/345] Tests for default behavior --- php_memcached.c | 49 ++++++++++++++++++++++++++++++++++--- php_memcached_private.h | 9 ++++++- tests/default_behavior.phpt | 32 ++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 tests/default_behavior.phpt diff --git a/php_memcached.c b/php_memcached.c index c01b7f94..04e330fc 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -341,6 +341,11 @@ PHP_INI_BEGIN() MEMC_INI_ENTRY("compression_threshold", "2000", OnUpdateLong, compression_threshold) MEMC_INI_ENTRY("serializer", SERIALIZER_DEFAULT_NAME, OnUpdateSerializer, serializer_name) MEMC_INI_ENTRY("store_retry_count", "2", OnUpdateLong, store_retry_count) + + MEMC_INI_ENTRY("default_consistent_hash", "0", OnUpdateBool, default_behavior.consistent_hash_enabled) + MEMC_INI_ENTRY("default_binary_protocol", "0", OnUpdateBool, default_behavior.binary_protocol_enabled) + MEMC_INI_ENTRY("default_connect_timeout", "0", OnUpdateLongGEZero, default_behavior.connect_timeout) + PHP_INI_END() /* }}} */ @@ -1190,7 +1195,8 @@ static PHP_METHOD(Memcached, __construct) } if (!intern->memc) { - // TODO: handle allocation fail + php_error_docref(NULL, E_ERROR, "Failed to allocate memory for memcached structure"); + /* never reached */ } memc_user_data = pecalloc (1, sizeof(*memc_user_data), is_persistent); @@ -1203,6 +1209,38 @@ static PHP_METHOD(Memcached, __construct) memcached_set_user_data(intern->memc, memc_user_data); + /* Set default behaviors */ + { +#ifdef mikko_0 + fprintf (stderr, "consistent_hash_enabled=%d binary_protocol_enabled=%d connect_timeout=%ld\n", + MEMC_G(default_behavior.consistent_hash_enabled), MEMC_G(default_behavior.binary_protocol_enabled), MEMC_G(default_behavior.connect_timeout)); +#endif + + memcached_return rc; + + if (MEMC_G(default_behavior.consistent_hash_enabled)) { + + rc = memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, MEMCACHED_DISTRIBUTION_CONSISTENT); + if (rc != MEMCACHED_SUCCESS) { + php_error_docref(NULL, E_WARNING, "Failed to turn on consistent hash: %s", memcached_strerror(intern->memc, rc)); + } + } + + if (MEMC_G(default_behavior.binary_protocol_enabled)) { + rc = memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1); + if (rc != MEMCACHED_SUCCESS) { + php_error_docref(NULL, E_WARNING, "Failed to turn on binary protocol: %s", memcached_strerror(intern->memc, rc)); + } + } + + if (MEMC_G(default_behavior.connect_timeout)) { + rc = memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, MEMC_G(default_behavior.connect_timeout)); + if (rc != MEMCACHED_SUCCESS) { + php_error_docref(NULL, E_WARNING, "Failed to set connect timeout: %s", memcached_strerror(intern->memc, rc)); + } + } + } + if (fci.size) { if (!s_invoke_new_instance_cb(getThis(), &fci, &fci_cache, persistent_id) || EG(exception)) { /* error calling or exception thrown from callback */ @@ -2263,7 +2301,7 @@ PHP_METHOD(Memcached, addServer) } MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000002 if (host->val[0] == '/') { /* unix domain socket */ @@ -2712,7 +2750,7 @@ static PHP_METHOD(Memcached, flush) } MEMC_METHOD_FETCH_OBJECT; - intern->rescode = MEMCACHED_SUCCESS; + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); status = memcached_flush(intern->memc, delay); if (s_memc_status_handle_result_code(intern, status) == FAILURE) { @@ -4100,6 +4138,11 @@ PHP_GINIT_FUNCTION(php_memcached) php_memcached_globals->memc.sasl_initialised = 0; php_memcached_globals->no_effect = 0; + + /* Defaults for certain options */ + php_memcached_globals->memc.default_behavior.consistent_hash_enabled = 0; + php_memcached_globals->memc.default_behavior.binary_protocol_enabled = 0; + php_memcached_globals->memc.default_behavior.connect_timeout = 0; } zend_module_entry memcached_module_entry = { diff --git a/php_memcached_private.h b/php_memcached_private.h index d19fe974..329afc8d 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -150,7 +150,6 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) zend_long lock_retries; zend_long lock_expiration; - zend_bool compression_enabled; zend_bool binary_protocol_enabled; zend_bool consistent_hash_enabled; @@ -183,6 +182,14 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) /* Whether we have initialised sasl for this process */ zend_bool sasl_initialised; + struct { + + zend_bool consistent_hash_enabled; + zend_bool binary_protocol_enabled; + zend_long connect_timeout; + + } default_behavior; + } memc; /* For deprecated values */ diff --git a/tests/default_behavior.phpt b/tests/default_behavior.phpt new file mode 100644 index 00000000..de46cec2 --- /dev/null +++ b/tests/default_behavior.phpt @@ -0,0 +1,32 @@ +--TEST-- +Default behaviors +--SKIPIF-- + +--FILE-- +getOption(Memcached::OPT_DISTRIBUTION) == Memcached::DISTRIBUTION_MODULA); +var_dump ($m->getOption(Memcached::OPT_BINARY_PROTOCOL) == false); +var_dump ($m->getOption(Memcached::OPT_CONNECT_TIMEOUT) != 0); + +ini_set('memcached.default_consistent_hash', true); +ini_set('memcached.default_binary_protocol', true); +ini_set('memcached.default_connect_timeout', 1212); + +$m = new Memcached(); +var_dump ($m->getOption(Memcached::OPT_DISTRIBUTION) == Memcached::DISTRIBUTION_CONSISTENT); +var_dump ($m->getOption(Memcached::OPT_BINARY_PROTOCOL) == true); +var_dump ($m->getOption(Memcached::OPT_CONNECT_TIMEOUT) == 1212); + +echo "OK"; + +?> +--EXPECT-- +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +OK From 21fd64ff3182accc38273d7c3aebd914f15e6f2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Sz=C3=A9pe?= Date: Mon, 22 Feb 2016 17:54:53 +0100 Subject: [PATCH 073/345] Up-to-date link to igbinary --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index e827e6fa..53a466e4 100644 --- a/README.markdown +++ b/README.markdown @@ -23,4 +23,4 @@ Resources --------- * [libmemcached](http://libmemcached.org/libMemcached.html) * [memcached](http://memcached.org/) - * [igbinary](https://github.com/phadej/igbinary/) + * [igbinary](https://github.com/igbinary/igbinary) From 3537b50d2548eb9d884cb8e980456bdfc9594523 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 22 Feb 2016 20:17:57 +0000 Subject: [PATCH 074/345] Update for release --- package.xml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/package.xml b/package.xml index 8ec578a7..40f0323f 100644 --- a/package.xml +++ b/package.xml @@ -21,14 +21,14 @@ http://pear.php.net/dtd/package-2.0.xsd"> mkoppanen@php.net yes - 2016-02-17 + 2016-02-22 - 3.0.0b1 + 3.0.0a1 3.0.0 - beta - beta + alpha + alpha PHP @@ -38,7 +38,7 @@ libmemcached. Please note that this is a beta release and reporting any issues w before we move closer to releasing stable version. API - * set/get commands do not take cas or user flags parameters. + * get commands do not take cas or user flags parameters. * get and getMulti commands take Memcached::GET_EXTENDED flag to retrieve user flags and cas tokens * Fixes getStats command to return all stats from all servers * Fixes allKeys command behaviour @@ -184,14 +184,14 @@ Tests - beta - beta + alpha + alpha - 3.0.0b1 + 3.0.0a1 3.0.0 - 2016-02-17 + 2016-02-22 PHP7 release of memcached extension. Note that support for libmemcached 0.x series has been discontinued and the oldest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of @@ -199,7 +199,7 @@ libmemcached. Please note that this is a beta release and reporting any issues w before we move closer to releasing stable version. API - * set/get commands do not take cas or user flags parameters. + * get commands do not take cas or user flags parameters. * get and getMulti commands take Memcached::GET_EXTENDED flag to retrieve user flags and cas tokens * Fixes getStats command to return all stats from all servers * Fixes allKeys command behaviour From 9b8126c043c79d75b3a160735a66572e5debdb0a Mon Sep 17 00:00:00 2001 From: xjewer Date: Thu, 3 Mar 2016 23:43:20 +0300 Subject: [PATCH 075/345] fix arginfo_get* --- php_memcached.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index 04e330fc..ced03752 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3716,12 +3716,14 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_get, 0, 0, 1) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, cache_cb) + ZEND_ARG_INFO(0, get_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getByKey, 0, 0, 2) ZEND_ARG_INFO(0, server_key) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, cache_cb) + ZEND_ARG_INFO(0, get_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getMulti, 0, 0, 1) From 4ee38195289edfa7ae936d2b0a434869c97d8817 Mon Sep 17 00:00:00 2001 From: Mikko Date: Sat, 5 Mar 2016 18:22:05 +0000 Subject: [PATCH 076/345] Fixes crash --- php_memcached.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index 04e330fc..804af76f 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1339,6 +1339,11 @@ static void s_clear_keys(php_memc_keys_t *keys) { size_t i; + + if (!keys->num_valid_keys) { + return; + } + for (i = 0; i < keys->num_valid_keys; i++) { zend_string_release (keys->strings[i]); } From 412daa91ce3fb9b4fa6aa50f118db1b17cb6cd3c Mon Sep 17 00:00:00 2001 From: David Zuelke Date: Fri, 18 Mar 2016 20:39:57 +0100 Subject: [PATCH 077/345] remove duplicate 2.2.0b1 from package.xml --- package.xml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/package.xml b/package.xml index 0ebc86f9..fe35edac 100644 --- a/package.xml +++ b/package.xml @@ -162,20 +162,6 @@ http://pear.php.net/dtd/package-2.0.xsd"> - Added the OPT_SERVER_TIMEOUT_LIMIT behaviour - - - betastable - 2.2.0b12.2.0 - 2013-10-28 - -- Reinstate support for libememcached 0.x series -- Added SASL support to session handler -- Added Memcached::flushBuffers as per GH #78 -- Fixes GH #54: Fixed UDP server adding with newer libmemcached -- Fixed PHP bug #65334: (Segfault if uncompress value failed) -- Fixes GH #14: get with cas token fails to fetch all results -- Fixes GH #69: compiling on CentOS 6.4 with libmemcached 1.0.17 - betastable From 0569c515c921e697b076008fabbc92a78222d882 Mon Sep 17 00:00:00 2001 From: David Zuelke Date: Fri, 18 Mar 2016 20:40:14 +0100 Subject: [PATCH 078/345] add missing releases (and dates for all) to changelog --- ChangeLog | 76 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/ChangeLog b/ChangeLog index b9b00ea5..05f77181 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,17 @@ memcached extension changelog -Version 2.2.0b1 ---------------- +Version 2.2.0 (2014-04-01) +-------------------------- + * Added the OPT_SERVER_TIMEOUT_LIMIT behaviour + +Version 2.2.0RC1 (2014-03-12) +----------------------------- + * Added the OPT_SERVER_TIMEOUT_LIMIT behaviour + * Fixes incorrect size when compressing serialized objects + * Fixes endianess of compressed values + +Version 2.2.0b1 (2013-10-28) +---------------------------- * Reinstate support for libememcached 0.x series * Added SASL support to session handler * Added Memcached::flushBuffers as per GH #78 @@ -20,28 +30,28 @@ Version 2.2.0b1 * Added Memcached::setBucket for virtual bucket support * Added support for msgpack serialization * Memcached::setSaslAuthData returns correct status on success - * Added support for user-defined flags in set and get operations + * Added support for user-defined flags in set and get operations -Version 2.1.0 -------------- +Version 2.1.0 (2012-08-06) +-------------------------- * Drop support for libmemcached 0.x series, now 1.0.x is required * Add support for virtual bucket distribution * Fix compilation against PHP 5.2 -Version 2.0.1 -------------- +Version 2.0.1 (2012-03-03) +-------------------------- * Fix embedded version number to be not -dev -Version 2.0.0 -------------- +Version 2.0.0 (2012-03-02) +-------------------------- * Add touch() and touchByKey() methods * Add resetServerList() and quit() methods * Support binary protocol in sessions * Make it work with libmemcached up to 1.0.4 * Test against PHP 5.4.0 -Version 2.0.0b2 ---------------- +Version 2.0.0b2 (2011-06-24) +---------------------------- * Add OPT_REMOVE_FAILED_SERVERS option. * Make it work with libmemcached up to 0.49. * Fix a case where invalid session ID could lock the script. @@ -61,8 +71,8 @@ Version 2.0.0b2 * Make increment/decrement initialize value when it is not available (when using binary protocol) -Version 2.0.0b1 ---------------- +Version 2.0.0b1 (2011-03-12) +---------------------------- * Add fastlz library that provides better/faster payload compression * Add configure switch to enable/disable JSON serialization support * Add getAllKeys() method @@ -84,23 +94,27 @@ Version 2.0.0b1 * Add 'on_new' callback to constructor * Add SASL support -Version 1.0.1 -------------- +Version 1.0.2 (2010-05-03) +-------------------------- + * Fix build for libmemcached-0.39 (memcached_server_list() issue) + +Version 1.0.1 (2010-03-11) +-------------------------- * Fix JSON API handling to account for PHP 5.2/5.3 version differences. * Add memcached.sess_locking, memcached.sess_lock_wait, and memcached.sess_prefix INI entries. * Add OPT_AUTO_EJECT_HOSTS option. -Version 1.0.0 -------------- +Version 1.0.0 (2009-07-04) +-------------------------- * First stable release. * Add getResultMessage() method. * Fix OPT_RECV_TIMEOUT definition. * Initialize Session lock wait to max execution time (if max execution time is unlimited, default to 30 seconds). -Version 0.2.0 -------------- +Version 0.2.0 (2009-06-04) +-------------------------- * Add JSON serializer support, requires PHP 5.2.10+. * Add HAVE_JSON and HAVE_IGBINARY class constants that indicate whether the respective serializers are available. @@ -114,25 +128,25 @@ Version 0.2.0 the cache when upgrading to this version. * Add several tests. -Version 0.1.5 -------------- +Version 0.1.5 (2009-03-31) +-------------------------- * Implement getVersion(). * Add support for preserving boolean value types. * Fix crash when child class does not call constructor. * Fix bug #16084 (Crash when addServers is called with an associative array). * ZTS compilation fixes. -Version 0.1.4 -------------- +Version 0.1.4 (2009-02-13) +-------------------------- * Fix compilation against PHP 5.3. * Add support for 'igbinary' serializer (Oleg Grenrus) -Version 0.1.3 -------------- +Version 0.1.3 (2009-02-06) +-------------------------- * Bludgeon bug #15896 (Memcached setMulti error) into submission. -Version 0.1.2 -------------- +Version 0.1.2 (2009-02-06) +-------------------------- * Fix bug #15896 (Memcached setMulti error). * Check for empty key in getServerByKey(). * Allow passing 'null' for callbacks. @@ -141,12 +155,12 @@ Version 0.1.2 * Allow only strings as the append/prepend value. * Remove expiration parameter from append/prepend. -Version 0.1.1 -------------- +Version 0.1.1 (2009-02-02) +-------------------------- * Add OPT_LIBKETAMA_COMPATIBLE option. * Implement addServers() method. * Swap internal compressed and serialized flags to be compatible with other clients. -Version 0.1.0 -------------- +Version 0.1.0 (2009-01-29) +-------------------------- * Initial release From 4bb264e60005e19b5573822d9d374b4cde8d1c3b Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Sun, 20 Mar 2016 15:37:27 -0700 Subject: [PATCH 079/345] Document ini settings for the default memcached connection configurations This documents memcached.default_consistent_hash, default_binary_protocol, and default_connect_timeout. For issue #233 --- memcached.ini | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/memcached.ini b/memcached.ini index 1aa9f266..e70c6b41 100644 --- a/memcached.ini +++ b/memcached.ini @@ -111,3 +111,32 @@ memcached.serializer = "igbinary" ; environment. ; the default is 2 memcached.store_retry_count = 2 + +; Sets the default for consistent hashing for new connections. +; (To configure consistent hashing for session connections, +; use memcached.sess_consistent_hash instead) +; +; If set to On, consistent hashing (libketama) is used +; for session handling. +; When consistent hashing is used, one can add or remove cache +; node(s) without messing up too much with existing keys +; default is Off +memcached.default_consistent_hash = Off + +; Sets the default memcached protocol for new connections. +; (To configure the memcached protocol for connections used by sessions, +; use memcached.sess_binary_protocol instead) +; +; If set to On, the memcached binary protocol is used by default. +; If set to Off, the memcached text protocol is used. +; Default is Off +memcached.default_binary_protocol = Off + +; Sets the default memcached connection timeout for new connections. +; (To configure the memcached connection timeout for sessions, +; use memcached.sess_connect_timeout instead) +; In non-blocking mode this changes the value of the timeout. +; during socket connection in milliseconds. Specifying -1 means an infinite timeout. +; Specifying 0 means using the memcached library's default connection timeout. +; Default is 0. +memcached.default_connect_timeout = 0 From e755d9db127d946740314d48dd01c81f43df0a7b Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Sun, 20 Mar 2016 15:16:35 -0700 Subject: [PATCH 080/345] Document miscellaneous ini settings and new defaults for PHP7 release This updates some of the memcached.ini documentation settings to reflect the default ini settings used in php_memcached.c. Some new settings were added, and other settings had changes to their defaults. There are other new/updated settings, which can be changed in other PRs. For issue #233 --- memcached.ini | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/memcached.ini b/memcached.ini index 1aa9f266..68f0a1ab 100644 --- a/memcached.ini +++ b/memcached.ini @@ -12,11 +12,17 @@ memcached.sess_locking = On ; The minimum time, in milliseconds, to wait between session lock attempts. ; This value is double on each lock retry until memcached.sess_lock_wait_max -; is reached -memcached.sess_lock_wait_min = 0; +; is reached, after which any further retries will take sess_lock_wait_max seconds. +; Default is 1000. +memcached.sess_lock_wait_min = 1000; ; The maximum time, in milliseconds, to wait between session lock attempts. -memcached.sess_lock_wait_max = 0; +; Default is 2000. +memcached.sess_lock_wait_max = 2000; + +; The number of times to retry locking the session lock, not including the first attempt. +; Default is 5. +memcached.sess_lock_retries = 5; ; The time, in seconds, before a lock should release itself. ; Setting to 0 results in the default behaviour, which is to @@ -29,16 +35,24 @@ memcached.sess_lock_expire = 0; ; the default value is "memc.sess.key." memcached.sess_prefix = "memc.sess.key." +; Whether or not to re-use the memcached connections corresponding to the value(s) +; of session.save_path after the execution of the script ends. +; Don't use this if certain settings (e.g. SASL settings, sess_binary_protocol) would +; be overridden between requests. +; Default is Off. +memcached.sess_persistent = Off + ; memcached session consistent hash mode ; if set to On, consistent hashing (libketama) is used ; for session handling. ; When consistent hashing is used, one can add or remove cache ; node(s) without messing up too much with existing keys -; default is Off -memcached.sess_consistent_hash = Off +; default is On +memcached.sess_consistent_hash = On -; Allow failed memcached server to automatically be removed -memcached.sess_remove_failed = 1 +; Allow failed memcached server to automatically be removed. +; Default is Off. (In previous versions, this setting was called memcached.sess_remove_failed) +memcached.sess_remove_failed_servers = Off ; Write data to a number of additional memcached servers ; This is "poor man's HA" as libmemcached calls it. @@ -57,7 +71,7 @@ memcached.sess_binary = Off memcached.sess_randomize_replica_read = Off ; memcached connect timeout value -; In non-blocking mode this changes the value of the timeout +; In non-blocking mode this changes the value of the timeout ; during socket connection in milliseconds. Specifying -1 means an infinite timeout. memcached.sess_connect_timeout = 1000 From b86282c5d6b7bacb435b4a49e5b986409a1c7c8a Mon Sep 17 00:00:00 2001 From: David Zuelke Date: Fri, 18 Mar 2016 20:40:14 +0100 Subject: [PATCH 081/345] add missing releases (and dates for all) to changelog --- ChangeLog | 76 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/ChangeLog b/ChangeLog index b9b00ea5..05f77181 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,17 @@ memcached extension changelog -Version 2.2.0b1 ---------------- +Version 2.2.0 (2014-04-01) +-------------------------- + * Added the OPT_SERVER_TIMEOUT_LIMIT behaviour + +Version 2.2.0RC1 (2014-03-12) +----------------------------- + * Added the OPT_SERVER_TIMEOUT_LIMIT behaviour + * Fixes incorrect size when compressing serialized objects + * Fixes endianess of compressed values + +Version 2.2.0b1 (2013-10-28) +---------------------------- * Reinstate support for libememcached 0.x series * Added SASL support to session handler * Added Memcached::flushBuffers as per GH #78 @@ -20,28 +30,28 @@ Version 2.2.0b1 * Added Memcached::setBucket for virtual bucket support * Added support for msgpack serialization * Memcached::setSaslAuthData returns correct status on success - * Added support for user-defined flags in set and get operations + * Added support for user-defined flags in set and get operations -Version 2.1.0 -------------- +Version 2.1.0 (2012-08-06) +-------------------------- * Drop support for libmemcached 0.x series, now 1.0.x is required * Add support for virtual bucket distribution * Fix compilation against PHP 5.2 -Version 2.0.1 -------------- +Version 2.0.1 (2012-03-03) +-------------------------- * Fix embedded version number to be not -dev -Version 2.0.0 -------------- +Version 2.0.0 (2012-03-02) +-------------------------- * Add touch() and touchByKey() methods * Add resetServerList() and quit() methods * Support binary protocol in sessions * Make it work with libmemcached up to 1.0.4 * Test against PHP 5.4.0 -Version 2.0.0b2 ---------------- +Version 2.0.0b2 (2011-06-24) +---------------------------- * Add OPT_REMOVE_FAILED_SERVERS option. * Make it work with libmemcached up to 0.49. * Fix a case where invalid session ID could lock the script. @@ -61,8 +71,8 @@ Version 2.0.0b2 * Make increment/decrement initialize value when it is not available (when using binary protocol) -Version 2.0.0b1 ---------------- +Version 2.0.0b1 (2011-03-12) +---------------------------- * Add fastlz library that provides better/faster payload compression * Add configure switch to enable/disable JSON serialization support * Add getAllKeys() method @@ -84,23 +94,27 @@ Version 2.0.0b1 * Add 'on_new' callback to constructor * Add SASL support -Version 1.0.1 -------------- +Version 1.0.2 (2010-05-03) +-------------------------- + * Fix build for libmemcached-0.39 (memcached_server_list() issue) + +Version 1.0.1 (2010-03-11) +-------------------------- * Fix JSON API handling to account for PHP 5.2/5.3 version differences. * Add memcached.sess_locking, memcached.sess_lock_wait, and memcached.sess_prefix INI entries. * Add OPT_AUTO_EJECT_HOSTS option. -Version 1.0.0 -------------- +Version 1.0.0 (2009-07-04) +-------------------------- * First stable release. * Add getResultMessage() method. * Fix OPT_RECV_TIMEOUT definition. * Initialize Session lock wait to max execution time (if max execution time is unlimited, default to 30 seconds). -Version 0.2.0 -------------- +Version 0.2.0 (2009-06-04) +-------------------------- * Add JSON serializer support, requires PHP 5.2.10+. * Add HAVE_JSON and HAVE_IGBINARY class constants that indicate whether the respective serializers are available. @@ -114,25 +128,25 @@ Version 0.2.0 the cache when upgrading to this version. * Add several tests. -Version 0.1.5 -------------- +Version 0.1.5 (2009-03-31) +-------------------------- * Implement getVersion(). * Add support for preserving boolean value types. * Fix crash when child class does not call constructor. * Fix bug #16084 (Crash when addServers is called with an associative array). * ZTS compilation fixes. -Version 0.1.4 -------------- +Version 0.1.4 (2009-02-13) +-------------------------- * Fix compilation against PHP 5.3. * Add support for 'igbinary' serializer (Oleg Grenrus) -Version 0.1.3 -------------- +Version 0.1.3 (2009-02-06) +-------------------------- * Bludgeon bug #15896 (Memcached setMulti error) into submission. -Version 0.1.2 -------------- +Version 0.1.2 (2009-02-06) +-------------------------- * Fix bug #15896 (Memcached setMulti error). * Check for empty key in getServerByKey(). * Allow passing 'null' for callbacks. @@ -141,12 +155,12 @@ Version 0.1.2 * Allow only strings as the append/prepend value. * Remove expiration parameter from append/prepend. -Version 0.1.1 -------------- +Version 0.1.1 (2009-02-02) +-------------------------- * Add OPT_LIBKETAMA_COMPATIBLE option. * Implement addServers() method. * Swap internal compressed and serialized flags to be compatible with other clients. -Version 0.1.0 -------------- +Version 0.1.0 (2009-01-29) +-------------------------- * Initial release From ffd1c64ccc5d38c4a12d6bd880e917171a77a8da Mon Sep 17 00:00:00 2001 From: David Zuelke Date: Fri, 18 Mar 2016 20:39:57 +0100 Subject: [PATCH 082/345] remove duplicate 2.2.0b1 from package.xml --- package.xml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/package.xml b/package.xml index 40f0323f..244acfab 100644 --- a/package.xml +++ b/package.xml @@ -225,20 +225,6 @@ Tests - Added the OPT_SERVER_TIMEOUT_LIMIT behaviour - - - betastable - 2.2.0b12.2.0 - 2013-10-28 - -- Reinstate support for libememcached 0.x series -- Added SASL support to session handler -- Added Memcached::flushBuffers as per GH #78 -- Fixes GH #54: Fixed UDP server adding with newer libmemcached -- Fixed PHP bug #65334: (Segfault if uncompress value failed) -- Fixes GH #14: get with cas token fails to fetch all results -- Fixes GH #69: compiling on CentOS 6.4 with libmemcached 1.0.17 - betastable From 4c13c4721fbac47262bd04bc6de47ea9f968b103 Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Sat, 2 Apr 2016 20:44:01 +0100 Subject: [PATCH 083/345] fix travis build, msgpack changed structure --- .travis/travis.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index 1eab43fb..453ed6be 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -79,7 +79,6 @@ function install_igbinary() { function install_msgpack() { git clone https://github.com/msgpack/msgpack-php.git pushd msgpack-php - git checkout php7 phpize ./configure make From 65ebcd5d62d6e374dadf6c335ba1736855e56f71 Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Sat, 2 Apr 2016 21:00:31 +0100 Subject: [PATCH 084/345] fix travis build, msgpack changed structure --- .travis/travis.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis/travis.sh b/.travis/travis.sh index f90cae9f..05f3da95 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -73,6 +73,7 @@ function install_igbinary() { function install_msgpack() { git clone https://github.com/msgpack/msgpack-php.git pushd msgpack-php + git checkout php5 phpize ./configure make From b79eebc923795d11ecb27ba9ee32cffcea09f033 Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Sat, 2 Apr 2016 21:01:59 +0100 Subject: [PATCH 085/345] fix ci img in readme [ci skip] --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index e827e6fa..bb76f076 100644 --- a/README.markdown +++ b/README.markdown @@ -1,6 +1,6 @@ Build Status ------------ -[![Build Status](https://travis-ci.org/php-memcached-dev/php-memcached.png?branch=master)](https://travis-ci.org/php-memcached-dev/php-memcached) +[![Build Status](https://travis-ci.org/php-memcached-dev/php-memcached.png?branch=php7)](https://travis-ci.org/php-memcached-dev/php-memcached) Description ----------- From 6ee96cad7be5caa1f13a1f3e5a4d5f900b9c04ce Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Mon, 4 Apr 2016 06:40:56 +0100 Subject: [PATCH 086/345] Fix #238 (memory errors in s_stat_execute_cb) --- php_memcached.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 9bff2fa8..dcf1f0da 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2635,8 +2635,7 @@ memcached_return s_stat_execute_cb (php_memcached_instance_st instance, const ch zval zv; array_init(&zv); - server_values = &zv; - add_assoc_zval_ex(return_value, server_key, server_key_len, server_values); + server_values = zend_hash_str_add(Z_ARRVAL_P(return_value), server_key, server_key_len, &zv); } spprintf (&buffer, 0, "%.*s", value_length, value); From f31ad20468a8b0ccdd57cf8028b807bd887b4089 Mon Sep 17 00:00:00 2001 From: Konstantin Leboev Date: Tue, 10 May 2016 13:25:28 +0300 Subject: [PATCH 087/345] Check the existence of an error, and only then if it is the maximum value. --- php_memcached.c | 4 ++-- tests/incrdecr.phpt | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index dcf1f0da..d9879f8c 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2248,11 +2248,11 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, } } - if (value == UINT64_MAX) { + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { RETURN_FALSE; } - if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + if (value == UINT64_MAX) { RETURN_FALSE; } diff --git a/tests/incrdecr.phpt b/tests/incrdecr.phpt index 3addcfd3..4a30daa6 100644 --- a/tests/incrdecr.phpt +++ b/tests/incrdecr.phpt @@ -10,8 +10,11 @@ $m = memc_get_instance (); echo "Not there\n"; $m->delete('foo'); var_dump($m->increment('foo', 1)); +var_dump($m->getResultCode()); var_dump($m->decrement('foo', 1)); +var_dump($m->getResultCode()); var_dump($m->get('foo')); +var_dump($m->getResultCode()); echo "Normal\n"; $m->set('foo', 1); @@ -37,8 +40,11 @@ var_dump($m->get('foo')); --EXPECT-- Not there bool(false) +int(16) bool(false) +int(16) bool(false) +int(16) Normal int(1) int(2) From d9b2c9f38410471adc5775543ac11aa5021b7647 Mon Sep 17 00:00:00 2001 From: Dick Tang Date: Thu, 9 Jun 2016 00:43:42 +0800 Subject: [PATCH 088/345] fix: null-terminated zend_string in s_decompress_value --- php_memcached.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index dcf1f0da..72db2cb2 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3443,6 +3443,8 @@ zend_string *s_decompress_value (const char *payload, size_t payload_len, uint32 decompress_status = (uncompress((Bytef *) buffer->val, &buffer->len, (Bytef *)payload, payload_len) == Z_OK); } + ZSTR_VAL(buffer)[stored_length] = '\0'; + if (!decompress_status) { php_error_docref(NULL, E_WARNING, "could not decompress value"); zend_string_release (buffer); From 7266824772d51f4a064e7478d6bbc551dcf445d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Magalh=C3=A3es?= Date: Thu, 9 Jun 2016 23:49:49 +0200 Subject: [PATCH 089/345] Fix object key validation --- php_memcached.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index c1bce93b..72bc8991 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -576,7 +576,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || strchr(key, ' ')) { + if (key_len == 0 || key_len > 250 || strchr(key, ' ') || strchr(key, '\n')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FROM_GET; } @@ -1448,7 +1448,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || strchr(key, ' ')) { + if (key_len == 0 || key_len > 250 || strchr(key, ' ') || strchr(key, '\n')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1599,7 +1599,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || strchr(key, ' ')) { + if (key_len == 0 || key_len > 250 || strchr(key, ' ') || strchr(key, '\n')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1717,7 +1717,7 @@ static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || strchr(key, ' ')) { + if (key_len == 0 || key_len > 250 || strchr(key, ' ') || strchr(key, '\n')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1817,7 +1817,7 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || strchr(key, ' ')) { + if (key_len == 0 || key_len > 250 || strchr(key, ' ') || strchr(key, '\n')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } From 382a786f9808e5b46cccf7e8e75399eaa79a7412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Magalh=C3=A3es?= Date: Fri, 10 Jun 2016 00:15:18 +0200 Subject: [PATCH 090/345] Added tests for the extended key validation --- tests/keys.phpt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/keys.phpt b/tests/keys.phpt index 0ed90896..7453d537 100644 --- a/tests/keys.phpt +++ b/tests/keys.phpt @@ -15,9 +15,18 @@ $ascii = memc_get_instance (); var_dump ($binary->set ('binary key with spaces', 'this is a test')); var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); +var_dump ($binary->set ('binarykeywith\nnewline', 'this is a test')); +var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); + var_dump ($ascii->set ('ascii key with spaces', 'this is a test')); var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); +var_dump ($binary->set ('asciikeywith\nnewline', 'this is a test')); +var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); + +var_dump ($ascii->set (''/*empty key*/, 'this is a test')); +var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); + var_dump ($ascii->set (str_repeat ('1234567890', 512), 'this is a test')); var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); @@ -30,4 +39,10 @@ bool(false) bool(true) bool(false) bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) OK From 5bd1a1fac50bf836fd96b0797326dd6b3f6663ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Magalh=C3=A3es?= Date: Fri, 10 Jun 2016 00:33:14 +0200 Subject: [PATCH 091/345] fix added tests --- tests/keys.phpt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/keys.phpt b/tests/keys.phpt index 7453d537..978670dc 100644 --- a/tests/keys.phpt +++ b/tests/keys.phpt @@ -15,13 +15,13 @@ $ascii = memc_get_instance (); var_dump ($binary->set ('binary key with spaces', 'this is a test')); var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); -var_dump ($binary->set ('binarykeywith\nnewline', 'this is a test')); +var_dump ($binary->set ('binarykeywithnewline' . PHP_EOL, 'this is a test')); var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); var_dump ($ascii->set ('ascii key with spaces', 'this is a test')); var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); -var_dump ($binary->set ('asciikeywith\nnewline', 'this is a test')); +var_dump ($binary->set ('asciikeywithnewline' . PHP_EOL, 'this is a test')); var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); var_dump ($ascii->set (''/*empty key*/, 'this is a test')); From 6e32d4013357ccc89c980ae6bf04bfa5efd1e15d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Magalh=C3=A3es?= Date: Sat, 11 Jun 2016 01:45:40 +0200 Subject: [PATCH 092/345] Use a constant for object key max length --- php_memcached.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 72bc8991..77dd8c29 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -57,6 +57,11 @@ #define JSON_PARSER_DEFAULT_DEPTH 512 #endif +/**************************************** + Protocol parameters +****************************************/ +#define MEMC_OBJECT_KEY_MAX_LENGTH 250 + /**************************************** Custom options ****************************************/ @@ -576,7 +581,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || key_len > 250 || strchr(key, ' ') || strchr(key, '\n')) { + if (key_len == 0 || key_len > MEMC_OBJECT_KEY_MAX_LENGTH || strchr(key, ' ') || strchr(key, '\n')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FROM_GET; } @@ -1448,7 +1453,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || key_len > 250 || strchr(key, ' ') || strchr(key, '\n')) { + if (key_len == 0 || key_len > MEMC_OBJECT_KEY_MAX_LENGTH || strchr(key, ' ') || strchr(key, '\n')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1599,7 +1604,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || key_len > 250 || strchr(key, ' ') || strchr(key, '\n')) { + if (key_len == 0 || key_len > MEMC_OBJECT_KEY_MAX_LENGTH || strchr(key, ' ') || strchr(key, '\n')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1717,7 +1722,7 @@ static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || key_len > 250 || strchr(key, ' ') || strchr(key, '\n')) { + if (key_len == 0 || key_len > MEMC_OBJECT_KEY_MAX_LENGTH || strchr(key, ' ') || strchr(key, '\n')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } @@ -1817,7 +1822,7 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, MEMC_METHOD_FETCH_OBJECT; i_obj->rescode = MEMCACHED_SUCCESS; - if (key_len == 0 || key_len > 250 || strchr(key, ' ') || strchr(key, '\n')) { + if (key_len == 0 || key_len > MEMC_OBJECT_KEY_MAX_LENGTH || strchr(key, ' ') || strchr(key, '\n')) { i_obj->rescode = MEMCACHED_BAD_KEY_PROVIDED; RETURN_FALSE; } From 0e517902d63ed82a9390bd8094d546f52899ce9f Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Thu, 21 Jul 2016 18:59:01 +0800 Subject: [PATCH 093/345] Improved the tests --- tests/001.phpt | 2 +- tests/add.phpt | 2 +- tests/append.phpt | 2 +- tests/bad_construct.phpt | 2 +- tests/bug_16084.phpt | 2 +- tests/bug_16959.phpt | 2 +- tests/bug_17137.phpt | 2 +- tests/bug_18639.phpt | 6 +++--- tests/cachecallback.phpt | 2 +- tests/callback_exception.phpt | 2 +- tests/callback_exception_2.phpt | 2 +- tests/cas.phpt | 2 +- tests/cas_multi.phpt | 2 +- tests/check_if_persistent.phpt | 2 +- tests/check_if_pristine.phpt | 2 +- tests/clone.phpt | 2 +- tests/compression_types.phpt | 2 +- tests/conf_persist.phpt | 2 +- tests/config.inc | 4 +++- tests/construct.phpt | 2 +- tests/construct_persistent.phpt | 2 +- tests/default_behavior.phpt | 2 +- tests/deleted.phpt | 2 +- tests/deletemulti.phpt | 2 +- tests/deletemultitypes.phpt | 2 +- tests/experimental/add_bykey.phpt | 6 +++--- tests/experimental/addserver_unixdomain.phpt | 2 +- tests/experimental/append_bykey.phpt | 6 +++--- tests/experimental/cas_bykey.phpt | 6 +++--- tests/experimental/cas_invalid_key.phpt | 6 +++--- tests/experimental/delete_bykey.phpt | 6 +++--- tests/experimental/deletemulti_nonstringkeys.phpt | 7 +++---- tests/experimental/extreme_floats.phpt | 6 +++--- tests/experimental/fetch.phpt | 6 +++--- tests/experimental/fetch_badunserialize.phpt | 6 +++--- tests/experimental/fetchall_badunserialize.phpt | 6 +++--- tests/experimental/get.phpt | 6 +++--- tests/experimental/get_bykey.phpt | 6 +++--- tests/experimental/get_bykey_cas.phpt | 6 +++--- tests/experimental/get_udp.phpt | 6 +++--- tests/experimental/getdelayed_badserver.phpt | 2 +- tests/experimental/getdelayed_badunserialize.phpt | 6 +++--- tests/experimental/getdelayed_bykey.phpt | 6 +++--- tests/experimental/getdelayed_bykey_cas.phpt | 6 +++--- tests/experimental/getdelayed_cbthrows.phpt | 6 +++--- tests/experimental/getdelayed_nonstring_keys.phpt | 6 +++--- tests/experimental/getmulti_badserver.phpt | 2 +- tests/experimental/getmulti_badunserialize.phpt | 6 +++--- tests/experimental/getmulti_bykey.phpt | 6 +++--- tests/experimental/getmulti_empty.phpt | 6 +++--- tests/experimental/getmulti_partial_error.phpt | 6 +++--- tests/experimental/getversion.phpt | 5 +++-- tests/experimental/locale_float.phpt | 13 +++++++------ tests/experimental/moduleinfo.phpt | 4 ++-- tests/experimental/prepend_bykey.phpt | 6 +++--- tests/experimental/replace_bykey.phpt | 6 +++--- tests/experimental/serializer/serializer_php.phpt | 6 +++--- .../serializer/serializer_php_bad_serialize.phpt | 6 +++--- .../serializer/serializer_php_bad_unserialize.phpt | 12 ++++++------ tests/experimental/serializer_igbinary.phpt | 2 +- tests/experimental/serializer_json.phpt | 2 +- tests/experimental/session_gc.phpt | 5 ++++- tests/experimental/set_bykey.phpt | 6 +++--- tests/experimental/set_comp_below_factor.phpt | 6 +++--- tests/experimental/set_default_serializer.phpt | 2 +- tests/experimental/set_invalid_serializer.phpt | 2 +- tests/experimental/setget_zero_factor.phpt | 6 +++--- tests/experimental/setmulti_badserialize.phpt | 6 +++--- tests/experimental/setmulti_bykey.phpt | 6 +++--- tests/experimental/stats.phpt | 2 +- tests/experimental/stats_badserver.phpt | 2 +- tests/expire.phpt | 2 +- tests/flush_buffers.phpt | 2 +- tests/get_flags.phpt | 2 +- tests/getdelayed.phpt | 2 +- tests/getmulti.phpt | 2 +- tests/getserverbykey.phpt | 2 +- tests/getserverlist.phpt | 2 +- tests/gh_155.phpt | 3 +-- tests/gh_21.phpt | 2 +- tests/gh_77.phpt | 2 +- tests/gh_90.phpt | 2 +- tests/gh_93.phpt | 2 +- tests/incrdecr.phpt | 2 +- tests/incrdecr_bykey.phpt | 2 +- tests/incrdecr_initial.phpt | 2 +- tests/incrdecr_invalid_key.phpt | 2 +- tests/invalid_options.phpt | 2 +- tests/invoke_callback.phpt | 6 +++--- tests/invoke_callback_2.phpt | 2 +- tests/invoke_callback_twice.phpt | 2 +- tests/keys.phpt | 2 +- tests/localserver.phpt | 2 +- tests/multi_order.phpt | 2 +- tests/no-not-found.phpt | 2 +- tests/options.phpt | 2 +- tests/pr_75.phpt | 2 +- tests/prepend.phpt | 2 +- tests/replace.phpt | 2 +- tests/rescode.phpt | 2 +- tests/session_badconf_emptyprefix.phpt | 2 +- tests/session_badconf_locktime.phpt | 2 +- tests/session_badconf_prefix.phpt | 2 +- tests/session_badconf_servers.phpt | 2 +- tests/session_basic.phpt | 2 +- tests/session_basic2.phpt | 2 +- tests/session_basic3.phpt | 2 +- tests/session_lock.phpt | 2 +- tests/session_regenerate.phpt | 2 +- tests/set_large.phpt | 2 +- tests/setmulti.phpt | 2 +- tests/setoptions.phpt | 2 +- tests/stats.phpt | 2 +- tests/touch_binary.phpt | 2 +- tests/types_igbinary.phpt | 2 +- tests/types_igbinary_multi.phpt | 2 +- tests/types_json.phpt | 2 +- tests/types_json_multi.phpt | 2 +- tests/types_msgpack.phpt | 2 +- tests/types_msgpack_multi.phpt | 2 +- tests/types_php.phpt | 2 +- tests/types_php_multi.phpt | 2 +- tests/undefined_set.phpt | 2 +- tests/user-flags.phpt | 2 +- tests/vbucket.phpt | 4 ++-- tests/version.phpt | 2 +- 126 files changed, 214 insertions(+), 209 deletions(-) diff --git a/tests/001.phpt b/tests/001.phpt index d5085cd5..a66d6df3 100644 --- a/tests/001.phpt +++ b/tests/001.phpt @@ -1,7 +1,7 @@ --TEST-- Check for memcached presence --SKIPIF-- - + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- array ( 'KEYHERE' => 'localhost', 11211, 3 ), ); diff --git a/tests/bug_16959.phpt b/tests/bug_16959.phpt index f03a7091..2411e15a 100644 --- a/tests/bug_16959.phpt +++ b/tests/bug_16959.phpt @@ -1,7 +1,7 @@ --TEST-- Memcached: Bug #16959 (getMulti + BINARY_PROTOCOL problem) --SKIPIF-- - + --FILE-- + --FILE-- + --FILE-- getServerByKey('1')); bool(true) array(3) { ["host"]=> - string(9) "127.0.0.1" + string(9) "%s" ["port"]=> - int(11211) + int(%d) ["weight"]=> int(%r[01]%r) } diff --git a/tests/cachecallback.phpt b/tests/cachecallback.phpt index 31a736b7..41edfc5c 100644 --- a/tests/cachecallback.phpt +++ b/tests/cachecallback.phpt @@ -1,7 +1,7 @@ --TEST-- Memcached::get() with cache callback --SKIPIF-- - + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- --FILE-- --FILE-- + --FILE-- + --FILE-- + --FILE-- addServer($host, $port); - $memcached->flush (); + if ($memcached->flush() === false) { + return NULL; + } return $memcached; } diff --git a/tests/construct.phpt b/tests/construct.phpt index c5c78977..49e508e7 100644 --- a/tests/construct.phpt +++ b/tests/construct.phpt @@ -1,7 +1,7 @@ --TEST-- Memcached constructor --SKIPIF-- - + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $m->delete('foo'); var_dump($m->addByKey('foo', 'foo', 1, 10)); diff --git a/tests/experimental/addserver_unixdomain.phpt b/tests/experimental/addserver_unixdomain.phpt index aaec92ae..4848015d 100644 --- a/tests/experimental/addserver_unixdomain.phpt +++ b/tests/experimental/addserver_unixdomain.phpt @@ -1,7 +1,7 @@ --TEST-- Memcached::addServer() unix doamin socket --SKIPIF-- - + --CLEAN-- + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $m->setOption(Memcached::OPT_COMPRESSION, false); var_dump($m->setByKey('foo', 'foo', 'bar', 10)); diff --git a/tests/experimental/cas_bykey.phpt b/tests/experimental/cas_bykey.phpt index f33e24ad..f8c80fa5 100644 --- a/tests/experimental/cas_bykey.phpt +++ b/tests/experimental/cas_bykey.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::casByKey() --SKIPIF-- - + --FILE-- addServer('127.0.0.1', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $m->delete('cas_test'); $cas_token = null; diff --git a/tests/experimental/cas_invalid_key.phpt b/tests/experimental/cas_invalid_key.phpt index 3a69e40e..6011c4b8 100644 --- a/tests/experimental/cas_invalid_key.phpt +++ b/tests/experimental/cas_invalid_key.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::cas() with strange key --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); error_reporting(0); var_dump($m->cas(0, '', true, 10)); diff --git a/tests/experimental/delete_bykey.phpt b/tests/experimental/delete_bykey.phpt index 9a198f15..807af8ca 100644 --- a/tests/experimental/delete_bykey.phpt +++ b/tests/experimental/delete_bykey.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::deleteByKey() --SKIPIF-- - + --FILE-- addServer('127.0.0.1', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $m->setByKey('keffe', 'eisaleeoo', "foo"); var_dump($m->getByKey('keffe', 'eisaleeoo')); diff --git a/tests/experimental/deletemulti_nonstringkeys.phpt b/tests/experimental/deletemulti_nonstringkeys.phpt index 69d56c78..2dac8920 100644 --- a/tests/experimental/deletemulti_nonstringkeys.phpt +++ b/tests/experimental/deletemulti_nonstringkeys.phpt @@ -1,12 +1,11 @@ --TEST-- Delete multi with integer keys --SKIPIF-- - + --FILE-- addServer('127.0.0.1', 11211, 1); -$m->addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $data = array( 1 => '1-data', diff --git a/tests/experimental/extreme_floats.phpt b/tests/experimental/extreme_floats.phpt index 0d530370..80ef568d 100644 --- a/tests/experimental/extreme_floats.phpt +++ b/tests/experimental/extreme_floats.phpt @@ -1,11 +1,11 @@ --TEST-- Extreme floats: max, min, Inf, -Inf, and NaN --SKIPIF-- - + --FILE-- addServer('127.0.0.1', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $m->set('float_inf', INF); $m->set('float_ninf', -INF); diff --git a/tests/experimental/fetch.phpt b/tests/experimental/fetch.phpt index e7eee9d3..13136c5b 100644 --- a/tests/experimental/fetch.phpt +++ b/tests/experimental/fetch.phpt @@ -1,7 +1,7 @@ --TEST-- Memcached getDelayed() and fetch() with and without cas --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $data = array( 'foo' => 'foo-data', diff --git a/tests/experimental/fetch_badunserialize.phpt b/tests/experimental/fetch_badunserialize.phpt index 36a3049e..251d2ca5 100644 --- a/tests/experimental/fetch_badunserialize.phpt +++ b/tests/experimental/fetch_badunserialize.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::fetch() with bad unserialize --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); class Foo implements Serializable { public $serialize_throws = false; diff --git a/tests/experimental/fetchall_badunserialize.phpt b/tests/experimental/fetchall_badunserialize.phpt index 6108498a..e3ad3310 100644 --- a/tests/experimental/fetchall_badunserialize.phpt +++ b/tests/experimental/fetchall_badunserialize.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::fetch() with bad unserialize --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); class Foo implements Serializable { public $serialize_throws = false; diff --git a/tests/experimental/get.phpt b/tests/experimental/get.phpt index 67e0b8f3..308bda98 100644 --- a/tests/experimental/get.phpt +++ b/tests/experimental/get.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::get() --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $m->delete('foo'); diff --git a/tests/experimental/get_bykey.phpt b/tests/experimental/get_bykey.phpt index 220dd44a..a392aaeb 100644 --- a/tests/experimental/get_bykey.phpt +++ b/tests/experimental/get_bykey.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::getByKey() --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $m->set('foo', 1, 10); diff --git a/tests/experimental/get_bykey_cas.phpt b/tests/experimental/get_bykey_cas.phpt index 6990927b..501b13a7 100644 --- a/tests/experimental/get_bykey_cas.phpt +++ b/tests/experimental/get_bykey_cas.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::getByKey() with CAS --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); function the_callback(Memcached $memc, $key, &$value) { echo "called\n"; diff --git a/tests/experimental/get_udp.phpt b/tests/experimental/get_udp.phpt index 3e038e10..ad10a7cf 100644 --- a/tests/experimental/get_udp.phpt +++ b/tests/experimental/get_udp.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::set()/delete() UDP --SKIPIF-- - + --FILE-- addServer('127.0.0.1', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $m_udp = new Memcached(); $m_udp->setOption(Memcached::OPT_USE_UDP, true); diff --git a/tests/experimental/getdelayed_badserver.phpt b/tests/experimental/getdelayed_badserver.phpt index dc0508fb..c4902174 100644 --- a/tests/experimental/getdelayed_badserver.phpt +++ b/tests/experimental/getdelayed_badserver.phpt @@ -1,7 +1,7 @@ --TEST-- Memcached::getDelayedByKey() with bad server --SKIPIF-- - + --FILE-- + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); class Foo implements Serializable { public $serialize_throws = false; diff --git a/tests/experimental/getdelayed_bykey.phpt b/tests/experimental/getdelayed_bykey.phpt index 4b3ddf6b..a29f646b 100644 --- a/tests/experimental/getdelayed_bykey.phpt +++ b/tests/experimental/getdelayed_bykey.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::getDelayedByKey() --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $data = array( 'foo' => 'foo-data', diff --git a/tests/experimental/getdelayed_bykey_cas.phpt b/tests/experimental/getdelayed_bykey_cas.phpt index b874e739..43b19596 100644 --- a/tests/experimental/getdelayed_bykey_cas.phpt +++ b/tests/experimental/getdelayed_bykey_cas.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::getDelayedByKey() with CAS --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $data = array( 'foo' => 'foo-data', diff --git a/tests/experimental/getdelayed_cbthrows.phpt b/tests/experimental/getdelayed_cbthrows.phpt index 482034b6..2b71b4b4 100644 --- a/tests/experimental/getdelayed_cbthrows.phpt +++ b/tests/experimental/getdelayed_cbthrows.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::getDelayedByKey() with callback exception --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $data = array( 'foo' => 'foo-data', diff --git a/tests/experimental/getdelayed_nonstring_keys.phpt b/tests/experimental/getdelayed_nonstring_keys.phpt index 0e68344f..81363f3b 100644 --- a/tests/experimental/getdelayed_nonstring_keys.phpt +++ b/tests/experimental/getdelayed_nonstring_keys.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached getDelayed non string keys --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); class Bar { public function __toString() { diff --git a/tests/experimental/getmulti_badserver.phpt b/tests/experimental/getmulti_badserver.phpt index 21bbe192..a34825c2 100644 --- a/tests/experimental/getmulti_badserver.phpt +++ b/tests/experimental/getmulti_badserver.phpt @@ -1,7 +1,7 @@ --TEST-- Memcached::getMulti() bad server --SKIPIF-- - + --FILE-- + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); class Foo implements Serializable { public function __sleep() { diff --git a/tests/experimental/getmulti_bykey.phpt b/tests/experimental/getmulti_bykey.phpt index 70ae01c5..e4eb112c 100644 --- a/tests/experimental/getmulti_bykey.phpt +++ b/tests/experimental/getmulti_bykey.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::getMultiByKey() --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $m->set('foo', 1, 10); $m->set('bar', 2, 10); diff --git a/tests/experimental/getmulti_empty.phpt b/tests/experimental/getmulti_empty.phpt index 7c8621da..6279104d 100644 --- a/tests/experimental/getmulti_empty.phpt +++ b/tests/experimental/getmulti_empty.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::getMulti() with empty array --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $v = $m->getMulti(array()); var_dump($v); diff --git a/tests/experimental/getmulti_partial_error.phpt b/tests/experimental/getmulti_partial_error.phpt index dc4daa50..fa392e9e 100644 --- a/tests/experimental/getmulti_partial_error.phpt +++ b/tests/experimental/getmulti_partial_error.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::getMulti() partial error --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $data = array(); for ($i = 0; $i < 1000; $i++) { diff --git a/tests/experimental/getversion.phpt b/tests/experimental/getversion.phpt index 509ff5d5..55d06714 100644 --- a/tests/experimental/getversion.phpt +++ b/tests/experimental/getversion.phpt @@ -1,13 +1,14 @@ --TEST-- Memcached::getVersion() --SKIPIF-- - + --FILE-- getVersion()); -$m->addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . "/config.inc"; +$m = memc_get_instance (); $stats = $m->getVersion(); var_dump($stats); diff --git a/tests/experimental/locale_float.phpt b/tests/experimental/locale_float.phpt index e6967bdb..9c512124 100644 --- a/tests/experimental/locale_float.phpt +++ b/tests/experimental/locale_float.phpt @@ -2,14 +2,15 @@ Float should not consider locale --SKIPIF-- addServer('127.0.0.1', 11211); + +include dirname (__FILE__) . '/config.inc'; +$memcache = memc_get_instance (); setlocale(LC_NUMERIC, "fi_FI", 'sv_SV', 'nl_NL'); diff --git a/tests/experimental/moduleinfo.phpt b/tests/experimental/moduleinfo.phpt index a1f59b44..0f02a570 100644 --- a/tests/experimental/moduleinfo.phpt +++ b/tests/experimental/moduleinfo.phpt @@ -2,7 +2,7 @@ Memcached::phpinfo() --SKIPIF-- --FILE-- @@ -35,4 +35,4 @@ memcached.sess_prefix => %s => %s memcached.sess_randomize_replica_read => %d => %d memcached.sess_remove_failed => %d => %d %rmemcached.use_sasl => %d => %d -|%rmemcached.store_retry_count => %d => %d \ No newline at end of file +|%rmemcached.store_retry_count => %d => %d diff --git a/tests/experimental/prepend_bykey.phpt b/tests/experimental/prepend_bykey.phpt index 85b12f98..87d3fd38 100644 --- a/tests/experimental/prepend_bykey.phpt +++ b/tests/experimental/prepend_bykey.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::appendByKey() --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $m->setOption(Memcached::OPT_COMPRESSION, false); var_dump($m->setByKey('foo', 'foo', 'bar', 10)); diff --git a/tests/experimental/replace_bykey.phpt b/tests/experimental/replace_bykey.phpt index 1cd858fb..b2f72836 100644 --- a/tests/experimental/replace_bykey.phpt +++ b/tests/experimental/replace_bykey.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::replaceByKey() --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); error_reporting(0); $m->delete('foo'); diff --git a/tests/experimental/serializer/serializer_php.phpt b/tests/experimental/serializer/serializer_php.phpt index ce3e7266..853d5bf4 100644 --- a/tests/experimental/serializer/serializer_php.phpt +++ b/tests/experimental/serializer/serializer_php.phpt @@ -2,12 +2,12 @@ Serializer basic --SKIPIF-- --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(dirname(__FILE__))) . '/config.inc'; +$m = memc_get_instance (); $serializer = Memcached::SERIALIZER_PHP; if (isset($_ENV['TEST_MEMC_SERIALIZER'])) { eval(sprintf('$serializer = %s;', $_ENV['TEST_MEMC_SERIALIZER'])); diff --git a/tests/experimental/serializer/serializer_php_bad_serialize.phpt b/tests/experimental/serializer/serializer_php_bad_serialize.phpt index 39ef4745..81e88b0c 100644 --- a/tests/experimental/serializer/serializer_php_bad_serialize.phpt +++ b/tests/experimental/serializer/serializer_php_bad_serialize.phpt @@ -2,7 +2,7 @@ Serializer: exception while serializing --SKIPIF-- addServer('localhost', 11211, 1); +include dirname(dirname(dirname(__FILE__))) . '/config.inc'; +$m = memc_get_instance (); $serializer = Memcached::SERIALIZER_PHP; if (isset($_ENV['TEST_MEMC_SERIALIZER'])) { eval(sprintf('$serializer = %s;', $_ENV['TEST_MEMC_SERIALIZER'])); diff --git a/tests/experimental/serializer/serializer_php_bad_unserialize.phpt b/tests/experimental/serializer/serializer_php_bad_unserialize.phpt index 86fba091..39d2cc37 100644 --- a/tests/experimental/serializer/serializer_php_bad_unserialize.phpt +++ b/tests/experimental/serializer/serializer_php_bad_unserialize.phpt @@ -2,10 +2,10 @@ Serializer: exception while unserializing --SKIPIF-- addServer('localhost', 11211, 1); +include dirname(dirname(dirname(__FILE__))) . '/config.inc'; +$m = memc_get_instance (); $serializer = Memcached::SERIALIZER_PHP; if (isset($_ENV['TEST_MEMC_SERIALIZER'])) { eval(sprintf('$serializer = %s;', $_ENV['TEST_MEMC_SERIALIZER'])); diff --git a/tests/experimental/serializer_igbinary.phpt b/tests/experimental/serializer_igbinary.phpt index a762121e..4d2360bc 100644 --- a/tests/experimental/serializer_igbinary.phpt +++ b/tests/experimental/serializer_igbinary.phpt @@ -2,7 +2,7 @@ Serialize igbinary --SKIPIF-- diff --git a/tests/experimental/session_gc.phpt b/tests/experimental/session_gc.phpt index 561901fc..61dc7d3d 100644 --- a/tests/experimental/session_gc.phpt +++ b/tests/experimental/session_gc.phpt @@ -2,7 +2,10 @@ Session expiration --SKIPIF-- --INI-- diff --git a/tests/experimental/set_bykey.phpt b/tests/experimental/set_bykey.phpt index fa6d6a4b..e1fec459 100644 --- a/tests/experimental/set_bykey.phpt +++ b/tests/experimental/set_bykey.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::setByKey() --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); var_dump($m->setByKey('foo', 'foo', 1, 10)); echo $m->getResultMessage(), "\n"; diff --git a/tests/experimental/set_comp_below_factor.phpt b/tests/experimental/set_comp_below_factor.phpt index f3eece2f..12e6d6a4 100644 --- a/tests/experimental/set_comp_below_factor.phpt +++ b/tests/experimental/set_comp_below_factor.phpt @@ -1,11 +1,11 @@ --TEST-- Compress below factor and fail to plain. --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); ini_set('memcached.compression_threshold', 100); ini_set('memcached.compression_factor', 10); diff --git a/tests/experimental/set_default_serializer.phpt b/tests/experimental/set_default_serializer.phpt index f9658736..4886e9b7 100644 --- a/tests/experimental/set_default_serializer.phpt +++ b/tests/experimental/set_default_serializer.phpt @@ -1,7 +1,7 @@ --TEST-- Set default serializer --SKIPIF-- - + --FILE-- + --FILE-- + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); ini_set('memcached.compression_factor', 0); $array = range(1, 20000, 1); diff --git a/tests/experimental/setmulti_badserialize.phpt b/tests/experimental/setmulti_badserialize.phpt index b12b1d3a..5081eedc 100644 --- a/tests/experimental/setmulti_badserialize.phpt +++ b/tests/experimental/setmulti_badserialize.phpt @@ -1,11 +1,11 @@ --TEST-- Memcached::setMultiByKey() with bad serialize --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); class Foo implements Serializable { public function __sleep() { diff --git a/tests/experimental/setmulti_bykey.phpt b/tests/experimental/setmulti_bykey.phpt index fad3db29..e3533c2f 100644 --- a/tests/experimental/setmulti_bykey.phpt +++ b/tests/experimental/setmulti_bykey.phpt @@ -1,7 +1,7 @@ --TEST-- Memcached::setMultiByKey() --SKIPIF-- - + --FILE-- addServer('localhost', 11211, 1); +include dirname(dirname(__FILE__)) . '/config.inc'; +$m = memc_get_instance (); $data = array( 'foo' => 'foo-data', diff --git a/tests/experimental/stats.phpt b/tests/experimental/stats.phpt index 4f416384..26d814ce 100644 --- a/tests/experimental/stats.phpt +++ b/tests/experimental/stats.phpt @@ -1,7 +1,7 @@ --TEST-- Memcached::getStats() --SKIPIF-- - + --FILE-- + --FILE-- --FILE-- diff --git a/tests/flush_buffers.phpt b/tests/flush_buffers.phpt index 989a4b63..a345edce 100644 --- a/tests/flush_buffers.phpt +++ b/tests/flush_buffers.phpt @@ -1,7 +1,7 @@ --TEST-- Test flushing buffers --SKIPIF-- - + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- array ( 'KEYHERE' => 'localhost', 11211, 3 ), ); diff --git a/tests/gh_155.phpt b/tests/gh_155.phpt index 643085ae..54d2b77f 100644 --- a/tests/gh_155.phpt +++ b/tests/gh_155.phpt @@ -2,8 +2,7 @@ Test for bug 155 --SKIPIF-- --FILE-- diff --git a/tests/gh_21.phpt b/tests/gh_21.phpt index 7302220e..920fb659 100644 --- a/tests/gh_21.phpt +++ b/tests/gh_21.phpt @@ -1,7 +1,7 @@ --TEST-- Test for Github issue 21 --SKIPIF-- - + --FILE-- --FILE-- diff --git a/tests/gh_90.phpt b/tests/gh_90.phpt index 9434a2d7..733b7615 100644 --- a/tests/gh_90.phpt +++ b/tests/gh_90.phpt @@ -1,7 +1,7 @@ --TEST-- Test for GH #90 --SKIPIF-- - + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- array(3) { ["host"]=> - string(9) "127.0.0.1" + string(9) "%s" ["port"]=> - int(11211) + int(%d) ["type"]=> string(3) "TCP" } diff --git a/tests/invoke_callback_2.phpt b/tests/invoke_callback_2.phpt index 276d1c26..07e84f94 100644 --- a/tests/invoke_callback_2.phpt +++ b/tests/invoke_callback_2.phpt @@ -1,7 +1,7 @@ --TEST-- Use callback initializer --SKIPIF-- - + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- --INI-- diff --git a/tests/session_badconf_locktime.phpt b/tests/session_badconf_locktime.phpt index 9bda76b6..edb2a49f 100644 --- a/tests/session_badconf_locktime.phpt +++ b/tests/session_badconf_locktime.phpt @@ -1,7 +1,7 @@ --TEST-- Session bad configurations, lock wait time --SKIPIF-- - --INI-- diff --git a/tests/session_badconf_prefix.phpt b/tests/session_badconf_prefix.phpt index 093485c4..c42e8376 100644 --- a/tests/session_badconf_prefix.phpt +++ b/tests/session_badconf_prefix.phpt @@ -2,7 +2,7 @@ Session bad configurations, prefix --SKIPIF-- --INI-- diff --git a/tests/session_badconf_servers.phpt b/tests/session_badconf_servers.phpt index 9fd911cd..b5c0803b 100644 --- a/tests/session_badconf_servers.phpt +++ b/tests/session_badconf_servers.phpt @@ -2,7 +2,7 @@ Session bad configurations, invalid save path (server list) --SKIPIF-- --INI-- diff --git a/tests/session_basic.phpt b/tests/session_basic.phpt index c5a464b5..3fdb6bd7 100644 --- a/tests/session_basic.phpt +++ b/tests/session_basic.phpt @@ -2,7 +2,7 @@ Session basic open, write, destroy --SKIPIF-- --INI-- diff --git a/tests/session_basic2.phpt b/tests/session_basic2.phpt index 782ae6d3..0a06c457 100644 --- a/tests/session_basic2.phpt +++ b/tests/session_basic2.phpt @@ -2,7 +2,7 @@ Session basic open, write, destroy --SKIPIF-- --INI-- diff --git a/tests/session_basic3.phpt b/tests/session_basic3.phpt index 21288571..d684fa35 100644 --- a/tests/session_basic3.phpt +++ b/tests/session_basic3.phpt @@ -2,7 +2,7 @@ Session basic open, write, destroy --SKIPIF-- --INI-- diff --git a/tests/session_lock.phpt b/tests/session_lock.phpt index a328dd68..79c32888 100644 --- a/tests/session_lock.phpt +++ b/tests/session_lock.phpt @@ -2,7 +2,7 @@ Session lock --SKIPIF-- --INI-- diff --git a/tests/session_regenerate.phpt b/tests/session_regenerate.phpt index 794f46fc..bbd37fa2 100644 --- a/tests/session_regenerate.phpt +++ b/tests/session_regenerate.phpt @@ -2,7 +2,7 @@ Session regenerate --SKIPIF-- --INI-- diff --git a/tests/set_large.phpt b/tests/set_large.phpt index bf1098ef..f3cb4cc3 100644 --- a/tests/set_large.phpt +++ b/tests/set_large.phpt @@ -1,7 +1,7 @@ --TEST-- set large data --SKIPIF-- - + --FILE-- + --FILE-- + --FILE-- + --FILE-- --FILE-- diff --git a/tests/types_igbinary.phpt b/tests/types_igbinary.phpt index 62fcc29b..da1b26fa 100644 --- a/tests/types_igbinary.phpt +++ b/tests/types_igbinary.phpt @@ -2,7 +2,7 @@ Memcached store & fetch type and value correctness using igbinary serializer --SKIPIF-- --FILE-- diff --git a/tests/types_igbinary_multi.phpt b/tests/types_igbinary_multi.phpt index 33f4df67..2a0823e0 100644 --- a/tests/types_igbinary_multi.phpt +++ b/tests/types_igbinary_multi.phpt @@ -2,7 +2,7 @@ Memcached multi store & multi fetch type and value correctness using igbinary serializer --SKIPIF-- --FILE-- diff --git a/tests/types_json.phpt b/tests/types_json.phpt index f5735f6d..2491fea7 100644 --- a/tests/types_json.phpt +++ b/tests/types_json.phpt @@ -2,7 +2,7 @@ Memcached store & fetch type and value correctness using JSON serializer --SKIPIF-- --FILE-- diff --git a/tests/types_json_multi.phpt b/tests/types_json_multi.phpt index 6a085039..b6bc203e 100644 --- a/tests/types_json_multi.phpt +++ b/tests/types_json_multi.phpt @@ -2,7 +2,7 @@ Memcached multi store & multi fetch type and value correctness using JSON serializer --SKIPIF-- --FILE-- diff --git a/tests/types_msgpack.phpt b/tests/types_msgpack.phpt index aed43627..aad0d5bb 100644 --- a/tests/types_msgpack.phpt +++ b/tests/types_msgpack.phpt @@ -2,7 +2,7 @@ Memcached store & fetch type and value correctness using msgpack serializer --SKIPIF-- --FILE-- diff --git a/tests/types_msgpack_multi.phpt b/tests/types_msgpack_multi.phpt index dcf251e1..4ba42347 100644 --- a/tests/types_msgpack_multi.phpt +++ b/tests/types_msgpack_multi.phpt @@ -2,7 +2,7 @@ Memcached multi store & fetch type and value correctness using msgpack serializer --SKIPIF-- --FILE-- diff --git a/tests/types_php.phpt b/tests/types_php.phpt index f6baab5b..8d99f375 100644 --- a/tests/types_php.phpt +++ b/tests/types_php.phpt @@ -1,7 +1,7 @@ --TEST-- Memcached store & fetch type and value correctness using PHP serializer --SKIPIF-- - + --FILE-- + --FILE-- + --FILE-- + --FILE-- --FILE-- @@ -45,4 +45,4 @@ NULL Warning: Memcached::setBucket(): the map must contain positive integers in %s on line %d bool(false) -OK \ No newline at end of file +OK diff --git a/tests/version.phpt b/tests/version.phpt index 8ffe275a..06cd537b 100644 --- a/tests/version.phpt +++ b/tests/version.phpt @@ -1,7 +1,7 @@ --TEST-- Get version --SKIPIF-- - + --FILE-- Date: Sat, 23 Jul 2016 11:11:34 +0800 Subject: [PATCH 094/345] Added skipif.inc --- tests/skipif.inc | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/skipif.inc diff --git a/tests/skipif.inc b/tests/skipif.inc new file mode 100644 index 00000000..bcd32d25 --- /dev/null +++ b/tests/skipif.inc @@ -0,0 +1,10 @@ + Date: Sat, 23 Jul 2016 12:11:31 +0800 Subject: [PATCH 095/345] Cleanup --- php_memcached.c | 147 ++++++++++++++++++++++++------------------------ 1 file changed, 73 insertions(+), 74 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 31bec912..3bd5ee48 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -241,9 +241,9 @@ static PHP_INI_MH(OnUpdateCompressionType) { if (!new_value) { MEMC_G(compression_type) = COMPRESSION_TYPE_FASTLZ; - } else if (!strcmp(new_value->val, "fastlz")) { + } else if (!strcmp(ZSTR_VAL(new_value), "fastlz")) { MEMC_G(compression_type) = COMPRESSION_TYPE_FASTLZ; - } else if (!strcmp(new_value->val, "zlib")) { + } else if (!strcmp(ZSTR_VAL(new_value), "zlib")) { MEMC_G(compression_type) = COMPRESSION_TYPE_ZLIB; } else { return FAILURE; @@ -255,20 +255,20 @@ static PHP_INI_MH(OnUpdateSerializer) { if (!new_value) { MEMC_G(serializer_type) = SERIALIZER_DEFAULT; - } else if (!strcmp(new_value->val, "php")) { + } else if (!strcmp(ZSTR_VAL(new_value), "php")) { MEMC_G(serializer_type) = SERIALIZER_PHP; #ifdef HAVE_MEMCACHED_IGBINARY - } else if (!strcmp(new_value->val, "igbinary")) { + } else if (!strcmp(ZSTR_VAL(new_value), "igbinary")) { MEMC_G(serializer_type) = SERIALIZER_IGBINARY; #endif // IGBINARY #ifdef HAVE_JSON_API - } else if (!strcmp(new_value->val, "json")) { + } else if (!strcmp(ZSTR_VAL(new_value), "json")) { MEMC_G(serializer_type) = SERIALIZER_JSON; - } else if (!strcmp(new_value->val, "json_array")) { + } else if (!strcmp(ZSTR_VAL(new_value), "json_array")) { MEMC_G(serializer_type) = SERIALIZER_JSON_ARRAY; #endif // JSON #ifdef HAVE_MEMCACHED_MSGPACK - } else if (!strcmp(new_value->val, "msgpack")) { + } else if (!strcmp(ZSTR_VAL(new_value), "msgpack")) { MEMC_G(serializer_type) = SERIALIZER_MSGPACK; #endif // msgpack } else { @@ -281,7 +281,7 @@ static PHP_INI_MH(OnUpdateSerializer) static PHP_INI_MH(OnUpdateDeprecatedLockValue) { - if (new_value->len > 0 && strcmp(new_value->val, "not set")) { + if (ZSTR_LEN(new_value) > 0 && strcmp(ZSTR_VAL(new_value), "not set")) { php_error_docref(NULL, E_DEPRECATED, "memcached.sess_lock_wait and memcached.sess_lock_max_wait are deprecated. Please update your configuration to use memcached.sess_lock_wait_min, memcached.sess_lock_wait_max and memcached.sess_lock_retries"); } return FAILURE; @@ -290,8 +290,8 @@ PHP_INI_MH(OnUpdateDeprecatedLockValue) static PHP_INI_MH(OnUpdateSessionPrefixString) { - if (new_value && new_value->len > 0) { - char *ptr = new_value->val; + if (new_value && ZSTR_LEN(new_value) > 0) { + char *ptr = ZSTR_VAL(new_value); while (*ptr != '\0') { if (isspace (*ptr++)) { @@ -299,7 +299,7 @@ PHP_INI_MH(OnUpdateSessionPrefixString) return FAILURE; } } - if (new_value->len > MEMCACHED_MAX_KEY) { + if (ZSTR_LEN(new_value) > MEMCACHED_MAX_KEY) { php_error_docref(NULL, E_WARNING, "memcached.sess_prefix too long (max: %d)", MEMCACHED_MAX_KEY - 1); return FAILURE; } @@ -672,7 +672,7 @@ zend_bool php_memc_mget_apply(php_memc_object_t *intern, zend_string *server_key } if (server_key) { - status = memcached_mget_by_key(intern->memc, server_key->val, server_key->len, keys->mkeys, keys->mkeys_len, keys->num_valid_keys); + status = memcached_mget_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), keys->mkeys, keys->mkeys_len, keys->num_valid_keys); } else { status = memcached_mget(intern->memc, keys->mkeys, keys->mkeys_len, keys->num_valid_keys); } @@ -810,18 +810,18 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str zend_string *payload = *payload_in; /* Additional 5% for the data */ - size_t buffer_size = (size_t) (((double) payload->len * 1.05) + 1.0); + size_t buffer_size = (size_t) (((double) ZSTR_LEN(payload) * 1.05) + 1.0); char *buffer = emalloc(buffer_size); /* Store compressed size here */ size_t compressed_size = 0; - uint32_t original_size = payload->len; + uint32_t original_size = ZSTR_LEN(payload); switch (compression_type) { case COMPRESSION_TYPE_FASTLZ: { - compressed_size = fastlz_compress(payload->val, payload->len, buffer); + compressed_size = fastlz_compress(ZSTR_VAL(payload), ZSTR_LEN(payload), buffer); if (compressed_size > 0) { compress_status = 1; @@ -833,7 +833,7 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str case COMPRESSION_TYPE_ZLIB: { compressed_size = buffer_size; - int status = compress((Bytef *) buffer, &compressed_size, (Bytef *) payload->val, payload->len); + int status = compress((Bytef *) buffer, &compressed_size, (Bytef *) ZSTR_VAL(payload), ZSTR_LEN(payload)); if (status == Z_OK) { compress_status = 1; @@ -855,7 +855,7 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str } /* This means the value was too small to be compressed, still a success */ - if (compressed_size > (payload->len * MEMC_G(compression_factor))) { + if (compressed_size > (ZSTR_LEN(payload) * MEMC_G(compression_factor))) { MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); efree (buffer); return 1; @@ -864,8 +864,8 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str payload = zend_string_realloc(payload, compressed_size + sizeof(uint32_t), 0); /* Copy the uin32_t at the beginning */ - memcpy(payload->val, &original_size, sizeof(uint32_t)); - memcpy(payload->val + sizeof (uint32_t), buffer, compressed_size); + memcpy(ZSTR_VAL(payload), &original_size, sizeof(uint32_t)); + memcpy(ZSTR_VAL(payload) + sizeof (uint32_t), buffer, compressed_size); efree(buffer); zend_string_forget_hash_val(payload); @@ -1014,7 +1014,7 @@ zend_string *s_zval_to_payload(php_memc_object_t *intern, zval *value, uint32_t zend_string_forget_hash_val(payload); /* turn off compression for values below the threshold */ - if (payload->len == 0 || payload->len < MEMC_G(compression_threshold)) { + if (ZSTR_LEN(payload) == 0 || ZSTR_LEN(payload) < MEMC_G(compression_threshold)) { should_compress = 0; } @@ -1063,8 +1063,8 @@ zend_bool s_memc_write_zval (php_memc_object_t *intern, php_memc_write_op op, ze } } -#define memc_write_using_fn(fn_name) payload ? fn_name(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags) : MEMC_RES_PAYLOAD_FAILURE; -#define memc_write_using_fn_by_key(fn_name) payload ? fn_name(intern->memc, server_key->val, server_key->len, key->val, key->len, payload->val, payload->len, expiration, flags) : MEMC_RES_PAYLOAD_FAILURE; +#define memc_write_using_fn(fn_name) payload ? fn_name(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(payload), ZSTR_LEN(payload), expiration, flags) : MEMC_RES_PAYLOAD_FAILURE; +#define memc_write_using_fn_by_key(fn_name) payload ? fn_name(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(payload), ZSTR_LEN(payload), expiration, flags) : MEMC_RES_PAYLOAD_FAILURE; if (server_key) { switch (op) { @@ -1073,7 +1073,7 @@ zend_bool s_memc_write_zval (php_memc_object_t *intern, php_memc_write_op op, ze break; case MEMC_OP_TOUCH: - status = memcached_touch_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, expiration); + status = memcached_touch_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), expiration); break; case MEMC_OP_ADD: @@ -1105,7 +1105,7 @@ zend_bool s_memc_write_zval (php_memc_object_t *intern, php_memc_write_op op, ze break; case MEMC_OP_TOUCH: - status = memcached_touch(intern->memc, key->val, key->len, expiration); + status = memcached_touch(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), expiration); break; case MEMC_OP_ADD: @@ -1302,12 +1302,12 @@ void s_hash_to_keys(php_memc_keys_t *keys_out, HashTable *hash_in, zend_bool pre zend_string *key = zval_get_string(zv); if (preserve_order && return_value) { - add_assoc_null_ex(return_value, key->val, key->len); + add_assoc_null_ex(return_value, ZSTR_VAL(key), ZSTR_LEN(key)); } - if (key->len > 0 && key->len < MEMCACHED_MAX_KEY) { - keys_out->mkeys[idx] = key->val; - keys_out->mkeys_len[idx] = key->len; + if (ZSTR_LEN(key) > 0 && ZSTR_LEN(key) < MEMCACHED_MAX_KEY) { + keys_out->mkeys[idx] = ZSTR_VAL(key); + keys_out->mkeys_len[idx] = ZSTR_LEN(key); keys_out->strings[idx] = key; idx++; @@ -1331,8 +1331,8 @@ void s_key_to_keys(php_memc_keys_t *keys_out, zend_string *key) { zval zv_keys; - array_init (&zv_keys); - add_next_index_stringl (&zv_keys, key->val, key->len); + array_init(&zv_keys); + add_next_index_str(&zv_keys, zend_string_copy(key)); s_hash_to_keys(keys_out, Z_ARRVAL(zv_keys), 0, NULL); zval_ptr_dtor(&zv_keys); @@ -1409,7 +1409,6 @@ void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) context.extended = (get_flags & MEMC_GET_EXTENDED); - ZVAL_UNDEF(return_value); context.return_value = return_value; s_key_to_keys(&keys, key); @@ -1461,15 +1460,15 @@ zend_bool s_get_multi_apply_fn(php_memc_object_t *intern, zend_string *key, zval Z_TRY_ADDREF_P(cas); - array_init (&node); - add_assoc_zval (&node, "value", value); - add_assoc_zval (&node, "cas", cas); - add_assoc_long (&node, "flags", (zend_long) MEMC_VAL_GET_USER_FLAGS(flags)); + array_init(&node); + add_assoc_zval(&node, "value", value); + add_assoc_zval(&node, "cas", cas); + add_assoc_long(&node, "flags", (zend_long) MEMC_VAL_GET_USER_FLAGS(flags)); - add_assoc_zval_ex(context->return_value, key->val, key->len, &node); + zend_symtable_update(Z_ARRVAL_P(context->return_value), key, &node); } else { - add_assoc_zval_ex(context->return_value, key->val, key->len, value); + zend_symtable_update(Z_ARRVAL_P(context->return_value), key, value); } return 1; } @@ -1563,10 +1562,10 @@ void s_create_result_array(zend_string *key, zval *value, zval *cas, uint32_t fl Z_TRY_ADDREF_P(value); Z_TRY_ADDREF_P(cas); - add_assoc_stringl_ex(return_value, ZEND_STRL("key"), key->val, key->len); - add_assoc_zval_ex(return_value, ZEND_STRL("value"), value); + add_assoc_str_ex(return_value, ZEND_STRL("key"), zend_string_copy(key)); + add_assoc_zval_ex(return_value, ZEND_STRL("value"), value); - add_assoc_zval_ex(return_value, ZEND_STRL("cas"), cas); + add_assoc_zval_ex(return_value, ZEND_STRL("cas"), cas); add_assoc_long_ex(return_value, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); } @@ -2029,9 +2028,9 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) } if (by_key) { - status = memcached_cas_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, payload->val, payload->len, expiration, flags, cas); + status = memcached_cas_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(payload), ZSTR_LEN(payload), expiration, flags, cas); } else { - status = memcached_cas(intern->memc, key->val, key->len, payload->val, payload->len, expiration, flags, cas); + status = memcached_cas(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(payload), ZSTR_LEN(payload), expiration, flags, cas); } zend_string_release(payload); @@ -2114,10 +2113,10 @@ static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); if (by_key) { - status = memcached_delete_by_key(intern->memc, server_key->val, server_key->len, key->val, - key->len, expiration); + status = memcached_delete_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), + ZSTR_LEN(key), expiration); } else { - status = memcached_delete(intern->memc, key->val, key->len, expiration); + status = memcached_delete(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), expiration); } if (s_memc_status_handle_result_code(intern, status) == FAILURE) { @@ -2131,10 +2130,10 @@ static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) /* {{{ -- php_memc_deleteMulti_impl */ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { - zval *entries; + zval *entries, *zv, ret; zend_string *server_key = NULL; time_t expiration = 0; - zval *entry; + zend_string *entry; memcached_return status; MEMC_METHOD_INIT_VARS; @@ -2153,27 +2152,27 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); array_init(return_value); - ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P(entries), entry) { - if (Z_TYPE_P(entry) != IS_STRING) { - convert_to_string_ex(entry); - } + ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P(entries), zv) { + entry = zval_get_string(zv); - if (Z_STRLEN_P(entry) == 0) { + if (ZSTR_LEN(entry) == 0) { + zend_string_release(entry); continue; } if (by_key) { - status = memcached_delete_by_key(intern->memc, server_key->val, server_key->len, Z_STRVAL_P(entry), Z_STRLEN_P(entry), expiration); + status = memcached_delete_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(entry), ZSTR_LEN(entry), expiration); } else { - status = memcached_delete_by_key(intern->memc, Z_STRVAL_P(entry), Z_STRLEN_P(entry), Z_STRVAL_P(entry), Z_STRLEN_P(entry), expiration); + status = memcached_delete_by_key(intern->memc, ZSTR_VAL(entry), ZSTR_LEN(entry), ZSTR_VAL(entry), ZSTR_LEN(entry), expiration); } - if (s_memc_status_handle_result_code(intern, status) == FAILURE) { - add_assoc_long(return_value, Z_STRVAL_P(entry), status); + ZVAL_LONG(&ret, status); } else { - add_assoc_bool(return_value, Z_STRVAL_P(entry), 1); + ZVAL_TRUE(&ret); } + zend_symtable_update(Z_ARRVAL_P(return_value), entry, &ret); + zend_string_release(entry); } ZEND_HASH_FOREACH_END(); return; @@ -2213,15 +2212,15 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, if ((!by_key && n_args < 3) || (by_key && n_args < 4)) { if (by_key) { if (incr) { - status = memcached_increment_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, &value); + status = memcached_increment_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, &value); } else { - status = memcached_decrement_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, &value); + status = memcached_decrement_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, &value); } } else { if (incr) { - status = memcached_increment(intern->memc, key->val, key->len, (unsigned int)offset, &value); + status = memcached_increment(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, &value); } else { - status = memcached_decrement(intern->memc, key->val, key->len, (unsigned int)offset, &value); + status = memcached_decrement(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, &value); } } @@ -2235,15 +2234,15 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, } if (by_key) { if (incr) { - status = memcached_increment_with_initial_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, initial, expiry, &value); + status = memcached_increment_with_initial_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, initial, expiry, &value); } else { - status = memcached_decrement_with_initial_by_key(intern->memc, server_key->val, server_key->len, key->val, key->len, (unsigned int)offset, initial, expiry, &value); + status = memcached_decrement_with_initial_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, initial, expiry, &value); } } else { if (incr) { - status = memcached_increment_with_initial(intern->memc, key->val, key->len, (unsigned int)offset, initial, expiry, &value); + status = memcached_increment_with_initial(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, initial, expiry, &value); } else { - status = memcached_decrement_with_initial(intern->memc, key->val, key->len, (unsigned int)offset, initial, expiry, &value); + status = memcached_decrement_with_initial(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, initial, expiry, &value); } } if (s_should_retry_write(intern, status) && retries-- > 0) { @@ -2452,7 +2451,7 @@ PHP_METHOD(Memcached, getServerByKey) MEMC_METHOD_FETCH_OBJECT; s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); - server_instance = memcached_server_by_key(intern->memc, server_key->val, server_key->len, &error); + server_instance = memcached_server_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), &error); if (server_instance == NULL) { s_memc_status_handle_result_code(intern, error); RETURN_FALSE; @@ -2651,7 +2650,7 @@ memcached_return s_stat_execute_cb (php_memcached_instance_st instance, const ch add_assoc_double(server_values, key, d_val); } else { - add_assoc_stringl_ex(server_values, key, key_length, value, value_length); + add_assoc_stringl_ex(server_values, key, key_length, (char*)value, value_length); } efree (buffer); efree (server_key); @@ -3369,9 +3368,9 @@ memcached_return s_server_cursor_list_servers_cb(const memcached_st *ptr, php_me zval *return_value = (zval *) in_context; array_init(&array); - add_assoc_string(&array, "host", memcached_server_name(instance)); + add_assoc_string(&array, "host", (char*)memcached_server_name(instance)); add_assoc_long(&array, "port", memcached_server_port(instance)); - add_assoc_string(&array, "type", memcached_server_type(instance)); + add_assoc_string(&array, "type", (char*)memcached_server_type(instance)); /* * API does not allow to get at this field. add_assoc_long(array, "weight", instance->weight); @@ -3467,8 +3466,8 @@ zend_bool s_unserialize_value (memcached_st *memc, int val_type, zend_string *pa php_unserialize_data_t var_hash; const unsigned char *p, *max; - p = (const unsigned char *) payload->val; - max = p + payload->len; + p = (const unsigned char *) ZSTR_VAL(payload); + max = p + ZSTR_LEN(payload); PHP_VAR_UNSERIALIZE_INIT(var_hash); if (!php_var_unserialize(return_value, &p, max, &var_hash)) { @@ -3484,7 +3483,7 @@ zend_bool s_unserialize_value (memcached_st *memc, int val_type, zend_string *pa case MEMC_VAL_IS_IGBINARY: #ifdef HAVE_MEMCACHED_IGBINARY - if (igbinary_unserialize((uint8_t *) payload->val, payload->len, return_value)) { + if (igbinary_unserialize((uint8_t *) ZSTR_VAL(payload), ZSTR_LEN(payload), return_value)) { ZVAL_FALSE(return_value); php_error_docref(NULL, E_WARNING, "could not unserialize value with igbinary"); return 0; @@ -3500,7 +3499,7 @@ zend_bool s_unserialize_value (memcached_st *memc, int val_type, zend_string *pa #ifdef HAVE_JSON_API { php_memc_user_data_t *memc_user_data = memcached_get_user_data(memc); - php_json_decode(return_value, payload->val, payload->len, (memc_user_data->serializer == SERIALIZER_JSON_ARRAY), PHP_JSON_PARSER_DEFAULT_DEPTH); + php_json_decode(return_value, ZSTR_VAL(payload), ZSTR_LEN(payload), (memc_user_data->serializer == SERIALIZER_JSON_ARRAY), PHP_JSON_PARSER_DEFAULT_DEPTH); } #else ZVAL_FALSE(return_value); @@ -3511,7 +3510,7 @@ zend_bool s_unserialize_value (memcached_st *memc, int val_type, zend_string *pa case MEMC_VAL_IS_MSGPACK: #ifdef HAVE_MEMCACHED_MSGPACK - php_msgpack_unserialize(return_value, payload->val, payload->len); + php_msgpack_unserialize(return_value, ZSTR_VAL(payload), ZSTR_LEN(payload)); #else ZVAL_FALSE(return_value); php_error_docref(NULL, E_WARNING, "could not unserialize value, no msgpack support"); From 09e29e65deabae5b23fdf5db1928992d6107d9c9 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 23 Jul 2016 12:27:52 +0800 Subject: [PATCH 096/345] Fixed possible crash with opcache (We should never edit a zval in place) --- php_memcached.c | 94 +++++++++++++++++++++++-------------------------- 1 file changed, 44 insertions(+), 50 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 3bd5ee48..078f1b25 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1819,8 +1819,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); ZEND_HASH_FOREACH_KEY_VAL (Z_ARRVAL_P(entries), num_key, skey, value) { - - zend_string *str_key; + zend_string *str_key = NULL; if (skey) { str_key = skey; @@ -2337,7 +2336,6 @@ PHP_METHOD(Memcached, addServers) zval *servers; zval *entry; zval *z_host, *z_port, *z_weight = NULL; - uint32_t weight = 0; HashPosition pos; int entry_size, i = 0; memcached_server_st *list = NULL; @@ -2361,6 +2359,10 @@ PHP_METHOD(Memcached, addServers) entry_size = zend_hash_num_elements(Z_ARRVAL_P(entry)); if (entry_size > 1) { + zend_string *host; + zend_long port; + uint32_t weight; + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(entry), &pos); /* Check that we have a host */ @@ -2378,8 +2380,8 @@ PHP_METHOD(Memcached, addServers) continue; } - convert_to_string_ex(z_host); - convert_to_long_ex(z_port); + host = zval_get_string(z_host); + port = zval_get_long(z_port); weight = 0; if (entry_size > 2) { @@ -2389,12 +2391,12 @@ PHP_METHOD(Memcached, addServers) php_error_docref(NULL, E_WARNING, "could not get server weight for entry #%d", i+1); } - convert_to_long_ex(z_weight); - weight = Z_LVAL_P(z_weight); + weight = zval_get_long(z_weight); } - list = memcached_server_list_append_with_weight(list, Z_STRVAL_P(z_host), - Z_LVAL_P(z_port), weight, &status); + list = memcached_server_list_append_with_weight(list, ZSTR_VAL(host), port, weight, &status); + + zend_string_release(host); if (s_memc_status_handle_result_code(intern, status) == SUCCESS) { i++; @@ -2839,21 +2841,21 @@ static PHP_METHOD(Memcached, getOption) static int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) { + zend_long lval; memcached_return rc = MEMCACHED_FAILURE; memcached_behavior flag; php_memc_user_data_t *memc_user_data = memcached_get_user_data(intern->memc); switch (option) { case MEMC_OPT_COMPRESSION: - convert_to_long(value); - memc_user_data->compression_enabled = Z_LVAL_P(value) ? 1 : 0; + memc_user_data->compression_enabled = zval_get_long(value) ? 1 : 0; break; case MEMC_OPT_COMPRESSION_TYPE: - convert_to_long(value); - if (Z_LVAL_P(value) == COMPRESSION_TYPE_FASTLZ || - Z_LVAL_P(value) == COMPRESSION_TYPE_ZLIB) { - memc_user_data->compression_type = Z_LVAL_P(value); + lval = zval_get_long(value); + if (lval == COMPRESSION_TYPE_FASTLZ || + lval == COMPRESSION_TYPE_ZLIB) { + memc_user_data->compression_type = lval; } else { /* invalid compression type */ intern->rescode = MEMCACHED_INVALID_ARGUMENTS; @@ -2863,12 +2865,13 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) case MEMC_OPT_PREFIX_KEY: { + zend_string *str; char *key; #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX == 0x00049000 char tmp[MEMCACHED_PREFIX_KEY_MAX_SIZE - 1]; #endif - convert_to_string(value); - if (Z_STRLEN_P(value) == 0) { + str = zval_get_string(value); + if (ZSTR_VAL(str) == 0) { key = NULL; } else { /* @@ -2876,25 +2879,27 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) character of the key prefix, to avoid the issue we pad it with a '0' */ #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX == 0x00049000 - snprintf(tmp, sizeof(tmp), "%s0", Z_STRVAL_P(value)); + snprintf(tmp, sizeof(tmp), "%s0", ZSTR_VAL(str)); key = tmp; #else - key = Z_STRVAL_P(value); + key = ZSTR_VAL(str); #endif } if (memcached_callback_set(intern->memc, MEMCACHED_CALLBACK_PREFIX_KEY, key) == MEMCACHED_BAD_KEY_PROVIDED) { + zend_string_release(str); intern->rescode = MEMCACHED_INVALID_ARGUMENTS; php_error_docref(NULL, E_WARNING, "bad key provided"); return 0; } + zend_string_release(str); } break; case MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED: flag = (memcached_behavior) option; - convert_to_long(value); - rc = memcached_behavior_set(intern->memc, flag, (uint64_t) Z_LVAL_P(value)); + lval = zval_get_long(value); + rc = memcached_behavior_set(intern->memc, flag, (uint64_t)lval); if (s_memc_status_handle_result_code(intern, rc) == FAILURE) { php_error_docref(NULL, E_WARNING, "error setting memcached option: %s", memcached_strerror (intern->memc, rc)); @@ -2906,7 +2911,7 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) * options on false case, like it does for MEMCACHED_BEHAVIOR_KETAMA * (non-weighted) case. We have to clean up ourselves. */ - if (!Z_LVAL_P(value)) { + if (!lval) { #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX > 0x00037000 (void)memcached_behavior_set_key_hash(intern->memc, MEMCACHED_HASH_DEFAULT); (void)memcached_behavior_set_distribution_hash(intern->memc, MEMCACHED_HASH_DEFAULT); @@ -2920,28 +2925,28 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) case MEMC_OPT_SERIALIZER: { - convert_to_long(value); + lval = zval_get_long(value); /* igbinary serializer */ #ifdef HAVE_MEMCACHED_IGBINARY - if (Z_LVAL_P(value) == SERIALIZER_IGBINARY) { + if (lval == SERIALIZER_IGBINARY) { memc_user_data->serializer = SERIALIZER_IGBINARY; } else #endif #ifdef HAVE_JSON_API - if (Z_LVAL_P(value) == SERIALIZER_JSON) { + if (lval == SERIALIZER_JSON) { memc_user_data->serializer = SERIALIZER_JSON; - } else if (Z_LVAL_P(value) == SERIALIZER_JSON_ARRAY) { + } else if (lval == SERIALIZER_JSON_ARRAY) { memc_user_data->serializer = SERIALIZER_JSON_ARRAY; } else #endif /* msgpack serializer */ #ifdef HAVE_MEMCACHED_MSGPACK - if (Z_LVAL_P(value) == SERIALIZER_MSGPACK) { + if (lval == SERIALIZER_MSGPACK) { memc_user_data->serializer = SERIALIZER_MSGPACK; } else #endif /* php serializer */ - if (Z_LVAL_P(value) == SERIALIZER_PHP) { + if (lval == SERIALIZER_PHP) { memc_user_data->serializer = SERIALIZER_PHP; } else { memc_user_data->serializer = SERIALIZER_PHP; @@ -2953,23 +2958,23 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) } case MEMC_OPT_USER_FLAGS: - convert_to_long(value); + lval = zval_get_long(value); - if (Z_LVAL_P(value) < 0) { + if (lval < 0) { memc_user_data->set_udf_flags = -1; return 1; } - if (Z_LVAL_P(value) > MEMC_VAL_USER_FLAGS_MAX) { + if (lval > MEMC_VAL_USER_FLAGS_MAX) { php_error_docref(NULL, E_WARNING, "MEMC_OPT_USER_FLAGS must be < %u", MEMC_VAL_USER_FLAGS_MAX); return 0; } - memc_user_data->set_udf_flags = Z_LVAL_P(value); + memc_user_data->set_udf_flags = lval; break; case MEMC_OPT_STORE_RETRY_COUNT: - convert_to_long(value); - memc_user_data->store_retry_count = Z_LVAL_P(value); + lval = zval_get_long(value); + memc_user_data->store_retry_count = lval; break; default: @@ -2981,10 +2986,10 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) } else { flag = (memcached_behavior) option; - convert_to_long(value); + lval = zval_get_long(value); if (flag < MEMCACHED_BEHAVIOR_MAX) { - rc = memcached_behavior_set(intern->memc, flag, (uint64_t) Z_LVAL_P(value)); + rc = memcached_behavior_set(intern->memc, flag, (uint64_t)lval); } else { rc = MEMCACHED_INVALID_ARGUMENTS; @@ -3016,15 +3021,9 @@ uint32_t *s_zval_to_uint32_array (zval *input, size_t *num_elements) retval = ecalloc(*num_elements, sizeof(uint32_t)); ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(input), pzval) { - long value = 0; - - if (Z_TYPE_P(pzval) == IS_LONG) { - value = Z_LVAL_P(pzval); - } else { - value = zval_get_long(pzval); - value = value > 0? value : 0; - } + zend_long value = 0; + value = zval_get_long(pzval); if (value < 0) { php_error_docref(NULL, E_WARNING, "the map must contain positive integers"); efree (retval); @@ -3126,14 +3125,9 @@ static PHP_METHOD(Memcached, setOptions) php_error_docref(NULL, E_WARNING, "invalid configuration option"); ok = 0; } else { - zval copy; - ZVAL_DUP(©, value); - - if (!php_memc_set_option(intern, (long) key_index, ©)) { + if (!php_memc_set_option(intern, (long) key_index, value)) { ok = 0; } - - zval_dtor(©); } } ZEND_HASH_FOREACH_END(); From 010d8e4894f068fda6b70d9b2dd6ada42b62beca Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 23 Jul 2016 12:33:56 +0800 Subject: [PATCH 097/345] Fixed possbile memleak --- php_memcached_server.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/php_memcached_server.c b/php_memcached_server.c index eb225db0..ad33e0bc 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -29,19 +29,15 @@ #define MEMC_MAKE_ZVAL_COOKIE(my_zcookie, my_ptr) \ do { \ - char *cookie_buf; \ - spprintf (&cookie_buf, 0, "%p", my_ptr); \ - MAKE_STD_ZVAL(my_zcookie); \ - ZVAL_STRING(my_zcookie, cookie_buf, 0); \ + zend_string *cookie_buf; \ + cookie_buf = zend_strpprintf(0, "%p", my_ptr); \ + ZVAL_STR(&my_zcookie, cookie_buf); \ } while (0) #define MEMC_MAKE_RESULT_CAS(my_zresult_cas, my_result_cas) \ do { \ my_result_cas = 0; \ - if (Z_TYPE_P(my_zresult_cas) != IS_NULL) { \ - convert_to_double (my_zresult_cas); \ - my_result_cas = (uint64_t) Z_DVAL_P(my_zresult_cas); \ - } \ + my_result_cas = zval_get_double(my_zresult_cas); \ } while (0) @@ -78,9 +74,7 @@ long s_invoke_php_callback (php_memc_server_cb_t *cb, zval ***params, ssize_t pa efree (buf); } if (retval_ptr) { - convert_to_long (retval_ptr); - retval = Z_LVAL_P(retval_ptr); - zval_ptr_dtor(&retval_ptr); + retval = zval_get_long(retval_ptr); } return retval; } @@ -223,10 +217,7 @@ protocol_binary_response_status s_incr_decr_handler (php_memc_event_t event, con retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 7); - if (Z_TYPE(zresult) != IS_LONG) { - convert_to_long (&zresult); - } - *result = (uint64_t) Z_LVAL(zresult); + *result = (uint64_t)zval_get_long(zresult); MEMC_MAKE_RESULT_CAS(zresult_cas, *result_cas); From 95f26c4f75dc9d29e5d7b1f8b4e6f8204b7db850 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 23 Jul 2016 12:38:41 +0800 Subject: [PATCH 098/345] Fixed warning in run-test.php and also fixed test --- tests/experimental/moduleinfo.phpt | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/tests/experimental/moduleinfo.phpt b/tests/experimental/moduleinfo.phpt index 0f02a570..8605c11a 100644 --- a/tests/experimental/moduleinfo.phpt +++ b/tests/experimental/moduleinfo.phpt @@ -19,20 +19,4 @@ echo implode("\n", $array); --EXPECTF-- memcached memcached support => enabled -memcached.compression_factor => %f => %f -memcached.compression_threshold => %d => %d -memcached.compression_type => %s => %s -memcached.serializer => %s => %s -memcached.sess_binary => %d => %d -memcached.sess_connect_timeout => %d => %d -memcached.sess_consistent_hash => %d => %d -memcached.sess_lock_expire => %d => %d -memcached.sess_lock_max_wait => %d => %d -memcached.sess_lock_wait => %d => %d -memcached.sess_locking => %d => %d -memcached.sess_number_of_replicas => %d => %d -memcached.sess_prefix => %s => %s -memcached.sess_randomize_replica_read => %d => %d -memcached.sess_remove_failed => %d => %d -%rmemcached.use_sasl => %d => %d -|%rmemcached.store_retry_count => %d => %d +%A From a1aab4e85576a008fd87eb50aa11668fa92842e0 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 23 Jul 2016 13:13:30 +0800 Subject: [PATCH 099/345] Avoid str duplication --- php_memcached.c | 12 ++++++------ php_memcached_server.c | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 078f1b25..48c3cc24 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2623,8 +2623,7 @@ zend_bool s_double_value(const char *str, double *value) static memcached_return s_stat_execute_cb (php_memcached_instance_st instance, const char *key, size_t key_length, const char *value, size_t value_length, void *context) { - char *server_key; - size_t server_key_len; + zend_string *server_key; zend_long long_val; double d_val; char *buffer; @@ -2632,14 +2631,14 @@ memcached_return s_stat_execute_cb (php_memcached_instance_st instance, const ch zval *return_value = (zval *) context; zval *server_values; - server_key_len = spprintf (&server_key, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance)); - server_values = zend_hash_str_find(Z_ARRVAL_P(return_value), server_key, server_key_len); + server_key = strpprintf(0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance)); + server_values = zend_hash_find(Z_ARRVAL_P(return_value), server_key); if (!server_values) { zval zv; array_init(&zv); - server_values = zend_hash_str_add(Z_ARRVAL_P(return_value), server_key, server_key_len, &zv); + server_values = zend_hash_add(Z_ARRVAL_P(return_value), server_key, &zv); } spprintf (&buffer, 0, "%.*s", value_length, value); @@ -2655,7 +2654,8 @@ memcached_return s_stat_execute_cb (php_memcached_instance_st instance, const ch add_assoc_stringl_ex(server_values, key, key_length, (char*)value, value_length); } efree (buffer); - efree (server_key); + zend_string_release(server_key); + return MEMCACHED_SUCCESS; } diff --git a/php_memcached_server.c b/php_memcached_server.c index ad33e0bc..94305101 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -30,7 +30,7 @@ #define MEMC_MAKE_ZVAL_COOKIE(my_zcookie, my_ptr) \ do { \ zend_string *cookie_buf; \ - cookie_buf = zend_strpprintf(0, "%p", my_ptr); \ + cookie_buf = strpprintf(0, "%p", my_ptr); \ ZVAL_STR(&my_zcookie, cookie_buf); \ } while (0) From 6405d96c54e41ce9020c80bfd48ab325789f29d7 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 23 Jul 2016 13:17:42 +0800 Subject: [PATCH 100/345] Msgpack master is php7 branch now --- .travis/travis.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index b587f5c5..d43a15fc 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -79,7 +79,7 @@ function install_igbinary() { function install_msgpack() { git clone https://github.com/msgpack/msgpack-php.git pushd msgpack-php - git checkout php5 + git checkout master phpize ./configure make From d67517b04d92464928f06402ac104bc133227d5f Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 23 Jul 2016 13:48:09 +0800 Subject: [PATCH 101/345] Fixed tests/keys.phpt --- php_memcached.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index 48c3cc24..be9f229f 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -206,6 +206,16 @@ static inline php_memc_object_t *php_memc_fetch_object(zend_object *obj) { } \ memc_user_data = (php_memc_user_data_t *) memcached_get_user_data(intern->memc); +#define MEMC_CHECK_KEY(intern, key) \ + if (UNEXPECTED(ZSTR_LEN(key) == 0 || \ + ZSTR_LEN(key) > MEMC_OBJECT_KEY_MAX_LENGTH || \ + (memcached_behavior_get(intern->memc, \ + MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) ? \ + strchr(ZSTR_VAL(key), '\n') : \ + strchr(ZSTR_VAL(key), ' ')))) { \ + intern->rescode = MEMCACHED_BAD_KEY_PROVIDED; \ + RETURN_FALSE; \ + } #ifdef HAVE_MEMCACHED_PROTOCOL @@ -1406,6 +1416,7 @@ void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); + MEMC_CHECK_KEY(intern, key); context.extended = (get_flags & MEMC_GET_EXTENDED); @@ -1960,6 +1971,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool MEMC_METHOD_FETCH_OBJECT; s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); + MEMC_CHECK_KEY(intern, key); if (memc_user_data->compression_enabled) { /* @@ -2017,6 +2029,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); + MEMC_CHECK_KEY(intern, key); cas = s_zval_to_uint64(zv_cas); @@ -2110,6 +2123,7 @@ static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_FETCH_OBJECT; s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); + MEMC_CHECK_KEY(intern, key); if (by_key) { status = memcached_delete_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), @@ -2202,6 +2216,7 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, MEMC_METHOD_FETCH_OBJECT; s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); + MEMC_CHECK_KEY(intern, key); if (offset < 0) { php_error_docref(NULL, E_WARNING, "offset has to be > 0"); From 0acaa06d98b2447c6c981bbed7b8a500fc46188f Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 23 Jul 2016 15:14:48 +0800 Subject: [PATCH 102/345] call_function always initialized retval --- php_memcached.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index be9f229f..81dd92f3 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -613,13 +613,7 @@ memcached_return php_memc_result_apply(php_memc_object_t *intern, php_memc_resul const char *res_key; size_t res_key_len; - - ZVAL_UNDEF(&zv_value); if (!s_memcached_result_to_zval(intern->memc, &result, &zv_value)) { - if (Z_TYPE(zv_value) != IS_UNDEF) { - zval_ptr_dtor(&zv_value); - } - if (EG(exception)) { status = MEMC_RES_PAYLOAD_FAILURE; memcached_quit(intern->memc); @@ -729,8 +723,6 @@ zend_bool s_invoke_new_instance_cb(zval *object, zend_fcall_info *fci, zend_fcal ZVAL_NULL(&id); } - ZVAL_UNDEF(&retval); - zend_fcall_info_argn(fci, 2, object, &id); fci->retval = &retval; fci->no_separation = 1; @@ -784,8 +776,6 @@ zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcal fci->params = params; fci->param_count = 4; - ZVAL_UNDEF(&retval); - if (zend_call_function(fci, fcc) == SUCCESS) { if (zend_is_true(&retval)) { time_t expiration = zval_get_long(Z_REFVAL(ref_expiration)); @@ -1596,7 +1586,6 @@ zend_bool s_result_callback_apply(php_memc_object_t *intern, zend_string *key, z context->fci.retval = &retval; context->fci.param_count = 2; - ZVAL_UNDEF(&retval); if (zend_call_function(&context->fci, &context->fcc) == FAILURE) { if (Z_TYPE(retval) != IS_UNDEF) { zval_ptr_dtor(&retval); @@ -3597,14 +3586,10 @@ zend_bool s_memcached_result_to_zval(memcached_st *memc, memcached_result_st *re default: php_error_docref(NULL, E_WARNING, "unknown payload type"); - retval = 0; break; } zend_string_release(data); - if (!retval) { - zval_ptr_dtor(return_value); - } return retval; } From a0ed436fca84faab5a1cbe978789c7e1c97970f3 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 23 Jul 2016 15:15:30 +0800 Subject: [PATCH 103/345] According to memcached wiki, touch is added since 1.4.8 https://github.com/memcached/memcached/wiki/ReleaseNotes148 --- tests/config.inc | 5 +++++ tests/expire.phpt | 4 +++- tests/gh_155.phpt | 1 + tests/gh_77.phpt | 6 ++++-- tests/skipif.inc | 8 +++++++- tests/touch_binary.phpt | 6 ++++-- 6 files changed, 24 insertions(+), 6 deletions(-) diff --git a/tests/config.inc b/tests/config.inc index 4f275af1..a5f3cc2f 100644 --- a/tests/config.inc +++ b/tests/config.inc @@ -66,3 +66,8 @@ function memc_create_combinations ($name, $serializer, $ignore_object_type = fal ), ); } + +function memc_get_version($memc, $host = '') { + $version = $memc->getVersion(); + return array_pop($version); +} diff --git a/tests/expire.phpt b/tests/expire.phpt index 0aa1a555..eac02408 100644 --- a/tests/expire.phpt +++ b/tests/expire.phpt @@ -3,7 +3,9 @@ Memcached store, fetch & touch expired key --XFAIL-- https://code.google.com/p/memcached/issues/detail?id=275 --SKIPIF-- - --FILE-- diff --git a/tests/gh_155.phpt b/tests/gh_155.phpt index 54d2b77f..a5b61d00 100644 --- a/tests/gh_155.phpt +++ b/tests/gh_155.phpt @@ -2,6 +2,7 @@ Test for bug 155 --SKIPIF-- diff --git a/tests/gh_77.phpt b/tests/gh_77.phpt index 193b6916..8f241ff4 100644 --- a/tests/gh_77.phpt +++ b/tests/gh_77.phpt @@ -1,8 +1,10 @@ --TEST-- Test for Github issue #77 --SKIPIF-- - --FILE-- --FILE-- Date: Sat, 23 Jul 2016 15:18:54 +0800 Subject: [PATCH 104/345] Remove unused arg --- tests/config.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/config.inc b/tests/config.inc index a5f3cc2f..98747d79 100644 --- a/tests/config.inc +++ b/tests/config.inc @@ -67,7 +67,7 @@ function memc_create_combinations ($name, $serializer, $ignore_object_type = fal ); } -function memc_get_version($memc, $host = '') { +function memc_get_version($memc) { $version = $memc->getVersion(); return array_pop($version); } From 09e13048ecb813e2d0866c34d7319024d11f91b0 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 23 Jul 2016 19:48:13 +0800 Subject: [PATCH 105/345] cleanup --- php_memcached.c | 143 ++++++++++++++++-------------------------------- 1 file changed, 47 insertions(+), 96 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 81dd92f3..2b543e73 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -58,12 +58,9 @@ #define MEMC_G(v) (php_memcached_globals.memc.v) #endif - static - int le_memc; +static int le_memc; -static -int php_memc_list_entry(void) -{ +static int php_memc_list_entry(void) { return le_memc; } @@ -379,8 +376,7 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); /* Invoke PHP functions */ -static - zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string *key, zval *value); +static zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string *key, zval *value); /* Iterate result sets */ typedef zend_bool (*php_memc_result_apply_fn)(php_memc_object_t *intern, zend_string *key, zval *value, zval *cas, uint32_t flags, void *context); @@ -655,7 +651,6 @@ zend_bool php_memc_mget_apply(php_memc_object_t *intern, zend_string *server_key php_memc_result_apply_fn result_apply_fn, zend_bool with_cas, void *context) { memcached_return status; - memcached_result_st result; int mget_status; uint64_t orig_cas_flag = 0; @@ -715,17 +710,19 @@ static zend_bool s_invoke_new_instance_cb(zval *object, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache, zend_string *persistent_id) { zend_bool ret = 1; - zval retval, id; + zval retval; + zval params[2]; + ZVAL_COPY(¶ms[0], object); if (persistent_id) { - ZVAL_STR(&id, persistent_id); + ZVAL_STR(¶ms[1], zend_string_copy(persistent_id)); } else { - ZVAL_NULL(&id); + ZVAL_NULL(¶ms[1]); } - zend_fcall_info_argn(fci, 2, object, &id); - fci->retval = &retval; - fci->no_separation = 1; + fci->retval = &retval; + fci->params = params; + fci->param_count = 2; if (zend_call_function(fci, fci_cache) == FAILURE) { char *buf = php_memc_printable_func (fci, fci_cache); @@ -734,43 +731,27 @@ zend_bool s_invoke_new_instance_cb(zval *object, zend_fcall_info *fci, zend_fcal ret = 0; } - if (Z_TYPE(retval) != IS_UNDEF) { - zval_ptr_dtor(&retval); - } + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(&retval); - if (EG(exception)) { - ret = 0; - } - - zend_fcall_info_args_clear(fci, 1); return ret; } static zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string *key, zval *value) { - memcached_return rc; zend_bool status = 0; - zval params[4]; zval retval; - zval zv_key, ref_val; - zval ref_expiration, zv_expiration; php_memc_object_t *intern = Z_MEMC_OBJ_P(zobject); /* Prepare params */ - ZVAL_STR(&zv_key, key); - - ZVAL_NULL(&ref_val); - ZVAL_NULL(&zv_expiration); - - ZVAL_NEW_REF(&ref_val, value); - ZVAL_NEW_REF(&ref_expiration, &zv_expiration); - ZVAL_COPY(¶ms[0], zobject); - ZVAL_COPY(¶ms[1], &zv_key); - ZVAL_COPY_VALUE(¶ms[2], &ref_val); - ZVAL_COPY_VALUE(¶ms[3], &ref_expiration); + ZVAL_STR(¶ms[1], zend_string_copy(key)); /* key */ + ZVAL_NEW_REF(¶ms[2], value); /* value */ + ZVAL_NEW_EMPTY_REF(¶ms[3]); /* expiration */ + ZVAL_NULL(Z_REFVAL(params[3])); fci->retval = &retval; fci->params = params; @@ -778,23 +759,22 @@ zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcal if (zend_call_function(fci, fcc) == SUCCESS) { if (zend_is_true(&retval)) { - time_t expiration = zval_get_long(Z_REFVAL(ref_expiration)); - status = s_memc_write_zval (intern, MEMC_OP_SET, NULL, key, Z_REFVAL(ref_val), expiration); - ZVAL_DUP(value, Z_REFVAL(ref_val)); + time_t expiration = zval_get_long(Z_REFVAL(params[3])); + status = s_memc_write_zval (intern, MEMC_OP_SET, NULL, key, Z_REFVAL(params[2]), expiration); + /* memleak? zval_ptr_dtor(value); */ + ZVAL_COPY(value, Z_REFVAL(params[2])); } } else { s_memc_set_status(intern, MEMCACHED_NOTFOUND, 0); } - zval_ptr_dtor(zobject); - zval_ptr_dtor(&zv_key); - zval_ptr_dtor(&ref_val); - zval_ptr_dtor(&ref_expiration); + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); + zval_ptr_dtor(¶ms[2]); + zval_ptr_dtor(¶ms[3]); + zval_ptr_dtor(&retval); - if (!Z_ISUNDEF(retval)) { - zval_ptr_dtor(&retval); - } return status; } @@ -1388,7 +1368,7 @@ void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) zend_long get_flags = 0; zend_string *key; zend_string *server_key = NULL; - zend_bool extended, mget_status; + zend_bool mget_status; memcached_return status = MEMCACHED_SUCCESS; zend_fcall_info fci = empty_fcall_info; zend_fcall_info_cache fcc = empty_fcall_info_cache; @@ -1484,8 +1464,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke zend_string *server_key = NULL; zend_long flags = 0; MEMC_METHOD_INIT_VARS; - - zend_bool with_cas, retval, preserve_order, extended; + zend_bool retval, preserve_order; if (by_key) { if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa|l", &server_key, @@ -1574,32 +1553,29 @@ static zend_bool s_result_callback_apply(php_memc_object_t *intern, zend_string *key, zval *value, zval *cas, uint32_t flags, void *in_context) { zend_bool status = 1; - - zval retval, zv_result; + zval params[2]; + zval retval; php_memc_result_callback_ctx_t *context = (php_memc_result_callback_ctx_t *) in_context; - array_init(&zv_result); - s_create_result_array(key, value, cas, flags, &zv_result); + ZVAL_COPY(¶ms[0], context->object); + array_init(¶ms[1]); - zend_fcall_info_argn(&context->fci, 2, context->object, &zv_result); + s_create_result_array(key, value, cas, flags, ¶ms[1]); context->fci.retval = &retval; + context->fci.params = params; context->fci.param_count = 2; if (zend_call_function(&context->fci, &context->fcc) == FAILURE) { - if (Z_TYPE(retval) != IS_UNDEF) { - zval_ptr_dtor(&retval); - } php_error_docref(NULL, E_WARNING, "could not invoke result callback"); status = 0; } - if (Z_TYPE(retval) != IS_UNDEF) { - zval_ptr_dtor(&retval); - } + zval_ptr_dtor(&retval); + + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(¶ms[1]); - zend_fcall_info_args_clear(&context->fci, 2); - zval_ptr_dtor(&zv_result); return status; } @@ -1663,14 +1639,6 @@ zend_bool s_fetch_apply(php_memc_object_t *intern, zend_string *key, zval *value Returns the next result from a previous delayed request */ PHP_METHOD(Memcached, fetch) { - const char *res_key = NULL; - size_t res_key_len = 0; - const char *payload = NULL; - size_t payload_len = 0; - uint32_t flags = 0; - uint64_t cas = 0; - zval value, zv_cas; - memcached_result_st result; memcached_return status = MEMCACHED_SUCCESS; MEMC_METHOD_INIT_VARS; @@ -1708,14 +1676,6 @@ zend_bool s_fetch_all_apply(php_memc_object_t *intern, zend_string *key, zval *v Returns all the results from a previous delayed request */ PHP_METHOD(Memcached, fetchAll) { - const char *res_key = NULL; - size_t res_key_len = 0; - const char *payload = NULL; - size_t payload_len = 0; - uint32_t flags; - uint64_t cas = 0; - zval value, entry, zv_cas; - memcached_result_st result; memcached_return status = MEMCACHED_SUCCESS; MEMC_METHOD_INIT_VARS; @@ -1794,13 +1754,8 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke zend_string *server_key = NULL; time_t expiration = 0; zval *value; - zend_string *skey, *str_key = NULL; - ulong num_key; - zend_string *payload; - uint32_t flags = 0; - uint32_t retry = 0; - memcached_return status; - char tmp_key[MEMCACHED_MAX_KEY]; + zend_string *skey; + zend_ulong num_key; int tmp_len = 0; MEMC_METHOD_INIT_VARS; @@ -1918,10 +1873,6 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool zval s_zvalue; zval *value = NULL; zend_long expiration = 0; - zend_string *payload = NULL; - uint32_t flags = 0; - uint32_t retry = 0; - memcached_return status; MEMC_METHOD_INIT_VARS; if (by_key) { @@ -2314,15 +2265,15 @@ PHP_METHOD(Memcached, addServer) s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000002 - if (host->val[0] == '/') { /* unix domain socket */ - status = memcached_server_add_unix_socket_with_weight(intern->memc, host->val, weight); + if (ZSTR_VAL(host)[0] == '/') { /* unix domain socket */ + status = memcached_server_add_unix_socket_with_weight(intern->memc, ZSTR_VAL(host), weight); } else if (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_USE_UDP)) { - status = memcached_server_add_udp_with_weight(intern->memc, host->val, port, weight); + status = memcached_server_add_udp_with_weight(intern->memc, ZSTR_VAL(host), port, weight); } else { - status = memcached_server_add_with_weight(intern->memc, host->val, port, weight); + status = memcached_server_add_with_weight(intern->memc, ZSTR_VAL(host), port, weight); } #else - status = memcached_server_add_with_weight(intern->memc, host->val, port, weight); + status = memcached_server_add_with_weight(intern->memc, ZSTR_VAL(host), port, weight); #endif if (s_memc_status_handle_result_code(intern, status) == FAILURE) { @@ -2409,7 +2360,7 @@ PHP_METHOD(Memcached, addServers) } i++; /* catch-all for all errors */ - php_error_docref(NULL, E_WARNING, "could not add entry #%d to the server list", i+1); + php_error_docref(NULL, E_WARNING, "could not add entry #%d to the server list", i + 1); } ZEND_HASH_FOREACH_END(); status = memcached_server_push(intern->memc, list); From 513c091a67539efbd8f9ade7c9bb7c6815fe95c1 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 23 Jul 2016 20:13:36 +0800 Subject: [PATCH 106/345] Fixed locale_float.phpt test --- tests/experimental/locale_float.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/experimental/locale_float.phpt b/tests/experimental/locale_float.phpt index 9c512124..c071d974 100644 --- a/tests/experimental/locale_float.phpt +++ b/tests/experimental/locale_float.phpt @@ -9,7 +9,7 @@ if (!setlocale(LC_NUMERIC, "fi_FI", 'sv_SV', 'nl_NL')) { --FILE-- Date: Sat, 23 Jul 2016 20:32:06 +0800 Subject: [PATCH 107/345] Fixed OOM (tests/experimental/locale_float.phpt) --- php_memcached.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 2b543e73..907914f3 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -829,18 +829,18 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str if (!compress_status) { php_error_docref(NULL, E_WARNING, "could not compress value"); - MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); efree (buffer); return 0; } /* This means the value was too small to be compressed, still a success */ if (compressed_size > (ZSTR_LEN(payload) * MEMC_G(compression_factor))) { - MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); efree (buffer); return 1; } + MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSED); + payload = zend_string_realloc(payload, compressed_size + sizeof(uint32_t), 0); /* Copy the uin32_t at the beginning */ @@ -1005,7 +1005,6 @@ zend_string *s_zval_to_payload(php_memc_object_t *intern, zval *value, uint32_t zend_string_release(payload); return NULL; } - MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSED); } if (memc_user_data->set_udf_flags >= 0) { From 6837d894944a488ecd2b15d2e700e6183fcc4d2e Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 23 Jul 2016 20:44:03 +0800 Subject: [PATCH 108/345] Fixed test (tests/experimental/setmulti_badserialize.phpt) --- php_memcached.c | 2 +- tests/experimental/setmulti_badserialize.phpt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 907914f3..0d208819 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1786,7 +1786,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke } if (!s_memc_write_zval (intern, MEMC_OP_SET, server_key, str_key, value, expiration)) { - php_error_docref(NULL, E_WARNING, "failed to set key %s", str_key->val); + php_error_docref(NULL, E_WARNING, "failed to set key %s", ZSTR_VAL(str_key)); } if (!skey) { diff --git a/tests/experimental/setmulti_badserialize.phpt b/tests/experimental/setmulti_badserialize.phpt index 5081eedc..3bba314a 100644 --- a/tests/experimental/setmulti_badserialize.phpt +++ b/tests/experimental/setmulti_badserialize.phpt @@ -42,6 +42,6 @@ try { var_dump($m->getByKey('kef', 'foo')); --EXPECT-- - +Memcached::setMultiByKey(): failed to set key foo 1234 int(10) From f73befd69c2ff79456c0b9e2515e4f7c7172afa7 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 23 Jul 2016 22:35:13 +0800 Subject: [PATCH 109/345] Use zend_string_equals_literal --- php_memcached.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 0d208819..e1d9d837 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -442,13 +442,13 @@ char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_ char *buffer = NULL; if (fci->object) { - spprintf (&buffer, 0, "%s::%s", fci->object->ce->name->val, fci_cache->function_handler->common.function_name); + spprintf (&buffer, 0, "%s::%s", ZSTR_VAL(fci->object->ce->name), fci_cache->function_handler->common.function_name); } else { if (Z_TYPE (fci->function_name) == IS_OBJECT) { - spprintf (&buffer, 0, "%s", Z_OBJCE (fci->function_name)->name->val); + spprintf (&buffer, 0, "%s", ZSTR_VAL(Z_OBJCE(fci->function_name)->name)); } else { - spprintf (&buffer, 0, "%s", Z_STRVAL (fci->function_name)); + spprintf (&buffer, 0, "%s", Z_STRVAL(fci->function_name)); } } return buffer; @@ -1156,7 +1156,7 @@ static PHP_METHOD(Memcached, __construct) zend_resource *le; plist_key = zend_string_alloc(sizeof("memcached:id=") + persistent_id->len - 1, 0); - snprintf(plist_key->val, plist_key->len + 1, "memcached:id=%s", persistent_id->val); + snprintf(ZSTR_VAL(plist_key), plist_key->len + 1, "memcached:id=%s", ZSTR_VAL(persistent_id)); if ((le = zend_hash_find_ptr(&EG(persistent_list), plist_key)) != NULL) { if (le->type == php_memc_list_entry()) { @@ -1170,7 +1170,7 @@ static PHP_METHOD(Memcached, __construct) } if (conn_str && conn_str->len > 0) { - intern->memc = memcached (conn_str->val, conn_str->len); + intern->memc = memcached (ZSTR_VAL(conn_str), ZSTR_LEN(conn_str)); } else { intern->memc = memcached (NULL, 0); @@ -1249,7 +1249,7 @@ static PHP_METHOD(Memcached, __construct) GC_REFCOUNT(&le) = 1; /* plist_key is not a persistent allocated key, thus we use str_update here */ - if (zend_hash_str_update_mem(&EG(persistent_list), plist_key->val, plist_key->len, &le, sizeof(le)) == NULL) { + if (zend_hash_str_update_mem(&EG(persistent_list), ZSTR_VAL(plist_key), ZSTR_LEN(plist_key), &le, sizeof(le)) == NULL) { zend_string_release(plist_key); php_error_docref(NULL, E_ERROR, "could not register persistent entry"); /* not reached */ @@ -3131,7 +3131,7 @@ static PHP_METHOD(Memcached, setSaslAuthData) RETURN_FALSE; } memc_user_data->has_sasl_data = 1; - status = memcached_set_sasl_auth_data(intern->memc, user->val, pass->val); + status = memcached_set_sasl_auth_data(intern->memc, ZSTR_VAL(user), ZSTR_VAL(pass)); if (s_memc_status_handle_result_code(intern, status) == FAILURE) { RETURN_FALSE; @@ -3503,28 +3503,28 @@ zend_bool s_memcached_result_to_zval(memcached_st *memc, memcached_result_st *re break; case MEMC_VAL_IS_LONG: - ZVAL_LONG(return_value, strtol(data->val, NULL, 10)); + ZVAL_LONG(return_value, strtol(ZSTR_VAL(data), NULL, 10)); break; case MEMC_VAL_IS_DOUBLE: { - if (payload_len == 8 && memcmp(data->val, "Infinity", 8) == 0) { + if (zend_string_equals_literal(data, "Infinity")) { ZVAL_DOUBLE(return_value, php_get_inf()); } - else if (payload_len == 9 && memcmp(data->val, "-Infinity", 9) == 0) { + else if (zend_string_equals_literal(data, "-Infinity")) { ZVAL_DOUBLE(return_value, -php_get_inf()); } - else if (payload_len == 3 && memcmp(data->val, "NaN", 3) == 0) { + else if (zend_string_equals_literal(data, "NaN")) { ZVAL_DOUBLE(return_value, php_get_nan()); } else { - ZVAL_DOUBLE(return_value, zend_strtod(data->val, NULL)); + ZVAL_DOUBLE(return_value, zend_strtod(ZSTR_VAL(data), NULL)); } } break; case MEMC_VAL_IS_BOOL: - ZVAL_BOOL(return_value, payload_len > 0 && data->val[0] == '1'); + ZVAL_BOOL(return_value, payload_len > 0 && ZSTR_VAL(data)[0] == '1'); break; case MEMC_VAL_IS_SERIALIZED: From 441168bebeab63b35813ded34c68d548bc3a1e4c Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sun, 24 Jul 2016 12:37:29 +0800 Subject: [PATCH 110/345] avoided memory duplication --- php_memcached.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index e1d9d837..71b3c255 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -525,15 +525,14 @@ static void s_uint64_to_zval (zval *target, uint64_t value) { if (value >= ((uint64_t) LONG_MAX)) { - char *buffer; + zend_string *buffer; #ifdef PRIu64 - spprintf (&buffer, 0, "%" PRIu64, value); + buffer = strpprintf (0, "%" PRIu64, value); #else /* Best effort */ - spprintf (&buffer, 0, "%llu", value); + buffer = strpprintf (0, "%llu", value); #endif - ZVAL_STRING (target, buffer); - efree(buffer); + ZVAL_STR(target, buffer); } else { ZVAL_LONG (target, (zend_long) value); @@ -3331,28 +3330,28 @@ memcached_return s_server_cursor_list_servers_cb(const memcached_st *ptr, php_me static memcached_return s_server_cursor_version_cb(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) { - char *address, *version; - size_t address_len, version_len; - - zval *return_value = (zval *) in_context; + zend_string *address, *version; + zval rv, *return_value = (zval *)in_context; #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000009 - version_len = spprintf(&version, sizeof(version), "%d.%d.%d", + version = strpprintf(0, "%d.%d.%d", memcached_server_major_version(instance), memcached_server_minor_version(instance), memcached_server_micro_version(instance)); #else - version_len = spprintf(&version, sizeof(version) - 1, "%d.%d.%d", + version = strpprintf(0, "%d.%d.%d", instance->major_version, instance->minor_version, instance->micro_version); #endif - address_len = spprintf(&address, 0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance) - 1); - add_assoc_stringl_ex(return_value, address, address_len, version, version_len); + address = strpprintf(0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance) - 1); + + ZVAL_STR(&rv, version); + zend_hash_add(Z_ARRVAL_P(return_value), address, &rv); + + zend_string_release(address); - efree(address); - efree(version); return MEMCACHED_SUCCESS; } From 5e42fa985b05cb1063a74a74ac14220d52652686 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sun, 24 Jul 2016 12:41:53 +0800 Subject: [PATCH 111/345] Remove old version staff --- php_memcached.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 71b3c255..f2cd38e3 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3565,8 +3565,8 @@ zend_class_entry *php_memc_get_exception_base(int root) zval *pce_z; if ((pce_z = zend_hash_str_find(CG(class_table), - "runtimeexception", - sizeof("RuntimeException") - 1)) != NULL) { + "runtimeexception", + sizeof("RuntimeException") - 1)) != NULL) { pce = Z_CE_P(pce_z); spl_ce_RuntimeException = pce; return pce; @@ -3576,11 +3576,7 @@ zend_class_entry *php_memc_get_exception_base(int root) } } #endif -#if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION < 2) return zend_exception_get_default(); -#else - return zend_exception_get_default(); -#endif } From bb4556a38ce1fa87c088d05e8d7bf28792a794c8 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Mon, 25 Jul 2016 08:38:22 -0700 Subject: [PATCH 112/345] Partial fix build for memcached-protocl --- php_memcached.c | 56 +++++++++++++++++++++++------------------ php_memcached_private.h | 1 - 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index f2cd38e3..a7c1f42e 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -217,10 +217,20 @@ static inline php_memc_object_t *php_memc_fetch_object(zend_object *obj) { #ifdef HAVE_MEMCACHED_PROTOCOL typedef struct { - zend_object zo; php_memc_proto_handler_t *handler; + zend_object zo; } php_memc_server_t; +static inline php_memc_server_t *php_memc_server_fetch_object(zend_object *obj) { + return (php_memc_server_t *)((char *)obj - XtOffsetOf(php_memc_server_t, zo)); +} +#define Z_MEMC_SERVER_P(zv) php_memc_server_fetch_object(Z_OBJ_P(zv)) + +#ifdef ZTS +#define MEMC_SERVER_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, server.v) +#else +#define MEMC_SERVER_G(v) (php_memcached_globals.server.v) +#endif #endif static zend_class_entry *memcached_ce = NULL; @@ -3271,28 +3281,24 @@ zend_object *php_memc_object_new(zend_class_entry *ce) #ifdef HAVE_MEMCACHED_PROTOCOL static -void php_memc_server_free_storage(php_memc_server_t *intern) +void php_memc_server_free_storage(zend_object *object) { + php_memc_server_t *intern = php_memc_server_fetch_object(object); zend_object_std_dtor(&intern->zo); - efree (intern); } -zend_object_value php_memc_server_new(zend_class_entry *ce) +zend_object *php_memc_server_new(zend_class_entry *ce) { - zend_object_value retval; php_memc_server_t *intern; - zval *tmp; - intern = ecalloc(1, sizeof(php_memc_server_t)); + intern = ecalloc(1, sizeof(php_memc_server_t) + zend_object_properties_size(ce)); + zend_object_std_init(&intern->zo, ce); object_properties_init(&intern->zo, ce); - intern->handler = php_memc_proto_handler_new (); - - retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)php_memc_server_free_storage, NULL); - retval.handlers = &memcached_server_object_handlers; + intern->zo.handlers = &memcached_server_object_handlers; - return retval; + return &intern->zo; } #endif @@ -3587,8 +3593,8 @@ void s_destroy_cb (zend_fcall_info *fci) { if (fci->size > 0) { zval_ptr_dtor(&fci->function_name); - if (fci->object_ptr != NULL) { - zval_ptr_dtor(&fci->object_ptr); + if (fci->object) { + OBJ_RELEASE(fci->object); } } } @@ -3598,19 +3604,19 @@ PHP_METHOD(MemcachedServer, run) { int i; zend_bool rc; - zend *address; + zend_string *address; php_memc_server_t *intern; - intern = Z_MEMC_OBJ_P(getThis()); + intern = Z_MEMC_SERVER_P(getThis()); if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &address) == FAILURE) { return; } - rc = php_memc_proto_handler_run (intern->handler, address); + rc = php_memc_proto_handler_run(intern->handler, address); for (i = MEMC_SERVER_ON_MIN + 1; i < MEMC_SERVER_ON_MAX; i++) { - s_destroy_cb (&MEMC_G(server.callbacks) [i].fci); + s_destroy_cb(&MEMC_SERVER_G(callbacks) [i].fci); } RETURN_BOOL(rc); @@ -3633,14 +3639,14 @@ PHP_METHOD(MemcachedServer, on) } if (fci.size > 0) { - s_destroy_cb (&MEMC_G(server.callbacks) [event].fci); + s_destroy_cb (&MEMC_SERVER_G(callbacks) [event].fci); - MEMC_G(server.callbacks) [event].fci = fci; - MEMC_G(server.callbacks) [event].fci_cache = fci_cache; + MEMC_SERVER_G(callbacks) [event].fci = fci; + MEMC_SERVER_G(callbacks) [event].fci_cache = fci_cache; - Z_ADDREF_P (fci.function_name); - if (fci.object_ptr) { - Z_ADDREF_P (fci.object_ptr); + Z_TRY_ADDREF(fci.function_name); + if (fci.object) { + GC_REFCOUNT(fci.object)++; } } RETURN_BOOL(rc); @@ -4370,7 +4376,9 @@ PHP_MINIT_FUNCTION(memcached) #ifdef HAVE_MEMCACHED_PROTOCOL memcpy(&memcached_server_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + memcached_server_object_handlers.offset = XtOffsetOf(php_memc_server_t, zo); memcached_server_object_handlers.clone_obj = NULL; + memcached_server_object_handlers.free_obj = php_memc_server_free_storage; INIT_CLASS_ENTRY(ce, "MemcachedServer", memcached_server_class_methods); memcached_server_ce = zend_register_internal_class(&ce); diff --git a/php_memcached_private.h b/php_memcached_private.h index 329afc8d..c06bd626 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -195,7 +195,6 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) /* For deprecated values */ zend_long no_effect; - #ifdef HAVE_MEMCACHED_PROTOCOL struct { php_memc_server_cb_t callbacks [MEMC_SERVER_ON_MAX]; From 045ab843ce47e6c2e9d0dbbe20bb4d0fc3dd56f4 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Sun, 20 Mar 2016 15:16:35 -0700 Subject: [PATCH 113/345] Document memcached.sess_binary_protocol And remove a TODO found in the code for allowing users to configure whether or not to use binary protocols for sessions. For issue #233 --- memcached.ini | 8 +++++--- php_memcached.c | 1 - 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/memcached.ini b/memcached.ini index 31a6eced..59001aaf 100644 --- a/memcached.ini +++ b/memcached.ini @@ -63,9 +63,11 @@ memcached.sess_remove_failed_servers = Off ; which could have old data or no data at all memcached.sess_number_of_replicas = 0 -; memcached session binary mode -; libmemcached replicas only work if binary mode is enabled -memcached.sess_binary = Off +; Use the memcached binary protocol for memcached sessions (Instead of the text protocol) +; libmemcached replicas work only if binary mode is enabled. +; However, certain proxies (such as twemproxy) will work only if the binary protocol is disabled. +; Default is On. In older versions of php-memcached, this setting was Off and was called memcached.sess_binary. +memcached.sess_binary_protocol = On ; memcached session replica read randomize memcached.sess_randomize_replica_read = Off diff --git a/php_memcached.c b/php_memcached.c index a7c1f42e..efc58218 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -19,7 +19,6 @@ /* TODO * - set LIBKETAMA_COMPATIBLE as the default? * - fix unserialize(serialize($memc)) - * - ability to set binary protocol for sessions */ #include "php_memcached.h" From 4d9fda94df531ea07753bba5744671c994619ad8 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Tue, 26 Jul 2016 14:54:59 +0800 Subject: [PATCH 114/345] use zval_copy --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index f2cd38e3..e426f04c 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1353,7 +1353,7 @@ zend_bool s_get_apply_fn(php_memc_object_t *intern, zend_string *key, zval *valu add_assoc_long (context->return_value, "flags", (zend_long) MEMC_VAL_GET_USER_FLAGS(flags)); } else { - ZVAL_ZVAL(context->return_value, value, 1, 0); + ZVAL_COPY(context->return_value, value); } return 0; /* Stop after one */ } From 56171da73e3d23f2728715abec261a97bfeed9c0 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Tue, 26 Jul 2016 17:07:14 +0800 Subject: [PATCH 115/345] Fixed bug fetch only fetched one result --- php_memcached.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index e426f04c..e7f73f31 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -382,7 +382,7 @@ static zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, ze typedef zend_bool (*php_memc_result_apply_fn)(php_memc_object_t *intern, zend_string *key, zval *value, zval *cas, uint32_t flags, void *context); static -memcached_return php_memc_result_apply(php_memc_object_t *intern, php_memc_result_apply_fn result_apply_fn, void *context); +memcached_return php_memc_result_apply(php_memc_object_t *intern, php_memc_result_apply_fn result_apply_fn, zend_bool fetch_delay, void *context); static zend_bool php_memc_mget_apply(php_memc_object_t *intern, zend_string *server_key, @@ -579,7 +579,7 @@ uint64_t s_zval_to_uint64 (zval *cas) ****************************************/ static -memcached_return php_memc_result_apply(php_memc_object_t *intern, php_memc_result_apply_fn result_apply_fn, void *context) +memcached_return php_memc_result_apply(php_memc_object_t *intern, php_memc_result_apply_fn result_apply_fn, zend_bool fetch_delay, void *context) { memcached_result_st result, *result_ptr; memcached_return rc, status = MEMCACHED_SUCCESS; @@ -599,7 +599,7 @@ memcached_return php_memc_result_apply(php_memc_object_t *intern, php_memc_resul } else { zend_string *key; - zval zv_value, zv_cas; + zval val, zcas; zend_bool retval; uint64_t cas; @@ -608,7 +608,7 @@ memcached_return php_memc_result_apply(php_memc_object_t *intern, php_memc_resul const char *res_key; size_t res_key_len; - if (!s_memcached_result_to_zval(intern->memc, &result, &zv_value)) { + if (!s_memcached_result_to_zval(intern->memc, &result, &val)) { if (EG(exception)) { status = MEMC_RES_PAYLOAD_FAILURE; memcached_quit(intern->memc); @@ -623,19 +623,21 @@ memcached_return php_memc_result_apply(php_memc_object_t *intern, php_memc_resul cas = memcached_result_cas(&result); flags = memcached_result_flags(&result); - s_uint64_to_zval(&zv_cas, cas); + s_uint64_to_zval(&zcas, cas); key = zend_string_init (res_key, res_key_len, 0); - retval = result_apply_fn(intern, key, &zv_value, &zv_cas, flags, context); + retval = result_apply_fn(intern, key, &val, &zcas, flags, context); - zend_string_release (key); - zval_ptr_dtor(&zv_value); - zval_ptr_dtor(&zv_cas); + zend_string_release(key); + zval_ptr_dtor(&val); + zval_ptr_dtor(&zcas); /* Stop iterating on false */ if (!retval) { - /* Make sure we clear our results */ - while (memcached_fetch_result(intern->memc, &result, &rc)) {} + if (!fetch_delay) { + /* Make sure we clear our results */ + while (memcached_fetch_result(intern->memc, &result, &rc)) {} + } break; } } @@ -692,7 +694,7 @@ zend_bool php_memc_mget_apply(php_memc_object_t *intern, zend_string *server_key return 1; } - status = php_memc_result_apply(intern, result_apply_fn, context); + status = php_memc_result_apply(intern, result_apply_fn, 0, context); if (s_memc_status_handle_result_code(intern, status) == FAILURE) { return 0; @@ -1543,8 +1545,11 @@ void s_create_result_array(zend_string *key, zval *value, zval *cas, uint32_t fl add_assoc_str_ex(return_value, ZEND_STRL("key"), zend_string_copy(key)); add_assoc_zval_ex(return_value, ZEND_STRL("value"), value); - add_assoc_zval_ex(return_value, ZEND_STRL("cas"), cas); - add_assoc_long_ex(return_value, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); + if (Z_LVAL_P(cas)) { + /* BC compatible */ + add_assoc_zval_ex(return_value, ZEND_STRL("cas"), cas); + add_assoc_long_ex(return_value, ZEND_STRL("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); + } } static @@ -1648,7 +1653,7 @@ PHP_METHOD(Memcached, fetch) s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); array_init(return_value); - status = php_memc_result_apply(intern, s_fetch_apply, return_value); + status = php_memc_result_apply(intern, s_fetch_apply, 1, return_value); if (s_memc_status_handle_result_code(intern, status) == FAILURE) { zval_ptr_dtor(return_value); @@ -1685,7 +1690,7 @@ PHP_METHOD(Memcached, fetchAll) s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); array_init(return_value); - status = php_memc_result_apply(intern, s_fetch_all_apply, return_value); + status = php_memc_result_apply(intern, s_fetch_all_apply, 0, return_value); if (s_memc_status_handle_result_code(intern, status) == FAILURE) { zval_dtor(return_value); From 41b005fd0f8587f105f673ef3ab77bd31d1285cd Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Tue, 26 Jul 2016 17:48:00 +0800 Subject: [PATCH 116/345] Fixed test --- tests/experimental/cas_bykey.phpt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/experimental/cas_bykey.phpt b/tests/experimental/cas_bykey.phpt index f8c80fa5..0a9da94e 100644 --- a/tests/experimental/cas_bykey.phpt +++ b/tests/experimental/cas_bykey.phpt @@ -8,12 +8,12 @@ include dirname(dirname(__FILE__)) . '/config.inc'; $m = memc_get_instance (); $m->delete('cas_test'); -$cas_token = null; $m->setByKey('keffe', 'cas_test', 10); -$v = $m->getbyKey('keffe', 'cas_test', null, $cas_token); +$v = $m->getbyKey('keffe', 'cas_test', null, Memcached::GET_EXTENDED); -if (is_null($cas_token)) { +$cas_token = $v["cas"]; +if (empty($cas_token)) { echo "Null cas token for key: cas_test value: 10\n"; return; } From 4fa21116f1e32efa4a9ef2045d32950649e6a508 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Tue, 26 Jul 2016 19:11:54 +0800 Subject: [PATCH 117/345] Value pass to callback behavior consistently with get (GET_EXTENED return array) --- php_memcached.c | 57 +++++++++++++++++++------- tests/experimental/getmulti_bykey.phpt | 6 +-- 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index a5dd979c..095366c4 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -386,7 +386,7 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key); /* Invoke PHP functions */ -static zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string *key, zval *value); +static zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_bool with_cas, zend_string *key, zval *value); /* Iterate result sets */ typedef zend_bool (*php_memc_result_apply_fn)(php_memc_object_t *intern, zend_string *key, zval *value, zval *cas, uint32_t flags, void *context); @@ -750,7 +750,7 @@ zend_bool s_invoke_new_instance_cb(zval *object, zend_fcall_info *fci, zend_fcal } static -zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string *key, zval *value) +zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_bool with_cas, zend_string *key, zval *value) { zend_bool status = 0; zval params[4]; @@ -759,21 +759,42 @@ zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcal /* Prepare params */ ZVAL_COPY(¶ms[0], zobject); - ZVAL_STR(¶ms[1], zend_string_copy(key)); /* key */ - ZVAL_NEW_REF(¶ms[2], value); /* value */ - ZVAL_NEW_EMPTY_REF(¶ms[3]); /* expiration */ - ZVAL_NULL(Z_REFVAL(params[3])); + ZVAL_STR_COPY(¶ms[1], key); /* key */ + ZVAL_NEW_REF(¶ms[2], value); /* value */ + + if (with_cas) { + fci->param_count = 3; + } else { + ZVAL_NEW_EMPTY_REF(¶ms[3]); /* expiration */ + ZVAL_NULL(Z_REFVAL(params[3])); + fci->param_count = 4; + } fci->retval = &retval; fci->params = params; - fci->param_count = 4; if (zend_call_function(fci, fcc) == SUCCESS) { if (zend_is_true(&retval)) { - time_t expiration = zval_get_long(Z_REFVAL(params[3])); - status = s_memc_write_zval (intern, MEMC_OP_SET, NULL, key, Z_REFVAL(params[2]), expiration); - /* memleak? zval_ptr_dtor(value); */ - ZVAL_COPY(value, Z_REFVAL(params[2])); + time_t expiration; + zval *val = Z_REFVAL(params[2]); + + if (with_cas) { + if (Z_TYPE_P(val) == IS_ARRAY) { + zval *rv = zend_hash_str_find(Z_ARRVAL_P(val), "value", sizeof("value") - 1); + if (rv) { + zval *cas = zend_hash_str_find(Z_ARRVAL_P(val), "cas", sizeof("cas") -1); + expiration = cas? Z_LVAL_P(cas) : 0; + status = s_memc_write_zval (intern, MEMC_OP_SET, NULL, key, rv, expiration); + } + /* memleak? zval_ptr_dtor(value); */ + ZVAL_COPY(value, val); + } + } else { + expiration = zval_get_long(Z_REFVAL(params[3])); + status = s_memc_write_zval (intern, MEMC_OP_SET, NULL, key, val, expiration); + /* memleak? zval_ptr_dtor(value); */ + ZVAL_COPY(value, val); + } } } else { @@ -783,7 +804,9 @@ zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcal zval_ptr_dtor(¶ms[0]); zval_ptr_dtor(¶ms[1]); zval_ptr_dtor(¶ms[2]); - zval_ptr_dtor(¶ms[3]); + if (!with_cas) { + zval_ptr_dtor(¶ms[3]); + } zval_ptr_dtor(&retval); return status; @@ -1408,7 +1431,7 @@ void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) if (!mget_status) { if (s_memc_status_has_result_code(intern, MEMCACHED_NOTFOUND) && fci.size > 0) { - status = s_invoke_cache_callback(object, &fci, &fcc, key, return_value); + status = s_invoke_cache_callback(object, &fci, &fcc, context.extended, key, return_value); if (!status) { zval_ptr_dtor(return_value); @@ -1488,9 +1511,15 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke } MEMC_METHOD_FETCH_OBJECT; - s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); array_init(return_value); + if (zend_hash_num_elements(Z_ARRVAL_P(keys)) == 0) { + /* BC compatible */ + s_memc_set_status(intern, MEMCACHED_NOTFOUND, 0); + return; + } + + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); preserve_order = (flags & MEMC_GET_PRESERVE_ORDER); s_hash_to_keys(&keys_out, Z_ARRVAL_P(keys), preserve_order, return_value); diff --git a/tests/experimental/getmulti_bykey.phpt b/tests/experimental/getmulti_bykey.phpt index e4eb112c..3f7a6f78 100644 --- a/tests/experimental/getmulti_bykey.phpt +++ b/tests/experimental/getmulti_bykey.phpt @@ -11,12 +11,10 @@ $m->set('foo', 1, 10); $m->set('bar', 2, 10); $m->delete('baz'); -$cas = array(); -var_dump($m->getMultiByKey('foo', array('foo', 'bar', 'baz'), $cas, Memcached::GET_PRESERVE_ORDER)); +var_dump($m->getMultiByKey('foo', array('foo', 'bar', 'baz'), Memcached::GET_PRESERVE_ORDER)); echo $m->getResultMessage(), "\n"; -$cas = array(); -var_dump($m->getMultiByKey('foo', array(), $cas, Memcached::GET_PRESERVE_ORDER)); +var_dump($m->getMultiByKey('foo', array(), Memcached::GET_PRESERVE_ORDER)); echo $m->getResultMessage(), "\n"; --EXPECT-- From 35ef91129d1303bd7d5c7e742d27c08d35d5728c Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Mon, 8 Aug 2016 00:37:20 -0400 Subject: [PATCH 118/345] Igbinary php7 development is in igbinary/igbinary master branch now igbinary7 was moved to src/php7, and bug fixes/improvements were/will be added there later. See https://github.com/igbinary/igbinary/pull/62 --- .travis/travis.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index d43a15fc..264a7f3b 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -67,8 +67,8 @@ function install_libmemcached() { } function install_igbinary() { - git clone https://github.com/igbinary/igbinary7.git - pushd igbinary7 + git clone https://github.com/igbinary/igbinary.git + pushd igbinary phpize ./configure make From 5bcf2008eedf90c38c57e51be0af677672606976 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 11 Oct 2016 07:23:16 -0700 Subject: [PATCH 119/345] Use only the HAVE_MEMCACHED_SASL definition from config.h --- php_memcached_private.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/php_memcached_private.h b/php_memcached_private.h index c06bd626..4c4f6375 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -104,11 +104,8 @@ typedef struct { #define SERIALIZER_DEFAULT_NAME "php" #endif /* HAVE_MEMCACHED_IGBINARY / HAVE_MEMCACHED_MSGPACK */ -#if LIBMEMCACHED_WITH_SASL_SUPPORT -# if defined(HAVE_SASL_SASL_H) -# include -# define HAVE_MEMCACHED_SASL 1 -# endif +#ifdef HAVE_MEMCACHED_SASL +# include #endif #ifdef HAVE_MEMCACHED_PROTOCOL From 957024f777e7e9514a4f4794c3726cb5472b2754 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 11 Oct 2016 07:29:33 -0700 Subject: [PATCH 120/345] Consistently use #ifdef instead of #if for autoconf definitions --- php_memcached.c | 16 ++++++++-------- php_memcached_private.h | 16 ++++++++-------- php_memcached_session.c | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 35dc0aac..c468163e 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -155,7 +155,7 @@ typedef struct { zend_long store_retry_count; zend_long set_udf_flags; -#if HAVE_MEMCACHED_SASL +#ifdef HAVE_MEMCACHED_SASL zend_bool has_sasl_data; #endif } php_memc_user_data_t; @@ -243,7 +243,7 @@ static zend_object_handlers memcached_server_object_handlers; static zend_class_entry *memcached_server_ce = NULL; #endif -#if HAVE_SPL +#ifdef HAVE_SPL static zend_class_entry *spl_ce_RuntimeException = NULL; #endif @@ -431,7 +431,7 @@ static zend_bool php_memc_init_sasl_if_needed() { -#if HAVE_MEMCACHED_SASL +#ifdef HAVE_MEMCACHED_SASL if (MEMC_G(sasl_initialised)) { return 1; } @@ -3273,7 +3273,7 @@ static PHP_METHOD(Memcached, isPristine) static void php_memc_destroy(memcached_st *memc, php_memc_user_data_t *memc_user_data) { -#if HAVE_MEMCACHED_SASL +#ifdef HAVE_MEMCACHED_SASL if (memc_user_data->has_sasl_data) { memcached_destroy_sasl_auth_data(memc); } @@ -3597,7 +3597,7 @@ zend_class_entry *php_memc_get_exception(void) PHP_MEMCACHED_API zend_class_entry *php_memc_get_exception_base(int root) { -#if HAVE_SPL +#ifdef HAVE_SPL if (!root) { if (!spl_ce_RuntimeException) { zend_class_entry *pce; @@ -4311,7 +4311,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(RES_SERVER_MEMORY_ALLOCATION_FAILURE, MEMCACHED_SERVER_MEMORY_ALLOCATION_FAILURE); #endif -#if HAVE_MEMCACHED_SASL +#ifdef HAVE_MEMCACHED_SASL REGISTER_MEMC_CLASS_CONST_LONG(RES_AUTH_PROBLEM, MEMCACHED_AUTH_PROBLEM); REGISTER_MEMC_CLASS_CONST_LONG(RES_AUTH_FAILURE, MEMCACHED_AUTH_FAILURE); REGISTER_MEMC_CLASS_CONST_LONG(RES_AUTH_CONTINUE, MEMCACHED_AUTH_CONTINUE); @@ -4437,7 +4437,7 @@ PHP_MINIT_FUNCTION(memcached) /* {{{ PHP_MSHUTDOWN_FUNCTION */ PHP_MSHUTDOWN_FUNCTION(memcached) { -#if HAVE_MEMCACHED_SASL +#ifdef HAVE_MEMCACHED_SASL if (MEMC_G(sasl_initialised)) { sasl_done(); } @@ -4456,7 +4456,7 @@ PHP_MINFO_FUNCTION(memcached) php_info_print_table_row(2, "Version", PHP_MEMCACHED_VERSION); php_info_print_table_row(2, "libmemcached version", memcached_lib_version()); -#if HAVE_MEMCACHED_SASL +#ifdef HAVE_MEMCACHED_SASL php_info_print_table_row(2, "SASL support", "yes"); #else php_info_print_table_row(2, "SASL support", "no"); diff --git a/php_memcached_private.h b/php_memcached_private.h index 4c4f6375..a04e19be 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -93,15 +93,15 @@ typedef struct { php_memc_serializer_type type; } php_memc_serializer; -#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" +#if defined(HAVE_MEMCACHED_IGBINARY) +# define SERIALIZER_DEFAULT SERIALIZER_IGBINARY +# define SERIALIZER_DEFAULT_NAME "igbinary" +#elif defined(HAVE_MEMCACHED_MSGPACK) +# define SERIALIZER_DEFAULT SERIALIZER_MSGPACK +# define SERIALIZER_DEFAULT_NAME "msgpack" #else -#define SERIALIZER_DEFAULT SERIALIZER_PHP -#define SERIALIZER_DEFAULT_NAME "php" +# define SERIALIZER_DEFAULT SERIALIZER_PHP +# define SERIALIZER_DEFAULT_NAME "php" #endif /* HAVE_MEMCACHED_IGBINARY / HAVE_MEMCACHED_MSGPACK */ #ifdef HAVE_MEMCACHED_SASL diff --git a/php_memcached_session.c b/php_memcached_session.c index 59f6b238..42659fe5 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -68,7 +68,7 @@ void s_destroy_mod_data(memcached_st *memc) { php_memcached_user_data *user_data = memcached_get_user_data(memc); -#if HAVE_MEMCACHED_SASL +#ifdef HAVE_MEMCACHED_SASL if (user_data->has_sasl_data) { memcached_destroy_sasl_auth_data(memc); } From c032fba4901de9049e13097a2699f4e76ef780f7 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 11 Oct 2016 07:58:07 -0700 Subject: [PATCH 121/345] Whitespace --- php_memcached.c | 54 ++++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index c468163e..e6b741ef 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -190,9 +190,9 @@ static inline php_memc_object_t *php_memc_fetch_object(zend_object *obj) { #define Z_MEMC_OBJ_P(zv) php_memc_fetch_object(Z_OBJ_P(zv)); #define MEMC_METHOD_INIT_VARS \ - zval* object = getThis(); \ - php_memc_object_t* intern = NULL; \ - php_memc_user_data_t* memc_user_data = NULL; + zval* object = getThis(); \ + php_memc_object_t* intern = NULL; \ + php_memc_user_data_t* memc_user_data = NULL; #define MEMC_METHOD_FETCH_OBJECT \ intern = Z_MEMC_OBJ_P(object); \ @@ -1341,13 +1341,13 @@ void s_hash_to_keys(php_memc_keys_t *keys_out, HashTable *hash_in, zend_bool pre static void s_key_to_keys(php_memc_keys_t *keys_out, zend_string *key) { - zval zv_keys; + zval zv_keys; - array_init(&zv_keys); - add_next_index_str(&zv_keys, zend_string_copy(key)); + array_init(&zv_keys); + add_next_index_str(&zv_keys, zend_string_copy(key)); - s_hash_to_keys(keys_out, Z_ARRVAL(zv_keys), 0, NULL); - zval_ptr_dtor(&zv_keys); + s_hash_to_keys(keys_out, Z_ARRVAL(zv_keys), 0, NULL); + zval_ptr_dtor(&zv_keys); } static @@ -1385,7 +1385,7 @@ zend_bool s_get_apply_fn(php_memc_object_t *intern, zend_string *key, zval *valu add_assoc_zval (context->return_value, "value", value); add_assoc_zval (context->return_value, "cas", cas); add_assoc_long (context->return_value, "flags", (zend_long) MEMC_VAL_GET_USER_FLAGS(flags)); - } + } else { ZVAL_COPY(context->return_value, value); } @@ -1650,7 +1650,7 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ MEMC_METHOD_FETCH_OBJECT; s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); - s_hash_to_keys(&keys_out, Z_ARRVAL_P(keys), 0, NULL); + s_hash_to_keys(&keys_out, Z_ARRVAL_P(keys), 0, NULL); if (fci.size > 0) { php_memc_result_callback_ctx_t context = { @@ -1758,7 +1758,7 @@ PHP_METHOD(Memcached, setByKey) Sets a new expiration for the given key */ PHP_METHOD(Memcached, touch) { - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_TOUCH, 0); + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_TOUCH, 0); } /* }}} */ @@ -1766,7 +1766,7 @@ PHP_METHOD(Memcached, touch) Sets a new expiration for the given key */ PHP_METHOD(Memcached, touchByKey) { - php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_TOUCH, 1); + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_TOUCH, 1); } /* }}} */ #endif @@ -2466,16 +2466,16 @@ PHP_METHOD(Memcached, getServerByKey) Reset the server list in use */ PHP_METHOD(Memcached, resetServerList) { - MEMC_METHOD_INIT_VARS; + MEMC_METHOD_INIT_VARS; if (zend_parse_parameters_none() == FAILURE) { return; } - MEMC_METHOD_FETCH_OBJECT; + MEMC_METHOD_FETCH_OBJECT; - memcached_servers_reset(intern->memc); - RETURN_TRUE; + memcached_servers_reset(intern->memc); + RETURN_TRUE; } /* }}} */ @@ -2483,16 +2483,16 @@ PHP_METHOD(Memcached, resetServerList) Close any open connections */ PHP_METHOD(Memcached, quit) { - MEMC_METHOD_INIT_VARS; + MEMC_METHOD_INIT_VARS; if (zend_parse_parameters_none() == FAILURE) { return; } - MEMC_METHOD_FETCH_OBJECT; + MEMC_METHOD_FETCH_OBJECT; - memcached_quit(intern->memc); - RETURN_TRUE; + memcached_quit(intern->memc); + RETURN_TRUE; } /* }}} */ @@ -2506,7 +2506,7 @@ PHP_METHOD(Memcached, flushBuffers) return; } - MEMC_METHOD_FETCH_OBJECT; + MEMC_METHOD_FETCH_OBJECT; RETURN_BOOL(memcached_flush_buffers(intern->memc) == MEMCACHED_SUCCESS); } /* }}} */ @@ -3494,7 +3494,7 @@ zend_bool s_unserialize_value (memcached_st *memc, int val_type, zend_string *pa #endif break; - case MEMC_VAL_IS_MSGPACK: + case MEMC_VAL_IS_MSGPACK: #ifdef HAVE_MEMCACHED_MSGPACK php_msgpack_unserialize(return_value, ZSTR_VAL(payload), ZSTR_LEN(payload)); #else @@ -4050,7 +4050,7 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(setOptions, arginfo_setOptions) MEMC_ME(setBucket, arginfo_setBucket) #ifdef HAVE_MEMCACHED_SASL - MEMC_ME(setSaslAuthData, arginfo_setSaslAuthData) + MEMC_ME(setSaslAuthData, arginfo_setSaslAuthData) #endif MEMC_ME(isPersistent, arginfo_isPersistent) MEMC_ME(isPristine, arginfo_isPristine) @@ -4191,9 +4191,9 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(HAVE_JSON, 0); #endif - /* - * Indicate whether msgpack serializer is available - */ + /* + * Indicate whether msgpack serializer is available + */ #ifdef HAVE_MEMCACHED_MSGPACK REGISTER_MEMC_CLASS_CONST_LONG(HAVE_MSGPACK, 1); #else @@ -4330,7 +4330,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); + REGISTER_MEMC_CLASS_CONST_LONG(SERIALIZER_MSGPACK, SERIALIZER_MSGPACK); /* * Compression types From e65be324557eda7167c4831b4bfb1ad23a152beb Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Wed, 7 Dec 2016 04:44:48 +0000 Subject: [PATCH 122/345] Adjust the Travis CI matrix: PHP 7.0 and 7.1, fewer revisions of libmemcached (#273) --- .travis.yml | 29 ++++++++++++++--------------- .travis/travis.sh | 3 +-- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/.travis.yml b/.travis.yml index b2e113ef..4aae7552 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,26 +1,27 @@ +sudo: required +dist: trusty + language: php php: - 7.0 + - 7.1 + +matrix: + fast_finish: true + allow_failures: + - php: 7.1 env: - - LIBMEMCACHED_VERSION=1.0.18 - - LIBMEMCACHED_VERSION=1.0.17 - - LIBMEMCACHED_VERSION=1.0.16 - - LIBMEMCACHED_VERSION=1.0.15 - - LIBMEMCACHED_VERSION=1.0.14 - - LIBMEMCACHED_VERSION=1.0.10 - - LIBMEMCACHED_VERSION=1.0.8 - - LIBMEMCACHED_VERSION=1.0.7 - - LIBMEMCACHED_VERSION=1.0.6 - - LIBMEMCACHED_VERSION=1.0.2 - #- LIBMEMCACHED_VERSION=0.53 - #- LIBMEMCACHED_VERSION=0.49 - #- LIBMEMCACHED_VERSION=0.44 + - LIBMEMCACHED_VERSION=1.0.18 # Debian Jessie / Ubuntu Xenial + - LIBMEMCACHED_VERSION=1.0.16 # RHEL / CentOS 7 + - LIBMEMCACHED_VERSION=1.0.8 # Debian Wheezy / Ubuntu Trusty + addons: apt: packages: - sasl2-bin - libsasl2-dev + - libevent-dev before_script: - ./.travis/travis.sh before_script $LIBMEMCACHED_VERSION @@ -28,8 +29,6 @@ before_script: script: - ./.travis/travis.sh script $LIBMEMCACHED_VERSION -sudo: false - cache: directories: - $HOME/cache diff --git a/.travis/travis.sh b/.travis/travis.sh index 264a7f3b..81049355 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -79,7 +79,6 @@ function install_igbinary() { function install_msgpack() { git clone https://github.com/msgpack/msgpack-php.git pushd msgpack-php - git checkout master phpize ./configure make @@ -238,7 +237,7 @@ case $ACTION in # Install igbinary extension install_igbinary - # install msgpack + # Install msgpack extension install_msgpack install_memcached From 67750f851ad01d054401ce988fe95f7bfe4cb9bf Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Wed, 4 Jan 2017 18:57:02 -0800 Subject: [PATCH 123/345] Update the README in preparation for php-memcached 3.x release --- README.markdown | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/README.markdown b/README.markdown index ae1b86db..35f4d7a0 100644 --- a/README.markdown +++ b/README.markdown @@ -1,15 +1,15 @@ Build Status ------------ -[![Build Status](https://travis-ci.org/php-memcached-dev/php-memcached.png?branch=php7)](https://travis-ci.org/php-memcached-dev/php-memcached) +[![Build Status](https://travis-ci.org/php-memcached-dev/php-memcached.png)](https://travis-ci.org/php-memcached-dev/php-memcached) Description ----------- -This extension uses libmemcached library to provide API for communicating with -memcached servers. +This is the [PECL memcached](https://pecl.php.net/package/memcached) extension, +using the libmemcached library to connect to memcached servers. -memcached is a high-performance, distributed memory object caching system, -generic in nature, but intended for use in speeding up dynamic web applications -by alleviating database load. +[memcached](https://memcached.org) is a high-performance, distributed memory +object caching system, generic in nature, but intended for use in speeding up +dynamic web applications by alleviating database load. Building -------- @@ -19,8 +19,19 @@ Building $ make $ make test -Resources ---------- - * [libmemcached](http://libmemcached.org/libMemcached.html) - * [memcached](http://memcached.org/) - * [igbinary](https://github.com/igbinary/igbinary) +Dependencies +------------ + +php-memcached 3.x releases support PHP 7.0 - 7.1, and require libmemcached 1.x or higher, and optionally support igbinary 2.0 or higher. + +php-memcached 2.x releases support PHP 5.2 - 5.6, and require libmemcached 0.44 or higher, and optionally support igbinary 1.0 or higher. + +[libmemcached](http://libmemcached.org/libMemcached.html) version 1.0.16 or +higher is recommended for best performance and compatibility with memcached +servers. + +[igbinary](https://github.com/igbinary/igbinary) is a faster and more compact +binary serializer for PHP data structures. When installing php-memcached from +source code, the igbinary module must be installed first so that php-memcached +can access its C header files. Load both modules in your `php.ini` at runtime +to begin using igbinary. From dd0219168659419ff4e936b6f77d75e199b2e2d7 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 5 Jan 2017 11:45:07 -0800 Subject: [PATCH 124/345] Add mention of msgpack to the README --- README.markdown | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/README.markdown b/README.markdown index 35f4d7a0..0cb2c032 100644 --- a/README.markdown +++ b/README.markdown @@ -22,9 +22,17 @@ Building Dependencies ------------ -php-memcached 3.x releases support PHP 7.0 - 7.1, and require libmemcached 1.x or higher, and optionally support igbinary 2.0 or higher. - -php-memcached 2.x releases support PHP 5.2 - 5.6, and require libmemcached 0.44 or higher, and optionally support igbinary 1.0 or higher. +php-memcached 3.x: +* Supports PHP 7.0 - 7.1. +* Requires libmemcached 1.x or higher. +* Optionally supports igbinary 2.0 or higher. +* Optionally supports msgpack 2.0 or higher. + +php-memcached 2.x: +* Supports PHP 5.2 - 5.6. +* Requires libmemcached 0.44 or higher. +* Optionally supports igbinary 1.0 or higher. +* Optionally supports msgpack 0.5 or higher. [libmemcached](http://libmemcached.org/libMemcached.html) version 1.0.16 or higher is recommended for best performance and compatibility with memcached @@ -35,3 +43,9 @@ binary serializer for PHP data structures. When installing php-memcached from source code, the igbinary module must be installed first so that php-memcached can access its C header files. Load both modules in your `php.ini` at runtime to begin using igbinary. + +[msgpack](https://msgpack.org) is a faster and more compact data structure +representation that is interoperable with msgpack implementations for other +languages. When installing php-memcached from source code, the msgpack module +must be installed first so that php-memcached can access its C header files. +Load both modules in your `php.ini` at runtime to begin using msgpack. From 7f6c3330327d5a89f9ced7fabbe63ac7fc7f4196 Mon Sep 17 00:00:00 2001 From: Arjen Date: Fri, 20 Jan 2017 13:20:42 +0100 Subject: [PATCH 125/345] Cannot reset OPT_PREFIX_KEY #293 (#294) - ZSTR_VAL(str) == 0 should be ZSTR_LEN(str) == 0 - add reset_keyprefix.phpt to package.xml --- package.xml | 1 + php_memcached.c | 2 +- tests/reset_keyprefix.phpt | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 tests/reset_keyprefix.phpt diff --git a/package.xml b/package.xml index 244acfab..f2b81369 100644 --- a/package.xml +++ b/package.xml @@ -164,6 +164,7 @@ Tests + diff --git a/php_memcached.c b/php_memcached.c index e6b741ef..e1a045b5 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2867,7 +2867,7 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) char tmp[MEMCACHED_PREFIX_KEY_MAX_SIZE - 1]; #endif str = zval_get_string(value); - if (ZSTR_VAL(str) == 0) { + if (ZSTR_LEN(str) == 0) { key = NULL; } else { /* diff --git a/tests/reset_keyprefix.phpt b/tests/reset_keyprefix.phpt new file mode 100644 index 00000000..385a21d5 --- /dev/null +++ b/tests/reset_keyprefix.phpt @@ -0,0 +1,38 @@ +--TEST-- +Cannot reset OPT_PREFIX_KEY #293 +--SKIPIF-- + +--FILE-- +set('key1', 'abc'); +var_dump($m->get('key1')); + +$m->setOption(Memcached::OPT_PREFIX_KEY, 'prefix'); +var_dump($m->get('key1')); + +$m->setOption(Memcached::OPT_PREFIX_KEY, false); +var_dump($m->get('key1')); + +$m->setOption(Memcached::OPT_PREFIX_KEY, 'prefix'); +var_dump($m->get('key1')); + +$m->setOption(Memcached::OPT_PREFIX_KEY, ''); +var_dump($m->get('key1')); + +$m->setOption(Memcached::OPT_PREFIX_KEY, 'prefix'); +var_dump($m->get('key1')); + +$m->setOption(Memcached::OPT_PREFIX_KEY, null); +var_dump($m->get('key1')); +--EXPECTF-- +string(3) "abc" +bool(false) +string(3) "abc" +bool(false) +string(3) "abc" +bool(false) +string(3) "abc" \ No newline at end of file From c564fd875ead3110b27dd3e1dfb9e5d4afabd042 Mon Sep 17 00:00:00 2001 From: Arjen Date: Fri, 20 Jan 2017 14:26:57 +0100 Subject: [PATCH 126/345] Cleanup all checks for unsupported libmemcached versions (#295) --- config.m4 | 2 +- package.xml | 2 -- php_libmemcached_compat.c | 37 ------------------------ php_libmemcached_compat.h | 59 --------------------------------------- php_memcached.c | 58 ++++++-------------------------------- php_memcached_private.h | 10 +++++-- php_memcached_session.c | 2 +- 7 files changed, 17 insertions(+), 153 deletions(-) delete mode 100644 php_libmemcached_compat.c delete mode 100644 php_libmemcached_compat.h diff --git a/config.m4 b/config.m4 index e6a2dfd0..ab6142a1 100644 --- a/config.m4 +++ b/config.m4 @@ -318,7 +318,7 @@ if test "$PHP_MEMCACHED" != "no"; then AC_DEFINE(HAVE_MEMCACHED_EXIST, [1], [Whether memcached_exist is defined]) fi - PHP_MEMCACHED_FILES="php_memcached.c php_libmemcached_compat.c g_fmt.c" + PHP_MEMCACHED_FILES="php_memcached.c g_fmt.c" if test "$PHP_SYSTEM_FASTLZ" != "no"; then AC_CHECK_HEADERS([fastlz.h], [ac_cv_have_fastlz="yes"], [ac_cv_have_fastlz="no"]) diff --git a/package.xml b/package.xml index f2b81369..e8d5c743 100644 --- a/package.xml +++ b/package.xml @@ -72,8 +72,6 @@ Tests - - diff --git a/php_libmemcached_compat.c b/php_libmemcached_compat.c deleted file mode 100644 index bd35d8fe..00000000 --- a/php_libmemcached_compat.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | Copyright (c) 2009 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Andrei Zmievski | - +----------------------------------------------------------------------+ -*/ - -#include "php_memcached.h" -#include "php_memcached_private.h" -#include "php_libmemcached_compat.h" - -memcached_return php_memcached_exist (memcached_st *memc, zend_string *key) -{ -#ifdef HAVE_MEMCACHED_EXIST - return memcached_exist (memc, key->val, key->len); -#else - memcached_return rc = MEMCACHED_SUCCESS; - uint32_t flags = 0; - size_t value_length = 0; - char *value = NULL; - - value = memcached_get (memc, key->val, key->len, &value_length, &flags, &rc); - if (value) { - free (value); - } - return rc; -#endif -} diff --git a/php_libmemcached_compat.h b/php_libmemcached_compat.h deleted file mode 100644 index e740d310..00000000 --- a/php_libmemcached_compat.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | Copyright (c) 2009 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Andrei Zmievski | - +----------------------------------------------------------------------+ -*/ - -#ifndef PHP_LIBMEMCACHED_COMPAT -#define PHP_LIBMEMCACHED_COMPAT - -/* this is the version(s) we support */ -#include - -memcached_return php_memcached_exist (memcached_st *memc, zend_string *key); - -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x00052000 -# define MEMCACHED_SERVER_TEMPORARILY_DISABLED (1024 << 2) -#endif - -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000002 -# define HAVE_MEMCACHED_TOUCH 1 -#endif - -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000017 -# define HAVE_MEMCACHED_INSTANCE_ST 1 -#endif - -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000 -# define HAVE_LIBMEMCACHED_CHECK_CONFIGURATION 1 -#endif - -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000002 -# define HAVE_MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS 1 -#endif - -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000 -# define HAVE_LIBMEMCACHED_MEMCACHED 1 -#endif - -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000018 -# define HAVE_MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT 1 -#endif - -#ifdef HAVE_MEMCACHED_INSTANCE_ST -typedef const memcached_instance_st * php_memcached_instance_st; -#else -typedef memcached_server_instance_st php_memcached_instance_st; -#endif - -#endif diff --git a/php_memcached.c b/php_memcached.c index e1a045b5..79001319 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1753,7 +1753,6 @@ PHP_METHOD(Memcached, setByKey) } /* }}} */ -#ifdef HAVE_MEMCACHED_TOUCH /* {{{ Memcached::touch(string key, [, int expiration ]) Sets a new expiration for the given key */ PHP_METHOD(Memcached, touch) @@ -1769,8 +1768,6 @@ PHP_METHOD(Memcached, touchByKey) php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_TOUCH, 1); } /* }}} */ -#endif - /* {{{ Memcached::setMulti(array items [, int expiration ]) Sets the keys/values specified in the items array */ @@ -2305,17 +2302,7 @@ PHP_METHOD(Memcached, addServer) MEMC_METHOD_FETCH_OBJECT; s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000002 - if (ZSTR_VAL(host)[0] == '/') { /* unix domain socket */ - status = memcached_server_add_unix_socket_with_weight(intern->memc, ZSTR_VAL(host), weight); - } else if (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_USE_UDP)) { - status = memcached_server_add_udp_with_weight(intern->memc, ZSTR_VAL(host), port, weight); - } else { - status = memcached_server_add_with_weight(intern->memc, ZSTR_VAL(host), port, weight); - } -#else status = memcached_server_add_with_weight(intern->memc, ZSTR_VAL(host), port, weight); -#endif if (s_memc_status_handle_result_code(intern, status) == FAILURE) { RETURN_FALSE; @@ -2511,7 +2498,6 @@ PHP_METHOD(Memcached, flushBuffers) } /* }}} */ -#ifdef HAVE_LIBMEMCACHED_CHECK_CONFIGURATION /* {{{ Memcached::getLastErrorMessage() Returns the last error message that occurred */ PHP_METHOD(Memcached, getLastErrorMessage) @@ -2559,7 +2545,6 @@ PHP_METHOD(Memcached, getLastErrorErrno) RETURN_LONG(memcached_last_error_errno(intern->memc)); } /* }}} */ -#endif /* {{{ Memcached::getLastDisconnectedServer() Returns the last disconnected server @@ -2794,11 +2779,7 @@ static PHP_METHOD(Memcached, getOption) result = memcached_callback_get(intern->memc, MEMCACHED_CALLBACK_PREFIX_KEY, &retval); if (retval == MEMCACHED_SUCCESS && result) { -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX == 0x00049000 - RETURN_STRINGL(result, strlen(result)); -#else RETURN_STRING(result); -#endif } else { RETURN_EMPTY_STRING(); } @@ -2863,23 +2844,11 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) { zend_string *str; char *key; -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX == 0x00049000 - char tmp[MEMCACHED_PREFIX_KEY_MAX_SIZE - 1]; -#endif str = zval_get_string(value); if (ZSTR_LEN(str) == 0) { key = NULL; } else { - /* - work-around a bug in libmemcached in version 0.49 that truncates the trailing - character of the key prefix, to avoid the issue we pad it with a '0' - */ -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX == 0x00049000 - snprintf(tmp, sizeof(tmp), "%s0", ZSTR_VAL(str)); - key = tmp; -#else key = ZSTR_VAL(str); -#endif } if (memcached_callback_set(intern->memc, MEMCACHED_CALLBACK_PREFIX_KEY, key) == MEMCACHED_BAD_KEY_PROVIDED) { zend_string_release(str); @@ -2908,14 +2877,9 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) * (non-weighted) case. We have to clean up ourselves. */ if (!lval) { -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX > 0x00037000 - (void)memcached_behavior_set_key_hash(intern->memc, MEMCACHED_HASH_DEFAULT); - (void)memcached_behavior_set_distribution_hash(intern->memc, MEMCACHED_HASH_DEFAULT); - (void)memcached_behavior_set_distribution(intern->memc, MEMCACHED_DISTRIBUTION_MODULA); -#else - intern->memc->hash = 0; - intern->memc->distribution = 0; -#endif + (void)memcached_behavior_set_key_hash(intern->memc, MEMCACHED_HASH_DEFAULT); + (void)memcached_behavior_set_distribution_hash(intern->memc, MEMCACHED_HASH_DEFAULT); + (void)memcached_behavior_set_distribution(intern->memc, MEMCACHED_DISTRIBUTION_MODULA); } break; @@ -3997,10 +3961,10 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(set, arginfo_set) MEMC_ME(setByKey, arginfo_setByKey) -#ifdef HAVE_MEMCACHED_TOUCH + MEMC_ME(touch, arginfo_touch) MEMC_ME(touchByKey, arginfo_touchByKey) -#endif + MEMC_ME(setMulti, arginfo_setMulti) MEMC_ME(setMultiByKey, arginfo_setMultiByKey) @@ -4032,11 +3996,10 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(quit, arginfo_quit) MEMC_ME(flushBuffers, arginfo_flushBuffers) -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000 MEMC_ME(getLastErrorMessage, arginfo_getLastErrorMessage) MEMC_ME(getLastErrorCode, arginfo_getLastErrorCode) MEMC_ME(getLastErrorErrno, arginfo_getLastErrorErrno) -#endif + MEMC_ME(getLastDisconnectedServer, arginfo_getLastDisconnectedServer) MEMC_ME(getStats, arginfo_getStats) @@ -4229,9 +4192,8 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(OPT_DISTRIBUTION, MEMCACHED_BEHAVIOR_DISTRIBUTION); REGISTER_MEMC_CLASS_CONST_LONG(DISTRIBUTION_MODULA, MEMCACHED_DISTRIBUTION_MODULA); REGISTER_MEMC_CLASS_CONST_LONG(DISTRIBUTION_CONSISTENT, MEMCACHED_DISTRIBUTION_CONSISTENT); -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000 REGISTER_MEMC_CLASS_CONST_LONG(DISTRIBUTION_VIRTUAL_BUCKET, MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET); -#endif + REGISTER_MEMC_CLASS_CONST_LONG(OPT_LIBKETAMA_COMPATIBLE, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED); REGISTER_MEMC_CLASS_CONST_LONG(OPT_LIBKETAMA_HASH, MEMCACHED_BEHAVIOR_KETAMA_HASH); REGISTER_MEMC_CLASS_CONST_LONG(OPT_TCP_KEEPALIVE, MEMCACHED_BEHAVIOR_TCP_KEEPALIVE); @@ -4257,14 +4219,10 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(OPT_SORT_HOSTS, MEMCACHED_BEHAVIOR_SORT_HOSTS); REGISTER_MEMC_CLASS_CONST_LONG(OPT_VERIFY_KEY, MEMCACHED_BEHAVIOR_VERIFY_KEY); REGISTER_MEMC_CLASS_CONST_LONG(OPT_USE_UDP, MEMCACHED_BEHAVIOR_USE_UDP); -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00037000 REGISTER_MEMC_CLASS_CONST_LONG(OPT_NUMBER_OF_REPLICAS, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS); REGISTER_MEMC_CLASS_CONST_LONG(OPT_RANDOMIZE_REPLICA_READ, MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ); -#endif -#ifdef HAVE_MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS REGISTER_MEMC_CLASS_CONST_LONG(OPT_REMOVE_FAILED_SERVERS, MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS); -#endif -#ifdef HAVE_MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000018 REGISTER_MEMC_CLASS_CONST_LONG(OPT_SERVER_TIMEOUT_LIMIT, MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT); #endif diff --git a/php_memcached_private.h b/php_memcached_private.h index a04e19be..fe6ccc2c 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -25,7 +25,13 @@ # include "config.h" #endif -#include "php_libmemcached_compat.h" +#include + +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000017 +typedef const memcached_instance_st * php_memcached_instance_st; +#else +typedef memcached_server_instance_st php_memcached_instance_st; +#endif #include #include @@ -208,8 +214,6 @@ PHP_MINFO_FUNCTION(memcached); char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_cache); -memcached_return php_memcached_exist (memcached_st *memc, zend_string *key); - zend_bool php_memc_init_sasl_if_needed(); #endif /* PHP_MEMCACHED_PRIVATE_H */ diff --git a/php_memcached_session.c b/php_memcached_session.c index 42659fe5..c7e6d1cd 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -527,7 +527,7 @@ PS_VALIDATE_SID_FUNC(memcached) { memcached_st *memc = PS_GET_MOD_DATA(); - if (php_memcached_exist(memc, key) == MEMCACHED_SUCCESS) { + if (memcached_exist(memc, key->val, key->len) == MEMCACHED_SUCCESS) { return SUCCESS; } else { return FAILURE; From d9dea45e9719abd0761ae51368359975cb26534b Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Fri, 20 Jan 2017 07:21:39 -0500 Subject: [PATCH 127/345] Add release notes about session protocol,get and getMulti changing (#271) And update the memcached-api.php file for the branch. --- memcached-api.php | 8 ++++---- package.xml | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/memcached-api.php b/memcached-api.php index d22d0cf9..e0e8f944 100644 --- a/memcached-api.php +++ b/memcached-api.php @@ -189,13 +189,13 @@ class Memcached { public function __construct( $persistent_id = '', $on_new_object_cb = null ) {} - public function get( $key, $cache_cb = null, &$cas_token = null, &$udf_flags = null ) {} + public function get( $key, callable $cache_cb = null, $flags = 0) {} - public function getByKey( $server_key, $key, $cache_cb = null, &$cas_token = null, &$udf_flags = null ) {} + public function getByKey( $server_key, $key, callable $cache_cb = null, $flags = 0 ) {} - public function getMulti( array $keys, &$cas_tokens = null, $flags = 0, &$udf_flags = null ) {} + public function getMulti( array $keys, $flags = 0) {} - public function getMultiByKey( $server_key, array $keys, &$cas_tokens = null, $flags = 0, &$udf_flags = null ) {} + public function getMultiByKey( $server_key, array $keys, $flags = 0) {} public function getDelayed( array $keys, $with_cas = null, $value_cb = null ) {} diff --git a/package.xml b/package.xml index e8d5c743..0dd61ada 100644 --- a/package.xml +++ b/package.xml @@ -38,8 +38,9 @@ libmemcached. Please note that this is a beta release and reporting any issues w before we move closer to releasing stable version. API - * get commands do not take cas or user flags parameters. - * get and getMulti commands take Memcached::GET_EXTENDED flag to retrieve user flags and cas tokens + * The method signature of get, getByKey, getMulti, and getMultiByKey changed. + * get* and getMulti* commands no longer take cas or user flags parameters. + * get* and getMulti* commands now take the Memcached::GET_EXTENDED flag to retrieve user flags and cas tokens. * Fixes getStats command to return all stats from all servers * Fixes allKeys command behaviour * Fixes error where cache callback for get command was not setting expiration time properly @@ -48,6 +49,7 @@ API * CAS tokens are returned as integers and they overflow to strings as needed Session handler + * The session memcached protocol config name was changed, and the default protocol was changed from text to binary protocol. If your memcached setup does not support the binary protocol(e.g. if using twemproxy), then set memcached.sess_binary_protocol = Off. (Previously called memcached.sess_binary) * Session lock algorithm updated (new ini-values memcached.sess_lock_wait_min, memcached.sess_lock_wait_max and memcached.sess_lock_retries) * Session extension uses PHP allocators (still some work to do on the rest of the extension) * Ini-values take effect during session_start or session_regenerate_id From 172d1ffe694406bf64193070b5498f44c4db093a Mon Sep 17 00:00:00 2001 From: Arjen Date: Fri, 20 Jan 2017 19:14:54 +0100 Subject: [PATCH 128/345] Fix tests for PHP 7.1 (#297) invoke_callback_2 fails because of ArgumentCountException (init_cb_arg gets only 2 args) Check number of passed arguments with func_num_args() insteadof checking $args is null session_lock fails because of second warning in 7.1 Skip session_lock.phpt for php < 7.1 and create new testcase for >= 7.1 which tests both warnings. Update .travis.yml, don't allow failures for 7.1 anymore! --- .travis.yml | 6 +--- package.xml | 1 + tests/invoke_callback_2.phpt | 17 +++++----- tests/session_lock-php71.phpt | 62 +++++++++++++++++++++++++++++++++++ tests/session_lock.phpt | 2 ++ 5 files changed, 74 insertions(+), 14 deletions(-) create mode 100644 tests/session_lock-php71.phpt diff --git a/.travis.yml b/.travis.yml index 4aae7552..02c367a9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,8 +8,6 @@ php: matrix: fast_finish: true - allow_failures: - - php: 7.1 env: - LIBMEMCACHED_VERSION=1.0.18 # Debian Jessie / Ubuntu Xenial @@ -31,6 +29,4 @@ script: cache: directories: - - $HOME/cache - - + - $HOME/cache \ No newline at end of file diff --git a/package.xml b/package.xml index 0dd61ada..2091f2e2 100644 --- a/package.xml +++ b/package.xml @@ -165,6 +165,7 @@ Tests + diff --git a/tests/invoke_callback_2.phpt b/tests/invoke_callback_2.phpt index 07e84f94..9749ed18 100644 --- a/tests/invoke_callback_2.phpt +++ b/tests/invoke_callback_2.phpt @@ -18,9 +18,9 @@ function init_cb_fail($m, $id) { echo "configured, should not be called.\n"; } -function init_cb_arg($m, $id, $arg) { +function init_cb_arg($m, $id) { + var_dump(func_num_args()); var_dump($id); - var_dump($arg); } function init_nopersist_cb($m, $id) { @@ -33,15 +33,14 @@ class Foo extends Memcached { parent::__construct($id, array($this, 'init')); } - function init($obj, $id, $options) { + function init($obj, $id) { + var_dump(func_num_args()); var_dump($this->isPristine()); var_dump($this->isPersistent()); var_dump($id); } } -error_reporting(0); - echo "cb call\n"; $m1 = new Memcached('foo1', 'init_cb'); @@ -50,7 +49,6 @@ $m1 = new Memcached('foo1', 'init_cb_fail'); echo "cb arg without arg\n"; $m1 = new Memcached('foo3', 'init_cb_arg'); -echo $php_errormsg, "\n"; echo "cb arg not persistent\n"; $m1 = new Memcached(null, 'init_nopersist_cb'); @@ -63,7 +61,7 @@ $m1 = new Foo('baz'); echo "cb second persistent in object\n"; $m1 = new Foo('baz'); - +?> --EXPECT-- cb call string(9) "Memcached" @@ -71,17 +69,18 @@ bool(true) string(4) "foo1" cb not run cb arg without arg +int(2) string(4) "foo3" -NULL - cb arg not persistent bool(false) NULL cb in object +int(2) bool(true) bool(false) NULL cb persistent in object +int(2) bool(true) bool(true) string(3) "baz" diff --git a/tests/session_lock-php71.phpt b/tests/session_lock-php71.phpt new file mode 100644 index 00000000..207f64cf --- /dev/null +++ b/tests/session_lock-php71.phpt @@ -0,0 +1,62 @@ +--TEST-- +Session lock +--SKIPIF-- + +--INI-- +memcached.sess_locking = true +memcached.sess_lock_wait_min = 500 +memcached.sess_lock_wait_max = 1000 +memcached.sess_lock_retries = 3 +memcached.sess_prefix = "memc.test." + +session.save_handler = memcached + +--FILE-- +addServer(MEMC_SERVER_HOST, MEMC_SERVER_PORT); + +ob_start(); +ini_set ('session.save_path', MEMC_SERVER_HOST . ':' . MEMC_SERVER_PORT); + +session_start(); +$session_id = session_id(); + +$_SESSION["test"] = "hello"; +session_write_close(); + +session_start(); +var_dump ($m->get ('memc.test.' . session_id())); +var_dump ($m->get ('memc.test.lock.' . session_id())); +session_write_close(); +var_dump ($m->get ('memc.test.lock.' . session_id())); + +// Test lock min / max +$m->set ('memc.test.lock.' . $session_id, '1'); + +$time_start = microtime(true); +session_start(); +$time = microtime(true) - $time_start; + +if (round ($time, 1) != 2.5) { + echo "Waited longer than expected: $time" . PHP_EOL; +} +echo "OK"; + +--EXPECTF-- +string(17) "test|s:5:"hello";" +string(1) "1" +bool(false) + +Warning: session_start(): Unable to clear session lock record in %s on line %d + +Warning: session_start(): Failed to read session data: memcached (path: 127.0.0.1:11211) in %s on line %d +OK diff --git a/tests/session_lock.phpt b/tests/session_lock.phpt index 79c32888..570e5a2a 100644 --- a/tests/session_lock.phpt +++ b/tests/session_lock.phpt @@ -4,6 +4,8 @@ Session lock = 70100) print "skip"; ?> --INI-- memcached.sess_locking = true From c3f90bcb59dc434986844cc1c91db0e1cd8b078d Mon Sep 17 00:00:00 2001 From: Frost Wong Date: Sat, 21 Jan 2017 02:19:34 +0800 Subject: [PATCH 129/345] correct a spelling mistake (#207) --- config.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.m4 b/config.m4 index ab6142a1..50e2d3bd 100644 --- a/config.m4 +++ b/config.m4 @@ -24,7 +24,7 @@ PHP_ARG_ENABLE(memcached-sasl, whether to enable memcached sasl support, [ --disable-memcached-sasl Disable memcached sasl support], yes, no) PHP_ARG_ENABLE(memcached-protocol, whether to enable memcached protocol support, -[ --enable-memcached-protocol Enable memcached protocoll support], no, no) +[ --enable-memcached-protocol Enable memcached protocol support], no, no) PHP_ARG_WITH(system-fastlz, whether to use system FastLZ bibrary, [ --with-system-fastlz Use system FastLZ bibrary], no, no) From 5fee5fa9099af5094b1ecc65945fff07918dd6f0 Mon Sep 17 00:00:00 2001 From: Steven Hilder Date: Fri, 20 Jan 2017 21:02:47 +0200 Subject: [PATCH 130/345] Use bool data type for HAVE_* class constants (#166) --- php_memcached.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 79001319..b500b887 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -4140,39 +4140,39 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) * Indicate whether igbinary serializer is available */ #ifdef HAVE_MEMCACHED_IGBINARY - REGISTER_MEMC_CLASS_CONST_LONG(HAVE_IGBINARY, 1); + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_IGBINARY, 1); #else - REGISTER_MEMC_CLASS_CONST_LONG(HAVE_IGBINARY, 0); + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_IGBINARY, 0); #endif /* * Indicate whether json serializer is available */ #ifdef HAVE_JSON_API - REGISTER_MEMC_CLASS_CONST_LONG(HAVE_JSON, 1); + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_JSON, 1); #else - REGISTER_MEMC_CLASS_CONST_LONG(HAVE_JSON, 0); + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_JSON, 0); #endif /* * Indicate whether msgpack serializer is available */ #ifdef HAVE_MEMCACHED_MSGPACK - REGISTER_MEMC_CLASS_CONST_LONG(HAVE_MSGPACK, 1); + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_MSGPACK, 1); #else - REGISTER_MEMC_CLASS_CONST_LONG(HAVE_MSGPACK, 0); + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_MSGPACK, 0); #endif #ifdef HAVE_MEMCACHED_SESSION - REGISTER_MEMC_CLASS_CONST_LONG(HAVE_SESSION, 1); + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_SESSION, 1); #else - REGISTER_MEMC_CLASS_CONST_LONG(HAVE_SESSION, 0); + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_SESSION, 0); #endif #ifdef HAVE_MEMCACHED_SASL - REGISTER_MEMC_CLASS_CONST_LONG(HAVE_SASL, 1); + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_SASL, 1); #else - REGISTER_MEMC_CLASS_CONST_LONG(HAVE_SASL, 0); + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_SASL, 0); #endif /* From b15936c0c04b3c24ec5677f1c4a8bc694d455a4a Mon Sep 17 00:00:00 2001 From: Timandes White Date: Sun, 22 Jan 2017 10:34:50 +0800 Subject: [PATCH 131/345] Add optional parameter 'type' for method 'getStats' (#298) --- memcached-api.php | 2 +- php_memcached.c | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/memcached-api.php b/memcached-api.php index e0e8f944..64b20b26 100644 --- a/memcached-api.php +++ b/memcached-api.php @@ -275,7 +275,7 @@ public function getLastDisconnectedServer( ) {} public function flush( $delay = 0 ) {} - public function getStats( ) {} + public function getStats( $type = null ) {} public function getVersion( ) {} diff --git a/php_memcached.c b/php_memcached.c index b500b887..0a19f204 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2645,16 +2645,21 @@ memcached_return s_stat_execute_cb (php_memcached_instance_st instance, const ch PHP_METHOD(Memcached, getStats) { memcached_return status; + char *args = NULL; + zend_string *args_string = NULL; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters_none() == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!", &args_string) == FAILURE) { return; } MEMC_METHOD_FETCH_OBJECT; + if (args_string) + args = ZSTR_VAL(args_string); + array_init(return_value); - status = memcached_stat_execute(intern->memc, NULL, s_stat_execute_cb, return_value); + status = memcached_stat_execute(intern->memc, args, s_stat_execute_cb, return_value); if (s_memc_status_handle_result_code(intern, status) == FAILURE) { zval_ptr_dtor(return_value); RETURN_FALSE; @@ -3927,6 +3932,7 @@ ZEND_BEGIN_ARG_INFO(arginfo_setBucket, 3) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_getStats, 0) + ZEND_ARG_INFO(0, args) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_getVersion, 0) From 493d6911bfc5460039b428b8c7c66b577511a19c Mon Sep 17 00:00:00 2001 From: Aris Buzachis Date: Sun, 22 Jan 2017 23:37:42 +0200 Subject: [PATCH 132/345] fix: 0 max_execution_time ini value (#266) It seems that zend_ini_long doesn't work anymore with ZEND_STRS and that the extesion should use ZEND_STRL, back again. --- php_memcached_session.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached_session.c b/php_memcached_session.c index c7e6d1cd..e8f61cf5 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -113,7 +113,7 @@ time_t s_lock_expiration() return s_adjust_expiration(MEMC_SESS_INI(lock_expiration)); } else { - zend_long max_execution_time = zend_ini_long(ZEND_STRS("max_execution_time"), 0); + zend_long max_execution_time = zend_ini_long(ZEND_STRL("max_execution_time"), 0); if (max_execution_time > 0) { return s_adjust_expiration(max_execution_time); } From 2af9b615907109874988ff57c27b04eecc862ee2 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 23 Jan 2017 07:28:10 +0000 Subject: [PATCH 133/345] Fix port number in getVersion (#300) (390) --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 0a19f204..cf26bff6 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3353,7 +3353,7 @@ memcached_return s_server_cursor_version_cb(const memcached_st *ptr, php_memcach instance->micro_version); #endif - address = strpprintf(0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance) - 1); + address = strpprintf(0, "%s:%d", memcached_server_name(instance), memcached_server_port(instance)); ZVAL_STR(&rv, version); zend_hash_add(Z_ARRVAL_P(return_value), address, &rv); From 9debfacb8c1c3daeb18388796711c87ad56d6c35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samantha=20Qui=C3=B1ones?= Date: Tue, 17 Mar 2015 00:32:06 -0400 Subject: [PATCH 134/345] Extended key checking to match the language of the memcached spec (#167) Updated to php7 branch by Aaron Stone --- php_memcached.c | 43 +++++++++------- tests/keys.phpt | 69 ++++++++++++++++++++++++++ tests/session_badconf_emptyprefix.phpt | 2 +- tests/session_badconf_prefix.phpt | 2 +- 4 files changed, 97 insertions(+), 19 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index cf26bff6..64f135ad 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -202,15 +202,28 @@ static inline php_memc_object_t *php_memc_fetch_object(zend_object *obj) { } \ memc_user_data = (php_memc_user_data_t *) memcached_get_user_data(intern->memc); -#define MEMC_CHECK_KEY(intern, key) \ - if (UNEXPECTED(ZSTR_LEN(key) == 0 || \ - ZSTR_LEN(key) > MEMC_OBJECT_KEY_MAX_LENGTH || \ - (memcached_behavior_get(intern->memc, \ - MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) ? \ - strchr(ZSTR_VAL(key), '\n') : \ - strchr(ZSTR_VAL(key), ' ')))) { \ - intern->rescode = MEMCACHED_BAD_KEY_PROVIDED; \ - RETURN_FALSE; \ +static +zend_bool s_memc_valid_key_binary(const char *key) +{ + return strchr(key, '\n') == NULL; +} + +static +zend_bool s_memc_valid_key_ascii(const char *key) +{ + while (*key && !iscntrl(*key) && !isspace(*key)) ++key; + return *key == '\0'; +} + +#define MEMC_CHECK_KEY(intern, key) \ + if (UNEXPECTED(ZSTR_LEN(key) == 0 || \ + ZSTR_LEN(key) > MEMC_OBJECT_KEY_MAX_LENGTH || \ + (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) \ + ? !s_memc_valid_key_binary(ZSTR_VAL(key)) \ + : !s_memc_valid_key_ascii(ZSTR_VAL(key)) \ + ))) { \ + intern->rescode = MEMCACHED_BAD_KEY_PROVIDED; \ + RETURN_FALSE; \ } #ifdef HAVE_MEMCACHED_PROTOCOL @@ -307,18 +320,14 @@ static PHP_INI_MH(OnUpdateSessionPrefixString) { if (new_value && ZSTR_LEN(new_value) > 0) { - char *ptr = ZSTR_VAL(new_value); - - while (*ptr != '\0') { - if (isspace (*ptr++)) { - php_error_docref(NULL, E_WARNING, "memcached.sess_prefix cannot contain whitespace characters"); - return FAILURE; - } - } if (ZSTR_LEN(new_value) > MEMCACHED_MAX_KEY) { php_error_docref(NULL, E_WARNING, "memcached.sess_prefix too long (max: %d)", MEMCACHED_MAX_KEY - 1); return FAILURE; } + if (!s_memc_valid_key_ascii(ZSTR_VAL(new_value))) { + php_error_docref(NULL, E_WARNING, "memcached.sess_prefix cannot contain whitespace or control characters"); + return FAILURE; + } } return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } diff --git a/tests/keys.phpt b/tests/keys.phpt index 63cce0a3..f320e03f 100644 --- a/tests/keys.phpt +++ b/tests/keys.phpt @@ -28,6 +28,11 @@ var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); var_dump ($ascii->set (''/*empty key*/, 'this is a test')); var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); +for ($i=0;$i<32;$i++) { + var_dump ($ascii->set ('asciikeywithnonprintablechar-' . chr($i) . '-here', 'this is a test')); + var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); +} + var_dump ($ascii->set (str_repeat ('1234567890', 512), 'this is a test')); var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); @@ -46,4 +51,68 @@ bool(false) bool(true) bool(false) bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) OK diff --git a/tests/session_badconf_emptyprefix.phpt b/tests/session_badconf_emptyprefix.phpt index fd19f1df..f49a8417 100644 --- a/tests/session_badconf_emptyprefix.phpt +++ b/tests/session_badconf_emptyprefix.phpt @@ -24,5 +24,5 @@ session_write_close(); echo "OK"; --EXPECTF-- -Warning: ini_set(): memcached.sess_prefix cannot contain whitespace characters in %s on line %d +Warning: ini_set(): memcached.sess_prefix cannot contain whitespace or control characters in %s on line %d OK diff --git a/tests/session_badconf_prefix.phpt b/tests/session_badconf_prefix.phpt index c42e8376..8421edc3 100644 --- a/tests/session_badconf_prefix.phpt +++ b/tests/session_badconf_prefix.phpt @@ -18,7 +18,7 @@ ini_set('memcached.sess_prefix', str_repeat('a', 512)); echo "OK"; --EXPECTF-- -Warning: ini_set(): memcached.sess_prefix cannot contain whitespace characters in %s on line %d +Warning: ini_set(): memcached.sess_prefix cannot contain whitespace or control characters in %s on line %d Warning: ini_set(): memcached.sess_prefix too long (max: %d) in %s on line %d OK \ No newline at end of file From e1932dceb68767995a03345164db8437e00d04e8 Mon Sep 17 00:00:00 2001 From: dyeldandi Date: Tue, 24 Jan 2017 15:37:37 +0400 Subject: [PATCH 135/345] Added error reporting to session code (#301) --- php_memcached_session.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/php_memcached_session.c b/php_memcached_session.c index e8f61cf5..25ca0ae2 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -442,6 +442,7 @@ PS_READ_FUNC(memcached) *val = ZSTR_EMPTY_ALLOC(); return SUCCESS; } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "error getting session from memcached: %s", memcached_last_error_message(memc)); return FAILURE; } } @@ -470,6 +471,8 @@ PS_WRITE_FUNC(memcached) do { if (memcached_set(memc, key->val, key->len, val->val, val->len, expiration, 0) == MEMCACHED_SUCCESS) { return SUCCESS; + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "error saving session to memcached: %s", memcached_last_error_message(memc)); } } while (--retries > 0); From 8924e3d72b9c735ec3e411f1958d84ac68b139c7 Mon Sep 17 00:00:00 2001 From: Dick Tang Date: Wed, 25 Jan 2017 02:17:07 +0800 Subject: [PATCH 136/345] fix: compression edge case (#255) * correct the compression_factor calculation * send uncompress value and proper set compressed flags when compression saving is too small --- php_memcached.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 64f135ad..b014ecc6 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -108,10 +108,10 @@ static int php_memc_list_entry(void) { #define MEMC_VAL_COMPRESSION_ZLIB (1<<1) #define MEMC_VAL_COMPRESSION_FASTLZ (1<<2) -#define MEMC_VAL_GET_FLAGS(internal_flags) ((internal_flags & MEMC_MASK_INTERNAL) >> 4) -#define MEMC_VAL_SET_FLAG(internal_flags, internal_flag) ((internal_flags) |= ((internal_flag << 4) & MEMC_MASK_INTERNAL)) -#define MEMC_VAL_HAS_FLAG(internal_flags, internal_flag) ((MEMC_VAL_GET_FLAGS(internal_flags) & internal_flag) == internal_flag) -#define MEMC_VAL_DEL_FLAG(internal_flags, internal_flag) internal_flags &= ~((internal_flag << 4) & MEMC_MASK_INTERNAL) +#define MEMC_VAL_GET_FLAGS(internal_flags) (((internal_flags) & MEMC_MASK_INTERNAL) >> 4) +#define MEMC_VAL_SET_FLAG(internal_flags, internal_flag) ((internal_flags) |= (((internal_flag) << 4) & MEMC_MASK_INTERNAL)) +#define MEMC_VAL_HAS_FLAG(internal_flags, internal_flag) ((MEMC_VAL_GET_FLAGS(internal_flags) & (internal_flag)) == (internal_flag)) +#define MEMC_VAL_DEL_FLAG(internal_flags, internal_flag) (internal_flags &= (~(((internal_flag) << 4) & MEMC_MASK_INTERNAL))) /**************************************** User-defined flags @@ -876,7 +876,8 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str } /* This means the value was too small to be compressed, still a success */ - if (compressed_size > (ZSTR_LEN(payload) * MEMC_G(compression_factor))) { + if (ZSTR_LEN(payload) <= (compressed_size * MEMC_G(compression_factor))) { + MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSION_FASTLZ | MEMC_VAL_COMPRESSION_ZLIB); efree (buffer); return 1; } From 7283b11d147c7fab4915623c627a75a612534a6b Mon Sep 17 00:00:00 2001 From: Dick Tang Date: Fri, 10 Jun 2016 21:37:55 +0800 Subject: [PATCH 137/345] test: compression edge case verification (#256) test compressed SET/GET under various settings of - compression_factor - compression_threshold - data length --- package.xml | 1 + tests/compression_conditions.phpt | 125 ++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 tests/compression_conditions.phpt diff --git a/package.xml b/package.xml index 2091f2e2..27491332 100644 --- a/package.xml +++ b/package.xml @@ -94,6 +94,7 @@ Tests + diff --git a/tests/compression_conditions.phpt b/tests/compression_conditions.phpt new file mode 100644 index 00000000..ca3c2d77 --- /dev/null +++ b/tests/compression_conditions.phpt @@ -0,0 +1,125 @@ +--TEST-- +Memcached compression test +--SKIPIF-- + +--FILE-- +setOption(Memcached::OPT_COMPRESSION, false); + } else { + $m->setOption(Memcached::OPT_COMPRESSION, true); + $m->setOption(Memcached::OPT_COMPRESSION_TYPE, get_compression($set_compression)); + } + + $m->set($key, $value, 1800); + + $value_back = $m->get($key); + var_dump($value === $value_back); +} + +fetch_with_compression($m, 'hello01', $data, 'zlib', 1.3, 4); +fetch_with_compression($m, 'hello02', $data, 'fastlz', 1.3, 4); +fetch_with_compression($m, 'hello03', $data, '', 1.3, 4); +fetch_with_compression($m, 'hello04', $short_data, 'zlib', 1.3, 4); +fetch_with_compression($m, 'hello05', $short_data, 'fastlz', 1.3, 4); +fetch_with_compression($m, 'hello06', $short_data, '', 1.3, 4); +fetch_with_compression($m, 'hello11', $data, 'zlib', 0.3, 4); +fetch_with_compression($m, 'hello12', $data, 'fastlz', 0.3, 4); +fetch_with_compression($m, 'hello13', $data, '', 0.3, 4); +fetch_with_compression($m, 'hello14', $short_data, 'zlib', 0.3, 4); +fetch_with_compression($m, 'hello15', $short_data, 'fastlz', 0.3, 4); +fetch_with_compression($m, 'hello16', $short_data, '', 0.3, 4); +fetch_with_compression($m, 'hello21', $data, 'zlib', 1.3, 2000); +fetch_with_compression($m, 'hello22', $data, 'fastlz', 1.3, 2000); +fetch_with_compression($m, 'hello23', $data, '', 1.3, 2000); +fetch_with_compression($m, 'hello24', $short_data, 'zlib', 1.3, 2000); +fetch_with_compression($m, 'hello25', $short_data, 'fastlz', 1.3, 2000); +fetch_with_compression($m, 'hello26', $short_data, '', 1.3, 2000); +fetch_with_compression($m, 'hello31', $data, 'zlib', 0.3, 2000); +fetch_with_compression($m, 'hello32', $data, 'fastlz', 0.3, 2000); +fetch_with_compression($m, 'hello33', $data, '', 0.3, 2000); +fetch_with_compression($m, 'hello34', $short_data, 'zlib', 0.3, 2000); +fetch_with_compression($m, 'hello35', $short_data, 'fastlz', 0.3, 2000); +fetch_with_compression($m, 'hello36', $short_data, '', 0.3, 2000); +?> +--EXPECT-- +len=[4877] set=[zlib] factor=[1.3] threshold=[4] +bool(true) +len=[4877] set=[fastlz] factor=[1.3] threshold=[4] +bool(true) +len=[4877] set=[] factor=[1.3] threshold=[4] +bool(true) +len=[7] set=[zlib] factor=[1.3] threshold=[4] +Memcached::set(): could not compress value +bool(true) +len=[7] set=[fastlz] factor=[1.3] threshold=[4] +bool(true) +len=[7] set=[] factor=[1.3] threshold=[4] +bool(true) +len=[4877] set=[zlib] factor=[0.3] threshold=[4] +bool(true) +len=[4877] set=[fastlz] factor=[0.3] threshold=[4] +bool(true) +len=[4877] set=[] factor=[0.3] threshold=[4] +bool(true) +len=[7] set=[zlib] factor=[0.3] threshold=[4] +Memcached::set(): could not compress value +bool(true) +len=[7] set=[fastlz] factor=[0.3] threshold=[4] +bool(true) +len=[7] set=[] factor=[0.3] threshold=[4] +bool(true) +len=[4877] set=[zlib] factor=[1.3] threshold=[2000] +bool(true) +len=[4877] set=[fastlz] factor=[1.3] threshold=[2000] +bool(true) +len=[4877] set=[] factor=[1.3] threshold=[2000] +bool(true) +len=[7] set=[zlib] factor=[1.3] threshold=[2000] +bool(true) +len=[7] set=[fastlz] factor=[1.3] threshold=[2000] +bool(true) +len=[7] set=[] factor=[1.3] threshold=[2000] +bool(true) +len=[4877] set=[zlib] factor=[0.3] threshold=[2000] +bool(true) +len=[4877] set=[fastlz] factor=[0.3] threshold=[2000] +bool(true) +len=[4877] set=[] factor=[0.3] threshold=[2000] +bool(true) +len=[7] set=[zlib] factor=[0.3] threshold=[2000] +bool(true) +len=[7] set=[fastlz] factor=[0.3] threshold=[2000] +bool(true) +len=[7] set=[] factor=[0.3] threshold=[2000] +bool(true) From c85f34c01ba884987fa3ed4daf7846e503a89cdf Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Wed, 25 Jan 2017 00:12:44 -0800 Subject: [PATCH 138/345] Make sure that s_compress_value() will always leave a valid payload, even if it did not get compressed --- php_memcached.c | 53 ++++++++++++++++--------------- tests/compression_conditions.phpt | 2 -- 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index b014ecc6..1e73a4f9 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -830,6 +830,7 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str /* status */ zend_bool compress_status = 0; zend_string *payload = *payload_in; + uint32_t compression_type_flag = 0; /* Additional 5% for the data */ size_t buffer_size = (size_t) (((double) ZSTR_LEN(payload) * 1.05) + 1.0); @@ -847,7 +848,7 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str if (compressed_size > 0) { compress_status = 1; - MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_FASTLZ); + compression_type_flag = MEMC_VAL_COMPRESSION_FASTLZ; } } break; @@ -859,7 +860,7 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str if (status == Z_OK) { compress_status = 1; - MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_ZLIB); + compression_type_flag = MEMC_VAL_COMPRESSION_ZLIB; } } break; @@ -869,31 +870,29 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str break; } - if (!compress_status) { - php_error_docref(NULL, E_WARNING, "could not compress value"); - efree (buffer); - return 0; - } - - /* This means the value was too small to be compressed, still a success */ + /* This means the value was too small to be compressed and ended up larger */ if (ZSTR_LEN(payload) <= (compressed_size * MEMC_G(compression_factor))) { - MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSION_FASTLZ | MEMC_VAL_COMPRESSION_ZLIB); - efree (buffer); - return 1; + compress_status = 0; } - MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSED); + /* Replace the payload with the compressed copy */ + if (compress_status) { + MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSED | compression_type_flag); + payload = zend_string_realloc(payload, compressed_size + sizeof(uint32_t), 0); - payload = zend_string_realloc(payload, compressed_size + sizeof(uint32_t), 0); + /* Copy the uin32_t at the beginning */ + memcpy(ZSTR_VAL(payload), &original_size, sizeof(uint32_t)); + memcpy(ZSTR_VAL(payload) + sizeof (uint32_t), buffer, compressed_size); + efree(buffer); - /* Copy the uin32_t at the beginning */ - memcpy(ZSTR_VAL(payload), &original_size, sizeof(uint32_t)); - memcpy(ZSTR_VAL(payload) + sizeof (uint32_t), buffer, compressed_size); - efree(buffer); + zend_string_forget_hash_val(payload); + *payload_in = payload; - zend_string_forget_hash_val(payload); - *payload_in = payload; - return 1; + return 1; + } + + /* Original payload was not modified */ + return 0; } static @@ -1043,11 +1042,13 @@ zend_string *s_zval_to_payload(php_memc_object_t *intern, zval *value, uint32_t /* If we have compression flag, compress the value */ if (should_compress) { - /* status */ - if (!s_compress_value (memc_user_data->compression_type, &payload, flags)) { - zend_string_release(payload); - return NULL; - } + /* s_compress_value() will always leave a valid payload, even if that payload + * did not actually get compressed. The flags will be set according to the + * to the compression type or no compression. + * + * No need to check the return value because the payload is always valid. + */ + (void)s_compress_value (memc_user_data->compression_type, &payload, flags); } if (memc_user_data->set_udf_flags >= 0) { diff --git a/tests/compression_conditions.phpt b/tests/compression_conditions.phpt index ca3c2d77..749ebe8a 100644 --- a/tests/compression_conditions.phpt +++ b/tests/compression_conditions.phpt @@ -80,7 +80,6 @@ bool(true) len=[4877] set=[] factor=[1.3] threshold=[4] bool(true) len=[7] set=[zlib] factor=[1.3] threshold=[4] -Memcached::set(): could not compress value bool(true) len=[7] set=[fastlz] factor=[1.3] threshold=[4] bool(true) @@ -93,7 +92,6 @@ bool(true) len=[4877] set=[] factor=[0.3] threshold=[4] bool(true) len=[7] set=[zlib] factor=[0.3] threshold=[4] -Memcached::set(): could not compress value bool(true) len=[7] set=[fastlz] factor=[0.3] threshold=[4] bool(true) From 6085768b48705b1e2a8f4ca516e43e0105850f3d Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 26 Jan 2017 02:06:30 +0000 Subject: [PATCH 139/345] Support for 64-bit offsets for increment and decrement (#306) While the memcached protocol allows for 64-bit increments or decrements, there is a quirk in the libmemcached API that the memcached_increment() and memcached_decrement() functions take only a 32-bit adjustment value. Since the memcached_increment_by_key() and memcached_decrement_by_key() functions do accept 64-bit adjustment values, and the memcached_increment() and memcached_decrement() functions are simply wrappers around those, we'll use them directly and thus support 64-bit adjustments in all cases. --- php_memcached.c | 25 +++++++++++++++---------- tests/incrdecr.phpt | 22 ++++++++++++++++++---- tests/incrdecr_bykey.phpt | 22 ++++++++++++++++++---- 3 files changed, 51 insertions(+), 18 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 1e73a4f9..93d8738f 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2185,7 +2185,7 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, zend_bool incr) { zend_string *key, *server_key = NULL; - long offset = 1; + zend_long offset = 1; uint64_t value = UINT64_MAX, initial = 0; time_t expiry = 0; memcached_return status; @@ -2208,22 +2208,27 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, MEMC_CHECK_KEY(intern, key); if (offset < 0) { - php_error_docref(NULL, E_WARNING, "offset has to be > 0"); + php_error_docref(NULL, E_WARNING, "offset cannot be a negative value"); RETURN_FALSE; } if ((!by_key && n_args < 3) || (by_key && n_args < 4)) { if (by_key) { if (incr) { - status = memcached_increment_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, &value); + status = memcached_increment_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), offset, &value); } else { - status = memcached_decrement_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, &value); + status = memcached_decrement_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), offset, &value); } } else { + /* The libmemcached API has a quirk that memcached_increment() takes only a 32-bit + * offset, but memcached_increment_by_key() and all other increment and decrement + * functions take a 64-bit offset. The memcached protocol allows increment/decrement + * greater than UINT_MAX, so we just work around memcached_increment() here. + */ if (incr) { - status = memcached_increment(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, &value); + status = memcached_increment_by_key(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(key), ZSTR_LEN(key), offset, &value); } else { - status = memcached_decrement(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, &value); + status = memcached_decrement_by_key(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(key), ZSTR_LEN(key), offset, &value); } } @@ -2237,15 +2242,15 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, } if (by_key) { if (incr) { - status = memcached_increment_with_initial_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, initial, expiry, &value); + status = memcached_increment_with_initial_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), offset, initial, expiry, &value); } else { - status = memcached_decrement_with_initial_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, initial, expiry, &value); + status = memcached_decrement_with_initial_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), offset, initial, expiry, &value); } } else { if (incr) { - status = memcached_increment_with_initial(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, initial, expiry, &value); + status = memcached_increment_with_initial(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), offset, initial, expiry, &value); } else { - status = memcached_decrement_with_initial(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), (unsigned int)offset, initial, expiry, &value); + status = memcached_decrement_with_initial(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), offset, initial, expiry, &value); } } if (s_should_retry_write(intern, status) && retries-- > 0) { diff --git a/tests/incrdecr.phpt b/tests/incrdecr.phpt index fc640985..cb3914a4 100644 --- a/tests/incrdecr.phpt +++ b/tests/incrdecr.phpt @@ -29,14 +29,25 @@ $m->decrement('foo', 2); var_dump($m->get('foo')); error_reporting(0); -echo "Invalid offset\n"; + +echo "Negative offset\n"; +$php_errormsg = ''; $m->increment('foo', -1); echo $php_errormsg, "\n"; var_dump($m->get('foo')); + +$php_errormsg = ''; $m->decrement('foo', -1); echo $php_errormsg, "\n"; var_dump($m->get('foo')); +echo "Enormous offset\n"; +$m->increment('foo', 4294967296); +var_dump($m->get('foo')); + +$m->decrement('foo', 4294967296); +var_dump($m->get('foo')); + --EXPECT-- Not there bool(false) @@ -51,8 +62,11 @@ int(2) int(4) int(3) int(1) -Invalid offset -Memcached::increment(): offset has to be > 0 +Negative offset +Memcached::increment(): offset cannot be a negative value +int(1) +Memcached::decrement(): offset cannot be a negative value int(1) -Memcached::decrement(): offset has to be > 0 +Enormous offset +int(4294967297) int(1) diff --git a/tests/incrdecr_bykey.phpt b/tests/incrdecr_bykey.phpt index 9c2db8dd..809f3b83 100644 --- a/tests/incrdecr_bykey.phpt +++ b/tests/incrdecr_bykey.phpt @@ -26,14 +26,25 @@ $m->decrementByKey('foo', 'foo', 2); var_dump($m->get('foo')); error_reporting(0); -echo "Invalid offset\n"; + +echo "Negative offset\n"; +$php_errormsg = ''; $m->incrementByKey('foo', 'foo', -1); echo $php_errormsg, "\n"; var_dump($m->get('foo')); + +$php_errormsg = ''; $m->decrementByKey('foo', 'foo', -1); echo $php_errormsg, "\n"; var_dump($m->get('foo')); +echo "Enormous offset\n"; +$m->incrementByKey('foo', 'foo', 4294967296); +var_dump($m->get('foo')); + +$m->decrementByKey('foo', 'foo', 4294967296); +var_dump($m->get('foo')); + --EXPECT-- Not there bool(false) @@ -45,8 +56,11 @@ int(2) int(4) int(3) int(1) -Invalid offset -Memcached::incrementByKey(): offset has to be > 0 +Negative offset +Memcached::incrementByKey(): offset cannot be a negative value +int(1) +Memcached::decrementByKey(): offset cannot be a negative value int(1) -Memcached::decrementByKey(): offset has to be > 0 +Enormous offset +int(4294967297) int(1) From 7a3b50992c5f68ed07132b6780128b3c7a1295e8 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 26 Jan 2017 01:43:46 -0800 Subject: [PATCH 140/345] Add ChangeLog notes and tentative release date for 3.0.0 --- ChangeLog | 39 +++++++++++++++++++++++++++++++++++++++ package.xml | 21 +++++++++++++++------ 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 05f77181..24cb0a74 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,44 @@ memcached extension changelog +Version 3.0.0 (2017-01-27) +-------------------------- + * Support for PHP 7.0 and PHP 7.1 + * Fix compiling with SASL disabled + * Improved the test suite and Travis CI test runners + * Fix small string compression / decompression + * Fix increment/decrement with adjustments greater than 32-bit integers + * Fix session.gc_maxlifetime to handle both relative and absolute times + * Fix inability to reset OPT_PREFIX_KEY + +Version 3.0.0a1 (2016-02-22) +---------------------------- + Dependencies + * Support for PHP 7.0 + * Requires libmemcached 1.0 or higher + * Optional extension igbinary must 2.0 or higher + * Optional extension msgpack must be 2.0 or higher + + API + * The method signature of get, getByKey, getMulti, and getMultiByKey changed. + * get* and getMulti* commands no longer take cas or user flags parameters. + * get* and getMulti* commands now take the Memcached::GET_EXTENDED flag to retrieve user flags and cas tokens. + * Fixes getStats command to return all stats from all servers + * Fixes allKeys command behaviour + * Fixes error where cache callback for get command was not setting expiration time properly + * Added server type to server list + * Remove use_sasl ini-variable and initialise sasl as needed + * CAS tokens are returned as integers and they overflow to strings as needed + + Session handler + * The session memcached protocol config name was changed, and the default protocol was changed from text to binary protocol. If your memcached setup does not support the binary protocol(e.g. if using twemproxy), then set memcached.sess_binary_protocol = Off. (Previously called memcached.sess_binary) + * Session lock algorithm updated (new ini-values memcached.sess_lock_wait_min, memcached.sess_lock_wait_max and memcached.sess_lock_retries) + * Session extension uses PHP allocators (still some work to do on the rest of the extension) + * Ini-values take effect during session_start or session_regenerate_id + * Fixes crash with session_regenerate_id (work-around for PHP bug) + + Tests + * Fix several problematic tests + Version 2.2.0 (2014-04-01) -------------------------- * Added the OPT_SERVER_TIMEOUT_LIMIT behaviour diff --git a/package.xml b/package.xml index 27491332..357086f8 100644 --- a/package.xml +++ b/package.xml @@ -21,21 +21,20 @@ http://pear.php.net/dtd/package-2.0.xsd"> mkoppanen@php.net yes - 2016-02-22 + 2017-01-27 - 3.0.0a1 + 3.0.0 3.0.0 - alpha - alpha + stable + stable PHP PHP7 release of memcached extension. Note that support for libmemcached 0.x series has been discontinued and the oldest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of -libmemcached. Please note that this is a beta release and reporting any issues would be highly appreciated -before we move closer to releasing stable version. +libmemcached. API * The method signature of get, getByKey, getMulti, and getMultiByKey changed. @@ -179,6 +178,16 @@ Tests 1.4.0b1 + + + igbinary + 2.0 + + + msgpack + 2.0 + + memcached From e495a6bb1de9ab7940d431f3deecf6d8e71584d2 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 30 Jan 2017 14:27:55 -0800 Subject: [PATCH 141/345] Bump version to 3.0.0 --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index 9e466cb4..0b1a9264 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -27,7 +27,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.0.0b1" +#define PHP_MEMCACHED_VERSION "3.0.0" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 218b019509453a463b8485afe1869a42051a6414 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 30 Jan 2017 21:58:31 -0800 Subject: [PATCH 142/345] Fix memory leak from recent change to s_compress_value Commit c85f34c01ba884987fa3ed4daf7846e503a89cdf cleaned up the function, but missed an all-important efree(buffer) on the no-compression path. --- php_memcached.c | 1 + 1 file changed, 1 insertion(+) diff --git a/php_memcached.c b/php_memcached.c index 93d8738f..ba3473de 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -892,6 +892,7 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str } /* Original payload was not modified */ + efree(buffer); return 0; } From e4f4878f123b1b7c2ef839e12c022de9629937ec Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 2 Feb 2017 19:53:25 +0000 Subject: [PATCH 143/345] Travis CI purge old versions of memcached and libmemcached (#309) * Purge all things memcached from Travis CI before installing local copies * Add ancient libmemcached 1.0.2 to Travis CI matrix --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 02c367a9..2581b516 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,7 @@ env: - LIBMEMCACHED_VERSION=1.0.18 # Debian Jessie / Ubuntu Xenial - LIBMEMCACHED_VERSION=1.0.16 # RHEL / CentOS 7 - LIBMEMCACHED_VERSION=1.0.8 # Debian Wheezy / Ubuntu Trusty + - LIBMEMCACHED_VERSION=1.0.2 # Ancient addons: apt: @@ -22,6 +23,7 @@ addons: - libevent-dev before_script: + - sudo apt-get purge -qq '^memcached*' '^libmemcached*' - ./.travis/travis.sh before_script $LIBMEMCACHED_VERSION script: @@ -29,4 +31,4 @@ script: cache: directories: - - $HOME/cache \ No newline at end of file + - $HOME/cache From fa620a48c4e5676c9f79b49694d90e3c3d7e78b6 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 7 Feb 2017 12:34:07 +0000 Subject: [PATCH 144/345] Restore php_libmemcached_compat with workaround for missing memcached_exists (#314) This partially reverts commit c564fd875ead3110b27dd3e1dfb9e5d4afabd042 from #295 --- config.m4 | 2 +- package.xml | 2 ++ php_libmemcached_compat.c | 37 +++++++++++++++++++++++++++++++++++++ php_libmemcached_compat.h | 31 +++++++++++++++++++++++++++++++ php_memcached.c | 2 -- php_memcached_private.h | 10 +++------- php_memcached_session.c | 2 +- 7 files changed, 75 insertions(+), 11 deletions(-) create mode 100644 php_libmemcached_compat.c create mode 100644 php_libmemcached_compat.h diff --git a/config.m4 b/config.m4 index 50e2d3bd..b34c30bf 100644 --- a/config.m4 +++ b/config.m4 @@ -318,7 +318,7 @@ if test "$PHP_MEMCACHED" != "no"; then AC_DEFINE(HAVE_MEMCACHED_EXIST, [1], [Whether memcached_exist is defined]) fi - PHP_MEMCACHED_FILES="php_memcached.c g_fmt.c" + PHP_MEMCACHED_FILES="php_memcached.c php_libmemcached_compat.c g_fmt.c" if test "$PHP_SYSTEM_FASTLZ" != "no"; then AC_CHECK_HEADERS([fastlz.h], [ac_cv_have_fastlz="yes"], [ac_cv_have_fastlz="no"]) diff --git a/package.xml b/package.xml index 357086f8..2f01cf46 100644 --- a/package.xml +++ b/package.xml @@ -73,6 +73,8 @@ Tests + + diff --git a/php_libmemcached_compat.c b/php_libmemcached_compat.c new file mode 100644 index 00000000..bd35d8fe --- /dev/null +++ b/php_libmemcached_compat.c @@ -0,0 +1,37 @@ +/* + +----------------------------------------------------------------------+ + | Copyright (c) 2009 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.0 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_0.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andrei Zmievski | + +----------------------------------------------------------------------+ +*/ + +#include "php_memcached.h" +#include "php_memcached_private.h" +#include "php_libmemcached_compat.h" + +memcached_return php_memcached_exist (memcached_st *memc, zend_string *key) +{ +#ifdef HAVE_MEMCACHED_EXIST + return memcached_exist (memc, key->val, key->len); +#else + memcached_return rc = MEMCACHED_SUCCESS; + uint32_t flags = 0; + size_t value_length = 0; + char *value = NULL; + + value = memcached_get (memc, key->val, key->len, &value_length, &flags, &rc); + if (value) { + free (value); + } + return rc; +#endif +} diff --git a/php_libmemcached_compat.h b/php_libmemcached_compat.h new file mode 100644 index 00000000..9bcbc20f --- /dev/null +++ b/php_libmemcached_compat.h @@ -0,0 +1,31 @@ +/* + +----------------------------------------------------------------------+ + | Copyright (c) 2009 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.0 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_0.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andrei Zmievski | + +----------------------------------------------------------------------+ +*/ + +#ifndef PHP_LIBMEMCACHED_COMPAT +#define PHP_LIBMEMCACHED_COMPAT + +/* this is the version(s) we support */ +#include + +memcached_return php_memcached_exist (memcached_st *memc, zend_string *key); + +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000017 +typedef const memcached_instance_st * php_memcached_instance_st; +#else +typedef memcached_server_instance_st php_memcached_instance_st; +#endif + +#endif diff --git a/php_memcached.c b/php_memcached.c index ba3473de..514f4c33 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -4022,7 +4022,6 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(getLastErrorMessage, arginfo_getLastErrorMessage) MEMC_ME(getLastErrorCode, arginfo_getLastErrorCode) MEMC_ME(getLastErrorErrno, arginfo_getLastErrorErrno) - MEMC_ME(getLastDisconnectedServer, arginfo_getLastDisconnectedServer) MEMC_ME(getStats, arginfo_getStats) @@ -4216,7 +4215,6 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(DISTRIBUTION_MODULA, MEMCACHED_DISTRIBUTION_MODULA); REGISTER_MEMC_CLASS_CONST_LONG(DISTRIBUTION_CONSISTENT, MEMCACHED_DISTRIBUTION_CONSISTENT); REGISTER_MEMC_CLASS_CONST_LONG(DISTRIBUTION_VIRTUAL_BUCKET, MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET); - REGISTER_MEMC_CLASS_CONST_LONG(OPT_LIBKETAMA_COMPATIBLE, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED); REGISTER_MEMC_CLASS_CONST_LONG(OPT_LIBKETAMA_HASH, MEMCACHED_BEHAVIOR_KETAMA_HASH); REGISTER_MEMC_CLASS_CONST_LONG(OPT_TCP_KEEPALIVE, MEMCACHED_BEHAVIOR_TCP_KEEPALIVE); diff --git a/php_memcached_private.h b/php_memcached_private.h index fe6ccc2c..a04e19be 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -25,13 +25,7 @@ # include "config.h" #endif -#include - -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000017 -typedef const memcached_instance_st * php_memcached_instance_st; -#else -typedef memcached_server_instance_st php_memcached_instance_st; -#endif +#include "php_libmemcached_compat.h" #include #include @@ -214,6 +208,8 @@ PHP_MINFO_FUNCTION(memcached); char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_cache); +memcached_return php_memcached_exist (memcached_st *memc, zend_string *key); + zend_bool php_memc_init_sasl_if_needed(); #endif /* PHP_MEMCACHED_PRIVATE_H */ diff --git a/php_memcached_session.c b/php_memcached_session.c index 25ca0ae2..1695b330 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -530,7 +530,7 @@ PS_VALIDATE_SID_FUNC(memcached) { memcached_st *memc = PS_GET_MOD_DATA(); - if (memcached_exist(memc, key->val, key->len) == MEMCACHED_SUCCESS) { + if (php_memcached_exist(memc, key) == MEMCACHED_SUCCESS) { return SUCCESS; } else { return FAILURE; From a86de05e86c47542f03084b6a6f37b5ba1e733cc Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 7 Feb 2017 12:34:23 +0000 Subject: [PATCH 145/345] Fix compiling with memcached binary protocol enabled (#312) --- php_memcached.c | 22 +++------------------- php_memcached.h | 8 ++++++++ php_memcached_server.c | 33 ++++++++++++++------------------- 3 files changed, 25 insertions(+), 38 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 514f4c33..78528332 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -51,12 +51,6 @@ # include "ext/msgpack/php_msgpack.h" #endif -#ifdef ZTS -#define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, memc.v) -#else -#define MEMC_G(v) (php_memcached_globals.memc.v) -#endif - static int le_memc; static int php_memc_list_entry(void) { @@ -238,24 +232,14 @@ static inline php_memc_server_t *php_memc_server_fetch_object(zend_object *obj) } #define Z_MEMC_SERVER_P(zv) php_memc_server_fetch_object(Z_OBJ_P(zv)) -#ifdef ZTS -#define MEMC_SERVER_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, server.v) -#else -#define MEMC_SERVER_G(v) (php_memcached_globals.server.v) -#endif +static zend_object_handlers memcached_server_object_handlers; +static zend_class_entry *memcached_server_ce = NULL; #endif static zend_class_entry *memcached_ce = NULL; - static zend_class_entry *memcached_exception_ce = NULL; - static zend_object_handlers memcached_object_handlers; -#ifdef HAVE_MEMCACHED_PROTOCOL -static zend_object_handlers memcached_server_object_handlers; -static zend_class_entry *memcached_server_ce = NULL; -#endif - #ifdef HAVE_SPL static zend_class_entry *spl_ce_RuntimeException = NULL; #endif @@ -3644,7 +3628,7 @@ PHP_METHOD(MemcachedServer, run) static PHP_METHOD(MemcachedServer, on) { - long event; + zend_long event; zend_fcall_info fci; zend_fcall_info_cache fci_cache; zend_bool rc = 0; diff --git a/php_memcached.h b/php_memcached.h index 0b1a9264..5d1e3a77 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -42,6 +42,14 @@ PHP_MEMCACHED_API zend_class_entry *php_memc_get_exception_base(int root); extern zend_module_entry memcached_module_entry; #define phpext_memcached_ptr &memcached_module_entry +#ifdef ZTS +#define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, memc.v) +#define MEMC_SERVER_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, server.v) +#else +#define MEMC_G(v) (php_memcached_globals.memc.v) +#define MEMC_SERVER_G(v) (php_memcached_globals.server.v) +#endif + #endif /* PHP_MEMCACHED_H */ /* diff --git a/php_memcached_server.c b/php_memcached_server.c index 94305101..4c0080e8 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -24,7 +24,7 @@ #undef _NDEBUG #include -#define MEMC_GET_CB(cb_type) (MEMC_G(server.callbacks)[cb_type]) +#define MEMC_GET_CB(cb_type) (MEMC_SERVER_G(callbacks)[cb_type]) #define MEMC_HAS_CB(cb_type) (MEMC_GET_CB(cb_type).fci.size > 0) #define MEMC_MAKE_ZVAL_COOKIE(my_zcookie, my_ptr) \ @@ -37,7 +37,7 @@ #define MEMC_MAKE_RESULT_CAS(my_zresult_cas, my_result_cas) \ do { \ my_result_cas = 0; \ - my_result_cas = zval_get_double(my_zresult_cas); \ + my_result_cas = zval_get_double(&my_zresult_cas); \ } while (0) @@ -56,27 +56,22 @@ typedef struct { } php_memc_client_t; static -long s_invoke_php_callback (php_memc_server_cb_t *cb, zval ***params, ssize_t param_count) +long s_invoke_php_callback (php_memc_server_cb_t *cb, zval *params, ssize_t param_count) { - long retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval *retval_ptr = NULL; + zval *retval = NULL; - cb->fci.params = params; + cb->fci.retval = retval; + cb->fci.params = params; cb->fci.param_count = param_count; - - /* Call the cb */ - cb->fci.no_separation = 1; - cb->fci.retval_ptr_ptr = &retval_ptr; + cb->fci.no_separation = 1; if (zend_call_function(&(cb->fci), &(cb->fci_cache)) == FAILURE) { - char *buf = php_memc_printable_func (&(cb->fci), &(cb->fci_cache)); + char *buf = php_memc_printable_func(&(cb->fci), &(cb->fci_cache)); php_error_docref(NULL, E_WARNING, "Failed to invoke callback %s()", buf); efree (buf); } - if (retval_ptr) { - retval = zval_get_long(retval_ptr); - } - return retval; + + return retval == NULL ? PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND : zval_get_long(retval); } // memcached protocol callbacks @@ -217,7 +212,7 @@ protocol_binary_response_status s_incr_decr_handler (php_memc_event_t event, con retval = s_invoke_php_callback (&MEMC_GET_CB(event), params, 7); - *result = (uint64_t)zval_get_long(zresult); + *result = (uint64_t)zval_get_long(&zresult); MEMC_MAKE_RESULT_CAS(zresult_cas, *result_cas); @@ -301,7 +296,7 @@ protocol_binary_response_status s_flush_handler(const void *cookie, uint32_t whe MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); ZVAL_COPY(¶ms[0], &zcookie); - ZVAL_COPY(¶ms[1], &zwhen) + ZVAL_COPY(¶ms[1], &zwhen); retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_FLUSH), params, 2); @@ -561,7 +556,7 @@ protocol_binary_response_status s_version_handler (const void *cookie, convert_to_string(&zversion); } - retval = response_handler (cookie, Z_STRVAL_P(zversion), (uint32_t) Z_STRLEN_P(zversion)); + retval = response_handler (cookie, Z_STRVAL(zversion), (uint32_t) Z_STRLEN(zversion)); } zval_ptr_dtor(¶ms[0]); @@ -592,7 +587,7 @@ void s_handle_memcached_event (evutil_socket_t fd, short what, void *arg) socklen_t addr_in_len = sizeof(addr_in); if (getpeername (fd, (struct sockaddr *) &addr_in, &addr_in_len) == 0) { - ZVAL_STRING(&zremoteip, inet_ntoa (addr_in.sin_addr), 1); + ZVAL_STRING(&zremoteip, inet_ntoa (addr_in.sin_addr)); ZVAL_LONG(&zremoteport, ntohs (addr_in.sin_port)); } else { php_error_docref(NULL, E_WARNING, "getpeername failed: %s", strerror (errno)); From 08b39ed6b142a1a059295c803d50e625741e3f5a Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 7 Feb 2017 12:34:41 +0000 Subject: [PATCH 146/345] Ignore specific errors from memcached_dump for getAllKeys() with newer memcached servers (#315) --- php_memcached.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 78528332..d6f42575 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2725,7 +2725,15 @@ PHP_METHOD(Memcached, getAllKeys) array_init(return_value); rc = memcached_dump(intern->memc, callback, return_value, 1); - if (s_memc_status_handle_result_code(intern, rc) == FAILURE) { + + /* Ignore two errors. libmemcached has a hardcoded loop of 200 slab + * classes that matches memcached < 1.4.24, at which version the server + * has only 63 slabs and throws an error when requesting the 64th slab. + * + * In multi-server some non-deterministic number of elements will be dropped. + */ + if (rc != MEMCACHED_CLIENT_ERROR && rc != MEMCACHED_SERVER_ERROR + && s_memc_status_handle_result_code(intern, rc) == FAILURE) { zval_dtor(return_value); RETURN_FALSE; } From 115cc0a2c41f617b639c55beed5513a06898403f Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 7 Feb 2017 12:34:54 +0000 Subject: [PATCH 147/345] Add API entries for flushBuffers() and getAllKeys() (#316) --- memcached-api.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/memcached-api.php b/memcached-api.php index 64b20b26..df725091 100644 --- a/memcached-api.php +++ b/memcached-api.php @@ -275,7 +275,11 @@ public function getLastDisconnectedServer( ) {} public function flush( $delay = 0 ) {} + public function flushBuffers( ) {} + public function getStats( $type = null ) {} + + public function getAllKeys( ) {} public function getVersion( ) {} From d019588648d3e7dd8d642234c95ff6f85cac1d94 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 7 Feb 2017 06:19:13 -0800 Subject: [PATCH 148/345] Notes for version 3.0.1 --- ChangeLog | 9 +++++++ package.xml | 67 +++++++++++++++++++++++++++++++++++------------------ 2 files changed, 54 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index 24cb0a74..a21e14b8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ memcached extension changelog +Version 3.0.1 (2017-02-07) +------------- + + * Add API entries for flushBuffers() and getAllKeys() (#316) + * Ignore specific errors from memcached_dump for getAllKeys() with newer memcached servers (#315) + * Fix compiling with memcached binary protocol enabled (#312) + * Restore php_libmemcached_compat with workaround for missing memcached_exists (#314) + * Travis CI purge old versions of memcached and libmemcached (#309) + Version 3.0.0 (2017-01-27) -------------------------- * Support for PHP 7.0 and PHP 7.1 diff --git a/package.xml b/package.xml index 2f01cf46..3366baf3 100644 --- a/package.xml +++ b/package.xml @@ -21,9 +21,9 @@ http://pear.php.net/dtd/package-2.0.xsd"> mkoppanen@php.net yes - 2017-01-27 + 2017-02-07 - 3.0.0 + 3.0.1 3.0.0 @@ -36,26 +36,12 @@ PHP7 release of memcached extension. Note that support for libmemcached 0.x seri and the oldest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of libmemcached. -API - * The method signature of get, getByKey, getMulti, and getMultiByKey changed. - * get* and getMulti* commands no longer take cas or user flags parameters. - * get* and getMulti* commands now take the Memcached::GET_EXTENDED flag to retrieve user flags and cas tokens. - * Fixes getStats command to return all stats from all servers - * Fixes allKeys command behaviour - * Fixes error where cache callback for get command was not setting expiration time properly - * Added server type to server list - * Remove use_sasl ini-variable and initialise sasl as needed - * CAS tokens are returned as integers and they overflow to strings as needed - -Session handler - * The session memcached protocol config name was changed, and the default protocol was changed from text to binary protocol. If your memcached setup does not support the binary protocol(e.g. if using twemproxy), then set memcached.sess_binary_protocol = Off. (Previously called memcached.sess_binary) - * Session lock algorithm updated (new ini-values memcached.sess_lock_wait_min, memcached.sess_lock_wait_max and memcached.sess_lock_retries) - * Session extension uses PHP allocators (still some work to do on the rest of the extension) - * Ini-values take effect during session_start or session_regenerate_id - * Fixes crash with session_regenerate_id (work-around for PHP bug) - -Tests - * Fix several problematic tests +Fixes + * Add API entries for flushBuffers() and getAllKeys() (#316) + * Ignore specific errors from memcached_dump for getAllKeys() with newer memcached servers (#315) + * Fix compiling with memcached binary protocol enabled (#312) + * Restore php_libmemcached_compat with workaround for missing memcached_exists (#314) + * Travis CI purge old versions of memcached and libmemcached (#309) @@ -196,6 +182,43 @@ Tests + + + stable + stable + + + 3.0.0 + 3.0.0 + + 2016-01-27 + +PHP7 release of memcached extension. Note that support for libmemcached 0.x series has been discontinued +and the oldest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of +libmemcached. + +API + * The method signature of get, getByKey, getMulti, and getMultiByKey changed. + * get* and getMulti* commands no longer take cas or user flags parameters. + * get* and getMulti* commands now take the Memcached::GET_EXTENDED flag to retrieve user flags and cas tokens. + * Fixes getStats command to return all stats from all servers + * Fixes allKeys command behaviour + * Fixes error where cache callback for get command was not setting expiration time properly + * Added server type to server list + * Remove use_sasl ini-variable and initialise sasl as needed + * CAS tokens are returned as integers and they overflow to strings as needed + +Session handler + * The session memcached protocol config name was changed, and the default protocol was changed from text to binary protocol. If your memcached setup does not support the binary protocol(e.g. if using tw + * Session lock algorithm updated (new ini-values memcached.sess_lock_wait_min, memcached.sess_lock_wait_max and memcached.sess_lock_retries) + * Session extension uses PHP allocators (still some work to do on the rest of the extension) + * Ini-values take effect during session_start or session_regenerate_id + * Fixes crash with session_regenerate_id (work-around for PHP bug) + +Tests + * Fix several problematic tests + + alpha From 71f20e19253f27d6deaeab200007bd4cf9d8aec4 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 7 Feb 2017 06:20:51 -0800 Subject: [PATCH 149/345] Bump version to 3.0.1 --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index 5d1e3a77..1a9411f9 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -27,7 +27,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.0.0" +#define PHP_MEMCACHED_VERSION "3.0.1" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 8a40f2ca5f08f3b3d9fe1eb7f068737484b0bc03 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Wed, 8 Feb 2017 10:00:47 -0800 Subject: [PATCH 150/345] Add myself to package.xml before uploading to PECL --- package.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/package.xml b/package.xml index 3366baf3..bbec4158 100644 --- a/package.xml +++ b/package.xml @@ -21,6 +21,12 @@ http://pear.php.net/dtd/package-2.0.xsd"> mkoppanen@php.net yes + + Aaron Stone + sodabrew + aaron@serendipity.cx + yes + 2017-02-07 3.0.1 From f8fd6228e34e1b49947890b060a501a6eab6978c Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 9 Feb 2017 07:24:15 +0100 Subject: [PATCH 151/345] ensure tests are ok for 32bits build --- tests/gh_90.phpt | 4 ++-- tests/incrdecr.phpt | 6 +++--- tests/incrdecr_bykey.phpt | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/gh_90.phpt b/tests/gh_90.phpt index 733b7615..2a16f603 100644 --- a/tests/gh_90.phpt +++ b/tests/gh_90.phpt @@ -12,7 +12,7 @@ $memcached = memc_get_instance (array ( // Create a key for use as a lock. If this key already exists, wait till it doesn't exist. { $key = 'LockKey'; - $lockToken = mt_rand(0, pow(2, 32)); //Random value betwen 0 and 2^32 for ownership verification + $lockToken = mt_rand(0, mt_getrandmax()); //Random value for ownership verification while (true) { @@ -88,4 +88,4 @@ array(10) { int(1) ["9_%s"]=> int(1) -} \ No newline at end of file +} diff --git a/tests/incrdecr.phpt b/tests/incrdecr.phpt index cb3914a4..b4e9469b 100644 --- a/tests/incrdecr.phpt +++ b/tests/incrdecr.phpt @@ -42,10 +42,10 @@ echo $php_errormsg, "\n"; var_dump($m->get('foo')); echo "Enormous offset\n"; -$m->increment('foo', 4294967296); +$m->increment('foo', 0x7f000000); var_dump($m->get('foo')); -$m->decrement('foo', 4294967296); +$m->decrement('foo', 0x7f000000); var_dump($m->get('foo')); --EXPECT-- @@ -68,5 +68,5 @@ int(1) Memcached::decrement(): offset cannot be a negative value int(1) Enormous offset -int(4294967297) +int(2130706433) int(1) diff --git a/tests/incrdecr_bykey.phpt b/tests/incrdecr_bykey.phpt index 809f3b83..8b931fa7 100644 --- a/tests/incrdecr_bykey.phpt +++ b/tests/incrdecr_bykey.phpt @@ -39,10 +39,10 @@ echo $php_errormsg, "\n"; var_dump($m->get('foo')); echo "Enormous offset\n"; -$m->incrementByKey('foo', 'foo', 4294967296); +$m->incrementByKey('foo', 'foo', 0x7f000000); var_dump($m->get('foo')); -$m->decrementByKey('foo', 'foo', 4294967296); +$m->decrementByKey('foo', 'foo', 0x7f000000); var_dump($m->get('foo')); --EXPECT-- @@ -62,5 +62,5 @@ int(1) Memcached::decrementByKey(): offset cannot be a negative value int(1) Enormous offset -int(4294967297) +int(2130706433) int(1) From ecd77ab93ff060f27bef32e40c2bd88fba3df199 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 9 Feb 2017 06:40:50 -0800 Subject: [PATCH 152/345] Recommend libmemcached 1.0.18 or higher to match the release notes --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 0cb2c032..f145c2df 100644 --- a/README.markdown +++ b/README.markdown @@ -34,7 +34,7 @@ php-memcached 2.x: * Optionally supports igbinary 1.0 or higher. * Optionally supports msgpack 0.5 or higher. -[libmemcached](http://libmemcached.org/libMemcached.html) version 1.0.16 or +[libmemcached](http://libmemcached.org/libMemcached.html) version 1.0.18 or higher is recommended for best performance and compatibility with memcached servers. From 83d5f308999ffad2c0642b7e450e2e350e464342 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 10 Feb 2017 13:51:14 +0000 Subject: [PATCH 153/345] Separate test for 64-bit increment/decrement/incrementByKey/decrementByKey (#321) --- package.xml | 2 ++ tests/incrdecr_64.phpt | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 tests/incrdecr_64.phpt diff --git a/package.xml b/package.xml index bbec4158..7aadf4db 100644 --- a/package.xml +++ b/package.xml @@ -74,6 +74,7 @@ Fixes + @@ -143,6 +144,7 @@ Fixes + diff --git a/tests/incrdecr_64.phpt b/tests/incrdecr_64.phpt new file mode 100644 index 00000000..dfa32c6a --- /dev/null +++ b/tests/incrdecr_64.phpt @@ -0,0 +1,39 @@ +--TEST-- +64-bit Memcached::increment() decrement() incrementByKey() decrementByKey() +--SKIPIF-- + +--FILE-- +set('foo', 1); +var_dump($m->get('foo')); + +echo "Enormous offset 64-bit\n"; +$m->increment('foo', 0x100000000); +var_dump($m->get('foo')); + +$m->decrement('foo', 0x100000000); +var_dump($m->get('foo')); + +echo "Enormous offset 64-bit by key\n"; +$m->incrementByKey('foo', 'foo', 0x100000000); +var_dump($m->get('foo')); + +$m->decrementByKey('foo', 'foo', 0x100000000); +var_dump($m->get('foo')); + +--EXPECT-- +Normal +int(1) +Enormous offset 64-bit +int(4294967297) +int(1) +Enormous offset 64-bit by key +int(4294967297) +int(1) From f7c92b06997d298f63a13d1791fa7a050c8598b9 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 12 Feb 2017 15:56:22 +0000 Subject: [PATCH 154/345] Update warning for touch command in binary protocol mode with libmemcached < 1.0.18 (#322) --- package.xml | 1 + php_libmemcached_compat.c | 21 +++++++++++++++ php_libmemcached_compat.h | 3 +++ php_memcached.c | 13 ++------- php_memcached_session.c | 2 +- tests/gh_155.phpt | 7 +++-- tests/session_basic.phpt | 1 + tests/session_basic2.phpt | 1 + tests/session_basic3.phpt | 1 + tests/session_lazy_warning.phpt | 47 +++++++++++++++++++++++++++++++++ tests/session_lock-php71.phpt | 4 +++ tests/session_lock.phpt | 4 +++ tests/touch_binary.phpt | 5 +++- 13 files changed, 95 insertions(+), 15 deletions(-) create mode 100644 tests/session_lazy_warning.phpt diff --git a/package.xml b/package.xml index 7aadf4db..a5c7c07b 100644 --- a/package.xml +++ b/package.xml @@ -157,6 +157,7 @@ Fixes + diff --git a/php_libmemcached_compat.c b/php_libmemcached_compat.c index bd35d8fe..7f003b1d 100644 --- a/php_libmemcached_compat.c +++ b/php_libmemcached_compat.c @@ -35,3 +35,24 @@ memcached_return php_memcached_exist (memcached_st *memc, zend_string *key) return rc; #endif } + +memcached_return php_memcached_touch(memcached_st *memc, const char *key, size_t key_len, time_t expiration) +{ +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000018 + if (memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { + php_error_docref(NULL, E_WARNING, "using touch command with binary protocol is not recommended with libmemcached versions below 1.0.18, please use ascii protocol or upgrade libmemcached"); + } +#endif + return memcached_touch(memc, key, key_len, expiration); +} + +memcached_return php_memcached_touch_by_key(memcached_st *memc, const char *server_key, size_t server_key_len, const char *key, size_t key_len, time_t expiration) +{ +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000018 + if (memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { + php_error_docref(NULL, E_WARNING, "using touch command with binary protocol is not recommended with libmemcached versions below 1.0.18, please use ascii protocol or upgrade libmemcached"); + } +#endif + return memcached_touch_by_key(memc, server_key, server_key_len, key, key_len, expiration); +} + diff --git a/php_libmemcached_compat.h b/php_libmemcached_compat.h index 9bcbc20f..42a409dc 100644 --- a/php_libmemcached_compat.h +++ b/php_libmemcached_compat.h @@ -22,6 +22,9 @@ memcached_return php_memcached_exist (memcached_st *memc, zend_string *key); +memcached_return php_memcached_touch(memcached_st *memc, const char *key, size_t key_len, time_t expiration); +memcached_return php_memcached_touch_by_key(memcached_st *memc, const char *server_key, size_t server_key_len, const char *key, size_t key_len, time_t expiration); + #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000017 typedef const memcached_instance_st * php_memcached_instance_st; #else diff --git a/php_memcached.c b/php_memcached.c index d6f42575..19673323 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1081,7 +1081,7 @@ zend_bool s_memc_write_zval (php_memc_object_t *intern, php_memc_write_op op, ze break; case MEMC_OP_TOUCH: - status = memcached_touch_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), expiration); + status = php_memcached_touch_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), expiration); break; case MEMC_OP_ADD: @@ -1113,7 +1113,7 @@ zend_bool s_memc_write_zval (php_memc_object_t *intern, php_memc_write_op op, ze break; case MEMC_OP_TOUCH: - status = memcached_touch(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), expiration); + status = php_memcached_touch(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), expiration); break; case MEMC_OP_ADD: @@ -1959,15 +1959,6 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool } } - - if (op == MEMC_OP_TOUCH) { -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000016 - if (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { - php_error_docref(NULL, E_WARNING, "using touch command with binary protocol is not recommended with libmemcached versions below 1.0.16"); - } -#endif - } - if (!s_memc_write_zval (intern, op, server_key, key, value, expiration)) { RETURN_FALSE; } diff --git a/php_memcached_session.c b/php_memcached_session.c index 1695b330..b6d93c5f 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -542,7 +542,7 @@ PS_UPDATE_TIMESTAMP_FUNC(memcached) memcached_st *memc = PS_GET_MOD_DATA(); time_t expiration = s_session_expiration(maxlifetime); - if (memcached_touch(memc, key->val, key->len, expiration) == MEMCACHED_FAILURE) { + if (php_memcached_touch(memc, key->val, key->len, expiration) == MEMCACHED_FAILURE) { return FAILURE; } return SUCCESS; diff --git a/tests/gh_155.phpt b/tests/gh_155.phpt index a5b61d00..699e8eca 100644 --- a/tests/gh_155.phpt +++ b/tests/gh_155.phpt @@ -4,7 +4,10 @@ Test for bug 155 --FILE-- setOption(Memcached::OPT_BINARY_PROTOCOL,true); +$m->setOption(Memcached::OPT_BINARY_PROTOCOL, true); $m->addServer(MEMC_SERVER_HOST, MEMC_SERVER_PORT); $key = 'bug_155_' . uniqid(); diff --git a/tests/session_basic.phpt b/tests/session_basic.phpt index 3fdb6bd7..0e8b3469 100644 --- a/tests/session_basic.phpt +++ b/tests/session_basic.phpt @@ -7,6 +7,7 @@ if (!Memcached::HAVE_SESSION) print "skip"; ?> --INI-- session.save_handler = memcached +memcached.sess_binary_protocol = Off --FILE-- --INI-- session.save_handler = memcached +memcached.sess_binary_protocol = Off --FILE-- --INI-- session.save_handler = memcached +memcached.sess_binary_protocol = Off --FILE-- = 0x01000018) die ('skip too old libmemcached'); +?> +--INI-- +session.save_handler = memcached +memcached.sess_binary_protocol = On +--FILE-- +TRUE]); +$_SESSION['foo'] = 1; +session_write_close(); + +$_SESSION = NULL; + +var_dump($_SESSION); +session_start(); +var_dump($_SESSION); +session_write_close(); + +session_start(); +session_destroy(); + +session_start(); +var_dump($_SESSION); +session_write_close(); + + +--EXPECTF-- +NULL +array(1) { + ["foo"]=> + int(1) +} + +Warning: session_write_close(): using touch command with binary protocol is not recommended with libmemcached versions below 1.0.18, please use ascii protocol or upgrade libmemcached in %s on line %d +array(0) { +} diff --git a/tests/session_lock-php71.phpt b/tests/session_lock-php71.phpt index 207f64cf..c0fceb67 100644 --- a/tests/session_lock-php71.phpt +++ b/tests/session_lock-php71.phpt @@ -14,6 +14,10 @@ memcached.sess_lock_wait_max = 1000 memcached.sess_lock_retries = 3 memcached.sess_prefix = "memc.test." +# Turn off binary protocol while the test matrix has older versions of +# libmemcached for which the extension warns of a broken touch command. +memcached.sess_binary_protocol = Off + session.save_handler = memcached --FILE-- diff --git a/tests/session_lock.phpt b/tests/session_lock.phpt index 570e5a2a..cedc83bb 100644 --- a/tests/session_lock.phpt +++ b/tests/session_lock.phpt @@ -14,6 +14,10 @@ memcached.sess_lock_wait_max = 1000 memcached.sess_lock_retries = 3 memcached.sess_prefix = "memc.test." +# Turn off binary protocol while the test matrix has older versions of +# libmemcached for which the extension warns of a broken touch command. +memcached.sess_binary_protocol = Off + session.save_handler = memcached --FILE-- diff --git a/tests/touch_binary.phpt b/tests/touch_binary.phpt index cc35e8fb..382c1778 100644 --- a/tests/touch_binary.phpt +++ b/tests/touch_binary.phpt @@ -4,7 +4,10 @@ Touch in binary mode --FILE-- Date: Sun, 12 Feb 2017 08:05:55 -0800 Subject: [PATCH 155/345] Release notes for 3.0.2 --- ChangeLog | 9 ++++++++- package.xml | 36 +++++++++++++++++++++++++++++------- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index a21e14b8..914cb4e3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,14 @@ memcached extension changelog +Version 3.0.2 (2017-02-12) +-------------------------- + + * Update warning for touch command in binary protocol mode with libmemcached < 1.0.18 (#322) + * Add tests for 64-bit increment/decrement/incrementByKey/decrementByKey (#321) + * Fix tests for 32-bit increment/decrement/incrementByKey/decrementByKey (#319) + Version 3.0.1 (2017-02-07) -------------- +-------------------------- * Add API entries for flushBuffers() and getAllKeys() (#316) * Ignore specific errors from memcached_dump for getAllKeys() with newer memcached servers (#315) diff --git a/package.xml b/package.xml index a5c7c07b..82b6a39e 100644 --- a/package.xml +++ b/package.xml @@ -27,9 +27,9 @@ http://pear.php.net/dtd/package-2.0.xsd"> aaron@serendipity.cx yes - 2017-02-07 + 2017-02-12 - 3.0.1 + 3.0.2 3.0.0 @@ -43,11 +43,10 @@ and the oldest actively tested version is 1.0.2. It is highly recommended to use libmemcached. Fixes - * Add API entries for flushBuffers() and getAllKeys() (#316) - * Ignore specific errors from memcached_dump for getAllKeys() with newer memcached servers (#315) - * Fix compiling with memcached binary protocol enabled (#312) - * Restore php_libmemcached_compat with workaround for missing memcached_exists (#314) - * Travis CI purge old versions of memcached and libmemcached (#309) + * Update warning for touch command in binary protocol mode with libmemcached < 1.0.18 (#322) + * Add tests for 64-bit increment/decrement/incrementByKey/decrementByKey (#321) + * Fix tests for 32-bit increment/decrement/incrementByKey/decrementByKey (#319) + @@ -191,6 +190,29 @@ Fixes + + + stable + stable + + + 3.0.1 + 3.0.0 + + 2016-02-07 + +PHP7 release of memcached extension. Note that support for libmemcached 0.x series has been discontinued +and the oldest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of +libmemcached. + +Fixes + * Add API entries for flushBuffers() and getAllKeys() (#316) + * Ignore specific errors from memcached_dump for getAllKeys() with newer memcached servers (#315) + * Fix compiling with memcached binary protocol enabled (#312) + * Restore php_libmemcached_compat with workaround for missing memcached_exists (#314) + * Travis CI purge old versions of memcached and libmemcached (#309) + + stable From de250ed68cce14b6779316b3909b22e777469bf8 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 12 Feb 2017 08:06:04 -0800 Subject: [PATCH 156/345] Bump version to 3.0.2 --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index 1a9411f9..e36b614b 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -27,7 +27,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.0.1" +#define PHP_MEMCACHED_VERSION "3.0.2" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 81bc04f1ac45181b06a788124c04e381d8aa2481 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 12 Feb 2017 16:04:39 -0800 Subject: [PATCH 157/345] Use the word below instead of less-than symbol in package.xml because XML --- package.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.xml b/package.xml index 82b6a39e..bfaf51ae 100644 --- a/package.xml +++ b/package.xml @@ -43,7 +43,7 @@ and the oldest actively tested version is 1.0.2. It is highly recommended to use libmemcached. Fixes - * Update warning for touch command in binary protocol mode with libmemcached < 1.0.18 (#322) + * Update warning for touch command in binary protocol mode with libmemcached below 1.0.18 (#322) * Add tests for 64-bit increment/decrement/incrementByKey/decrementByKey (#321) * Fix tests for 32-bit increment/decrement/incrementByKey/decrementByKey (#319) From 1e7e4eedb62befa7449a92528d6e0adaf8786369 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sun, 19 Feb 2017 18:26:55 +0800 Subject: [PATCH 158/345] Fixed issue #327 --- php_memcached_session.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/php_memcached_session.c b/php_memcached_session.c index b6d93c5f..8678ffff 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -435,8 +435,9 @@ PS_READ_FUNC(memcached) payload = memcached_get(memc, key->val, key->len, &payload_len, &flags, &status); if (status == MEMCACHED_SUCCESS) { + zend_bool *is_persistent = memcached_get_user_data(memc); *val = zend_string_init(payload, payload_len, 0); - efree(payload); + pefree(payload, *is_persistent); return SUCCESS; } else if (status == MEMCACHED_NOTFOUND) { *val = ZSTR_EMPTY_ALLOC(); From bff303547f67f6832a5df48b3e5eb78642871156 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sun, 19 Feb 2017 18:32:16 +0800 Subject: [PATCH 159/345] Fixed memleak (severs) --- package.xml | 1 + php_memcached_session.c | 1 + tests/session_persistent.phpt | 27 +++++++++++++++++++++++++++ 3 files changed, 29 insertions(+) create mode 100644 tests/session_persistent.phpt diff --git a/package.xml b/package.xml index bfaf51ae..554aa428 100644 --- a/package.xml +++ b/package.xml @@ -118,6 +118,7 @@ Fixes + diff --git a/php_memcached_session.c b/php_memcached_session.c index 8678ffff..afa973bb 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -351,6 +351,7 @@ PS_OPEN_FUNC(memcached) else { efree(plist_key); PS_SET_MOD_DATA(memc); + memcached_server_list_free(servers); return SUCCESS; } } diff --git a/tests/session_persistent.phpt b/tests/session_persistent.phpt new file mode 100644 index 00000000..cb29c3e8 --- /dev/null +++ b/tests/session_persistent.phpt @@ -0,0 +1,27 @@ +--TEST-- +Session persistent +--SKIPIF-- + +--INI-- +session.save_handler=memcached +memcached.sess_persistent=1 +--FILE-- + +--EXPECT-- +array(1) { + ["test"]=> + bool(true) +} From a8517cd97b4df25cdc04b3f40b810c0202c7daba Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sun, 19 Feb 2017 18:34:48 +0800 Subject: [PATCH 160/345] dev version --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index e36b614b..1ec55df6 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -27,7 +27,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.0.2" +#define PHP_MEMCACHED_VERSION "3.0.3-dev" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 99cab0e08166ca9b4219016b30cf0d5e2c0f393c Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 19 Feb 2017 17:23:35 -0800 Subject: [PATCH 161/345] Fix session-persistent test failures on older libmemcached versions --- tests/session_persistent.phpt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/session_persistent.phpt b/tests/session_persistent.phpt index cb29c3e8..e096f2b6 100644 --- a/tests/session_persistent.phpt +++ b/tests/session_persistent.phpt @@ -3,7 +3,8 @@ Session persistent --SKIPIF-- --INI-- session.save_handler=memcached From beb58dc69f59fff185baa92cef6a6e739769a5ab Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 19 Feb 2017 19:30:22 -0800 Subject: [PATCH 162/345] Replace traditional free with pefree to match the registered allocators, fixes #328 --- php_libmemcached_compat.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/php_libmemcached_compat.c b/php_libmemcached_compat.c index 7f003b1d..4e294647 100644 --- a/php_libmemcached_compat.c +++ b/php_libmemcached_compat.c @@ -18,19 +18,20 @@ #include "php_memcached_private.h" #include "php_libmemcached_compat.h" -memcached_return php_memcached_exist (memcached_st *memc, zend_string *key) +memcached_return php_memcached_exist(memcached_st *memc, zend_string *key) { #ifdef HAVE_MEMCACHED_EXIST - return memcached_exist (memc, key->val, key->len); + return memcached_exist(memc, key->val, key->len); #else memcached_return rc = MEMCACHED_SUCCESS; uint32_t flags = 0; size_t value_length = 0; char *value = NULL; - value = memcached_get (memc, key->val, key->len, &value_length, &flags, &rc); + value = memcached_get(memc, key->val, key->len, &value_length, &flags, &rc); if (value) { - free (value); + zend_bool *is_persistent = memcached_get_user_data(memc); + pefree(value, *is_persistent); } return rc; #endif From 357efc40df1fee72a5fca918be308ebf97afd87b Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 19 Feb 2017 19:48:33 -0800 Subject: [PATCH 163/345] Release notes for 3.0.3 --- ChangeLog | 6 ++++++ package.xml | 31 +++++++++++++++++++++++++------ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 914cb4e3..1db3dd44 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ memcached extension changelog +Version 3.0.3 (2017-02-19) +-------------------------- + + * Fix crash when checking session data with older versions of libmemcached (#328) + * Fix crash due to zend_mm_corrupted when fetching session data (#327) + Version 3.0.2 (2017-02-12) -------------------------- diff --git a/package.xml b/package.xml index 554aa428..2306344d 100644 --- a/package.xml +++ b/package.xml @@ -27,9 +27,9 @@ http://pear.php.net/dtd/package-2.0.xsd"> aaron@serendipity.cx yes - 2017-02-12 + 2017-02-19 - 3.0.2 + 3.0.3 3.0.0 @@ -43,10 +43,8 @@ and the oldest actively tested version is 1.0.2. It is highly recommended to use libmemcached. Fixes - * Update warning for touch command in binary protocol mode with libmemcached below 1.0.18 (#322) - * Add tests for 64-bit increment/decrement/incrementByKey/decrementByKey (#321) - * Fix tests for 32-bit increment/decrement/incrementByKey/decrementByKey (#319) - + * Fix crash when checking session data with older versions of libmemcached (#328) + * Fix crash due to zend_mm_corrupted when fetching session data (#327) @@ -191,6 +189,27 @@ Fixes + + + stable + stable + + + 3.0.2 + 3.0.0 + + 2016-02-12 + +PHP7 release of memcached extension. Note that support for libmemcached 0.x series has been discontinued +and the oldest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of +libmemcached. + +Fixes + * Update warning for touch command in binary protocol mode with libmemcached below 1.0.18 (#322) + * Add tests for 64-bit increment/decrement/incrementByKey/decrementByKey (#321) + * Fix tests for 32-bit increment/decrement/incrementByKey/decrementByKey (#319) + + stable From 466485a2ca98b4c1354c7815d23e3bdc64b69db9 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 19 Feb 2017 19:48:43 -0800 Subject: [PATCH 164/345] Bump version to 3.0.3 --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index 1ec55df6..65a0349f 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -27,7 +27,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.0.3-dev" +#define PHP_MEMCACHED_VERSION "3.0.3" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From d81697f7a04646edbbed8ecf34cb524ab1ff8d3c Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Mon, 20 Feb 2017 19:27:39 +0100 Subject: [PATCH 165/345] Refresh memcached.ini provided configuration - remove deprecated options - add missing memcached.sess_server_failure_limit option - comment all options default value (only needed when not default value) see php.ini-production which follow this convention --- memcached.ini | 56 +++++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/memcached.ini b/memcached.ini index 59001aaf..fa9a6fd4 100644 --- a/memcached.ini +++ b/memcached.ini @@ -2,45 +2,39 @@ ; Use session locking ; valid values: On, Off ; the default is On -memcached.sess_locking = On - -; !! DEPRECATED AND REMOVED in 3.x !! -; memcached.sess_lock_wait = 150000 - -; !! DEPRECATED AND REMOVED in 3.x !! -; memcached.sess_lock_max_wait = 0; +;memcached.sess_locking = On ; The minimum time, in milliseconds, to wait between session lock attempts. ; This value is double on each lock retry until memcached.sess_lock_wait_max ; is reached, after which any further retries will take sess_lock_wait_max seconds. ; Default is 1000. -memcached.sess_lock_wait_min = 1000; +;memcached.sess_lock_wait_min = 1000; ; The maximum time, in milliseconds, to wait between session lock attempts. ; Default is 2000. -memcached.sess_lock_wait_max = 2000; +;memcached.sess_lock_wait_max = 2000; ; The number of times to retry locking the session lock, not including the first attempt. ; Default is 5. -memcached.sess_lock_retries = 5; +;memcached.sess_lock_retries = 5; ; The time, in seconds, before a lock should release itself. ; Setting to 0 results in the default behaviour, which is to ; use the memcached.sess_lock_max_wait setting. If that is ; also 0, max_execution_time will be used. -memcached.sess_lock_expire = 0; +;memcached.sess_lock_expire = 0; ; memcached session key prefix ; valid values are strings less than 219 bytes long ; the default value is "memc.sess.key." -memcached.sess_prefix = "memc.sess.key." +;memcached.sess_prefix = "memc.sess.key." ; Whether or not to re-use the memcached connections corresponding to the value(s) ; of session.save_path after the execution of the script ends. ; Don't use this if certain settings (e.g. SASL settings, sess_binary_protocol) would ; be overridden between requests. ; Default is Off. -memcached.sess_persistent = Off +;memcached.sess_persistent = Off ; memcached session consistent hash mode ; if set to On, consistent hashing (libketama) is used @@ -48,11 +42,15 @@ memcached.sess_persistent = Off ; When consistent hashing is used, one can add or remove cache ; node(s) without messing up too much with existing keys ; default is On -memcached.sess_consistent_hash = On +;memcached.sess_consistent_hash = On ; Allow failed memcached server to automatically be removed. ; Default is Off. (In previous versions, this setting was called memcached.sess_remove_failed) -memcached.sess_remove_failed_servers = Off +;memcached.sess_remove_failed_servers = Off + +; Set this value to enable the server be removed after +; configured number of continuous times connection failure. +;memcached.sess_server_failure_limit = 0 ; Write data to a number of additional memcached servers ; This is "poor man's HA" as libmemcached calls it. @@ -61,34 +59,34 @@ memcached.sess_remove_failed_servers = Off ; from a replica. However, if the failed memcache server ; becomes available again it will read the session from there ; which could have old data or no data at all -memcached.sess_number_of_replicas = 0 +;memcached.sess_number_of_replicas = 0 ; Use the memcached binary protocol for memcached sessions (Instead of the text protocol) ; libmemcached replicas work only if binary mode is enabled. ; However, certain proxies (such as twemproxy) will work only if the binary protocol is disabled. ; Default is On. In older versions of php-memcached, this setting was Off and was called memcached.sess_binary. -memcached.sess_binary_protocol = On +;memcached.sess_binary_protocol = On ; memcached session replica read randomize -memcached.sess_randomize_replica_read = Off +;memcached.sess_randomize_replica_read = Off ; memcached connect timeout value ; In non-blocking mode this changes the value of the timeout ; during socket connection in milliseconds. Specifying -1 means an infinite timeout. -memcached.sess_connect_timeout = 1000 +;memcached.sess_connect_timeout = 1000 ; Session SASL username ; Both username and password need to be set for SASL to be enabled ; In addition to this memcached.use_sasl needs to be on -memcached.sess_sasl_username = NULL +;memcached.sess_sasl_username = NULL ; Session SASL password -memcached.sess_sasl_password = NULL +;memcached.sess_sasl_password = NULL ; Set the compression type ; valid values are: fastlz, zlib ; the default is fastlz -memcached.compression_type = "fastlz" +;memcached.compression_type = "fastlz" ; Compression factor ; Store compressed value only if the compression @@ -98,13 +96,13 @@ memcached.compression_type = "fastlz" ; plain_len > comp_len * factor ; ; the default value is 1.3 (23% space saving) -memcached.compression_factor = "1.3" +;memcached.compression_factor = "1.3" ; The compression threshold ; ; Do not compress serialized values below this threshold. ; the default is 2000 bytes -memcached.compression_threshold = 2000 +;memcached.compression_threshold = 2000 ; Set the default serializer for new memcached objects. ; valid values are: php, igbinary, json, json_array, msgpack @@ -119,14 +117,14 @@ memcached.compression_threshold = 2000 ; msgpack - a cross-language binary serializer ; ; The default is igbinary if available, then msgpack if available, then php otherwise. -memcached.serializer = "igbinary" +;memcached.serializer = "igbinary" ; The amount of retries for failed store commands. ; This mechanism allows transparent fail-over to secondary servers when ; set/increment/decrement/setMulti operations fail on the desired server in a multi-server ; environment. ; the default is 2 -memcached.store_retry_count = 2 +;memcached.store_retry_count = 2 ; Sets the default for consistent hashing for new connections. ; (To configure consistent hashing for session connections, @@ -137,7 +135,7 @@ memcached.store_retry_count = 2 ; When consistent hashing is used, one can add or remove cache ; node(s) without messing up too much with existing keys ; default is Off -memcached.default_consistent_hash = Off +;memcached.default_consistent_hash = Off ; Sets the default memcached protocol for new connections. ; (To configure the memcached protocol for connections used by sessions, @@ -146,7 +144,7 @@ memcached.default_consistent_hash = Off ; If set to On, the memcached binary protocol is used by default. ; If set to Off, the memcached text protocol is used. ; Default is Off -memcached.default_binary_protocol = Off +;memcached.default_binary_protocol = Off ; Sets the default memcached connection timeout for new connections. ; (To configure the memcached connection timeout for sessions, @@ -155,4 +153,4 @@ memcached.default_binary_protocol = Off ; during socket connection in milliseconds. Specifying -1 means an infinite timeout. ; Specifying 0 means using the memcached library's default connection timeout. ; Default is 0. -memcached.default_connect_timeout = 0 +;memcached.default_connect_timeout = 0 From 0a90491dd13af8dfc9a2e1ee600590fe9245ac50 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Mon, 20 Feb 2017 19:32:37 +0100 Subject: [PATCH 166/345] set sess_binary_protocol off by default with older libmemcached --- memcached.ini | 4 +++- php_memcached.c | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/memcached.ini b/memcached.ini index fa9a6fd4..6d05da3c 100644 --- a/memcached.ini +++ b/memcached.ini @@ -64,7 +64,9 @@ ; Use the memcached binary protocol for memcached sessions (Instead of the text protocol) ; libmemcached replicas work only if binary mode is enabled. ; However, certain proxies (such as twemproxy) will work only if the binary protocol is disabled. -; Default is On. In older versions of php-memcached, this setting was Off and was called memcached.sess_binary. +; In older versions of php-memcached, this setting was Off and was called memcached.sess_binary. +; Default is On with libmemcached 1.0.18 or newer. +; Default is Off with older version. ;memcached.sess_binary_protocol = On ; memcached session replica read randomize diff --git a/php_memcached.c b/php_memcached.c index 19673323..b920970b 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -332,7 +332,11 @@ PHP_INI_BEGIN() MEMC_SESSION_INI_ENTRY("lock_wait_max", "2000", OnUpdateLongGEZero, lock_wait_max) MEMC_SESSION_INI_ENTRY("lock_retries", "5", OnUpdateLong, lock_retries) MEMC_SESSION_INI_ENTRY("lock_expire", "0", OnUpdateLongGEZero, lock_expiration) +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000018 + MEMC_SESSION_INI_ENTRY("binary_protocol", "0", OnUpdateBool, binary_protocol_enabled) +#else MEMC_SESSION_INI_ENTRY("binary_protocol", "1", OnUpdateBool, binary_protocol_enabled) +#endif MEMC_SESSION_INI_ENTRY("consistent_hash", "1", OnUpdateBool, consistent_hash_enabled) MEMC_SESSION_INI_ENTRY("number_of_replicas", "0", OnUpdateLongGEZero, number_of_replicas) MEMC_SESSION_INI_ENTRY("randomize_replica_read", "0", OnUpdateLongGEZero, randomize_replica_read_enabled) From 3b3e63dac7df9e6085442d7cd4f1e898e1af9114 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Tue, 21 Feb 2017 23:47:15 +0100 Subject: [PATCH 167/345] typo in skip message (#331) --- tests/session_lazy_warning.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/session_lazy_warning.phpt b/tests/session_lazy_warning.phpt index 79d7f2f3..6847f5b5 100644 --- a/tests/session_lazy_warning.phpt +++ b/tests/session_lazy_warning.phpt @@ -4,7 +4,7 @@ Session lazy binary warning old libmemcached = 0x01000018) die ('skip too old libmemcached'); +if (Memcached::LIBMEMCACHED_VERSION_HEX >= 0x01000018) die ('skip too recent libmemcached'); ?> --INI-- session.save_handler = memcached From 037ed570bae27a7a3d47fda9f38f6d0355554e9b Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 22 Feb 2017 01:22:11 +0100 Subject: [PATCH 168/345] Fix build warnings (#329) --- php_memcached.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 19673323..55d1bdb8 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -194,7 +194,8 @@ static inline php_memc_object_t *php_memc_fetch_object(zend_object *obj) { php_error_docref(NULL, E_WARNING, "Memcached constructor was not called"); \ return; \ } \ - memc_user_data = (php_memc_user_data_t *) memcached_get_user_data(intern->memc); + memc_user_data = (php_memc_user_data_t *) memcached_get_user_data(intern->memc); \ + (void)memc_user_data; /* avoid unused variable warning */ static zend_bool s_memc_valid_key_binary(const char *key) @@ -898,7 +899,7 @@ zend_bool s_serialize_value (php_memc_serializer_type serializer, zval *value, s php_error_docref(NULL, E_WARNING, "could not serialize value with igbinary"); return 0; } - smart_str_appendl (buf, buffer, buffer_len); + smart_str_appendl (buf, (char *)buffer, buffer_len); efree(buffer); MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_IGBINARY); } @@ -1058,7 +1059,7 @@ zend_bool s_memc_write_zval (php_memc_object_t *intern, php_memc_write_op op, ze { uint32_t flags = 0; zend_string *payload = NULL; - memcached_return status; + memcached_return status = 0; php_memc_user_data_t *memc_user_data = memcached_get_user_data(intern->memc); zend_long retries = memc_user_data->store_retry_count; @@ -3911,10 +3912,12 @@ ZEND_BEGIN_ARG_INFO(arginfo_getOption, 0) ZEND_ARG_INFO(0, option) ZEND_END_ARG_INFO() +#ifdef HAVE_MEMCACHED_SASL ZEND_BEGIN_ARG_INFO(arginfo_setSaslAuthData, 0) ZEND_ARG_INFO(0, username) ZEND_ARG_INFO(0, password) ZEND_END_ARG_INFO() +#endif ZEND_BEGIN_ARG_INFO(arginfo_setOption, 0) ZEND_ARG_INFO(0, option) From 6b660bd554368bae69c2fbf490c6e78712e50708 Mon Sep 17 00:00:00 2001 From: Akihito Nakano Date: Sun, 23 Apr 2017 15:12:36 +0900 Subject: [PATCH 169/345] Fix optional parameter getStats($type) (#337) * Fix 'type' is optional * Change argument name args -> type --- php_memcached.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 55d1bdb8..3f3ac286 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3876,6 +3876,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_addServer, 0, 0, 2) ZEND_ARG_INFO(0, weight) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_getStats, 0, 0, 0) + ZEND_ARG_INFO(0, type) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO(arginfo_addServers, 0) ZEND_ARG_ARRAY_INFO(0, servers, 0) ZEND_END_ARG_INFO() @@ -3934,10 +3938,6 @@ ZEND_BEGIN_ARG_INFO(arginfo_setBucket, 3) ZEND_ARG_INFO(0, replicas) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(arginfo_getStats, 0) - ZEND_ARG_INFO(0, args) -ZEND_END_ARG_INFO() - ZEND_BEGIN_ARG_INFO(arginfo_getVersion, 0) ZEND_END_ARG_INFO() From c23ea262f3b481951b0131db358770b352953e14 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Sun, 30 Apr 2017 08:15:36 -0700 Subject: [PATCH 170/345] Document GET_EXTENDED flag. Add/rename other missing/misnamed constants. (#335) --- memcached-api.php | 108 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 89 insertions(+), 19 deletions(-) diff --git a/memcached-api.php b/memcached-api.php index df725091..f5174e22 100644 --- a/memcached-api.php +++ b/memcached-api.php @@ -10,13 +10,13 @@ class Memcached { */ const OPT_HASH; - - const OPT_HASH_DEFAULT; + + const HASH_DEFAULT; const HASH_MD5; const HASH_CRC; - + const HASH_FNV1_64; const HASH_FNV1A_64; @@ -34,12 +34,16 @@ class Memcached { const DISTRIBUTION_MODULA; const DISTRIBUTION_CONSISTENT; - + const DISTRIBUTION_VIRTUAL_BUCKET; - const LIBKETAMA_COMPATIBLE; + const OPT_LIBKETAMA_COMPATIBLE; - const OPT_BUFFER_REQUESTS; + const OPT_LIBKETAMA_HASH; + + const OPT_TCP_KEEPALIVE; + + const OPT_BUFFER_WRITES; const OPT_BINARY_PROTOCOL; @@ -57,9 +61,9 @@ class Memcached { const OPT_DEAD_TIMEOUT; - const OPT_SND_TIMEOUT; + const OPT_SEND_TIMEOUT; - const OPT_RCV_TIMEOUT; + const OPT_RECV_TIMEOUT; const OPT_POLL_TIMEOUT; @@ -71,22 +75,34 @@ class Memcached { const OPT_AUTO_EJECT_HOSTS; - const OPT_NUMBER_OF_REPLICAS; - const OPT_NOREPLY; const OPT_VERIFY_KEY; - + + const OPT_USE_UDP; + + const OPT_NUMBER_OF_REPLICAS; + const OPT_RANDOMIZE_REPLICA_READS; + const OPT_REMOVE_FAILED_SERVERS; /** - * Class parameters + * Supported serializers */ const HAVE_JSON; const HAVE_IGBINARY; + const HAVE_MSGPACK; + + /** + * Feature support + */ + const HAVE_SESSION; + + const HAVE_SASL; + /** * Class options. */ @@ -107,18 +123,24 @@ class Memcached { const SERIALIZER_JSON_ARRAY; + const SERIALIZER_MSGPACK; + /** * Compression types */ - const COMPRESSION_TYPE_FASTLZ; + const COMPRESSION_FASTLZ; - const COMPRESSION_TYPE_ZLIB; + const COMPRESSION_ZLIB; /** - * Flags + * Flags for get and getMulti operations. */ + // Whether to preserve key order in the result const GET_PRESERVE_ORDER; + // Whether to fetch CAS token as well (use "gets"). + const GET_EXTENDED; + /** * Return values */ @@ -186,9 +208,57 @@ class Memcached { const RES_CONNECTION_SOCKET_CREATE_FAILURE; + const RES_E2BIG; + + const RES_KEY_TOO_BIG; + + const RES_SERVER_TEMPORARILY_DISABLED; + + const RES_SERVER_MEMORY_ALLOCATION_FAILURE; + + const RES_AUTH_PROBLEM; + + const RES_AUTH_FAILURE; + + const RES_AUTH_CONTINUE; + + /** Server callbacks, if compiled with --memcached-protocol */ + const ON_CONNECT; + const ON_ADD; + const ON_APPEND; + const ON_DECREMENT; + const ON_DELETE; + const ON_FLUSH; + const ON_GET; + const ON_INCREMENT; + const ON_NOOP; + const ON_PREPEND; + const ON_QUIT; + const ON_REPLACE; + const ON_SET; + const ON_STAT; + const ON_VERSION; + /** Constants used when compiled with --memcached-protocol */ + const RESPONSE_SUCCESS; + const RESPONSE_KEY_ENOENT; + const RESPONSE_KEY_EEXISTS; + const RESPONSE_E2BIG; + const RESPONSE_EINVAL; + const RESPONSE_NOT_STORED; + const RESPONSE_DELTA_BADVAL; + const RESPONSE_NOT_MY_VBUCKET; + const RESPONSE_AUTH_ERROR; + const RESPONSE_AUTH_CONTINUE; + const RESPONSE_UNKNOWN_COMMAND; + const RESPONSE_ENOMEM; + const RESPONSE_NOT_SUPPORTED; + const RESPONSE_EINTERNAL; + const RESPONSE_EBUSY; + const RESPONSE_ETMPFAIL; + public function __construct( $persistent_id = '', $on_new_object_cb = null ) {} - + public function get( $key, callable $cache_cb = null, $flags = 0) {} public function getByKey( $server_key, $key, callable $cache_cb = null, $flags = 0 ) {} @@ -202,7 +272,7 @@ public function getDelayed( array $keys, $with_cas = null, $value_cb = null ) {} public function getDelayedByKey( $server_key, array $keys, $with_cas = null, $value_cb = null ) {} public function fetch( ) {} - + public function fetchAll( ) {} public function set( $key, $value, $expiration = 0, $udf_flags = 0 ) {} @@ -250,7 +320,7 @@ public function increment( $key, $offset = 1, $initial_value = 0, $expiry = 0) { public function decrement( $key, $offset = 1, $initial_value = 0, $expiry = 0) {} public function getOption( $option ) {} - + public function setOption( $option, $value ) {} public function setOptions( array $options ) {} @@ -280,7 +350,7 @@ public function flushBuffers( ) {} public function getStats( $type = null ) {} public function getAllKeys( ) {} - + public function getVersion( ) {} public function getResultCode( ) {} From 14581c4604b4e4a525e1a30a52a8ac39ac1ac7e4 Mon Sep 17 00:00:00 2001 From: Eric Norris Date: Tue, 2 May 2017 16:24:34 -0400 Subject: [PATCH 171/345] s/encryption/compression/g (#342) --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 3f3ac286..7cda4ac3 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3383,7 +3383,7 @@ zend_string *s_decompress_value (const char *payload, size_t payload_len, uint32 is_zlib = MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_ZLIB); if (!is_fastlz && !is_zlib) { - php_error_docref(NULL, E_WARNING, "could not decompress value: unrecognised encryption type"); + php_error_docref(NULL, E_WARNING, "could not decompress value: unrecognised compression type"); return NULL; } From 5f28025c15c87d0895f39def77068c8fd66d442a Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Tue, 23 May 2017 11:43:19 +0800 Subject: [PATCH 172/345] This will lead unexpected behavior if zval is an interned string --- php_memcached.c | 1 - 1 file changed, 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 7cda4ac3..9eacbbfb 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1019,7 +1019,6 @@ zend_string *s_zval_to_payload(php_memc_object_t *intern, zval *value, uint32_t } break; } - zend_string_forget_hash_val(payload); /* turn off compression for values below the threshold */ if (ZSTR_LEN(payload) == 0 || ZSTR_LEN(payload) < MEMC_G(compression_threshold)) { From 23cf6c60f398cecb896e4fead37c18c9b56717fa Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Fri, 9 Jun 2017 11:08:33 -0700 Subject: [PATCH 173/345] Fix ReflectionMethod signatures for appendByKey,prepend, etc. (#352) --- php_memcached.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 9eacbbfb..7e020eaa 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3775,27 +3775,23 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_append, 0, 0, 2) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, expiration) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_appendByKey, 0, 0, 3) ZEND_ARG_INFO(0, server_key) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, expiration) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_prepend, 0, 0, 2) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, expiration) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_prependByKey, 0, 0, 3) ZEND_ARG_INFO(0, server_key) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, expiration) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_cas, 0, 0, 3) From 43bbf0080206b157b0d3f47ab1f07ede4bc80c86 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 7 Jul 2017 18:45:42 -0700 Subject: [PATCH 174/345] In PHP 7.2, php_errormsg is deprecated --- tests/append.phpt | 2 +- tests/bad_construct.phpt | 2 +- tests/experimental/fetch_badunserialize.phpt | 2 +- tests/experimental/fetchall_badunserialize.phpt | 2 +- tests/experimental/getdelayed_badunserialize.phpt | 2 +- tests/experimental/getdelayed_cbthrows.phpt | 2 +- tests/experimental/getmulti_badunserialize.phpt | 2 +- tests/experimental/replace_bykey.phpt | 2 +- .../serializer/serializer_php_bad_serialize.phpt | 2 +- .../serializer/serializer_php_bad_unserialize.phpt | 2 +- tests/experimental/setmulti_badserialize.phpt | 2 +- tests/incrdecr.phpt | 8 ++++---- tests/incrdecr_bykey.phpt | 8 ++++---- 13 files changed, 19 insertions(+), 19 deletions(-) diff --git a/tests/append.phpt b/tests/append.phpt index c463fde8..b958b391 100644 --- a/tests/append.phpt +++ b/tests/append.phpt @@ -11,7 +11,7 @@ error_reporting(0); $m->delete('foo'); $m->setOption(Memcached::OPT_COMPRESSION, true); var_dump($m->append('foo', 'a')); -echo $php_errormsg, "\n"; +echo error_get_last()["message"], "\n"; $m->setOption(Memcached::OPT_COMPRESSION, false); $m->delete('foo'); diff --git a/tests/bad_construct.phpt b/tests/bad_construct.phpt index aa9b18c4..0b740e00 100644 --- a/tests/bad_construct.phpt +++ b/tests/bad_construct.phpt @@ -6,7 +6,7 @@ Memcached construct with bad arguments getDelayed(array('foo'), false)); try { var_dump($m->fetch()); } catch (Exception $e) { - echo $php_errormsg, "\n"; + echo error_get_last()["message"], "\n"; echo $e->getMessage(), "\n"; } diff --git a/tests/experimental/fetchall_badunserialize.phpt b/tests/experimental/fetchall_badunserialize.phpt index e3ad3310..5684763f 100644 --- a/tests/experimental/fetchall_badunserialize.phpt +++ b/tests/experimental/fetchall_badunserialize.phpt @@ -42,7 +42,7 @@ var_dump($m->getDelayed(array('foo'), false)); try { var_dump($m->fetchAll()); } catch (Exception $e) { - echo $php_errormsg, "\n"; + echo error_get_last()["message"], "\n"; echo $e->getMessage(), "\n"; } diff --git a/tests/experimental/getdelayed_badunserialize.phpt b/tests/experimental/getdelayed_badunserialize.phpt index 571e76e0..397135ae 100644 --- a/tests/experimental/getdelayed_badunserialize.phpt +++ b/tests/experimental/getdelayed_badunserialize.phpt @@ -45,7 +45,7 @@ error_reporting(0); try { var_dump($m->getDelayed(array('foo'), false, 'mycb')); } catch (Exception $e) { - echo $php_errormsg, "\n"; + echo error_get_last()["message"], "\n"; echo $e->getMessage(), "\n"; } diff --git a/tests/experimental/getdelayed_cbthrows.phpt b/tests/experimental/getdelayed_cbthrows.phpt index 2b71b4b4..b0427ac9 100644 --- a/tests/experimental/getdelayed_cbthrows.phpt +++ b/tests/experimental/getdelayed_cbthrows.phpt @@ -24,7 +24,7 @@ error_reporting(0); try { $m->getDelayedByKey('kef', array_keys($data), false, 'myfunc'); } catch (Exception $e) { - echo $php_errormsg, "\n"; + echo error_get_last()["message"], "\n"; echo $e->getMessage(), "\n"; } diff --git a/tests/experimental/getmulti_badunserialize.phpt b/tests/experimental/getmulti_badunserialize.phpt index b33d5ccd..963e9730 100644 --- a/tests/experimental/getmulti_badunserialize.phpt +++ b/tests/experimental/getmulti_badunserialize.phpt @@ -32,7 +32,7 @@ error_reporting(0); try { var_dump($m->getMulti(array('bar', 'foo'))); } catch (Exception $e) { - echo $php_errormsg, "\n"; + echo error_get_last()["message"], "\n"; echo $e->getMessage(), "\n"; } diff --git a/tests/experimental/replace_bykey.phpt b/tests/experimental/replace_bykey.phpt index b2f72836..cddf10f0 100644 --- a/tests/experimental/replace_bykey.phpt +++ b/tests/experimental/replace_bykey.phpt @@ -10,7 +10,7 @@ error_reporting(0); $m->delete('foo'); var_dump($m->replaceByKey('kef', 'foo', 'bar', 60)); -echo $php_errormsg, "\n"; +echo error_get_last()["message"], "\n"; echo $m->getResultMessage(), "\n"; var_dump($m->getByKey('kef', 'foo')); diff --git a/tests/experimental/serializer/serializer_php_bad_serialize.phpt b/tests/experimental/serializer/serializer_php_bad_serialize.phpt index 81e88b0c..76d3daca 100644 --- a/tests/experimental/serializer/serializer_php_bad_serialize.phpt +++ b/tests/experimental/serializer/serializer_php_bad_serialize.phpt @@ -44,7 +44,7 @@ error_reporting(0); try { var_dump($m->set('foo', new Foo(), 10)); } catch (Exception $e) { - echo $php_errormsg, "\n"; + echo error_get_last()["message"], "\n"; echo $e->getMessage(), "\n"; } try { diff --git a/tests/experimental/serializer/serializer_php_bad_unserialize.phpt b/tests/experimental/serializer/serializer_php_bad_unserialize.phpt index 39d2cc37..341ddedc 100644 --- a/tests/experimental/serializer/serializer_php_bad_unserialize.phpt +++ b/tests/experimental/serializer/serializer_php_bad_unserialize.phpt @@ -40,7 +40,7 @@ var_dump($m->set('foo', new Foo(), 10)); try { var_dump($m->get('foo')); } catch (Exception $e) { - echo $php_errormsg, "\n"; + echo error_get_last()["message"], "\n"; echo $e->getMessage(), "\n"; } diff --git a/tests/experimental/setmulti_badserialize.phpt b/tests/experimental/setmulti_badserialize.phpt index 3bba314a..eafc7772 100644 --- a/tests/experimental/setmulti_badserialize.phpt +++ b/tests/experimental/setmulti_badserialize.phpt @@ -36,7 +36,7 @@ try { } } - echo $php_errormsg, "\n"; + echo error_get_last()["message"], "\n"; echo $e->getMessage(), "\n"; } var_dump($m->getByKey('kef', 'foo')); diff --git a/tests/incrdecr.phpt b/tests/incrdecr.phpt index b4e9469b..87b410c9 100644 --- a/tests/incrdecr.phpt +++ b/tests/incrdecr.phpt @@ -31,14 +31,14 @@ var_dump($m->get('foo')); error_reporting(0); echo "Negative offset\n"; -$php_errormsg = ''; +error_clear_last(); $m->increment('foo', -1); -echo $php_errormsg, "\n"; +echo error_get_last()["message"], "\n"; var_dump($m->get('foo')); -$php_errormsg = ''; +error_clear_last(); $m->decrement('foo', -1); -echo $php_errormsg, "\n"; +echo error_get_last()["message"], "\n"; var_dump($m->get('foo')); echo "Enormous offset\n"; diff --git a/tests/incrdecr_bykey.phpt b/tests/incrdecr_bykey.phpt index 8b931fa7..ee089938 100644 --- a/tests/incrdecr_bykey.phpt +++ b/tests/incrdecr_bykey.phpt @@ -28,14 +28,14 @@ var_dump($m->get('foo')); error_reporting(0); echo "Negative offset\n"; -$php_errormsg = ''; +error_clear_last(); $m->incrementByKey('foo', 'foo', -1); -echo $php_errormsg, "\n"; +echo error_get_last()["message"], "\n"; var_dump($m->get('foo')); -$php_errormsg = ''; +error_clear_last(); $m->decrementByKey('foo', 'foo', -1); -echo $php_errormsg, "\n"; +echo error_get_last()["message"], "\n"; var_dump($m->get('foo')); echo "Enormous offset\n"; From e91eae7be3d6076f5a66f4ef3b588d61df8ec1a2 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 10 Jul 2017 14:46:20 -0700 Subject: [PATCH 175/345] Split tests for invalid keys ascii and binary Test get command for invalid keys as well as set command --- package.xml | 3 +- tests/keys.phpt | 118 ------------------------- tests/keys_ascii.phpt | 190 +++++++++++++++++++++++++++++++++++++++++ tests/keys_binary.phpt | 190 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 382 insertions(+), 119 deletions(-) delete mode 100644 tests/keys.phpt create mode 100644 tests/keys_ascii.phpt create mode 100644 tests/keys_binary.phpt diff --git a/package.xml b/package.xml index 2306344d..2cc8995b 100644 --- a/package.xml +++ b/package.xml @@ -147,7 +147,8 @@ Fixes - + + diff --git a/tests/keys.phpt b/tests/keys.phpt deleted file mode 100644 index f320e03f..00000000 --- a/tests/keys.phpt +++ /dev/null @@ -1,118 +0,0 @@ ---TEST-- -Test different kind of keys ---SKIPIF-- - ---FILE-- - true, - )); - -$ascii = memc_get_instance (); -$ascii->setOption(Memcached::OPT_VERIFY_KEY, 1); - -var_dump ($binary->set ('binary key with spaces', 'this is a test')); -var_dump ($binary->getResultCode () == Memcached::RES_SUCCESS); - -var_dump ($binary->set ('binarykeywithnewline' . PHP_EOL, 'this is a test')); -var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); - -var_dump ($ascii->set ('ascii key with spaces', 'this is a test')); -var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); - -var_dump ($binary->set ('asciikeywithnewline' . PHP_EOL, 'this is a test')); -var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); - -var_dump ($ascii->set (''/*empty key*/, 'this is a test')); -var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); - -for ($i=0;$i<32;$i++) { - var_dump ($ascii->set ('asciikeywithnonprintablechar-' . chr($i) . '-here', 'this is a test')); - var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); -} - -var_dump ($ascii->set (str_repeat ('1234567890', 512), 'this is a test')); -var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); - -echo "OK" . PHP_EOL; - ---EXPECT-- -bool(true) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -OK diff --git a/tests/keys_ascii.phpt b/tests/keys_ascii.phpt new file mode 100644 index 00000000..f7e98894 --- /dev/null +++ b/tests/keys_ascii.phpt @@ -0,0 +1,190 @@ +--TEST-- +Test valid and invalid keys - ascii +--SKIPIF-- + +--FILE-- + false, + Memcached::OPT_VERIFY_KEY => false + )); +// libmemcached can verify keys, but these are tests are for our own +// function s_memc_valid_key_ascii, so explicitly disable the checks +// that libmemcached can perform. + +echo 'ASCII: SPACES' . PHP_EOL; +var_dump ($ascii->set ('ascii key with spaces', 'this is a test')); +var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); + +echo 'ASCII: NEWLINE' . PHP_EOL; +var_dump ($ascii->set ('asciikeywithnewline' . PHP_EOL, 'this is a test')); +var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); + +echo 'ASCII: EMPTY' . PHP_EOL; +var_dump ($ascii->set (''/*empty key*/, 'this is a test')); +var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); + +echo 'ASCII: TOO LONG' . PHP_EOL; +var_dump ($ascii->set (str_repeat ('1234567890', 512), 'this is a test')); +var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); + +echo 'ASCII: GET' . PHP_EOL; +for ($i=0;$i<32;$i++) { + var_dump ($ascii->get ('asciikeywithnonprintablechar-' . chr($i) . '-here')); + var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); +} + +echo 'ASCII: SET' . PHP_EOL; +for ($i=0;$i<32;$i++) { + var_dump ($ascii->set ('asciikeywithnonprintablechar-' . chr($i) . '-here', 'this is a test')); + var_dump ($ascii->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); +} + +echo 'OK' . PHP_EOL; + +--EXPECT-- +ASCII: SPACES +bool(false) +bool(true) +ASCII: NEWLINE +bool(false) +bool(true) +ASCII: EMPTY +bool(false) +bool(true) +ASCII: TOO LONG +bool(false) +bool(true) +ASCII: GET +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +ASCII: SET +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +OK diff --git a/tests/keys_binary.phpt b/tests/keys_binary.phpt new file mode 100644 index 00000000..f0ae67bd --- /dev/null +++ b/tests/keys_binary.phpt @@ -0,0 +1,190 @@ +--TEST-- +Test valid and invalid keys - binary +--SKIPIF-- + +--FILE-- + true, + )); + +echo 'BINARY: SPACES' . PHP_EOL; +var_dump ($binary->set ('binary key with spaces', 'this is a test')); +var_dump ($binary->getResultCode () == Memcached::RES_SUCCESS); + +echo 'BINARY: NEWLINE' . PHP_EOL; +var_dump ($binary->set ('binarykeywithnewline' . PHP_EOL, 'this is a test')); +var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); + +echo 'BINARY: EMPTY' . PHP_EOL; +var_dump ($binary->set (''/*empty key*/, 'this is a test')); +var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); + +echo 'BINARY: TOO LONG' . PHP_EOL; +var_dump ($binary->set (str_repeat ('1234567890', 512), 'this is a test')); +var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); + +echo 'BINARY: GET' . PHP_EOL; +// Only newline fails in binary mode (char 10) +for ($i=0;$i<32;$i++) { + $binary->delete ('binarykeywithnonprintablechar-' . chr($i) . '-here'); + var_dump ($binary->get ('binarykeywithnonprintablechar-' . chr($i) . '-here')); + var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); +} + +echo 'BINARY: SET' . PHP_EOL; +// Only newline fails in binary mode (char 10) +for ($i=0;$i<32;$i++) { + var_dump ($binary->set ('binarykeywithnonprintablechar-' . chr($i) . '-here', 'this is a test')); + var_dump ($binary->getResultCode () == Memcached::RES_BAD_KEY_PROVIDED); + $binary->delete ('binarykeywithnonprintablechar-' . chr($i) . '-here'); +} + +echo 'OK' . PHP_EOL; + +--EXPECT-- +BINARY: SPACES +bool(true) +bool(true) +BINARY: NEWLINE +bool(false) +bool(true) +BINARY: EMPTY +bool(false) +bool(true) +BINARY: TOO LONG +bool(false) +bool(true) +BINARY: GET +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +BINARY: SET +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(false) +bool(true) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +OK From be93a459eedc54fbbf2dfa63babea38b730fc313 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 10 Jul 2017 11:04:59 -0700 Subject: [PATCH 176/345] Fix the key validity tests to handle strings with embedded nulls --- php_memcached.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 4449200b..65d11eb2 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -198,24 +198,30 @@ static inline php_memc_object_t *php_memc_fetch_object(zend_object *obj) { (void)memc_user_data; /* avoid unused variable warning */ static -zend_bool s_memc_valid_key_binary(const char *key) +zend_bool s_memc_valid_key_binary(zend_string *key) { - return strchr(key, '\n') == NULL; + return memchr(ZSTR_VAL(key), '\n', ZSTR_LEN(key)) == NULL; } static -zend_bool s_memc_valid_key_ascii(const char *key) +zend_bool s_memc_valid_key_ascii(zend_string *key) { - while (*key && !iscntrl(*key) && !isspace(*key)) ++key; - return *key == '\0'; + const char *str = ZSTR_VAL(key); + size_t i, len = ZSTR_LEN(key); + + for (i = 0; i < len; i++) { + if (iscntrl(str[i]) || isspace(str[i])) + return 0; + } + return 1; } #define MEMC_CHECK_KEY(intern, key) \ if (UNEXPECTED(ZSTR_LEN(key) == 0 || \ ZSTR_LEN(key) > MEMC_OBJECT_KEY_MAX_LENGTH || \ (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) \ - ? !s_memc_valid_key_binary(ZSTR_VAL(key)) \ - : !s_memc_valid_key_ascii(ZSTR_VAL(key)) \ + ? !s_memc_valid_key_binary(key) \ + : !s_memc_valid_key_ascii(key) \ ))) { \ intern->rescode = MEMCACHED_BAD_KEY_PROVIDED; \ RETURN_FALSE; \ @@ -309,7 +315,7 @@ PHP_INI_MH(OnUpdateSessionPrefixString) php_error_docref(NULL, E_WARNING, "memcached.sess_prefix too long (max: %d)", MEMCACHED_MAX_KEY - 1); return FAILURE; } - if (!s_memc_valid_key_ascii(ZSTR_VAL(new_value))) { + if (!s_memc_valid_key_ascii(new_value)) { php_error_docref(NULL, E_WARNING, "memcached.sess_prefix cannot contain whitespace or control characters"); return FAILURE; } From 39bfab06c0c27dc620486f56a926308df5d4c819 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 11 Jul 2017 15:57:51 -0700 Subject: [PATCH 177/345] In PHP 7.2 the session_start() error messages have changed a bit (#359) See PHP Bug 71038 for details https://bugs.php.net/bug.php?id=71038 Added PHP 7.2.0alpha2 to Travis CI matrix --- .travis.yml | 3 ++- package.xml | 1 + tests/session_badconf_servers-php72.phpt | 30 ++++++++++++++++++++++++ tests/session_badconf_servers.phpt | 7 +++--- 4 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 tests/session_badconf_servers-php72.phpt diff --git a/.travis.yml b/.travis.yml index 2581b516..d12cd3c9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,8 +3,9 @@ dist: trusty language: php php: - - 7.0 + - 7.2.0alpha2 - 7.1 + - 7.0 matrix: fast_finish: true diff --git a/package.xml b/package.xml index 2cc8995b..5e1961f7 100644 --- a/package.xml +++ b/package.xml @@ -113,6 +113,7 @@ Fixes + diff --git a/tests/session_badconf_servers-php72.phpt b/tests/session_badconf_servers-php72.phpt new file mode 100644 index 00000000..92012369 --- /dev/null +++ b/tests/session_badconf_servers-php72.phpt @@ -0,0 +1,30 @@ +--TEST-- +Session bad configurations, invalid save path (server list) +--SKIPIF-- + +--INI-- +session.save_handler = memcached +--FILE-- + 70100) print "skip"; ?> --INI-- session.save_handler = memcached @@ -24,5 +25,5 @@ ini_set('session.save_path', ''); session_start(); session_write_close(); ---EXPECTF-- +--EXPECT-- session_start(): failed to parse session.save_path From 56145402e9d4a624037cdbfb5d9bab3bc7874e21 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 27 Jul 2017 00:03:48 -0700 Subject: [PATCH 178/345] Travis CI now provides the PHP 7.2 alias --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d12cd3c9..d2457f55 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ dist: trusty language: php php: - - 7.2.0alpha2 + - 7.2 - 7.1 - 7.0 From f82e6845af474ff98c5b6dae283f8beb3f4e6d4d Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 20 Nov 2017 23:15:34 -0600 Subject: [PATCH 179/345] Use new fast_zpp parameter parsing API (#311) The one that took a while to figure out was zpp("f!") to Z_PARAM_FUNC_EX(fci, fcc, 1, 0) --- php_memcached.c | 368 +++++++++++++++++++++++++++++++----------------- 1 file changed, 242 insertions(+), 126 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 65d11eb2..891b2a3e 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1184,9 +1184,13 @@ static PHP_METHOD(Memcached, __construct) zend_bool is_persistent = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!f!S", &persistent_id, &fci, &fci_cache, &conn_str) == FAILURE) { - return; - } + /* "|S!f!S" */ + ZEND_PARSE_PARAMETERS_START(0, 3) + Z_PARAM_OPTIONAL + Z_PARAM_STR_EX(persistent_id, 1, 0) + Z_PARAM_FUNC_EX(fci, fci_cache, 1, 0) + Z_PARAM_STR(conn_str) + ZEND_PARSE_PARAMETERS_END(); intern = Z_MEMC_OBJ_P(getThis()); intern->is_pristine = 1; @@ -1413,13 +1417,22 @@ void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|f!l", &server_key, &key, &fci, &fcc, &get_flags) == FAILURE) { - return; - } + /* "SS|f!l" */ + ZEND_PARSE_PARAMETERS_START(2, 4) + Z_PARAM_STR(server_key) + Z_PARAM_STR(key) + Z_PARAM_OPTIONAL + Z_PARAM_FUNC_EX(fci, fcc, 1, 0) + Z_PARAM_LONG(get_flags) + ZEND_PARSE_PARAMETERS_END(); } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|f!l", &key, &fci, &fcc, &get_flags) == FAILURE) { - return; - } + /* "S|f!l" */ + ZEND_PARSE_PARAMETERS_START(1, 3) + Z_PARAM_STR(key) + Z_PARAM_OPTIONAL + Z_PARAM_FUNC_EX(fci, fcc, 1, 0) + Z_PARAM_LONG(get_flags) + ZEND_PARSE_PARAMETERS_END(); } MEMC_METHOD_FETCH_OBJECT; @@ -1505,14 +1518,20 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke zend_bool retval, preserve_order; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa|l", &server_key, - &keys, &flags) == FAILURE) { - return; - } + /* "Sa|l" */ + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_STR(server_key) + Z_PARAM_ARRAY(keys) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(flags) + ZEND_PARSE_PARAMETERS_END(); } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|l", &keys, &flags) == FAILURE) { - return; - } + /* "a|l" */ + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_ARRAY(keys) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(flags) + ZEND_PARSE_PARAMETERS_END(); } MEMC_METHOD_FETCH_OBJECT; @@ -1642,15 +1661,22 @@ static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|bf!", &server_key, - &keys, &with_cas, &fci, &fcc) == FAILURE) { - return; - } + /* "Sa/|bf!" */ + ZEND_PARSE_PARAMETERS_START(2, 4) + Z_PARAM_STR(server_key) + Z_PARAM_ARRAY_EX(keys, 0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_BOOL(with_cas) + Z_PARAM_FUNC_EX(fci, fcc, 1, 0) + ZEND_PARSE_PARAMETERS_END(); } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|bf!", &keys, &with_cas, - &fci, &fcc) == FAILURE) { - return; - } + /* "a/|bf!" */ + ZEND_PARSE_PARAMETERS_START(1, 3) + Z_PARAM_ARRAY_EX(keys, 0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_BOOL(with_cas) + Z_PARAM_FUNC_EX(fci, fcc, 1, 0) + ZEND_PARSE_PARAMETERS_END(); } MEMC_METHOD_FETCH_OBJECT; @@ -1796,7 +1822,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke { zval *entries; zend_string *server_key = NULL; - time_t expiration = 0; + zend_long expiration = 0, ignored; zval *value; zend_string *skey; zend_ulong num_key; @@ -1804,14 +1830,22 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa|ll", &server_key, - &entries, &expiration) == FAILURE) { - return; - } + /* "Sa|ll" */ + ZEND_PARSE_PARAMETERS_START(2, 4) + Z_PARAM_STR(server_key) + Z_PARAM_ARRAY(entries) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(expiration) + Z_PARAM_LONG(ignored) + ZEND_PARSE_PARAMETERS_END(); } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|ll", &entries, &expiration) == FAILURE) { - return; - } + /* "a|ll" */ + ZEND_PARSE_PARAMETERS_START(1, 3) + Z_PARAM_ARRAY(entries) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(expiration) + Z_PARAM_LONG(ignored) + ZEND_PARSE_PARAMETERS_END(); } MEMC_METHOD_FETCH_OBJECT; @@ -1921,35 +1955,56 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool if (by_key) { if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSS", &server_key, &key, &s_value) == FAILURE) { - return; - } + /* "SSS" */ + ZEND_PARSE_PARAMETERS_START(3, 3) + Z_PARAM_STR(server_key) + Z_PARAM_STR(key) + Z_PARAM_STR(s_value) + ZEND_PARSE_PARAMETERS_END(); value = &s_zvalue; ZVAL_STR(value, s_value); } else if (op == MEMC_OP_TOUCH) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|l", &server_key, &key, &expiration) == FAILURE) { - return; - } + /* "SS|l" */ + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_STR(server_key) + Z_PARAM_STR(key) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(expiration) + ZEND_PARSE_PARAMETERS_END(); } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSz|l", &server_key, &key, &value, &expiration) == FAILURE) { - return; - } + /* "SSz|l" */ + ZEND_PARSE_PARAMETERS_START(3, 4) + Z_PARAM_STR(server_key) + Z_PARAM_STR(key) + Z_PARAM_ZVAL(value) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(expiration) + ZEND_PARSE_PARAMETERS_END(); } } else { if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &key, &s_value) == FAILURE) { - return; - } + /* "SS" */ + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_STR(key) + Z_PARAM_STR(s_value) + ZEND_PARSE_PARAMETERS_END(); value = &s_zvalue; ZVAL_STR(value, s_value); } else if (op == MEMC_OP_TOUCH) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &key, &expiration) == FAILURE) { - return; - } + /* "S|l */ + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_STR(key) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(expiration) + ZEND_PARSE_PARAMETERS_END(); } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|l", &key, &value, &expiration) == FAILURE) { - return; - } + /* "Sz|l" */ + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_STR(key) + Z_PARAM_ZVAL(value) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(expiration) + ZEND_PARSE_PARAMETERS_END(); } } @@ -1984,22 +2039,34 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) zend_string *key; zend_string *server_key = NULL; zval *value; - time_t expiration = 0; + zend_long expiration = 0; + zend_long ignored; zend_string *payload; uint32_t flags = 0; memcached_return status; MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "zSSz|ll", &zv_cas, &server_key, &key, - &value, &expiration) == FAILURE) { - return; - } + /* "zSSz|ll" */ + ZEND_PARSE_PARAMETERS_START(4, 6) + Z_PARAM_ZVAL(zv_cas) + Z_PARAM_STR(server_key) + Z_PARAM_STR(key) + Z_PARAM_ZVAL(value) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(expiration) + Z_PARAM_LONG(ignored) + ZEND_PARSE_PARAMETERS_END(); } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "zSz|ll", &zv_cas, &key, &value, - &expiration) == FAILURE) { - return; - } + /* "zSz|ll" */ + ZEND_PARSE_PARAMETERS_START(3, 5) + Z_PARAM_ZVAL(zv_cas) + Z_PARAM_STR(key) + Z_PARAM_ZVAL(value) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(expiration) + Z_PARAM_LONG(ignored) + ZEND_PARSE_PARAMETERS_END(); } MEMC_METHOD_FETCH_OBJECT; @@ -2081,18 +2148,25 @@ PHP_METHOD(Memcached, deleteMultiByKey) static void php_memc_delete_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { zend_string *key, *server_key; - time_t expiration = 0; + zend_long expiration = 0; memcached_return status; MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|l", &server_key, &key, &expiration) == FAILURE) { - return; - } + /* "SS|l" */ + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_STR(server_key) + Z_PARAM_STR(key) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(expiration) + ZEND_PARSE_PARAMETERS_END(); } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &key, &expiration) == FAILURE) { - return; - } + /* "S|l" */ + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_STR(key) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(expiration) + ZEND_PARSE_PARAMETERS_END(); server_key = key; } @@ -2120,20 +2194,27 @@ static void php_memc_deleteMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by { zval *entries, *zv, ret; zend_string *server_key = NULL; - time_t expiration = 0; + zend_long expiration = 0; zend_string *entry; memcached_return status; MEMC_METHOD_INIT_VARS; if (by_key) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa/|l", &server_key, &entries, &expiration) == FAILURE) { - return; - } + /* "Sa/|l" */ + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_STR(server_key) + Z_PARAM_ARRAY_EX(entries, 0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(expiration) + ZEND_PARSE_PARAMETERS_END(); } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|l", &entries, &expiration) == FAILURE) { - return; - } + /* "a/|l" */ + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_ARRAY_EX(entries, 0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(expiration) + ZEND_PARSE_PARAMETERS_END(); } MEMC_METHOD_FETCH_OBJECT; @@ -2172,21 +2253,33 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, { zend_string *key, *server_key = NULL; zend_long offset = 1; - uint64_t value = UINT64_MAX, initial = 0; - time_t expiry = 0; + zend_long expiry = 0; + zend_long initial = 0; + uint64_t value = UINT64_MAX; memcached_return status; int n_args = ZEND_NUM_ARGS(); MEMC_METHOD_INIT_VARS; if (!by_key) { - if (zend_parse_parameters(n_args, "S|lll", &key, &offset, &initial, &expiry) == FAILURE) { - return; - } + /* "S|lll" */ + ZEND_PARSE_PARAMETERS_START(1, 4) + Z_PARAM_STR(key) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(offset) + Z_PARAM_LONG(initial) + Z_PARAM_LONG(expiry) + ZEND_PARSE_PARAMETERS_END(); } else { - if (zend_parse_parameters(n_args, "SS|lll", &server_key, &key, &offset, &initial, &expiry) == FAILURE) { - return; - } + /* "SS|lll" */ + ZEND_PARSE_PARAMETERS_START(2, 5) + Z_PARAM_STR(server_key) + Z_PARAM_STR(key) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(offset) + Z_PARAM_LONG(initial) + Z_PARAM_LONG(expiry) + ZEND_PARSE_PARAMETERS_END(); } MEMC_METHOD_FETCH_OBJECT; @@ -2228,15 +2321,15 @@ static void php_memc_incdec_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key, } if (by_key) { if (incr) { - status = memcached_increment_with_initial_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), offset, initial, expiry, &value); + status = memcached_increment_with_initial_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), offset, initial, (time_t)expiry, &value); } else { - status = memcached_decrement_with_initial_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), offset, initial, expiry, &value); + status = memcached_decrement_with_initial_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), offset, initial, (time_t)expiry, &value); } } else { if (incr) { - status = memcached_increment_with_initial(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), offset, initial, expiry, &value); + status = memcached_increment_with_initial(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), offset, initial, (time_t)expiry, &value); } else { - status = memcached_decrement_with_initial(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), offset, initial, expiry, &value); + status = memcached_decrement_with_initial(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), offset, initial, (time_t)expiry, &value); } } if (s_should_retry_write(intern, status) && retries-- > 0) { @@ -2293,13 +2386,17 @@ PHP_METHOD(Memcached, incrementByKey) PHP_METHOD(Memcached, addServer) { zend_string *host; - long port, weight = 0; + zend_long port, weight = 0; memcached_return status; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sl|l", &host, &port, &weight) == FAILURE) { - return; - } + /* "Sa/|l" */ + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_STR(host) + Z_PARAM_LONG(port) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(weight) + ZEND_PARSE_PARAMETERS_END(); MEMC_METHOD_FETCH_OBJECT; s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); @@ -2327,9 +2424,10 @@ PHP_METHOD(Memcached, addServers) memcached_return status; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/", &servers) == FAILURE) { - return; - } + /* "a/" */ + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_ARRAY_EX(servers, 0, 1) + ZEND_PARSE_PARAMETERS_END(); MEMC_METHOD_FETCH_OBJECT; s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); @@ -2431,9 +2529,10 @@ PHP_METHOD(Memcached, getServerByKey) memcached_return error; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &server_key) == FAILURE) { - return; - } + /* "S" */ + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STR(server_key) + ZEND_PARSE_PARAMETERS_END(); MEMC_METHOD_FETCH_OBJECT; s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); @@ -2651,9 +2750,11 @@ PHP_METHOD(Memcached, getStats) zend_string *args_string = NULL; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!", &args_string) == FAILURE) { - return; - } + /* "|S!" */ + ZEND_PARSE_PARAMETERS_START(0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_STR_EX(args_string, 1, 0) + ZEND_PARSE_PARAMETERS_END(); MEMC_METHOD_FETCH_OBJECT; @@ -2745,13 +2846,15 @@ PHP_METHOD(Memcached, getAllKeys) Flushes the data on all the servers */ static PHP_METHOD(Memcached, flush) { - time_t delay = 0; + zend_long delay = 0; memcached_return status; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &delay) == FAILURE) { - return; - } + /* "|l" */ + ZEND_PARSE_PARAMETERS_START(0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(delay) + ZEND_PARSE_PARAMETERS_END(); MEMC_METHOD_FETCH_OBJECT; s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); @@ -2769,14 +2872,15 @@ static PHP_METHOD(Memcached, flush) Returns the value for the given option constant */ static PHP_METHOD(Memcached, getOption) { - long option; + zend_long option; uint64_t result; memcached_behavior flag; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &option) == FAILURE) { - return; - } + /* "l" */ + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_LONG(option) + ZEND_PARSE_PARAMETERS_END(); MEMC_METHOD_FETCH_OBJECT; @@ -3018,7 +3122,7 @@ PHP_METHOD(Memcached, setBucket) { zval *zserver_map; zval *zforward_map = NULL; - long replicas = 0; + zend_long replicas = 0; zend_bool retval = 1; uint32_t *server_map = NULL, *forward_map = NULL; @@ -3026,9 +3130,12 @@ PHP_METHOD(Memcached, setBucket) memcached_return rc; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "aa!l", &zserver_map, &zforward_map, &replicas) == FAILURE) { - return; - } + /* "aa!l" */ + ZEND_PARSE_PARAMETERS_START(3, 3) + Z_PARAM_ARRAY(zserver_map) + Z_PARAM_ARRAY_EX(zforward_map, 1, 0) + Z_PARAM_LONG(replicas) + ZEND_PARSE_PARAMETERS_END(); MEMC_METHOD_FETCH_OBJECT; @@ -3089,9 +3196,11 @@ static PHP_METHOD(Memcached, setOptions) MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &options) == FAILURE) { - return; - } + /* "a" */ + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_ARRAY(options) + ZEND_PARSE_PARAMETERS_END(); + MEMC_METHOD_FETCH_OBJECT; @@ -3114,13 +3223,15 @@ static PHP_METHOD(Memcached, setOptions) Sets the value for the given option constant */ static PHP_METHOD(Memcached, setOption) { - long option; + zend_long option; zval *value; MEMC_METHOD_INIT_VARS; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "lz/", &option, &value) == FAILURE) { - return; - } + /* "lz/" */ + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_LONG(option) + Z_PARAM_ZVAL_EX(value, 0, 1) + ZEND_PARSE_PARAMETERS_END(); MEMC_METHOD_FETCH_OBJECT; @@ -3137,9 +3248,11 @@ static PHP_METHOD(Memcached, setSaslAuthData) memcached_return status; zend_string *user, *pass; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &user, &pass) == FAILURE) { - return; - } + /* "SS/" */ + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_STR(user) + Z_PARAM_STR(pass) + ZEND_PARSE_PARAMETERS_END(); if (!php_memc_init_sasl_if_needed()) { RETURN_FALSE; @@ -3621,9 +3734,10 @@ PHP_METHOD(MemcachedServer, run) php_memc_server_t *intern; intern = Z_MEMC_SERVER_P(getThis()); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &address) == FAILURE) { - return; - } + /* "S" */ + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STR(address) + ZEND_PARSE_PARAMETERS_END(); rc = php_memc_proto_handler_run(intern->handler, address); @@ -3642,9 +3756,11 @@ PHP_METHOD(MemcachedServer, on) zend_fcall_info_cache fci_cache; zend_bool rc = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "lf!", &event, &fci, &fci_cache) == FAILURE) { - return; - } + /* "lf!" */ + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_LONG(event) + Z_PARAM_FUNC_EX(fci, fci_cache, 1, 0) + ZEND_PARSE_PARAMETERS_END(); if (event <= MEMC_SERVER_ON_MIN || event >= MEMC_SERVER_ON_MAX) { RETURN_FALSE; From 3f1362ae8b5d4f4ed9ad01bc826c906608137746 Mon Sep 17 00:00:00 2001 From: Tom Van Looy Date: Tue, 21 Nov 2017 06:18:26 +0100 Subject: [PATCH 180/345] Remove unused defines MEMC_SESS_DEFAULT_LOCK_WAIT and MEMC_SESS_LOCK_EXPIRATION (#354) --- php_memcached_session.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/php_memcached_session.c b/php_memcached_session.c index afa973bb..ab3e7222 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -22,9 +22,6 @@ extern ZEND_DECLARE_MODULE_GLOBALS(php_memcached) -#define MEMC_SESS_DEFAULT_LOCK_WAIT 150000 -#define MEMC_SESS_LOCK_EXPIRATION 30 - #define REALTIME_MAXDELTA 60*60*24*30 ps_module ps_mod_memcached = { From 5edd5bac25016646a4e6f4ad758847ceaaa1d874 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 20 Nov 2017 23:48:40 -0600 Subject: [PATCH 181/345] Restore default value memcached.sess_prefix = "memc.sess.key." Resolves #340 --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 891b2a3e..952b582c 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -352,7 +352,7 @@ PHP_INI_BEGIN() MEMC_SESSION_INI_ENTRY("connect_timeout", "0", OnUpdateLongGEZero, connect_timeout) MEMC_SESSION_INI_ENTRY("sasl_username", "", OnUpdateString, sasl_username) MEMC_SESSION_INI_ENTRY("sasl_password", "", OnUpdateString, sasl_password) - MEMC_SESSION_INI_ENTRY("prefix", "memc.sess.", OnUpdateSessionPrefixString, prefix) + MEMC_SESSION_INI_ENTRY("prefix", "memc.sess.key.", OnUpdateSessionPrefixString, prefix) MEMC_SESSION_INI_ENTRY("persistent", "0", OnUpdateBool, persistent_enabled) /* Deprecated */ From f30e7428e5f55f0dc8eec0dc6d30cc3f0f05d73e Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Tue, 5 Dec 2017 18:13:23 +0100 Subject: [PATCH 182/345] Fix typo bibrary to library (#372) --- config.m4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.m4 b/config.m4 index b34c30bf..705f4957 100644 --- a/config.m4 +++ b/config.m4 @@ -26,8 +26,8 @@ PHP_ARG_ENABLE(memcached-sasl, whether to enable memcached sasl support, PHP_ARG_ENABLE(memcached-protocol, whether to enable memcached protocol support, [ --enable-memcached-protocol Enable memcached protocol support], no, no) -PHP_ARG_WITH(system-fastlz, whether to use system FastLZ bibrary, -[ --with-system-fastlz Use system FastLZ bibrary], no, no) +PHP_ARG_WITH(system-fastlz, whether to use system FastLZ library, +[ --with-system-fastlz Use system FastLZ library], no, no) if test -z "$PHP_ZLIB_DIR"; then PHP_ARG_WITH(zlib-dir, for ZLIB, From 809e4b078a6a4d8fc683b1160f1ae6e6b43bd925 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 20 Nov 2017 22:43:00 -0600 Subject: [PATCH 183/345] Release notes for 3.0.4 --- ChangeLog | 11 +++++++++++ package.xml | 38 ++++++++++++++++++++++++++++++++------ 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1db3dd44..5e406ee2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,16 @@ memcached extension changelog +Version 3.0.4 (2017-11-20) +-------------------------- + + * Fix corrupted interned strings (#338) + * Fix unit tests for compatibility with PHP 7.2 (#358, #359) + * Fix \x0a in key name locks up connection and triggers a fatal timeout error (#339) + * Fix missing optional parameter getStats($type) (#337) + * Fix typo in skip message (#331) + * Fix build warnings (#329) + * Document GET_EXTENDED flag, add/rename other missing/misnamed constants (#335) + Version 3.0.3 (2017-02-19) -------------------------- diff --git a/package.xml b/package.xml index 5e1961f7..bbdaae81 100644 --- a/package.xml +++ b/package.xml @@ -27,9 +27,9 @@ http://pear.php.net/dtd/package-2.0.xsd"> aaron@serendipity.cx yes - 2017-02-19 + 2017-11-20 - 3.0.3 + 3.0.4 3.0.0 @@ -38,13 +38,19 @@ http://pear.php.net/dtd/package-2.0.xsd"> PHP -PHP7 release of memcached extension. Note that support for libmemcached 0.x series has been discontinued -and the oldest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of +PHP 7.0 - 7.1 - 7.2 release of memcached extension. Note that support for +libmemcached 0.x series has been discontinued and the oldest actively tested +version is 1.0.2. It is highly recommended to use version 1.0.18 of libmemcached. Fixes - * Fix crash when checking session data with older versions of libmemcached (#328) - * Fix crash due to zend_mm_corrupted when fetching session data (#327) + * Fix corrupted interned strings (#338) + * Fix unit tests for compatibility with PHP 7.2 (#358, #359) + * Fix \x0a in key name locks up connection and triggers a fatal timeout error (#339) + * Fix missing optional parameter getStats($type) (#337) + * Fix typo in skip message (#331) + * Fix build warnings (#329) + * Document GET_EXTENDED flag, add/rename other missing/misnamed constants (#335) @@ -191,6 +197,26 @@ Fixes + + + stable + stable + + + 3.0.3 + 3.0.0 + + 2017-02-19 + +PHP7 release of memcached extension. Note that support for libmemcached 0.x series has been discontinued +and the oldest actively tested version is 1.0.2. It is highly recommended to use version 1.0.18 of +libmemcached. + +Fixes + * Fix crash when checking session data with older versions of libmemcached (#328) + * Fix crash due to zend_mm_corrupted when fetching session data (#327) + + stable From 04e404631f4a94d825287cb92d55290395d77b73 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 10 Dec 2017 01:21:51 -0800 Subject: [PATCH 184/345] Bump version to 3.1.0-dev --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index 65a0349f..5194c038 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -27,7 +27,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.0.3" +#define PHP_MEMCACHED_VERSION "3.1.0-dev" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 6767a79dc3f74e4a8bb214beaeccf0b2d769746b Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 19 Dec 2017 04:06:52 -0800 Subject: [PATCH 185/345] Supports PHP 7.0 - 7.2 --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index f145c2df..19a8ab18 100644 --- a/README.markdown +++ b/README.markdown @@ -23,7 +23,7 @@ Dependencies ------------ php-memcached 3.x: -* Supports PHP 7.0 - 7.1. +* Supports PHP 7.0 - 7.2. * Requires libmemcached 1.x or higher. * Optionally supports igbinary 2.0 or higher. * Optionally supports msgpack 2.0 or higher. From c65cc1c2661e4bc529761bcc033247446b869f2c Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 18 Jan 2018 12:36:04 -0800 Subject: [PATCH 186/345] Fix session persistence by checking memcached behavior values before setting (#379) --- php_memcached_session.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/php_memcached_session.c b/php_memcached_session.c index ab3e7222..d8e9be62 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -186,12 +186,15 @@ void s_unlock_session(memcached_st *memc) static zend_bool s_configure_from_ini_values(memcached_st *memc, zend_bool silent) { - memcached_return rc; - #define check_set_behavior(behavior, value) \ - if ((rc = memcached_behavior_set(memc, (behavior), (value))) != MEMCACHED_SUCCESS) { \ - if (!silent) { php_error_docref(NULL, E_WARNING, "failed to initialise session memcached configuration: %s", memcached_strerror(memc, rc)); } \ - return 0; \ + if ((value) != memcached_behavior_get(memc, (behavior))) { \ + memcached_return rc; \ + if ((rc = memcached_behavior_set(memc, (behavior), (value))) != MEMCACHED_SUCCESS) { \ + if (!silent) { \ + php_error_docref(NULL, E_WARNING, "failed to initialise session memcached configuration: %s", memcached_strerror(memc, rc)); \ + } \ + return 0; \ + } \ } if (MEMC_SESS_INI(binary_protocol_enabled)) { @@ -243,7 +246,7 @@ zend_bool s_configure_from_ini_values(memcached_st *memc, zend_bool silent) user_data->has_sasl_data = 1; } -#undef safe_set_behavior +#undef check_set_behavior return 1; } From 7ed5b38a3e0fb8ad490c095da9c659b50d7a0ebd Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 18 Jan 2018 19:21:41 -0800 Subject: [PATCH 187/345] Removed ifdef 0 code and trivial block cleanup --- php_memcached.c | 38 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 952b582c..cc6456be 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -228,7 +228,6 @@ zend_bool s_memc_valid_key_ascii(zend_string *key) } #ifdef HAVE_MEMCACHED_PROTOCOL - typedef struct { php_memc_proto_handler_t *handler; zend_object zo; @@ -1235,34 +1234,25 @@ static PHP_METHOD(Memcached, __construct) memcached_set_user_data(intern->memc, memc_user_data); /* Set default behaviors */ - { -#ifdef mikko_0 - fprintf (stderr, "consistent_hash_enabled=%d binary_protocol_enabled=%d connect_timeout=%ld\n", - MEMC_G(default_behavior.consistent_hash_enabled), MEMC_G(default_behavior.binary_protocol_enabled), MEMC_G(default_behavior.connect_timeout)); -#endif - - memcached_return rc; + if (MEMC_G(default_behavior.consistent_hash_enabled)) { - if (MEMC_G(default_behavior.consistent_hash_enabled)) { - - rc = memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, MEMCACHED_DISTRIBUTION_CONSISTENT); - if (rc != MEMCACHED_SUCCESS) { - php_error_docref(NULL, E_WARNING, "Failed to turn on consistent hash: %s", memcached_strerror(intern->memc, rc)); - } + memcached_return rc = memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, MEMCACHED_DISTRIBUTION_CONSISTENT); + if (rc != MEMCACHED_SUCCESS) { + php_error_docref(NULL, E_WARNING, "Failed to turn on consistent hash: %s", memcached_strerror(intern->memc, rc)); } + } - if (MEMC_G(default_behavior.binary_protocol_enabled)) { - rc = memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1); - if (rc != MEMCACHED_SUCCESS) { - php_error_docref(NULL, E_WARNING, "Failed to turn on binary protocol: %s", memcached_strerror(intern->memc, rc)); - } + if (MEMC_G(default_behavior.binary_protocol_enabled)) { + memcached_return rc = memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1); + if (rc != MEMCACHED_SUCCESS) { + php_error_docref(NULL, E_WARNING, "Failed to turn on binary protocol: %s", memcached_strerror(intern->memc, rc)); } + } - if (MEMC_G(default_behavior.connect_timeout)) { - rc = memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, MEMC_G(default_behavior.connect_timeout)); - if (rc != MEMCACHED_SUCCESS) { - php_error_docref(NULL, E_WARNING, "Failed to set connect timeout: %s", memcached_strerror(intern->memc, rc)); - } + if (MEMC_G(default_behavior.connect_timeout)) { + memcached_return rc = memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, MEMC_G(default_behavior.connect_timeout)); + if (rc != MEMCACHED_SUCCESS) { + php_error_docref(NULL, E_WARNING, "Failed to set connect timeout: %s", memcached_strerror(intern->memc, rc)); } } From e622992e6f6d7c3098eb3c42c1b5f80d9cdf1c6a Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 18 Jan 2018 23:58:19 -0800 Subject: [PATCH 188/345] The configure script warns if libmemcached needs sasl.h if sasl.h cannot be found (#380) --- config.m4 | 65 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/config.m4 b/config.m4 index 705f4957..7a4a6c9f 100644 --- a/config.m4 +++ b/config.m4 @@ -184,7 +184,7 @@ if test "$PHP_MEMCACHED" != "no"; then else AC_MSG_RESULT([$msgpack_inc_path]) fi - fi + fi AC_MSG_CHECKING([for memcached session support]) if test "$PHP_MEMCACHED_SESSION" != "no"; then @@ -255,42 +255,45 @@ if test "$PHP_MEMCACHED" != "no"; then PHP_EVAL_LIBLINE($PHP_LIBMEMCACHED_LIBS, MEMCACHED_SHARED_LIBADD) PHP_EVAL_INCLINE($PHP_LIBMEMCACHED_INCLUDES) - # - # Added -lpthread here because AC_TRY_LINK tests on CentOS 6 seem to fail with undefined reference to pthread_once - # + dnl # Added -lpthread here because AC_TRY_LINK tests on CentOS 6 seem to fail with undefined reference to pthread_once ORIG_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $INCLUDES" + dnl # Always check if libmemcached was built with SASL support, + dnl # because it will require sasl.h even if not used here. + AC_CACHE_CHECK([for libmemcached sasl.h requirement], ac_cv_memc_sasl_support, [ + AC_TRY_COMPILE( + [ #include ], + [ + #if LIBMEMCACHED_WITH_SASL_SUPPORT + /* yes */ + #else + # error "no sasl support" + #endif + ], + [ ac_cv_memc_sasl_support="yes" ], + [ ac_cv_memc_sasl_support="no" ] + ) + ]) + + if test "$ac_cv_memc_sasl_support" = "yes"; then + AC_CHECK_HEADERS([sasl/sasl.h], [ac_cv_have_memc_sasl_h="yes"], [ac_cv_have_memc_sasl_h="no"]) + fi + + dnl # If libmemcached requires sasl.h but we can't find sasl.h, that's a hard error + dnl # regardless of the option --enable-memcached-sasl or --disable-memcached-sasl AC_MSG_CHECKING([whether to enable sasl support]) + if test "$ac_cv_memc_sasl_support" = "yes" && test "$ac_cv_have_memc_sasl_h" = "no"; then + AC_MSG_ERROR([no, libmemcached built with sasl required, but sasl.h not found.]) + fi + if test "$PHP_MEMCACHED_SASL" != "no"; then AC_MSG_RESULT(yes) - AC_CHECK_HEADERS([sasl/sasl.h], [ac_cv_have_memc_sasl_h="yes"], [ac_cv_have_memc_sasl_h="no"]) - - if test "$ac_cv_have_memc_sasl_h" = "yes"; then - - AC_CACHE_CHECK([whether libmemcached supports sasl], ac_cv_memc_sasl_support, [ - AC_TRY_COMPILE( - [ #include ], - [ - #if LIBMEMCACHED_WITH_SASL_SUPPORT - /* yes */ - #else - # error "no sasl support" - #endif - ], - [ ac_cv_memc_sasl_support="yes" ], - [ ac_cv_memc_sasl_support="no" ] - ) - ]) - - if test "$ac_cv_memc_sasl_support" = "yes"; then - PHP_CHECK_LIBRARY(sasl2, sasl_client_init, [PHP_ADD_LIBRARY(sasl2, 1, MEMCACHED_SHARED_LIBADD)]) - AC_DEFINE(HAVE_MEMCACHED_SASL, 1, [Have SASL support]) - else - AC_MSG_ERROR([no, libmemcached sasl support is not enabled. Run configure with --disable-memcached-sasl to disable this check]) - fi + if test "$ac_cv_memc_sasl_support" = "yes" && test "$ac_cv_have_memc_sasl_h" = "yes"; then + PHP_CHECK_LIBRARY(sasl2, sasl_client_init, [PHP_ADD_LIBRARY(sasl2, 1, MEMCACHED_SHARED_LIBADD)]) + AC_DEFINE(HAVE_MEMCACHED_SASL, 1, [Have SASL support]) else - AC_MSG_ERROR([no, sasl.h is not available. Run configure with --disable-memcached-sasl to disable this check]) + AC_MSG_ERROR([no, libmemcached built with sasl disabled. Run configure with --disable-memcached-sasl or update libmemcached with sasl support]) fi else AC_MSG_RESULT([no]) @@ -298,7 +301,7 @@ if test "$PHP_MEMCACHED" != "no"; then ORIG_CFLAGS="$CFLAGS" ORIG_LIBS="$LIBS" - + CFLAGS="$CFLAGS $PHP_LIBMEMCACHED_INCLUDES" LIBS="$LIBS $PHP_LIBMEMCACHED_LIBS" From 5c6de2b0e4096211d56f11131acb5d5bdc794190 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sat, 20 Jan 2018 08:04:40 -0800 Subject: [PATCH 189/345] Add support for libmemcached encryption (#381) This feature is fully supported in libmemcached 1.0.18 and higher, but has a notable bug in the original implementation in libmemcached versions 1.0.6 - 1.0.17 that the encryption key, once set, cannot be changed otherwise all further get/set operations fail. --- config.m4 | 19 ++++++++++++ memcached-api.php | 4 +++ package.xml | 2 ++ php_memcached.c | 56 ++++++++++++++++++++++++++++++++++ tests/set_encoding_key.phpt | 59 ++++++++++++++++++++++++++++++++++++ tests/set_encoding_key2.phpt | 37 ++++++++++++++++++++++ 6 files changed, 177 insertions(+) create mode 100644 tests/set_encoding_key.phpt create mode 100644 tests/set_encoding_key2.phpt diff --git a/config.m4 b/config.m4 index 7a4a6c9f..d38d5dc4 100644 --- a/config.m4 +++ b/config.m4 @@ -317,10 +317,29 @@ if test "$PHP_MEMCACHED" != "no"; then CFLAGS="$ORIG_CFLAGS" LIBS="$ORIG_LIBS" + CFLAGS="$CFLAGS $PHP_LIBMEMCACHED_INCLUDES" + LIBS="$LIBS $PHP_LIBMEMCACHED_LIBS" + if test "$ac_cv_have_memcached_exist" = "yes"; then AC_DEFINE(HAVE_MEMCACHED_EXIST, [1], [Whether memcached_exist is defined]) fi + AC_CACHE_CHECK([whether memcached_set_encoding_key is defined], ac_cv_have_memcached_set_encoding_key, [ + AC_TRY_LINK( + [ #include ], + [ memcached_set_encoding_key (NULL, NULL, 0); ], + [ ac_cv_have_memcached_set_encoding_key="yes" ], + [ ac_cv_have_memcached_set_encoding_key="no" ] + ) + ]) + + CFLAGS="$ORIG_CFLAGS" + LIBS="$ORIG_LIBS" + + if test "$ac_cv_have_memcached_set_encoding_key" = "yes"; then + AC_DEFINE(HAVE_MEMCACHED_SET_ENCODING_KEY, [1], [Whether memcached_set_encoding_key is defined]) + fi + PHP_MEMCACHED_FILES="php_memcached.c php_libmemcached_compat.c g_fmt.c" if test "$PHP_SYSTEM_FASTLZ" != "no"; then diff --git a/memcached-api.php b/memcached-api.php index f5174e22..8ab03d4c 100644 --- a/memcached-api.php +++ b/memcached-api.php @@ -96,6 +96,8 @@ class Memcached { const HAVE_MSGPACK; + const HAVE_ENCODING; + /** * Feature support */ @@ -363,6 +365,8 @@ public function isPristine( ) {} public function setSaslAuthData( $username, $password ) {} + public function setEncodingKey( $key ) {} + } class MemcachedException extends Exception { diff --git a/package.xml b/package.xml index bbdaae81..a8ece289 100644 --- a/package.xml +++ b/package.xml @@ -159,6 +159,8 @@ Fixes + + diff --git a/php_memcached.c b/php_memcached.c index cc6456be..ec76f9bb 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -142,6 +142,7 @@ typedef struct { zend_bool is_persistent; zend_bool compression_enabled; + zend_bool encoding_enabled; zend_long serializer; zend_long compression_type; @@ -1227,6 +1228,7 @@ static PHP_METHOD(Memcached, __construct) memc_user_data->serializer = MEMC_G(serializer_type); memc_user_data->compression_type = MEMC_G(compression_type); memc_user_data->compression_enabled = 1; + memc_user_data->encoding_enabled = 0; memc_user_data->store_retry_count = MEMC_G(store_retry_count); memc_user_data->set_udf_flags = -1; memc_user_data->is_persistent = is_persistent; @@ -3265,6 +3267,42 @@ static PHP_METHOD(Memcached, setSaslAuthData) /* }}} */ #endif /* HAVE_MEMCACHED_SASL */ +#ifdef HAVE_MEMCACHED_SET_ENCODING_KEY +/* {{{ Memcached::setEncodingKey(string key) + Sets AES encryption key (libmemcached 1.0.6 and higher) */ +static PHP_METHOD(Memcached, setEncodingKey) +{ + MEMC_METHOD_INIT_VARS; + memcached_return status; + zend_string *key; + + /* "S" */ + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STR(key) + ZEND_PARSE_PARAMETERS_END(); + + MEMC_METHOD_FETCH_OBJECT; + + // libmemcached < 1.0.18 cannot handle a change of encoding key. Warn about this and return false. +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000018 + if (memc_user_data->encoding_enabled) { + php_error_docref(NULL, E_WARNING, "libmemcached versions less than 1.0.18 cannot change encoding key"); + RETURN_FALSE; + } +#endif + + status = memcached_set_encoding_key(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key)); + + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { + RETURN_FALSE; + } + + memc_user_data->encoding_enabled = 1; + RETURN_TRUE; +} +/* }}} */ +#endif /* HAVE_MEMCACHED_SET_ENCODING_KEY */ + /* {{{ Memcached::getResultCode() Returns the result code from the last operation */ static PHP_METHOD(Memcached, getResultCode) @@ -4034,6 +4072,12 @@ ZEND_BEGIN_ARG_INFO(arginfo_setSaslAuthData, 0) ZEND_END_ARG_INFO() #endif +#ifdef HAVE_MEMCACHED_SET_ENCODING_KEY +ZEND_BEGIN_ARG_INFO(arginfo_setEncodingKey, 0) + ZEND_ARG_INFO(0, key) +ZEND_END_ARG_INFO() +#endif + ZEND_BEGIN_ARG_INFO(arginfo_setOption, 0) ZEND_ARG_INFO(0, option) ZEND_ARG_INFO(0, value) @@ -4133,6 +4177,9 @@ static zend_function_entry memcached_class_methods[] = { MEMC_ME(setBucket, arginfo_setBucket) #ifdef HAVE_MEMCACHED_SASL MEMC_ME(setSaslAuthData, arginfo_setSaslAuthData) +#endif +#ifdef HAVE_MEMCACHED_SET_ENCODING_KEY + MEMC_ME(setEncodingKey, arginfo_setEncodingKey) #endif MEMC_ME(isPersistent, arginfo_isPersistent) MEMC_ME(isPristine, arginfo_isPristine) @@ -4282,6 +4329,15 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_MSGPACK, 0); #endif + /* + * Indicate whether set_encoding_key is available + */ +#ifdef HAVE_MEMCACHED_SET_ENCODING_KEY + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_ENCODING, 1); +#else + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_ENCODING, 0); +#endif + #ifdef HAVE_MEMCACHED_SESSION REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_SESSION, 1); #else diff --git a/tests/set_encoding_key.phpt b/tests/set_encoding_key.phpt new file mode 100644 index 00000000..72d96daa --- /dev/null +++ b/tests/set_encoding_key.phpt @@ -0,0 +1,59 @@ +--TEST-- +Test libmemcached encryption +--SKIPIF-- + +--FILE-- +setEncodingKey("Hello")); +var_dump ($m->set ($key, 'set using encoding')); +var_dump ($m->get ($key)); + +echo "OK" . PHP_EOL; + +# Change the encryption key. The old value will be inaccessible. +var_dump ($m->setEncodingKey("World")); +var_dump ($m->get ($key)); + +echo "OK" . PHP_EOL; + +# Restore the original key to retrieve old values again. +var_dump ($m->setEncodingKey("Hello")); +var_dump ($m->get ($key)); + +echo "OK" . PHP_EOL; + +# With a new encoding key we can still write new values, +# this works as expected with libmemcached 1.0.18 and higher. +var_dump ($m->setEncodingKey("World")); +var_dump ($m->get ($key)); +var_dump ($m->set ($key, 'set using encoding')); +var_dump ($m->get ($key)); + +echo "OK" . PHP_EOL; + +?> +--EXPECT-- +bool(true) +bool(true) +string(18) "set using encoding" +OK +bool(true) +bool(false) +OK +bool(true) +string(18) "set using encoding" +OK +bool(true) +bool(false) +bool(true) +string(18) "set using encoding" +OK diff --git a/tests/set_encoding_key2.phpt b/tests/set_encoding_key2.phpt new file mode 100644 index 00000000..f8d21a16 --- /dev/null +++ b/tests/set_encoding_key2.phpt @@ -0,0 +1,37 @@ +--TEST-- +Test libmemcached encryption +--SKIPIF-- += 0x01000018) die ("skip test for libmemcached lower than 1.0.18"); +?> +--FILE-- +setEncodingKey("Hello")); +var_dump ($m->set ($key, 'set using encoding')); +var_dump ($m->get ($key)); + +echo "OK" . PHP_EOL; + +# libmemcached < 1.0.18 goes into a bad state when the encoding key is changed, +# so php-memcached warns and returns false when trying to change the key. +var_dump ($m->setEncodingKey("World")); + +echo "OK" . PHP_EOL; + +?> +--EXPECTF-- +bool(true) +bool(true) +string(18) "set using encoding" +OK + +Warning: Memcached::setEncodingKey(): libmemcached versions less than 1.0.18 cannot change encoding key in %s on line %d +bool(false) +OK From 2fc7d3659c127eaabc0458e46e7118bcd721f92c Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 21 Jan 2018 21:46:56 -0800 Subject: [PATCH 190/345] Fix wrong INI parsing method for memcached.sess_randomize_replica_read --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index ec76f9bb..8a5afa57 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -346,7 +346,7 @@ PHP_INI_BEGIN() #endif MEMC_SESSION_INI_ENTRY("consistent_hash", "1", OnUpdateBool, consistent_hash_enabled) MEMC_SESSION_INI_ENTRY("number_of_replicas", "0", OnUpdateLongGEZero, number_of_replicas) - MEMC_SESSION_INI_ENTRY("randomize_replica_read", "0", OnUpdateLongGEZero, randomize_replica_read_enabled) + MEMC_SESSION_INI_ENTRY("randomize_replica_read", "0", OnUpdateBool, randomize_replica_read_enabled) MEMC_SESSION_INI_ENTRY("remove_failed_servers", "0", OnUpdateBool, remove_failed_servers_enabled) MEMC_SESSION_INI_ENTRY("server_failure_limit", "0", OnUpdateLongGEZero, server_failure_limit) MEMC_SESSION_INI_ENTRY("connect_timeout", "0", OnUpdateLongGEZero, connect_timeout) From deb451ae9e519b326becfe51f4097918684d9003 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 21 Jan 2018 21:47:48 -0800 Subject: [PATCH 191/345] Fix wrong undefs of local macros for registering constants --- php_memcached.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 8a5afa57..6a03b0c3 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -4514,12 +4514,15 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(RESPONSE_ETMPFAIL, PROTOCOL_BINARY_RESPONSE_ETMPFAIL); #endif - #undef REGISTER_MEMC_CLASS_CONST_LONG - /* * Return value from simple get errors */ REGISTER_MEMC_CLASS_CONST_BOOL(GET_ERROR_RETURN_VALUE, 0); + + #undef REGISTER_MEMC_CLASS_CONST_LONG + #undef REGISTER_MEMC_CLASS_CONST_BOOL + #undef REGISTER_MEMC_CLASS_CONST_NULL + } /* }}} */ From f54ed299c0220a0a308b346e53944a35247e4efa Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 23 Jan 2018 03:32:07 -0800 Subject: [PATCH 192/345] Use STD_PHP_INI_BOOLEAN to correctly display php.ini booleans --- php_memcached.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 6a03b0c3..495cfd1e 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -326,34 +326,40 @@ PHP_INI_MH(OnUpdateSessionPrefixString) #define MEMC_INI_ENTRY(key, default_value, update_fn, gkey) \ STD_PHP_INI_ENTRY("memcached."key, default_value, PHP_INI_ALL, update_fn, memc.gkey, zend_php_memcached_globals, php_memcached_globals) +#define MEMC_INI_BOOL(key, default_value, update_fn, gkey) \ + STD_PHP_INI_BOOLEAN("memcached."key, default_value, PHP_INI_ALL, update_fn, memc.gkey, zend_php_memcached_globals, php_memcached_globals) + #define MEMC_SESSION_INI_ENTRY(key, default_value, update_fn, gkey) \ STD_PHP_INI_ENTRY("memcached.sess_"key, default_value, PHP_INI_ALL, update_fn, session.gkey, zend_php_memcached_globals, php_memcached_globals) +#define MEMC_SESSION_INI_BOOL(key, default_value, update_fn, gkey) \ + STD_PHP_INI_BOOLEAN("memcached.sess_"key, default_value, PHP_INI_ALL, update_fn, session.gkey, zend_php_memcached_globals, php_memcached_globals) + /* {{{ INI entries */ PHP_INI_BEGIN() #ifdef HAVE_MEMCACHED_SESSION - MEMC_SESSION_INI_ENTRY("locking", "1", OnUpdateBool, lock_enabled) + MEMC_SESSION_INI_BOOL ("locking", "1", OnUpdateBool, lock_enabled) MEMC_SESSION_INI_ENTRY("lock_wait_min", "1000", OnUpdateLongGEZero, lock_wait_min) MEMC_SESSION_INI_ENTRY("lock_wait_max", "2000", OnUpdateLongGEZero, lock_wait_max) MEMC_SESSION_INI_ENTRY("lock_retries", "5", OnUpdateLong, lock_retries) MEMC_SESSION_INI_ENTRY("lock_expire", "0", OnUpdateLongGEZero, lock_expiration) #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000018 - MEMC_SESSION_INI_ENTRY("binary_protocol", "0", OnUpdateBool, binary_protocol_enabled) + MEMC_SESSION_INI_BOOL ("binary_protocol", "0", OnUpdateBool, binary_protocol_enabled) #else - MEMC_SESSION_INI_ENTRY("binary_protocol", "1", OnUpdateBool, binary_protocol_enabled) + MEMC_SESSION_INI_BOOL ("binary_protocol", "1", OnUpdateBool, binary_protocol_enabled) #endif - MEMC_SESSION_INI_ENTRY("consistent_hash", "1", OnUpdateBool, consistent_hash_enabled) + MEMC_SESSION_INI_BOOL ("consistent_hash", "1", OnUpdateBool, consistent_hash_enabled) MEMC_SESSION_INI_ENTRY("number_of_replicas", "0", OnUpdateLongGEZero, number_of_replicas) - MEMC_SESSION_INI_ENTRY("randomize_replica_read", "0", OnUpdateBool, randomize_replica_read_enabled) - MEMC_SESSION_INI_ENTRY("remove_failed_servers", "0", OnUpdateBool, remove_failed_servers_enabled) + MEMC_SESSION_INI_BOOL ("randomize_replica_read", "0", OnUpdateBool, randomize_replica_read_enabled) + MEMC_SESSION_INI_BOOL ("remove_failed_servers", "0", OnUpdateBool, remove_failed_servers_enabled) MEMC_SESSION_INI_ENTRY("server_failure_limit", "0", OnUpdateLongGEZero, server_failure_limit) MEMC_SESSION_INI_ENTRY("connect_timeout", "0", OnUpdateLongGEZero, connect_timeout) MEMC_SESSION_INI_ENTRY("sasl_username", "", OnUpdateString, sasl_username) MEMC_SESSION_INI_ENTRY("sasl_password", "", OnUpdateString, sasl_password) + MEMC_SESSION_INI_BOOL ("persistent", "0", OnUpdateBool, persistent_enabled) MEMC_SESSION_INI_ENTRY("prefix", "memc.sess.key.", OnUpdateSessionPrefixString, prefix) - MEMC_SESSION_INI_ENTRY("persistent", "0", OnUpdateBool, persistent_enabled) /* Deprecated */ STD_PHP_INI_ENTRY("memcached.sess_lock_wait", "not set", PHP_INI_ALL, OnUpdateDeprecatedLockValue, no_effect, zend_php_memcached_globals, php_memcached_globals) @@ -367,14 +373,16 @@ PHP_INI_BEGIN() MEMC_INI_ENTRY("serializer", SERIALIZER_DEFAULT_NAME, OnUpdateSerializer, serializer_name) MEMC_INI_ENTRY("store_retry_count", "2", OnUpdateLong, store_retry_count) - MEMC_INI_ENTRY("default_consistent_hash", "0", OnUpdateBool, default_behavior.consistent_hash_enabled) - MEMC_INI_ENTRY("default_binary_protocol", "0", OnUpdateBool, default_behavior.binary_protocol_enabled) + MEMC_INI_BOOL ("default_consistent_hash", "0", OnUpdateBool, default_behavior.consistent_hash_enabled) + MEMC_INI_BOOL ("default_binary_protocol", "0", OnUpdateBool, default_behavior.binary_protocol_enabled) MEMC_INI_ENTRY("default_connect_timeout", "0", OnUpdateLongGEZero, default_behavior.connect_timeout) PHP_INI_END() /* }}} */ +#undef MEMC_INI_BOOL #undef MEMC_INI_ENTRY +#undef MEMC_SESSION_INI_BOOL #undef MEMC_SESSION_INI_ENTRY /**************************************** From 2c693c7a9b8239ccc73d6c8ae8f95f21ae282b5e Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 23 Jan 2018 03:52:34 -0800 Subject: [PATCH 193/345] Allow connect_timeout value of -1 and show Unlimited in phpinfo() --- php_memcached.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 495cfd1e..1d015ccc 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -329,12 +329,18 @@ PHP_INI_MH(OnUpdateSessionPrefixString) #define MEMC_INI_BOOL(key, default_value, update_fn, gkey) \ STD_PHP_INI_BOOLEAN("memcached."key, default_value, PHP_INI_ALL, update_fn, memc.gkey, zend_php_memcached_globals, php_memcached_globals) +#define MEMC_INI_LINK(key, default_value, update_fn, gkey) \ + STD_PHP_INI_ENTRY_EX("memcached."key, default_value, PHP_INI_ALL, update_fn, memc.gkey, zend_php_memcached_globals, php_memcached_globals, display_link_numbers) + #define MEMC_SESSION_INI_ENTRY(key, default_value, update_fn, gkey) \ STD_PHP_INI_ENTRY("memcached.sess_"key, default_value, PHP_INI_ALL, update_fn, session.gkey, zend_php_memcached_globals, php_memcached_globals) #define MEMC_SESSION_INI_BOOL(key, default_value, update_fn, gkey) \ STD_PHP_INI_BOOLEAN("memcached.sess_"key, default_value, PHP_INI_ALL, update_fn, session.gkey, zend_php_memcached_globals, php_memcached_globals) +#define MEMC_SESSION_INI_LINK(key, default_value, update_fn, gkey) \ + STD_PHP_INI_ENTRY_EX("memcached.sess_"key, default_value, PHP_INI_ALL, update_fn, session.gkey, zend_php_memcached_globals, php_memcached_globals, display_link_numbers) + /* {{{ INI entries */ PHP_INI_BEGIN() @@ -355,7 +361,8 @@ PHP_INI_BEGIN() MEMC_SESSION_INI_BOOL ("randomize_replica_read", "0", OnUpdateBool, randomize_replica_read_enabled) MEMC_SESSION_INI_BOOL ("remove_failed_servers", "0", OnUpdateBool, remove_failed_servers_enabled) MEMC_SESSION_INI_ENTRY("server_failure_limit", "0", OnUpdateLongGEZero, server_failure_limit) - MEMC_SESSION_INI_ENTRY("connect_timeout", "0", OnUpdateLongGEZero, connect_timeout) + MEMC_SESSION_INI_LINK ("connect_timeout", "0", OnUpdateLong, connect_timeout) + MEMC_SESSION_INI_ENTRY("sasl_username", "", OnUpdateString, sasl_username) MEMC_SESSION_INI_ENTRY("sasl_password", "", OnUpdateString, sasl_password) MEMC_SESSION_INI_BOOL ("persistent", "0", OnUpdateBool, persistent_enabled) @@ -375,14 +382,16 @@ PHP_INI_BEGIN() MEMC_INI_BOOL ("default_consistent_hash", "0", OnUpdateBool, default_behavior.consistent_hash_enabled) MEMC_INI_BOOL ("default_binary_protocol", "0", OnUpdateBool, default_behavior.binary_protocol_enabled) - MEMC_INI_ENTRY("default_connect_timeout", "0", OnUpdateLongGEZero, default_behavior.connect_timeout) + MEMC_INI_LINK ("default_connect_timeout", "0", OnUpdateLong, default_behavior.connect_timeout) PHP_INI_END() /* }}} */ #undef MEMC_INI_BOOL +#undef MEMC_INI_LINK #undef MEMC_INI_ENTRY #undef MEMC_SESSION_INI_BOOL +#undef MEMC_SESSION_INI_LINK #undef MEMC_SESSION_INI_ENTRY /**************************************** From dfcbc02693d49fa8708f6282776f7af4a884d904 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 23 Jan 2018 04:13:27 -0800 Subject: [PATCH 194/345] Remove memcached.ini reference to deprecated sess_lock_max_wait setting --- memcached.ini | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/memcached.ini b/memcached.ini index 6d05da3c..e4256c10 100644 --- a/memcached.ini +++ b/memcached.ini @@ -20,8 +20,7 @@ ; The time, in seconds, before a lock should release itself. ; Setting to 0 results in the default behaviour, which is to -; use the memcached.sess_lock_max_wait setting. If that is -; also 0, max_execution_time will be used. +; use PHP's max_execution_time. ;memcached.sess_lock_expire = 0; ; memcached session key prefix From e0ccf87c517bc3ec54067166d34058f21d67b0b3 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 23 Jan 2018 06:21:40 -0800 Subject: [PATCH 195/345] Avoid hanging getStats() when binary protocol and non-blocking are both enabled Fixes #348. --- package.xml | 1 + php_memcached.c | 12 ++++++ tests/stats_hang.phpt | 89 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 tests/stats_hang.phpt diff --git a/package.xml b/package.xml index a8ece289..c0e8e09d 100644 --- a/package.xml +++ b/package.xml @@ -168,6 +168,7 @@ Fixes + diff --git a/php_memcached.c b/php_memcached.c index 1d015ccc..a42ff195 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2757,6 +2757,7 @@ PHP_METHOD(Memcached, getStats) memcached_return status; char *args = NULL; zend_string *args_string = NULL; + uint64_t orig_no_block, orig_protocol; MEMC_METHOD_INIT_VARS; /* "|S!" */ @@ -2770,8 +2771,19 @@ PHP_METHOD(Memcached, getStats) if (args_string) args = ZSTR_VAL(args_string); + /* stats hangs in nonblocking mode, turn off during the call. Only change the + * value if needed, because libmemcached reconnects for this behavior_set. */ + orig_no_block = memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_NO_BLOCK); + orig_protocol = memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL); + if (orig_no_block && orig_protocol) + memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_NO_BLOCK, 0); + array_init(return_value); status = memcached_stat_execute(intern->memc, args, s_stat_execute_cb, return_value); + + if (orig_no_block && orig_protocol) + memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_NO_BLOCK, orig_no_block); + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { zval_ptr_dtor(return_value); RETURN_FALSE; diff --git a/tests/stats_hang.phpt b/tests/stats_hang.phpt new file mode 100644 index 00000000..181e15e0 --- /dev/null +++ b/tests/stats_hang.phpt @@ -0,0 +1,89 @@ +--TEST-- +Check stats does not hang on non-blocking binary protocol +--SKIPIF-- + +--FILE-- +setOption(Memcached::OPT_NO_BLOCK, true); +$m->setOption(Memcached::OPT_BINARY_PROTOCOL, true); + +$stats = $m->getStats(); +$conns1 = $stats[$key]['total_connections']; + +$stats = $m->getStats(); +$conns2 = $stats[$key]['total_connections']; + +var_dump($conns1 == $conns2); +var_dump($m->getOption(Memcached::OPT_NO_BLOCK)); +var_dump($m->getOption(Memcached::OPT_BINARY_PROTOCOL)); +echo "OK" . PHP_EOL; + +// If either or both options are false no need to reconnect +$m->setOption(Memcached::OPT_NO_BLOCK, false); +$m->setOption(Memcached::OPT_BINARY_PROTOCOL, true); + +$stats = $m->getStats(); +$conns1 = $stats[$key]['total_connections']; + +$stats = $m->getStats(); +$conns2 = $stats[$key]['total_connections']; + +var_dump($conns1 == $conns2); +var_dump($m->getOption(Memcached::OPT_NO_BLOCK)); +var_dump($m->getOption(Memcached::OPT_BINARY_PROTOCOL)); +echo "OK" . PHP_EOL; + +// If either or both options are false no need to reconnect +$m->setOption(Memcached::OPT_NO_BLOCK, true); +$m->setOption(Memcached::OPT_BINARY_PROTOCOL, false); + +$stats = $m->getStats(); +$conns1 = $stats[$key]['total_connections']; + +$stats = $m->getStats(); +$conns2 = $stats[$key]['total_connections']; + +var_dump($conns1 == $conns2); +var_dump($m->getOption(Memcached::OPT_NO_BLOCK)); +var_dump($m->getOption(Memcached::OPT_BINARY_PROTOCOL)); +echo "OK" . PHP_EOL; + +// If either or both options are false no need to reconnect +$m->setOption(Memcached::OPT_NO_BLOCK, false); +$m->setOption(Memcached::OPT_BINARY_PROTOCOL, false); + +$stats = $m->getStats(); +$conns1 = $stats[$key]['total_connections']; + +$stats = $m->getStats(); +$conns2 = $stats[$key]['total_connections']; + +var_dump($conns1 == $conns2); +var_dump($m->getOption(Memcached::OPT_NO_BLOCK)); +var_dump($m->getOption(Memcached::OPT_BINARY_PROTOCOL)); +echo "OK" . PHP_EOL; + +?> +--EXPECT-- +bool(false) +int(1) +int(1) +OK +bool(true) +int(0) +int(1) +OK +bool(true) +int(1) +int(0) +OK +bool(true) +int(0) +int(0) +OK From 8bfdbcc9063dafcb25fdb1d1705e07ee027d7379 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 29 Mar 2018 23:26:46 -0700 Subject: [PATCH 196/345] Update for new PHP 7.3 REFCOUNT macros (#390) --- .travis.yml | 3 +++ php_memcached.c | 4 ++-- php_memcached_private.h | 7 +++++++ php_memcached_session.c | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index d2457f55..26973f0a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,12 +3,15 @@ dist: trusty language: php php: + - master - 7.2 - 7.1 - 7.0 matrix: fast_finish: true + allow_failures: + - php: master env: - LIBMEMCACHED_VERSION=1.0.18 # Debian Jessie / Ubuntu Xenial diff --git a/php_memcached.c b/php_memcached.c index a42ff195..bd0f559e 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1298,7 +1298,7 @@ static PHP_METHOD(Memcached, __construct) le.type = php_memc_list_entry(); le.ptr = intern->memc; - GC_REFCOUNT(&le) = 1; + GC_SET_REFCOUNT(&le, 1); /* plist_key is not a persistent allocated key, thus we use str_update here */ if (zend_hash_str_update_mem(&EG(persistent_list), ZSTR_VAL(plist_key), ZSTR_LEN(plist_key), &le, sizeof(le)) == NULL) { @@ -3831,7 +3831,7 @@ PHP_METHOD(MemcachedServer, on) Z_TRY_ADDREF(fci.function_name); if (fci.object) { - GC_REFCOUNT(fci.object)++; + GC_ADDREF(fci.object); } } RETURN_BOOL(rc); diff --git a/php_memcached_private.h b/php_memcached_private.h index a04e19be..abc0459c 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -72,6 +72,13 @@ typedef unsigned long int uint32_t; # endif #endif +/* Backwards compatibility for GC API change in PHP 7.3 */ +#if PHP_VERSION_ID < 70300 +# define GC_ADDREF(p) ++GC_REFCOUNT(p) +# define GC_DELREF(p) --GC_REFCOUNT(p) +# define GC_SET_REFCOUNT(p, rc) GC_REFCOUNT(p) = rc +#endif + /**************************************** Structures and definitions ****************************************/ diff --git a/php_memcached_session.c b/php_memcached_session.c index d8e9be62..607a02c2 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -376,7 +376,7 @@ PS_OPEN_FUNC(memcached) le.type = s_memc_sess_list_entry(); le.ptr = memc; - GC_REFCOUNT(&le) = 1; + GC_SET_REFCOUNT(&le, 1); /* plist_key is not a persistent allocated key, thus we use str_update here */ if (zend_hash_str_update_mem(&EG(persistent_list), plist_key, plist_key_len, &le, sizeof(le)) == NULL) { From 893d7d53062a0ff0a4112c22ce048db0b2afc67d Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 29 Mar 2018 23:42:08 -0700 Subject: [PATCH 197/345] Expose build configuration via PECL (#383) --- package.xml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/package.xml b/package.xml index c0e8e09d..0edfd3da 100644 --- a/package.xml +++ b/package.xml @@ -197,7 +197,15 @@ Fixes memcached - + + + + + + + + + From f4dafd207e4b3f1f54a7ce52194dda7cf40b0934 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 8 Apr 2018 19:39:38 -0700 Subject: [PATCH 198/345] Add INI setting to choose session consistent hash (ketama or ketama_weighted) (#392) Provides a new INI option to select the same consistent hash behavior as older versions of php-memcached, to aid in migration from PHP 5.x to PHP 7.x. When `memcached_sess_consistent_hash_type` is set to `ketama` or `ketama_weighted`, that sets either MEMCACHED_BEHAVIOR_KETAMA or MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED, respectively. Resolves #344 --- memcached.ini | 7 +++++++ php_memcached.c | 20 +++++++++++++++++++- php_memcached.h | 8 -------- php_memcached_private.h | 15 +++++++++++++++ php_memcached_session.c | 16 +++++----------- 5 files changed, 46 insertions(+), 20 deletions(-) diff --git a/memcached.ini b/memcached.ini index e4256c10..138fd09a 100644 --- a/memcached.ini +++ b/memcached.ini @@ -43,6 +43,13 @@ ; default is On ;memcached.sess_consistent_hash = On +; memcached session consistent hash type +; if set to 'ketama', consistent hashing (libketama) is used +; for session handling (default for php-memcached 3.x) +; if set to 'ketama_weighted', weighted consistent hashing (libketama) is used +; for session handling (default for php-memcached 2.x) +;memcached.sess_consistent_hash_type = "ketama" + ; Allow failed memcached server to automatically be removed. ; Default is Off. (In previous versions, this setting was called memcached.sess_remove_failed) ;memcached.sess_remove_failed_servers = Off diff --git a/php_memcached.c b/php_memcached.c index bd0f559e..c24e58af 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -323,6 +323,22 @@ PHP_INI_MH(OnUpdateSessionPrefixString) return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } +static +PHP_INI_MH(OnUpdateConsistentHash) +{ + if (!new_value) { + MEMC_SESS_INI(consistent_hash_type) = MEMCACHED_BEHAVIOR_KETAMA; + } else if (!strcmp(ZSTR_VAL(new_value), "ketama")) { + MEMC_SESS_INI(consistent_hash_type) = MEMCACHED_BEHAVIOR_KETAMA; + } else if (!strcmp(ZSTR_VAL(new_value), "ketama_weighted")) { + MEMC_SESS_INI(consistent_hash_type) = MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED; + } else { + php_error_docref(NULL, E_WARNING, "memcached.sess_consistent_hash_type must be ketama or ketama_weighted"); + return FAILURE; + } + return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); +} + #define MEMC_INI_ENTRY(key, default_value, update_fn, gkey) \ STD_PHP_INI_ENTRY("memcached."key, default_value, PHP_INI_ALL, update_fn, memc.gkey, zend_php_memcached_globals, php_memcached_globals) @@ -357,6 +373,7 @@ PHP_INI_BEGIN() MEMC_SESSION_INI_BOOL ("binary_protocol", "1", OnUpdateBool, binary_protocol_enabled) #endif MEMC_SESSION_INI_BOOL ("consistent_hash", "1", OnUpdateBool, consistent_hash_enabled) + MEMC_SESSION_INI_ENTRY("consistent_hash_type", "ketama", OnUpdateConsistentHash, consistent_hash_name) MEMC_SESSION_INI_ENTRY("number_of_replicas", "0", OnUpdateLongGEZero, number_of_replicas) MEMC_SESSION_INI_BOOL ("randomize_replica_read", "0", OnUpdateBool, randomize_replica_read_enabled) MEMC_SESSION_INI_BOOL ("remove_failed_servers", "0", OnUpdateBool, remove_failed_servers_enabled) @@ -1254,7 +1271,6 @@ static PHP_METHOD(Memcached, __construct) /* Set default behaviors */ if (MEMC_G(default_behavior.consistent_hash_enabled)) { - memcached_return rc = memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, MEMCACHED_DISTRIBUTION_CONSISTENT); if (rc != MEMCACHED_SUCCESS) { php_error_docref(NULL, E_WARNING, "Failed to turn on consistent hash: %s", memcached_strerror(intern->memc, rc)); @@ -4263,6 +4279,8 @@ PHP_GINIT_FUNCTION(php_memcached) php_memcached_globals->session.lock_expiration = 30; php_memcached_globals->session.binary_protocol_enabled = 1; php_memcached_globals->session.consistent_hash_enabled = 1; + php_memcached_globals->session.consistent_hash_type = MEMCACHED_BEHAVIOR_KETAMA; + php_memcached_globals->session.consistent_hash_name = NULL; php_memcached_globals->session.number_of_replicas = 0; php_memcached_globals->session.server_failure_limit = 1; php_memcached_globals->session.randomize_replica_read_enabled = 1; diff --git a/php_memcached.h b/php_memcached.h index 5194c038..a33f8be6 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -42,14 +42,6 @@ PHP_MEMCACHED_API zend_class_entry *php_memc_get_exception_base(int root); extern zend_module_entry memcached_module_entry; #define phpext_memcached_ptr &memcached_module_entry -#ifdef ZTS -#define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, memc.v) -#define MEMC_SERVER_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, server.v) -#else -#define MEMC_G(v) (php_memcached_globals.memc.v) -#define MEMC_SERVER_G(v) (php_memcached_globals.server.v) -#endif - #endif /* PHP_MEMCACHED_H */ /* diff --git a/php_memcached_private.h b/php_memcached_private.h index abc0459c..cf652e39 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -156,6 +156,8 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) zend_bool binary_protocol_enabled; zend_bool consistent_hash_enabled; + char *consistent_hash_name; + int consistent_hash_type; zend_long server_failure_limit; zend_long number_of_replicas; @@ -207,6 +209,19 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) ZEND_END_MODULE_GLOBALS(php_memcached) +/* Globals accessor macros */ +#ifdef ZTS +# define MEMC_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, memc.v) +# define MEMC_SERVER_G(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, server.v) +# define MEMC_SESS_INI(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, session.v) +#else +# define MEMC_G(v) (php_memcached_globals.memc.v) +# define MEMC_SERVER_G(v) (php_memcached_globals.server.v) +# define MEMC_SESS_INI(v) (php_memcached_globals.session.v) +#endif + +#define MEMC_SESS_STR_INI(vv) ((MEMC_SESS_INI(vv) && *MEMC_SESS_INI(vv)) ? MEMC_SESS_INI(vv) : NULL) + PHP_RINIT_FUNCTION(memcached); PHP_RSHUTDOWN_FUNCTION(memcached); PHP_MINIT_FUNCTION(memcached); diff --git a/php_memcached_session.c b/php_memcached_session.c index 607a02c2..7d072af2 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -43,14 +43,6 @@ typedef struct { # define MAX(a,b) (((a)>(b))?(a):(b)) #endif -#ifdef ZTS -#define MEMC_SESS_INI(v) TSRMG(php_memcached_globals_id, zend_php_memcached_globals *, session.v) -#else -#define MEMC_SESS_INI(v) (php_memcached_globals.session.v) -#endif - -#define MEMC_SESS_STR_INI(vv) ((MEMC_SESS_INI(vv) && *MEMC_SESS_INI(vv)) ? MEMC_SESS_INI(vv) : NULL) - static int le_memc_sess; @@ -187,9 +179,11 @@ static zend_bool s_configure_from_ini_values(memcached_st *memc, zend_bool silent) { #define check_set_behavior(behavior, value) \ - if ((value) != memcached_behavior_get(memc, (behavior))) { \ + int b = (behavior); \ + uint64_t v = (value); \ + if (v != memcached_behavior_get(memc, b)) { \ memcached_return rc; \ - if ((rc = memcached_behavior_set(memc, (behavior), (value))) != MEMCACHED_SUCCESS) { \ + if ((rc = memcached_behavior_set(memc, b, v)) != MEMCACHED_SUCCESS) { \ if (!silent) { \ php_error_docref(NULL, E_WARNING, "failed to initialise session memcached configuration: %s", memcached_strerror(memc, rc)); \ } \ @@ -202,7 +196,7 @@ zend_bool s_configure_from_ini_values(memcached_st *memc, zend_bool silent) } if (MEMC_SESS_INI(consistent_hash_enabled)) { - check_set_behavior(MEMCACHED_BEHAVIOR_KETAMA, 1); + check_set_behavior(MEMC_SESS_INI(consistent_hash_type), 1); } if (MEMC_SESS_INI(server_failure_limit)) { From f5f84c592f8950ae150d7123704feb6a1258e3c5 Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Sat, 30 Jun 2018 19:00:44 +0200 Subject: [PATCH 199/345] Remove unused Git attributes ident (#402) The $Id$ keywords were used in Subversion where they can be substituted with filename, last revision number change, last changed date, and last user who changed it. In Git this functionality is different and can be done with Git attribute ident. These need to be defined manually for each file in the .gitattributes file and are afterwards replaced with 40-character hexadecimal blob object name which is based only on the particular file contents. This patch simplifies handling of $Id$ keywords by removing them since they are not used anymore. --- config.m4 | 2 -- config.w32 | 1 - php_memcached.c | 2 -- php_memcached.h | 2 -- php_memcached_private.h | 2 -- 5 files changed, 9 deletions(-) diff --git a/config.m4 b/config.m4 index d38d5dc4..f086d492 100644 --- a/config.m4 +++ b/config.m4 @@ -1,5 +1,3 @@ -dnl -dnl $ Id: $ dnl vim:se ts=2 sw=2 et: PHP_ARG_ENABLE(memcached, whether to enable memcached support, diff --git a/config.w32 b/config.w32 index 380a9a12..e6e0c425 100644 --- a/config.w32 +++ b/config.w32 @@ -1,4 +1,3 @@ -// $ Id: $ // vim:ft=javascript ARG_WITH('memcached', 'libmemcached extension', 'no'); diff --git a/php_memcached.c b/php_memcached.c index c24e58af..01f98729 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -14,8 +14,6 @@ +----------------------------------------------------------------------+ */ -/* $ Id: $ */ - /* TODO * - set LIBKETAMA_COMPATIBLE as the default? * - fix unserialize(serialize($memc)) diff --git a/php_memcached.h b/php_memcached.h index a33f8be6..59989f5b 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -14,8 +14,6 @@ +----------------------------------------------------------------------+ */ -/* $ Id: $ */ - #ifndef PHP_MEMCACHED_H #define PHP_MEMCACHED_H diff --git a/php_memcached_private.h b/php_memcached_private.h index cf652e39..561812e5 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -14,8 +14,6 @@ +----------------------------------------------------------------------+ */ -/* $ Id: $ */ - #ifndef PHP_MEMCACHED_PRIVATE_H #define PHP_MEMCACHED_PRIVATE_H From c54075a1bf77188af172287395dee4b81bbafd74 Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Mon, 2 Jul 2018 19:16:12 +0200 Subject: [PATCH 200/345] Remove .cvsignore unused file (#404) The .cvsignore file was used in CVS. In Git the .gitignore file includes the ignored project files. --- .cvsignore | 46 ---------------------------------------------- 1 file changed, 46 deletions(-) delete mode 100644 .cvsignore diff --git a/.cvsignore b/.cvsignore deleted file mode 100644 index cc617d3d..00000000 --- a/.cvsignore +++ /dev/null @@ -1,46 +0,0 @@ -*.lo -*.la -.deps -.libs -Makefile -Makefile.fragments -Makefile.global -Makefile.objects -acinclude.m4 -aclocal.m4 -autom4te.cache -build -config.cache -config.guess -config.h -config.h.in -config.log -config.nice -config.status -config.sub -configure -configure.in -conftest -conftest.c -include -install-sh -libtool -ltmain.sh -missing -mkinstalldirs -modules -scan_makefile_in.awk -*.dsw -*.plg -*.opt -*.ncb -Release -Release_inline -Debug -Release_TS -Release_TSDbg -Release_TS_inline -Debug_TS -memcached*.tgz -run-tests.php -cscope.out From b70b82ee4a793e3664394a20f92dd711044eea5b Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Sat, 21 Jul 2018 00:57:05 +0200 Subject: [PATCH 201/345] Remove forgotten unused comment about -lpthread (#406) The -lpthread option has been added long time ago in commit c10de3699faa3ecb4cb6861d6c92157e0c7e18ce and has been since also refactored and therefore comment is not needed anymore: feed35e22040b874ba6fc8659dc16b498e6e4150 --- config.m4 | 1 - 1 file changed, 1 deletion(-) diff --git a/config.m4 b/config.m4 index f086d492..9694b5e2 100644 --- a/config.m4 +++ b/config.m4 @@ -253,7 +253,6 @@ if test "$PHP_MEMCACHED" != "no"; then PHP_EVAL_LIBLINE($PHP_LIBMEMCACHED_LIBS, MEMCACHED_SHARED_LIBADD) PHP_EVAL_INCLINE($PHP_LIBMEMCACHED_INCLUDES) - dnl # Added -lpthread here because AC_TRY_LINK tests on CentOS 6 seem to fail with undefined reference to pthread_once ORIG_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $INCLUDES" From 549e7c8a3af643ab5ce76002a6748990f04570d2 Mon Sep 17 00:00:00 2001 From: Tom Van Looy Date: Sat, 21 Jul 2018 01:01:55 +0200 Subject: [PATCH 202/345] Change session_lock default ini values (#350) --- memcached.ini | 12 ++++++------ php_memcached.c | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/memcached.ini b/memcached.ini index 138fd09a..c2072324 100644 --- a/memcached.ini +++ b/memcached.ini @@ -7,16 +7,16 @@ ; The minimum time, in milliseconds, to wait between session lock attempts. ; This value is double on each lock retry until memcached.sess_lock_wait_max ; is reached, after which any further retries will take sess_lock_wait_max seconds. -; Default is 1000. -;memcached.sess_lock_wait_min = 1000; +; Default is 150. +;memcached.sess_lock_wait_min = 150; ; The maximum time, in milliseconds, to wait between session lock attempts. -; Default is 2000. -;memcached.sess_lock_wait_max = 2000; +; Default is 150. +;memcached.sess_lock_wait_max = 150; ; The number of times to retry locking the session lock, not including the first attempt. -; Default is 5. -;memcached.sess_lock_retries = 5; +; Default is 200. +;memcached.sess_lock_retries = 200; ; The time, in seconds, before a lock should release itself. ; Setting to 0 results in the default behaviour, which is to diff --git a/php_memcached.c b/php_memcached.c index 01f98729..2e283818 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -361,8 +361,8 @@ PHP_INI_BEGIN() #ifdef HAVE_MEMCACHED_SESSION MEMC_SESSION_INI_BOOL ("locking", "1", OnUpdateBool, lock_enabled) - MEMC_SESSION_INI_ENTRY("lock_wait_min", "1000", OnUpdateLongGEZero, lock_wait_min) - MEMC_SESSION_INI_ENTRY("lock_wait_max", "2000", OnUpdateLongGEZero, lock_wait_max) + MEMC_SESSION_INI_ENTRY("lock_wait_min", "150", OnUpdateLongGEZero, lock_wait_min) + MEMC_SESSION_INI_ENTRY("lock_wait_max", "150", OnUpdateLongGEZero, lock_wait_max) MEMC_SESSION_INI_ENTRY("lock_retries", "5", OnUpdateLong, lock_retries) MEMC_SESSION_INI_ENTRY("lock_expire", "0", OnUpdateLongGEZero, lock_expiration) #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000018 @@ -4271,9 +4271,9 @@ PHP_GINIT_FUNCTION(php_memcached) #ifdef HAVE_MEMCACHED_SESSION php_memcached_globals->session.lock_enabled = 0; - php_memcached_globals->session.lock_wait_max = 2000; - php_memcached_globals->session.lock_wait_min = 1000; - php_memcached_globals->session.lock_retries = 5; + php_memcached_globals->session.lock_wait_max = 150; + php_memcached_globals->session.lock_wait_min = 150; + php_memcached_globals->session.lock_retries = 200; php_memcached_globals->session.lock_expiration = 30; php_memcached_globals->session.binary_protocol_enabled = 1; php_memcached_globals->session.consistent_hash_enabled = 1; From 58b299e5856f6728e9adef4cd8d5b33a4aaf3748 Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Sat, 1 Sep 2018 18:27:21 +0200 Subject: [PATCH 203/345] Add configure.ac to Git ignored files (#405) Starting with PHP 7.2, the phpize script outputs configure.ac. Earlier verisons of phpize generated configure.in. Since configure.in was already on the gitignore list, this PR adds configure.ac to the gitignore list. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index bc9d558c..0cbefe90 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ config.status config.sub configure configure.in +configure.ac conftest conftest.c include From f773f278c9c43a40f3a66fea792247b4e04df931 Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Sat, 1 Sep 2018 18:30:31 +0200 Subject: [PATCH 204/345] Replace obsolete AC_TRY_FOO with AC_FOO_IFELSE (#403) Autoconf made several macros obsolete including the AC_TRY_COMPILE and AC_TRY_LINK in 2000 and since Autoconf 2.50: http://git.savannah.gnu.org/cgit/autoconf.git/tree/ChangeLog.2 These macros should be replaced with the current AC_FOO_IFELSE instead. It is fairly safe to upgrade and take the recommendation advice of autoconf upgrade manual since the upgrade should be compatible at least with PHP versions 5.4 and up, on some systems even with PHP 5.3. PHP versions from 5.4 to 7.1 require Autoconf 2.59+ and PHP 7.2+ require Autoconf 2.64+. This patch was created with the help of autoupdate script. Reference docs: - https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Obsolete-Macros.html - https://www.gnu.org/software/autoconf/manual/autoconf-2.59/autoconf.pdf --- config.m4 | 43 +++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/config.m4 b/config.m4 index 9694b5e2..1f75d622 100644 --- a/config.m4 +++ b/config.m4 @@ -259,17 +259,15 @@ if test "$PHP_MEMCACHED" != "no"; then dnl # Always check if libmemcached was built with SASL support, dnl # because it will require sasl.h even if not used here. AC_CACHE_CHECK([for libmemcached sasl.h requirement], ac_cv_memc_sasl_support, [ - AC_TRY_COMPILE( - [ #include ], - [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ #if LIBMEMCACHED_WITH_SASL_SUPPORT /* yes */ #else # error "no sasl support" #endif - ], - [ ac_cv_memc_sasl_support="yes" ], - [ ac_cv_memc_sasl_support="no" ] + ]])], + [ac_cv_memc_sasl_support="yes"], + [ac_cv_memc_sasl_support="no"] ) ]) @@ -303,12 +301,11 @@ if test "$PHP_MEMCACHED" != "no"; then LIBS="$LIBS $PHP_LIBMEMCACHED_LIBS" AC_CACHE_CHECK([whether memcached_exist is defined], ac_cv_have_memcached_exist, [ - AC_TRY_LINK( - [ #include ], - [ memcached_exist (NULL, NULL, 0); ], - [ ac_cv_have_memcached_exist="yes" ], - [ ac_cv_have_memcached_exist="no" ] - ) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[#include ]], + [[memcached_exist (NULL, NULL, 0);]])], + [ac_cv_have_memcached_exist="yes"], + [ac_cv_have_memcached_exist="no"]) ]) CFLAGS="$ORIG_CFLAGS" @@ -322,12 +319,11 @@ if test "$PHP_MEMCACHED" != "no"; then fi AC_CACHE_CHECK([whether memcached_set_encoding_key is defined], ac_cv_have_memcached_set_encoding_key, [ - AC_TRY_LINK( - [ #include ], - [ memcached_set_encoding_key (NULL, NULL, 0); ], - [ ac_cv_have_memcached_set_encoding_key="yes" ], - [ ac_cv_have_memcached_set_encoding_key="no" ] - ) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[#include ]], + [[memcached_set_encoding_key (NULL, NULL, 0);]])], + [ac_cv_have_memcached_set_encoding_key="yes"], + [ac_cv_have_memcached_set_encoding_key="no"]) ]) CFLAGS="$ORIG_CFLAGS" @@ -359,13 +355,12 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_RESULT([enabled]) AC_CACHE_CHECK([whether libmemcachedprotocol is usable], ac_cv_have_libmemcachedprotocol, [ - AC_TRY_COMPILE( - [ #include ], - [ memcached_binary_protocol_callback_st s_test_impl; + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[memcached_binary_protocol_callback_st s_test_impl; s_test_impl.interface.v1.delete_object = 0; - ], - [ ac_cv_have_libmemcachedprotocol="yes" ], - [ ac_cv_have_libmemcachedprotocol="no" ] + ]])], + [ac_cv_have_libmemcachedprotocol="yes"], + [ac_cv_have_libmemcachedprotocol="no"] ) ]) From 6220e207b05e7ff8ef0ed3ac79907bcd753c4a65 Mon Sep 17 00:00:00 2001 From: "Michael D. Stemle, Jr" Date: Wed, 14 Nov 2018 19:25:58 -0500 Subject: [PATCH 205/345] In the latest zlib package for homebrew, the install target is /usr/local/opt/zlib, so I'm adding that to the list. (#410) --- config.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.m4 b/config.m4 index 1f75d622..6deddfb9 100644 --- a/config.m4 +++ b/config.m4 @@ -60,7 +60,7 @@ if test "$PHP_MEMCACHED" != "no"; then AC_MSG_ERROR([Can't find ZLIB headers under "$PHP_ZLIB_DIR"]) fi else - for i in /usr/local /usr; do + for i in /usr/local /usr/local/opt/zlib /usr; do if test -f "$i/include/zlib/zlib.h"; then PHP_ZLIB_DIR="$i" PHP_ZLIB_INCDIR="$i/include/zlib" From 6d8f5d524f35e72422b9e81319b96f23af02adcc Mon Sep 17 00:00:00 2001 From: Xander Date: Thu, 15 Nov 2018 11:27:53 +1100 Subject: [PATCH 206/345] Windows fixes (#411) --- README.win32.txt | 13 +++++++++++++ config.w32 | 30 ++++++++++++++++++++++++++++-- php_memcached.c | 8 +++++++- php_memcached.h | 5 +++++ php_memcached_private.h | 4 ++++ 5 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 README.win32.txt diff --git a/README.win32.txt b/README.win32.txt new file mode 100644 index 00000000..c717aa8a --- /dev/null +++ b/README.win32.txt @@ -0,0 +1,13 @@ +Build Steps for Windows +------------------------- + +Follow https://wiki.php.net/internals/windows/stepbystepbuild_sdk_2#building_pecl_extensions + +- Add igbinary module to pecl directory if support desired +- Download/Compile libmemcached & add to deps folders (includes & lib). Lib should be named memcache.lib + - Important for 32bit: libmemcached must be built with _USE_32BIT_TIME_T defined (confirmed on PHP 7.2, VC15) + - https://github.com/yshurik/libmemcached-win/tree/1.0.18 is confirmed working + - To use the dll on the releases page you'd likely need to change the header files to use __time64_t instead of time_t +- Enable all options desired: --enable-memcached=shared --enable-memcached-session --enable-memcached-json + - for igbinary, add --enable-memcached-igbinary --enable-igbinary=shared +- Run nmake \ No newline at end of file diff --git a/config.w32 b/config.w32 index e6e0c425..9c84a059 100644 --- a/config.w32 +++ b/config.w32 @@ -1,6 +1,10 @@ // vim:ft=javascript -ARG_WITH('memcached', 'libmemcached extension', 'no'); +ARG_ENABLE('memcached', 'libmemcached extension', 'no'); + +ARG_ENABLE('memcached-session', 'whether to enable memcached session handler support', 'no'); +ARG_ENABLE('memcached-igbinary', 'whether to enable memcached igbinary serializer support', 'no'); +ARG_ENABLE('memcached-json', 'whether to enable memcached json serializer support', 'no'); if (PHP_MEMCACHED == "yes") { @@ -11,7 +15,29 @@ if (PHP_MEMCACHED == "yes") { if (!CHECK_HEADER_ADD_INCLUDE("libmemcached/memcached.h", "CFLAGS_MEMCACHED")) { ERROR("memcached: header 'libmemcached/memcached.h' not found"); } - EXTENSION("memcached", "memcached.c"); + + if (PHP_MEMCACHED_JSON != "no"){ + AC_DEFINE("HAVE_JSON_API",1); + } + + var memcached_extra_src = ""; + + if (PHP_MEMCACHED_SESSION != "no"){ + AC_DEFINE("HAVE_MEMCACHED_SESSION",1); + ADD_EXTENSION_DEP("memcached", "session", true) + memcached_extra_src += " php_memcached_session.c"; + } + + if (PHP_MEMCACHED_IGBINARY != "no"){ + AC_DEFINE("HAVE_MEMCACHED_IGBINARY",1); + ADD_EXTENSION_DEP("memcached", "igbinary", true); + if (!CHECK_HEADER_ADD_INCLUDE("igbinary.h", "CFLAGS_MEMCACHED")) { + ERROR("memcached: header 'igbinary.h' not found"); + } + } + + EXTENSION("memcached", "php_memcached.c php_libmemcached_compat.c g_fmt.c"+memcached_extra_src); + ADD_SOURCES(configure_module_dirname+"\\fastlz", "fastlz.c", "memcached"); AC_DEFINE("HAVE_MEMCACHED", 1, "memcached support"); AC_DEFINE("MEMCACHED_EXPORTS", 1) } diff --git a/php_memcached.c b/php_memcached.c index 2e283818..760c2c45 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -42,8 +42,14 @@ #endif #ifdef HAVE_MEMCACHED_IGBINARY +#ifdef PHP_WIN32 +//Windows extensions are generally built together, +//so it wont be in the installed location +#include "igbinary.h" +#else # include "ext/igbinary/igbinary.h" #endif +#endif #ifdef HAVE_MEMCACHED_MSGPACK # include "ext/msgpack/php_msgpack.h" @@ -1428,7 +1434,7 @@ zend_bool s_get_apply_fn(php_memc_object_t *intern, zend_string *key, zval *valu static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { - php_memc_get_ctx_t context = {}; + php_memc_get_ctx_t context = {0}; php_memc_keys_t keys = {0}; zend_long get_flags = 0; zend_string *key; diff --git a/php_memcached.h b/php_memcached.h index 59989f5b..b391790a 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -19,7 +19,12 @@ #include "php.h" #include "Zend/zend_smart_str.h" + +#ifdef PHP_WIN32 +#include "main/config.w32.h" +#else #include "main/php_config.h" +#endif #ifdef HAVE_CONFIG_H # include "config.h" diff --git a/php_memcached_private.h b/php_memcached_private.h index 561812e5..3e1f3586 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -17,7 +17,11 @@ #ifndef PHP_MEMCACHED_PRIVATE_H #define PHP_MEMCACHED_PRIVATE_H +#ifdef PHP_WIN32 +#include "main/config.w32.h" +#else #include "main/php_config.h" +#endif #ifdef HAVE_CONFIG_H # include "config.h" From 0b79956e6d92268295c67e26bc173d44724bf5a8 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 9 Apr 2018 00:35:56 -0700 Subject: [PATCH 207/345] Error message if old PERSISTENT=n flag is used in session.save_path --- package.xml | 1 + php_memcached_session.c | 7 +++++++ tests/session_badconf_persistent.phpt | 25 +++++++++++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 tests/session_badconf_persistent.phpt diff --git a/package.xml b/package.xml index 0edfd3da..2c537c02 100644 --- a/package.xml +++ b/package.xml @@ -117,6 +117,7 @@ Fixes + diff --git a/php_memcached_session.c b/php_memcached_session.c index 7d072af2..6acd9d3e 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -319,6 +319,13 @@ PS_OPEN_FUNC(memcached) memcached_server_list_st servers; + // Fail on incompatible PERSISTENT identifier (removed in php-memcached 3.0) + if (strstr(save_path, "PERSISTENT=")) { + php_error_docref(NULL, E_WARNING, "failed to parse session.save_path: PERSISTENT is replaced by memcached.sess_persistent = On"); + PS_SET_MOD_DATA(NULL); + return FAILURE; + } + // First parse servers servers = memcached_servers_parse(save_path); diff --git a/tests/session_badconf_persistent.phpt b/tests/session_badconf_persistent.phpt new file mode 100644 index 00000000..04b5e44e --- /dev/null +++ b/tests/session_badconf_persistent.phpt @@ -0,0 +1,25 @@ +--TEST-- +Session bad configurations, persistent +--SKIPIF-- + +--INI-- +session.save_handler = "memcached" +session.save_path = "PERSISTENT=1 hello:11211,world:11211" + +--FILE-- + Date: Mon, 9 Apr 2018 02:15:58 -0700 Subject: [PATCH 208/345] Nits --- php_memcached.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 760c2c45..a7c33d31 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1526,7 +1526,7 @@ zend_bool s_get_multi_apply_fn(php_memc_object_t *intern, zend_string *key, zval add_assoc_zval(&node, "cas", cas); add_assoc_long(&node, "flags", (zend_long) MEMC_VAL_GET_USER_FLAGS(flags)); - zend_symtable_update(Z_ARRVAL_P(context->return_value), key, &node); + zend_symtable_update(Z_ARRVAL_P(context->return_value), key, &node); } else { zend_symtable_update(Z_ARRVAL_P(context->return_value), key, value); @@ -3213,7 +3213,7 @@ PHP_METHOD(Memcached, setBucket) rc = memcached_bucket_set (intern->memc, server_map, forward_map, (uint32_t) server_map_len, replicas); if (s_memc_status_handle_result_code(intern, rc) == FAILURE) { - retval = 0;; + retval = 0; } efree(server_map); From 282eca70cb6f4466093ab9a2f89ee1fbea5f1abd Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 21 Dec 2018 01:29:12 -0800 Subject: [PATCH 209/345] Add PHP 7.3 to Travis CI matrix, drop ancient libmemcached --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 26973f0a..ddc6d379 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ dist: trusty language: php php: - master + - 7.3 - 7.2 - 7.1 - 7.0 @@ -17,7 +18,6 @@ env: - LIBMEMCACHED_VERSION=1.0.18 # Debian Jessie / Ubuntu Xenial - LIBMEMCACHED_VERSION=1.0.16 # RHEL / CentOS 7 - LIBMEMCACHED_VERSION=1.0.8 # Debian Wheezy / Ubuntu Trusty - - LIBMEMCACHED_VERSION=1.0.2 # Ancient addons: apt: From e9381d07ca09367846d974b1ce1d4b02f8ba7c0a Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 21 Dec 2018 01:39:33 -0800 Subject: [PATCH 210/345] Travis CI switch to Xenial, remove deprecated sudo flag --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index ddc6d379..5ce37750 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,4 @@ -sudo: required -dist: trusty +dist: xenial language: php php: From c5618158c56569a1c20a94b4d792a3e182b528d0 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 21 Dec 2018 02:08:04 -0800 Subject: [PATCH 211/345] Handle fatal error in session badconf persistent test --- tests/session_badconf_persistent.phpt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/session_badconf_persistent.phpt b/tests/session_badconf_persistent.phpt index 04b5e44e..7deeb1e1 100644 --- a/tests/session_badconf_persistent.phpt +++ b/tests/session_badconf_persistent.phpt @@ -16,10 +16,10 @@ ob_start(); session_start(); session_write_close(); -echo "OK"; +// In PHP < 7.2 this is a Fatal Error so the OK is not printed +// echo "OK"; --EXPECTF-- Warning: session_start(): failed to parse session.save_path: PERSISTENT is replaced by memcached.sess_persistent = On in %s on line %d -Warning: session_start(): Failed to initialize storage module: memcached (path: PERSISTENT=1 %s) in %s on line %d -OK +%s: session_start(): Failed to initialize storage module: memcached (path: PERSISTENT=1 %s) in %s on line %d From 193590e93b4169fb830791d68b28d748f3951729 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 21 Dec 2018 03:48:49 -0800 Subject: [PATCH 212/345] Release notes for 3.1.0 --- ChangeLog | 28 +++++++++++++++++++++++ package.xml | 64 ++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 81 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5e406ee2..71536d94 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,33 @@ memcached extension changelog +Version 3.1.0 (2017-12-21) +-------------------------- + + New + * Support for PHP 7.3 (#385, #390) + * Add INI setting to choose session consistent hash (ketama or ketama_weighted) (#344, #392) + * Add support for libmemcached encryption (#345, #381) + * Add error reporting to session code (#165) + * Expose build configuration via PECL (#383) + + Fixes + * Fix hanging getStats() when binary protocol and non-blocking are both enabled (#348) + * Fix session persistence by checking memcached behavior values before setting (#379) + * Fix memcached.sess_persistent not working with memcached.sess_binary_protocol = On (#375) + * Configure warns if libmemcached needs sasl.h (#341, #380) + * Resolve various INI deviations in 3.0.3 (#351) + * Turn off sess_binary_protocol by default with older libmemcached (#330) + + Changes + * Impove Windows builds (#411) + * Support Homebrew ZLIB path (#410) + * Remove forgotten unused comment about -lpthread (#406) + * Git ignore configure.ac (#405) + * Replace obsolete macros AC_TRY_FOO with AC_FOO_IFELSE (#403) + * Remove unused defines (#354) + * Change session_lock and sess_prefix default ini values (#340, #350) + * Use new fast_zpp parameter parsing API (#302, #311) + Version 3.0.4 (2017-11-20) -------------------------- diff --git a/package.xml b/package.xml index 2c537c02..3015d032 100644 --- a/package.xml +++ b/package.xml @@ -27,9 +27,9 @@ http://pear.php.net/dtd/package-2.0.xsd"> aaron@serendipity.cx yes - 2017-11-20 + 2018-12-21 - 3.0.4 + 3.1.0 3.0.0 @@ -38,19 +38,35 @@ http://pear.php.net/dtd/package-2.0.xsd"> PHP -PHP 7.0 - 7.1 - 7.2 release of memcached extension. Note that support for +PHP 7.0 - 7.1 - 7.2 - 7.3 release of memcached extension. Note that support for libmemcached 0.x series has been discontinued and the oldest actively tested -version is 1.0.2. It is highly recommended to use version 1.0.18 of +version is 1.0.8. It is highly recommended to use version 1.0.18 of libmemcached. +New + * Support for PHP 7.3 (#385, #390) + * Add INI setting to choose session consistent hash (ketama or ketama_weighted) (#344, #392) + * Add support for libmemcached encryption (#345, #381) + * Add error reporting to session code (#165) + * Expose build configuration via PECL (#383) + Fixes - * Fix corrupted interned strings (#338) - * Fix unit tests for compatibility with PHP 7.2 (#358, #359) - * Fix \x0a in key name locks up connection and triggers a fatal timeout error (#339) - * Fix missing optional parameter getStats($type) (#337) - * Fix typo in skip message (#331) - * Fix build warnings (#329) - * Document GET_EXTENDED flag, add/rename other missing/misnamed constants (#335) + * Fix hanging getStats() when binary protocol and non-blocking are both enabled (#348) + * Fix session persistence by checking memcached behavior values before setting (#379) + * Fix memcached.sess_persistent not working with memcached.sess_binary_protocol = On (#375) + * Configure warns if libmemcached needs sasl.h (#341, #380) + * Resolve various INI deviations in 3.0.3 (#351) + * Turn off sess_binary_protocol by default with older libmemcached (#330) + +Changes + * Impove Windows builds (#411) + * Support Homebrew ZLIB path (#410) + * Remove forgotten unused comment about -lpthread (#406) + * Git ignore configure.ac (#405) + * Replace obsolete macros AC_TRY_FOO with AC_FOO_IFELSE (#403) + * Remove unused defines (#354) + * Change session_lock and sess_prefix default ini values (#340, #350) + * Use new fast_zpp parameter parsing API (#302, #311) @@ -209,6 +225,32 @@ Fixes + + + stable + stable + + + 3.0.4 + 3.0.0 + + 2017-11-20 + +PHP 7.0 - 7.1 - 7.2 release of memcached extension. Note that support for +libmemcached 0.x series has been discontinued and the oldest actively tested +version is 1.0.2. It is highly recommended to use version 1.0.18 of +libmemcached. + +Fixes + * Fix corrupted interned strings (#338) + * Fix unit tests for compatibility with PHP 7.2 (#358, #359) + * Fix \x0a in key name locks up connection and triggers a fatal timeout error (#339) + * Fix missing optional parameter getStats($type) (#337) + * Fix typo in skip message (#331) + * Fix build warnings (#329) + * Document GET_EXTENDED flag, add/rename other missing/misnamed constants (#335) + + stable From 699e68953a908e90235cf23671ce245ad35c5ef6 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 21 Dec 2018 03:49:01 -0800 Subject: [PATCH 213/345] Bump version to 3.1.0 --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index b391790a..97c64404 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.1.0-dev" +#define PHP_MEMCACHED_VERSION "3.1.0" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 4a82c59f49fe0a222a6cab6cc612f899ccc199a5 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 21 Dec 2018 04:44:15 -0800 Subject: [PATCH 214/345] Document that --disable-x options are --enable-x --- config.m4 | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/config.m4 b/config.m4 index 6deddfb9..c7a15f11 100644 --- a/config.m4 +++ b/config.m4 @@ -1,40 +1,40 @@ dnl vim:se ts=2 sw=2 et: PHP_ARG_ENABLE(memcached, whether to enable memcached support, -[ --enable-memcached Enable memcached support]) +[ --enable-memcached Enable memcached support]) PHP_ARG_WITH(libmemcached-dir, for libmemcached, -[ --with-libmemcached-dir[=DIR] Set the path to libmemcached install prefix.], yes) +[ --with-libmemcached-dir=DIR Set the path to libmemcached install prefix.], yes) PHP_ARG_ENABLE(memcached-session, whether to enable memcached session handler support, -[ --disable-memcached-session Disable memcached session handler support], yes, no) +[ --enable-memcached-session Enable memcached session handler support], yes, no) PHP_ARG_ENABLE(memcached-igbinary, whether to enable memcached igbinary serializer support, -[ --enable-memcached-igbinary Enable memcached igbinary serializer support], no, no) +[ --enable-memcached-igbinary Enable memcached igbinary serializer support], no, no) PHP_ARG_ENABLE(memcached-json, whether to enable memcached json serializer support, -[ --enable-memcached-json Enable memcached json serializer support], no, no) +[ --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) +[ --enable-memcached-msgpack Enable memcached msgpack serializer support], no, no) PHP_ARG_ENABLE(memcached-sasl, whether to enable memcached sasl support, -[ --disable-memcached-sasl Disable memcached sasl support], yes, no) +[ --enable-memcached-sasl Enable memcached sasl support], yes, no) PHP_ARG_ENABLE(memcached-protocol, whether to enable memcached protocol support, -[ --enable-memcached-protocol Enable memcached protocol support], no, no) +[ --enable-memcached-protocol Enable memcached protocol support], no, no) PHP_ARG_WITH(system-fastlz, whether to use system FastLZ library, -[ --with-system-fastlz Use system FastLZ library], no, no) +[ --with-system-fastlz Use system FastLZ library], no, no) if test -z "$PHP_ZLIB_DIR"; then PHP_ARG_WITH(zlib-dir, for ZLIB, -[ --with-zlib-dir[=DIR] Set the path to ZLIB install prefix.], no) +[ --with-zlib-dir=DIR Set the path to ZLIB install prefix.], no) fi if test -z "$PHP_DEBUG"; then AC_ARG_ENABLE(debug, - [ --enable-debug compile with debugging symbols],[ + [ --enable-debug Compile with debugging symbols],[ PHP_DEBUG=$enableval ],[ PHP_DEBUG=no ]) From b4d105bd41f1b6a54635d1e681f38924b264ec67 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 21 Dec 2018 04:45:44 -0800 Subject: [PATCH 215/345] Set defaults to match --enable-x rather than --disable-x --- package.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.xml b/package.xml index 3015d032..d9270d03 100644 --- a/package.xml +++ b/package.xml @@ -220,9 +220,9 @@ Changes - - - + + + From 9f7d049737f6ebe77013e6a21906959844696ade Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 21 Dec 2018 04:46:06 -0800 Subject: [PATCH 216/345] Fix zend_string warning --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index a7c33d31..858d0aca 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -493,7 +493,7 @@ char *php_memc_printable_func (zend_fcall_info *fci, zend_fcall_info_cache *fci_ char *buffer = NULL; if (fci->object) { - spprintf (&buffer, 0, "%s::%s", ZSTR_VAL(fci->object->ce->name), fci_cache->function_handler->common.function_name); + spprintf (&buffer, 0, "%s::%s", ZSTR_VAL(fci->object->ce->name), ZSTR_VAL(fci_cache->function_handler->common.function_name)); } else { if (Z_TYPE (fci->function_name) == IS_OBJECT) { spprintf (&buffer, 0, "%s", ZSTR_VAL(Z_OBJCE(fci->function_name)->name)); From e2dbf33fe9a9fcced24dc2728084fd09e1fe8b72 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 21 Dec 2018 04:51:32 -0800 Subject: [PATCH 217/345] Release notes for 3.1.1 --- ChangeLog | 5 ++++ package.xml | 68 ++++++++++++++++++++++++++++++++++------------------- 2 files changed, 49 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index 71536d94..4a1748b3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ memcached extension changelog +Version 3.1.1 (2017-12-21) +-------------------------- + + * Fix --disable-memcached-sasl and --disable-memcached-session replaced by --enable variants (#416) + Version 3.1.0 (2017-12-21) -------------------------- diff --git a/package.xml b/package.xml index d9270d03..9b6faf68 100644 --- a/package.xml +++ b/package.xml @@ -29,7 +29,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> 2018-12-21 - 3.1.0 + 3.1.1 3.0.0 @@ -43,30 +43,8 @@ libmemcached 0.x series has been discontinued and the oldest actively tested version is 1.0.8. It is highly recommended to use version 1.0.18 of libmemcached. -New - * Support for PHP 7.3 (#385, #390) - * Add INI setting to choose session consistent hash (ketama or ketama_weighted) (#344, #392) - * Add support for libmemcached encryption (#345, #381) - * Add error reporting to session code (#165) - * Expose build configuration via PECL (#383) - Fixes - * Fix hanging getStats() when binary protocol and non-blocking are both enabled (#348) - * Fix session persistence by checking memcached behavior values before setting (#379) - * Fix memcached.sess_persistent not working with memcached.sess_binary_protocol = On (#375) - * Configure warns if libmemcached needs sasl.h (#341, #380) - * Resolve various INI deviations in 3.0.3 (#351) - * Turn off sess_binary_protocol by default with older libmemcached (#330) - -Changes - * Impove Windows builds (#411) - * Support Homebrew ZLIB path (#410) - * Remove forgotten unused comment about -lpthread (#406) - * Git ignore configure.ac (#405) - * Replace obsolete macros AC_TRY_FOO with AC_FOO_IFELSE (#403) - * Remove unused defines (#354) - * Change session_lock and sess_prefix default ini values (#340, #350) - * Use new fast_zpp parameter parsing API (#302, #311) + * Fix --disable-memcached-sasl and --disable-memcached-session replaced by --enable variants (#416) @@ -225,6 +203,48 @@ Changes + + + stable + stable + + + 3.1.0 + 3.0.0 + + 2018-12-21 + +PHP 7.0 - 7.1 - 7.2 - 7.3 release of memcached extension. Note that support for +libmemcached 0.x series has been discontinued and the oldest actively tested +version is 1.0.8. It is highly recommended to use version 1.0.18 of +libmemcached. + +New + * Support for PHP 7.3 (#385, #390) + * Add INI setting to choose session consistent hash (ketama or ketama_weighted) (#344, #392) + * Add support for libmemcached encryption (#345, #381) + * Add error reporting to session code (#165) + * Expose build configuration via PECL (#383) + +Fixes + * Fix hanging getStats() when binary protocol and non-blocking are both enabled (#348) + * Fix session persistence by checking memcached behavior values before setting (#379) + * Fix memcached.sess_persistent not working with memcached.sess_binary_protocol = On (#375) + * Configure warns if libmemcached needs sasl.h (#341, #380) + * Resolve various INI deviations in 3.0.3 (#351) + * Turn off sess_binary_protocol by default with older libmemcached (#330) + +Changes + * Impove Windows builds (#411) + * Support Homebrew ZLIB path (#410) + * Remove forgotten unused comment about -lpthread (#406) + * Git ignore configure.ac (#405) + * Replace obsolete macros AC_TRY_FOO with AC_FOO_IFELSE (#403) + * Remove unused defines (#354) + * Change session_lock and sess_prefix default ini values (#340, #350) + * Use new fast_zpp parameter parsing API (#302, #311) + + stable From b4103acd0356db74518534c5da1702c72b38d459 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 21 Dec 2018 04:51:44 -0800 Subject: [PATCH 218/345] Bump version to 3.1.1 --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index 97c64404..3197d058 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.1.0" +#define PHP_MEMCACHED_VERSION "3.1.1" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 5ad7c05614dc2ea7f977193ad6157187d15fc89e Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sat, 22 Dec 2018 05:59:52 -0800 Subject: [PATCH 219/345] Partially revert b4d105b caught one option too many --- package.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.xml b/package.xml index 9b6faf68..7eca1a2c 100644 --- a/package.xml +++ b/package.xml @@ -198,7 +198,7 @@ Fixes - + From 206f12bddaf014eec4a53437c16c99ae9537216c Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sat, 22 Dec 2018 07:54:24 -0800 Subject: [PATCH 220/345] Release notes for 3.1.2 --- package.xml | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/package.xml b/package.xml index 7eca1a2c..8f54da93 100644 --- a/package.xml +++ b/package.xml @@ -27,9 +27,9 @@ http://pear.php.net/dtd/package-2.0.xsd"> aaron@serendipity.cx yes - 2018-12-21 + 2018-12-22 - 3.1.1 + 3.1.2 3.0.0 @@ -44,7 +44,7 @@ version is 1.0.8. It is highly recommended to use version 1.0.18 of libmemcached. Fixes - * Fix --disable-memcached-sasl and --disable-memcached-session replaced by --enable variants (#416) + * Fix --enable-memcached-protocol was set to yes by default, reverted to no (#418) @@ -203,6 +203,26 @@ Fixes + + + stable + stable + + + 3.1.1 + 3.0.0 + + 2018-12-21 + +PHP 7.0 - 7.1 - 7.2 - 7.3 release of memcached extension. Note that support for +libmemcached 0.x series has been discontinued and the oldest actively tested +version is 1.0.8. It is highly recommended to use version 1.0.18 of +libmemcached. + +Fixes + * Fix --disable-memcached-sasl and --disable-memcached-session replaced by --enable variants (#416) + + stable From 02e1e2ffd25fc0cc5e8b0507e83d28612128cc8c Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sat, 22 Dec 2018 07:54:42 -0800 Subject: [PATCH 221/345] Bump version to 3.1.2 --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index 3197d058..810b62ed 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.1.1" +#define PHP_MEMCACHED_VERSION "3.1.2" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 35292435e29795166b65bbb73653a957c9f91cee Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Sat, 22 Dec 2018 17:00:04 +0100 Subject: [PATCH 222/345] fix build warning (#417) --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 858d0aca..4deb5de8 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2752,7 +2752,7 @@ memcached_return s_stat_execute_cb (php_memcached_instance_st instance, const ch server_values = zend_hash_add(Z_ARRVAL_P(return_value), server_key, &zv); } - spprintf (&buffer, 0, "%.*s", value_length, value); + spprintf (&buffer, 0, "%.*s", (int)value_length, value); /* Check type */ if (s_long_value (buffer, &long_val)) { From c85d9029fbe525fb1cd113d22d61aba1eb9876bd Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 24 Dec 2018 13:16:42 -0800 Subject: [PATCH 223/345] Fix --disable-memcached-session by ifdef-ing session INI handler callbacks (#420) Resolves #396 --- php_memcached.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index 4deb5de8..930e1189 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -302,6 +302,7 @@ static PHP_INI_MH(OnUpdateSerializer) return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } +#ifdef HAVE_MEMCACHED_SESSION static PHP_INI_MH(OnUpdateDeprecatedLockValue) { @@ -342,6 +343,7 @@ PHP_INI_MH(OnUpdateConsistentHash) } return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } +#endif // HAVE_MEMCACHED_SESSION #define MEMC_INI_ENTRY(key, default_value, update_fn, gkey) \ STD_PHP_INI_ENTRY("memcached."key, default_value, PHP_INI_ALL, update_fn, memc.gkey, zend_php_memcached_globals, php_memcached_globals) From c76ec9e6ea3e15f239f71532025762a0217afb44 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 24 Dec 2018 13:38:57 -0800 Subject: [PATCH 224/345] Release notes for 3.1.2 and 3.1.3, fix dates for 3.1.x --- ChangeLog | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4a1748b3..e55dd8fd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,11 +1,21 @@ memcached extension changelog -Version 3.1.1 (2017-12-21) +Version 3.1.3 (2018-12-24) +-------------------------- + + * Fix --disable-memcached-session by ifdef-ing session INI handler callbacks (#396, #420) + +Version 3.1.2 (2018-12-22) +-------------------------- + + * Fix --enable-memcached-protocol was set to yes by default, reverted to no (#418) + +Version 3.1.1 (2018-12-21) -------------------------- * Fix --disable-memcached-sasl and --disable-memcached-session replaced by --enable variants (#416) -Version 3.1.0 (2017-12-21) +Version 3.1.0 (2018-12-21) -------------------------- New From 9cf95806225d79716db606ae9351b0c4043f6862 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 24 Dec 2018 13:40:29 -0800 Subject: [PATCH 225/345] Release notes for 3.1.3 --- package.xml | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/package.xml b/package.xml index 8f54da93..a801f856 100644 --- a/package.xml +++ b/package.xml @@ -27,9 +27,9 @@ http://pear.php.net/dtd/package-2.0.xsd"> aaron@serendipity.cx yes - 2018-12-22 + 2018-12-24 - 3.1.2 + 3.1.3 3.0.0 @@ -44,7 +44,7 @@ version is 1.0.8. It is highly recommended to use version 1.0.18 of libmemcached. Fixes - * Fix --enable-memcached-protocol was set to yes by default, reverted to no (#418) + * Fix --disable-memcached-session by ifdef-ing session INI handler callbacks (#396, #420) @@ -203,6 +203,26 @@ Fixes + + + stable + stable + + + 3.1.2 + 3.0.0 + + 2018-12-22 + +PHP 7.0 - 7.1 - 7.2 - 7.3 release of memcached extension. Note that support for +libmemcached 0.x series has been discontinued and the oldest actively tested +version is 1.0.8. It is highly recommended to use version 1.0.18 of +libmemcached. + +Fixes + * Fix --enable-memcached-protocol was set to yes by default, reverted to no (#418) + + stable From 3ba380c1290959f67fc0d00755c93918037ead71 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 24 Dec 2018 13:40:44 -0800 Subject: [PATCH 226/345] Bump version to 3.1.3 --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index 810b62ed..be1235e7 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.1.2" +#define PHP_MEMCACHED_VERSION "3.1.3" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 37f2cf98ae8000e54aab3c1be558d2dfc667304b Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Mon, 11 Mar 2019 17:39:57 -0400 Subject: [PATCH 227/345] Fix segfault for unknown memcache flags Set retval to false so that the resulting uninitialized zval won't be used. --- php_memcached.c | 1 + 1 file changed, 1 insertion(+) diff --git a/php_memcached.c b/php_memcached.c index 930e1189..85c79901 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3745,6 +3745,7 @@ zend_bool s_memcached_result_to_zval(memcached_st *memc, memcached_result_st *re default: php_error_docref(NULL, E_WARNING, "unknown payload type"); + retval = 0; break; } zend_string_release(data); From 455d7823b9d02c9cad442413de096baf98351ef7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20M?= Date: Thu, 11 Apr 2019 14:59:20 +0200 Subject: [PATCH 228/345] Supports PHP 7.3 Supported according to #408 --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 19a8ab18..c3ee51a1 100644 --- a/README.markdown +++ b/README.markdown @@ -23,7 +23,7 @@ Dependencies ------------ php-memcached 3.x: -* Supports PHP 7.0 - 7.2. +* Supports PHP 7.0 - 7.3. * Requires libmemcached 1.x or higher. * Optionally supports igbinary 2.0 or higher. * Optionally supports msgpack 2.0 or higher. From cd62e8f463132c166697d5ae5e0026a255be13ac Mon Sep 17 00:00:00 2001 From: Gerry Demaret Date: Tue, 21 May 2019 20:44:17 +0200 Subject: [PATCH 229/345] Update documented default for sess_lock_retries (#432) The documented default was 200, while in reality it seems this is actually set to 5. While 5 is arguably on the low side, at least have the documentation in sync with reality. --- memcached.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/memcached.ini b/memcached.ini index c2072324..5ed79bdb 100644 --- a/memcached.ini +++ b/memcached.ini @@ -15,8 +15,8 @@ ;memcached.sess_lock_wait_max = 150; ; The number of times to retry locking the session lock, not including the first attempt. -; Default is 200. -;memcached.sess_lock_retries = 200; +; Default is 5. +;memcached.sess_lock_retries = 5; ; The time, in seconds, before a lock should release itself. ; Setting to 0 results in the default behaviour, which is to From 7443d16d02fb73cdba2e90ae282446f80969229c Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Mon, 17 Jun 2019 16:04:47 +0100 Subject: [PATCH 230/345] Test on PHP 7.4 as well as 8.0 (#440) --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 5ce37750..22db51da 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,7 @@ dist: xenial language: php php: - master + - 7.4snapshot - 7.3 - 7.2 - 7.1 From 5d154be2864ce9b1572119e2416a874e73c0ccc5 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 3 Oct 2019 16:25:36 -0700 Subject: [PATCH 231/345] Remove stray instances of TSRMLS_CC macro This macro was defined empty in PHP 7.x, and removed in PHP 8.x. --- php_memcached_session.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php_memcached_session.c b/php_memcached_session.c index 6acd9d3e..ce9a46db 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -445,7 +445,7 @@ PS_READ_FUNC(memcached) *val = ZSTR_EMPTY_ALLOC(); return SUCCESS; } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "error getting session from memcached: %s", memcached_last_error_message(memc)); + php_error_docref(NULL, E_WARNING, "error getting session from memcached: %s", memcached_last_error_message(memc)); return FAILURE; } } @@ -475,7 +475,7 @@ PS_WRITE_FUNC(memcached) if (memcached_set(memc, key->val, key->len, val->val, val->len, expiration, 0) == MEMCACHED_SUCCESS) { return SUCCESS; } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "error saving session to memcached: %s", memcached_last_error_message(memc)); + php_error_docref(NULL, E_WARNING, "error saving session to memcached: %s", memcached_last_error_message(memc)); } } while (--retries > 0); From 26e38ccee6110a1491c5e36d297cdb12cb261a99 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 3 Oct 2019 16:46:23 -0700 Subject: [PATCH 232/345] Use temporary fork of igbinary for php-8 support --- .travis/travis.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index 81049355..090e3992 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -67,8 +67,9 @@ function install_libmemcached() { } function install_igbinary() { - git clone https://github.com/igbinary/igbinary.git + git clone https://github.com/sodabrew/igbinary.git pushd igbinary + git checkout php-8 phpize ./configure make From 77120444b4f24b51621aa3e9088e08349597c786 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sat, 5 Oct 2019 09:02:48 -0700 Subject: [PATCH 233/345] Revert "Use temporary fork of igbinary for php-8 support" Upstream accepted the patch for PHP master / PHP 8 support. This reverts commit 26e38ccee6110a1491c5e36d297cdb12cb261a99. --- .travis/travis.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis/travis.sh b/.travis/travis.sh index 090e3992..81049355 100755 --- a/.travis/travis.sh +++ b/.travis/travis.sh @@ -67,9 +67,8 @@ function install_libmemcached() { } function install_igbinary() { - git clone https://github.com/sodabrew/igbinary.git + git clone https://github.com/igbinary/igbinary.git pushd igbinary - git checkout php-8 phpize ./configure make From 0ee62bd55d85ae1495ca87c096cde061df8df00a Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sat, 5 Oct 2019 09:32:26 -0700 Subject: [PATCH 234/345] Release notes for 3.1.4 --- ChangeLog | 8 ++++++++ README.markdown | 2 +- package.xml | 31 +++++++++++++++++++++++++++---- 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index e55dd8fd..05060cb7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ memcached extension changelog +Version 3.1.4 (2019-10-06) +-------------------------- + + * Test on PHP 7.4 as well as 8.0 (#440) + * Fix segfault for unknown memcached flags (#431) + * Update documented defaults for sess_lock_retries( #432) + * Remove stray instances of the TSRMLS_CC macro for PHP 8 compatibility (#444) + Version 3.1.3 (2018-12-24) -------------------------- diff --git a/README.markdown b/README.markdown index c3ee51a1..31f57b16 100644 --- a/README.markdown +++ b/README.markdown @@ -23,7 +23,7 @@ Dependencies ------------ php-memcached 3.x: -* Supports PHP 7.0 - 7.3. +* Supports PHP 7.0 - 7.4. * Requires libmemcached 1.x or higher. * Optionally supports igbinary 2.0 or higher. * Optionally supports msgpack 2.0 or higher. diff --git a/package.xml b/package.xml index a801f856..0cbc9f63 100644 --- a/package.xml +++ b/package.xml @@ -27,9 +27,9 @@ http://pear.php.net/dtd/package-2.0.xsd"> aaron@serendipity.cx yes - 2018-12-24 + 2019-10-06 - 3.1.3 + 3.1.4 3.0.0 @@ -38,13 +38,16 @@ http://pear.php.net/dtd/package-2.0.xsd"> PHP -PHP 7.0 - 7.1 - 7.2 - 7.3 release of memcached extension. Note that support for +PHP 7.0 - 7.1 - 7.2 - 7.3 - 7.4 release of memcached extension. Note that support for libmemcached 0.x series has been discontinued and the oldest actively tested version is 1.0.8. It is highly recommended to use version 1.0.18 of libmemcached. Fixes - * Fix --disable-memcached-session by ifdef-ing session INI handler callbacks (#396, #420) + * Test on PHP 7.4 as well as 8.0 (#440) + * Fix segfault for unknown memcached flags (#431) + * Update documented defaults for sess_lock_retries( #432) + * Remove stray instances of the TSRMLS_CC macro for PHP 8 compatibility (#444) @@ -203,6 +206,26 @@ Fixes + + + stable + stable + + + 3.1.3 + 3.0.0 + + 2018-12-22 + +PHP 7.0 - 7.1 - 7.2 - 7.3 release of memcached extension. Note that support for +libmemcached 0.x series has been discontinued and the oldest actively tested +version is 1.0.8. It is highly recommended to use version 1.0.18 of +libmemcached. + +Fixes + * Fix --disable-memcached-session by ifdef-ing session INI handler callbacks (#396, #420) + + stable From 5fd997fc68674a192db19c32c4c46aa201fff215 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 6 Oct 2019 09:01:37 -0700 Subject: [PATCH 235/345] Bump version to 3.1.4 --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index be1235e7..71e3acef 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.1.3" +#define PHP_MEMCACHED_VERSION "3.1.4" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 03f034f63ea8224cf0072f9bcf3fd9c7b6141290 Mon Sep 17 00:00:00 2001 From: Po-Chuan Hsieh Date: Tue, 19 Nov 2019 02:01:10 +0800 Subject: [PATCH 236/345] Fix build with PHP 7.4 (#445) Build error on FreeBSD with PHP 7.4 RC6: --- php_memcached.lo --- /wrkdirs/usr/ports/databases/pecl-memcached/work-php74/memcached-3.1.4/php_memcached.c:3237:7: error: expected ';' after expression ulong key_index; ^ ; /wrkdirs/usr/ports/databases/pecl-memcached/work-php74/memcached-3.1.4/php_memcached.c:3237:2: error: use of undeclared identifier 'ulong' ulong key_index; ^ /wrkdirs/usr/ports/databases/pecl-memcached/work-php74/memcached-3.1.4/php_memcached.c:3237:8: error: use of undeclared identifier 'key_index' ulong key_index; ^ /wrkdirs/usr/ports/databases/pecl-memcached/work-php74/memcached-3.1.4/php_memcached.c:3250:49: error: use of undeclared identifier 'key_index' ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(options), key_index, key, value) { ^ /wrkdirs/usr/ports/databases/pecl-memcached/work-php74/memcached-3.1.4/php_memcached.c:3255:44: error: use of undeclared identifier 'key_index' if (!php_memc_set_option(intern, (long) key_index, value)) { ^ 5 errors generated. *** [php_memcached.lo] Error code 1 --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 85c79901..50636952 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3234,7 +3234,7 @@ static PHP_METHOD(Memcached, setOptions) zval *options; zend_bool ok = 1; zend_string *key; - ulong key_index; + zend_ulong key_index; zval *value; MEMC_METHOD_INIT_VARS; From 7141624896470d28492a6f39c844f57ea57cbf1f Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 6 Oct 2019 09:04:40 -0700 Subject: [PATCH 237/345] Fix typo --- package.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.xml b/package.xml index 0cbc9f63..4cf8d3ee 100644 --- a/package.xml +++ b/package.xml @@ -46,7 +46,7 @@ libmemcached. Fixes * Test on PHP 7.4 as well as 8.0 (#440) * Fix segfault for unknown memcached flags (#431) - * Update documented defaults for sess_lock_retries( #432) + * Update documented defaults for sess_lock_retries (#432) * Remove stray instances of the TSRMLS_CC macro for PHP 8 compatibility (#444) From d7daff649406efbd43af3253212b1cb946ff3f85 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 3 Dec 2019 13:56:22 -0800 Subject: [PATCH 238/345] Bump version and release notes for 3.1.5 --- ChangeLog | 5 +++++ package.xml | 32 ++++++++++++++++++++++++++------ php_memcached.h | 2 +- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 05060cb7..31994e3b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ memcached extension changelog +Version 3.1.5 (2019-12-03) +-------------------------- + + * Fix build with PHP 7.4 release due to ulong typedef removal (#445) + Version 3.1.4 (2019-10-06) -------------------------- diff --git a/package.xml b/package.xml index 4cf8d3ee..c5588a3f 100644 --- a/package.xml +++ b/package.xml @@ -27,9 +27,9 @@ http://pear.php.net/dtd/package-2.0.xsd"> aaron@serendipity.cx yes - 2019-10-06 + 2019-12-03 - 3.1.4 + 3.1.5 3.0.0 @@ -44,10 +44,7 @@ version is 1.0.8. It is highly recommended to use version 1.0.18 of libmemcached. Fixes - * Test on PHP 7.4 as well as 8.0 (#440) - * Fix segfault for unknown memcached flags (#431) - * Update documented defaults for sess_lock_retries (#432) - * Remove stray instances of the TSRMLS_CC macro for PHP 8 compatibility (#444) + * Fix build with PHP 7.4 release due to ulong typedef removal (#445) @@ -206,6 +203,29 @@ Fixes + + + stable + stable + + + 3.1.4 + 3.0.0 + + 2019-10-06 + +PHP 7.0 - 7.1 - 7.2 - 7.3 - 7.4 release of memcached extension. Note that support for +libmemcached 0.x series has been discontinued and the oldest actively tested +version is 1.0.8. It is highly recommended to use version 1.0.18 of +libmemcached. + +Fixes + * Test on PHP 7.4 as well as 8.0 (#440) + * Fix segfault for unknown memcached flags (#431) + * Update documented defaults for sess_lock_retries (#432) + * Remove stray instances of the TSRMLS_CC macro for PHP 8 compatibility (#444) + + stable diff --git a/php_memcached.h b/php_memcached.h index 71e3acef..cccb6d47 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.1.4" +#define PHP_MEMCACHED_VERSION "3.1.5" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From ed3f39d07e08517e68acdbf57304da1328d7adac Mon Sep 17 00:00:00 2001 From: Julien Boulen Date: Wed, 11 Mar 2020 12:00:43 +0100 Subject: [PATCH 239/345] Fix memcached.ini comment - use new config name not the old one (#455) --- memcached.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/memcached.ini b/memcached.ini index 5ed79bdb..35548f32 100644 --- a/memcached.ini +++ b/memcached.ini @@ -60,7 +60,7 @@ ; Write data to a number of additional memcached servers ; This is "poor man's HA" as libmemcached calls it. -; If this value is positive and sess_remove_failed is enabled +; If this value is positive and sess_remove_failed_servers is enabled ; when a memcached server fails the session will continue to be available ; from a replica. However, if the failed memcache server ; becomes available again it will read the session from there From 2d43ce8c92c08f4576e57ad88c8521f85e90cd94 Mon Sep 17 00:00:00 2001 From: Jon Desrosiers Date: Tue, 29 Sep 2020 14:16:48 -0400 Subject: [PATCH 240/345] PHP 7.4 is no longer in "snapshot". (#460) --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 22db51da..7d6b57d7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ dist: xenial language: php php: - master - - 7.4snapshot + - 7.4 - 7.3 - 7.2 - 7.1 @@ -34,5 +34,5 @@ script: - ./.travis/travis.sh script $LIBMEMCACHED_VERSION cache: - directories: + directories: - $HOME/cache From c94e014da53cc8a3d0510402f36bc6e5e17bf608 Mon Sep 17 00:00:00 2001 From: Dmitriy Date: Fri, 2 Oct 2020 19:34:31 +0300 Subject: [PATCH 241/345] fix php 8.0 build (#461) fci.no_separation removed on php 8.0. https://github.com/php/php-src/commit/302933daea77663f5759b10accd1d0231393b24c --- php_memcached_server.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/php_memcached_server.c b/php_memcached_server.c index 4c0080e8..870209c1 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -63,7 +63,9 @@ long s_invoke_php_callback (php_memc_server_cb_t *cb, zval *params, ssize_t para cb->fci.retval = retval; cb->fci.params = params; cb->fci.param_count = param_count; +#if PHP_VERSION_ID < 80000 cb->fci.no_separation = 1; +#endif if (zend_call_function(&(cb->fci), &(cb->fci_cache)) == FAILURE) { char *buf = php_memc_printable_func(&(cb->fci), &(cb->fci_cache)); From e8f53777d3f578586f2a32f1b3bdcc3f53e74b39 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 8 Oct 2020 11:58:43 +0200 Subject: [PATCH 242/345] generate arginfo from stub for PHP 7 and 8 --- php_memcached.c | 404 +------------------------------- php_memcached.stub.php | 94 ++++++++ php_memcached_arginfo.h | 411 +++++++++++++++++++++++++++++++++ php_memcached_legacy_arginfo.h | 407 ++++++++++++++++++++++++++++++++ tests/bad_construct.phpt | 5 +- tests/bad_construct_8.phpt | 34 +++ tests/expire.phpt | 1 + tests/undefined_set.phpt | 10 +- tests/vbucket.phpt | 20 -- tests/vbucket_error_7.phpt | 40 ++++ tests/vbucket_error_8.phpt | 41 ++++ 11 files changed, 1044 insertions(+), 423 deletions(-) create mode 100644 php_memcached.stub.php create mode 100644 php_memcached_arginfo.h create mode 100644 php_memcached_legacy_arginfo.h create mode 100644 tests/bad_construct_8.phpt create mode 100644 tests/vbucket_error_7.phpt create mode 100644 tests/vbucket_error_8.phpt diff --git a/php_memcached.c b/php_memcached.c index 50636952..147cb4ab 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1853,7 +1853,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke { zval *entries; zend_string *server_key = NULL; - zend_long expiration = 0, ignored; + zend_long expiration = 0; zval *value; zend_string *skey; zend_ulong num_key; @@ -1867,7 +1867,6 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke Z_PARAM_ARRAY(entries) Z_PARAM_OPTIONAL Z_PARAM_LONG(expiration) - Z_PARAM_LONG(ignored) ZEND_PARSE_PARAMETERS_END(); } else { /* "a|ll" */ @@ -1875,7 +1874,6 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke Z_PARAM_ARRAY(entries) Z_PARAM_OPTIONAL Z_PARAM_LONG(expiration) - Z_PARAM_LONG(ignored) ZEND_PARSE_PARAMETERS_END(); } @@ -2071,7 +2069,6 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) zend_string *server_key = NULL; zval *value; zend_long expiration = 0; - zend_long ignored; zend_string *payload; uint32_t flags = 0; memcached_return status; @@ -2086,7 +2083,6 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) Z_PARAM_ZVAL(value) Z_PARAM_OPTIONAL Z_PARAM_LONG(expiration) - Z_PARAM_LONG(ignored) ZEND_PARSE_PARAMETERS_END(); } else { /* "zSz|ll" */ @@ -2096,7 +2092,6 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) Z_PARAM_ZVAL(value) Z_PARAM_OPTIONAL Z_PARAM_LONG(expiration) - Z_PARAM_LONG(ignored) ZEND_PARSE_PARAMETERS_END(); } @@ -3862,395 +3857,10 @@ PHP_METHOD(MemcachedServer, on) #endif -/* {{{ methods arginfo */ -ZEND_BEGIN_ARG_INFO_EX(arginfo___construct, 0, 0, 0) - ZEND_ARG_INFO(0, persistent_id) - ZEND_ARG_INFO(0, callback) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_getResultCode, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_getResultMessage, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_get, 0, 0, 1) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, cache_cb) - ZEND_ARG_INFO(0, get_flags) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_getByKey, 0, 0, 2) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, cache_cb) - ZEND_ARG_INFO(0, get_flags) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_getMulti, 0, 0, 1) - ZEND_ARG_ARRAY_INFO(0, keys, 0) - ZEND_ARG_INFO(0, get_flags) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_getMultiByKey, 0, 0, 2) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_ARRAY_INFO(0, keys, 0) - ZEND_ARG_INFO(0, get_flags) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_getDelayed, 0, 0, 1) - ZEND_ARG_ARRAY_INFO(0, keys, 0) - ZEND_ARG_INFO(0, with_cas) - ZEND_ARG_INFO(0, value_cb) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_getDelayedByKey, 0, 0, 2) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_ARRAY_INFO(0, keys, 0) - ZEND_ARG_INFO(0, with_cas) - ZEND_ARG_INFO(0, value_cb) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_fetch, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_fetchAll, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_set, 0, 0, 2) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, expiration) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_setByKey, 0, 0, 3) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, expiration) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_touch, 0, 0, 2) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, expiration) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_touchByKey, 0, 0, 3) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, expiration) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_setMulti, 0, 0, 1) - ZEND_ARG_ARRAY_INFO(0, items, 0) - ZEND_ARG_INFO(0, expiration) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_setMultiByKey, 0, 0, 2) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_ARRAY_INFO(0, items, 0) - ZEND_ARG_INFO(0, expiration) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_add, 0, 0, 2) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, expiration) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_addByKey, 0, 0, 3) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, expiration) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_replace, 0, 0, 2) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, expiration) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_replaceByKey, 0, 0, 3) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, expiration) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_append, 0, 0, 2) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, value) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_appendByKey, 0, 0, 3) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, value) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_prepend, 0, 0, 2) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, value) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_prependByKey, 0, 0, 3) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, value) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_cas, 0, 0, 3) - ZEND_ARG_INFO(0, cas_token) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, expiration) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_casByKey, 0, 0, 4) - ZEND_ARG_INFO(0, cas_token) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, expiration) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_delete, 0, 0, 1) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, time) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_deleteMulti, 0, 0, 1) - ZEND_ARG_INFO(0, keys) - ZEND_ARG_INFO(0, time) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_deleteByKey, 0, 0, 2) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, time) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_deleteMultiByKey, 0, 0, 2) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_INFO(0, keys) - ZEND_ARG_INFO(0, time) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_increment, 0, 0, 1) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, offset) - ZEND_ARG_INFO(0, initial_value) - ZEND_ARG_INFO(0, expiry) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_decrement, 0, 0, 1) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, offset) - ZEND_ARG_INFO(0, initial_value) - ZEND_ARG_INFO(0, expiry) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_incrementByKey, 0, 0, 2) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, offset) - ZEND_ARG_INFO(0, initial_value) - ZEND_ARG_INFO(0, expiry) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_decrementByKey, 0, 0, 2) - ZEND_ARG_INFO(0, server_key) - ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, offset) - ZEND_ARG_INFO(0, initial_value) - ZEND_ARG_INFO(0, expiry) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_flush, 0, 0, 0) - ZEND_ARG_INFO(0, delay) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_addServer, 0, 0, 2) - ZEND_ARG_INFO(0, host) - ZEND_ARG_INFO(0, port) - ZEND_ARG_INFO(0, weight) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_getStats, 0, 0, 0) - ZEND_ARG_INFO(0, type) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_addServers, 0) - ZEND_ARG_ARRAY_INFO(0, servers, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_getServerList, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_resetServerList, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_quit, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_flushBuffers, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_getServerByKey, 0) - ZEND_ARG_INFO(0, server_key) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_getLastErrorMessage, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_getLastErrorCode, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_getLastErrorErrno, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_getLastDisconnectedServer, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_getOption, 0) - ZEND_ARG_INFO(0, option) -ZEND_END_ARG_INFO() - -#ifdef HAVE_MEMCACHED_SASL -ZEND_BEGIN_ARG_INFO(arginfo_setSaslAuthData, 0) - ZEND_ARG_INFO(0, username) - ZEND_ARG_INFO(0, password) -ZEND_END_ARG_INFO() -#endif - -#ifdef HAVE_MEMCACHED_SET_ENCODING_KEY -ZEND_BEGIN_ARG_INFO(arginfo_setEncodingKey, 0) - ZEND_ARG_INFO(0, key) -ZEND_END_ARG_INFO() -#endif - -ZEND_BEGIN_ARG_INFO(arginfo_setOption, 0) - ZEND_ARG_INFO(0, option) - ZEND_ARG_INFO(0, value) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_setOptions, 0) - ZEND_ARG_INFO(0, options) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_setBucket, 3) - ZEND_ARG_INFO(0, host_map) - ZEND_ARG_INFO(0, forward_map) - ZEND_ARG_INFO(0, replicas) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_getVersion, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_isPersistent, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_isPristine, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_getAllKeys, 0) -ZEND_END_ARG_INFO() -/* }}} */ - -/* {{{ memcached_class_methods */ -#define MEMC_ME(name, args) PHP_ME(Memcached, name, args, ZEND_ACC_PUBLIC) -static zend_function_entry memcached_class_methods[] = { - MEMC_ME(__construct, arginfo___construct) - - MEMC_ME(getResultCode, arginfo_getResultCode) - MEMC_ME(getResultMessage, arginfo_getResultMessage) - - MEMC_ME(get, arginfo_get) - MEMC_ME(getByKey, arginfo_getByKey) - MEMC_ME(getMulti, arginfo_getMulti) - MEMC_ME(getMultiByKey, arginfo_getMultiByKey) - MEMC_ME(getDelayed, arginfo_getDelayed) - MEMC_ME(getDelayedByKey, arginfo_getDelayedByKey) - MEMC_ME(fetch, arginfo_fetch) - MEMC_ME(fetchAll, arginfo_fetchAll) - - MEMC_ME(set, arginfo_set) - MEMC_ME(setByKey, arginfo_setByKey) - - MEMC_ME(touch, arginfo_touch) - MEMC_ME(touchByKey, arginfo_touchByKey) - - MEMC_ME(setMulti, arginfo_setMulti) - MEMC_ME(setMultiByKey, arginfo_setMultiByKey) - - MEMC_ME(cas, arginfo_cas) - MEMC_ME(casByKey, arginfo_casByKey) - MEMC_ME(add, arginfo_add) - MEMC_ME(addByKey, arginfo_addByKey) - MEMC_ME(append, arginfo_append) - MEMC_ME(appendByKey, arginfo_appendByKey) - MEMC_ME(prepend, arginfo_prepend) - MEMC_ME(prependByKey, arginfo_prependByKey) - MEMC_ME(replace, arginfo_replace) - MEMC_ME(replaceByKey, arginfo_replaceByKey) - MEMC_ME(delete, arginfo_delete) - MEMC_ME(deleteMulti, arginfo_deleteMulti) - MEMC_ME(deleteByKey, arginfo_deleteByKey) - MEMC_ME(deleteMultiByKey, arginfo_deleteMultiByKey) - - MEMC_ME(increment, arginfo_increment) - MEMC_ME(decrement, arginfo_decrement) - MEMC_ME(incrementByKey, arginfo_incrementByKey) - MEMC_ME(decrementByKey, arginfo_decrementByKey) - - MEMC_ME(addServer, arginfo_addServer) - MEMC_ME(addServers, arginfo_addServers) - MEMC_ME(getServerList, arginfo_getServerList) - MEMC_ME(getServerByKey, arginfo_getServerByKey) - MEMC_ME(resetServerList, arginfo_resetServerList) - MEMC_ME(quit, arginfo_quit) - MEMC_ME(flushBuffers, arginfo_flushBuffers) - - MEMC_ME(getLastErrorMessage, arginfo_getLastErrorMessage) - MEMC_ME(getLastErrorCode, arginfo_getLastErrorCode) - MEMC_ME(getLastErrorErrno, arginfo_getLastErrorErrno) - MEMC_ME(getLastDisconnectedServer, arginfo_getLastDisconnectedServer) - - MEMC_ME(getStats, arginfo_getStats) - MEMC_ME(getVersion, arginfo_getVersion) - MEMC_ME(getAllKeys, arginfo_getAllKeys) - - MEMC_ME(flush, arginfo_flush) - - MEMC_ME(getOption, arginfo_getOption) - MEMC_ME(setOption, arginfo_setOption) - MEMC_ME(setOptions, arginfo_setOptions) - MEMC_ME(setBucket, arginfo_setBucket) -#ifdef HAVE_MEMCACHED_SASL - MEMC_ME(setSaslAuthData, arginfo_setSaslAuthData) -#endif -#ifdef HAVE_MEMCACHED_SET_ENCODING_KEY - MEMC_ME(setEncodingKey, arginfo_setEncodingKey) -#endif - MEMC_ME(isPersistent, arginfo_isPersistent) - MEMC_ME(isPristine, arginfo_isPristine) - { NULL, NULL, NULL } -}; -#undef MEMC_ME -/* }}} */ - -#ifdef HAVE_MEMCACHED_PROTOCOL -/* {{{ */ -#define MEMC_SE_ME(name, args) PHP_ME(MemcachedServer, name, args, ZEND_ACC_PUBLIC) -static -zend_function_entry memcached_server_class_methods[] = { - MEMC_SE_ME(run, NULL) - MEMC_SE_ME(on, NULL) - { NULL, NULL, NULL } -}; -#undef MEMC_SE_ME -/* }}} */ +#if PHP_VERSION_ID < 80000 +#include "php_memcached_legacy_arginfo.h" +#else +#include "php_memcached_arginfo.h" #endif /* {{{ memcached_module_entry @@ -4592,7 +4202,7 @@ PHP_MINIT_FUNCTION(memcached) le_memc = zend_register_list_destructors_ex(NULL, php_memc_dtor, "Memcached persistent connection", module_number); - INIT_CLASS_ENTRY(ce, "Memcached", memcached_class_methods); + INIT_CLASS_ENTRY(ce, "Memcached", class_Memcached_methods); memcached_ce = zend_register_internal_class(&ce); memcached_ce->create_object = php_memc_object_new; @@ -4602,7 +4212,7 @@ PHP_MINIT_FUNCTION(memcached) memcached_server_object_handlers.clone_obj = NULL; memcached_server_object_handlers.free_obj = php_memc_server_free_storage; - INIT_CLASS_ENTRY(ce, "MemcachedServer", memcached_server_class_methods); + INIT_CLASS_ENTRY(ce, "MemcachedServer", class_MemcachedServer_methods); memcached_server_ce = zend_register_internal_class(&ce); memcached_server_ce->create_object = php_memc_server_new; #endif diff --git a/php_memcached.stub.php b/php_memcached.stub.php new file mode 100644 index 00000000..4ba6d5b6 --- /dev/null +++ b/php_memcached.stub.php @@ -0,0 +1,94 @@ + += 80000) die("skip PHP 7 only"); +?> --FILE-- +--FILE-- +getMessage() . PHP_EOL; +} + +class extended extends Memcached { + public function __construct () { + } +} + +error_reporting(E_ALL); +$extended = new extended (); +var_dump ($extended->setOption (Memcached::OPT_BINARY_PROTOCOL, true)); + +echo "OK" . PHP_EOL; + +--EXPECTF-- +Memcached::__construct(): Argument #1 ($persistent_id) must be of type ?string, stdClass given + +Warning: Memcached::setOption(): Memcached constructor was not called in %s +NULL +OK + diff --git a/tests/expire.phpt b/tests/expire.phpt index eac02408..4fb49c55 100644 --- a/tests/expire.phpt +++ b/tests/expire.phpt @@ -7,6 +7,7 @@ https://code.google.com/p/memcached/issues/detail?id=275 $min_version = "1.4.8"; include dirname(__FILE__) . "/skipif.inc"; if (!method_exists("memcached", "touch")) die ("skip memcached::touch is not available"); +if (getenv("SKIP_SLOW_TESTS")) die('skip slow test'); ?> --FILE-- set($key, $value, $no_time); var_dump($rv); ?> --EXPECTF-- -Notice: Undefined variable: no_key in %s +%s: Undefined variable%sno_key in %s bool(false) -Notice: Undefined variable: no_value in %s +%s: Undefined variable%sno_value in %s bool(true) -Notice: Undefined variable: no_key in %s +%s: Undefined variable%sno_key in %s -Notice: Undefined variable: no_value in %s +%s: Undefined variable%sno_value in %s bool(false) -Notice: Undefined variable: no_time in %s +%s: Undefined variable%sno_time in %s bool(true) diff --git a/tests/vbucket.phpt b/tests/vbucket.phpt index f17eb94a..a691680d 100644 --- a/tests/vbucket.phpt +++ b/tests/vbucket.phpt @@ -18,14 +18,6 @@ var_dump ($m->setBucket (array (1,2,2), array (1,2,2), 2)); var_dump ($m->setBucket (array ('a', 'b', 'c'), null, 2)); -var_dump ($m->setBucket (array (), null, 2)); - -var_dump ($m->setBucket (array (), array (), -1)); - -var_dump ($m->setBucket (null, array (), -1)); - -var_dump ($m->setBucket (array (-1), array (-1), 1)); - echo "OK\n"; ?> @@ -33,16 +25,4 @@ echo "OK\n"; bool(true) bool(true) bool(true) - -Warning: Memcached::setBucket(): server map cannot be empty in %s on line %d -bool(false) - -Warning: Memcached::setBucket(): server map cannot be empty in %s on line %d -bool(false) - -Warning: Memcached::setBucket() expects parameter 1 to be array, null given in %s on line %d -NULL - -Warning: Memcached::setBucket(): the map must contain positive integers in %s on line %d -bool(false) OK diff --git a/tests/vbucket_error_7.phpt b/tests/vbucket_error_7.phpt new file mode 100644 index 00000000..286534af --- /dev/null +++ b/tests/vbucket_error_7.phpt @@ -0,0 +1,40 @@ +--TEST-- +Memcached virtual buckets +--SKIPIF-- += 80000) die("skip PHP 7 only"); +?> +--FILE-- + Memcached::DISTRIBUTION_VIRTUAL_BUCKET + )); + +var_dump ($m->setBucket (array (), null, 2)); + +var_dump ($m->setBucket (array (), array (), -1)); + +var_dump ($m->setBucket (null, array (), -1)); + +var_dump ($m->setBucket (array (-1), array (-1), 1)); + +echo "OK\n"; + +?> +--EXPECTF-- + +Warning: Memcached::setBucket(): server map cannot be empty in %s on line %d +bool(false) + +Warning: Memcached::setBucket(): server map cannot be empty in %s on line %d +bool(false) + +Warning: Memcached::setBucket() expects parameter 1 to be array, null given in %s on line %d +NULL + +Warning: Memcached::setBucket(): the map must contain positive integers in %s on line %d +bool(false) +OK diff --git a/tests/vbucket_error_8.phpt b/tests/vbucket_error_8.phpt new file mode 100644 index 00000000..c8af2315 --- /dev/null +++ b/tests/vbucket_error_8.phpt @@ -0,0 +1,41 @@ +--TEST-- +Memcached virtual buckets +--SKIPIF-- + +--FILE-- + Memcached::DISTRIBUTION_VIRTUAL_BUCKET + )); + +var_dump ($m->setBucket (array (), null, 2)); + +var_dump ($m->setBucket (array (), array (), -1)); + +try { + var_dump ($m->setBucket (null, array (), -1)); +} catch (TypeError $e) { + echo $e->getMessage() . PHP_EOL; +} + +var_dump ($m->setBucket (array (-1), array (-1), 1)); + +echo "OK\n"; + +?> +--EXPECTF-- +Warning: Memcached::setBucket(): server map cannot be empty in %s on line %d +bool(false) + +Warning: Memcached::setBucket(): server map cannot be empty in %s on line %d +bool(false) +Memcached::setBucket(): Argument #1 ($host_map) must be of type array, null given + +Warning: Memcached::setBucket(): the map must contain positive integers in %s on line %d +bool(false) +OK From 18945f9b5867e3c4c7016ded29801da7337301ec Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 8 Oct 2020 12:37:20 +0200 Subject: [PATCH 243/345] add new file to pecl archive --- package.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/package.xml b/package.xml index c5588a3f..ec44bd1b 100644 --- a/package.xml +++ b/package.xml @@ -59,6 +59,9 @@ Fixes + + + @@ -133,10 +136,13 @@ Fixes + + + From baa6bfda6fbf4c1c75b5a7492db4cc40e6aa81f3 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 8 Oct 2020 13:45:49 +0200 Subject: [PATCH 244/345] cleanup HAVE_SPL, removed in 8 as always there --- php_memcached.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 147cb4ab..8d9040ec 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -55,6 +55,8 @@ # include "ext/msgpack/php_msgpack.h" #endif +# include "ext/spl/spl_exceptions.h" + static int le_memc; static int php_memc_list_entry(void) { @@ -251,10 +253,6 @@ static zend_class_entry *memcached_ce = NULL; static zend_class_entry *memcached_exception_ce = NULL; static zend_object_handlers memcached_object_handlers; -#ifdef HAVE_SPL -static zend_class_entry *spl_ce_RuntimeException = NULL; -#endif - ZEND_DECLARE_MODULE_GLOBALS(php_memcached) #ifdef COMPILE_DL_MEMCACHED @@ -3764,7 +3762,6 @@ zend_class_entry *php_memc_get_exception(void) PHP_MEMCACHED_API zend_class_entry *php_memc_get_exception_base(int root) { -#ifdef HAVE_SPL if (!root) { if (!spl_ce_RuntimeException) { zend_class_entry *pce; @@ -3781,7 +3778,7 @@ zend_class_entry *php_memc_get_exception_base(int root) return spl_ce_RuntimeException; } } -#endif + return zend_exception_get_default(); } @@ -3877,10 +3874,8 @@ static const zend_module_dep memcached_deps[] = { #ifdef HAVE_MEMCACHED_MSGPACK ZEND_MOD_REQUIRED("msgpack") #endif -#ifdef HAVE_SPL ZEND_MOD_REQUIRED("spl") -#endif - {NULL, NULL, NULL} + ZEND_MOD_END }; #endif From 38ad2e0b0923230472118f97b3471529ee2353b2 Mon Sep 17 00:00:00 2001 From: Julien Boulen Date: Fri, 9 Oct 2020 11:52:03 +0200 Subject: [PATCH 245/345] Fix memcached.ini comment - remove reference to old config name (#456) Co-authored-by: julien --- memcached.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/memcached.ini b/memcached.ini index 35548f32..c11db719 100644 --- a/memcached.ini +++ b/memcached.ini @@ -85,7 +85,6 @@ ; Session SASL username ; Both username and password need to be set for SASL to be enabled -; In addition to this memcached.use_sasl needs to be on ;memcached.sess_sasl_username = NULL ; Session SASL password From a452d9a1e59ae0bc58174d7bd8101ee440d4aa1d Mon Sep 17 00:00:00 2001 From: hulk Date: Fri, 9 Oct 2020 02:53:09 -0700 Subject: [PATCH 246/345] MOD: don't re-set the libmemcached option if not modified (#451) libmemcached would close all connections if the option(like MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) was set, even though value wasn't modified. --- php_memcached.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index 8d9040ec..4389fd2f 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3104,6 +3104,11 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) lval = zval_get_long(value); if (flag < MEMCACHED_BEHAVIOR_MAX) { + // don't reset the option when the option value wasn't modified, + // while the libmemcached may shutdown all connections. + if (memcached_behavior_get(intern->memc, flag) == (uint64_t)lval) { + return 1; + } rc = memcached_behavior_set(intern->memc, flag, (uint64_t)lval); } else { From 7120d80cb9dc69a58c552ce44304c1e2f0eeaee3 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 9 Oct 2020 03:23:41 -0700 Subject: [PATCH 247/345] Set TCP_NODELAY when setting binary protocol (#421) * Set TCP_NODELAY when setting binary protocol * Add braces to the check_set_behavior macro --- php_memcached.c | 5 +++++ php_memcached_session.c | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 4389fd2f..85799730 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1286,6 +1286,11 @@ static PHP_METHOD(Memcached, __construct) if (rc != MEMCACHED_SUCCESS) { php_error_docref(NULL, E_WARNING, "Failed to turn on binary protocol: %s", memcached_strerror(intern->memc, rc)); } + /* Also enable TCP_NODELAY when binary protocol is enabled */ + rc = memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, 1); + if (rc != MEMCACHED_SUCCESS) { + php_error_docref(NULL, E_WARNING, "Failed to set TCP_NODELAY: %s", memcached_strerror(intern->memc, rc)); + } } if (MEMC_G(default_behavior.connect_timeout)) { diff --git a/php_memcached_session.c b/php_memcached_session.c index ce9a46db..e509cb84 100644 --- a/php_memcached_session.c +++ b/php_memcached_session.c @@ -178,7 +178,9 @@ void s_unlock_session(memcached_st *memc) static zend_bool s_configure_from_ini_values(memcached_st *memc, zend_bool silent) { +/* This macro looks like a function but returns errors directly */ #define check_set_behavior(behavior, value) \ +{ \ int b = (behavior); \ uint64_t v = (value); \ if (v != memcached_behavior_get(memc, b)) { \ @@ -189,10 +191,13 @@ zend_bool s_configure_from_ini_values(memcached_st *memc, zend_bool silent) } \ return 0; \ } \ - } + } \ +} if (MEMC_SESS_INI(binary_protocol_enabled)) { check_set_behavior(MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1); + /* Also enable TCP_NODELAY when binary protocol is enabled */ + check_set_behavior(MEMCACHED_BEHAVIOR_TCP_NODELAY, 1); } if (MEMC_SESS_INI(consistent_hash_enabled)) { From f97b2e3ad95bbd83c862abba08c34ac3f4acc497 Mon Sep 17 00:00:00 2001 From: SpencerMalone Date: Fri, 9 Oct 2020 04:49:58 -0700 Subject: [PATCH 248/345] Include a fuller list of response constants from libmemcached (#457) --- php_memcached.c | 69 +++++++++++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 85799730..d49b7d57 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -4073,34 +4073,47 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) * libmemcached result codes */ - REGISTER_MEMC_CLASS_CONST_LONG(RES_SUCCESS, MEMCACHED_SUCCESS); - REGISTER_MEMC_CLASS_CONST_LONG(RES_FAILURE, MEMCACHED_FAILURE); - REGISTER_MEMC_CLASS_CONST_LONG(RES_HOST_LOOKUP_FAILURE, MEMCACHED_HOST_LOOKUP_FAILURE); - REGISTER_MEMC_CLASS_CONST_LONG(RES_UNKNOWN_READ_FAILURE, MEMCACHED_UNKNOWN_READ_FAILURE); - REGISTER_MEMC_CLASS_CONST_LONG(RES_PROTOCOL_ERROR, MEMCACHED_PROTOCOL_ERROR); - REGISTER_MEMC_CLASS_CONST_LONG(RES_CLIENT_ERROR, MEMCACHED_CLIENT_ERROR); - REGISTER_MEMC_CLASS_CONST_LONG(RES_SERVER_ERROR, MEMCACHED_SERVER_ERROR); - REGISTER_MEMC_CLASS_CONST_LONG(RES_WRITE_FAILURE, MEMCACHED_WRITE_FAILURE); - REGISTER_MEMC_CLASS_CONST_LONG(RES_DATA_EXISTS, MEMCACHED_DATA_EXISTS); - REGISTER_MEMC_CLASS_CONST_LONG(RES_NOTSTORED, MEMCACHED_NOTSTORED); - REGISTER_MEMC_CLASS_CONST_LONG(RES_NOTFOUND, MEMCACHED_NOTFOUND); - REGISTER_MEMC_CLASS_CONST_LONG(RES_PARTIAL_READ, MEMCACHED_PARTIAL_READ); - REGISTER_MEMC_CLASS_CONST_LONG(RES_SOME_ERRORS, MEMCACHED_SOME_ERRORS); - REGISTER_MEMC_CLASS_CONST_LONG(RES_NO_SERVERS, MEMCACHED_NO_SERVERS); - REGISTER_MEMC_CLASS_CONST_LONG(RES_END, MEMCACHED_END); - REGISTER_MEMC_CLASS_CONST_LONG(RES_ERRNO, MEMCACHED_ERRNO); - REGISTER_MEMC_CLASS_CONST_LONG(RES_BUFFERED, MEMCACHED_BUFFERED); - REGISTER_MEMC_CLASS_CONST_LONG(RES_TIMEOUT, MEMCACHED_TIMEOUT); - REGISTER_MEMC_CLASS_CONST_LONG(RES_BAD_KEY_PROVIDED, MEMCACHED_BAD_KEY_PROVIDED); - REGISTER_MEMC_CLASS_CONST_LONG(RES_STORED, MEMCACHED_STORED); - REGISTER_MEMC_CLASS_CONST_LONG(RES_DELETED, MEMCACHED_DELETED); - REGISTER_MEMC_CLASS_CONST_LONG(RES_STAT, MEMCACHED_STAT); - REGISTER_MEMC_CLASS_CONST_LONG(RES_ITEM, MEMCACHED_ITEM); - REGISTER_MEMC_CLASS_CONST_LONG(RES_NOT_SUPPORTED, MEMCACHED_NOT_SUPPORTED); - REGISTER_MEMC_CLASS_CONST_LONG(RES_FETCH_NOTFINISHED, MEMCACHED_FETCH_NOTFINISHED); - REGISTER_MEMC_CLASS_CONST_LONG(RES_SERVER_MARKED_DEAD, MEMCACHED_SERVER_MARKED_DEAD); - REGISTER_MEMC_CLASS_CONST_LONG(RES_UNKNOWN_STAT_KEY, MEMCACHED_UNKNOWN_STAT_KEY); - REGISTER_MEMC_CLASS_CONST_LONG(RES_INVALID_HOST_PROTOCOL, MEMCACHED_INVALID_HOST_PROTOCOL); + REGISTER_MEMC_CLASS_CONST_LONG(RES_SUCCESS, MEMCACHED_SUCCESS); + REGISTER_MEMC_CLASS_CONST_LONG(RES_FAILURE, MEMCACHED_FAILURE); + REGISTER_MEMC_CLASS_CONST_LONG(RES_HOST_LOOKUP_FAILURE, MEMCACHED_HOST_LOOKUP_FAILURE); + REGISTER_MEMC_CLASS_CONST_LONG(RES_CONNECTION_FAILURE, MEMCACHED_CONNECTION_FAILURE); + REGISTER_MEMC_CLASS_CONST_LONG(RES_CONNECTION_BIND_FAILURE, MEMCACHED_CONNECTION_BIND_FAILURE); + REGISTER_MEMC_CLASS_CONST_LONG(RES_WRITE_FAILURE, MEMCACHED_WRITE_FAILURE); + REGISTER_MEMC_CLASS_CONST_LONG(RES_READ_FAILURE, MEMCACHED_READ_FAILURE); + REGISTER_MEMC_CLASS_CONST_LONG(RES_UNKNOWN_READ_FAILURE, MEMCACHED_UNKNOWN_READ_FAILURE); + REGISTER_MEMC_CLASS_CONST_LONG(RES_PROTOCOL_ERROR, MEMCACHED_PROTOCOL_ERROR); + REGISTER_MEMC_CLASS_CONST_LONG(RES_CLIENT_ERROR, MEMCACHED_CLIENT_ERROR); + REGISTER_MEMC_CLASS_CONST_LONG(RES_SERVER_ERROR, MEMCACHED_SERVER_ERROR); + REGISTER_MEMC_CLASS_CONST_LONG(RES_DATA_EXISTS, MEMCACHED_DATA_EXISTS); + REGISTER_MEMC_CLASS_CONST_LONG(RES_DATA_DOES_NOT_EXIST, MEMCACHED_DATA_DOES_NOT_EXIST); + REGISTER_MEMC_CLASS_CONST_LONG(RES_NOTSTORED, MEMCACHED_NOTSTORED); + REGISTER_MEMC_CLASS_CONST_LONG(RES_STORED, MEMCACHED_STORED); + REGISTER_MEMC_CLASS_CONST_LONG(RES_NOTFOUND, MEMCACHED_NOTFOUND); + REGISTER_MEMC_CLASS_CONST_LONG(RES_PARTIAL_READ, MEMCACHED_PARTIAL_READ); + REGISTER_MEMC_CLASS_CONST_LONG(RES_SOME_ERRORS, MEMCACHED_SOME_ERRORS); + REGISTER_MEMC_CLASS_CONST_LONG(RES_NO_SERVERS, MEMCACHED_NO_SERVERS); + REGISTER_MEMC_CLASS_CONST_LONG(RES_END, MEMCACHED_END); + REGISTER_MEMC_CLASS_CONST_LONG(RES_DELETED, MEMCACHED_DELETED); + REGISTER_MEMC_CLASS_CONST_LONG(RES_VALUE, MEMCACHED_VALUE); + REGISTER_MEMC_CLASS_CONST_LONG(RES_STAT, MEMCACHED_STAT); + REGISTER_MEMC_CLASS_CONST_LONG(RES_ITEM, MEMCACHED_ITEM); + REGISTER_MEMC_CLASS_CONST_LONG(RES_ERRNO, MEMCACHED_ERRNO); + REGISTER_MEMC_CLASS_CONST_LONG(RES_FAIL_UNIX_SOCKET, MEMCACHED_FAIL_UNIX_SOCKET); + REGISTER_MEMC_CLASS_CONST_LONG(RES_NOT_SUPPORTED, MEMCACHED_NOT_SUPPORTED); + REGISTER_MEMC_CLASS_CONST_LONG(RES_NO_KEY_PROVIDED, MEMCACHED_NO_KEY_PROVIDED); + REGISTER_MEMC_CLASS_CONST_LONG(RES_FETCH_NOTFINISHED, MEMCACHED_FETCH_NOTFINISHED); + REGISTER_MEMC_CLASS_CONST_LONG(RES_TIMEOUT, MEMCACHED_TIMEOUT); + REGISTER_MEMC_CLASS_CONST_LONG(RES_BUFFERED, MEMCACHED_BUFFERED); + REGISTER_MEMC_CLASS_CONST_LONG(RES_BAD_KEY_PROVIDED, MEMCACHED_BAD_KEY_PROVIDED); + REGISTER_MEMC_CLASS_CONST_LONG(RES_INVALID_HOST_PROTOCOL, MEMCACHED_INVALID_HOST_PROTOCOL); + REGISTER_MEMC_CLASS_CONST_LONG(RES_SERVER_MARKED_DEAD, MEMCACHED_SERVER_MARKED_DEAD); + REGISTER_MEMC_CLASS_CONST_LONG(RES_UNKNOWN_STAT_KEY, MEMCACHED_UNKNOWN_STAT_KEY); + REGISTER_MEMC_CLASS_CONST_LONG(RES_INVALID_ARGUMENTS, MEMCACHED_INVALID_ARGUMENTS); + REGISTER_MEMC_CLASS_CONST_LONG(RES_PARSE_ERROR, MEMCACHED_PARSE_ERROR); + REGISTER_MEMC_CLASS_CONST_LONG(RES_PARSE_USER_ERROR, MEMCACHED_PARSE_USER_ERROR); + REGISTER_MEMC_CLASS_CONST_LONG(RES_DEPRECATED, MEMCACHED_DEPRECATED); + REGISTER_MEMC_CLASS_CONST_LONG(RES_IN_PROGRESS, MEMCACHED_IN_PROGRESS); + REGISTER_MEMC_CLASS_CONST_LONG(RES_MAXIMUM_RETURN, MEMCACHED_MAXIMUM_RETURN); REGISTER_MEMC_CLASS_CONST_LONG(RES_MEMORY_ALLOCATION_FAILURE, MEMCACHED_MEMORY_ALLOCATION_FAILURE); REGISTER_MEMC_CLASS_CONST_LONG(RES_CONNECTION_SOCKET_CREATE_FAILURE, MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE); From 9a429d43f8a4aab9292287502a3393588e2255c1 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Tue, 17 Nov 2020 12:04:15 +0100 Subject: [PATCH 249/345] Promote error "Memcached constructor was not called" to exception with PHP 8 (#465) For consistency with other PHP 8 extensions. --- php_memcached.c | 11 +++++++++++ tests/bad_construct_8.phpt | 12 +++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index d49b7d57..1e218a00 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -195,6 +195,7 @@ static inline php_memc_object_t *php_memc_fetch_object(zend_object *obj) { php_memc_object_t* intern = NULL; \ php_memc_user_data_t* memc_user_data = NULL; +#if PHP_VERSION_ID < 80000 #define MEMC_METHOD_FETCH_OBJECT \ intern = Z_MEMC_OBJ_P(object); \ if (!intern->memc) { \ @@ -203,6 +204,16 @@ static inline php_memc_object_t *php_memc_fetch_object(zend_object *obj) { } \ memc_user_data = (php_memc_user_data_t *) memcached_get_user_data(intern->memc); \ (void)memc_user_data; /* avoid unused variable warning */ +#else +#define MEMC_METHOD_FETCH_OBJECT \ + intern = Z_MEMC_OBJ_P(object); \ + if (!intern->memc) { \ + zend_throw_error(NULL, "Memcached constructor was not called"); \ + RETURN_THROWS(); \ + } \ + memc_user_data = (php_memc_user_data_t *) memcached_get_user_data(intern->memc); \ + (void)memc_user_data; /* avoid unused variable warning */ +#endif static zend_bool s_memc_valid_key_binary(zend_string *key) diff --git a/tests/bad_construct_8.phpt b/tests/bad_construct_8.phpt index 81daa5a5..10928cfd 100644 --- a/tests/bad_construct_8.phpt +++ b/tests/bad_construct_8.phpt @@ -20,15 +20,17 @@ class extended extends Memcached { } error_reporting(E_ALL); -$extended = new extended (); -var_dump ($extended->setOption (Memcached::OPT_BINARY_PROTOCOL, true)); +try { + $extended = new extended (); + var_dump ($extended->setOption (Memcached::OPT_BINARY_PROTOCOL, true)); +} catch (Error $e) { + echo $e->getMessage() . PHP_EOL; +} echo "OK" . PHP_EOL; --EXPECTF-- Memcached::__construct(): Argument #1 ($persistent_id) must be of type ?string, stdClass given - -Warning: Memcached::setOption(): Memcached constructor was not called in %s -NULL +Memcached constructor was not called OK From 8f3c5dc0fa773aded5d169e5c5b8eab18c8931c6 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 1 Dec 2020 04:09:57 +0100 Subject: [PATCH 250/345] fix php8 arginfo (#467) --- php_memcached.stub.php | 14 +++++++------- php_memcached_arginfo.h | 28 ++++++++++++++-------------- php_memcached_legacy_arginfo.h | 2 +- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/php_memcached.stub.php b/php_memcached.stub.php index 4ba6d5b6..e44ff4aa 100644 --- a/php_memcached.stub.php +++ b/php_memcached.stub.php @@ -35,16 +35,16 @@ public function cas(string $cas_token, string $key, mixed $value, int $expiratio public function casByKey(string $cas_token, string $server_key, string $key, mixed $value, int $expiration=0): bool {} public function add(string $key, mixed $value, int $expiration=0): bool {} public function addByKey(string $server_key, string $key, mixed $value, int $expiration=0): bool {} - public function append(string $key, string $value): bool {} - public function appendByKey(string $server_key, string $key, string $value): bool {} - public function prepend(string $key, string $value): bool {} - public function prependByKey(string $server_key, string $key, string $value): bool {} + public function append(string $key, string $value): ?bool {} + public function appendByKey(string $server_key, string $key, string $value): ?bool {} + public function prepend(string $key, string $value): ?bool {} + public function prependByKey(string $server_key, string $key, string $value): ?bool {} public function replace(string $key, mixed $value, int $expiration=0): bool {} public function replaceByKey(string $server_key, string $key, mixed $value, int $expiration=0): bool {} public function delete(string $key, int $time=0): bool {} - public function deleteMulti(array $keys, int $time=0): bool {} + public function deleteMulti(array $keys, int $time=0): array {} public function deleteByKey(string $server_key, string $key, int $time=0): bool {} - public function deleteMultiByKey(string $server_key, array $keys, int $time=0): bool {} + public function deleteMultiByKey(string $server_key, array $keys, int $time=0): array {} public function increment(string $key, int $offset=1, int $initial_value=0, int $expiry=0): false|int {} public function decrement(string $key, int $offset=1, int $initial_value=0, int $expiry=0): false|int {} @@ -73,7 +73,7 @@ public function flush(int $delay=0): bool {} public function getOption(int $option): mixed {} public function setOption(int $option, mixed $value): bool {} public function setOptions(array $options): bool {} - public function setBucket(array $host_map, array $forward_map, int $replicas): bool {} + public function setBucket(array $host_map, ?array $forward_map, int $replicas): bool {} #ifdef HAVE_MEMCACHED_SASL public function setSaslAuthData(string $username, string $password): bool {} #endif diff --git a/php_memcached_arginfo.h b/php_memcached_arginfo.h index 6729dd36..18b17cc7 100644 --- a/php_memcached_arginfo.h +++ b/php_memcached_arginfo.h @@ -1,10 +1,10 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: a33d23c6659922e98d3704879eb4bc820e1819df */ + * Stub hash: 3e5af769d67ce91bd713bb11b325a9ccaabbfb7a */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, persistent_id, IS_STRING, 0, "NULL") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, callback, IS_CALLABLE, 0, "NULL") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, connection_str, IS_STRING, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, persistent_id, IS_STRING, 1, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, callback, IS_CALLABLE, 1, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, connection_str, IS_STRING, 1, "NULL") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getResultCode, 0, 0, IS_LONG, 0) @@ -15,14 +15,14 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_get, 0, 1, IS_MIXED, 0) ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cache_cb, IS_CALLABLE, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cache_cb, IS_CALLABLE, 1, "NULL") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, get_flags, IS_LONG, 0, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getByKey, 0, 2, IS_MIXED, 0) ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cache_cb, IS_CALLABLE, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cache_cb, IS_CALLABLE, 1, "NULL") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, get_flags, IS_LONG, 0, "0") ZEND_END_ARG_INFO() @@ -40,14 +40,14 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getDelayed, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, keys, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, with_cas, _IS_BOOL, 0, "0") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value_cb, IS_CALLABLE, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value_cb, IS_CALLABLE, 1, "NULL") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getDelayedByKey, 0, 2, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, keys, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, with_cas, _IS_BOOL, 0, "0") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value_cb, IS_CALLABLE, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value_cb, IS_CALLABLE, 1, "NULL") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_fetch, 0, 0, MAY_BE_FALSE|MAY_BE_ARRAY) @@ -109,12 +109,12 @@ ZEND_END_ARG_INFO() #define arginfo_class_Memcached_addByKey arginfo_class_Memcached_setByKey -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_append, 0, 2, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_append, 0, 2, _IS_BOOL, 1) ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, value, IS_STRING, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_appendByKey, 0, 3, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_appendByKey, 0, 3, _IS_BOOL, 1) ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, value, IS_STRING, 0) @@ -133,7 +133,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_delete, 0, 1, _I ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, time, IS_LONG, 0, "0") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_deleteMulti, 0, 1, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_deleteMulti, 0, 1, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO(0, keys, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, time, IS_LONG, 0, "0") ZEND_END_ARG_INFO() @@ -144,7 +144,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_deleteByKey, 0, ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, time, IS_LONG, 0, "0") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_deleteMultiByKey, 0, 2, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_deleteMultiByKey, 0, 2, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, keys, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, time, IS_LONG, 0, "0") @@ -202,7 +202,7 @@ ZEND_END_ARG_INFO() #define arginfo_class_Memcached_getLastDisconnectedServer arginfo_class_Memcached_fetch ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getStats, 0, 0, MAY_BE_FALSE|MAY_BE_ARRAY) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, type, IS_STRING, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, type, IS_STRING, 1, "NULL") ZEND_END_ARG_INFO() #define arginfo_class_Memcached_getVersion arginfo_class_Memcached_fetch @@ -228,7 +228,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_setBucket, 0, 3, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, host_map, IS_ARRAY, 0) - ZEND_ARG_TYPE_INFO(0, forward_map, IS_ARRAY, 0) + ZEND_ARG_TYPE_INFO(0, forward_map, IS_ARRAY, 1) ZEND_ARG_TYPE_INFO(0, replicas, IS_LONG, 0) ZEND_END_ARG_INFO() diff --git a/php_memcached_legacy_arginfo.h b/php_memcached_legacy_arginfo.h index 6f21d2a8..2c0b2de3 100644 --- a/php_memcached_legacy_arginfo.h +++ b/php_memcached_legacy_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: a33d23c6659922e98d3704879eb4bc820e1819df */ + * Stub hash: 3e5af769d67ce91bd713bb11b325a9ccaabbfb7a */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) ZEND_ARG_INFO(0, persistent_id) From fc33513d32504843fe0864f9855d3a0b37a76ddc Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Thu, 3 Dec 2020 09:16:42 -0800 Subject: [PATCH 251/345] Add PHP 8.0 to the Travis CI matrix, use 'nightly' builds (#462) --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7d6b57d7..5478b296 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,8 @@ dist: xenial language: php php: - - master + - nightly + - 8.0 - 7.4 - 7.3 - 7.2 @@ -12,7 +13,7 @@ php: matrix: fast_finish: true allow_failures: - - php: master + - php: nightly env: - LIBMEMCACHED_VERSION=1.0.18 # Debian Jessie / Ubuntu Xenial From b8202146903692e3ae2f2f7ad9915c3c03928ac3 Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Thu, 17 Dec 2020 20:00:42 +0000 Subject: [PATCH 252/345] Fixed ParseError in stub file (#468) Match PHP 7 version of the file which has NULL as the default value of this bool argument. --- php_memcached.stub.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php_memcached.stub.php b/php_memcached.stub.php index e44ff4aa..6b84c5b7 100644 --- a/php_memcached.stub.php +++ b/php_memcached.stub.php @@ -17,8 +17,8 @@ public function get(string $key, callable $cache_cb=NULL, int $get_flags=0): mix public function getByKey(string $server_key, string $key, callable $cache_cb=NULL, int $get_flags=0): mixed {} public function getMulti(array $keys, int $get_flags=0): false|array {} public function getMultiByKey(string $server_key, array $keys, int $get_flags=0): false|array {} - public function getDelayed(array $keys, bool $with_cas=0, callable $value_cb=NULL): bool {} - public function getDelayedByKey(string $server_key, array $keys, bool $with_cas=0, callable $value_cb=NULL): bool {} + public function getDelayed(array $keys, bool $with_cas=NULL, callable $value_cb=NULL): bool {} + public function getDelayedByKey(string $server_key, array $keys, bool $with_cas=NULL, callable $value_cb=NULL): bool {} public function fetch(): false|array {} public function fetchAll(): false|array {} From bfb0a66809d43080219ab5381235f848c91eff7e Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Fri, 18 Dec 2020 23:40:15 +0000 Subject: [PATCH 253/345] Re-generated .h files after stubs were modified (#469) --- php_memcached_arginfo.h | 22 +++++++++++----------- php_memcached_legacy_arginfo.h | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/php_memcached_arginfo.h b/php_memcached_arginfo.h index 18b17cc7..6b05cf4c 100644 --- a/php_memcached_arginfo.h +++ b/php_memcached_arginfo.h @@ -1,10 +1,10 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 3e5af769d67ce91bd713bb11b325a9ccaabbfb7a */ + * Stub hash: 8ce11ff45ccb2b1c765e5f313305f539ca3fa4f6 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, persistent_id, IS_STRING, 1, "NULL") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, callback, IS_CALLABLE, 1, "NULL") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, connection_str, IS_STRING, 1, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, persistent_id, IS_STRING, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, callback, IS_CALLABLE, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, connection_str, IS_STRING, 0, "NULL") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getResultCode, 0, 0, IS_LONG, 0) @@ -15,14 +15,14 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_get, 0, 1, IS_MIXED, 0) ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cache_cb, IS_CALLABLE, 1, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cache_cb, IS_CALLABLE, 0, "NULL") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, get_flags, IS_LONG, 0, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getByKey, 0, 2, IS_MIXED, 0) ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cache_cb, IS_CALLABLE, 1, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cache_cb, IS_CALLABLE, 0, "NULL") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, get_flags, IS_LONG, 0, "0") ZEND_END_ARG_INFO() @@ -39,15 +39,15 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getDelayed, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, keys, IS_ARRAY, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, with_cas, _IS_BOOL, 0, "0") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value_cb, IS_CALLABLE, 1, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, with_cas, _IS_BOOL, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value_cb, IS_CALLABLE, 0, "NULL") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getDelayedByKey, 0, 2, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, keys, IS_ARRAY, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, with_cas, _IS_BOOL, 0, "0") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value_cb, IS_CALLABLE, 1, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, with_cas, _IS_BOOL, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value_cb, IS_CALLABLE, 0, "NULL") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_fetch, 0, 0, MAY_BE_FALSE|MAY_BE_ARRAY) @@ -202,7 +202,7 @@ ZEND_END_ARG_INFO() #define arginfo_class_Memcached_getLastDisconnectedServer arginfo_class_Memcached_fetch ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getStats, 0, 0, MAY_BE_FALSE|MAY_BE_ARRAY) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, type, IS_STRING, 1, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, type, IS_STRING, 0, "NULL") ZEND_END_ARG_INFO() #define arginfo_class_Memcached_getVersion arginfo_class_Memcached_fetch diff --git a/php_memcached_legacy_arginfo.h b/php_memcached_legacy_arginfo.h index 2c0b2de3..c9426166 100644 --- a/php_memcached_legacy_arginfo.h +++ b/php_memcached_legacy_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 3e5af769d67ce91bd713bb11b325a9ccaabbfb7a */ + * Stub hash: 8ce11ff45ccb2b1c765e5f313305f539ca3fa4f6 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) ZEND_ARG_INFO(0, persistent_id) From c8f9376a8b1399907e732064890101da7261d8bb Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Mon, 18 Jan 2021 16:34:41 +0100 Subject: [PATCH 254/345] fix php8 arginfo (#472) --- php_memcached.stub.php | 12 ++++++------ php_memcached_arginfo.h | 22 +++++++++++----------- php_memcached_legacy_arginfo.h | 2 +- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/php_memcached.stub.php b/php_memcached.stub.php index 6b84c5b7..5a735b57 100644 --- a/php_memcached.stub.php +++ b/php_memcached.stub.php @@ -8,17 +8,17 @@ class Memcached { - public function __construct(string $persistent_id=NULL, callable $callback=NULL, string $connection_str=NULL) {} + public function __construct(string $persistent_id=null, callable $callback=null, string $connection_str=null) {} public function getResultCode(): int {} public function getResultMessage(): string {} - public function get(string $key, callable $cache_cb=NULL, int $get_flags=0): mixed {} - public function getByKey(string $server_key, string $key, callable $cache_cb=NULL, int $get_flags=0): mixed {} + public function get(string $key, callable $cache_cb=null, int $get_flags=0): mixed {} + public function getByKey(string $server_key, string $key, callable $cache_cb=null, int $get_flags=0): mixed {} public function getMulti(array $keys, int $get_flags=0): false|array {} public function getMultiByKey(string $server_key, array $keys, int $get_flags=0): false|array {} - public function getDelayed(array $keys, bool $with_cas=NULL, callable $value_cb=NULL): bool {} - public function getDelayedByKey(string $server_key, array $keys, bool $with_cas=NULL, callable $value_cb=NULL): bool {} + public function getDelayed(array $keys, bool $with_cas=false, callable $value_cb=null): bool {} + public function getDelayedByKey(string $server_key, array $keys, bool $with_cas=false, callable $value_cb=null): bool {} public function fetch(): false|array {} public function fetchAll(): false|array {} @@ -64,7 +64,7 @@ public function getLastErrorCode(): int {} public function getLastErrorErrno(): int {} public function getLastDisconnectedServer(): false|array {} - public function getStats(string $type=NULL): false|array {} + public function getStats(string $type=null): false|array {} public function getVersion(): false|array {} public function getAllKeys(): false|array {} diff --git a/php_memcached_arginfo.h b/php_memcached_arginfo.h index 6b05cf4c..4c8a6845 100644 --- a/php_memcached_arginfo.h +++ b/php_memcached_arginfo.h @@ -1,10 +1,10 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 8ce11ff45ccb2b1c765e5f313305f539ca3fa4f6 */ + * Stub hash: 573d35c5c6b6c397943e0f8ab9c505e2f4ce9e34 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, persistent_id, IS_STRING, 0, "NULL") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, callback, IS_CALLABLE, 0, "NULL") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, connection_str, IS_STRING, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, persistent_id, IS_STRING, 1, "null") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, callback, IS_CALLABLE, 1, "null") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, connection_str, IS_STRING, 1, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getResultCode, 0, 0, IS_LONG, 0) @@ -15,14 +15,14 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_get, 0, 1, IS_MIXED, 0) ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cache_cb, IS_CALLABLE, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cache_cb, IS_CALLABLE, 1, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, get_flags, IS_LONG, 0, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getByKey, 0, 2, IS_MIXED, 0) ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cache_cb, IS_CALLABLE, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cache_cb, IS_CALLABLE, 1, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, get_flags, IS_LONG, 0, "0") ZEND_END_ARG_INFO() @@ -39,15 +39,15 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getDelayed, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, keys, IS_ARRAY, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, with_cas, _IS_BOOL, 0, "NULL") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value_cb, IS_CALLABLE, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, with_cas, _IS_BOOL, 0, "false") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value_cb, IS_CALLABLE, 1, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getDelayedByKey, 0, 2, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, keys, IS_ARRAY, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, with_cas, _IS_BOOL, 0, "NULL") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value_cb, IS_CALLABLE, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, with_cas, _IS_BOOL, 0, "false") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value_cb, IS_CALLABLE, 1, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_fetch, 0, 0, MAY_BE_FALSE|MAY_BE_ARRAY) @@ -202,7 +202,7 @@ ZEND_END_ARG_INFO() #define arginfo_class_Memcached_getLastDisconnectedServer arginfo_class_Memcached_fetch ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getStats, 0, 0, MAY_BE_FALSE|MAY_BE_ARRAY) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, type, IS_STRING, 0, "NULL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, type, IS_STRING, 1, "null") ZEND_END_ARG_INFO() #define arginfo_class_Memcached_getVersion arginfo_class_Memcached_fetch diff --git a/php_memcached_legacy_arginfo.h b/php_memcached_legacy_arginfo.h index c9426166..a615e3a6 100644 --- a/php_memcached_legacy_arginfo.h +++ b/php_memcached_legacy_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 8ce11ff45ccb2b1c765e5f313305f539ca3fa4f6 */ + * Stub hash: 573d35c5c6b6c397943e0f8ab9c505e2f4ce9e34 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) ZEND_ARG_INFO(0, persistent_id) From 19a02bb5bfaeb520b857a2d64172f7d2a9615fb3 Mon Sep 17 00:00:00 2001 From: Arjen de Korte Date: Thu, 21 Jan 2021 04:06:53 +0100 Subject: [PATCH 255/345] Don't expect tests/expire to fail (#475) The issue reported in https://code.google.com/archive/p/memcached/issues/275 was fixed more than 8 years ago and the test is no longer expected to fail --- tests/expire.phpt | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/expire.phpt b/tests/expire.phpt index 4fb49c55..d53309e7 100644 --- a/tests/expire.phpt +++ b/tests/expire.phpt @@ -1,7 +1,5 @@ --TEST-- Memcached store, fetch & touch expired key ---XFAIL-- -https://code.google.com/p/memcached/issues/detail?id=275 --SKIPIF-- Date: Wed, 9 Jun 2021 14:53:43 +0200 Subject: [PATCH 256/345] fix incorrect zp, fixes #484 --- php_memcached.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 1e218a00..d2f23434 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1876,7 +1876,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke if (by_key) { /* "Sa|ll" */ - ZEND_PARSE_PARAMETERS_START(2, 4) + ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_STR(server_key) Z_PARAM_ARRAY(entries) Z_PARAM_OPTIONAL @@ -1884,7 +1884,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke ZEND_PARSE_PARAMETERS_END(); } else { /* "a|ll" */ - ZEND_PARSE_PARAMETERS_START(1, 3) + ZEND_PARSE_PARAMETERS_START(1, 2) Z_PARAM_ARRAY(entries) Z_PARAM_OPTIONAL Z_PARAM_LONG(expiration) From 51c9baf49f96c5f35be8257549f426ef1860f0ef Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Wed, 9 Jun 2021 14:58:37 +0200 Subject: [PATCH 257/345] fix zpp in mem_cas_impl --- php_memcached.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index d2f23434..2ea93604 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -2089,8 +2089,8 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) MEMC_METHOD_INIT_VARS; if (by_key) { - /* "zSSz|ll" */ - ZEND_PARSE_PARAMETERS_START(4, 6) + /* "zSSz|l" */ + ZEND_PARSE_PARAMETERS_START(4, 5) Z_PARAM_ZVAL(zv_cas) Z_PARAM_STR(server_key) Z_PARAM_STR(key) @@ -2099,8 +2099,8 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) Z_PARAM_LONG(expiration) ZEND_PARSE_PARAMETERS_END(); } else { - /* "zSz|ll" */ - ZEND_PARSE_PARAMETERS_START(3, 5) + /* "zSz|l" */ + ZEND_PARSE_PARAMETERS_START(3, 4) Z_PARAM_ZVAL(zv_cas) Z_PARAM_STR(key) Z_PARAM_ZVAL(value) From 899e4dc27c672b1617a232e9757809bf0dd5b89a Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 9 Jun 2021 14:30:12 +0200 Subject: [PATCH 258/345] fix test for PHP 8.1 --- tests/undefined_set.phpt | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/tests/undefined_set.phpt b/tests/undefined_set.phpt index caeda19d..581c9406 100644 --- a/tests/undefined_set.phpt +++ b/tests/undefined_set.phpt @@ -10,30 +10,25 @@ $m = memc_get_instance (); $key = 'foobarbazDEADC0DE'; $value = array('foo' => 'bar'); -$rv = $m->set($no_key, $value, 360); +// silent to hide: +// Warning: Undefined variable +// Deprecated: Memcached::set(): Passing null to parameter (PHP 8.1) + +$rv = @$m->set($no_key, $value, 360); var_dump($rv); -$rv = $m->set($key, $no_value, 360); +$rv = @$m->set($key, $no_value, 360); var_dump($rv); -$rv = $m->set($no_key, $no_value, 360); +$rv = @$m->set($no_key, $no_value, 360); var_dump($rv); -$rv = $m->set($key, $value, $no_time); +$rv = @$m->set($key, $value, $no_time); var_dump($rv); ?> --EXPECTF-- -%s: Undefined variable%sno_key in %s bool(false) - -%s: Undefined variable%sno_value in %s bool(true) - -%s: Undefined variable%sno_key in %s - -%s: Undefined variable%sno_value in %s bool(false) - -%s: Undefined variable%sno_time in %s bool(true) From 0c3f411e710a360a41c256c310f3e7440acb5add Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 9 Jun 2021 14:30:12 +0200 Subject: [PATCH 259/345] fix test for PHP 8.1 --- tests/undefined_set.phpt | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/tests/undefined_set.phpt b/tests/undefined_set.phpt index caeda19d..581c9406 100644 --- a/tests/undefined_set.phpt +++ b/tests/undefined_set.phpt @@ -10,30 +10,25 @@ $m = memc_get_instance (); $key = 'foobarbazDEADC0DE'; $value = array('foo' => 'bar'); -$rv = $m->set($no_key, $value, 360); +// silent to hide: +// Warning: Undefined variable +// Deprecated: Memcached::set(): Passing null to parameter (PHP 8.1) + +$rv = @$m->set($no_key, $value, 360); var_dump($rv); -$rv = $m->set($key, $no_value, 360); +$rv = @$m->set($key, $no_value, 360); var_dump($rv); -$rv = $m->set($no_key, $no_value, 360); +$rv = @$m->set($no_key, $no_value, 360); var_dump($rv); -$rv = $m->set($key, $value, $no_time); +$rv = @$m->set($key, $value, $no_time); var_dump($rv); ?> --EXPECTF-- -%s: Undefined variable%sno_key in %s bool(false) - -%s: Undefined variable%sno_value in %s bool(true) - -%s: Undefined variable%sno_key in %s - -%s: Undefined variable%sno_value in %s bool(false) - -%s: Undefined variable%sno_time in %s bool(true) From c2a31946f0be9a12d2ebb54f876da9dce17c40a3 Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Thu, 25 Feb 2021 06:52:02 -0800 Subject: [PATCH 260/345] Fix stubs to make them consistent for PHP 8 --- php_memcached.stub.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/php_memcached.stub.php b/php_memcached.stub.php index 5a735b57..1efc5877 100644 --- a/php_memcached.stub.php +++ b/php_memcached.stub.php @@ -8,17 +8,17 @@ class Memcached { - public function __construct(string $persistent_id=null, callable $callback=null, string $connection_str=null) {} + public function __construct(?string $persistent_id=null, ?callable $callback=null, ?string $connection_str=null) {} public function getResultCode(): int {} public function getResultMessage(): string {} - public function get(string $key, callable $cache_cb=null, int $get_flags=0): mixed {} - public function getByKey(string $server_key, string $key, callable $cache_cb=null, int $get_flags=0): mixed {} + public function get(string $key, ?callable $cache_cb=null, int $get_flags=0): mixed {} + public function getByKey(string $server_key, string $key, ?callable $cache_cb=null, int $get_flags=0): mixed {} public function getMulti(array $keys, int $get_flags=0): false|array {} public function getMultiByKey(string $server_key, array $keys, int $get_flags=0): false|array {} - public function getDelayed(array $keys, bool $with_cas=false, callable $value_cb=null): bool {} - public function getDelayedByKey(string $server_key, array $keys, bool $with_cas=false, callable $value_cb=null): bool {} + public function getDelayed(array $keys, bool $with_cas=false, ?callable $value_cb=null): bool {} + public function getDelayedByKey(string $server_key, array $keys, bool $with_cas=false, ?callable $value_cb=null): bool {} public function fetch(): false|array {} public function fetchAll(): false|array {} @@ -64,7 +64,7 @@ public function getLastErrorCode(): int {} public function getLastErrorErrno(): int {} public function getLastDisconnectedServer(): false|array {} - public function getStats(string $type=null): false|array {} + public function getStats(?string $type=null): false|array {} public function getVersion(): false|array {} public function getAllKeys(): false|array {} From 7bbf4fbad3b25cb2628b96eafce50d19f22e3b47 Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Thu, 25 Feb 2021 07:52:54 -0800 Subject: [PATCH 261/345] Expose internal key check via checkKey() method Make ascii key check consistent with libmemcached's isgraph() check Add test to check that they match --- php_memcached.c | 20 +++++++++++++++++++- php_memcached.stub.php | 1 + php_memcached_arginfo.h | 8 +++++++- php_memcached_legacy_arginfo.h | 8 +++++++- 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 2ea93604..d49cbeb4 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -228,7 +228,7 @@ zend_bool s_memc_valid_key_ascii(zend_string *key) size_t i, len = ZSTR_LEN(key); for (i = 0; i < len; i++) { - if (iscntrl(str[i]) || isspace(str[i])) + if (!isgraph(str[i]) || isspace(str[i])) return 0; } return 1; @@ -3450,6 +3450,24 @@ static PHP_METHOD(Memcached, isPristine) } /* }}} */ +/* {{{ bool Memcached::checkKey(string key) + Checks if a key is valid */ +PHP_METHOD(Memcached, checkKey) +{ + zend_string *key; + MEMC_METHOD_INIT_VARS; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STR(key) + ZEND_PARSE_PARAMETERS_END(); + + MEMC_METHOD_FETCH_OBJECT; + s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); + MEMC_CHECK_KEY(intern, key); + RETURN_TRUE; +} +/* }}} */ + /**************************************** Internal support code ****************************************/ diff --git a/php_memcached.stub.php b/php_memcached.stub.php index 1efc5877..819186f4 100644 --- a/php_memcached.stub.php +++ b/php_memcached.stub.php @@ -83,6 +83,7 @@ public function setEncodingKey(string $key): bool {} #endif public function isPersistent(): bool {} public function isPristine(): bool {} + public function checkKey(string $key): bool {} } #ifdef HAVE_MEMCACHED_PROTOCOL diff --git a/php_memcached_arginfo.h b/php_memcached_arginfo.h index 4c8a6845..3373624e 100644 --- a/php_memcached_arginfo.h +++ b/php_memcached_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 573d35c5c6b6c397943e0f8ab9c505e2f4ce9e34 */ + * Stub hash: 3f4694d4e1f3d1647a832acd8539b056b2ab5e7a */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, persistent_id, IS_STRING, 1, "null") @@ -249,6 +249,10 @@ ZEND_END_ARG_INFO() #define arginfo_class_Memcached_isPristine arginfo_class_Memcached_resetServerList +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_checkKey, 0, 1, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) +ZEND_END_ARG_INFO() + #if defined(HAVE_MEMCACHED_PROTOCOL) ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_MemcachedServer_run, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, address, IS_STRING, 0) @@ -325,6 +329,7 @@ ZEND_METHOD(Memcached, setEncodingKey); #endif ZEND_METHOD(Memcached, isPersistent); ZEND_METHOD(Memcached, isPristine); +ZEND_METHOD(Memcached, checkKey); #if defined(HAVE_MEMCACHED_PROTOCOL) ZEND_METHOD(MemcachedServer, run); #endif @@ -396,6 +401,7 @@ static const zend_function_entry class_Memcached_methods[] = { #endif ZEND_ME(Memcached, isPersistent, arginfo_class_Memcached_isPersistent, ZEND_ACC_PUBLIC) ZEND_ME(Memcached, isPristine, arginfo_class_Memcached_isPristine, ZEND_ACC_PUBLIC) + ZEND_ME(Memcached, checkKey, arginfo_class_Memcached_checkKey, ZEND_ACC_PUBLIC) ZEND_FE_END }; diff --git a/php_memcached_legacy_arginfo.h b/php_memcached_legacy_arginfo.h index a615e3a6..ad6d6562 100644 --- a/php_memcached_legacy_arginfo.h +++ b/php_memcached_legacy_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 573d35c5c6b6c397943e0f8ab9c505e2f4ce9e34 */ + * Stub hash: 3f4694d4e1f3d1647a832acd8539b056b2ab5e7a */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) ZEND_ARG_INFO(0, persistent_id) @@ -245,6 +245,10 @@ ZEND_END_ARG_INFO() #define arginfo_class_Memcached_isPristine arginfo_class_Memcached_getResultCode +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_checkKey, 0, 0, 1) + ZEND_ARG_INFO(0, key) +ZEND_END_ARG_INFO() + #if defined(HAVE_MEMCACHED_PROTOCOL) ZEND_BEGIN_ARG_INFO_EX(arginfo_class_MemcachedServer_run, 0, 0, 1) ZEND_ARG_INFO(0, address) @@ -321,6 +325,7 @@ ZEND_METHOD(Memcached, setEncodingKey); #endif ZEND_METHOD(Memcached, isPersistent); ZEND_METHOD(Memcached, isPristine); +ZEND_METHOD(Memcached, checkKey); #if defined(HAVE_MEMCACHED_PROTOCOL) ZEND_METHOD(MemcachedServer, run); #endif @@ -392,6 +397,7 @@ static const zend_function_entry class_Memcached_methods[] = { #endif ZEND_ME(Memcached, isPersistent, arginfo_class_Memcached_isPersistent, ZEND_ACC_PUBLIC) ZEND_ME(Memcached, isPristine, arginfo_class_Memcached_isPristine, ZEND_ACC_PUBLIC) + ZEND_ME(Memcached, checkKey, arginfo_class_Memcached_checkKey, ZEND_ACC_PUBLIC) ZEND_FE_END }; From 7be9f007799ccdd9018176a0a3ea3cf7c7d56ab0 Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Thu, 25 Feb 2021 07:55:27 -0800 Subject: [PATCH 262/345] Add test --- package.xml | 1 + tests/check_key.phpt | 132 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 tests/check_key.phpt diff --git a/package.xml b/package.xml index ec44bd1b..519de583 100644 --- a/package.xml +++ b/package.xml @@ -87,6 +87,7 @@ Fixes + diff --git a/tests/check_key.phpt b/tests/check_key.phpt new file mode 100644 index 00000000..74ec6214 --- /dev/null +++ b/tests/check_key.phpt @@ -0,0 +1,132 @@ +--TEST-- +Memcached::checkKey() +--SKIPIF-- + +--FILE-- + false, + Memcached::OPT_VERIFY_KEY => true + )); + +$keys = [ + 'foo', + 'foo bar', + str_repeat('a',65), + str_repeat('b',250), + str_repeat('c',251), + 'Montréal', + 'København', + 'Düsseldorf', + 'Kraków', + 'İstanbul', + 'ﺎﺨﺘﺑïºïº­ PHP', + '測試', + 'ТеÑтирование', + 'Ù¾ÛŒ ایچ Ù¾ÛŒ Ú©ÛŒ جانچ ÛÙˆ رÛÛŒ ÛÛ’', + 'Testataan PHP: tä', + 'Að prófa PHP', + 'د Ù¾ÛŒ ایچ Ù¾ÛŒ ازمول', + 'Pruvà PHP' +]; +foreach($keys as $key) { + echo "Checking \"$key\"" . PHP_EOL; + echo "MEMC_CHECK_KEY: "; + var_dump($m->checkKey($key)); + echo "libmemcached: "; + var_dump($m->set($key, "this is a test")); + var_dump($m->getResultMessage()); + echo "\n"; +} +--EXPECT-- +Checking "foo" +MEMC_CHECK_KEY: bool(true) +libmemcached: bool(true) +string(7) "SUCCESS" + +Checking "foo bar" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +MEMC_CHECK_KEY: bool(true) +libmemcached: bool(true) +string(7) "SUCCESS" + +Checking "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" +MEMC_CHECK_KEY: bool(true) +libmemcached: bool(true) +string(7) "SUCCESS" + +Checking "ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "Montréal" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "København" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "Düsseldorf" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "Kraków" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "İstanbul" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "ﺎﺨﺘﺑïºïº­ PHP" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "測試" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "ТеÑтирование" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "Ù¾ÛŒ ایچ Ù¾ÛŒ Ú©ÛŒ جانچ ÛÙˆ رÛÛŒ ÛÛ’" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "Testataan PHP: tä" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "Að prófa PHP" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "د Ù¾ÛŒ ایچ Ù¾ÛŒ ازمول" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + +Checking "Pruvà PHP" +MEMC_CHECK_KEY: bool(false) +libmemcached: bool(false) +string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE" + From 8ed8092c7f4c07e170f38465dbf89a3447fe35cd Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 19 Jan 2021 16:16:30 +0100 Subject: [PATCH 263/345] fix MemcachedServer related: #418, m6w6/libmemcached#94 --- php_memcached.c | 3 ++ php_memcached_server.c | 80 +++++++++++++++++++++++------------ server-example/run-server.php | 2 +- 3 files changed, 56 insertions(+), 29 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index d49cbeb4..e7a28e0a 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3520,6 +3520,8 @@ static void php_memc_server_free_storage(zend_object *object) { php_memc_server_t *intern = php_memc_server_fetch_object(object); + + php_memc_proto_handler_destroy(&intern->handler); zend_object_std_dtor(&intern->zo); } @@ -3533,6 +3535,7 @@ zend_object *php_memc_server_new(zend_class_entry *ce) object_properties_init(&intern->zo, ce); intern->zo.handlers = &memcached_server_object_handlers; + intern->handler = php_memc_proto_handler_new(); return &intern->zo; } diff --git a/php_memcached_server.c b/php_memcached_server.c index 870209c1..e816b90d 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -17,13 +17,16 @@ #include "php_memcached.h" #include "php_memcached_private.h" #include "php_memcached_server.h" +#include "php_network.h" #include -#undef NDEBUG -#undef _NDEBUG #include +#if HAVE_ARPA_INET_H +# include +#endif + #define MEMC_GET_CB(cb_type) (MEMC_SERVER_G(callbacks)[cb_type]) #define MEMC_HAS_CB(cb_type) (MEMC_GET_CB(cb_type).fci.size > 0) @@ -58,9 +61,9 @@ typedef struct { static long s_invoke_php_callback (php_memc_server_cb_t *cb, zval *params, ssize_t param_count) { - zval *retval = NULL; + zval retval; - cb->fci.retval = retval; + cb->fci.retval = &retval; cb->fci.params = params; cb->fci.param_count = param_count; #if PHP_VERSION_ID < 80000 @@ -73,7 +76,7 @@ long s_invoke_php_callback (php_memc_server_cb_t *cb, zval *params, ssize_t para efree (buf); } - return retval == NULL ? PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND : zval_get_long(retval); + return Z_ISUNDEF(retval) ? PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND : zval_get_long(&retval); } // memcached protocol callbacks @@ -96,6 +99,7 @@ protocol_binary_response_status s_add_handler(const void *cookie, const void *ke ZVAL_LONG(&zflags, flags); ZVAL_LONG(&zexptime, exptime); ZVAL_NULL(&zresult_cas); + ZVAL_MAKE_REF(&zresult_cas); ZVAL_COPY(¶ms[0], &zcookie); ZVAL_COPY(¶ms[1], &zkey); @@ -142,6 +146,7 @@ protocol_binary_response_status s_append_prepend_handler (php_memc_event_t event ZVAL_STRINGL(&zvalue, data, data_len); ZVAL_DOUBLE(&zcas, cas); ZVAL_NULL(&zresult_cas); + ZVAL_MAKE_REF(&zresult_cas); ZVAL_COPY(¶ms[0], &zcookie); ZVAL_COPY(¶ms[1], &zkey); @@ -198,11 +203,13 @@ protocol_binary_response_status s_incr_decr_handler (php_memc_event_t event, con MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); ZVAL_STRINGL(&zkey, key, key_len); - ZVAL_LONG(&zdelta, (long) delta); - ZVAL_LONG(&zinital, (long) initial); - ZVAL_LONG(&zexpiration, (long) expiration); + ZVAL_LONG(&zdelta, (zend_long) delta); + ZVAL_LONG(&zinital, (zend_long) initial); + ZVAL_LONG(&zexpiration, (zend_long) expiration); ZVAL_LONG(&zresult, 0); + ZVAL_MAKE_REF(&zresult); ZVAL_NULL(&zresult_cas); + ZVAL_MAKE_REF(&zresult_cas); ZVAL_COPY(¶ms[0], &zcookie); ZVAL_COPY(¶ms[1], &zkey); @@ -322,6 +329,13 @@ protocol_binary_response_status s_get_handler (const void *cookie, const void *k } MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); + ZVAL_STRINGL(&zkey, key, key_len); + ZVAL_NULL(&zvalue); + ZVAL_MAKE_REF(&zvalue); + ZVAL_NULL(&zflags); + ZVAL_MAKE_REF(&zflags); + ZVAL_NULL(&zresult_cas); + ZVAL_MAKE_REF(&zresult_cas); ZVAL_COPY(¶ms[0], &zcookie); ZVAL_COPY(¶ms[1], &zkey); @@ -436,11 +450,12 @@ protocol_binary_response_status s_set_replace_handler (php_memc_event_t event, c MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); ZVAL_STRINGL(&zkey, key, key_len); - ZVAL_STRINGL(&zdata, ((char *) data), (int) data_len); - ZVAL_LONG(&zflags, (long) flags); - ZVAL_LONG(&zexpiration, (long) expiration); + ZVAL_STRINGL(&zdata, data, data_len); + ZVAL_LONG(&zflags, (zend_long) flags); + ZVAL_LONG(&zexpiration, (zend_long) expiration); ZVAL_DOUBLE(&zcas, (double) cas); ZVAL_NULL(&zresult_cas); + ZVAL_MAKE_REF(&zresult_cas); ZVAL_COPY(¶ms[0], &zcookie); ZVAL_COPY(¶ms[1], &zkey); @@ -504,6 +519,7 @@ protocol_binary_response_status s_stat_handler (const void *cookie, const void * ZVAL_STRINGL(&zkey, key, key_len); ZVAL_NULL(&zbody); + ZVAL_MAKE_REF(&zbody); ZVAL_COPY(¶ms[0], &zcookie); ZVAL_COPY(¶ms[1], &zkey); @@ -584,17 +600,27 @@ void s_handle_memcached_event (evutil_socket_t fd, short what, void *arg) zval zremoteip, zremoteport; zval params[2]; protocol_binary_response_status retval; - - struct sockaddr_in addr_in; - socklen_t addr_in_len = sizeof(addr_in); - - if (getpeername (fd, (struct sockaddr *) &addr_in, &addr_in_len) == 0) { - ZVAL_STRING(&zremoteip, inet_ntoa (addr_in.sin_addr)); - ZVAL_LONG(&zremoteport, ntohs (addr_in.sin_port)); + struct sockaddr_storage ss; + socklen_t ss_len = sizeof(ss); + + ZVAL_NULL(&zremoteip); + ZVAL_NULL(&zremoteport); + + if (getpeername (fd, (struct sockaddr *) &ss, &ss_len) == 0) { + char addr_buf[0x100]; + + switch (ss.ss_family) { + case AF_INET6: + ZVAL_STRING(&zremoteip, inet_ntop(ss.ss_family, &((struct sockaddr_in6 *) &ss)->sin6_addr, addr_buf, sizeof(addr_buf))); + ZVAL_LONG(&zremoteport, ntohs(((struct sockaddr_in6 *) &ss)->sin6_port)); + break; + case AF_INET: + ZVAL_STRING(&zremoteip, inet_ntop(ss.ss_family, &((struct sockaddr_in *) &ss)->sin_addr, addr_buf, sizeof(addr_buf))); + ZVAL_LONG(&zremoteport, ntohs(((struct sockaddr_in *) &ss)->sin_port)); + break; + } } else { php_error_docref(NULL, E_WARNING, "getpeername failed: %s", strerror (errno)); - ZVAL_NULL(&zremoteip); - ZVAL_NULL(&zremoteport); } ZVAL_COPY(¶ms[0], &zremoteip); @@ -714,22 +740,20 @@ php_memc_proto_handler_t *php_memc_proto_handler_new () } static -evutil_socket_t s_create_listening_socket (const char *spec) +evutil_socket_t s_create_listening_socket (const zend_string *spec) { evutil_socket_t sock; struct sockaddr_storage addr; - int addr_len; - + socklen_t addr_len; int rc; addr_len = sizeof (struct sockaddr); - rc = evutil_parse_sockaddr_port (spec, (struct sockaddr *) &addr, &addr_len); - if (rc != 0) { - php_error_docref(NULL, E_WARNING, "Failed to parse bind address"); + if (SUCCESS != php_network_parse_network_address_with_port(spec->val, spec->len, (struct sockaddr *) &addr, &addr_len)) { + php_error_docref(NULL, E_WARNING, "Failed to parse bind address: %s", spec->val); return -1; } - sock = socket (AF_INET, SOCK_STREAM, 0); + sock = socket (addr.ss_family, SOCK_STREAM, 0); if (sock < 0) { php_error_docref(NULL, E_WARNING, "socket failed: %s", strerror (errno)); return -1; @@ -770,7 +794,7 @@ evutil_socket_t s_create_listening_socket (const char *spec) zend_bool php_memc_proto_handler_run (php_memc_proto_handler_t *handler, zend_string *address) { struct event *accept_event; - evutil_socket_t sock = s_create_listening_socket (address->val); + evutil_socket_t sock = s_create_listening_socket (address); if (sock == -1) { return 0; diff --git a/server-example/run-server.php b/server-example/run-server.php index a02c6a60..a9ba5834 100644 --- a/server-example/run-server.php +++ b/server-example/run-server.php @@ -89,4 +89,4 @@ function ($client_id) { return Memcached::RESPONSE_SUCCESS; }); -$server->run ("127.0.0.1:3434"); \ No newline at end of file +$server->run ("127.0.0.1:3434"); From 46967cc67fb7294893489b8317f5a3cc31b64079 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 19 Jan 2021 16:32:52 +0100 Subject: [PATCH 264/345] use php_network_get_peer_name --- php_memcached_server.c | 38 ++++++++++------------------------- server-example/run-server.php | 4 ++-- 2 files changed, 13 insertions(+), 29 deletions(-) diff --git a/php_memcached_server.c b/php_memcached_server.c index e816b90d..fee8d28d 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -597,41 +597,25 @@ void s_handle_memcached_event (evutil_socket_t fd, short what, void *arg) if (!client->on_connect_invoked) { if (MEMC_HAS_CB(MEMC_SERVER_ON_CONNECT)) { - zval zremoteip, zremoteport; - zval params[2]; + zend_string *zremoteaddr_str; + zval zremoteaddr; + zval params[1]; protocol_binary_response_status retval; - struct sockaddr_storage ss; - socklen_t ss_len = sizeof(ss); - - ZVAL_NULL(&zremoteip); - ZVAL_NULL(&zremoteport); - - if (getpeername (fd, (struct sockaddr *) &ss, &ss_len) == 0) { - char addr_buf[0x100]; - - switch (ss.ss_family) { - case AF_INET6: - ZVAL_STRING(&zremoteip, inet_ntop(ss.ss_family, &((struct sockaddr_in6 *) &ss)->sin6_addr, addr_buf, sizeof(addr_buf))); - ZVAL_LONG(&zremoteport, ntohs(((struct sockaddr_in6 *) &ss)->sin6_port)); - break; - case AF_INET: - ZVAL_STRING(&zremoteip, inet_ntop(ss.ss_family, &((struct sockaddr_in *) &ss)->sin_addr, addr_buf, sizeof(addr_buf))); - ZVAL_LONG(&zremoteport, ntohs(((struct sockaddr_in *) &ss)->sin_port)); - break; - } + + ZVAL_NULL(&zremoteaddr); + + if (SUCCESS == php_network_get_peer_name (fd, &zremoteaddr_str, NULL, NULL)) { + ZVAL_STR(&zremoteaddr, zremoteaddr_str); } else { php_error_docref(NULL, E_WARNING, "getpeername failed: %s", strerror (errno)); } - ZVAL_COPY(¶ms[0], &zremoteip); - ZVAL_COPY(¶ms[1], &zremoteport); + ZVAL_COPY(¶ms[0], &zremoteaddr); - retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_CONNECT), params, 2); + retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_CONNECT), params, 1); zval_ptr_dtor(¶ms[0]); - zval_ptr_dtor(¶ms[1]); - zval_ptr_dtor(&zremoteip); - zval_ptr_dtor(&zremoteport); + zval_ptr_dtor(&zremoteaddr); if (retval != PROTOCOL_BINARY_RESPONSE_SUCCESS) { memcached_protocol_client_destroy (client->protocol_client); diff --git a/server-example/run-server.php b/server-example/run-server.php index a9ba5834..b7612c80 100644 --- a/server-example/run-server.php +++ b/server-example/run-server.php @@ -3,8 +3,8 @@ $server = new MemcachedServer(); $server->on (Memcached::ON_CONNECT, - function ($remote_ip, $remote_port) { - echo "Incoming connection from {$remote_ip}:{$remote_port}" . PHP_EOL; + function ($remote_addr) { + echo "Incoming connection from {$remote_addr}" . PHP_EOL; return Memcached::RESPONSE_SUCCESS; }); From f4f724caf74f506b6121e87b95239a8a11795284 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 19 Jan 2021 16:34:08 +0100 Subject: [PATCH 265/345] remove unused include again --- php_memcached_server.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/php_memcached_server.c b/php_memcached_server.c index fee8d28d..ce93a2bf 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -23,10 +23,6 @@ #include -#if HAVE_ARPA_INET_H -# include -#endif - #define MEMC_GET_CB(cb_type) (MEMC_SERVER_G(callbacks)[cb_type]) #define MEMC_HAS_CB(cb_type) (MEMC_GET_CB(cb_type).fci.size > 0) From 7381ce71b891d8500cecce91da00555366625b5c Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 19 Jan 2021 16:57:39 +0100 Subject: [PATCH 266/345] as per https://github.com/php-memcached-dev/php-memcached/pull/474#issuecomment-762934191 --- php_memcached_server.c | 1 + 1 file changed, 1 insertion(+) diff --git a/php_memcached_server.c b/php_memcached_server.c index ce93a2bf..1f28d936 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -299,6 +299,7 @@ protocol_binary_response_status s_flush_handler(const void *cookie, uint32_t whe } MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); + ZVAL_LONG(&zwhen, when); ZVAL_COPY(¶ms[0], &zcookie); ZVAL_COPY(¶ms[1], &zwhen); From 57f2999ea5113b2b31523c659cfb223a8fd6a5ce Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 20 Jan 2021 10:54:13 +0100 Subject: [PATCH 267/345] add 1 test for MemcachedServer --- tests/memcachedserver.phpt | 58 +++++++++++++++++++++++ tests/server.inc | 78 +++++++++++++++++++++++++++++++ tests/server.php | 94 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 230 insertions(+) create mode 100644 tests/memcachedserver.phpt create mode 100644 tests/server.inc create mode 100644 tests/server.php diff --git a/tests/memcachedserver.phpt b/tests/memcachedserver.phpt new file mode 100644 index 00000000..54b7fe45 --- /dev/null +++ b/tests/memcachedserver.phpt @@ -0,0 +1,58 @@ +--TEST-- +Memcached::get() with cache callback +--SKIPIF-- + +--FILE-- +setOption(Memcached::OPT_BINARY_PROTOCOL, true); +$cache->setOption(Memcached::OPT_COMPRESSION, false); +$cache->addServer('127.0.0.1', 3434); + +$cache->add("add_key", "hello", 500); +$cache->append("append_key", "world"); +$cache->prepend("prepend_key", "world"); + +$cache->increment("incr", 2, 1, 500); +$cache->decrement("decr", 2, 1, 500); + +$cache->delete("delete_k"); +$cache->flush(1); + +var_dump($cache->get('get_this')); + +$cache->set ('set_key', 'value 1', 100); +$cache->replace ('replace_key', 'value 2', 200); + +var_dump($cache->getStats()); + +$cache->quit(); + +memcached_server_stop($server); +?> +Done +--EXPECTF-- +Listening on 127.0.0.1:3434 +Incoming connection from 127.0.0.1:%s +Incoming connection from 127.0.0.1:%s +client_id=[%s]: Add key=[add_key], value=[hello], flags=[0], expiration=[500] +client_id=[%s]: Append key=[append_key], value=[world], cas=[0] +client_id=[%s]: Prepend key=[prepend_key], value=[world], cas=[0] +client_id=[%s]: Incrementing key=[incr], delta=[2], initial=[1], expiration=[500] +client_id=[%s]: Decrementing key=[decr], delta=[2], initial=[1], expiration=[500] +client_id=[%s]: Delete key=[delete_k], cas=[0] +client_id=[%s]: Flush when=[1] +client_id=[%s]: Get key=[get_this] +client_id=[%s]: Noop +string(20) "Hello to you client!" +client_id=[%s]: Set key=[set_key], value=[value 1], flags=[0], expiration=[100], cas=[0] +client_id=[%s]: Replace key=[replace_key], value=[value 2], flags=[0], expiration=[200], cas=[0] +bool(false) +Done diff --git a/tests/server.inc b/tests/server.inc new file mode 100644 index 00000000..96cc942f --- /dev/null +++ b/tests/server.inc @@ -0,0 +1,78 @@ + STDIN, + 1 => STDOUT, + 2 => STDERR, + ); + + $cmd = "{$php_executable} {$php_args} {$code} {$host}:{$port} "; + if (substr(PHP_OS, 0, 3) == 'WIN') { + $cmd = "{$php_executable} {$php_args} {$code} {$host}:{$port} "; + + $handle = proc_open(addslashes($cmd), $descriptorspec, $pipes, __DIR__, NULL, array("bypass_shell" => true, "suppress_errors" => true)); + } else { + $cmd = "exec {$cmd} 2>/dev/null"; + + $handle = proc_open($cmd, $descriptorspec, $pipes, __DIR__); + } + + // note: even when server prints 'Listening on localhost:8964...Press Ctrl-C to quit.' + // it might not be listening yet...need to wait until fsockopen() call returns + $error = "Unable to connect to server\n"; + for ($i=0; $i < 60; $i++) { + usleep(50000); // 50ms per try + $status = proc_get_status($handle); + $fp = @fsockopen($host, $port); + // Failure, the server is no longer running + if (!($status && $status['running'])) { + $error = "Server is not running\n"; + break; + } + // Success, Connected to servers + if ($fp) { + $error = ''; + break; + } + } + + if ($fp) { + fclose($fp); + } + + if ($error) { + echo $error; + proc_terminate($handle); + exit(1); + } + + register_shutdown_function( + function($handle) { + proc_terminate($handle); + }, + $handle + ); + + return $handle; +} + +function memcached_server_stop($handle) { + $success = FALSE; + if ($handle) { + proc_terminate($handle); + /* Wait for server to shutdown */ + for ($i = 0; $i < 60; $i++) { + $status = proc_get_status($handle); + if (!($status && $status['running'])) { + $success = TRUE; + break; + } + usleep(50000); + } + } + return $success; +} + diff --git a/tests/server.php b/tests/server.php new file mode 100644 index 00000000..674f91ac --- /dev/null +++ b/tests/server.php @@ -0,0 +1,94 @@ +on (Memcached::ON_CONNECT, + function ($remote_addr) { + echo "Incoming connection from {$remote_addr}" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_ADD, + function ($client_id, $key, $value, $flags, $expiration, &$cas) { + echo "client_id=[$client_id]: Add key=[$key], value=[$value], flags=[$flags], expiration=[$expiration]" . PHP_EOL; + $cas = 15; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_APPEND, + function ($client_id, $key, $value, $cas, &$result_cas) { + echo "client_id=[$client_id]: Append key=[$key], value=[$value], cas=[$cas]" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_PREPEND, + function ($client_id, $key, $value, $cas, &$result_cas) { + echo "client_id=[$client_id]: Prepend key=[$key], value=[$value], cas=[$cas]" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_INCREMENT, + function ($client_id, $key, $delta, $initial, $expiration, &$result, &$result_cas) { + echo "client_id=[$client_id]: Incrementing key=[$key], delta=[$delta], initial=[$initial], expiration=[$expiration]" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_DECREMENT, + function ($client_id, $key, $delta, $initial, $expiration, &$result, &$result_cas) { + echo "client_id=[$client_id]: Decrementing key=[$key], delta=[$delta], initial=[$initial], expiration=[$expiration]" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_DELETE, + function ($client_id, $key, $cas) { + echo "client_id=[$client_id]: Delete key=[$key], cas=[$cas]" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_FLUSH, + function ($client_id, $when) { + echo "client_id=[$client_id]: Flush when=[$when]" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_GET, + function ($client_id, $key, &$value, &$flags, &$cas) { + echo "client_id=[$client_id]: Get key=[$key]" . PHP_EOL; + $value = "Hello to you client!"; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_NOOP, + function ($client_id) { + echo "client_id=[$client_id]: Noop" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_REPLACE, + function ($client_id, $key, $value, $flags, $expiration, $cas, &$result_cas) { + echo "client_id=[$client_id]: Replace key=[$key], value=[$value], flags=[$flags], expiration=[$expiration], cas=[$cas]" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_SET, + function ($client_id, $key, $value, $flags, $expiration, $cas, &$result_cas) { + echo "client_id=[$client_id]: Set key=[$key], value=[$value], flags=[$flags], expiration=[$expiration], cas=[$cas]" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_STAT, + function ($client_id, $key, &$value) { + echo "client_id=[$client_id]: Stat key=[$key]" . PHP_EOL; + $value = "Stat reply"; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_QUIT, + function ($client_id) { + echo "client_id=[$client_id]: Client quit" . PHP_EOL; + return Memcached::RESPONSE_SUCCESS; + }); + +$addr = ($_SERVER['argv'][1] ?? "127.0.0.1:3434"); +echo "Listening on $addr" . PHP_EOL; +$server->run($addr); From d21814e647f15b654e6fa6009ef49d148e54dffc Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 20 Jan 2021 12:08:53 +0100 Subject: [PATCH 268/345] minor fix for version handler --- php_memcached_server.c | 1 + tests/memcachedserver.phpt | 5 +++-- tests/server.php | 7 +++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/php_memcached_server.c b/php_memcached_server.c index 1f28d936..57cb749b 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -560,6 +560,7 @@ protocol_binary_response_status s_version_handler (const void *cookie, MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); ZVAL_NULL(&zversion); + ZVAL_MAKE_REF(&zversion); ZVAL_COPY(¶ms[0], &zcookie); ZVAL_COPY(¶ms[1], &zversion); diff --git a/tests/memcachedserver.phpt b/tests/memcachedserver.phpt index 54b7fe45..6d4abb9d 100644 --- a/tests/memcachedserver.phpt +++ b/tests/memcachedserver.phpt @@ -31,7 +31,8 @@ var_dump($cache->get('get_this')); $cache->set ('set_key', 'value 1', 100); $cache->replace ('replace_key', 'value 2', 200); -var_dump($cache->getStats()); +// TODO var_dump($cache->getVersion()); +// TODO var_dump($cache->getStats()); $cache->quit(); @@ -54,5 +55,5 @@ client_id=[%s]: Noop string(20) "Hello to you client!" client_id=[%s]: Set key=[set_key], value=[value 1], flags=[0], expiration=[100], cas=[0] client_id=[%s]: Replace key=[replace_key], value=[value 2], flags=[0], expiration=[200], cas=[0] -bool(false) +client_id=[%s]: Client quit Done diff --git a/tests/server.php b/tests/server.php index 674f91ac..c39b04e8 100644 --- a/tests/server.php +++ b/tests/server.php @@ -79,6 +79,13 @@ function ($client_id, $key, $value, $flags, $expiration, $cas, &$result_cas) { $server->on (Memcached::ON_STAT, function ($client_id, $key, &$value) { echo "client_id=[$client_id]: Stat key=[$key]" . PHP_EOL; + $value = "Stat reply for $key"; + return Memcached::RESPONSE_SUCCESS; + }); + +$server->on (Memcached::ON_VERSION, + function ($client_id, &$value) { + echo "client_id=[$client_id]: Version" . PHP_EOL; $value = "Stat reply"; return Memcached::RESPONSE_SUCCESS; }); From 0262e5c8031194736c6985f91a9ba7f2c7eea9db Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Wed, 20 Jan 2021 16:43:57 +0100 Subject: [PATCH 269/345] handle empty STATS key --- php_memcached_server.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/php_memcached_server.c b/php_memcached_server.c index 57cb749b..d1e903a1 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -514,7 +514,11 @@ protocol_binary_response_status s_stat_handler (const void *cookie, const void * MEMC_MAKE_ZVAL_COOKIE(zcookie, cookie); - ZVAL_STRINGL(&zkey, key, key_len); + if (key && key_len) { + ZVAL_STRINGL(&zkey, key, key_len); + } else { + ZVAL_NULL(&zkey); + } ZVAL_NULL(&zbody); ZVAL_MAKE_REF(&zbody); @@ -566,7 +570,6 @@ protocol_binary_response_status s_version_handler (const void *cookie, ZVAL_COPY(¶ms[1], &zversion); retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_VERSION), params, 2); - if (retval == PROTOCOL_BINARY_RESPONSE_SUCCESS) { if (Z_TYPE(zversion) != IS_STRING) { convert_to_string(&zversion); From f064f6c817b899a7c0e8ea089c81163c66a9be05 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Wed, 20 Jan 2021 16:51:34 +0100 Subject: [PATCH 270/345] fix running the server from command line --- tests/server.inc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/server.inc b/tests/server.inc index 96cc942f..5700a9d2 100644 --- a/tests/server.inc +++ b/tests/server.inc @@ -1,7 +1,7 @@ STDIN, @@ -29,7 +29,7 @@ function memcached_server_start($code = 'server.php', $host = "127.0.0.1", $port $fp = @fsockopen($host, $port); // Failure, the server is no longer running if (!($status && $status['running'])) { - $error = "Server is not running\n"; + $error = "Server is not running {$status['command']}\n"; break; } // Success, Connected to servers @@ -75,4 +75,3 @@ function memcached_server_stop($handle) { } return $success; } - From 941ae835441e38e61e5349969f58b120c4ec7506 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Wed, 20 Jan 2021 16:52:31 +0100 Subject: [PATCH 271/345] add stats/version tests --- tests/memcachedserver.phpt | 31 ++++++++++++++++++++++++++++--- tests/server.php | 2 +- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/tests/memcachedserver.phpt b/tests/memcachedserver.phpt index 6d4abb9d..82601e12 100644 --- a/tests/memcachedserver.phpt +++ b/tests/memcachedserver.phpt @@ -1,10 +1,13 @@ --TEST-- -Memcached::get() with cache callback +MemcachedServer --SKIPIF-- --FILE-- get('get_this')); $cache->set ('set_key', 'value 1', 100); $cache->replace ('replace_key', 'value 2', 200); -// TODO var_dump($cache->getVersion()); -// TODO var_dump($cache->getStats()); +var_dump($cache->getVersion()); +var_dump($cache->getStats()); +var_dump($cache->getStats("foobar")); $cache->quit(); @@ -55,5 +59,26 @@ client_id=[%s]: Noop string(20) "Hello to you client!" client_id=[%s]: Set key=[set_key], value=[value 1], flags=[0], expiration=[100], cas=[0] client_id=[%s]: Replace key=[replace_key], value=[value 2], flags=[0], expiration=[200], cas=[0] +client_id=[%s]: Version +array(1) { + ["127.0.0.1:3434"]=> + string(5) "1.1.1" +} +client_id=[%s]: Stat key=[] +array(1) { + ["127.0.0.1:3434"]=> + array(1) { + [""]=> + string(15) "Stat reply for " + } +} +client_id=[%s]: Stat key=[foobar] +array(1) { + ["127.0.0.1:3434"]=> + array(1) { + ["foobar"]=> + string(21) "Stat reply for foobar" + } +} client_id=[%s]: Client quit Done diff --git a/tests/server.php b/tests/server.php index c39b04e8..b6ab1cf6 100644 --- a/tests/server.php +++ b/tests/server.php @@ -86,7 +86,7 @@ function ($client_id, $key, &$value) { $server->on (Memcached::ON_VERSION, function ($client_id, &$value) { echo "client_id=[$client_id]: Version" . PHP_EOL; - $value = "Stat reply"; + $value = "1.1.1"; return Memcached::RESPONSE_SUCCESS; }); From bee6b53d57e18a13e21aa4d5c887b5303228a339 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Wed, 20 Jan 2021 17:42:58 +0100 Subject: [PATCH 272/345] expect an array as STATS value and reply foreach key/value --- php_memcached_server.c | 36 +++++++++++++++++++++++++----------- tests/memcachedserver.phpt | 16 ++++++++++------ tests/server.php | 7 +++++-- 3 files changed, 40 insertions(+), 19 deletions(-) diff --git a/php_memcached_server.c b/php_memcached_server.c index d1e903a1..a166051e 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -506,7 +506,7 @@ protocol_binary_response_status s_stat_handler (const void *cookie, const void * { zval params[3]; protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND; - zval zcookie, zkey, zbody; + zval zcookie, zkey, zstats; if (!MEMC_HAS_CB(MEMC_SERVER_ON_STAT)) { return retval; @@ -519,24 +519,38 @@ protocol_binary_response_status s_stat_handler (const void *cookie, const void * } else { ZVAL_NULL(&zkey); } - ZVAL_NULL(&zbody); - ZVAL_MAKE_REF(&zbody); + ZVAL_NULL(&zstats); + ZVAL_MAKE_REF(&zstats); ZVAL_COPY(¶ms[0], &zcookie); ZVAL_COPY(¶ms[1], &zkey); - ZVAL_COPY(¶ms[2], &zbody); + ZVAL_COPY(¶ms[2], &zstats); retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_STAT), params, 3); if (retval == PROTOCOL_BINARY_RESPONSE_SUCCESS) { - if (Z_TYPE(zbody) == IS_NULL) { + if (Z_ISNULL(zstats)) { retval = response_handler(cookie, NULL, 0, NULL, 0); - } - else { - if (Z_TYPE(zbody) != IS_STRING) { - convert_to_string(&zbody); + } else { + zval *zarray = &zstats; + zend_string *key; + zval *val; + + ZVAL_DEREF(zarray); + if (Z_TYPE_P(zarray) != IS_ARRAY) { + convert_to_array(zarray); + } + + ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(zarray), key, val) + { + zend_string *val_str = zval_get_string(val); + retval = response_handler(cookie, key->val, key->len, val_str->val, val_str->len); + if (retval != PROTOCOL_BINARY_RESPONSE_SUCCESS) { + break; + } + zend_string_release(val_str); } - retval = response_handler(cookie, key, key_len, Z_STRVAL(zbody), (uint32_t) Z_STRLEN(zbody)); + ZEND_HASH_FOREACH_END(); } } @@ -545,7 +559,7 @@ protocol_binary_response_status s_stat_handler (const void *cookie, const void * zval_ptr_dtor(¶ms[2]); zval_ptr_dtor (&zcookie); zval_ptr_dtor (&zkey); - zval_ptr_dtor (&zbody); + zval_ptr_dtor (&zstats); return retval; } diff --git a/tests/memcachedserver.phpt b/tests/memcachedserver.phpt index 82601e12..d47dd73b 100644 --- a/tests/memcachedserver.phpt +++ b/tests/memcachedserver.phpt @@ -67,17 +67,21 @@ array(1) { client_id=[%s]: Stat key=[] array(1) { ["127.0.0.1:3434"]=> - array(1) { - [""]=> - string(15) "Stat reply for " + array(2) { + ["key"]=> + string(0) "" + ["foo"]=> + string(3) "bar" } } client_id=[%s]: Stat key=[foobar] array(1) { ["127.0.0.1:3434"]=> - array(1) { - ["foobar"]=> - string(21) "Stat reply for foobar" + array(2) { + ["key"]=> + string(6) "foobar" + ["foo"]=> + string(3) "bar" } } client_id=[%s]: Client quit diff --git a/tests/server.php b/tests/server.php index b6ab1cf6..f5ff2f6a 100644 --- a/tests/server.php +++ b/tests/server.php @@ -77,9 +77,12 @@ function ($client_id, $key, $value, $flags, $expiration, $cas, &$result_cas) { }); $server->on (Memcached::ON_STAT, - function ($client_id, $key, &$value) { + function ($client_id, $key, array &$values = null) { echo "client_id=[$client_id]: Stat key=[$key]" . PHP_EOL; - $value = "Stat reply for $key"; + $values = [ + "key" => $key, + "foo" => "bar", + ]; return Memcached::RESPONSE_SUCCESS; }); From 984086633264d30fad442c4a2394145f9e014d1a Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Wed, 20 Jan 2021 18:00:52 +0100 Subject: [PATCH 273/345] valgrind --- php_memcached.c | 5 ++++- tests/server.inc | 9 +++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index e7a28e0a..19af8fda 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3925,7 +3925,6 @@ static PHP_GINIT_FUNCTION(php_memcached) { #ifdef HAVE_MEMCACHED_SESSION - php_memcached_globals->session.lock_enabled = 0; php_memcached_globals->session.lock_wait_max = 150; php_memcached_globals->session.lock_wait_min = 150; @@ -3944,8 +3943,12 @@ PHP_GINIT_FUNCTION(php_memcached) php_memcached_globals->session.persistent_enabled = 0; php_memcached_globals->session.sasl_username = NULL; php_memcached_globals->session.sasl_password = NULL; +#endif +#ifdef HAVE_MEMCACHED_PROTOCOL + memset(&php_memcached_globals->server, 0, sizeof(php_memcached_globals->server)); #endif + php_memcached_globals->memc.serializer_name = NULL; php_memcached_globals->memc.serializer_type = SERIALIZER_DEFAULT; php_memcached_globals->memc.compression_name = NULL; diff --git a/tests/server.inc b/tests/server.inc index 5700a9d2..9678f043 100644 --- a/tests/server.inc +++ b/tests/server.inc @@ -23,7 +23,7 @@ function memcached_server_start($code = 'server.php', $host = "127.0.0.1", $port // note: even when server prints 'Listening on localhost:8964...Press Ctrl-C to quit.' // it might not be listening yet...need to wait until fsockopen() call returns $error = "Unable to connect to server\n"; - for ($i=0; $i < 60; $i++) { + for ($i=0; $i < getenv("VALGRIND") ? 1000 : 60; $i++) { usleep(50000); // 50ms per try $status = proc_get_status($handle); $fp = @fsockopen($host, $port); @@ -46,12 +46,16 @@ function memcached_server_start($code = 'server.php', $host = "127.0.0.1", $port if ($error) { echo $error; proc_terminate($handle); + proc_close($handle); exit(1); } register_shutdown_function( function($handle) { - proc_terminate($handle); + if (is_resource($handle)) { + proc_terminate($handle); + proc_close($handle); + } }, $handle ); @@ -72,6 +76,7 @@ function memcached_server_stop($handle) { } usleep(50000); } + proc_close($handle); } return $success; } From 6dc086e721d2d843f240f69ed181575588a9c140 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Thu, 21 Jan 2021 17:28:07 +0100 Subject: [PATCH 274/345] add test files to package.xml --- package.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/package.xml b/package.xml index 519de583..8241d221 100644 --- a/package.xml +++ b/package.xml @@ -173,7 +173,10 @@ Fixes - + + + + From 4b6c45dd23be82abc2fdbf1655700ddd55c09538 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Mon, 25 Jan 2021 14:45:03 +0100 Subject: [PATCH 275/345] implement stats callback suggestions by Remi --- php_memcached_server.c | 45 +++++++++++++++++++++----------------- tests/memcachedserver.phpt | 22 +++++++++++++++++++ tests/server.php | 19 ++++++++++------ 3 files changed, 59 insertions(+), 27 deletions(-) diff --git a/php_memcached_server.c b/php_memcached_server.c index a166051e..24c328f8 100644 --- a/php_memcached_server.c +++ b/php_memcached_server.c @@ -519,7 +519,7 @@ protocol_binary_response_status s_stat_handler (const void *cookie, const void * } else { ZVAL_NULL(&zkey); } - ZVAL_NULL(&zstats); + array_init(&zstats); ZVAL_MAKE_REF(&zstats); ZVAL_COPY(¶ms[0], &zcookie); @@ -529,29 +529,34 @@ protocol_binary_response_status s_stat_handler (const void *cookie, const void * retval = s_invoke_php_callback (&MEMC_GET_CB(MEMC_SERVER_ON_STAT), params, 3); if (retval == PROTOCOL_BINARY_RESPONSE_SUCCESS) { - if (Z_ISNULL(zstats)) { - retval = response_handler(cookie, NULL, 0, NULL, 0); - } else { - zval *zarray = &zstats; - zend_string *key; - zval *val; - - ZVAL_DEREF(zarray); - if (Z_TYPE_P(zarray) != IS_ARRAY) { - convert_to_array(zarray); - } + zval *zarray = &zstats; + zend_string *key; + zend_long idx; + zval *val; + + ZVAL_DEREF(zarray); + if (Z_TYPE_P(zarray) != IS_ARRAY) { + convert_to_array(zarray); + } - ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(zarray), key, val) - { - zend_string *val_str = zval_get_string(val); + ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(zarray), idx, key, val) + { + zend_string *val_str = zval_get_string(val); + + if (key) { retval = response_handler(cookie, key->val, key->len, val_str->val, val_str->len); - if (retval != PROTOCOL_BINARY_RESPONSE_SUCCESS) { - break; - } - zend_string_release(val_str); + } else { + char buf[0x20], *ptr, *end = &buf[sizeof(buf) - 1]; + ptr = zend_print_long_to_buf(end, idx); + retval = response_handler(cookie, ptr, end - ptr, val_str->val, val_str->len); + } + zend_string_release(val_str); + + if (retval != PROTOCOL_BINARY_RESPONSE_SUCCESS) { + break; } - ZEND_HASH_FOREACH_END(); } + ZEND_HASH_FOREACH_END(); } zval_ptr_dtor(¶ms[0]); diff --git a/tests/memcachedserver.phpt b/tests/memcachedserver.phpt index d47dd73b..8d6bf222 100644 --- a/tests/memcachedserver.phpt +++ b/tests/memcachedserver.phpt @@ -37,6 +37,8 @@ $cache->replace ('replace_key', 'value 2', 200); var_dump($cache->getVersion()); var_dump($cache->getStats()); var_dump($cache->getStats("foobar")); +var_dump($cache->getStats("scalar")); +var_dump($cache->getStats("numeric array")); $cache->quit(); @@ -84,5 +86,25 @@ array(1) { string(3) "bar" } } +client_id=[%s]: Stat key=[scalar] +array(1) { + ["127.0.0.1:3434"]=> + array(1) { + [0]=> + string(%d) "you want it, you get it" + } +} +client_id=[%s]: Stat key=[numeric array] +array(1) { + ["127.0.0.1:3434"]=> + array(3) { + [-1]=> + string(3) "one" + [0]=> + string(3) "two" + [1]=> + string(5) "three" + } +} client_id=[%s]: Client quit Done diff --git a/tests/server.php b/tests/server.php index f5ff2f6a..bce4c0bf 100644 --- a/tests/server.php +++ b/tests/server.php @@ -77,13 +77,18 @@ function ($client_id, $key, $value, $flags, $expiration, $cas, &$result_cas) { }); $server->on (Memcached::ON_STAT, - function ($client_id, $key, array &$values = null) { - echo "client_id=[$client_id]: Stat key=[$key]" . PHP_EOL; - $values = [ - "key" => $key, - "foo" => "bar", - ]; - return Memcached::RESPONSE_SUCCESS; + function ($client_id, $key, array &$values) { + echo "client_id=[$client_id]: Stat key=[$key]" . PHP_EOL; + + if ($key === "scalar") { + $values = "you want it, you get it"; + } elseif ($key === "numeric array") { + $values = [-1 => "one", "two", "three"]; + } else { + $values["key"] = $key; + $values["foo"] = "bar"; + } + return Memcached::RESPONSE_SUCCESS; }); $server->on (Memcached::ON_VERSION, From 4e7f20cdb062537d5c4fc7ef0cf5d4e3b912fd13 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Mon, 25 Jan 2021 14:54:24 +0100 Subject: [PATCH 276/345] skip test with libmemcached < 1.1.0 --- tests/memcachedserver.phpt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/memcachedserver.phpt b/tests/memcachedserver.phpt index 8d6bf222..145acfba 100644 --- a/tests/memcachedserver.phpt +++ b/tests/memcachedserver.phpt @@ -8,6 +8,10 @@ if (!extension_loaded("memcached")) { if (!class_exists("MemcachedServer")) { die("skip memcached not built with libmemcachedprotocol support\n"); } + +if (Memcached::LIBMEMCACHED_VERSION_HEX < 0x1001000) { + die("skip needs at least libmemcached 1.1.0\n"); +} ?> --FILE-- Date: Tue, 26 Jan 2021 11:38:12 +0100 Subject: [PATCH 277/345] add IPv6 test --- tests/memcachedserver.phpt | 4 ++ tests/memcachedserver6.phpt | 114 ++++++++++++++++++++++++++++++++++++ tests/server.php | 2 + 3 files changed, 120 insertions(+) create mode 100644 tests/memcachedserver6.phpt diff --git a/tests/memcachedserver.phpt b/tests/memcachedserver.phpt index 145acfba..21ce8d64 100644 --- a/tests/memcachedserver.phpt +++ b/tests/memcachedserver.phpt @@ -40,6 +40,7 @@ $cache->replace ('replace_key', 'value 2', 200); var_dump($cache->getVersion()); var_dump($cache->getStats()); +var_dump($cache->getStats("empty")); var_dump($cache->getStats("foobar")); var_dump($cache->getStats("scalar")); var_dump($cache->getStats("numeric array")); @@ -80,6 +81,9 @@ array(1) { string(3) "bar" } } +client_id=[%s]: Stat key=[empty] +array(0) { +} client_id=[%s]: Stat key=[foobar] array(1) { ["127.0.0.1:3434"]=> diff --git a/tests/memcachedserver6.phpt b/tests/memcachedserver6.phpt new file mode 100644 index 00000000..8ae0b362 --- /dev/null +++ b/tests/memcachedserver6.phpt @@ -0,0 +1,114 @@ +--TEST-- +MemcachedServer +--SKIPIF-- + +--FILE-- +setOption(Memcached::OPT_BINARY_PROTOCOL, true); +$cache->setOption(Memcached::OPT_COMPRESSION, false); +$cache->addServer('[::1]', 3434); + +$cache->add("add_key", "hello", 500); +$cache->append("append_key", "world"); +$cache->prepend("prepend_key", "world"); + +$cache->increment("incr", 2, 1, 500); +$cache->decrement("decr", 2, 1, 500); + +$cache->delete("delete_k"); +$cache->flush(1); + +var_dump($cache->get('get_this')); + +$cache->set ('set_key', 'value 1', 100); +$cache->replace ('replace_key', 'value 2', 200); + +var_dump($cache->getVersion()); +var_dump($cache->getStats()); +var_dump($cache->getStats("empty")); +var_dump($cache->getStats("foobar")); +var_dump($cache->getStats("scalar")); +var_dump($cache->getStats("numeric array")); + +$cache->quit(); + +memcached_server_stop($server); +?> +Done +--EXPECTF-- +Listening on [::1]:3434 +Incoming connection from [::1]:%s +Incoming connection from [::1]:%s +client_id=[%s]: Add key=[add_key], value=[hello], flags=[0], expiration=[500] +client_id=[%s]: Append key=[append_key], value=[world], cas=[0] +client_id=[%s]: Prepend key=[prepend_key], value=[world], cas=[0] +client_id=[%s]: Incrementing key=[incr], delta=[2], initial=[1], expiration=[500] +client_id=[%s]: Decrementing key=[decr], delta=[2], initial=[1], expiration=[500] +client_id=[%s]: Delete key=[delete_k], cas=[0] +client_id=[%s]: Flush when=[1] +client_id=[%s]: Get key=[get_this] +client_id=[%s]: Noop +string(20) "Hello to you client!" +client_id=[%s]: Set key=[set_key], value=[value 1], flags=[0], expiration=[100], cas=[0] +client_id=[%s]: Replace key=[replace_key], value=[value 2], flags=[0], expiration=[200], cas=[0] +client_id=[%s]: Version +array(1) { + ["[::1]:3434"]=> + string(5) "1.1.1" +} +client_id=[%s]: Stat key=[] +array(1) { + ["[::1]:3434"]=> + array(2) { + ["key"]=> + string(0) "" + ["foo"]=> + string(3) "bar" + } +} +client_id=[%s]: Stat key=[empty] +array(0) { +} +client_id=[%s]: Stat key=[foobar] +array(1) { + ["[::1]:3434"]=> + array(2) { + ["key"]=> + string(6) "foobar" + ["foo"]=> + string(3) "bar" + } +} +client_id=[%s]: Stat key=[scalar] +array(1) { + ["[::1]:3434"]=> + array(1) { + [0]=> + string(%d) "you want it, you get it" + } +} +client_id=[%s]: Stat key=[numeric array] +array(1) { + ["[::1]:3434"]=> + array(3) { + [-1]=> + string(3) "one" + [0]=> + string(3) "two" + [1]=> + string(5) "three" + } +} +client_id=[%s]: Client quit +Done diff --git a/tests/server.php b/tests/server.php index bce4c0bf..9a50eb06 100644 --- a/tests/server.php +++ b/tests/server.php @@ -84,6 +84,8 @@ function ($client_id, $key, array &$values) { $values = "you want it, you get it"; } elseif ($key === "numeric array") { $values = [-1 => "one", "two", "three"]; + } elseif ($key === "empty") { + $values = []; } else { $values["key"] = $key; $values["foo"] = "bar"; From 10f449752bb42459f7b29aeaf4583854ccc24678 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Tue, 26 Jan 2021 11:42:37 +0100 Subject: [PATCH 278/345] small sleep to avoid loosing message from subprocess --- tests/memcachedserver.phpt | 1 + tests/memcachedserver6.phpt | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/memcachedserver.phpt b/tests/memcachedserver.phpt index 21ce8d64..7b058d70 100644 --- a/tests/memcachedserver.phpt +++ b/tests/memcachedserver.phpt @@ -46,6 +46,7 @@ var_dump($cache->getStats("scalar")); var_dump($cache->getStats("numeric array")); $cache->quit(); +usleep(50000); memcached_server_stop($server); ?> diff --git a/tests/memcachedserver6.phpt b/tests/memcachedserver6.phpt index 8ae0b362..a2277b4a 100644 --- a/tests/memcachedserver6.phpt +++ b/tests/memcachedserver6.phpt @@ -42,6 +42,7 @@ var_dump($cache->getStats("scalar")); var_dump($cache->getStats("numeric array")); $cache->quit(); +usleep(50000); memcached_server_stop($server); ?> From 13ba74317d7a94f87b9d30e6297fb39142c04d36 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Tue, 27 Jul 2021 08:35:08 +0200 Subject: [PATCH 279/345] Improve phpinfo information - display libmemcached-awesome when used (since 1.1.1) - display both builtime and runtime versions when different --- php_memcached.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index d49cbeb4..0f42a97f 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -4300,7 +4300,22 @@ PHP_MINFO_FUNCTION(memcached) php_info_print_table_start(); php_info_print_table_header(2, "memcached support", "enabled"); php_info_print_table_row(2, "Version", PHP_MEMCACHED_VERSION); - php_info_print_table_row(2, "libmemcached version", memcached_lib_version()); + +#ifdef LIBMEMCACHED_AWESOME + if (strcmp(LIBMEMCACHED_VERSION_STRING, memcached_lib_version())) { + php_info_print_table_row(2, "libmemcached-awesome headers version", LIBMEMCACHED_VERSION_STRING); + php_info_print_table_row(2, "libmemcached-awesome library version", memcached_lib_version()); + } else { + php_info_print_table_row(2, "libmemcached-awesome version", memcached_lib_version()); + } +#else + if (strcmp(LIBMEMCACHED_VERSION_STRING, memcached_lib_version())) { + php_info_print_table_row(2, "libmemcached headers version", LIBMEMCACHED_VERSION_STRING); + php_info_print_table_row(2, "libmemcached library version", memcached_lib_version()); + } else { + php_info_print_table_row(2, "libmemcached version", memcached_lib_version()); + } +#endif #ifdef HAVE_MEMCACHED_SASL php_info_print_table_row(2, "SASL support", "yes"); From 605a8a63a7461983512ce12601e995dad18f5a9b Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 29 Jul 2021 04:55:08 +0200 Subject: [PATCH 280/345] fix zend_dtoa API change in 8.1.0beta1 (#487) --- g_fmt.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/g_fmt.c b/g_fmt.c index 73f82fd0..f456790c 100644 --- a/g_fmt.c +++ b/g_fmt.c @@ -27,12 +27,17 @@ * // Teddy Grenman , 2010-05-18. */ -#include +#include char *php_memcached_g_fmt(register char *b, double x) { register int i, k; register char *s; - int decpt, j, sign; + int decpt, j; +#if PHP_VERSION_ID < 80100 + int sign; +#else + bool sign; +#endif char *b0, *s0, *se; b0 = b; From 6d457155fbdf2c8c4615c04a4beb1a7462d55097 Mon Sep 17 00:00:00 2001 From: Timo Tijhof Date: Mon, 23 Aug 2021 05:56:19 +0100 Subject: [PATCH 281/345] Remove "failed to set key" warning from setMulti (#490) This was introduced in https://github.com/php-memcached-dev/php-memcached/commit/6837d89494, pull https://github.com/php-memcached-dev/php-memcached/pull/214. I suspect it may have been a left-over from debugging something. The test was later changed in 6837d89494 to expect the warning in question, although other similar tests don't encounter such warning currently. It appears no other Memcached methods emit a PHP Warning when they encounter a write read or failure. Instead, they typically turn their return value into boolean false, and provide details via getResultMessage(). The introduction of this warning since php-memcached 3.0 has led to a number of confused consumers (locally #260, #409, #450, and more reports within downstream issue trackers). Closes https://github.com/php-memcached-dev/php-memcached/issues/409. --- php_memcached.c | 5 ++--- tests/experimental/setmulti_badserialize.phpt | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index d49cbeb4..069aa60d 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1907,9 +1907,8 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke str_key = zend_string_init(tmp_key, tmp_len, 0); } - if (!s_memc_write_zval (intern, MEMC_OP_SET, server_key, str_key, value, expiration)) { - php_error_docref(NULL, E_WARNING, "failed to set key %s", ZSTR_VAL(str_key)); - } + /* If this failed to write a value, intern stores the error for the return value */ + s_memc_write_zval (intern, MEMC_OP_SET, server_key, str_key, value, expiration); if (!skey) { zend_string_release (str_key); diff --git a/tests/experimental/setmulti_badserialize.phpt b/tests/experimental/setmulti_badserialize.phpt index eafc7772..2d8dde53 100644 --- a/tests/experimental/setmulti_badserialize.phpt +++ b/tests/experimental/setmulti_badserialize.phpt @@ -42,6 +42,5 @@ try { var_dump($m->getByKey('kef', 'foo')); --EXPECT-- -Memcached::setMultiByKey(): failed to set key foo 1234 int(10) From e6df8ab3f6620cf0b2d4e683753aae846a68b4e5 Mon Sep 17 00:00:00 2001 From: hulk Date: Mon, 23 Aug 2021 12:57:11 +0800 Subject: [PATCH 282/345] FIX: store_retry_count shouldn't be set implicitly (#452) It's wired that store commands would be auto-retry implicitly while the default value of store_retry_count was 2, as well as the timeout, would be 3 times in those store commands which may confuse users. IMHO, the retry should be set explicitly instead of implicitly. --- memcached.ini | 4 ++-- php_memcached.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/memcached.ini b/memcached.ini index c11db719..c54e1fd4 100644 --- a/memcached.ini +++ b/memcached.ini @@ -130,8 +130,8 @@ ; This mechanism allows transparent fail-over to secondary servers when ; set/increment/decrement/setMulti operations fail on the desired server in a multi-server ; environment. -; the default is 2 -;memcached.store_retry_count = 2 +; the default is 0 +;memcached.store_retry_count = 0 ; Sets the default for consistent hashing for new connections. ; (To configure consistent hashing for session connections, diff --git a/php_memcached.c b/php_memcached.c index 069aa60d..0f02878c 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -410,7 +410,7 @@ PHP_INI_BEGIN() MEMC_INI_ENTRY("compression_factor", "1.3", OnUpdateReal, compression_factor) MEMC_INI_ENTRY("compression_threshold", "2000", OnUpdateLong, compression_threshold) MEMC_INI_ENTRY("serializer", SERIALIZER_DEFAULT_NAME, OnUpdateSerializer, serializer_name) - MEMC_INI_ENTRY("store_retry_count", "2", OnUpdateLong, store_retry_count) + MEMC_INI_ENTRY("store_retry_count", "0", OnUpdateLong, store_retry_count) MEMC_INI_BOOL ("default_consistent_hash", "0", OnUpdateBool, default_behavior.consistent_hash_enabled) MEMC_INI_BOOL ("default_binary_protocol", "0", OnUpdateBool, default_behavior.binary_protocol_enabled) From 60a8f9f8810aab2b4cff16b05667c6d4af85ef09 Mon Sep 17 00:00:00 2001 From: mszabo-wikia Date: Mon, 8 Nov 2021 18:18:14 +0100 Subject: [PATCH 283/345] Add GitHub Actions build (#492) travis-ci.org builds have ceased, so this patch adds a GitHub Actions workflow to build and test the extension, as well as a Dependabot configuration file to keep the referenced actions up to date. I've opted to slightly simplify the workflow compared to the Travis build script. For one, I have not included libmemcached protocol support, as most distros do not supply a libmemcached compiled with server protocol support, and previous discussion suggests its usefulness in the context of this extension may be limited.[1] I've also opted to remove multiversion libmemcached testing in favor of using the system libmemcached, as the referenced other versions seem to be old enough for this to hopefully not be a problem. These could conceivably be reintroduced if needed. --- [1] https://github.com/php-memcached-dev/php-memcached/issues/418#issuecomment-449587972 --- .github/dependabot.yml | 6 + .github/workflows/build-and-test.yml | 84 +++++++++ .travis.yml | 39 ---- .travis/travis.sh | 270 --------------------------- 4 files changed, 90 insertions(+), 309 deletions(-) create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/build-and-test.yml delete mode 100644 .travis.yml delete mode 100755 .travis/travis.sh diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..12301490 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml new file mode 100644 index 00000000..eb19d01e --- /dev/null +++ b/.github/workflows/build-and-test.yml @@ -0,0 +1,84 @@ +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental }} + strategy: + fail-fast: false + matrix: + php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0'] + experimental: [false] + include: + - php: '8.1' + experimental: true + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: true + - name: Install PHP ${{ matrix.php }} + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: none, json, igbinary, msgpack + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install libmemcached-dev memcached libsasl2-dev sasl2-bin zlib1g-dev + - name: Start memcached daemons + run: | + export SASL_CONF_PATH="/tmp/sasl2" + mkdir "${SASL_CONF_PATH}" + export MEMCACHED_SASL_PWDB="${SASL_CONF_PATH}/sasldb2" + + # Create configuration + cat< "${SASL_CONF_PATH}/memcached.conf" + mech_list: PLAIN + plainlog_level: 5 + sasldb_path: ${MEMCACHED_SASL_PWDB} + EOF + + echo "test" | /usr/sbin/saslpasswd2 -c memcached -a memcached -f "${MEMCACHED_SASL_PWDB}" + + # Run normal memcached + memcached -d -p 11211 + + # Run memcached on port 11212 with SASL support + memcached -S -d -p 11212 + - name: Build extension + run: | + phpize + ./configure \ + --enable-memcached-protocol=no \ + --enable-memcached-sasl \ + --enable-memcached-json \ + --enable-memcached-msgpack \ + --enable-memcached-igbinary + make + sudo make install + - name: Create test configuration + run: | + cat< tests/config.inc.local + /dev/null - if [ $? != 0 ]; then - echo "Missing $file from package.xml" - retval=1; - fi - done - return $retval -} - -function install_libmemcached() { - - if test -d "${LIBMEMCACHED_PREFIX}" - then - echo "Using cached libmemcached: ${LIBMEMCACHED_PREFIX}" - return - fi - - wget "https://launchpad.net/libmemcached/1.0/${LIBMEMCACHED_VERSION}/+download/libmemcached-${LIBMEMCACHED_VERSION}.tar.gz" -O libmemcached-${LIBMEMCACHED_VERSION}.tar.gz - - tar xvfz libmemcached-${LIBMEMCACHED_VERSION}.tar.gz - pushd "libmemcached-${LIBMEMCACHED_VERSION}" - - local protocol_flag="" - if test "x$ENABLE_PROTOOCOL" = "xyes"; then - protocol_flag="--enable-libmemcachedprotocol" - fi - - ./configure --prefix="$LIBMEMCACHED_PREFIX" $protocol_flag LDFLAGS="-lpthread" - make - make install - popd -} - -function install_igbinary() { - git clone https://github.com/igbinary/igbinary.git - pushd igbinary - phpize - ./configure - make - make install - popd -} - -function install_msgpack() { - git clone https://github.com/msgpack/msgpack-php.git - pushd msgpack-php - phpize - ./configure - make - make install - popd -} - -function install_memcached() { - local prefix="${HOME}/cache/memcached-sasl-${MEMCACHED_VERSION}" - - if test -d "$prefix" - then - echo "Using cached memcached: ${prefix}" - return - fi - - wget http://www.memcached.org/files/memcached-${MEMCACHED_VERSION}.tar.gz -O memcached-${MEMCACHED_VERSION}.tar.gz - tar xfz memcached-${MEMCACHED_VERSION}.tar.gz - - pushd memcached-${MEMCACHED_VERSION} - ./configure --enable-sasl --enable-sasl-pwdb --prefix="${prefix}" - make - make install - popd -} - -function run_memcached() { - local prefix="${HOME}/cache/memcached-sasl-${MEMCACHED_VERSION}" - - export SASL_CONF_PATH="/tmp/sasl2" - - if test -d "${SASL_CONF_PATH}" - then - rm -rf "${SASL_CONF_PATH}" - fi - - mkdir "${SASL_CONF_PATH}" - export MEMCACHED_SASL_PWDB="${SASL_CONF_PATH}/sasldb2" - - # Create configuration - cat< "${SASL_CONF_PATH}/memcached.conf" -mech_list: PLAIN -plainlog_level: 5 -sasldb_path: ${MEMCACHED_SASL_PWDB} -EOF - - echo "test" | /usr/sbin/saslpasswd2 -c memcached -a memcached -f "${MEMCACHED_SASL_PWDB}" - - # Run normal memcached - "${prefix}/bin/memcached" -d -p 11211 - - # Run memcached on port 11212 with SASL support - "${prefix}/bin/memcached" -S -d -p 11212 -} - -function build_php_memcached() { - pear package - mkdir "$PHP_MEMCACHED_BUILD_DIR" - tar xfz "memcached-${PHP_MEMCACHED_VERSION}.tgz" -C "$PHP_MEMCACHED_BUILD_DIR" - pushd "${PHP_MEMCACHED_BUILD_DIR}/memcached-${PHP_MEMCACHED_VERSION}" - phpize - - local protocol_flag="" - if test "x$ENABLE_PROTOCOL" = "xyes"; then - protocol_flag="--enable-memcached-protocol" - fi - - local sasl_flag="--disable-memcached-sasl" - if test "x$ENABLE_SASL" = "xyes"; then - sasl_flag="--enable-memcached-sasl" - fi - - # ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag - ./configure --with-libmemcached-dir="$LIBMEMCACHED_PREFIX" $protocol_flag $sasl_flag --enable-memcached-json --enable-memcached-msgpack --enable-memcached-igbinary - make - make install - popd -} - -function create_memcached_test_configuration() { -cat< "${PHP_MEMCACHED_BUILD_DIR}/memcached-${PHP_MEMCACHED_VERSION}/tests/config.inc.local" - " - exit 1 -fi - -if test "x$LIBMEMCACHED_VERSION" = "x"; then - echo "Usage: $0 " - exit 1 -fi - -if test "x$3" != "x"; then - MEMCACHED_VERSION=$3 -fi - -# the extension version -PHP_MEMCACHED_VERSION=$(php -r '$sxe = simplexml_load_file ("package.xml"); echo (string) $sxe->version->release;') - -# Libmemcached install dir -LIBMEMCACHED_PREFIX="${HOME}/cache/libmemcached-${LIBMEMCACHED_VERSION}" - -# Where to do the build -PHP_MEMCACHED_BUILD_DIR="/tmp/php-memcached-build" - -# Check whether to enable building with protoocol and sasl support -check_protocol_support -check_sasl_support - -echo "Enable protocol: $ENABLE_PROTOOCOL" -echo "Enable sasl: $ENABLE_SASL" - -set -e - -case $ACTION in - before_script) - # validate the package.xml - validate_package_xml || exit 1 - - # Install libmemcached version - install_libmemcached - - # Install igbinary extension - install_igbinary - - # Install msgpack extension - install_msgpack - - install_memcached - run_memcached - ;; - - script) - # Build the extension - build_php_memcached - - # Create configuration - if test "x$ENABLE_SASL" = "xyes"; then - create_memcached_test_configuration - fi - - # Run tests - set +e - run_memcached_tests || exit 1 - ;; - - *) - echo "Unknown action. Valid actions are: before_script and script" - exit 1 - ;; -esac - - - - - From d3b8ce13f13cee3017aa8a00a0cfb2e7709154d8 Mon Sep 17 00:00:00 2001 From: Ruud Kamphuis Date: Mon, 29 Nov 2021 19:58:58 +0100 Subject: [PATCH 284/345] Remove experimental for PHP 8.1 and add PHP 8.2 experimental (#494) --- .github/workflows/build-and-test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index eb19d01e..aa1b22c7 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -7,10 +7,10 @@ jobs: strategy: fail-fast: false matrix: - php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0'] + php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1'] experimental: [false] include: - - php: '8.1' + - php: '8.2' experimental: true steps: - name: Checkout From 7a0623098261c4f9d20a9eb325e33474862a5524 Mon Sep 17 00:00:00 2001 From: lfeng Date: Wed, 29 Dec 2021 16:24:57 +0800 Subject: [PATCH 285/345] fix windows php8 php_stdint.h path --- php_memcached_private.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/php_memcached_private.h b/php_memcached_private.h index 3e1f3586..127ff28c 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -48,7 +48,11 @@ #include #ifdef PHP_WIN32 +#if PHP_VERSION_ID >= 80000 +#include "php_stdint.h" +#else # include "win32/php_stdint.h" +#endif #else /* Used to store the size of the block */ # if defined(HAVE_INTTYPES_H) From 5a8db865c16c95af56769c7e292fc6fe6c70635d Mon Sep 17 00:00:00 2001 From: lfeng Date: Thu, 30 Dec 2021 10:08:48 +0800 Subject: [PATCH 286/345] format code --- php_memcached_private.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php_memcached_private.h b/php_memcached_private.h index 127ff28c..2891d80b 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -48,8 +48,8 @@ #include #ifdef PHP_WIN32 -#if PHP_VERSION_ID >= 80000 -#include "php_stdint.h" +# if PHP_VERSION_ID >= 80000 +# include "php_stdint.h" #else # include "win32/php_stdint.h" #endif From 082615656f80e8654c22de97ed3017233dd18278 Mon Sep 17 00:00:00 2001 From: lfeng Date: Thu, 30 Dec 2021 14:04:09 +0800 Subject: [PATCH 287/345] format code --- php_memcached_private.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php_memcached_private.h b/php_memcached_private.h index 2891d80b..b4b1115b 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -48,8 +48,8 @@ #include #ifdef PHP_WIN32 -# if PHP_VERSION_ID >= 80000 -# include "php_stdint.h" + # if PHP_VERSION_ID >= 80000 + # include "php_stdint.h" #else # include "win32/php_stdint.h" #endif From 8a5ef9ef348f1cb6d3438072acc777b66eeb2ea2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Mar 2022 13:57:02 -0800 Subject: [PATCH 288/345] Bump actions/checkout from 2 to 3 (#505) Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-and-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index aa1b22c7..79b22569 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -14,7 +14,7 @@ jobs: experimental: true steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: submodules: true - name: Install PHP ${{ matrix.php }} From 5bb007e62503cf2730514db742a3d47b2d28f9be Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Mon, 7 Mar 2022 14:47:06 +0100 Subject: [PATCH 289/345] Prepare 3.2.0RC1 --- package.xml | 49 +++++++++++++++++++++++++++++++++++++------------ php_memcached.h | 2 +- 2 files changed, 38 insertions(+), 13 deletions(-) diff --git a/package.xml b/package.xml index 8241d221..99a1b204 100644 --- a/package.xml +++ b/package.xml @@ -27,24 +27,27 @@ http://pear.php.net/dtd/package-2.0.xsd"> aaron@serendipity.cx yes - 2019-12-03 + + Remi Collet + remi + remi@php.net + yes + + 2022-03-07 - 3.1.5 - 3.0.0 + 3.2.0RC1 + 3.2.0 - stable - stable + beta + beta PHP -PHP 7.0 - 7.1 - 7.2 - 7.3 - 7.4 release of memcached extension. Note that support for -libmemcached 0.x series has been discontinued and the oldest actively tested -version is 1.0.8. It is highly recommended to use version 1.0.18 of -libmemcached. - -Fixes - * Fix build with PHP 7.4 release due to ulong typedef removal (#445) +- PHP 8.0 and 8.1 support +- store_retry_count is no more set explicitly (#452) +- fix MemcachedServer (libmemcached-awesome is recommended) +- code cleanup @@ -177,6 +180,7 @@ Fixes + @@ -213,6 +217,27 @@ Fixes + + 2019-12-03 + + 3.1.5 + 3.0.0 + + + stable + stable + + PHP + +PHP 7.0 - 7.1 - 7.2 - 7.3 - 7.4 release of memcached extension. Note that support for +libmemcached 0.x series has been discontinued and the oldest actively tested +version is 1.0.8. It is highly recommended to use version 1.0.18 of +libmemcached. + +Fixes + * Fix build with PHP 7.4 release due to ulong typedef removal (#445) + + stable diff --git a/php_memcached.h b/php_memcached.h index cccb6d47..f53f4a5c 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.1.5" +#define PHP_MEMCACHED_VERSION "3.2.0RC1" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From e45fef86348b3fb58779f3cb601d7a0d8b425c5e Mon Sep 17 00:00:00 2001 From: Pavel Djundik Date: Fri, 18 Feb 2022 00:03:42 +0200 Subject: [PATCH 290/345] Create gh_500.phpt --- package.xml | 1 + tests/gh_500.phpt | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tests/gh_500.phpt diff --git a/package.xml b/package.xml index 99a1b204..90844f21 100644 --- a/package.xml +++ b/package.xml @@ -107,6 +107,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> + diff --git a/tests/gh_500.phpt b/tests/gh_500.phpt new file mode 100644 index 00000000..366138db --- /dev/null +++ b/tests/gh_500.phpt @@ -0,0 +1,25 @@ +--TEST-- +Test for Github issue 500 +--SKIPIF-- + +--FILE-- +addServers($newServers); + +$m->set('floatpoint', 100.2); +$n = $m->get('floatpoint'); +var_dump($n); + +$m->set('floatpoint_neg', -300.4); +$n = $m->get('floatpoint_neg'); +var_dump($n); +?> +--EXPECT-- +float(100.2) +float(-300.4) From 857b8afab80592f56349ace1f6d02f9002a1189d Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 9 Mar 2022 11:17:17 +0100 Subject: [PATCH 291/345] 8.x is supported + libmemcached-awesome --- README.markdown | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.markdown b/README.markdown index 31f57b16..8819caf9 100644 --- a/README.markdown +++ b/README.markdown @@ -23,7 +23,7 @@ Dependencies ------------ php-memcached 3.x: -* Supports PHP 7.0 - 7.4. +* Supports PHP 7.0 - 8.1. * Requires libmemcached 1.x or higher. * Optionally supports igbinary 2.0 or higher. * Optionally supports msgpack 2.0 or higher. @@ -34,9 +34,10 @@ php-memcached 2.x: * Optionally supports igbinary 1.0 or higher. * Optionally supports msgpack 0.5 or higher. -[libmemcached](http://libmemcached.org/libMemcached.html) version 1.0.18 or -higher is recommended for best performance and compatibility with memcached -servers. +[libmemcached](http://libmemcached.org/libMemcached.html) or the new +[libmemcached-awesome](https://github.com/awesomized/libmemcached) version +1.0.18 or higher is recommended for best performance and compatibility with +memcached servers. [igbinary](https://github.com/igbinary/igbinary) is a faster and more compact binary serializer for PHP data structures. When installing php-memcached from From c7433c9a53e6b8cafd28ca8a0aee6474763fc02d Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 9 Mar 2022 14:22:40 +0100 Subject: [PATCH 292/345] Fix MSVC builds wrt. ssize_t The Windows SDK does not define `ssize_t`, so libmemcached does not define `HAVE_SSIZE_T`. However, PHP's config.w32.h has `#define ssize_t SSIZE_T`, so building memcached fails. We fix this by defining `HAVE_SSIZE_T` via the extension's `CFLAGS`. --- config.w32 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.w32 b/config.w32 index 9c84a059..7ca3a498 100644 --- a/config.w32 +++ b/config.w32 @@ -36,7 +36,7 @@ if (PHP_MEMCACHED == "yes") { } } - EXTENSION("memcached", "php_memcached.c php_libmemcached_compat.c g_fmt.c"+memcached_extra_src); + EXTENSION("memcached", "php_memcached.c php_libmemcached_compat.c g_fmt.c"+memcached_extra_src, null, " /DHAVE_SSIZE_T"); ADD_SOURCES(configure_module_dirname+"\\fastlz", "fastlz.c", "memcached"); AC_DEFINE("HAVE_MEMCACHED", 1, "memcached support"); AC_DEFINE("MEMCACHED_EXPORTS", 1) From 1f4b029003896f8f891041070dc7f90ead45dff3 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 9 Mar 2022 14:30:51 +0100 Subject: [PATCH 293/345] [ci skip] fix windows build in changelog --- package.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/package.xml b/package.xml index 90844f21..cf13e03b 100644 --- a/package.xml +++ b/package.xml @@ -48,6 +48,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> - store_retry_count is no more set explicitly (#452) - fix MemcachedServer (libmemcached-awesome is recommended) - code cleanup +- fix windows build From ca0d9392cb1f32754df99b2035fc3b3f0ddf493d Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 9 Mar 2022 14:34:33 +0100 Subject: [PATCH 294/345] Prepare 3.2.0RC2 --- package.xml | 4 ++-- php_memcached.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.xml b/package.xml index cf13e03b..18926a80 100644 --- a/package.xml +++ b/package.xml @@ -33,9 +33,9 @@ http://pear.php.net/dtd/package-2.0.xsd"> remi@php.net yes - 2022-03-07 + 2022-03-09 - 3.2.0RC1 + 3.2.0RC2 3.2.0 diff --git a/php_memcached.h b/php_memcached.h index f53f4a5c..5fb082f3 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.2.0RC1" +#define PHP_MEMCACHED_VERSION "3.2.0RC2" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 4694a665d23a39854cbb978a9bdbb566a2a90585 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 9 Mar 2022 14:49:44 +0100 Subject: [PATCH 295/345] Adhere to standard naming convention of Windows libs for PHP The memcached library is usually named libmemcached.lib, so we should check for this name, too. --- config.w32 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.w32 b/config.w32 index 7ca3a498..51aa3bd0 100644 --- a/config.w32 +++ b/config.w32 @@ -8,7 +8,7 @@ ARG_ENABLE('memcached-json', 'whether to enable memcached json serializer suppor if (PHP_MEMCACHED == "yes") { - if (!CHECK_LIB("memcached.lib", "memcached", PHP_MEMCACHED)) { + if (!CHECK_LIB("memcached.lib;libmemcached.lib", "memcached", PHP_MEMCACHED)) { ERROR("memcached: library 'memcached' not found"); } From d1cb3ae87be5382444322118f87324f4044d13b0 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 24 Mar 2022 13:57:18 +0100 Subject: [PATCH 296/345] Prepare 3.2.0 --- package.xml | 8 ++++---- php_memcached.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.xml b/package.xml index 18926a80..761c9584 100644 --- a/package.xml +++ b/package.xml @@ -33,14 +33,14 @@ http://pear.php.net/dtd/package-2.0.xsd"> remi@php.net yes - 2022-03-09 + 2022-03-24 - 3.2.0RC2 + 3.2.0 3.2.0 - beta - beta + stable + stable PHP diff --git a/php_memcached.h b/php_memcached.h index 5fb082f3..dfb3444d 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.2.0RC2" +#define PHP_MEMCACHED_VERSION "3.2.0" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 09e094d3909ceb97bd98ccb658b5a7b6637650a4 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 24 Mar 2022 14:02:06 +0100 Subject: [PATCH 297/345] back to dev --- package.xml | 27 +++++++++++++++++++++------ php_memcached.h | 2 +- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/package.xml b/package.xml index 761c9584..9dc283be 100644 --- a/package.xml +++ b/package.xml @@ -35,7 +35,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> 2022-03-24 - 3.2.0 + 3.2.1dev 3.2.0 @@ -44,11 +44,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> PHP -- PHP 8.0 and 8.1 support -- store_retry_count is no more set explicitly (#452) -- fix MemcachedServer (libmemcached-awesome is recommended) -- code cleanup -- fix windows build +- @@ -219,6 +215,25 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + 2022-03-24 + + 3.2.0 + 3.2.0 + + + stable + stable + + PHP + +- PHP 8.0 and 8.1 support +- store_retry_count is no more set explicitly (#452) +- fix MemcachedServer (libmemcached-awesome is recommended) +- code cleanup +- fix windows build + + 2019-12-03 diff --git a/php_memcached.h b/php_memcached.h index dfb3444d..e966d19d 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.2.0" +#define PHP_MEMCACHED_VERSION "3.2.1-dev" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 1f22de74379208d9758ba99a9bd7373eefeb48f2 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Mon, 28 Mar 2022 08:09:29 +0200 Subject: [PATCH 298/345] fix #513 skip test with old and dead libmemcached --- tests/memcachedserver.phpt | 1 - tests/memcachedserver6.phpt | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/memcachedserver.phpt b/tests/memcachedserver.phpt index 7b058d70..407fcf97 100644 --- a/tests/memcachedserver.phpt +++ b/tests/memcachedserver.phpt @@ -8,7 +8,6 @@ if (!extension_loaded("memcached")) { if (!class_exists("MemcachedServer")) { die("skip memcached not built with libmemcachedprotocol support\n"); } - if (Memcached::LIBMEMCACHED_VERSION_HEX < 0x1001000) { die("skip needs at least libmemcached 1.1.0\n"); } diff --git a/tests/memcachedserver6.phpt b/tests/memcachedserver6.phpt index a2277b4a..3d02b244 100644 --- a/tests/memcachedserver6.phpt +++ b/tests/memcachedserver6.phpt @@ -8,6 +8,9 @@ if (!extension_loaded("memcached")) { if (!class_exists("MemcachedServer")) { die("skip memcached not built with libmemcachedprotocol support\n"); } +if (Memcached::LIBMEMCACHED_VERSION_HEX < 0x1001000) { + die("skip needs at least libmemcached 1.1.0\n"); +} ?> --FILE-- Date: Fri, 3 Jun 2022 16:56:00 +0200 Subject: [PATCH 299/345] fix ${var} deprecation --- tests/touch_binary.phpt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/touch_binary.phpt b/tests/touch_binary.phpt index 382c1778..059ec74c 100644 --- a/tests/touch_binary.phpt +++ b/tests/touch_binary.phpt @@ -28,12 +28,12 @@ function status_print ($op, $mem, $expected) $code = $mem->getResultcode(); if ($code == $expected) - echo "${op} status code as expected" . PHP_EOL; + echo "{$op} status code as expected" . PHP_EOL; else { $expected = resolve_to_constant ($expected); $code = resolve_to_constant ($code); - echo "${op} status code mismatch, expected ${expected} but got ${code}" . PHP_EOL; + echo "{$op} status code mismatch, expected {$expected} but got {$code}" . PHP_EOL; } } From ce2dfa5e649e01e4b4df925ebaef95ca75a3f353 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 28 Jul 2022 09:28:33 +0200 Subject: [PATCH 300/345] mark password as a sensitive param for 8.2 (#516) * mark password as a sensitive param for 8.2 --- php_memcached.c | 7 +++---- php_memcached.stub.php | 6 +++--- php_memcached_arginfo.h | 37 +++++++++++++++++++++++++++++----- php_memcached_legacy_arginfo.h | 30 ++++++++++++++++++++++----- 4 files changed, 63 insertions(+), 17 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 73deaf64..7ccc9b58 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3898,6 +3898,7 @@ PHP_METHOD(MemcachedServer, on) #if PHP_VERSION_ID < 80000 #include "php_memcached_legacy_arginfo.h" #else +#include "zend_attributes.h" #include "php_memcached_arginfo.h" #endif @@ -4254,8 +4255,7 @@ PHP_MINIT_FUNCTION(memcached) le_memc = zend_register_list_destructors_ex(NULL, php_memc_dtor, "Memcached persistent connection", module_number); - INIT_CLASS_ENTRY(ce, "Memcached", class_Memcached_methods); - memcached_ce = zend_register_internal_class(&ce); + memcached_ce = register_class_Memcached(); memcached_ce->create_object = php_memc_object_new; #ifdef HAVE_MEMCACHED_PROTOCOL @@ -4264,8 +4264,7 @@ PHP_MINIT_FUNCTION(memcached) memcached_server_object_handlers.clone_obj = NULL; memcached_server_object_handlers.free_obj = php_memc_server_free_storage; - INIT_CLASS_ENTRY(ce, "MemcachedServer", class_MemcachedServer_methods); - memcached_server_ce = zend_register_internal_class(&ce); + memcached_server_ce = register_class_MemcachedServer(); memcached_server_ce->create_object = php_memc_server_new; #endif diff --git a/php_memcached.stub.php b/php_memcached.stub.php index 819186f4..a44b1801 100644 --- a/php_memcached.stub.php +++ b/php_memcached.stub.php @@ -3,9 +3,9 @@ /** * @generate-function-entries * @generate-legacy-arginfo + * @generate-class-entries */ - class Memcached { public function __construct(?string $persistent_id=null, ?callable $callback=null, ?string $connection_str=null) {} @@ -75,7 +75,7 @@ public function setOption(int $option, mixed $value): bool {} public function setOptions(array $options): bool {} public function setBucket(array $host_map, ?array $forward_map, int $replicas): bool {} #ifdef HAVE_MEMCACHED_SASL - public function setSaslAuthData(string $username, string $password): bool {} + public function setSaslAuthData(string $username, #[\SensitiveParameter] string $password): bool {} #endif #ifdef HAVE_MEMCACHED_SET_ENCODING_KEY @@ -86,7 +86,7 @@ public function isPristine(): bool {} public function checkKey(string $key): bool {} } -#ifdef HAVE_MEMCACHED_PROTOCOL +#if defined(HAVE_MEMCACHED_PROTOCOL) class MemcachedServer { public function run(string $address): bool {} diff --git a/php_memcached_arginfo.h b/php_memcached_arginfo.h index 3373624e..3108e39f 100644 --- a/php_memcached_arginfo.h +++ b/php_memcached_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 3f4694d4e1f3d1647a832acd8539b056b2ab5e7a */ + * Stub hash: 0964c9bfee903e59b63e5a16bd8b6611d827b151 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, persistent_id, IS_STRING, 1, "null") @@ -406,12 +406,39 @@ static const zend_function_entry class_Memcached_methods[] = { }; -static const zend_function_entry class_MemcachedServer_methods[] = { #if defined(HAVE_MEMCACHED_PROTOCOL) +static const zend_function_entry class_MemcachedServer_methods[] = { ZEND_ME(MemcachedServer, run, arginfo_class_MemcachedServer_run, ZEND_ACC_PUBLIC) -#endif -#if defined(HAVE_MEMCACHED_PROTOCOL) ZEND_ME(MemcachedServer, on, arginfo_class_MemcachedServer_on, ZEND_ACC_PUBLIC) -#endif ZEND_FE_END }; +#endif + +static zend_class_entry *register_class_Memcached(void) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "Memcached", class_Memcached_methods); + class_entry = zend_register_internal_class_ex(&ce, NULL); +#if (PHP_VERSION_ID >= 80200) + +#if defined(HAVE_MEMCACHED_SASL) + + zend_add_parameter_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "setsaslauthdata", sizeof("setsaslauthdata") - 1), 1, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); +#endif +#endif + + return class_entry; +} + +#if defined(HAVE_MEMCACHED_PROTOCOL) +static zend_class_entry *register_class_MemcachedServer(void) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "MemcachedServer", class_MemcachedServer_methods); + class_entry = zend_register_internal_class_ex(&ce, NULL); + + return class_entry; +} +#endif diff --git a/php_memcached_legacy_arginfo.h b/php_memcached_legacy_arginfo.h index ad6d6562..6bb8e2d6 100644 --- a/php_memcached_legacy_arginfo.h +++ b/php_memcached_legacy_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 3f4694d4e1f3d1647a832acd8539b056b2ab5e7a */ + * Stub hash: 0964c9bfee903e59b63e5a16bd8b6611d827b151 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) ZEND_ARG_INFO(0, persistent_id) @@ -402,12 +402,32 @@ static const zend_function_entry class_Memcached_methods[] = { }; -static const zend_function_entry class_MemcachedServer_methods[] = { #if defined(HAVE_MEMCACHED_PROTOCOL) +static const zend_function_entry class_MemcachedServer_methods[] = { ZEND_ME(MemcachedServer, run, arginfo_class_MemcachedServer_run, ZEND_ACC_PUBLIC) -#endif -#if defined(HAVE_MEMCACHED_PROTOCOL) ZEND_ME(MemcachedServer, on, arginfo_class_MemcachedServer_on, ZEND_ACC_PUBLIC) -#endif ZEND_FE_END }; +#endif + +static zend_class_entry *register_class_Memcached(void) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "Memcached", class_Memcached_methods); + class_entry = zend_register_internal_class_ex(&ce, NULL); + + return class_entry; +} + +#if defined(HAVE_MEMCACHED_PROTOCOL) +static zend_class_entry *register_class_MemcachedServer(void) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "MemcachedServer", class_MemcachedServer_methods); + class_entry = zend_register_internal_class_ex(&ce, NULL); + + return class_entry; +} +#endif From 3ff7436dd9ff6b7951f5e9e93cc35242b41a26a8 Mon Sep 17 00:00:00 2001 From: LeoLee Date: Wed, 31 Aug 2022 03:41:08 +0800 Subject: [PATCH 301/345] Windows msgpack support (#518) Co-authored-by: lfeng --- config.w32 | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/config.w32 b/config.w32 index 51aa3bd0..76d4ee3c 100644 --- a/config.w32 +++ b/config.w32 @@ -5,6 +5,7 @@ ARG_ENABLE('memcached', 'libmemcached extension', 'no'); ARG_ENABLE('memcached-session', 'whether to enable memcached session handler support', 'no'); ARG_ENABLE('memcached-igbinary', 'whether to enable memcached igbinary serializer support', 'no'); ARG_ENABLE('memcached-json', 'whether to enable memcached json serializer support', 'no'); +ARG_ENABLE('memcached-msgpack', 'whether to enable memcached msgpack serializer support', 'no'); if (PHP_MEMCACHED == "yes") { @@ -35,7 +36,13 @@ if (PHP_MEMCACHED == "yes") { ERROR("memcached: header 'igbinary.h' not found"); } } - + if (PHP_MEMCACHED_MSGPACK != "no"){ + AC_DEFINE("HAVE_MEMCACHED_MSGPACK",1); + ADD_EXTENSION_DEP("memcached", "msgpack", true); + if (!CHECK_HEADER_ADD_INCLUDE("php_msgpack.h", "CFLAGS_MEMCACHED")) { + ERROR("memcached: header 'php_msgpack.h' not found"); + } + } EXTENSION("memcached", "php_memcached.c php_libmemcached_compat.c g_fmt.c"+memcached_extra_src, null, " /DHAVE_SSIZE_T"); ADD_SOURCES(configure_module_dirname+"\\fastlz", "fastlz.c", "memcached"); AC_DEFINE("HAVE_MEMCACHED", 1, "memcached support"); From aa4868d0f1e91ad08f59fa93c60756587a26f8e5 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Tue, 27 Sep 2022 16:35:41 +0100 Subject: [PATCH 302/345] Put false in union types at the end --- php_memcached.stub.php | 26 +++++++++++++------------- php_memcached_arginfo.h | 16 ++++++++-------- php_memcached_legacy_arginfo.h | 2 +- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/php_memcached.stub.php b/php_memcached.stub.php index a44b1801..80cd44ca 100644 --- a/php_memcached.stub.php +++ b/php_memcached.stub.php @@ -15,12 +15,12 @@ public function getResultMessage(): string {} public function get(string $key, ?callable $cache_cb=null, int $get_flags=0): mixed {} public function getByKey(string $server_key, string $key, ?callable $cache_cb=null, int $get_flags=0): mixed {} - public function getMulti(array $keys, int $get_flags=0): false|array {} - public function getMultiByKey(string $server_key, array $keys, int $get_flags=0): false|array {} + public function getMulti(array $keys, int $get_flags=0): array|false {} + public function getMultiByKey(string $server_key, array $keys, int $get_flags=0): array|false {} public function getDelayed(array $keys, bool $with_cas=false, ?callable $value_cb=null): bool {} public function getDelayedByKey(string $server_key, array $keys, bool $with_cas=false, ?callable $value_cb=null): bool {} - public function fetch(): false|array {} - public function fetchAll(): false|array {} + public function fetch(): array|false {} + public function fetchAll(): array|false {} public function set(string $key, mixed $value, int $expiration=0): bool {} public function setByKey(string $server_key, string $key, mixed $value, int $expiration=0): bool {} @@ -46,15 +46,15 @@ public function deleteMulti(array $keys, int $time=0): array {} public function deleteByKey(string $server_key, string $key, int $time=0): bool {} public function deleteMultiByKey(string $server_key, array $keys, int $time=0): array {} - public function increment(string $key, int $offset=1, int $initial_value=0, int $expiry=0): false|int {} - public function decrement(string $key, int $offset=1, int $initial_value=0, int $expiry=0): false|int {} - public function incrementByKey(string $server_key, string $key, int $offset=1, int $initial_value=0, int $expiry=0): false|int {} - public function decrementByKey(string $server_key, string $key, int $offset=1, int $initial_value=0, int $expiry=0): false|int {} + public function increment(string $key, int $offset=1, int $initial_value=0, int $expiry=0): int|false {} + public function decrement(string $key, int $offset=1, int $initial_value=0, int $expiry=0): int|false {} + public function incrementByKey(string $server_key, string $key, int $offset=1, int $initial_value=0, int $expiry=0): int|false {} + public function decrementByKey(string $server_key, string $key, int $offset=1, int $initial_value=0, int $expiry=0): int|false {} public function addServer(string $host, int $port, int $weight=0): bool {} public function addServers(array $servers): bool {} public function getServerList(): array {} - public function getServerByKey(string $server_key): false|array {} + public function getServerByKey(string $server_key): array|false {} public function resetServerList(): bool {} public function quit(): bool {} public function flushBuffers(): bool {} @@ -62,11 +62,11 @@ public function flushBuffers(): bool {} public function getLastErrorMessage(): string {} public function getLastErrorCode(): int {} public function getLastErrorErrno(): int {} - public function getLastDisconnectedServer(): false|array {} + public function getLastDisconnectedServer(): array|false {} - public function getStats(?string $type=null): false|array {} - public function getVersion(): false|array {} - public function getAllKeys(): false|array {} + public function getStats(?string $type=null): array|false {} + public function getVersion(): array|false {} + public function getAllKeys(): array|false {} public function flush(int $delay=0): bool {} diff --git a/php_memcached_arginfo.h b/php_memcached_arginfo.h index 3108e39f..2b6ef282 100644 --- a/php_memcached_arginfo.h +++ b/php_memcached_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 0964c9bfee903e59b63e5a16bd8b6611d827b151 */ + * Stub hash: 8cb8a18e8e09c6bfc62a51fc31d60171038500ef */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, persistent_id, IS_STRING, 1, "null") @@ -26,12 +26,12 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getByKey, 0, 2, ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, get_flags, IS_LONG, 0, "0") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getMulti, 0, 1, MAY_BE_FALSE|MAY_BE_ARRAY) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getMulti, 0, 1, MAY_BE_ARRAY|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, keys, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, get_flags, IS_LONG, 0, "0") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getMultiByKey, 0, 2, MAY_BE_FALSE|MAY_BE_ARRAY) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getMultiByKey, 0, 2, MAY_BE_ARRAY|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, keys, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, get_flags, IS_LONG, 0, "0") @@ -50,7 +50,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getDelayedByKey, ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value_cb, IS_CALLABLE, 1, "null") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_fetch, 0, 0, MAY_BE_FALSE|MAY_BE_ARRAY) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_fetch, 0, 0, MAY_BE_ARRAY|MAY_BE_FALSE) ZEND_END_ARG_INFO() #define arginfo_class_Memcached_fetchAll arginfo_class_Memcached_fetch @@ -150,7 +150,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_deleteMultiByKey ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, time, IS_LONG, 0, "0") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_increment, 0, 1, MAY_BE_FALSE|MAY_BE_LONG) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_increment, 0, 1, MAY_BE_LONG|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, offset, IS_LONG, 0, "1") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, initial_value, IS_LONG, 0, "0") @@ -159,7 +159,7 @@ ZEND_END_ARG_INFO() #define arginfo_class_Memcached_decrement arginfo_class_Memcached_increment -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_incrementByKey, 0, 2, MAY_BE_FALSE|MAY_BE_LONG) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_incrementByKey, 0, 2, MAY_BE_LONG|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, offset, IS_LONG, 0, "1") @@ -182,7 +182,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getServerList, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getServerByKey, 0, 1, MAY_BE_FALSE|MAY_BE_ARRAY) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getServerByKey, 0, 1, MAY_BE_ARRAY|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0) ZEND_END_ARG_INFO() @@ -201,7 +201,7 @@ ZEND_END_ARG_INFO() #define arginfo_class_Memcached_getLastDisconnectedServer arginfo_class_Memcached_fetch -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getStats, 0, 0, MAY_BE_FALSE|MAY_BE_ARRAY) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getStats, 0, 0, MAY_BE_ARRAY|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, type, IS_STRING, 1, "null") ZEND_END_ARG_INFO() diff --git a/php_memcached_legacy_arginfo.h b/php_memcached_legacy_arginfo.h index 6bb8e2d6..81edffa0 100644 --- a/php_memcached_legacy_arginfo.h +++ b/php_memcached_legacy_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 0964c9bfee903e59b63e5a16bd8b6611d827b151 */ + * Stub hash: 8cb8a18e8e09c6bfc62a51fc31d60171038500ef */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) ZEND_ARG_INFO(0, persistent_id) From 121473118ab13b4993c6623f4a63a7e91ce61261 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Mon, 14 Nov 2022 08:43:03 +0100 Subject: [PATCH 303/345] Fix #523 Incorrect PHP reflection type for Memcached::cas $cas_token --- php_memcached.stub.php | 4 ++-- php_memcached_arginfo.h | 6 +++--- php_memcached_legacy_arginfo.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/php_memcached.stub.php b/php_memcached.stub.php index 80cd44ca..7e85ef32 100644 --- a/php_memcached.stub.php +++ b/php_memcached.stub.php @@ -31,8 +31,8 @@ public function touchByKey(string $server_key, string $key, int $expiration=0): public function setMulti(array $items, int $expiration=0): bool {} public function setMultiByKey(string $server_key, array $items, int $expiration=0): bool {} - public function cas(string $cas_token, string $key, mixed $value, int $expiration=0): bool {} - public function casByKey(string $cas_token, string $server_key, string $key, mixed $value, int $expiration=0): bool {} + public function cas(string|int|float $cas_token, string $key, mixed $value, int $expiration=0): bool {} + public function casByKey(string|int|float $cas_token, string $server_key, string $key, mixed $value, int $expiration=0): bool {} public function add(string $key, mixed $value, int $expiration=0): bool {} public function addByKey(string $server_key, string $key, mixed $value, int $expiration=0): bool {} public function append(string $key, string $value): ?bool {} diff --git a/php_memcached_arginfo.h b/php_memcached_arginfo.h index 2b6ef282..e8b999de 100644 --- a/php_memcached_arginfo.h +++ b/php_memcached_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 8cb8a18e8e09c6bfc62a51fc31d60171038500ef */ + * Stub hash: 75604abd7f58655a9ebda6f0ea579840311c1f08 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, persistent_id, IS_STRING, 1, "null") @@ -91,14 +91,14 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_setMultiByKey, 0 ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_cas, 0, 3, _IS_BOOL, 0) - ZEND_ARG_TYPE_INFO(0, cas_token, IS_STRING, 0) + ZEND_ARG_TYPE_MASK(0, cas_token, MAY_BE_STRING|MAY_BE_LONG|MAY_BE_DOUBLE, NULL) ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, value, IS_MIXED, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, expiration, IS_LONG, 0, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_casByKey, 0, 4, _IS_BOOL, 0) - ZEND_ARG_TYPE_INFO(0, cas_token, IS_STRING, 0) + ZEND_ARG_TYPE_MASK(0, cas_token, MAY_BE_STRING|MAY_BE_LONG|MAY_BE_DOUBLE, NULL) ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, value, IS_MIXED, 0) diff --git a/php_memcached_legacy_arginfo.h b/php_memcached_legacy_arginfo.h index 81edffa0..66d5bb91 100644 --- a/php_memcached_legacy_arginfo.h +++ b/php_memcached_legacy_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 8cb8a18e8e09c6bfc62a51fc31d60171038500ef */ + * Stub hash: 75604abd7f58655a9ebda6f0ea579840311c1f08 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0) ZEND_ARG_INFO(0, persistent_id) From 38c38d7b47074b3007a67c2d2b435011872469e8 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 16 Nov 2022 07:56:04 +0100 Subject: [PATCH 304/345] changelog --- package.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.xml b/package.xml index 9dc283be..6a14b96c 100644 --- a/package.xml +++ b/package.xml @@ -44,7 +44,8 @@ http://pear.php.net/dtd/package-2.0.xsd"> PHP -- +- mark password as a sensitive param for PHP 8.2 +- Fix #523 Incorrect PHP reflection type for Memcached::cas $cas_token From 3b0070aab2e5984e9ad322df51449b570f85bbc9 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Fri, 6 Jan 2023 14:32:41 -0800 Subject: [PATCH 305/345] CI: Add PHP 8.2 to the required matrix, add PHP 8.3 to experimental (#529) --- .github/workflows/build-and-test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 79b22569..a5995e3a 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -7,10 +7,10 @@ jobs: strategy: fail-fast: false matrix: - php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1'] + php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2'] experimental: [false] include: - - php: '8.2' + - php: '8.3' experimental: true steps: - name: Checkout From 04a0f72eaafc0ac4ba646b57761b8d7331cdc82a Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 9 Jan 2023 11:07:54 -0800 Subject: [PATCH 306/345] CI: Add libmemcached-awesome to matrix (#530) --- .github/workflows/build-and-test.yml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index a5995e3a..7384dd88 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -10,6 +10,9 @@ jobs: php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2'] experimental: [false] include: + - php: '8.2' + awesome: true + experimental: true - php: '8.3' experimental: true steps: @@ -25,7 +28,21 @@ jobs: - name: Install dependencies run: | sudo apt-get update - sudo apt-get install libmemcached-dev memcached libsasl2-dev sasl2-bin zlib1g-dev + sudo apt-get install cmake memcached libsasl2-dev sasl2-bin zlib1g-dev + - if: ${{ ! matrix.awesome }} + name: Install libmemcached-dev (from distro) + run: sudo apt-get install libmemcached-dev + - if: ${{ matrix.awesome }} + name: Install libmemcached-awesome (from source) + run: | + curl -sL -o libmemcached.tgz https://github.com/awesomized/libmemcached/archive/refs/tags/1.1.3.tar.gz + mkdir libmemcached + tar --strip-components=1 -xf libmemcached.tgz -C libmemcached + mkdir build-libmemcached + cd build-libmemcached + cmake -D ENABLE_HASH_HSIEH=ON -D ENABLE_SASL=ON ../libmemcached + make + sudo make install - name: Start memcached daemons run: | export SASL_CONF_PATH="/tmp/sasl2" From 6a58af6abc3edbe3d4848f80e54e1fb5cb821ba4 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 18 Jan 2023 18:50:05 +0100 Subject: [PATCH 307/345] Add minimal Windows CI (#532) For now, only building the extension is supported. --- .github/workflows/build-windows.yml | 37 +++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/workflows/build-windows.yml diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml new file mode 100644 index 00000000..36cf7cba --- /dev/null +++ b/.github/workflows/build-windows.yml @@ -0,0 +1,37 @@ +name: Build on Windows +on: [push, pull_request] +jobs: + windows: + defaults: + run: + shell: cmd + strategy: + matrix: + version: ['7.4', '8.0', '8.1'] + arch: [x64, x86] + ts: [nts, zts] + runs-on: windows-latest + steps: + - name: Checkout memcached + uses: actions/checkout@v2 + - name: Setup PHP + id: setup-php + uses: cmb69/setup-php-sdk@v0.7 + with: + version: ${{matrix.version}} + arch: ${{matrix.arch}} + ts: ${{matrix.ts}} + deps: zlib + - name: Fetch libmemcached + run: curl -OLs https://windows.php.net/downloads/pecl/deps/libmemcached-1.1.1-${{steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip && 7z x libmemcached-1.1.1-${{steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip -o..\deps + - name: Enable Developer Command Prompt + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: ${{matrix.arch}} + toolset: ${{steps.setup-php.outputs.toolset}} + - name: phpize + run: phpize + - name: configure + run: configure --enable-memcached --enable-memcached-session --enable-memcached-json --with-prefix=${{steps.setup-php.outputs.prefix}} + - name: make + run: nmake From 1eac9f8b8e8998f2feefc47d3aa80cfe93da22af Mon Sep 17 00:00:00 2001 From: LeoLee Date: Wed, 1 Feb 2023 06:45:26 +0800 Subject: [PATCH 308/345] PHP 8 compatibility Windows (#528) Use PHP_VERSION_ID instead of _MSC_VER to select the right headers. win32/php_stdint.h was removed in PHP 8.0.0 and php_stdint.h file was removed in PHP 8.2.0 entirely: https://github.com/php/php-src/blob/PHP-8.2/UPGRADING.INTERNALS#L26 --- php_memcached_private.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/php_memcached_private.h b/php_memcached_private.h index b4b1115b..48f1dfab 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -48,11 +48,11 @@ #include #ifdef PHP_WIN32 - # if PHP_VERSION_ID >= 80000 - # include "php_stdint.h" -#else -# include "win32/php_stdint.h" -#endif + # if PHP_VERSION_ID >= 80000 + # include + #else + # include "win32/php_stdint.h" + #endif #else /* Used to store the size of the block */ # if defined(HAVE_INTTYPES_H) From 811c8a142239242f928419d349eea092536c24aa Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 2 Feb 2023 20:42:07 +0100 Subject: [PATCH 309/345] Fix #522 Signed integer overflow (#526) --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 7ccc9b58..ece54408 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -86,7 +86,7 @@ static int php_memc_list_entry(void) { /**************************************** Payload value flags ****************************************/ -#define MEMC_CREATE_MASK(start, n_bits) (((1 << n_bits) - 1) << start) +#define MEMC_CREATE_MASK(start, n_bits) (((1U << n_bits) - 1) << start) #define MEMC_MASK_TYPE MEMC_CREATE_MASK(0, 4) #define MEMC_MASK_INTERNAL MEMC_CREATE_MASK(4, 12) From 6926c53ac32a579b38a0dcc3c8aec662f8cd9dd5 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 11 Apr 2023 11:15:46 -0700 Subject: [PATCH 310/345] README.markdown: PHP 8.2 is supported --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 8819caf9..b17b7e55 100644 --- a/README.markdown +++ b/README.markdown @@ -23,7 +23,7 @@ Dependencies ------------ php-memcached 3.x: -* Supports PHP 7.0 - 8.1. +* Supports PHP 7.0 - 8.2 or higher. * Requires libmemcached 1.x or higher. * Optionally supports igbinary 2.0 or higher. * Optionally supports msgpack 2.0 or higher. From 58335902966f37f82548210556095a11759bcc60 Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Thu, 27 Apr 2023 11:32:10 -0400 Subject: [PATCH 311/345] zstd support (#539) This adds zstd compression support. The current two options, zlib and fastlz is basically a choice between performance and compression ratio. You would choose zlib if you are memory-bound and fastlz if you are cpu-bound. With zstd, you get the performance of fastlz with the compression of zlib. And often it wins on both. See this benchmark I ran on json files of varying sizes: https://gist.github.com/rlerdorf/788f3d0144f9c5514d8fee9477cbe787 Taking just a 40k json blob, we see that zstd at compression level 3 reduces it to 8862 bytes. Our current zlib 1 gets worse compression at 10091 bytes and takes longer both to compress and decompress. C Size ratio% C MB/s D MB/s SCORE Name File 8037 19.9 0.58 2130.89 0.08 zstd 22 file-39.54k-json 8204 20.3 31.85 2381.59 0.01 zstd 10 file-39.54k-json 8371 20.7 47.52 547.12 0.01 zlib 9 file-39.54k-json 8477 20.9 74.84 539.83 0.01 zlib 6 file-39.54k-json 8862 21.9 449.86 2130.89 0.01 zstd 3 file-39.54k-json 9171 22.7 554.62 2381.59 0.01 zstd 1 file-39.54k-json 10091 24.9 153.94 481.99 0.01 zlib 1 file-39.54k-json 10646 26.3 43.39 8097.40 0.01 lz4 16 file-39.54k-json 10658 26.3 72.30 8097.40 0.01 lz4 10 file-39.54k-json 13004 32.1 1396.10 6747.83 0.01 lz4 1 file-39.54k-json 13321 32.9 440.08 1306.03 0.01 fastlz 2 file-39.54k-json 14807 36.6 444.91 1156.77 0.01 fastlz 1 file-39.54k-json 15517 38.3 1190.79 4048.70 0.02 zstd -10 file-39.54k-json The fact that decompression a dramatically faster with zstd is a win for most common memcache uses since they tend to be read-heavy. The PR also adds a `memcache.compression_level` INI switch which currently only applies to zstd compression. It could probably be made to also apply to zlib and fastlz. --- config.m4 | 10 ++++ php_memcached.c | 78 ++++++++++++++++++++++++++++++- php_memcached_private.h | 4 +- tests/compression_conditions.phpt | 2 + tests/compression_types.phpt | 34 ++++++++++++++ 5 files changed, 125 insertions(+), 3 deletions(-) diff --git a/config.m4 b/config.m4 index c7a15f11..0e4ef8cf 100644 --- a/config.m4 +++ b/config.m4 @@ -27,6 +27,9 @@ PHP_ARG_ENABLE(memcached-protocol, whether to enable memcached protocol support, PHP_ARG_WITH(system-fastlz, whether to use system FastLZ library, [ --with-system-fastlz Use system FastLZ library], no, no) +PHP_ARG_WITH(zstd, whether to use system zstd library, +[ --with-zstd Use system zstd library], no, no) + if test -z "$PHP_ZLIB_DIR"; then PHP_ARG_WITH(zlib-dir, for ZLIB, [ --with-zlib-dir=DIR Set the path to ZLIB install prefix.], no) @@ -345,6 +348,13 @@ if test "$PHP_MEMCACHED" != "no"; then PHP_MEMCACHED_FILES="${PHP_MEMCACHED_FILES} fastlz/fastlz.c" fi + if test "$PHP_ZSTD" != "no"; then + AC_CHECK_HEADERS([zstd.h], [ac_cv_have_zstd="yes"], [ac_cv_have_zstd="no"]) + PHP_CHECK_LIBRARY(zstd, ZSTD_compress, + [PHP_ADD_LIBRARY(zstd, 1, MEMCACHED_SHARED_LIBADD)], + [AC_MSG_ERROR(zstd library not found)]) + fi + if test "$PHP_MEMCACHED_SESSION" != "no"; then PHP_MEMCACHED_FILES="${PHP_MEMCACHED_FILES} php_memcached_session.c" fi diff --git a/php_memcached.c b/php_memcached.c index ece54408..e7d5736c 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -37,6 +37,10 @@ #endif #include +#ifdef HAVE_ZSTD_H +#include +#endif + #ifdef HAVE_JSON_API # include "ext/json/php_json.h" #endif @@ -77,6 +81,7 @@ static int php_memc_list_entry(void) { #define MEMC_OPT_COMPRESSION_TYPE -1004 #define MEMC_OPT_STORE_RETRY_COUNT -1005 #define MEMC_OPT_USER_FLAGS -1006 +#define MEMC_OPT_COMPRESSION_LEVEL -1007 /**************************************** Custom result codes @@ -107,6 +112,7 @@ static int php_memc_list_entry(void) { #define MEMC_VAL_COMPRESSED (1<<0) #define MEMC_VAL_COMPRESSION_ZLIB (1<<1) #define MEMC_VAL_COMPRESSION_FASTLZ (1<<2) +#define MEMC_VAL_COMPRESSION_ZSTD (1<<3) #define MEMC_VAL_GET_FLAGS(internal_flags) (((internal_flags) & MEMC_MASK_INTERNAL) >> 4) #define MEMC_VAL_SET_FLAG(internal_flags, internal_flag) ((internal_flags) |= (((internal_flag) << 4) & MEMC_MASK_INTERNAL)) @@ -152,6 +158,7 @@ typedef struct { zend_long serializer; zend_long compression_type; + zend_long compression_level; zend_long store_retry_count; zend_long set_udf_flags; @@ -278,6 +285,10 @@ static PHP_INI_MH(OnUpdateCompressionType) MEMC_G(compression_type) = COMPRESSION_TYPE_FASTLZ; } else if (!strcmp(ZSTR_VAL(new_value), "zlib")) { MEMC_G(compression_type) = COMPRESSION_TYPE_ZLIB; +#ifdef HAVE_ZSTD_H + } else if (!strcmp(ZSTR_VAL(new_value), "zstd")) { + MEMC_G(compression_type) = COMPRESSION_TYPE_ZSTD; +#endif } else { return FAILURE; } @@ -408,6 +419,7 @@ PHP_INI_BEGIN() MEMC_INI_ENTRY("compression_type", "fastlz", OnUpdateCompressionType, compression_name) MEMC_INI_ENTRY("compression_factor", "1.3", OnUpdateReal, compression_factor) + MEMC_INI_ENTRY("compression_level", "3", OnUpdateLong, compression_level) MEMC_INI_ENTRY("compression_threshold", "2000", OnUpdateLong, compression_threshold) MEMC_INI_ENTRY("serializer", SERIALIZER_DEFAULT_NAME, OnUpdateSerializer, serializer_name) MEMC_INI_ENTRY("store_retry_count", "0", OnUpdateLong, store_retry_count) @@ -897,6 +909,19 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str } break; +#ifdef HAVE_ZSTD_H + case COMPRESSION_TYPE_ZSTD: + { + compressed_size = ZSTD_compress((void *)buffer, buffer_size, ZSTR_VAL(payload), ZSTR_LEN(payload), MEMC_G(compression_level)); + + if (!ZSTD_isError(compressed_size)) { + compress_status = 1; + compression_type_flag = MEMC_VAL_COMPRESSION_ZSTD; + } + } + break; +#endif + case COMPRESSION_TYPE_ZLIB: { compressed_size = buffer_size; @@ -2939,6 +2964,9 @@ static PHP_METHOD(Memcached, getOption) case MEMC_OPT_COMPRESSION_TYPE: RETURN_LONG(memc_user_data->compression_type); + case MEMC_OPT_COMPRESSION_LEVEL: + RETURN_LONG(memc_user_data->compression_level); + case MEMC_OPT_COMPRESSION: RETURN_BOOL(memc_user_data->compression_enabled); @@ -3001,6 +3029,9 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) case MEMC_OPT_COMPRESSION_TYPE: lval = zval_get_long(value); if (lval == COMPRESSION_TYPE_FASTLZ || +#ifdef HAVE_ZSTD_H + lval == COMPRESSION_TYPE_ZSTD || +#endif lval == COMPRESSION_TYPE_ZLIB) { memc_user_data->compression_type = lval; } else { @@ -3608,16 +3639,24 @@ zend_string *s_decompress_value (const char *payload, size_t payload_len, uint32 uint32_t stored_length; unsigned long length; zend_bool decompress_status = 0; - zend_bool is_fastlz = 0, is_zlib = 0; + zend_bool is_fastlz = 0, is_zlib = 0, is_zstd = 0; if (payload_len < sizeof (uint32_t)) { return NULL; } is_fastlz = MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_FASTLZ); + is_zstd = MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_ZSTD); is_zlib = MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_ZLIB); - if (!is_fastlz && !is_zlib) { +#ifndef HAVE_ZSTD_H + if (is_zstd) { + php_error_docref(NULL, E_WARNING, "could not decompress value: value was compressed with zstd but zstd support has not been compiled in"); + return NULL; + } +#endif + + if (!is_fastlz && !is_zlib && !is_zstd) { php_error_docref(NULL, E_WARNING, "could not decompress value: unrecognised compression type"); return NULL; } @@ -3629,6 +3668,23 @@ zend_string *s_decompress_value (const char *payload, size_t payload_len, uint32 buffer = zend_string_alloc (stored_length, 0); +#ifdef HAVE_ZSTD_H + if (is_zstd) { + length = ZSTD_getFrameContentSize(payload, payload_len); + if (length == ZSTD_CONTENTSIZE_ERROR) { + php_error_docref(NULL, E_WARNING, "value was not compressed by zstd"); + zend_string_release (buffer); + return NULL; + } else if (length == ZSTD_CONTENTSIZE_UNKNOWN) { + php_error_docref(NULL, E_WARNING, "zstd streaming decompression not supported"); + zend_string_release (buffer); + return NULL; + } + decompress_status = !ZSTD_isError(ZSTD_decompress(&buffer->val, buffer->len, payload, payload_len)); + + } + else +#endif if (is_fastlz) { decompress_status = ((length = fastlz_decompress(payload, payload_len, &buffer->val, buffer->len)) > 0); } @@ -3955,6 +4011,7 @@ PHP_GINIT_FUNCTION(php_memcached) php_memcached_globals->memc.compression_threshold = 2000; php_memcached_globals->memc.compression_type = COMPRESSION_TYPE_FASTLZ; php_memcached_globals->memc.compression_factor = 1.30; + php_memcached_globals->memc.compression_level = 3; php_memcached_globals->memc.store_retry_count = 2; php_memcached_globals->memc.sasl_initialised = 0; @@ -4000,6 +4057,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(OPT_COMPRESSION, MEMC_OPT_COMPRESSION); REGISTER_MEMC_CLASS_CONST_LONG(OPT_COMPRESSION_TYPE, MEMC_OPT_COMPRESSION_TYPE); + REGISTER_MEMC_CLASS_CONST_LONG(OPT_COMPRESSION_LEVEL, MEMC_OPT_COMPRESSION_LEVEL); REGISTER_MEMC_CLASS_CONST_LONG(OPT_PREFIX_KEY, MEMC_OPT_PREFIX_KEY); REGISTER_MEMC_CLASS_CONST_LONG(OPT_SERIALIZER, MEMC_OPT_SERIALIZER); @@ -4015,6 +4073,15 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_IGBINARY, 0); #endif + /* + * Indicate whether zstd compression is available + */ +#ifdef HAVE_ZSTD_H + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_ZSTD, 1); +#else + REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_ZSTD, 0); +#endif + /* * Indicate whether json serializer is available */ @@ -4186,6 +4253,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) */ REGISTER_MEMC_CLASS_CONST_LONG(COMPRESSION_FASTLZ, COMPRESSION_TYPE_FASTLZ); REGISTER_MEMC_CLASS_CONST_LONG(COMPRESSION_ZLIB, COMPRESSION_TYPE_ZLIB); + REGISTER_MEMC_CLASS_CONST_LONG(COMPRESSION_ZSTD, COMPRESSION_TYPE_ZSTD); /* * Flags. @@ -4351,6 +4419,12 @@ PHP_MINFO_FUNCTION(memcached) php_info_print_table_row(2, "msgpack support", "no"); #endif +#ifdef HAVE_ZSTD_H + php_info_print_table_row(2, "zstd support", "yes"); +#else + php_info_print_table_row(2, "zstd support", "no"); +#endif + php_info_print_table_end(); DISPLAY_INI_ENTRIES(); diff --git a/php_memcached_private.h b/php_memcached_private.h index 48f1dfab..aefaf4fb 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -98,7 +98,8 @@ typedef enum { typedef enum { COMPRESSION_TYPE_ZLIB = 1, - COMPRESSION_TYPE_FASTLZ = 2 + COMPRESSION_TYPE_FASTLZ = 2, + COMPRESSION_TYPE_ZSTD = 3 } php_memc_compression_type; typedef struct { @@ -186,6 +187,7 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) zend_long compression_threshold; double compression_factor; zend_long store_retry_count; + zend_long compression_level; /* Converted values*/ php_memc_serializer_type serializer_type; diff --git a/tests/compression_conditions.phpt b/tests/compression_conditions.phpt index 749ebe8a..960058b6 100644 --- a/tests/compression_conditions.phpt +++ b/tests/compression_conditions.phpt @@ -21,6 +21,8 @@ function get_compression($name) { return Memcached::COMPRESSION_ZLIB; case 'fastlz': return Memcached::COMPRESSION_FASTLZ; + case 'zstd': + return Memcached::COMPRESSION_ZSTD; default: echo "Strange compression type: $name\n"; return 0; diff --git a/tests/compression_types.phpt b/tests/compression_types.phpt index ce07aed5..81d7867c 100644 --- a/tests/compression_types.phpt +++ b/tests/compression_types.phpt @@ -15,6 +15,10 @@ function get_compression($name) { return Memcached::COMPRESSION_ZLIB; case 'fastlz': return Memcached::COMPRESSION_FASTLZ; + case 'zstd': + if (Memcached::HAVE_ZSTD) { + return Memcached::COMPRESSION_ZSTD; + } else return 0; default: echo "Strange compression type: $name\n"; return 0; @@ -54,6 +58,26 @@ fetch_with_compression($m, 'hello6', $data, '', 'fastlz'); fetch_with_compression($m, 'hello7', $data, 'zlib', ''); fetch_with_compression($m, 'hello8', $data, 'fastlz', ''); fetch_with_compression($m, 'hello9', $data, '', ''); +if (Memcached::HAVE_ZSTD) { +fetch_with_compression($m, 'hello10', $data, 'zstd', 'zstd'); +fetch_with_compression($m, 'hello11', $data, 'zstd', 'fastlz'); +fetch_with_compression($m, 'hello12', $data, 'fastlz', 'zstd'); +fetch_with_compression($m, 'hello13', $data, '', 'zstd'); +fetch_with_compression($m, 'hello14', $data, 'zstd', ''); +} else { + echo << --EXPECT-- set=[zlib] get=[zlib] @@ -74,3 +98,13 @@ set=[fastlz] get=[] bool(true) set=[] get=[] bool(true) +set=[zstd] get=[zstd] +bool(true) +set=[zstd] get=[fastlz] +bool(true) +set=[fastlz] get=[zstd] +bool(true) +set=[] get=[zstd] +bool(true) +set=[zstd] get=[] +bool(true) From 7348cc11f729432116b652ccddb87011d553ca42 Mon Sep 17 00:00:00 2001 From: Pavel Djundik Date: Thu, 27 Apr 2023 18:35:07 +0300 Subject: [PATCH 312/345] Move working tests up a folder (#503) Tests in the experimental/ folder were not executed on CI. The ones that work move up, the few that remain in experimental/ need further investigation to get working or remove. --- tests/{experimental => }/add_bykey.phpt | 6 +- .../addserver_unixdomain.phpt | 2 +- tests/{experimental => }/append_bykey.phpt | 4 +- tests/{experimental => }/cas_bykey.phpt | 4 +- tests/{experimental => }/cas_invalid_key.phpt | 6 +- tests/{experimental => }/delete_bykey.phpt | 6 +- .../deletemulti_nonstringkeys.phpt | 4 +- tests/experimental/get_bykey_cas.phpt | 70 ------------------- tests/{experimental => }/fetch.phpt | 4 +- .../fetch_badunserialize.phpt | 15 +++- .../fetchall_badunserialize.phpt | 15 +++- tests/{experimental => }/get.phpt | 6 +- tests/{experimental => }/get_bykey.phpt | 6 +- tests/get_bykey_cas.phpt | 61 ++++++++++++++++ .../getdelayed_badserver.phpt | 2 +- .../getdelayed_badunserialize.phpt | 15 +++- .../{experimental => }/getdelayed_bykey.phpt | 4 +- .../getdelayed_bykey_cas.phpt | 34 +++++---- .../getdelayed_nonstring_keys.phpt | 4 +- .../getmulti_badserver.phpt | 8 +-- .../getmulti_badunserialize.phpt | 12 +++- tests/{experimental => }/getmulti_bykey.phpt | 4 +- tests/{experimental => }/getmulti_empty.phpt | 4 +- .../getmulti_partial_error.phpt | 4 +- tests/{experimental => }/getversion.phpt | 4 +- tests/{experimental => }/locale_float.phpt | 4 +- tests/{experimental => }/moduleinfo.phpt | 2 +- tests/{experimental => }/prepend_bykey.phpt | 4 +- tests/{experimental => }/replace_bykey.phpt | 4 +- tests/{experimental => }/set_bykey.phpt | 6 +- .../set_comp_below_factor.phpt | 4 +- .../set_default_serializer.phpt | 2 +- .../set_invalid_serializer.phpt | 2 +- .../setget_zero_factor.phpt | 4 +- tests/{experimental => }/setmulti_bykey.phpt | 4 +- 35 files changed, 190 insertions(+), 150 deletions(-) rename tests/{experimental => }/add_bykey.phpt (84%) rename tests/{experimental => }/addserver_unixdomain.phpt (87%) rename tests/{experimental => }/append_bykey.phpt (78%) rename tests/{experimental => }/cas_bykey.phpt (84%) rename tests/{experimental => }/cas_invalid_key.phpt (65%) rename tests/{experimental => }/delete_bykey.phpt (82%) rename tests/{experimental => }/deletemulti_nonstringkeys.phpt (87%) delete mode 100644 tests/experimental/get_bykey_cas.phpt rename tests/{experimental => }/fetch.phpt (93%) rename tests/{experimental => }/fetch_badunserialize.phpt (76%) rename tests/{experimental => }/fetchall_badunserialize.phpt (76%) rename tests/{experimental => }/get.phpt (78%) rename tests/{experimental => }/get_bykey.phpt (75%) create mode 100644 tests/get_bykey_cas.phpt rename tests/{experimental => }/getdelayed_badserver.phpt (87%) rename tests/{experimental => }/getdelayed_badunserialize.phpt (77%) rename tests/{experimental => }/getdelayed_bykey.phpt (89%) rename tests/{experimental => }/getdelayed_bykey_cas.phpt (76%) rename tests/{experimental => }/getdelayed_nonstring_keys.phpt (90%) rename tests/{experimental => }/getmulti_badserver.phpt (85%) rename tests/{experimental => }/getmulti_badunserialize.phpt (77%) rename tests/{experimental => }/getmulti_bykey.phpt (82%) rename tests/{experimental => }/getmulti_empty.phpt (60%) rename tests/{experimental => }/getmulti_partial_error.phpt (84%) rename tests/{experimental => }/getversion.phpt (69%) rename tests/{experimental => }/locale_float.phpt (80%) rename tests/{experimental => }/moduleinfo.phpt (86%) rename tests/{experimental => }/prepend_bykey.phpt (78%) rename tests/{experimental => }/replace_bykey.phpt (82%) rename tests/{experimental => }/set_bykey.phpt (83%) rename tests/{experimental => }/set_comp_below_factor.phpt (74%) rename tests/{experimental => }/set_default_serializer.phpt (95%) rename tests/{experimental => }/set_invalid_serializer.phpt (92%) rename tests/{experimental => }/setget_zero_factor.phpt (70%) rename tests/{experimental => }/setmulti_bykey.phpt (87%) diff --git a/tests/experimental/add_bykey.phpt b/tests/add_bykey.phpt similarity index 84% rename from tests/experimental/add_bykey.phpt rename to tests/add_bykey.phpt index 195fe96d..1c1521d2 100644 --- a/tests/experimental/add_bykey.phpt +++ b/tests/add_bykey.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached::addByKey() --SKIPIF-- - + --FILE-- delete('foo'); @@ -15,7 +15,7 @@ echo $m->getResultMessage(), "\n"; var_dump($m->addByKey('foo', '', 1, 10)); echo $m->getResultMessage(), "\n"; // This is OK for the binary protocol -$rv = $m->addByKey('foo', ' asd åäö', 1, 1); +$rv = $m->addByKey('foo', ' asd åäö', 1, 1); if ($m->getOption(Memcached::OPT_BINARY_PROTOCOL)) { if ($rv !== true and $m->getResultCode() !== Memcached::RES_SUCCESS) { var_dump($rv); diff --git a/tests/experimental/addserver_unixdomain.phpt b/tests/addserver_unixdomain.phpt similarity index 87% rename from tests/experimental/addserver_unixdomain.phpt rename to tests/addserver_unixdomain.phpt index 4848015d..7e16834c 100644 --- a/tests/experimental/addserver_unixdomain.phpt +++ b/tests/addserver_unixdomain.phpt @@ -1,7 +1,7 @@ --TEST-- Memcached::addServer() unix doamin socket --SKIPIF-- - + --CLEAN-- + --FILE-- setOption(Memcached::OPT_COMPRESSION, false); diff --git a/tests/experimental/cas_bykey.phpt b/tests/cas_bykey.phpt similarity index 84% rename from tests/experimental/cas_bykey.phpt rename to tests/cas_bykey.phpt index 0a9da94e..32808813 100644 --- a/tests/experimental/cas_bykey.phpt +++ b/tests/cas_bykey.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached::casByKey() --SKIPIF-- - + --FILE-- delete('cas_test'); diff --git a/tests/experimental/cas_invalid_key.phpt b/tests/cas_invalid_key.phpt similarity index 65% rename from tests/experimental/cas_invalid_key.phpt rename to tests/cas_invalid_key.phpt index 6011c4b8..b8a815dc 100644 --- a/tests/experimental/cas_invalid_key.phpt +++ b/tests/cas_invalid_key.phpt @@ -1,17 +1,17 @@ --TEST-- Memcached::cas() with strange key --SKIPIF-- - + --FILE-- cas(0, '', true, 10)); echo $m->getResultMessage(), "\n"; -var_dump($m->cas(0, ' äö jas kjjhask d ', true, 10)); # no spaces allowed +var_dump($m->cas(0, ' äö jas kjjhask d ', true, 10)); # no spaces allowed echo $m->getResultMessage(), "\n"; --EXPECTF-- diff --git a/tests/experimental/delete_bykey.phpt b/tests/delete_bykey.phpt similarity index 82% rename from tests/experimental/delete_bykey.phpt rename to tests/delete_bykey.phpt index 807af8ca..929ffbc1 100644 --- a/tests/experimental/delete_bykey.phpt +++ b/tests/delete_bykey.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached::deleteByKey() --SKIPIF-- - + --FILE-- setByKey('keffe', 'eisaleeoo', "foo"); @@ -21,7 +21,7 @@ var_dump($m->deleteByKey('keffe', '')); echo $m->getResultMessage(), "\n"; var_dump($m->deleteByKey('', 'keffe')); echo $m->getResultMessage(), "\n"; -var_dump($m->deleteByKey('keffe', 'äöåasäö åaösdäf asdf')); # no spaces allowed +var_dump($m->deleteByKey('keffe', 'äöåasäö Ã¥aösdäf asdf')); # no spaces allowed echo $m->getResultMessage(), "\n"; --EXPECTF-- string(3) "foo" diff --git a/tests/experimental/deletemulti_nonstringkeys.phpt b/tests/deletemulti_nonstringkeys.phpt similarity index 87% rename from tests/experimental/deletemulti_nonstringkeys.phpt rename to tests/deletemulti_nonstringkeys.phpt index 2dac8920..8e275e9c 100644 --- a/tests/experimental/deletemulti_nonstringkeys.phpt +++ b/tests/deletemulti_nonstringkeys.phpt @@ -1,10 +1,10 @@ --TEST-- Delete multi with integer keys --SKIPIF-- - + --FILE-- ---FILE-- -set('foo', 1, 10); - -$cas = null; -var_dump($m->getByKey('foo', 'foo', null, $cas)); -var_dump($cas); -echo $m->getResultMessage(), "\n"; - -$cas = null; -var_dump($m->getByKey('', 'foo', null, $cas)); -var_dump($cas); -echo $m->getResultMessage(), "\n"; - -$m->set('bar', "asdf", 10); - -$cas = null; -var_dump($m->getByKey('foo', 'bar', null, $cas)); -var_dump($cas); -echo $m->getResultMessage(), "\n"; - -$m->delete('foo'); -$cas = null; -var_dump($m->getByKey(' ä foo jkh a s åäö', 'foo', null, $cas)); -var_dump($cas); -echo $m->getResultMessage(), "\n"; - -$cas = null; -var_dump($m->getByKey(' ä foo jkh a s åäö', '', null, $cas)); -var_dump($cas); -echo $m->getResultMessage(), "\n"; - -$m->delete('foo'); -$cas = null; -var_dump($m->getByKey('foo', 'foo', 'the_callback', $cas)); -var_dump($cas); -var_dump($m->getByKey('foo', 'foo')); ---EXPECTF-- -int(1) -float(%d) -SUCCESS -int(1) -float(%d) -SUCCESS -string(4) "asdf" -float(%d) -SUCCESS -bool(false) -float(0) -NOT FOUND -bool(false) -NULL -A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE -called -string(4) "1234" -float(0) -string(4) "1234" diff --git a/tests/experimental/fetch.phpt b/tests/fetch.phpt similarity index 93% rename from tests/experimental/fetch.phpt rename to tests/fetch.phpt index 13136c5b..68977466 100644 --- a/tests/experimental/fetch.phpt +++ b/tests/fetch.phpt @@ -1,7 +1,7 @@ --TEST-- Memcached getDelayed() and fetch() with and without cas --SKIPIF-- - + --FILE-- + --FILE-- serialize_throws) { + throw new Exception("1234"); + } + return ["1234"]; + } + + public function __unserialize($str) { + throw new Exception("123456"); + } } $data = new Foo(); diff --git a/tests/experimental/fetchall_badunserialize.phpt b/tests/fetchall_badunserialize.phpt similarity index 76% rename from tests/experimental/fetchall_badunserialize.phpt rename to tests/fetchall_badunserialize.phpt index 5684763f..815c9e21 100644 --- a/tests/experimental/fetchall_badunserialize.phpt +++ b/tests/fetchall_badunserialize.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached::fetch() with bad unserialize --SKIPIF-- - + --FILE-- serialize_throws) { + throw new Exception("1234"); + } + return ["1234"]; + } + + public function __unserialize($str) { + throw new Exception("123456"); + } } $data = new Foo(); diff --git a/tests/experimental/get.phpt b/tests/get.phpt similarity index 78% rename from tests/experimental/get.phpt rename to tests/get.phpt index 308bda98..71889064 100644 --- a/tests/experimental/get.phpt +++ b/tests/get.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached::get() --SKIPIF-- - + --FILE-- delete('foo'); @@ -20,7 +20,7 @@ var_dump($m->get('foo')); echo $m->getResultMessage(), "\n"; $m->delete('foo'); -var_dump($m->get(' ä foo jkh a s åäö')); +var_dump($m->get(' ä foo jkh a s åäö')); echo $m->getResultMessage(), "\n"; --EXPECT-- bool(false) diff --git a/tests/experimental/get_bykey.phpt b/tests/get_bykey.phpt similarity index 75% rename from tests/experimental/get_bykey.phpt rename to tests/get_bykey.phpt index a392aaeb..704e8f04 100644 --- a/tests/experimental/get_bykey.phpt +++ b/tests/get_bykey.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached::getByKey() --SKIPIF-- - + --FILE-- set('foo', 1, 10); @@ -20,7 +20,7 @@ var_dump($m->getByKey('foo', 'bar')); echo $m->getResultMessage(), "\n"; $m->delete('foo'); -var_dump($m->getByKey(' ä foo jkh a s åäö', 'foo')); +var_dump($m->getByKey(' ä foo jkh a s åäö', 'foo')); echo $m->getResultMessage(), "\n"; --EXPECTF-- diff --git a/tests/get_bykey_cas.phpt b/tests/get_bykey_cas.phpt new file mode 100644 index 00000000..90b566c4 --- /dev/null +++ b/tests/get_bykey_cas.phpt @@ -0,0 +1,61 @@ +--TEST-- +Memcached::getByKey() with CAS +--SKIPIF-- + +--FILE-- +set('foo', 1, 10); + +$v = $m->getByKey('foo', 'foo', null, Memcached::GET_EXTENDED); +var_dump($v['value']); +var_dump($v['cas']); +echo $m->getResultMessage(), "\n"; + +$v = $m->getByKey('', 'foo', null, Memcached::GET_EXTENDED); +var_dump($v['value']); +var_dump($v['cas']); +echo $m->getResultMessage(), "\n"; + +$m->set('bar', "asdf", 10); + +$v = $m->getByKey('foo', 'bar', null, Memcached::GET_EXTENDED); +var_dump($v['value']); +var_dump($v['cas']); +echo $m->getResultMessage(), "\n"; + +$m->delete('foo'); +var_dump($m->getByKey(' ä foo jkh a s åäö', 'foo', null, Memcached::GET_EXTENDED)); +echo $m->getResultMessage(), "\n"; + +var_dump($m->getByKey(' ä foo jkh a s åäö', '', null, Memcached::GET_EXTENDED)); +echo $m->getResultMessage(), "\n"; + +$m->delete('foo'); +var_dump($m->getByKey('foo', 'foo', 'the_callback', Memcached::GET_EXTENDED)); +var_dump($m->getByKey('foo', 'foo')); +--EXPECTF-- +int(1) +int(%d) +SUCCESS +int(1) +int(%d) +SUCCESS +string(4) "asdf" +int(%d) +SUCCESS +bool(false) +NOT FOUND +bool(false) +A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE +called +bool(false) +bool(false) \ No newline at end of file diff --git a/tests/experimental/getdelayed_badserver.phpt b/tests/getdelayed_badserver.phpt similarity index 87% rename from tests/experimental/getdelayed_badserver.phpt rename to tests/getdelayed_badserver.phpt index c4902174..5d274efb 100644 --- a/tests/experimental/getdelayed_badserver.phpt +++ b/tests/getdelayed_badserver.phpt @@ -1,7 +1,7 @@ --TEST-- Memcached::getDelayedByKey() with bad server --SKIPIF-- - + --FILE-- + --FILE-- serialize_throws) { + throw new Exception("1234"); + } + return ["1234"]; + } + + public function __unserialize($str) { + throw new Exception("123456"); + } } function mycb($memc, $key, $value) { diff --git a/tests/experimental/getdelayed_bykey.phpt b/tests/getdelayed_bykey.phpt similarity index 89% rename from tests/experimental/getdelayed_bykey.phpt rename to tests/getdelayed_bykey.phpt index a29f646b..442320a2 100644 --- a/tests/experimental/getdelayed_bykey.phpt +++ b/tests/getdelayed_bykey.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached::getDelayedByKey() --SKIPIF-- - + --FILE-- + --FILE-- getDelayedByKey('kef', array_keys($data), true, 'myfunc'); ?> --EXPECTF-- -array(3) { +array(4) { ["key"]=> string(3) "foo" ["value"]=> string(8) "foo-data" ["cas"]=> - float(%d) + int(%d) + ["flags"]=> + int(0) } -array(3) { +array(4) { ["key"]=> string(3) "bar" ["value"]=> string(8) "bar-data" ["cas"]=> - float(%d) + int(%d) + ["flags"]=> + int(0) } -array(3) { +array(4) { ["key"]=> string(3) "baz" ["value"]=> string(8) "baz-data" ["cas"]=> - float(%d) + int(%d) + ["flags"]=> + int(0) } -array(3) { +array(4) { ["key"]=> string(3) "lol" ["value"]=> string(8) "lol-data" ["cas"]=> - float(%d) + int(%d) + ["flags"]=> + int(0) } -array(3) { +array(4) { ["key"]=> string(3) "kek" ["value"]=> string(8) "kek-data" ["cas"]=> - float(%d) + int(%d) + ["flags"]=> + int(0) } diff --git a/tests/experimental/getdelayed_nonstring_keys.phpt b/tests/getdelayed_nonstring_keys.phpt similarity index 90% rename from tests/experimental/getdelayed_nonstring_keys.phpt rename to tests/getdelayed_nonstring_keys.phpt index 81363f3b..005d0579 100644 --- a/tests/experimental/getdelayed_nonstring_keys.phpt +++ b/tests/getdelayed_nonstring_keys.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached getDelayed non string keys --SKIPIF-- - + --FILE-- + --FILE-- getResultCode()) { } --EXPECTF-- -array(0) { -} +bool(false) NO SERVERS DEFINED -array(0) { -} +bool(false) %d: %s diff --git a/tests/experimental/getmulti_badunserialize.phpt b/tests/getmulti_badunserialize.phpt similarity index 77% rename from tests/experimental/getmulti_badunserialize.phpt rename to tests/getmulti_badunserialize.phpt index 963e9730..280feed3 100644 --- a/tests/experimental/getmulti_badunserialize.phpt +++ b/tests/getmulti_badunserialize.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached::getMulti() with bad unserialize --SKIPIF-- - + --FILE-- set('bar', "12", 10)); diff --git a/tests/experimental/getmulti_bykey.phpt b/tests/getmulti_bykey.phpt similarity index 82% rename from tests/experimental/getmulti_bykey.phpt rename to tests/getmulti_bykey.phpt index 3f7a6f78..b615dc66 100644 --- a/tests/experimental/getmulti_bykey.phpt +++ b/tests/getmulti_bykey.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached::getMultiByKey() --SKIPIF-- - + --FILE-- set('foo', 1, 10); diff --git a/tests/experimental/getmulti_empty.phpt b/tests/getmulti_empty.phpt similarity index 60% rename from tests/experimental/getmulti_empty.phpt rename to tests/getmulti_empty.phpt index 6279104d..3550e814 100644 --- a/tests/experimental/getmulti_empty.phpt +++ b/tests/getmulti_empty.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached::getMulti() with empty array --SKIPIF-- - + --FILE-- getMulti(array()); diff --git a/tests/experimental/getmulti_partial_error.phpt b/tests/getmulti_partial_error.phpt similarity index 84% rename from tests/experimental/getmulti_partial_error.phpt rename to tests/getmulti_partial_error.phpt index fa392e9e..928f49f4 100644 --- a/tests/experimental/getmulti_partial_error.phpt +++ b/tests/getmulti_partial_error.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached::getMulti() partial error --SKIPIF-- - + --FILE-- + --FILE-- getVersion()); -include dirname(dirname(__FILE__)) . "/config.inc"; +include dirname(__FILE__) . "/config.inc"; $m = memc_get_instance (); $stats = $m->getVersion(); diff --git a/tests/experimental/locale_float.phpt b/tests/locale_float.phpt similarity index 80% rename from tests/experimental/locale_float.phpt rename to tests/locale_float.phpt index c071d974..2f25ea73 100644 --- a/tests/experimental/locale_float.phpt +++ b/tests/locale_float.phpt @@ -2,14 +2,14 @@ Float should not consider locale --SKIPIF-- --FILE-- diff --git a/tests/experimental/prepend_bykey.phpt b/tests/prepend_bykey.phpt similarity index 78% rename from tests/experimental/prepend_bykey.phpt rename to tests/prepend_bykey.phpt index 87d3fd38..482899de 100644 --- a/tests/experimental/prepend_bykey.phpt +++ b/tests/prepend_bykey.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached::appendByKey() --SKIPIF-- - + --FILE-- setOption(Memcached::OPT_COMPRESSION, false); diff --git a/tests/experimental/replace_bykey.phpt b/tests/replace_bykey.phpt similarity index 82% rename from tests/experimental/replace_bykey.phpt rename to tests/replace_bykey.phpt index cddf10f0..b844824c 100644 --- a/tests/experimental/replace_bykey.phpt +++ b/tests/replace_bykey.phpt @@ -1,10 +1,10 @@ --TEST-- Memcached::replaceByKey() --SKIPIF-- - + --FILE-- + --FILE-- setByKey('foo', 'foo', 1, 10)); @@ -14,7 +14,7 @@ echo $m->getResultMessage(), "\n"; var_dump($m->setByKey('foo', '', 1, 10)); echo $m->getResultMessage(), "\n"; // This is OK for the binary protocol -$rv = $m->setByKey('foo', ' asd åäö', 1, 1); +$rv = $m->setByKey('foo', ' asd åäö', 1, 1); if ($m->getOption(Memcached::OPT_BINARY_PROTOCOL)) { if ($rv !== true and $m->getResultCode() !== Memcached::RES_SUCCESS) { var_dump($rv); diff --git a/tests/experimental/set_comp_below_factor.phpt b/tests/set_comp_below_factor.phpt similarity index 74% rename from tests/experimental/set_comp_below_factor.phpt rename to tests/set_comp_below_factor.phpt index 12e6d6a4..80d28006 100644 --- a/tests/experimental/set_comp_below_factor.phpt +++ b/tests/set_comp_below_factor.phpt @@ -1,10 +1,10 @@ --TEST-- Compress below factor and fail to plain. --SKIPIF-- - + --FILE-- + --FILE-- + --FILE-- + --FILE-- + --FILE-- Date: Thu, 27 Apr 2023 10:48:49 -0500 Subject: [PATCH 313/345] Add option to locally enforce payload size limit (#515) Add a configuration option to enforce an item size limit on the client side. This avoids sending large items over the wire and getting rejected by the server which can cause delays. The default is 0 for no limit. The same error code RES_E2BIG is used for the client side limit as for the server side limit. --- memcached.ini | 6 +++++ php_memcached.c | 45 ++++++++++++++++++++++++++++++++++++++ php_memcached_private.h | 5 +++-- tests/cas_e2big.phpt | 32 +++++++++++++++++++++++++++ tests/options.phpt | 32 +++++++++++++++++++++++++++ tests/set_large.phpt | 4 +++- tests/set_large_e2big.phpt | 27 +++++++++++++++++++++++ tests/setoptions.phpt | 3 +++ 8 files changed, 151 insertions(+), 3 deletions(-) create mode 100644 tests/cas_e2big.phpt create mode 100644 tests/set_large_e2big.phpt diff --git a/memcached.ini b/memcached.ini index c54e1fd4..5decf399 100644 --- a/memcached.ini +++ b/memcached.ini @@ -133,6 +133,12 @@ ; the default is 0 ;memcached.store_retry_count = 0 +; The maximum payload size in bytes that can be written. +; Writing a payload larger than the limit will result in RES_E2BIG error. +; Specifying 0 means no limit is enforced, though the server may still reject with RES_E2BIG. +; Default is 0. +;memcached.item_size_limit = 1000000 + ; Sets the default for consistent hashing for new connections. ; (To configure consistent hashing for session connections, ; use memcached.sess_consistent_hash instead) diff --git a/php_memcached.c b/php_memcached.c index e7d5736c..9c5ba8aa 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -82,6 +82,7 @@ static int php_memc_list_entry(void) { #define MEMC_OPT_STORE_RETRY_COUNT -1005 #define MEMC_OPT_USER_FLAGS -1006 #define MEMC_OPT_COMPRESSION_LEVEL -1007 +#define MEMC_OPT_ITEM_SIZE_LIMIT -1008 /**************************************** Custom result codes @@ -162,6 +163,7 @@ typedef struct { zend_long store_retry_count; zend_long set_udf_flags; + zend_long item_size_limit; #ifdef HAVE_MEMCACHED_SASL zend_bool has_sasl_data; @@ -423,6 +425,7 @@ PHP_INI_BEGIN() MEMC_INI_ENTRY("compression_threshold", "2000", OnUpdateLong, compression_threshold) MEMC_INI_ENTRY("serializer", SERIALIZER_DEFAULT_NAME, OnUpdateSerializer, serializer_name) MEMC_INI_ENTRY("store_retry_count", "0", OnUpdateLong, store_retry_count) + MEMC_INI_ENTRY("item_size_limit", "0", OnUpdateLongGEZero, item_size_limit) MEMC_INI_BOOL ("default_consistent_hash", "0", OnUpdateBool, default_behavior.consistent_hash_enabled) MEMC_INI_BOOL ("default_binary_protocol", "0", OnUpdateBool, default_behavior.binary_protocol_enabled) @@ -1127,6 +1130,21 @@ zend_string *s_zval_to_payload(php_memc_object_t *intern, zval *value, uint32_t return payload; } +static +zend_bool s_is_payload_too_big(php_memc_object_t *intern, zend_string *payload) +{ + php_memc_user_data_t *memc_user_data = memcached_get_user_data(intern->memc); + + /* An item size limit of 0 implies no limit enforced */ + if (memc_user_data->item_size_limit == 0) { + return 0; + } + if (ZSTR_LEN(payload) > memc_user_data->item_size_limit) { + return 1; + } + return 0; +} + static zend_bool s_should_retry_write (php_memc_object_t *intern, memcached_return status) { @@ -1153,6 +1171,12 @@ zend_bool s_memc_write_zval (php_memc_object_t *intern, php_memc_write_op op, ze s_memc_set_status(intern, MEMC_RES_PAYLOAD_FAILURE, 0); return 0; } + + if (s_is_payload_too_big(intern, payload)) { + s_memc_set_status(intern, MEMCACHED_E2BIG, 0); + zend_string_release(payload); + return 0; + } } #define memc_write_using_fn(fn_name) payload ? fn_name(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(payload), ZSTR_LEN(payload), expiration, flags) : MEMC_RES_PAYLOAD_FAILURE; @@ -1305,6 +1329,7 @@ static PHP_METHOD(Memcached, __construct) memc_user_data->encoding_enabled = 0; memc_user_data->store_retry_count = MEMC_G(store_retry_count); memc_user_data->set_udf_flags = -1; + memc_user_data->item_size_limit = MEMC_G(item_size_limit); memc_user_data->is_persistent = is_persistent; memcached_set_user_data(intern->memc, memc_user_data); @@ -2145,6 +2170,12 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) RETURN_FALSE; } + if (s_is_payload_too_big(intern, payload)) { + intern->rescode = MEMCACHED_E2BIG; + zend_string_release(payload); + RETURN_FALSE; + } + if (by_key) { status = memcached_cas_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(payload), ZSTR_LEN(payload), expiration, flags, cas); } else { @@ -2970,6 +3001,9 @@ static PHP_METHOD(Memcached, getOption) case MEMC_OPT_COMPRESSION: RETURN_BOOL(memc_user_data->compression_enabled); + case MEMC_OPT_ITEM_SIZE_LIMIT: + RETURN_LONG(memc_user_data->item_size_limit); + case MEMC_OPT_PREFIX_KEY: { memcached_return retval; @@ -3041,6 +3075,15 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) } break; + case MEMC_OPT_ITEM_SIZE_LIMIT: + lval = zval_get_long(value); + if (lval < 0) { + php_error_docref(NULL, E_WARNING, "ITEM_SIZE_LIMIT must be >= 0"); + return 0; + } + memc_user_data->item_size_limit = lval; + break; + case MEMC_OPT_PREFIX_KEY: { zend_string *str; @@ -4013,6 +4056,7 @@ PHP_GINIT_FUNCTION(php_memcached) php_memcached_globals->memc.compression_factor = 1.30; php_memcached_globals->memc.compression_level = 3; php_memcached_globals->memc.store_retry_count = 2; + php_memcached_globals->memc.item_size_limit = 0; php_memcached_globals->memc.sasl_initialised = 0; php_memcached_globals->no_effect = 0; @@ -4063,6 +4107,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) REGISTER_MEMC_CLASS_CONST_LONG(OPT_USER_FLAGS, MEMC_OPT_USER_FLAGS); REGISTER_MEMC_CLASS_CONST_LONG(OPT_STORE_RETRY_COUNT, MEMC_OPT_STORE_RETRY_COUNT); + REGISTER_MEMC_CLASS_CONST_LONG(OPT_ITEM_SIZE_LIMIT, MEMC_OPT_ITEM_SIZE_LIMIT); /* * Indicate whether igbinary serializer is available diff --git a/php_memcached_private.h b/php_memcached_private.h index aefaf4fb..93c20570 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -186,8 +186,9 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) char *compression_name; zend_long compression_threshold; double compression_factor; - zend_long store_retry_count; - zend_long compression_level; + zend_long store_retry_count; + zend_long compression_level; + zend_long item_size_limit; /* Converted values*/ php_memc_serializer_type serializer_type; diff --git a/tests/cas_e2big.phpt b/tests/cas_e2big.phpt new file mode 100644 index 00000000..99c3562b --- /dev/null +++ b/tests/cas_e2big.phpt @@ -0,0 +1,32 @@ +--TEST-- +set data exceeding size limit +--SKIPIF-- + +--FILE-- + 100, +)); + +$m->delete('cas_e2big_test'); + +$m->set('cas_e2big_test', 'hello'); +$result = $m->get('cas_e2big_test', null, Memcached::GET_EXTENDED); +var_dump(is_array($result) && isset($result['cas']) && isset($result['value']) && $result['value'] == 'hello'); + +$value = str_repeat('a large payload', 1024 * 1024); + +var_dump($m->cas($result['cas'], 'cas_e2big_test', $value, 360)); +var_dump($m->getResultCode() == Memcached::RES_E2BIG); +var_dump($m->getResultMessage() == 'ITEM TOO BIG'); +var_dump($m->get('cas_e2big_test') == 'hello'); +var_dump($m->getResultCode() == Memcached::RES_SUCCESS); +?> +--EXPECT-- +bool(true) +bool(false) +bool(true) +bool(true) +bool(true) +bool(true) diff --git a/tests/options.phpt b/tests/options.phpt index ce895385..a096c8f1 100644 --- a/tests/options.phpt +++ b/tests/options.phpt @@ -26,6 +26,26 @@ var_dump($m->getOption(Memcached::OPT_COMPRESSION_TYPE) == Memcached::COMPRESSIO var_dump($m->setOption(Memcached::OPT_COMPRESSION_TYPE, 0)); var_dump($m->getOption(Memcached::OPT_COMPRESSION_TYPE) == Memcached::COMPRESSION_FASTLZ); + +echo "item_size_limit setOption\n"; +var_dump($m->setOption(Memcached::OPT_ITEM_SIZE_LIMIT, 0)); +var_dump($m->getOption(Memcached::OPT_ITEM_SIZE_LIMIT) === 0); +var_dump($m->setOption(Memcached::OPT_ITEM_SIZE_LIMIT, -1)); +var_dump($m->setOption(Memcached::OPT_ITEM_SIZE_LIMIT, 1000000)); +var_dump($m->getOption(Memcached::OPT_ITEM_SIZE_LIMIT) == 1000000); + +echo "item_size_limit ini\n"; +ini_set('memcached.item_size_limit', '0'); +$m = new Memcached(); +var_dump($m->getOption(Memcached::OPT_ITEM_SIZE_LIMIT) === 0); + +ini_set('memcached.item_size_limit', '1000000'); +$m = new Memcached(); +var_dump($m->getOption(Memcached::OPT_ITEM_SIZE_LIMIT) == 1000000); + +ini_set('memcached.item_size_limit', null); +$m = new Memcached(); +var_dump($m->getOption(Memcached::OPT_ITEM_SIZE_LIMIT) === 0); ?> --EXPECTF-- bool(true) @@ -41,3 +61,15 @@ bool(true) bool(true) bool(false) bool(true) +item_size_limit setOption +bool(true) +bool(true) + +Warning: Memcached::setOption(): ITEM_SIZE_LIMIT must be >= 0 in %s on line %d +bool(false) +bool(true) +bool(true) +item_size_limit ini +bool(true) +bool(true) +bool(true) diff --git a/tests/set_large.phpt b/tests/set_large.phpt index f3cb4cc3..ba9fbca1 100644 --- a/tests/set_large.phpt +++ b/tests/set_large.phpt @@ -5,7 +5,9 @@ set large data --FILE-- 0, +)); $key = 'foobarbazDEADC0DE'; $value = str_repeat("foo bar", 1024 * 1024); diff --git a/tests/set_large_e2big.phpt b/tests/set_large_e2big.phpt new file mode 100644 index 00000000..498231e4 --- /dev/null +++ b/tests/set_large_e2big.phpt @@ -0,0 +1,27 @@ +--TEST-- +set data exceeding size limit +--SKIPIF-- + +--FILE-- + 100, +)); + +$m->delete('set_large_e2big_test'); + +$value = str_repeat('a large payload', 1024 * 1024); + +var_dump($m->set('set_large_e2big_test', $value)); +var_dump($m->getResultCode() == Memcached::RES_E2BIG); +var_dump($m->getResultMessage() == 'ITEM TOO BIG'); +var_dump($m->get('set_large_e2big_test') === false); +var_dump($m->getResultCode() == Memcached::RES_NOTFOUND); +?> +--EXPECT-- +bool(false) +bool(true) +bool(true) +bool(true) +bool(true) diff --git a/tests/setoptions.phpt b/tests/setoptions.phpt index 4bf39d14..9cefd138 100644 --- a/tests/setoptions.phpt +++ b/tests/setoptions.phpt @@ -13,12 +13,14 @@ var_dump($m->setOptions(array( Memcached::OPT_COMPRESSION => 0, Memcached::OPT_LIBKETAMA_COMPATIBLE => 1, Memcached::OPT_CONNECT_TIMEOUT => 5000, + Memcached::OPT_ITEM_SIZE_LIMIT => 1000000, ))); var_dump($m->getOption(Memcached::OPT_PREFIX_KEY) == 'a_prefix'); var_dump($m->getOption(Memcached::OPT_SERIALIZER) == Memcached::SERIALIZER_PHP); var_dump($m->getOption(Memcached::OPT_COMPRESSION) == 0); var_dump($m->getOption(Memcached::OPT_LIBKETAMA_COMPATIBLE) == 1); +var_dump($m->getOption(Memcached::OPT_ITEM_SIZE_LIMIT) == 1000000); echo "test invalid options\n"; @@ -36,6 +38,7 @@ bool(true) bool(true) bool(true) bool(true) +bool(true) test invalid options Warning: Memcached::setOptions(): invalid configuration option in %s on line %d From 7fefcb792423906bba2bac66a49194f98bf11aa6 Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Wed, 3 May 2023 19:10:38 -0400 Subject: [PATCH 314/345] Make the compression_level at settable option and expand it to zlib (#540) Make it possible to use setOption to set Memcached::OPT_COMPRESSION_LEVEL which was missed in the original zstd PR #539 zlib compression was using the default zlib compression level of 6. With this PR it is now possible to choose other levels for zlib as well. The default remains at 6 so nothing will change for people upgrading unless they explicitly set a different level. Here is some more benchmarking data using php serialized data https://gist.github.com/rlerdorf/b9bae385446d5a30b65e6e241e34d0a8 fastlz is not really useful at any value size anymore. Anybody looking for lightning quick compression and decompression should use zstd at level 1. compression_level is not applied to fastlz because it only has 2 levels and php-memcached already switches from level 1 to 2 automatically for values larger than 65535 bytes. Forcing it to one or the other doesn't seem useful. --- php_memcached.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 9c5ba8aa..00d5e3d4 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -884,7 +884,7 @@ zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcal ****************************************/ static -zend_bool s_compress_value (php_memc_compression_type compression_type, zend_string **payload_in, uint32_t *flags) +zend_bool s_compress_value (php_memc_compression_type compression_type, zend_long compression_level, zend_string **payload_in, uint32_t *flags) { /* status */ zend_bool compress_status = 0; @@ -915,7 +915,13 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str #ifdef HAVE_ZSTD_H case COMPRESSION_TYPE_ZSTD: { - compressed_size = ZSTD_compress((void *)buffer, buffer_size, ZSTR_VAL(payload), ZSTR_LEN(payload), MEMC_G(compression_level)); + compressed_size = ZSTD_compress((void *)buffer, buffer_size, ZSTR_VAL(payload), ZSTR_LEN(payload), compression_level); + + if (compression_level < -22) { + compression_level = -22; + } else if (compression_level > 22) { + compression_level = 22; + } if (!ZSTD_isError(compressed_size)) { compress_status = 1; @@ -928,7 +934,14 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str case COMPRESSION_TYPE_ZLIB: { compressed_size = buffer_size; - int status = compress((Bytef *) buffer, &compressed_size, (Bytef *) ZSTR_VAL(payload), ZSTR_LEN(payload)); + + if (compression_level < 0) { + compression_level = 0; + } else if (compression_level > 9) { + compression_level = 9; + } + + int status = compress2((Bytef *) buffer, &compressed_size, (Bytef *) ZSTR_VAL(payload), ZSTR_LEN(payload), compression_level); if (status == Z_OK) { compress_status = 1; @@ -1120,7 +1133,7 @@ zend_string *s_zval_to_payload(php_memc_object_t *intern, zval *value, uint32_t * * No need to check the return value because the payload is always valid. */ - (void)s_compress_value (memc_user_data->compression_type, &payload, flags); + (void)s_compress_value (memc_user_data->compression_type, memc_user_data->compression_level, &payload, flags); } if (memc_user_data->set_udf_flags >= 0) { @@ -1325,6 +1338,7 @@ static PHP_METHOD(Memcached, __construct) memc_user_data = pecalloc (1, sizeof(*memc_user_data), is_persistent); memc_user_data->serializer = MEMC_G(serializer_type); memc_user_data->compression_type = MEMC_G(compression_type); + memc_user_data->compression_level = MEMC_G(compression_level); memc_user_data->compression_enabled = 1; memc_user_data->encoding_enabled = 0; memc_user_data->store_retry_count = MEMC_G(store_retry_count); @@ -3075,6 +3089,11 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value) } break; + case MEMC_OPT_COMPRESSION_LEVEL: + lval = zval_get_long(value); + memc_user_data->compression_level = lval; + break; + case MEMC_OPT_ITEM_SIZE_LIMIT: lval = zval_get_long(value); if (lval < 0) { @@ -4054,7 +4073,7 @@ PHP_GINIT_FUNCTION(php_memcached) php_memcached_globals->memc.compression_threshold = 2000; php_memcached_globals->memc.compression_type = COMPRESSION_TYPE_FASTLZ; php_memcached_globals->memc.compression_factor = 1.30; - php_memcached_globals->memc.compression_level = 3; + php_memcached_globals->memc.compression_level = 6; php_memcached_globals->memc.store_retry_count = 2; php_memcached_globals->memc.item_size_limit = 0; From d2b1172dffbee713857a960bd10b550f7921a1eb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Oct 2023 07:57:32 -0700 Subject: [PATCH 315/345] Bump actions/checkout from 2 to 3 (#534) Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 36cf7cba..de13c538 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -13,7 +13,7 @@ jobs: runs-on: windows-latest steps: - name: Checkout memcached - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup PHP id: setup-php uses: cmb69/setup-php-sdk@v0.7 From eb39e469d02576033e75848ca757a32e3502a3a4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Oct 2023 10:33:10 -0700 Subject: [PATCH 316/345] Bump actions/checkout from 3 to 4 (#548) Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-and-test.yml | 2 +- .github/workflows/build-windows.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 7384dd88..2dcb6673 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -17,7 +17,7 @@ jobs: experimental: true steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: true - name: Install PHP ${{ matrix.php }} diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index de13c538..a7aa8577 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -13,7 +13,7 @@ jobs: runs-on: windows-latest steps: - name: Checkout memcached - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup PHP id: setup-php uses: cmb69/setup-php-sdk@v0.7 From dfd038f13c4347fc15835cd9077a960218e01d98 Mon Sep 17 00:00:00 2001 From: Robert Date: Wed, 27 Dec 2023 19:55:59 -0500 Subject: [PATCH 317/345] Correct whitespace formatting (#553) --- php_memcached_private.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php_memcached_private.h b/php_memcached_private.h index 93c20570..2c22ecba 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -186,8 +186,8 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) char *compression_name; zend_long compression_threshold; double compression_factor; - zend_long store_retry_count; - zend_long compression_level; + zend_long store_retry_count; + zend_long compression_level; zend_long item_size_limit; /* Converted values*/ From 7f31d8651b9ec98b2eb46705d1d17983b9999c13 Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Thu, 7 Mar 2024 10:36:43 -0500 Subject: [PATCH 318/345] The key length check was not taking the prefix into account --- php_memcached.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index 00d5e3d4..1e686f17 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -230,6 +230,19 @@ zend_bool s_memc_valid_key_binary(zend_string *key) return memchr(ZSTR_VAL(key), '\n', ZSTR_LEN(key)) == NULL; } +static +uint32_t s_memc_object_key_max_length(php_memc_object_t *intern) { + memcached_return retval; + char *result; + + result = memcached_callback_get(intern->memc, MEMCACHED_CALLBACK_PREFIX_KEY, &retval); + if (retval == MEMCACHED_SUCCESS && result) { + return MEMC_OBJECT_KEY_MAX_LENGTH - strlen(result); + } else { + return MEMC_OBJECT_KEY_MAX_LENGTH; + } +} + static zend_bool s_memc_valid_key_ascii(zend_string *key) { @@ -245,7 +258,7 @@ zend_bool s_memc_valid_key_ascii(zend_string *key) #define MEMC_CHECK_KEY(intern, key) \ if (UNEXPECTED(ZSTR_LEN(key) == 0 || \ - ZSTR_LEN(key) > MEMC_OBJECT_KEY_MAX_LENGTH || \ + ZSTR_LEN(key) > s_memc_object_key_max_length(intern) || \ (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) \ ? !s_memc_valid_key_binary(key) \ : !s_memc_valid_key_ascii(key) \ From abd372b454986afbea0a53ee1eb8393ff1145216 Mon Sep 17 00:00:00 2001 From: William Van Hevelingen Date: Wed, 15 May 2024 18:31:36 -0700 Subject: [PATCH 319/345] CI: Add PHP 8.3 to the required matrix, add PHP 8.4 to experimental (#557) --- .github/workflows/build-and-test.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 2dcb6673..14733ec1 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -7,13 +7,13 @@ jobs: strategy: fail-fast: false matrix: - php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2'] + php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3'] experimental: [false] include: - php: '8.2' awesome: true experimental: true - - php: '8.3' + - php: '8.4' experimental: true steps: - name: Checkout @@ -35,7 +35,7 @@ jobs: - if: ${{ matrix.awesome }} name: Install libmemcached-awesome (from source) run: | - curl -sL -o libmemcached.tgz https://github.com/awesomized/libmemcached/archive/refs/tags/1.1.3.tar.gz + curl -sL -o libmemcached.tgz https://github.com/awesomized/libmemcached/archive/refs/tags/1.1.4.tar.gz mkdir libmemcached tar --strip-components=1 -xf libmemcached.tgz -C libmemcached mkdir build-libmemcached @@ -83,7 +83,7 @@ jobs: define ("MEMC_SASL_SERVER_HOST", "127.0.0.1"); define ("MEMC_SASL_SERVER_PORT", 11212); - + define ('MEMC_SASL_USER', 'memcached'); define ('MEMC_SASL_PASS', 'test'); EOF From d8d99f07846d201836fe2308263dd0fac087c7be Mon Sep 17 00:00:00 2001 From: William Van Hevelingen Date: Wed, 15 May 2024 22:39:48 -0700 Subject: [PATCH 320/345] docs: fix build status on README.md (#558) --- README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.markdown b/README.markdown index b17b7e55..38dbd5bc 100644 --- a/README.markdown +++ b/README.markdown @@ -1,6 +1,6 @@ Build Status ------------ -[![Build Status](https://travis-ci.org/php-memcached-dev/php-memcached.png)](https://travis-ci.org/php-memcached-dev/php-memcached) +![Build Status](https://github.com/php-memcached-dev/php-memcached/actions/workflows/build-and-test.yml/badge.svg?branch=master) Description ----------- @@ -23,7 +23,7 @@ Dependencies ------------ php-memcached 3.x: -* Supports PHP 7.0 - 8.2 or higher. +* Supports PHP 7.0 - 8.3 or higher. * Requires libmemcached 1.x or higher. * Optionally supports igbinary 2.0 or higher. * Optionally supports msgpack 2.0 or higher. From 93c1bc449ff32e2a26b5f922fdd6dfa43edaeeb9 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Wed, 25 Sep 2024 23:54:00 +0200 Subject: [PATCH 321/345] ci: attempt to fix windows build --- .github/workflows/build-windows.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index a7aa8577..fefd7deb 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -7,7 +7,7 @@ jobs: shell: cmd strategy: matrix: - version: ['7.4', '8.0', '8.1'] + version: ['8.3'] arch: [x64, x86] ts: [nts, zts] runs-on: windows-latest @@ -16,7 +16,7 @@ jobs: uses: actions/checkout@v4 - name: Setup PHP id: setup-php - uses: cmb69/setup-php-sdk@v0.7 + uses: php/setup-php-sdk@v0.9 with: version: ${{matrix.version}} arch: ${{matrix.arch}} From 8a6b0c78014dfb0d133595f06fc4c5bb29ba9a83 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Wed, 25 Sep 2024 23:54:27 +0200 Subject: [PATCH 322/345] ci: ubuntu already ships with awesomized/libmemcached --- .github/workflows/build-and-test.yml | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 14733ec1..a142e10b 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -10,9 +10,6 @@ jobs: php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3'] experimental: [false] include: - - php: '8.2' - awesome: true - experimental: true - php: '8.4' experimental: true steps: @@ -29,20 +26,8 @@ jobs: run: | sudo apt-get update sudo apt-get install cmake memcached libsasl2-dev sasl2-bin zlib1g-dev - - if: ${{ ! matrix.awesome }} - name: Install libmemcached-dev (from distro) + - name: Install libmemcached-dev run: sudo apt-get install libmemcached-dev - - if: ${{ matrix.awesome }} - name: Install libmemcached-awesome (from source) - run: | - curl -sL -o libmemcached.tgz https://github.com/awesomized/libmemcached/archive/refs/tags/1.1.4.tar.gz - mkdir libmemcached - tar --strip-components=1 -xf libmemcached.tgz -C libmemcached - mkdir build-libmemcached - cd build-libmemcached - cmake -D ENABLE_HASH_HSIEH=ON -D ENABLE_SASL=ON ../libmemcached - make - sudo make install - name: Start memcached daemons run: | export SASL_CONF_PATH="/tmp/sasl2" From 899f0d52425b3efe2f67ed73eca115a0b5dc6c34 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Tue, 30 Jan 2024 09:44:48 +0100 Subject: [PATCH 323/345] Fix incompatible pointer types --- php_memcached.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 00d5e3d4..c3ef16e8 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -933,7 +933,7 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_lon case COMPRESSION_TYPE_ZLIB: { - compressed_size = buffer_size; + unsigned long cs = compressed_size = buffer_size; if (compression_level < 0) { compression_level = 0; @@ -941,9 +941,10 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_lon compression_level = 9; } - int status = compress2((Bytef *) buffer, &compressed_size, (Bytef *) ZSTR_VAL(payload), ZSTR_LEN(payload), compression_level); + int status = compress2((Bytef *) buffer, &cs, (Bytef *) ZSTR_VAL(payload), ZSTR_LEN(payload), compression_level); if (status == Z_OK) { + compressed_size = cs; compress_status = 1; compression_type_flag = MEMC_VAL_COMPRESSION_ZLIB; } @@ -3751,7 +3752,10 @@ zend_string *s_decompress_value (const char *payload, size_t payload_len, uint32 decompress_status = ((length = fastlz_decompress(payload, payload_len, &buffer->val, buffer->len)) > 0); } else if (is_zlib) { - decompress_status = (uncompress((Bytef *) buffer->val, &buffer->len, (Bytef *)payload, payload_len) == Z_OK); + unsigned long ds = buffer->len; + + decompress_status = (uncompress((Bytef *) buffer->val, &ds, (Bytef *)payload, payload_len) == Z_OK); + buffer->len = ds; } ZSTR_VAL(buffer)[stored_length] = '\0'; From 7227982467bb16786817b6c1aec85f99ce1e3a2e Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Thu, 19 Sep 2024 07:52:19 +0100 Subject: [PATCH 324/345] Added a composer.json to enable support for PIE --- composer.json | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 composer.json diff --git a/composer.json b/composer.json new file mode 100644 index 00000000..3356c89d --- /dev/null +++ b/composer.json @@ -0,0 +1,68 @@ +{ + "name": "php-memcached/php-memcached", + "type": "php-ext", + "license": "PHP-3.01", + "description": "memcached extension based on libmemcached library ", + "require": { + "php": ">= 7.0.0" + }, + "suggest": { + "ext-igbinary": "igbinary is a faster and more compact binary serializer for PHP data structures.", + "ext-msgpack": "msgpack is a faster and more compact data structure representation that is interoperable with msgpack implementations for other languages." + }, + "php-ext": { + "extension-name": "memcached", + "configure-options": [ + { + "name": "enable-memcached", + "description": "Enable memcached support" + }, + { + "name": "with-libmemcached-dir", + "description": "Set the path to libmemcached install prefix.", + "needs-value": true + }, + { + "name": "enable-memcached-session", + "description": "Enable memcached session handler support" + }, + { + "name": "enable-memcached-igbinary", + "description": "Enable memcached igbinary serializer support" + }, + { + "name": "enable-memcached-json", + "description": "Enable memcached json serializer support" + }, + { + "name": "enable-memcached-msgpack", + "description": "Enable memcached msgpack serializer support" + }, + { + "name": "enable-memcached-sasl", + "description": "Enable memcached sasl support" + }, + { + "name": "enable-memcached-protocol", + "description": "Enable memcached protocol support" + }, + { + "name": "with-system-fastlz", + "description": "Use system FastLZ library" + }, + { + "name": "with-zstd", + "description": "Use system zstd library" + }, + { + "name": "with-zlib-dir", + "description": "Set the path to ZLIB install prefix.", + "needs-value": true + }, + { + "name": "enable-debug", + "description": "Compile with debugging symbols" + } + ] + } +} From 0987380a558c4dadb9e0fa909132c5adea1f44ad Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Thu, 19 Oct 2023 18:07:48 -0700 Subject: [PATCH 325/345] If client-side verify_key is not enabled, don't check it automatically --- php_memcached.c | 1 + 1 file changed, 1 insertion(+) diff --git a/php_memcached.c b/php_memcached.c index c3ef16e8..71725bb9 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -246,6 +246,7 @@ zend_bool s_memc_valid_key_ascii(zend_string *key) #define MEMC_CHECK_KEY(intern, key) \ if (UNEXPECTED(ZSTR_LEN(key) == 0 || \ ZSTR_LEN(key) > MEMC_OBJECT_KEY_MAX_LENGTH || \ + memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_VERIFY_KEY) && \ (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) \ ? !s_memc_valid_key_binary(key) \ : !s_memc_valid_key_ascii(key) \ From 198e9b3681bb0a401385271e5a25b0d863b89d8f Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Thu, 19 Oct 2023 19:06:12 -0700 Subject: [PATCH 326/345] fix tests --- tests/cas_invalid_key.phpt | 5 ++++- tests/delete_bykey.phpt | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/cas_invalid_key.phpt b/tests/cas_invalid_key.phpt index b8a815dc..9cb7293c 100644 --- a/tests/cas_invalid_key.phpt +++ b/tests/cas_invalid_key.phpt @@ -5,7 +5,10 @@ Memcached::cas() with strange key --FILE-- false, + Memcached::OPT_VERIFY_KEY => true +)); error_reporting(0); var_dump($m->cas(0, '', true, 10)); diff --git a/tests/delete_bykey.phpt b/tests/delete_bykey.phpt index 929ffbc1..6aa589c5 100644 --- a/tests/delete_bykey.phpt +++ b/tests/delete_bykey.phpt @@ -5,7 +5,10 @@ Memcached::deleteByKey() --FILE-- false, + Memcached::OPT_VERIFY_KEY => true +)); $m->setByKey('keffe', 'eisaleeoo', "foo"); var_dump($m->getByKey('keffe', 'eisaleeoo')); From da71ae036237130b9e879f02326690e8ca73358a Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Thu, 19 Oct 2023 21:42:43 -0700 Subject: [PATCH 327/345] Fix more tests with a slight refactor --- php_memcached.c | 3 +-- tests/get.phpt | 5 ++++- tests/keys_ascii.phpt | 5 +---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 71725bb9..55c20089 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -246,10 +246,9 @@ zend_bool s_memc_valid_key_ascii(zend_string *key) #define MEMC_CHECK_KEY(intern, key) \ if (UNEXPECTED(ZSTR_LEN(key) == 0 || \ ZSTR_LEN(key) > MEMC_OBJECT_KEY_MAX_LENGTH || \ - memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_VERIFY_KEY) && \ (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) \ ? !s_memc_valid_key_binary(key) \ - : !s_memc_valid_key_ascii(key) \ + : (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_VERIFY_KEY) && !s_memc_valid_key_ascii(key)) \ ))) { \ intern->rescode = MEMCACHED_BAD_KEY_PROVIDED; \ RETURN_FALSE; \ diff --git a/tests/get.phpt b/tests/get.phpt index 71889064..722308f0 100644 --- a/tests/get.phpt +++ b/tests/get.phpt @@ -5,7 +5,10 @@ Memcached::get() --FILE-- false, + Memcached::OPT_VERIFY_KEY => true +)); $m->delete('foo'); diff --git a/tests/keys_ascii.phpt b/tests/keys_ascii.phpt index f7e98894..e7846e99 100644 --- a/tests/keys_ascii.phpt +++ b/tests/keys_ascii.phpt @@ -8,11 +8,8 @@ Test valid and invalid keys - ascii include dirname (__FILE__) . '/config.inc'; $ascii = memc_get_instance (array ( Memcached::OPT_BINARY_PROTOCOL => false, - Memcached::OPT_VERIFY_KEY => false + Memcached::OPT_VERIFY_KEY => true )); -// libmemcached can verify keys, but these are tests are for our own -// function s_memc_valid_key_ascii, so explicitly disable the checks -// that libmemcached can perform. echo 'ASCII: SPACES' . PHP_EOL; var_dump ($ascii->set ('ascii key with spaces', 'this is a test')); From d15c2e2fdf3791a0fc7b711a8b02cfce1e78b76f Mon Sep 17 00:00:00 2001 From: Rasmus Lerdorf Date: Fri, 20 Oct 2023 08:00:37 -0700 Subject: [PATCH 328/345] Check for spaces in keys when using the non-binary protocol even if key verification is disabled to avoid injection issues --- php_memcached.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 55c20089..e77e99b0 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -231,14 +231,21 @@ zend_bool s_memc_valid_key_binary(zend_string *key) } static -zend_bool s_memc_valid_key_ascii(zend_string *key) +zend_bool s_memc_valid_key_ascii(zend_string *key, uint64_t verify_key) { const char *str = ZSTR_VAL(key); size_t i, len = ZSTR_LEN(key); - for (i = 0; i < len; i++) { - if (!isgraph(str[i]) || isspace(str[i])) - return 0; + if (verify_key) { + for (i = 0; i < len; i++) { + if (!isgraph(str[i]) || isspace(str[i])) + return 0; + } + } else { /* if key verification is disabled, only check for spaces to avoid injection issues */ + for (i = 0; i < len; i++) { + if (isspace(str[i])) + return 0; + } } return 1; } @@ -248,7 +255,7 @@ zend_bool s_memc_valid_key_ascii(zend_string *key) ZSTR_LEN(key) > MEMC_OBJECT_KEY_MAX_LENGTH || \ (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) \ ? !s_memc_valid_key_binary(key) \ - : (memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_VERIFY_KEY) && !s_memc_valid_key_ascii(key)) \ + : !s_memc_valid_key_ascii(key, memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_VERIFY_KEY)) \ ))) { \ intern->rescode = MEMCACHED_BAD_KEY_PROVIDED; \ RETURN_FALSE; \ @@ -342,7 +349,7 @@ PHP_INI_MH(OnUpdateSessionPrefixString) php_error_docref(NULL, E_WARNING, "memcached.sess_prefix too long (max: %d)", MEMCACHED_MAX_KEY - 1); return FAILURE; } - if (!s_memc_valid_key_ascii(new_value)) { + if (!s_memc_valid_key_ascii(new_value, 1)) { php_error_docref(NULL, E_WARNING, "memcached.sess_prefix cannot contain whitespace or control characters"); return FAILURE; } From 3ca10ec762c3844088f49d2f82a64ee188582d83 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Thu, 26 Sep 2024 13:28:51 +0200 Subject: [PATCH 329/345] ci: supply a name for the ubuntu workflow --- .github/workflows/build-and-test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index a142e10b..2e10b05b 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -1,3 +1,5 @@ + +name: Test on Ubuntu on: [push, pull_request] jobs: From 2719e1ec2d0050d9ad82f32528b866c6cacfa586 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Thu, 26 Sep 2024 13:29:34 +0200 Subject: [PATCH 330/345] prepare v3.3.0RC1 - Add #515 option to locally enforce payload size limit - Add #539 zstd support - Add #540 compression_level option - Mark password as a sensitive param for PHP 8.2 - Fix Windows PHP 8 compatibility - Fix #518 Windows msgpack support - Fix #522 signed integer overflow - Fix #523 incorrect PHP reflection type for Memcached::cas $cas_token - Fix #546 don't check key automatically, unless client-side verify_key is enabled - Fix #555 incompatible pointer types (32-bit) --- package.xml | 20 ++++++++++++++------ php_memcached.h | 2 +- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/package.xml b/package.xml index 6a14b96c..bee0600e 100644 --- a/package.xml +++ b/package.xml @@ -33,19 +33,27 @@ http://pear.php.net/dtd/package-2.0.xsd"> remi@php.net yes - 2022-03-24 + 2024-09-26 - 3.2.1dev - 3.2.0 + 3.3.0RC1 + 3.3.0 - stable + beta stable PHP -- mark password as a sensitive param for PHP 8.2 -- Fix #523 Incorrect PHP reflection type for Memcached::cas $cas_token +- Add #515 option to locally enforce payload size limit +- Add #539 zstd support +- Add #540 compression_level option +- Mark password as a sensitive param for PHP 8.2 +- Fix Windows PHP 8 compatibility +- Fix #518 Windows msgpack support +- Fix #522 signed integer overflow +- Fix #523 incorrect PHP reflection type for Memcached::cas $cas_token +- Fix #546 don't check key automatically, unless client-side verify_key is enabled +- Fix #555 incompatible pointer types (32-bit) diff --git a/php_memcached.h b/php_memcached.h index e966d19d..56664235 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.2.1-dev" +#define PHP_MEMCACHED_VERSION "3.3.0RC1" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 25a192cde20e43e1a1200f6aee74aebeb3bfb435 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Fri, 4 Oct 2024 16:45:19 +0200 Subject: [PATCH 331/345] release v3.3.0RC1 - Add #515 option to locally enforce payload size limit - Add #539 zstd support - Add #540 compression_level option - Mark password as a sensitive param for PHP 8.2 - Fix Windows PHP 8 compatibility - Fix #518 Windows msgpack support - Fix #522 signed integer overflow - Fix #523 incorrect PHP reflection type for Memcached::cas $cas_token - Fix #546 don't check key automatically, unless client-side verify_key is enabled --- package.xml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/package.xml b/package.xml index bee0600e..e1d6f060 100644 --- a/package.xml +++ b/package.xml @@ -33,7 +33,13 @@ http://pear.php.net/dtd/package-2.0.xsd"> remi@php.net yes - 2024-09-26 + + Michael Wallner + mike + mike@php.net + yes + + 2024-10-04 3.3.0RC1 3.3.0 From 6189c32892d4bc553a3707160656469a089b5d43 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 30 Sep 2024 13:00:37 +0200 Subject: [PATCH 332/345] Use setup-php-sdk caching While a new release is pending, it seems worthwhile to make use of the caching as soon as possible to speed up Windows CI. --- .github/workflows/build-windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index fefd7deb..b4231090 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -16,7 +16,7 @@ jobs: uses: actions/checkout@v4 - name: Setup PHP id: setup-php - uses: php/setup-php-sdk@v0.9 + uses: php/setup-php-sdk@d07cd9875fcb041bbfa63c2c592c4e68a137e1ca with: version: ${{matrix.version}} arch: ${{matrix.arch}} From 61957273e30537c3b14ec0413bc6863156d1b538 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 30 Sep 2024 13:07:18 +0200 Subject: [PATCH 333/345] Actually enable caching --- .github/workflows/build-windows.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index b4231090..c30c9dfe 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -22,6 +22,7 @@ jobs: arch: ${{matrix.arch}} ts: ${{matrix.ts}} deps: zlib + cache: true - name: Fetch libmemcached run: curl -OLs https://windows.php.net/downloads/pecl/deps/libmemcached-1.1.1-${{steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip && 7z x libmemcached-1.1.1-${{steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip -o..\deps - name: Enable Developer Command Prompt From cf30549f250690607d8c7363051a6a7bd3f637b6 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 30 Sep 2024 13:20:10 +0200 Subject: [PATCH 334/345] Test PHP 8.4 on Windows, too While caching speeds up the Windows builds, allocating an available runner takes some time (especially for many pushes in a short time). Thus we only build PHP 8.4 x64,zts, which should already suffice to detect most issues. --- .github/workflows/build-windows.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index c30c9dfe..3356c265 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -7,9 +7,13 @@ jobs: shell: cmd strategy: matrix: - version: ['8.3'] + version: ['8.3', '8.4'] arch: [x64, x86] ts: [nts, zts] + exclude: + - { version: '8.4', arch: x64, ts: zts } + - { version: '8.4', arch: x86, ts: nts } + - { version: '8.4', arch: x86, ts: zts } runs-on: windows-latest steps: - name: Checkout memcached From 8877b9ac8ab6dfc29384a549e06de0c03f8081eb Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 30 Sep 2024 13:25:46 +0200 Subject: [PATCH 335/345] Use new download server windows.php.net is in the process of being replaced by downloads.php.net, so we switch right away. --- .github/workflows/build-windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 3356c265..d4d6133b 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -28,7 +28,7 @@ jobs: deps: zlib cache: true - name: Fetch libmemcached - run: curl -OLs https://windows.php.net/downloads/pecl/deps/libmemcached-1.1.1-${{steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip && 7z x libmemcached-1.1.1-${{steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip -o..\deps + run: curl -OLs https://downloads.php.net/~windows/pecl/deps/libmemcached-1.1.1-${{steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip && 7z x libmemcached-1.1.1-${{steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip -o..\deps - name: Enable Developer Command Prompt uses: ilammy/msvc-dev-cmd@v1 with: From c6f7d8d2beb4e9172ef517e7f99046db803f23ac Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 30 Sep 2024 13:31:04 +0200 Subject: [PATCH 336/345] Cater to yet missing libmemcached-vs17 Using libmemcached-vs16 instead should be fine. --- .github/workflows/build-windows.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index d4d6133b..c5b04ce6 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -28,7 +28,9 @@ jobs: deps: zlib cache: true - name: Fetch libmemcached - run: curl -OLs https://downloads.php.net/~windows/pecl/deps/libmemcached-1.1.1-${{steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip && 7z x libmemcached-1.1.1-${{steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip -o..\deps + run: | + set MEMCACHED_FILENAME=libmemcached-1.1.1-${{steps.setup-php.outputs.vs == 'vs17' && 'vs16' || steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip + curl -OLs https://downloads.php.net/~windows/pecl/deps/%MEMCACHED_FILENAME% && 7z x %MEMCACHED_FILENAME% -o..\deps - name: Enable Developer Command Prompt uses: ilammy/msvc-dev-cmd@v1 with: From 089a367fe211ca4eebe5b7ae8fb1370ac00add94 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 30 Sep 2024 15:07:48 +0200 Subject: [PATCH 337/345] Update setup-php-sdk to v0.10 --- .github/workflows/build-windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index c5b04ce6..4c2640e4 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -20,7 +20,7 @@ jobs: uses: actions/checkout@v4 - name: Setup PHP id: setup-php - uses: php/setup-php-sdk@d07cd9875fcb041bbfa63c2c592c4e68a137e1ca + uses: php/setup-php-sdk@v0.10 with: version: ${{matrix.version}} arch: ${{matrix.arch}} From 9243f1ff40a771de11093726a7862cc085b19da2 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 15 Oct 2024 15:02:35 +0200 Subject: [PATCH 338/345] Update libmemcached to 1.1.4 for Windows CI --- .github/workflows/build-windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 4c2640e4..15dba3f2 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -29,7 +29,7 @@ jobs: cache: true - name: Fetch libmemcached run: | - set MEMCACHED_FILENAME=libmemcached-1.1.1-${{steps.setup-php.outputs.vs == 'vs17' && 'vs16' || steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip + set MEMCACHED_FILENAME=libmemcached-1.1.4-${{steps.setup-php.outputs.vs == 'vs17' && 'vs16' || steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip curl -OLs https://downloads.php.net/~windows/pecl/deps/%MEMCACHED_FILENAME% && 7z x %MEMCACHED_FILENAME% -o..\deps - name: Enable Developer Command Prompt uses: ilammy/msvc-dev-cmd@v1 From b0b82692d789a2a5fd95b3910e87f73615c0f918 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Thu, 17 Oct 2024 19:33:43 +0200 Subject: [PATCH 339/345] release v3.3.0 --- package.xml | 7 ++++--- php_memcached.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/package.xml b/package.xml index e1d6f060..1acb7c73 100644 --- a/package.xml +++ b/package.xml @@ -39,13 +39,13 @@ http://pear.php.net/dtd/package-2.0.xsd"> mike@php.net yes - 2024-10-04 + 2024-10-17 - 3.3.0RC1 + 3.3.0 3.3.0 - beta + stable stable PHP @@ -54,6 +54,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> - Add #539 zstd support - Add #540 compression_level option - Mark password as a sensitive param for PHP 8.2 +- Upgrade Windows libmemcached to v1.1.4 - Fix Windows PHP 8 compatibility - Fix #518 Windows msgpack support - Fix #522 signed integer overflow diff --git a/php_memcached.h b/php_memcached.h index 56664235..905f941d 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.3.0RC1" +#define PHP_MEMCACHED_VERSION "3.3.0" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From bfcd9e7bbac40693cc055adc5f8722ef13909e38 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Thu, 17 Oct 2024 19:50:29 +0200 Subject: [PATCH 340/345] back to dev --- package.xml | 41 ++++++++++++++++++++++++++++------------- php_memcached.h | 2 +- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/package.xml b/package.xml index 1acb7c73..5565863e 100644 --- a/package.xml +++ b/package.xml @@ -41,26 +41,16 @@ http://pear.php.net/dtd/package-2.0.xsd"> 2024-10-17 - 3.3.0 + 3.3.1dev 3.3.0 - stable + beta stable PHP -- Add #515 option to locally enforce payload size limit -- Add #539 zstd support -- Add #540 compression_level option -- Mark password as a sensitive param for PHP 8.2 -- Upgrade Windows libmemcached to v1.1.4 -- Fix Windows PHP 8 compatibility -- Fix #518 Windows msgpack support -- Fix #522 signed integer overflow -- Fix #523 incorrect PHP reflection type for Memcached::cas $cas_token -- Fix #546 don't check key automatically, unless client-side verify_key is enabled -- Fix #555 incompatible pointer types (32-bit) +- @@ -231,6 +221,31 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + 2024-10-17 + + 3.3.0 + 3.3.0 + + + stable + stable + + PHP + +- Add #515 option to locally enforce payload size limit +- Add #539 zstd support +- Add #540 compression_level option +- Mark password as a sensitive param for PHP 8.2 +- Upgrade Windows libmemcached to v1.1.4 +- Fix Windows PHP 8 compatibility +- Fix #518 Windows msgpack support +- Fix #522 signed integer overflow +- Fix #523 incorrect PHP reflection type for Memcached::cas $cas_token +- Fix #546 don't check key automatically, unless client-side verify_key is enabled +- Fix #555 incompatible pointer types (32-bit) + + 2022-03-24 diff --git a/php_memcached.h b/php_memcached.h index 905f941d..dfd19185 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.3.0" +#define PHP_MEMCACHED_VERSION "3.3.1dev" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From bb83855d1874d1741ec51277f2ed496a476d35ff Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Tue, 15 Jul 2025 19:56:33 +0200 Subject: [PATCH 341/345] use zend_ce_exception (#573) --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index c8abb844..b78eb82a 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3961,7 +3961,7 @@ zend_class_entry *php_memc_get_exception_base(int root) } } - return zend_exception_get_default(); + return zend_ce_exception; } From de7d53d13aecd329f03eab2eaf51c1ad8fa5c18f Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 31 Jul 2025 01:30:53 +0200 Subject: [PATCH 342/345] use Zend/zend_smart_string.h (#574) --- php_memcached_private.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/php_memcached_private.h b/php_memcached_private.h index 2c22ecba..b7d2a5e1 100644 --- a/php_memcached_private.h +++ b/php_memcached_private.h @@ -43,7 +43,11 @@ #include #include #include +#if PHP_VERSION_ID < 70200 #include +#else +#include +#endif #include #include From 44868b5b25c4f94bb09116cc50faab8eafc20da4 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 12 Oct 2025 20:45:03 -0700 Subject: [PATCH 343/345] Release 3.4.0 with tests for PHP 8.5 (#575) --- .github/workflows/build-and-test.yml | 6 +++--- .github/workflows/build-windows.yml | 7 ++++--- package.xml | 24 ++++++++++++++++++++---- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 2e10b05b..50a0c2fd 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -9,14 +9,14 @@ jobs: strategy: fail-fast: false matrix: - php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3'] + php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5'] experimental: [false] include: - - php: '8.4' + - php: '8.6' experimental: true steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: submodules: true - name: Install PHP ${{ matrix.php }} diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 15dba3f2..b12a3557 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -7,9 +7,10 @@ jobs: shell: cmd strategy: matrix: - version: ['8.3', '8.4'] arch: [x64, x86] + os: [windows-2022] ts: [nts, zts] + version: ['8.3', '8.4', '8.5'] exclude: - { version: '8.4', arch: x64, ts: zts } - { version: '8.4', arch: x86, ts: nts } @@ -17,10 +18,10 @@ jobs: runs-on: windows-latest steps: - name: Checkout memcached - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Setup PHP id: setup-php - uses: php/setup-php-sdk@v0.10 + uses: php/setup-php-sdk@v0.11 with: version: ${{matrix.version}} arch: ${{matrix.arch}} diff --git a/package.xml b/package.xml index 5565863e..384e7ea1 100644 --- a/package.xml +++ b/package.xml @@ -39,13 +39,13 @@ http://pear.php.net/dtd/package-2.0.xsd"> mike@php.net yes - 2024-10-17 + 2025-10-12 - 3.3.1dev - 3.3.0 + 3.4.0 + 3.4.0 - beta + stable stable PHP @@ -221,6 +221,22 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + 2025-10-12 + + 3.4.0 + 3.4.0 + + + stable + stable + + PHP + +- Use Zend/zend_smart_string.h for PHP 8.5 compatibility (#574) +- Use zen_ce_exception for PHP 8.5 compatibility (#573) + + 2024-10-17 From ce37962769fc7b25f9905c4b23fa53df92447a32 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 12 Oct 2025 22:03:44 -0700 Subject: [PATCH 344/345] Release 3.4.0 --- package.xml | 2 +- php_memcached.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.xml b/package.xml index 384e7ea1..bfcd6edd 100644 --- a/package.xml +++ b/package.xml @@ -39,7 +39,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> mike@php.net yes - 2025-10-12 + 2025-10-13 3.4.0 3.4.0 diff --git a/php_memcached.h b/php_memcached.h index dfd19185..dda3353f 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.3.1dev" +#define PHP_MEMCACHED_VERSION "3.4.0" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport) From 4ef6dce3bd1b486b372c79b398e86b03b8c76df3 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 12 Oct 2025 22:04:37 -0700 Subject: [PATCH 345/345] Mark as next dev version 3.4.1dev --- php_memcached.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.h b/php_memcached.h index dda3353f..60b916e9 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -30,7 +30,7 @@ # include "config.h" #endif -#define PHP_MEMCACHED_VERSION "3.4.0" +#define PHP_MEMCACHED_VERSION "3.4.1dev" #if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS) #define PHP_MEMCACHED_API __declspec(dllexport)