From 2cc0e324fd76fd9034d7f6bdb57654920d91fa0c Mon Sep 17 00:00:00 2001 From: Nicolas Van Eenaeme Date: Thu, 7 Nov 2013 00:24:58 +0100 Subject: [PATCH 01/15] Initial commit that introduces UDF (user defined flags). Memcached.txt specifies that flags are a 16-bit integer. Since the library uses internally 8 bits to store type, compression and serialization, this leaves us 8 bytes left to store user data. So basically added the udf_flags parameter to all relevant functions to store and retrieve them. --- php_memcached.c | 160 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 128 insertions(+), 32 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 642cb162..925b9b4b 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -129,6 +129,13 @@ typedef unsigned long int uint32_t; #define MEMC_VAL_COMPRESSION_ZLIB (1<<5) #define MEMC_VAL_COMPRESSION_FASTLZ (1<<6) +/**************************************** + User-defined flags +****************************************/ +#define MEMC_UDF_MASK 0xf0 +#define MEMC_UDF_GET(flags) ((long)(((flags) & MEMC_UDF_MASK)>>8)) +#define MEMC_UDF_SET(flags, udf_flags) ((flags) |= ((udf_flags<<8) & MEMC_VAL_TYPE_MASK)) + /**************************************** "get" operation flags ****************************************/ @@ -491,7 +498,7 @@ static PHP_METHOD(Memcached, __construct) } /* }}} */ -/* {{{ Memcached::get(string key [, mixed callback [, double &cas_token ] ]) +/* {{{ Memcached::get(string key [, mixed callback [, double &cas_token [, int &udf_flags ] ] ]) Returns a value for the given key or false */ PHP_METHOD(Memcached, get) { @@ -499,7 +506,7 @@ PHP_METHOD(Memcached, get) } /* }}} */ -/* {{{ Memcached::getByKey(string server_key, string key [, mixed callback [, double &cas_token ] ]) +/* {{{ Memcached::getByKey(string server_key, string key [, mixed callback [, double &cas_token [, int &udf_flags ] ] ]) Returns a value for key from the server identified by the server key or false */ PHP_METHOD(Memcached, getByKey) { @@ -521,6 +528,7 @@ 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; zend_fcall_info fci = empty_fcall_info; zend_fcall_info_cache fcc = empty_fcall_info_cache; memcached_result_st result; @@ -528,13 +536,13 @@ 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!z", &server_key, - &server_key_len, &key, &key_len, &fci, &fcc, &cas_token) == FAILURE) { + 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) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|f!z", &key, &key_len, - &fci, &fcc, &cas_token) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|f!zz", &key, &key_len, + &fci, &fcc, &cas_token, &udf_flags) == FAILURE) { return; } } @@ -616,6 +624,10 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) zval_dtor(cas_token); ZVAL_DOUBLE(cas_token, (double)cas); + if (udf_flags) ( + ZVAL_DOUBLE(udf_flags, MEMC_UDF_GET(flags)); + } + memcached_result_free(&result); } else { @@ -663,11 +675,14 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) } } + if (udf_flags) ( + ZVAL_DOUBLE(udf_flags, MEMC_UDF_GET(flags)); + } } } /* }}} */ -/* {{{ Memcached::getMulti(array keys [, array &cas_tokens ]) +/* {{{ Memcached::getMulti(array keys [, array &cas_tokens [, array &udf_flags ] ]) Returns values for the given keys or false */ PHP_METHOD(Memcached, getMulti) { @@ -675,7 +690,7 @@ PHP_METHOD(Memcached, getMulti) } /* }}} */ -/* {{{ Memcached::getMultiByKey(string server_key, array keys [, array &cas_tokens ]) +/* {{{ Memcached::getMultiByKey(string server_key, array keys [, array &cas_tokens [, array &udf_flags ] ]) Returns values for the given keys from the server identified by the server key or false */ PHP_METHOD(Memcached, getMultiByKey) { @@ -700,6 +715,7 @@ 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; zval *value; long get_flags = 0; @@ -710,12 +726,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/|zl", &server_key, - &server_key_len, &keys, &cas_tokens, &get_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa/|zlz", &server_key, + &server_key_len, &keys, &cas_tokens, &get_flags, &udf_flags) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/|zl", &keys, &cas_tokens, &get_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/|zlz", &keys, &cas_tokens, &get_flags, &udf_flags) == FAILURE) { return; } } @@ -792,6 +808,15 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke array_init(cas_tokens); } + /* + * Iterate through the result set and create the result array. The flags are + * returned as longs. + */ + if (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) { if (status != MEMCACHED_SUCCESS) { @@ -834,6 +859,9 @@ 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+1, (double)cas); } + if (udf_flags) { + add_assoc_long_ex(udf_flags, res_key, res_key_len+1, MEMC_UDF_GET(flags)); + } } memcached_result_free(&result); @@ -844,6 +872,10 @@ 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_dtor(udf_flags); + ZVAL_NULL(udf_flags); + } zval_dtor(return_value); RETURN_FALSE; } @@ -1040,6 +1072,9 @@ PHP_METHOD(Memcached, fetch) /* XXX: also check against ULLONG_MAX or memc_behavior */ add_assoc_double_ex(return_value, ZEND_STRS("cas"), (double)cas); } + if (flags & MEMC_UDF_MASK != 0) { + add_assoc_long_ex(return_value, ZEND_STRS("flags"), MEMC_UDF_GET(flags)); + } memcached_result_free(&result); } @@ -1096,6 +1131,9 @@ PHP_METHOD(Memcached, fetchAll) /* XXX: also check against ULLONG_MAX or memc_behavior */ add_assoc_double_ex(entry, ZEND_STRS("cas"), (double)cas); } + if (flags & MEMC_UDF_MASK != 0) { + add_assoc_long_ex(entry, ZEND_STRS("flags"), MEMC_UDF_GET(flags)); + } add_next_index_zval(return_value, entry); } @@ -1108,7 +1146,7 @@ PHP_METHOD(Memcached, fetchAll) } /* }}} */ -/* {{{ Memcached::set(string key, mixed value [, int expiration ]) +/* {{{ Memcached::set(string key, mixed value [, int expiration [, int udf_flags ] ]) Sets the value for the given key */ PHP_METHOD(Memcached, set) { @@ -1116,7 +1154,7 @@ PHP_METHOD(Memcached, set) } /* }}} */ -/* {{{ Memcached::setByKey(string server_key, string key, mixed value [, int expiration ]) +/* {{{ Memcached::setByKey(string server_key, string key, mixed value [, int expiration [, int udf_flags ] ]) Sets the value for the given key on the server identified by the server key */ PHP_METHOD(Memcached, setByKey) { @@ -1143,7 +1181,7 @@ PHP_METHOD(Memcached, touchByKey) #endif -/* {{{ Memcached::setMulti(array items [, int expiration ]) +/* {{{ Memcached::setMulti(array items [, int expiration [, int udf_flags ] ]) Sets the keys/values specified in the items array */ PHP_METHOD(Memcached, setMulti) { @@ -1151,7 +1189,7 @@ PHP_METHOD(Memcached, setMulti) } /* }}} */ -/* {{{ Memcached::setMultiByKey(string server_key, array items [, int expiration ]) +/* {{{ Memcached::setMultiByKey(string server_key, array items [, int expiration [, int udf_flags ] ]) Sets the keys/values specified in the items array on the server identified by the given server key */ PHP_METHOD(Memcached, setMultiByKey) { @@ -1190,6 +1228,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke char *server_key = NULL; int server_key_len = 0; time_t expiration = 0; + uint32_t udf_flags = 0; zval **entry; char *str_key; uint str_key_len; @@ -1203,12 +1242,12 @@ 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() TSRMLS_CC, "sa|l", &server_key, - &server_key_len, &entries, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa|ll", &server_key, + &server_key_len, &entries, &expiration, &udf_flags) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &entries, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|ll", &entries, &expiration, &udf_flags) == FAILURE) { return; } } @@ -1216,6 +1255,16 @@ 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 8 bits internally to store type, compression and serialization info. + * We use 8 upper bits to store user defined flags. + */ + if (udf_flags > 0) { + if (udf_flags > 0xf) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to 8 bits (0xf)"); + } + } + 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))) { @@ -1238,6 +1287,10 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke flags |= MEMC_VAL_COMPRESSED; } + if (udf_flags > 0) { + MEMC_UDF_SET(flags, udf_flags); + } + payload = php_memc_zval_to_payload(*entry, &payload_len, &flags, m_obj->serializer, m_obj->compression_type TSRMLS_CC); if (payload == NULL) { i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; @@ -1263,7 +1316,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke } /* }}} */ -/* {{{ Memcached::add(string key, mixed value [, int expiration ]) +/* {{{ Memcached::add(string key, mixed value [, int expiration [, int udf_flags ] ]) Sets the value for the given key, failing if the key already exists */ PHP_METHOD(Memcached, add) { @@ -1271,7 +1324,7 @@ PHP_METHOD(Memcached, add) } /* }}} */ -/* {{{ Memcached::addByKey(string server_key, string key, mixed value [, int expiration ]) +/* {{{ Memcached::addByKey(string server_key, string key, mixed value [, int expiration [, int udf_flags ] ]) 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) { @@ -1311,7 +1364,7 @@ PHP_METHOD(Memcached, prependByKey) } /* }}} */ -/* {{{ Memcached::replace(string key, mixed value [, int expiration ]) +/* {{{ Memcached::replace(string key, mixed value [, int expiration [, int udf_flags ] ]) Replaces the value for the given key, failing if the key doesn't exist */ PHP_METHOD(Memcached, replace) { @@ -1319,7 +1372,7 @@ PHP_METHOD(Memcached, replace) } /* }}} */ -/* {{{ Memcached::replaceByKey(string server_key, string key, mixed value [, int expiration ]) +/* {{{ Memcached::replaceByKey(string server_key, string key, mixed value [, int expiration [, int udf_flags ] ]) 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) { @@ -1340,6 +1393,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool zval s_zvalue; zval *value; time_t expiration = 0; + uint32_t udf_flags = 0; char *payload; size_t payload_len; uint32_t flags = 0; @@ -1362,8 +1416,8 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssz|l", &server_key, - &server_key_len, &key, &key_len, &value, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssz|ll", &server_key, + &server_key_len, &key, &key_len, &value, &expiration, &udf_flags) == FAILURE) { return; } } @@ -1382,8 +1436,8 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &key, &key_len, - &value, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|ll", &key, &key_len, + &value, &expiration, &udf_flags) == FAILURE) { return; } } @@ -1410,6 +1464,18 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool flags |= MEMC_VAL_COMPRESSED; } + /* + * php_memcached uses 8 bits internally to store type, compression and serialization info. + * We use 8 upper bits to store user defined flags. + */ + if (udf_flags > 0) { + if (udf_flags > 0xf) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to 8 bits (0xf)"); + } + + MEMC_UDF_SET(flags, udf_flags); + } + if (op == MEMC_OP_TOUCH) { if (!memcached_behavior_get(m_obj->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "touch is only supported with binary protocol"); @@ -1509,6 +1575,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) int server_key_len = 0; zval *value; time_t expiration = 0; + uint32_t udf_flags = 0; char *payload; size_t payload_len; uint32_t flags = 0; @@ -1516,13 +1583,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|l", &cas_d, &server_key, - &server_key_len, &key, &key_len, &value, &expiration) == FAILURE) { + 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) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dsz|l", &cas_d, &key, &key_len, - &value, &expiration) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dsz|ll", &cas_d, &key, &key_len, + &value, &expiration, &udf_flags) == FAILURE) { return; } } @@ -1541,6 +1608,18 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) flags |= MEMC_VAL_COMPRESSED; } + /* + * php_memcached uses 8 bits internally to store type, compression and serialization info. + * We use 8 upper bits to store user defined flags. + */ + if (udf_flags > 0) { + if (udf_flags > 0xf) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to 8 bits (0xf)"); + } + + MEMC_UDF_SET(flags, udf_flags); + } + payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type TSRMLS_CC); if (payload == NULL) { i_obj->rescode = MEMC_RES_PAYLOAD_FAILURE; @@ -1561,7 +1640,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 ]) +/* {{{ Memcached::cas(double cas_token, string key, mixed value [, int expiration [, int udf_flags ] ]) Sets the value for the given key, failing if the cas_token doesn't match the one in memcache */ PHP_METHOD(Memcached, cas) { @@ -1569,7 +1648,7 @@ PHP_METHOD(Memcached, cas) } /* }}} */ -/* {{{ Memcached::casByKey(double cas_token, string server_key, string key, mixed value [, int expiration ]) +/* {{{ Memcached::casByKey(double cas_token, string server_key, string key, mixed value [, int expiration [, int udf_flags ] ]) 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) { @@ -3307,6 +3386,9 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, if (cas != 0) { add_assoc_double_ex(z_result, ZEND_STRS("cas"), (double)cas); } + if (flags & MEMC_UDF_MASK != 0) { + add_assoc_long_ex(z_result, ZEND_STRS("flags"), MEMC_UDF_GET(flags)); + } if (zend_call_function(fci, fcc TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not invoke result callback"); @@ -3339,6 +3421,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_get, 0, 0, 1) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, cache_cb) ZEND_ARG_INFO(1, cas_token) + ZEND_ARG_INFO(1, udf_flags) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getByKey, 0, 0, 2) @@ -3346,12 +3429,14 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_getByKey, 0, 0, 2) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, cache_cb) ZEND_ARG_INFO(1, 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(1, 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) @@ -3359,6 +3444,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_getMultiByKey, 0, 0, 2) ZEND_ARG_ARRAY_INFO(0, keys, 0) ZEND_ARG_INFO(1, 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) @@ -3384,6 +3470,7 @@ 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) @@ -3391,6 +3478,7 @@ 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) @@ -3407,18 +3495,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_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) @@ -3426,12 +3517,14 @@ 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) @@ -3439,6 +3532,7 @@ 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) @@ -3472,6 +3566,7 @@ 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) @@ -3480,6 +3575,7 @@ 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) From 7f52206bb1af459f1de7516ca3b4d3139edd9632 Mon Sep 17 00:00:00 2001 From: Nicolas Van Eenaeme Date: Thu, 7 Nov 2013 00:38:40 +0100 Subject: [PATCH 02/15] Was a bit too greedy with all the errors --- php_memcached.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 925b9b4b..3f6377d0 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -133,7 +133,7 @@ typedef unsigned long int uint32_t; User-defined flags ****************************************/ #define MEMC_UDF_MASK 0xf0 -#define MEMC_UDF_GET(flags) ((long)(((flags) & MEMC_UDF_MASK)>>8)) +#define MEMC_UDF_GET(flags) ((long)(flags & MEMC_UDF_MASK)>>8) #define MEMC_UDF_SET(flags, udf_flags) ((flags) |= ((udf_flags<<8) & MEMC_VAL_TYPE_MASK)) /**************************************** @@ -624,7 +624,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) zval_dtor(cas_token); ZVAL_DOUBLE(cas_token, (double)cas); - if (udf_flags) ( + if (udf_flags) { ZVAL_DOUBLE(udf_flags, MEMC_UDF_GET(flags)); } @@ -675,7 +675,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) } } - if (udf_flags) ( + if (udf_flags) { ZVAL_DOUBLE(udf_flags, MEMC_UDF_GET(flags)); } } @@ -1072,7 +1072,7 @@ PHP_METHOD(Memcached, fetch) /* XXX: also check against ULLONG_MAX or memc_behavior */ add_assoc_double_ex(return_value, ZEND_STRS("cas"), (double)cas); } - if (flags & MEMC_UDF_MASK != 0) { + if ((flags & MEMC_UDF_MASK) != 0) { add_assoc_long_ex(return_value, ZEND_STRS("flags"), MEMC_UDF_GET(flags)); } @@ -1131,7 +1131,7 @@ PHP_METHOD(Memcached, fetchAll) /* XXX: also check against ULLONG_MAX or memc_behavior */ add_assoc_double_ex(entry, ZEND_STRS("cas"), (double)cas); } - if (flags & MEMC_UDF_MASK != 0) { + if ((flags & MEMC_UDF_MASK) != 0) { add_assoc_long_ex(entry, ZEND_STRS("flags"), MEMC_UDF_GET(flags)); } add_next_index_zval(return_value, entry); @@ -3386,7 +3386,7 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, if (cas != 0) { add_assoc_double_ex(z_result, ZEND_STRS("cas"), (double)cas); } - if (flags & MEMC_UDF_MASK != 0) { + if ((flags & MEMC_UDF_MASK) != 0) { add_assoc_long_ex(z_result, ZEND_STRS("flags"), MEMC_UDF_GET(flags)); } From 81971e7abe4796754be17c719a1adc667d138aa8 Mon Sep 17 00:00:00 2001 From: Nicolas Van Eenaeme Date: Thu, 7 Nov 2013 00:41:37 +0100 Subject: [PATCH 03/15] updated memcached documentation --- memcached-api.php | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/memcached-api.php b/memcached-api.php index 69ff659e..5eee7020 100644 --- a/memcached-api.php +++ b/memcached-api.php @@ -185,13 +185,13 @@ class Memcached { public function __construct( $persistent_id = '', $on_new_object_cb = null ) {} - public function get( $key, $cache_cb = null, &$cas_token = null ) {} + public function get( $key, $cache_cb = null, &$cas_token = null, &$udf_flags = null ) {} - public function getByKey( $server_key, $key, $cache_cb = null, &$cas_token = null ) {} + public function getByKey( $server_key, $key, $cache_cb = null, &$cas_token = null, &$udf_flags = null ) {} - public function getMulti( array $keys, &$cas_tokens = null, $flags = 0 ) {} + public function getMulti( array $keys, &$cas_tokens = null, $flags = 0, &$udf_flags = null ) {} - public function getMultiByKey( $server_key, array $keys, &$cas_tokens = null, $flags = 0 ) {} + public function getMultiByKey( $server_key, array $keys, &$cas_tokens = null, $flags = 0, &$udf_flags = null ) {} public function getDelayed( array $keys, $with_cas = null, $value_cb = null ) {} @@ -201,25 +201,25 @@ public function fetch( ) {} public function fetchAll( ) {} - public function set( $key, $value, $expiration = 0 ) {} + public function set( $key, $value, $expiration = 0, $udf_flags = 0 ) {} public function touch( $key, $expiration = 0 ) {} public function touchbyKey( $key, $expiration = 0 ) {} - public function setByKey( $server_key, $key, $value, $expiration = 0 ) {} + public function setByKey( $server_key, $key, $value, $expiration = 0, $udf_flags = 0 ) {} - public function setMulti( array $items, $expiration = 0 ) {} + public function setMulti( array $items, $expiration = 0, $udf_flags = 0 ) {} - public function setMultiByKey( $server_key, array $items, $expiration = 0 ) {} + public function setMultiByKey( $server_key, array $items, $expiration = 0, $udf_flags = 0 ) {} - public function cas( $token, $key, $value, $expiration = 0 ) {} + public function cas( $token, $key, $value, $expiration = 0, $udf_flags = 0 ) {} - public function casByKey( $token, $server_key, $key, $value, $expiration = 0 ) {} + public function casByKey( $token, $server_key, $key, $value, $expiration = 0, $udf_flags = 0 ) {} - public function add( $key, $value, $expiration = 0 ) {} + public function add( $key, $value, $expiration = 0, $udf_flags = 0 ) {} - public function addByKey( $server_key, $key, $value, $expiration = 0 ) {} + public function addByKey( $server_key, $key, $value, $expiration = 0, $udf_flags = 0 ) {} public function append( $key, $value ) {} @@ -229,9 +229,9 @@ public function prepend( $key, $value ) {} public function prependByKey( $server_key, $key, $value ) {} - public function replace( $key, $value, $expiration = 0 ) {} + public function replace( $key, $value, $expiration = 0, $udf_flags = 0 ) {} - public function replaceByKey( $server_key, $key, $value, $expiration = 0 ) {} + public function replaceByKey( $server_key, $key, $value, $expiration = 0, $udf_flags = 0 ) {} public function delete( $key, $time = 0 ) {} From e4ae8fb560eb06dd069368c28612524a386c1ddd Mon Sep 17 00:00:00 2001 From: Nicolas Van Eenaeme Date: Thu, 7 Nov 2013 17:50:59 +0100 Subject: [PATCH 04/15] Final fixes and tests, cleanup --- php_memcached.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 3f6377d0..11f74ff4 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -132,9 +132,9 @@ typedef unsigned long int uint32_t; /**************************************** User-defined flags ****************************************/ -#define MEMC_UDF_MASK 0xf0 +#define MEMC_UDF_MASK 0xff00 #define MEMC_UDF_GET(flags) ((long)(flags & MEMC_UDF_MASK)>>8) -#define MEMC_UDF_SET(flags, udf_flags) ((flags) |= ((udf_flags<<8) & MEMC_VAL_TYPE_MASK)) +#define MEMC_UDF_SET(flags, udf_flags) ((flags) |= ((udf_flags<<8) & MEMC_UDF_MASK)) /**************************************** "get" operation flags @@ -558,7 +558,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) keys[0] = key; key_lens[0] = key_len; - if (cas_token) { + if (cas_token && Z_TYPE_P(cas_token) != IS_NULL) { uint64_t orig_cas_flag; /* @@ -625,7 +625,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) ZVAL_DOUBLE(cas_token, (double)cas); if (udf_flags) { - ZVAL_DOUBLE(udf_flags, MEMC_UDF_GET(flags)); + ZVAL_LONG(udf_flags, MEMC_UDF_GET(flags)); } memcached_result_free(&result); @@ -676,7 +676,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) } if (udf_flags) { - ZVAL_DOUBLE(udf_flags, MEMC_UDF_GET(flags)); + ZVAL_LONG(udf_flags, MEMC_UDF_GET(flags)); } } } @@ -1260,8 +1260,8 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { - if (udf_flags > 0xf) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to 8 bits (0xf)"); + if (udf_flags > (MEMC_UDF_MASK>>8)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", (MEMC_UDF_MASK>>8)); } } @@ -1469,8 +1469,8 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { - if (udf_flags > 0xf) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to 8 bits (0xf)"); + if (udf_flags > (MEMC_UDF_MASK>>8)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", (MEMC_UDF_MASK>>8)); } MEMC_UDF_SET(flags, udf_flags); @@ -1613,8 +1613,8 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { - if (udf_flags > 0xf) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to 8 bits (0xf)"); + if (udf_flags > (MEMC_UDF_MASK>>8)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", (MEMC_UDF_MASK>>8)); } MEMC_UDF_SET(flags, udf_flags); From a5e677d9cf20898f20a04dde7c6c527988ddf912 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 11 Nov 2013 02:57:48 +0800 Subject: [PATCH 05/15] Test flags --- php_memcached.c | 88 +++++++++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 39 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 41be52df..db3c91d1 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -120,9 +120,14 @@ typedef unsigned long int uint32_t; /**************************************** Payload value flags ****************************************/ -#define MEMC_VAL_TYPE_MASK 0xf -#define MEMC_VAL_GET_TYPE(flags) ((flags) & MEMC_VAL_TYPE_MASK) -#define MEMC_VAL_SET_TYPE(flags, type) ((flags) |= ((type) & MEMC_VAL_TYPE_MASK)) +#define MEMC_CREATE_MASK(start, n_bits) (((1 << n_bits) - 1) << start) + +#define MEMC_MASK_TYPE MEMC_CREATE_MASK(0, 4) +#define MEMC_MASK_INTERNAL MEMC_CREATE_MASK(4, 12) +#define MEMC_MASK_USER MEMC_CREATE_MASK(16, 16) + +#define MEMC_VAL_GET_TYPE(flags) ((flags) & MEMC_MASK_TYPE) +#define MEMC_VAL_SET_TYPE(flags, type) ((flags) |= ((type) & MEMC_MASK_TYPE)) #define MEMC_VAL_IS_STRING 0 #define MEMC_VAL_IS_LONG 1 @@ -132,16 +137,21 @@ typedef unsigned long int uint32_t; #define MEMC_VAL_IS_IGBINARY 5 #define MEMC_VAL_IS_JSON 6 -#define MEMC_VAL_COMPRESSED (1<<4) -#define MEMC_VAL_COMPRESSION_ZLIB (1<<5) -#define MEMC_VAL_COMPRESSION_FASTLZ (1<<6) +#define MEMC_VAL_COMPRESSED (1<<0) +#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); /**************************************** User-defined flags ****************************************/ -#define MEMC_UDF_MASK 0xff00 -#define MEMC_UDF_GET(flags) ((long)(flags & MEMC_UDF_MASK)>>8) -#define MEMC_UDF_SET(flags, udf_flags) ((flags) |= ((udf_flags<<8) & MEMC_UDF_MASK)) +#define MEMC_VAL_GET_USER_FLAGS(flags) ((flags & MEMC_MASK_USER) >> 16) +#define MEMC_VAL_SET_USER_FLAGS(flags, udf_flags) ((flags) |= ((udf_flags << 16) & MEMC_MASK_USER)) +#define MEMC_VAL_USER_FLAGS_MAX (MEMC_MASK_USER >> 16) /**************************************** "get" operation flags @@ -652,7 +662,7 @@ static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) if (udf_flags) { zval_dtor(udf_flags); - ZVAL_LONG(udf_flags, MEMC_UDF_GET(flags)); + ZVAL_LONG(udf_flags, MEMC_VAL_GET_USER_FLAGS(flags)); } memcached_result_free(&result); @@ -840,7 +850,7 @@ static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke add_assoc_double_ex(cas_tokens, res_key, res_key_len+1, (double)cas); } if (udf_flags) { - add_assoc_long_ex(udf_flags, res_key, res_key_len+1, MEMC_UDF_GET(flags)); + add_assoc_long_ex(udf_flags, res_key, res_key_len+1, MEMC_VAL_GET_USER_FLAGS(flags)); } } @@ -1052,8 +1062,8 @@ PHP_METHOD(Memcached, fetch) /* XXX: also check against ULLONG_MAX or memc_behavior */ add_assoc_double_ex(return_value, ZEND_STRS("cas"), (double)cas); } - if ((flags & MEMC_UDF_MASK) != 0) { - add_assoc_long_ex(return_value, ZEND_STRS("flags"), MEMC_UDF_GET(flags)); + if (MEMC_VAL_GET_USER_FLAGS(flags) != 0) { + add_assoc_long_ex(return_value, ZEND_STRS("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); } memcached_result_free(&result); @@ -1111,8 +1121,8 @@ PHP_METHOD(Memcached, fetchAll) /* XXX: also check against ULLONG_MAX or memc_behavior */ add_assoc_double_ex(entry, ZEND_STRS("cas"), (double)cas); } - if ((flags & MEMC_UDF_MASK) != 0) { - add_assoc_long_ex(entry, ZEND_STRS("flags"), MEMC_UDF_GET(flags)); + if (MEMC_VAL_GET_USER_FLAGS(flags) != 0) { + add_assoc_long_ex(entry, ZEND_STRS("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); } add_next_index_zval(return_value, entry); } @@ -1241,8 +1251,8 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { - if (udf_flags > (MEMC_UDF_MASK>>8)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", (MEMC_UDF_MASK>>8)); + if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); } } @@ -1265,11 +1275,11 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke flags = 0; if (m_obj->compression) { - flags |= MEMC_VAL_COMPRESSED; + MEMC_VAL_SET_FLAG(flags, MEMC_VAL_COMPRESSED); } if (udf_flags > 0) { - MEMC_UDF_SET(flags, udf_flags); + MEMC_VAL_SET_USER_FLAGS(flags, udf_flags); } payload = php_memc_zval_to_payload(*entry, &payload_len, &flags, m_obj->serializer, m_obj->compression_type TSRMLS_CC); @@ -1442,7 +1452,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot append/prepend with compression turned on"); return; } - flags |= MEMC_VAL_COMPRESSED; + MEMC_VAL_SET_FLAG(flags, MEMC_VAL_COMPRESSED); } /* @@ -1450,11 +1460,11 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { - if (udf_flags > (MEMC_UDF_MASK>>8)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", (MEMC_UDF_MASK>>8)); + if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); } - MEMC_UDF_SET(flags, udf_flags); + MEMC_VAL_SET_USER_FLAGS(flags, udf_flags); } if (op == MEMC_OP_TOUCH) { @@ -1586,7 +1596,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) DVAL_TO_LVAL(cas_d, cas); if (m_obj->compression) { - flags |= MEMC_VAL_COMPRESSED; + MEMC_VAL_SET_FLAG(flags, MEMC_VAL_COMPRESSED); } /* @@ -1594,11 +1604,11 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { - if (udf_flags > (MEMC_UDF_MASK>>8)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", (MEMC_UDF_MASK>>8)); + if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); } - MEMC_UDF_SET(flags, udf_flags); + MEMC_VAL_SET_USER_FLAGS(flags, udf_flags); } payload = php_memc_zval_to_payload(value, &payload_len, &flags, m_obj->serializer, m_obj->compression_type TSRMLS_CC); @@ -2978,11 +2988,11 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t } /* turn off compression for values below the threshold */ - if ((*flags & MEMC_VAL_COMPRESSED) && l < MEMC_G(compression_threshold)) { - *flags &= ~MEMC_VAL_COMPRESSED; + if (MEMC_VAL_HAS_FLAG(*flags, MEMC_VAL_COMPRESSED) && l < MEMC_G(compression_threshold)) { + MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); } - if (*flags & MEMC_VAL_COMPRESSED) { + if (MEMC_VAL_HAS_FLAG(*flags, MEMC_VAL_COMPRESSED)) { /* status */ zend_bool compress_status = 0; @@ -2995,10 +3005,10 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t if (compression_type == COMPRESSION_TYPE_FASTLZ) { compress_status = ((payload_comp_len = fastlz_compress(p, l, payload_comp)) > 0); - *flags |= MEMC_VAL_COMPRESSION_FASTLZ; + MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_FASTLZ); } else if (compression_type == COMPRESSION_TYPE_ZLIB) { compress_status = (compress((Bytef *)payload_comp, &payload_comp_len, (Bytef *)p, l) == Z_OK); - *flags |= MEMC_VAL_COMPRESSION_ZLIB; + MEMC_VAL_SET_FLAG(*flags, MEMC_VAL_COMPRESSION_ZLIB); } if (!compress_status) { @@ -3016,7 +3026,7 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t payload[*payload_len] = 0; } else { /* Store plain value */ - *flags &= ~MEMC_VAL_COMPRESSED; + MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED) *payload_len = l; memcpy(payload, p, l); payload[l] = 0; @@ -3041,7 +3051,7 @@ char *s_handle_decompressed (const char *payload, size_t *payload_len, uint32_t zend_bool decompress_status = 0; /* Stored with newer memcached extension? */ - if (flags & MEMC_VAL_COMPRESSION_FASTLZ || flags & MEMC_VAL_COMPRESSION_ZLIB) { + 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); @@ -3049,9 +3059,9 @@ char *s_handle_decompressed (const char *payload, size_t *payload_len, uint32_t payload += sizeof(uint32_t); length = len; - if (flags & MEMC_VAL_COMPRESSION_FASTLZ) { + if (MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_FASTLZ)) { decompress_status = ((length = fastlz_decompress(payload, *payload_len, buffer, len)) > 0); - } else if (flags & MEMC_VAL_COMPRESSION_ZLIB) { + } else if (MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_ZLIB)) { decompress_status = (uncompress((Bytef *)buffer, &length, (Bytef *)payload, *payload_len) == Z_OK); } } @@ -3106,7 +3116,7 @@ static int php_memc_zval_from_payload(zval *value, const char *payload_in, size_ return 0; } - if (flags & MEMC_VAL_COMPRESSED) { + if (MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSED)) { char *datas = s_handle_decompressed (payload_in, &payload_len, flags TSRMLS_CC); if (!datas) { ZVAL_FALSE(value); @@ -3426,8 +3436,8 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci, if (cas != 0) { add_assoc_double_ex(z_result, ZEND_STRS("cas"), (double)cas); } - if ((flags & MEMC_UDF_MASK) != 0) { - add_assoc_long_ex(z_result, ZEND_STRS("flags"), MEMC_UDF_GET(flags)); + if (MEMC_VAL_GET_USER_FLAGS(flags) != 0) { + add_assoc_long_ex(z_result, ZEND_STRS("flags"), MEMC_VAL_GET_USER_FLAGS(flags)); } if (zend_call_function(fci, fcc TSRMLS_CC) == FAILURE) { From ddf3f0ca34d6cac1688ac8fe7d1bb1194251eae5 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 11 Nov 2013 13:10:59 +0800 Subject: [PATCH 06/15] Test memcached version when using flags --- php_memcached.c | 58 +++++++++++++++++++++++++++++++++++++++++++ php_memcached.h | 4 ++- tests/user-flags.phpt | 56 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 tests/user-flags.phpt diff --git a/php_memcached.c b/php_memcached.c index db3c91d1..26280eec 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -116,6 +116,7 @@ typedef unsigned long int uint32_t; Custom result codes ****************************************/ #define MEMC_RES_PAYLOAD_FAILURE -1001 +#define MEMC_RES_VERSION_FAILURE -1002 /**************************************** Payload value flags @@ -1212,6 +1213,45 @@ PHP_METHOD(Memcached, setMultiByKey) } \ } \ + +static +memcached_return s_user_flag_cb(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) +{ + uint32_t version; + uint8_t major, minor, micro; + + major = memcached_server_major_version (instance); + minor = memcached_server_minor_version (instance); + micro = memcached_server_micro_version (instance); + + if ((major < 1) || (major == 1 && minor < 2) || (major == 1 && minor == 2 && micro < 1)) { + MEMC_G (user_flag_check_result) = 0; + } + return MEMCACHED_SUCCESS; +} + +static +zend_bool s_user_flags_possible (const memcached_st *memc TSRMLS_DC) +{ + memcached_server_function callbacks [1]; + + if (MEMC_G (user_flag_check_done)) + return MEMC_G (user_flag_check_result); + + if (memcached_version(memc) != MEMCACHED_SUCCESS) { + MEMC_G (user_flag_check_done) = 1; + MEMC_G (user_flag_check_result) = 0; + return 0; + } + + MEMC_G (user_flag_check_done) = 1; + MEMC_G (user_flag_check_result) = 1; + + callbacks[0] =& s_user_flag_cb; + memcached_server_cursor(memc, callbacks, NULL, 1); +} + + /* {{{ -- php_memc_setMulti_impl */ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { @@ -1251,6 +1291,11 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { + if (!s_user_flags_possible (m_obj->memc TSRMLS_CC)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "memcached server 1.2.1+ needed to store user flags"); + i_obj->rescode = MEMC_RES_VERSION_FAILURE; + RETURN_FALSE; + } if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); } @@ -1460,6 +1505,11 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { + if (!s_user_flags_possible (m_obj->memc TSRMLS_CC)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "memcached server 1.2.1+ needed to store user flags"); + i_obj->rescode = MEMC_RES_VERSION_FAILURE; + RETURN_FALSE; + } if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); } @@ -1604,6 +1654,11 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { + if (!s_user_flags_possible (m_obj->memc TSRMLS_CC)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "memcached server 1.2.1+ needed to store user flags"); + i_obj->rescode = MEMC_RES_VERSION_FAILURE; + RETURN_FALSE; + } if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); } @@ -3265,6 +3320,8 @@ static void php_memc_init_globals(zend_php_memcached_globals *php_memcached_glob #if HAVE_MEMCACHED_SASL MEMC_G(use_sasl) = 0; #endif + MEMC_G(user_flag_check_done) = 0; + MEMC_G(user_flag_check_result) = 0; } static void php_memc_destroy_globals(zend_php_memcached_globals *php_memcached_globals_p TSRMLS_DC) @@ -4018,6 +4075,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) */ REGISTER_MEMC_CLASS_CONST_LONG(RES_PAYLOAD_FAILURE, MEMC_RES_PAYLOAD_FAILURE); + REGISTER_MEMC_CLASS_CONST_LONG(RES_VERSION_FAILURE, MEMC_RES_VERSION_FAILURE); /* * Serializer types. diff --git a/php_memcached.h b/php_memcached.h index 9eeb8a0e..99715402 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -91,8 +91,10 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) double compression_factor; #if HAVE_MEMCACHED_SASL - bool use_sasl; + zend_bool use_sasl; #endif + zend_bool user_flag_check_done; + zend_bool user_flag_check_result; ZEND_END_MODULE_GLOBALS(php_memcached) PHP_MEMCACHED_API zend_class_entry *php_memc_get_ce(void); diff --git a/tests/user-flags.phpt b/tests/user-flags.phpt new file mode 100644 index 00000000..4427ec14 --- /dev/null +++ b/tests/user-flags.phpt @@ -0,0 +1,56 @@ +--TEST-- +Memcached user flags +--SKIPIF-- + +--FILE-- +setOption(Memcached::OPT_BINARY_PROTOCOL, true); +$m->addServer('127.0.0.1', 11211, 1); + +$key = uniqid ('udf_test_'); + +echo "stored with flags" . PHP_EOL; + +$m->set ($key, '1', 10, FLAG_1 | FLAG_4); +$udf_flags = 0; +$value = $m->get ($key, null, $x, $udf_flags); + +var_dump (check_flag ($udf_flags, FLAG_1)); +var_dump (check_flag ($udf_flags, FLAG_2)); +var_dump (check_flag ($udf_flags, FLAG_4)); + + +echo "stored without flags" . PHP_EOL; +$m->set ($key, '1'); +$value = $m->get ($key, null, $x, $udf_flags); + +var_dump (check_flag ($udf_flags, FLAG_1)); +var_dump (check_flag ($udf_flags, FLAG_2)); +var_dump (check_flag ($udf_flags, FLAG_4)); + + +echo "DONE TEST\n"; +?> +--EXPECT-- +stored with flags +bool(true) +bool(false) +bool(true) +stored without flags +bool(false) +bool(false) +bool(false) +DONE TEST \ No newline at end of file From 1514dd413f2f855d1c2da536cda41430d56cac83 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 11 Nov 2013 13:12:44 +0800 Subject: [PATCH 07/15] Dont break old libmemcached --- php_memcached.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/php_memcached.c b/php_memcached.c index 26280eec..77b4bf11 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1220,9 +1220,15 @@ memcached_return s_user_flag_cb(const memcached_st *ptr, php_memcached_instance_ uint32_t version; uint8_t major, minor, micro; +#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000009 major = memcached_server_major_version (instance); minor = memcached_server_minor_version (instance); micro = memcached_server_micro_version (instance); +#else + major = instance->major_version; + minor = instance->minor_version; + micro = instance->micro_version; +#endif if ((major < 1) || (major == 1 && minor < 2) || (major == 1 && minor == 2 && micro < 1)) { MEMC_G (user_flag_check_result) = 0; From 7140a4b33bb778032c6c32406c437eb4fc4f7df4 Mon Sep 17 00:00:00 2001 From: Mikko Date: Mon, 11 Nov 2013 13:17:44 +0800 Subject: [PATCH 08/15] This should return a value --- php_memcached.c | 1 + 1 file changed, 1 insertion(+) diff --git a/php_memcached.c b/php_memcached.c index 77b4bf11..51743d5a 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1255,6 +1255,7 @@ zend_bool s_user_flags_possible (const memcached_st *memc TSRMLS_DC) callbacks[0] =& s_user_flag_cb; memcached_server_cursor(memc, callbacks, NULL, 1); + return MEMC_G (user_flag_check_result); } From 1010295bc69467e13b8db343271fac532cffd768 Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 13 Nov 2013 01:10:02 +0800 Subject: [PATCH 09/15] Remove version check //cc #92 --- php_memcached.c | 63 ------------------------------------------------- php_memcached.h | 2 -- 2 files changed, 65 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 51743d5a..6aa65368 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1211,54 +1211,8 @@ PHP_METHOD(Memcached, setMultiByKey) } \ break; \ } \ - } \ - - -static -memcached_return s_user_flag_cb(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context) -{ - uint32_t version; - uint8_t major, minor, micro; - -#if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000009 - major = memcached_server_major_version (instance); - minor = memcached_server_minor_version (instance); - micro = memcached_server_micro_version (instance); -#else - major = instance->major_version; - minor = instance->minor_version; - micro = instance->micro_version; -#endif - - if ((major < 1) || (major == 1 && minor < 2) || (major == 1 && minor == 2 && micro < 1)) { - MEMC_G (user_flag_check_result) = 0; - } - return MEMCACHED_SUCCESS; -} - -static -zend_bool s_user_flags_possible (const memcached_st *memc TSRMLS_DC) -{ - memcached_server_function callbacks [1]; - - if (MEMC_G (user_flag_check_done)) - return MEMC_G (user_flag_check_result); - - if (memcached_version(memc) != MEMCACHED_SUCCESS) { - MEMC_G (user_flag_check_done) = 1; - MEMC_G (user_flag_check_result) = 0; - return 0; } - MEMC_G (user_flag_check_done) = 1; - MEMC_G (user_flag_check_result) = 1; - - callbacks[0] =& s_user_flag_cb; - memcached_server_cursor(memc, callbacks, NULL, 1); - return MEMC_G (user_flag_check_result); -} - - /* {{{ -- php_memc_setMulti_impl */ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) { @@ -1298,11 +1252,6 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { - if (!s_user_flags_possible (m_obj->memc TSRMLS_CC)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "memcached server 1.2.1+ needed to store user flags"); - i_obj->rescode = MEMC_RES_VERSION_FAILURE; - RETURN_FALSE; - } if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); } @@ -1512,11 +1461,6 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { - if (!s_user_flags_possible (m_obj->memc TSRMLS_CC)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "memcached server 1.2.1+ needed to store user flags"); - i_obj->rescode = MEMC_RES_VERSION_FAILURE; - RETURN_FALSE; - } if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); } @@ -1661,11 +1605,6 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { - if (!s_user_flags_possible (m_obj->memc TSRMLS_CC)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "memcached server 1.2.1+ needed to store user flags"); - i_obj->rescode = MEMC_RES_VERSION_FAILURE; - RETURN_FALSE; - } if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); } @@ -3327,8 +3266,6 @@ static void php_memc_init_globals(zend_php_memcached_globals *php_memcached_glob #if HAVE_MEMCACHED_SASL MEMC_G(use_sasl) = 0; #endif - MEMC_G(user_flag_check_done) = 0; - MEMC_G(user_flag_check_result) = 0; } static void php_memc_destroy_globals(zend_php_memcached_globals *php_memcached_globals_p TSRMLS_DC) diff --git a/php_memcached.h b/php_memcached.h index 99715402..49d5f041 100644 --- a/php_memcached.h +++ b/php_memcached.h @@ -93,8 +93,6 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached) #if HAVE_MEMCACHED_SASL zend_bool use_sasl; #endif - zend_bool user_flag_check_done; - zend_bool user_flag_check_result; ZEND_END_MODULE_GLOBALS(php_memcached) PHP_MEMCACHED_API zend_class_entry *php_memc_get_ce(void); From 79a299591df30853c6238286d816a6e1dad8e01f Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 13 Nov 2013 01:57:25 +0800 Subject: [PATCH 10/15] Merging from poison/feature-udf. Changed flags for parse parameters to long. //cc #92 --- php_memcached.c | 45 ++++++++++++++++++++++++-------------------- tests/cas.phpt | 19 +++++++++++++++++++ tests/cas_multi.phpt | 27 ++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 20 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index dee08205..e3d5c44e 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -116,7 +116,6 @@ typedef unsigned long int uint32_t; Custom result codes ****************************************/ #define MEMC_RES_PAYLOAD_FAILURE -1001 -#define MEMC_RES_VERSION_FAILURE -1002 /**************************************** Payload value flags @@ -591,13 +590,13 @@ 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_TYPE_P(cas_token) != IS_NULL && orig_cas_flag == 0) { + if (cas_token && PZVAL_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); - if (cas_token && Z_TYPE_P(cas_token) != IS_NULL && orig_cas_flag == 0) { + if (cas_token && PZVAL_IS_REF(cas_token) && orig_cas_flag == 0) { memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); } @@ -766,7 +765,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) { + if (cas_tokens && PZVAL_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); @@ -780,7 +779,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 && orig_cas_flag == 0) { + if (cas_tokens && PZVAL_IS_REF(cas_tokens) && orig_cas_flag == 0) { memcached_behavior_set(m_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag); } @@ -792,8 +791,17 @@ 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) { - zval_dtor(cas_tokens); - array_init(cas_tokens); + if (PZVAL_IS_REF(cas_tokens)) { + /* cas_tokens was passed by reference, we'll create an array for it. */ + 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; + } } /* @@ -1220,7 +1228,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke char *server_key = NULL; int server_key_len = 0; time_t expiration = 0; - uint32_t udf_flags = 0; + long udf_flags = 0; zval **entry; char *str_key; uint str_key_len; @@ -1280,7 +1288,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke } if (udf_flags > 0) { - MEMC_VAL_SET_USER_FLAGS(flags, udf_flags); + 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); @@ -1385,7 +1393,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool zval s_zvalue; zval *value; long expiration = 0; - uint32_t udf_flags = 0; + long udf_flags = 0; char *payload; size_t payload_len; uint32_t flags = 0; @@ -1464,8 +1472,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); } - - MEMC_VAL_SET_USER_FLAGS(flags, udf_flags); + MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) udf_flags)); } if (op == MEMC_OP_TOUCH) { @@ -1567,7 +1574,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) int server_key_len = 0; zval *value; time_t expiration = 0; - uint32_t udf_flags = 0; + long udf_flags = 0; char *payload; size_t payload_len; uint32_t flags = 0; @@ -1608,8 +1615,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); } - - MEMC_VAL_SET_USER_FLAGS(flags, udf_flags); + 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); @@ -3482,7 +3488,7 @@ 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(1, cas_token) + ZEND_ARG_INFO(2, cas_token) ZEND_ARG_INFO(1, udf_flags) ZEND_END_ARG_INFO() @@ -3490,13 +3496,13 @@ 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(1, cas_token) + 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(1, cas_tokens) + ZEND_ARG_INFO(2, cas_tokens) ZEND_ARG_INFO(0, flags) ZEND_ARG_INFO(1, udf_flags) ZEND_END_ARG_INFO() @@ -3504,7 +3510,7 @@ 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(1, cas_tokens) + ZEND_ARG_INFO(2, cas_tokens) ZEND_ARG_INFO(0, flags) ZEND_ARG_INFO(1, udf_flags) ZEND_END_ARG_INFO() @@ -4030,7 +4036,6 @@ static void php_memc_register_constants(INIT_FUNC_ARGS) */ REGISTER_MEMC_CLASS_CONST_LONG(RES_PAYLOAD_FAILURE, MEMC_RES_PAYLOAD_FAILURE); - REGISTER_MEMC_CLASS_CONST_LONG(RES_VERSION_FAILURE, MEMC_RES_VERSION_FAILURE); /* * Serializer types. diff --git a/tests/cas.phpt b/tests/cas.phpt index fc14842b..09b436e0 100644 --- a/tests/cas.phpt +++ b/tests/cas.phpt @@ -30,6 +30,25 @@ 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; +} + echo "OK\n"; ?> --EXPECT-- diff --git a/tests/cas_multi.phpt b/tests/cas_multi.phpt index d180d779..e4c9e0f3 100644 --- a/tests/cas_multi.phpt +++ b/tests/cas_multi.phpt @@ -45,6 +45,33 @@ foreach ($data as $key => $v) { } } +if (array_keys($actual) !== array_keys($data)) { + echo "missing value(s)\n"; + echo "data :"; + var_dump($data); + echo "actual data: "; + var_dump($actual); + 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"; ?> From 5bde0d1c5eb720b7d6178b7dae15b94470940cc3 Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 13 Nov 2013 02:10:18 +0800 Subject: [PATCH 11/15] Missing casts --- php_memcached.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index e3d5c44e..7285734b 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -1260,8 +1260,8 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { - if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); + 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); } } @@ -1469,8 +1469,8 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { - if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); + 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); } MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) udf_flags)); } @@ -1612,8 +1612,8 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) * We use 8 upper bits to store user defined flags. */ if (udf_flags > 0) { - if (udf_flags > MEMC_VAL_USER_FLAGS_MAX) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "udf_flags will be limited to %d", MEMC_VAL_USER_FLAGS_MAX); + 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); } MEMC_VAL_SET_USER_FLAGS(flags, ((uint32_t) udf_flags)); } From ccb7e3bbc8f4d95bb7e43ad665fba956a2bceefc Mon Sep 17 00:00:00 2001 From: Mikko Date: Wed, 13 Nov 2013 02:23:46 +0800 Subject: [PATCH 12/15] More testing of user flags --- php_memcached.c | 14 +++++++------- tests/user-flags.phpt | 25 ++++++++++++++----------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 7285734b..e3610049 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -151,7 +151,7 @@ typedef unsigned long int uint32_t; ****************************************/ #define MEMC_VAL_GET_USER_FLAGS(flags) ((flags & MEMC_MASK_USER) >> 16) #define MEMC_VAL_SET_USER_FLAGS(flags, udf_flags) ((flags) |= ((udf_flags << 16) & MEMC_MASK_USER)) -#define MEMC_VAL_USER_FLAGS_MAX (MEMC_MASK_USER >> 16) +#define MEMC_VAL_USER_FLAGS_MAX ((1 << 16) - 1) /**************************************** "get" operation flags @@ -1256,8 +1256,8 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke i_obj->rescode = MEMCACHED_SUCCESS; /* - * php_memcached uses 8 bits internally to store type, compression and serialization info. - * We use 8 upper bits to store user defined flags. + * 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) { @@ -1465,8 +1465,8 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool } /* - * php_memcached uses 8 bits internally to store type, compression and serialization info. - * We use 8 upper bits to store user defined flags. + * 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) { @@ -1608,8 +1608,8 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) } /* - * php_memcached uses 8 bits internally to store type, compression and serialization info. - * We use 8 upper bits to store user defined flags. + * 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) { diff --git a/tests/user-flags.phpt b/tests/user-flags.phpt index 4427ec14..af96e462 100644 --- a/tests/user-flags.phpt +++ b/tests/user-flags.phpt @@ -13,7 +13,9 @@ function check_flag ($flags, $flag) define ('FLAG_1', 1); define ('FLAG_2', 2); define ('FLAG_4', 4); - +define ('FLAG_32', 32); +define ('FLAG_64', 64); +define ('FLAG_TOO_LARGE', pow(2, 16)); $x = 0; $m = new Memcached(); @@ -24,33 +26,34 @@ $key = uniqid ('udf_test_'); echo "stored with flags" . PHP_EOL; -$m->set ($key, '1', 10, FLAG_1 | FLAG_4); +$m->set ($key, '1', 10, FLAG_1 | FLAG_4 | FLAG_64); $udf_flags = 0; $value = $m->get ($key, null, $x, $udf_flags); var_dump (check_flag ($udf_flags, FLAG_1)); var_dump (check_flag ($udf_flags, FLAG_2)); var_dump (check_flag ($udf_flags, FLAG_4)); - +var_dump (check_flag ($udf_flags, FLAG_32)); +var_dump (check_flag ($udf_flags, FLAG_64)); echo "stored without flags" . PHP_EOL; $m->set ($key, '1'); $value = $m->get ($key, null, $x, $udf_flags); -var_dump (check_flag ($udf_flags, FLAG_1)); -var_dump (check_flag ($udf_flags, FLAG_2)); -var_dump (check_flag ($udf_flags, FLAG_4)); - +var_dump ($udf_flags == 0); +$m->set ($key, '1', 10, FLAG_TOO_LARGE); echo "DONE TEST\n"; ?> ---EXPECT-- +--EXPECTF-- stored with flags bool(true) bool(false) bool(true) -stored without flags -bool(false) -bool(false) bool(false) +bool(true) +stored without flags +bool(true) + +Warning: Memcached::set(): udf_flags will be limited to 65535 in %s on line %d DONE TEST \ No newline at end of file From a4535461cf2730add577bd3f427a708bc636b353 Mon Sep 17 00:00:00 2001 From: Mikko Date: Thu, 14 Nov 2013 01:47:18 +0800 Subject: [PATCH 13/15] Test user flags with compression --- tests/user-flags.phpt | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/tests/user-flags.phpt b/tests/user-flags.phpt index af96e462..4891bfd3 100644 --- a/tests/user-flags.phpt +++ b/tests/user-flags.phpt @@ -5,9 +5,15 @@ Memcached user flags --FILE-- set ($key, '1', 10, FLAG_1 | FLAG_4 | FLAG_64); $udf_flags = 0; $value = $m->get ($key, null, $x, $udf_flags); -var_dump (check_flag ($udf_flags, FLAG_1)); -var_dump (check_flag ($udf_flags, FLAG_2)); -var_dump (check_flag ($udf_flags, FLAG_4)); -var_dump (check_flag ($udf_flags, FLAG_32)); -var_dump (check_flag ($udf_flags, FLAG_64)); +check_flags ($udf_flags, array (FLAG_1, FLAG_4, FLAG_64)); echo "stored without flags" . PHP_EOL; $m->set ($key, '1'); @@ -43,17 +45,24 @@ $value = $m->get ($key, null, $x, $udf_flags); var_dump ($udf_flags == 0); $m->set ($key, '1', 10, FLAG_TOO_LARGE); +$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); + +$udf_flags = 0; +$value_back = $m->get($key, null, null, $udf_flags); + +check_flags ($udf_flags, array (FLAG_1, FLAG_4, FLAG_64)); + echo "DONE TEST\n"; ?> --EXPECTF-- stored with flags -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) +Flags OK stored without flags bool(true) Warning: Memcached::set(): udf_flags will be limited to 65535 in %s on line %d +Flags OK DONE TEST \ No newline at end of file From d69bf88461fefc25a3b00730a50b64e3abd3ce5e Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 15 Nov 2013 22:54:31 +0800 Subject: [PATCH 14/15] Fixes comments by @poison --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index e3610049..de1d21d8 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -144,7 +144,7 @@ typedef unsigned long int uint32_t; #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_DEL_FLAG(internal_flags, internal_flag) internal_flags &= ~((internal_flag << 4) & MEMC_MASK_INTERNAL) /**************************************** User-defined flags From c88c4d6bbca32306a7efc0b3c1d20038c3367b47 Mon Sep 17 00:00:00 2001 From: Mikko Date: Fri, 15 Nov 2013 23:32:38 +0800 Subject: [PATCH 15/15] Fixes error with mixing semicolon --- php_memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_memcached.c b/php_memcached.c index de1d21d8..5ad6e2b2 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -3033,7 +3033,7 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t payload[*payload_len] = 0; } else { /* Store plain value */ - MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED) + MEMC_VAL_DEL_FLAG(*flags, MEMC_VAL_COMPRESSED); *payload_len = l; memcpy(payload, p, l); payload[l] = 0;