From ba1adee56287b08ced1a6922b3392e2d2dbbd36d Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Sun, 12 Feb 2017 15:29:52 -0800 Subject: [PATCH 1/3] Consolidate get(...GET_EXTENDED) and cas into the store implementation --- php_memcached.c | 166 ++++++++++++++------------------------- tests/cachecallback.phpt | 84 +++++++++++++++++++- 2 files changed, 143 insertions(+), 107 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 19673323..26cab2b8 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -135,7 +135,8 @@ typedef enum { MEMC_OP_ADD, MEMC_OP_REPLACE, MEMC_OP_APPEND, - MEMC_OP_PREPEND + MEMC_OP_PREPEND, + MEMC_OP_CAS } php_memc_write_op; typedef struct { @@ -400,7 +401,7 @@ static memcached_return s_server_cursor_version_cb(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context); 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); + 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, uint64_t cas_token); static void php_memc_destroy(memcached_st *memc, php_memc_user_data_t *memc_user_data); @@ -750,44 +751,32 @@ zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcal php_memc_object_t *intern = Z_MEMC_OBJ_P(zobject); /* Prepare params */ - ZVAL_COPY(¶ms[0], zobject); + ZVAL_COPY(¶ms[0], zobject); /* memc */ ZVAL_STR_COPY(¶ms[1], key); /* key */ ZVAL_NEW_REF(¶ms[2], value); /* value */ + ZVAL_NEW_EMPTY_REF(¶ms[3]); /* expiration */ + ZVAL_NULL(Z_REFVAL(params[3])); - 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->param_count = 4; fci->retval = &retval; fci->params = params; - if (zend_call_function(fci, fcc) == SUCCESS) { - if (zend_is_true(&retval)) { - 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); - } + if (zend_call_function(fci, fcc) == SUCCESS && zend_is_true(&retval)) { + time_t expiration; + zval *val = Z_REFVAL(params[2]); + zval *rv = NULL; + zval *zv_cas = NULL; + uint64_t cas; + + if (Z_TYPE_P(val) == IS_ARRAY) { + rv = zend_hash_str_find(Z_ARRVAL_P(val), "value", sizeof("value") - 1); + zv_cas = zend_hash_str_find(Z_ARRVAL_P(val), "cas", sizeof("cas") - 1); } + + expiration = zval_get_long(Z_REFVAL(params[3])); + cas = zv_cas ? s_zval_to_uint64(zv_cas) : 0; + status = s_memc_write_zval (intern, MEMC_OP_SET, NULL, key, rv ? rv : val, expiration, cas); + ZVAL_COPY(value, val); } else { s_memc_set_status(intern, MEMCACHED_NOTFOUND, 0); @@ -1054,7 +1043,7 @@ zend_bool s_should_retry_write (php_memc_object_t *intern, memcached_return stat } 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) +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, uint64_t cas) { uint32_t flags = 0; zend_string *payload = NULL; @@ -1099,6 +1088,10 @@ zend_bool s_memc_write_zval (php_memc_object_t *intern, php_memc_write_op op, ze case MEMC_OP_PREPEND: status = memc_write_using_fn_by_key(memcached_prepend_by_key); break; + + case MEMC_OP_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); + break; } if (status == MEMCACHED_END) { @@ -1131,6 +1124,10 @@ zend_bool s_memc_write_zval (php_memc_object_t *intern, php_memc_write_op op, ze case MEMC_OP_PREPEND: status = memc_write_using_fn(memcached_prepend); break; + + case MEMC_OP_CAS: + status = memcached_cas(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(payload), ZSTR_LEN(payload), expiration, flags, cas); + break; } if (status == MEMCACHED_END) { status = MEMCACHED_SUCCESS; @@ -1820,7 +1817,7 @@ 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)) { + if (!s_memc_write_zval (intern, MEMC_OP_SET, server_key, str_key, value, expiration, 0)) { php_error_docref(NULL, E_WARNING, "failed to set key %s", ZSTR_VAL(str_key)); } @@ -1898,6 +1895,22 @@ PHP_METHOD(Memcached, replaceByKey) } /* }}} */ +/* {{{ 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) +{ + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_CAS, 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) +{ + php_memc_store_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, MEMC_OP_CAS, 1); +} +/* }}} */ + /* {{{ -- php_memc_store_impl */ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool by_key) { @@ -1906,7 +1919,9 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool zend_string *s_value; zval s_zvalue; zval *value = NULL; + zval *zv_cas = NULL; zend_long expiration = 0; + uint64_t cas = 0; MEMC_METHOD_INIT_VARS; if (by_key) { @@ -1920,6 +1935,11 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|l", &server_key, &key, &expiration) == FAILURE) { return; } + } else if (op == MEMC_OP_CAS) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zSSz|l", &zv_cas, &server_key, &key, &value, &expiration) == FAILURE) { + return; + } + cas = s_zval_to_uint64(zv_cas); } else { if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSz|l", &server_key, &key, &value, &expiration) == FAILURE) { return; @@ -1936,6 +1956,11 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &key, &expiration) == FAILURE) { return; } + } else if (op == MEMC_OP_CAS) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zSz|l", &zv_cas, &key, &value, &expiration) == FAILURE) { + return; + } + cas = s_zval_to_uint64(zv_cas); } else { if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|l", &key, &value, &expiration) == FAILURE) { return; @@ -1959,82 +1984,13 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool } } - if (!s_memc_write_zval (intern, op, server_key, key, value, expiration)) { + if (!s_memc_write_zval (intern, op, server_key, key, value, expiration, cas)) { RETURN_FALSE; } RETURN_TRUE; } /* }}} */ -/* {{{ -- php_memc_cas_impl */ -static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key) -{ - 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; - - 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; - } - } - - MEMC_METHOD_FETCH_OBJECT; - s_memc_set_status(intern, MEMCACHED_SUCCESS, 0); - MEMC_CHECK_KEY(intern, key); - - cas = s_zval_to_uint64(zv_cas); - - payload = s_zval_to_payload(intern, value, &flags); - if (payload == NULL) { - intern->rescode = MEMC_RES_PAYLOAD_FAILURE; - 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 { - status = memcached_cas(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(payload), ZSTR_LEN(payload), expiration, flags, cas); - } - - zend_string_release(payload); - if (s_memc_status_handle_result_code(intern, status) == FAILURE) { - 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) -{ - php_memc_cas_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 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) -{ - php_memc_cas_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); -} -/* }}} */ - /* {{{ Memcached::delete(string key [, int time ]) Deletes the given key */ PHP_METHOD(Memcached, delete) diff --git a/tests/cachecallback.phpt b/tests/cachecallback.phpt index 41edfc5c..55d4f647 100644 --- a/tests/cachecallback.phpt +++ b/tests/cachecallback.phpt @@ -27,6 +27,11 @@ $m->get ($first_key, function (Memcached $memc, $key, &$value, &$expiration) { var_dump ($m->get ($first_key)); +// Get the first key again, expecting that the callback is _not_ called a second timd +$m->get ($first_key, function (Memcached $memc, $key, &$value, &$expiration) { + throw new Exception ('This callback should not be called'); + }); + var_dump ( $m->get ($second_key, function (Memcached $memc, $key, &$value, &$expiration) { $value = "hello"; @@ -50,14 +55,89 @@ try { var_dump ($m->get ($third_key)); +echo "OK" . PHP_EOL; + +// +// Run through the scenarios again in GET_EXTENDED mode +// +$m->delete($first_key); +$m->delete($second_key); +$m->delete($third_key); + +var_dump ( +$m->get ($first_key, function (Memcached $memc, $key, &$value) { + $value = [ + "value" => "first_ext", + "cas" => 12345, + "expiration" => 10 ]; + return true; + }, Memcached::GET_EXTENDED) +); + +var_dump ($m->get ($first_key, null, Memcached::GET_EXTENDED)); + +// Get the first key again, expecting that the callback is _not_ called a second timd +$m->get ($first_key, function (Memcached $memc, $key, &$value) { + throw new Exception ('This callback should not be called'); + }, Memcached::GET_EXTENDED); + +var_dump ( +$m->get ($second_key, function (Memcached $memc, $key, &$value) { + $value = [ + "value" => "second_ext", + "cas" => 12345, + "expiration" => 10 ]; + return false; + }, Memcached::GET_EXTENDED) +); + +var_dump ($m->get ($second_key)); +var_dump ($m->get ($second_key, null, Memcached::GET_EXTENDED)); + +try { + $m->get ($third_key, function (Memcached $memc, $key, &$value) { + $value = [ + "value" => "third_ext", + "cas" => "12345", + "expiration" => "10" ]; + throw new Exception ('this is a test'); + return true; + }, Memcached::GET_EXTENDED); +} catch (Exception $e) { + echo 'Got exception' . PHP_EOL; +} + +var_dump ($m->get ($third_key)); echo "OK" . PHP_EOL; ---EXPECT-- +--EXPECTF-- string(5) "hello" string(5) "hello" bool(false) bool(false) Got exception bool(false) -OK \ No newline at end of file +OK +array(3) { + ["value"]=> + string(9) "first_ext" + ["cas"]=> + int(%d) + ["flags"]=> + int(0) +} +array(3) { + ["value"]=> + string(9) "first_ext" + ["cas"]=> + int(%d) + ["flags"]=> + int(0) +} +bool(false) +bool(false) +bool(false) +Got exception +bool(false) +OK From 626c1ace6aac3636cee223b0b2b23c65d8971217 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 14 Feb 2017 08:19:42 -0800 Subject: [PATCH 2/3] Work in progress --- php_memcached.c | 111 +++++++++++++++++++++++---------------- tests/cachecallback.phpt | 21 ++++---- 2 files changed, 76 insertions(+), 56 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 26cab2b8..62f18b74 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -401,7 +401,7 @@ static memcached_return s_server_cursor_version_cb(const memcached_st *ptr, php_memcached_instance_st instance, void *in_context); 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, uint64_t cas_token); + 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, uint32_t *flags, time_t expiration, uint64_t cas_token); static void php_memc_destroy(memcached_st *memc, php_memc_user_data_t *memc_user_data); @@ -742,6 +742,9 @@ zend_bool s_invoke_new_instance_cb(zval *object, zend_fcall_info *fci, zend_fcal return ret; } +static +void s_create_result_array(zend_string *key, zval *value, zval *cas, uint32_t flags, zval *return_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) { @@ -762,21 +765,36 @@ zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcal fci->params = params; if (zend_call_function(fci, fcc) == SUCCESS && zend_is_true(&retval)) { + uint32_t flags = 0; time_t expiration; zval *val = Z_REFVAL(params[2]); - zval *rv = NULL; - zval *zv_cas = NULL; - uint64_t cas; + expiration = zval_get_long(Z_REFVAL(params[3])); - if (Z_TYPE_P(val) == IS_ARRAY) { - rv = zend_hash_str_find(Z_ARRVAL_P(val), "value", sizeof("value") - 1); - zv_cas = zend_hash_str_find(Z_ARRVAL_P(val), "cas", sizeof("cas") - 1); +printf("before with_cas\n"); + if (with_cas) { + zval *rv = NULL; + zval *zv_cas = NULL; + uint64_t cas = 0; + if (Z_TYPE_P(val) == IS_ARRAY) { + rv = zend_hash_str_find(Z_ARRVAL_P(val), "value", sizeof("value") - 1); + zv_cas = zend_hash_str_find(Z_ARRVAL_P(val), "cas", sizeof("cas") - 1); + } +printf("after array\n"); + if (zv_cas) { + cas = s_zval_to_uint64(zv_cas); + status = s_memc_write_zval (intern, MEMC_OP_CAS, NULL, key, rv, &flags, expiration, cas); + } else { + status = s_memc_write_zval (intern, MEMC_OP_SET, NULL, key, rv, &flags, expiration, 0); + } +printf("after write_zval\n"); + array_init(value); + s_create_result_array(key, rv, zv_cas, flags, value); + // ZVAL_COPY(value, rv); // FIXME: this needs to be in extended result format + } else { +printf("else case\n"); + status = s_memc_write_zval (intern, MEMC_OP_SET, NULL, key, val, &flags, expiration, 0); + ZVAL_COPY(value, val); } - - expiration = zval_get_long(Z_REFVAL(params[3])); - cas = zv_cas ? s_zval_to_uint64(zv_cas) : 0; - status = s_memc_write_zval (intern, MEMC_OP_SET, NULL, key, rv ? rv : val, expiration, cas); - ZVAL_COPY(value, val); } else { s_memc_set_status(intern, MEMCACHED_NOTFOUND, 0); @@ -1025,9 +1043,11 @@ zend_string *s_zval_to_payload(php_memc_object_t *intern, zval *value, uint32_t (void)s_compress_value (memc_user_data->compression_type, &payload, flags); } +printf("before setting *flags\n"); if (memc_user_data->set_udf_flags >= 0) { MEMC_VAL_SET_USER_FLAGS(*flags, ((uint32_t) memc_user_data->set_udf_flags)); } +printf("after setting *flags\n"); return payload; } @@ -1043,25 +1063,27 @@ zend_bool s_should_retry_write (php_memc_object_t *intern, memcached_return stat } 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, uint64_t cas) +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, uint32_t *flags, time_t expiration, uint64_t cas) { - 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 (value) { - payload = s_zval_to_payload(intern, value, &flags); +printf("before flags\n"); + payload = s_zval_to_payload(intern, value, flags); +printf("after flags\n"); + } - if (!payload) { - s_memc_set_status(intern, MEMC_RES_PAYLOAD_FAILURE, 0); - return 0; - } + // Only touch has no payload + if (!payload && op != MEMC_OP_TOUCH) { + s_memc_set_status(intern, MEMC_RES_PAYLOAD_FAILURE, 0); + 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; -#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; +#define memc_write_using_fn(fn_name) fn_name(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(payload), ZSTR_LEN(payload), expiration, *flags); +#define memc_write_using_fn_by_key(fn_name) 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); if (server_key) { switch (op) { @@ -1069,10 +1091,6 @@ zend_bool s_memc_write_zval (php_memc_object_t *intern, php_memc_write_op op, ze status = memc_write_using_fn_by_key(memcached_set_by_key); break; - case MEMC_OP_TOUCH: - 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: status = memc_write_using_fn_by_key(memcached_add_by_key); break; @@ -1089,26 +1107,21 @@ zend_bool s_memc_write_zval (php_memc_object_t *intern, php_memc_write_op op, ze status = memc_write_using_fn_by_key(memcached_prepend_by_key); break; + case MEMC_OP_TOUCH: + 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_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); + 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); break; } - - if (status == MEMCACHED_END) { - status = MEMCACHED_SUCCESS; - } - } - else { + } else { retry: switch (op) { case MEMC_OP_SET: status = memc_write_using_fn(memcached_set); break; - case MEMC_OP_TOUCH: - status = php_memcached_touch(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), expiration); - break; - case MEMC_OP_ADD: status = memc_write_using_fn(memcached_add); break; @@ -1125,25 +1138,31 @@ zend_bool s_memc_write_zval (php_memc_object_t *intern, php_memc_write_op op, ze status = memc_write_using_fn(memcached_prepend); break; + case MEMC_OP_TOUCH: + status = php_memcached_touch(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), expiration); + break; + case MEMC_OP_CAS: - status = memcached_cas(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(payload), ZSTR_LEN(payload), expiration, flags, cas); + status = memcached_cas(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(payload), ZSTR_LEN(payload), expiration, *flags, cas); break; } - if (status == MEMCACHED_END) { - status = MEMCACHED_SUCCESS; - } + } + +#undef memc_write_using_fn +#undef memc_write_using_fn_by_key + + if (status == MEMCACHED_END) { + status = MEMCACHED_SUCCESS; } if (s_should_retry_write (intern, status) && retries-- > 0) { goto retry; } -#undef memc_write_using_fn -#undef memc_write_using_fn_by_key - if (payload) { zend_string_release(payload); } + if (s_memc_status_handle_result_code(intern, status) == FAILURE) { return 0; } @@ -1783,6 +1802,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke { zval *entries; zend_string *server_key = NULL; + uint32_t flags = 0; time_t expiration = 0; zval *value; zend_string *skey; @@ -1817,7 +1837,7 @@ 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, 0)) { + if (!s_memc_write_zval (intern, MEMC_OP_SET, server_key, str_key, value, &flags, expiration, 0)) { php_error_docref(NULL, E_WARNING, "failed to set key %s", ZSTR_VAL(str_key)); } @@ -1921,6 +1941,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool zval *value = NULL; zval *zv_cas = NULL; zend_long expiration = 0; + uint32_t flags = 0; uint64_t cas = 0; MEMC_METHOD_INIT_VARS; @@ -1984,7 +2005,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool } } - if (!s_memc_write_zval (intern, op, server_key, key, value, expiration, cas)) { + if (!s_memc_write_zval (intern, op, server_key, key, value, &flags, expiration, cas)) { RETURN_FALSE; } RETURN_TRUE; diff --git a/tests/cachecallback.phpt b/tests/cachecallback.phpt index 55d4f647..e1b42f39 100644 --- a/tests/cachecallback.phpt +++ b/tests/cachecallback.phpt @@ -65,11 +65,10 @@ $m->delete($second_key); $m->delete($third_key); var_dump ( -$m->get ($first_key, function (Memcached $memc, $key, &$value) { - $value = [ - "value" => "first_ext", - "cas" => 12345, - "expiration" => 10 ]; +$m->get ($first_key, function (Memcached $memc, $key, &$value, &$expiration) { + $value = [ "value" => "first_ext" ]; + // "cas" => 12345 ]; + $expiration = 10; return true; }, Memcached::GET_EXTENDED) ); @@ -82,11 +81,11 @@ $m->get ($first_key, function (Memcached $memc, $key, &$value) { }, Memcached::GET_EXTENDED); var_dump ( -$m->get ($second_key, function (Memcached $memc, $key, &$value) { +$m->get ($second_key, function (Memcached $memc, $key, &$value, &$expiration) { $value = [ "value" => "second_ext", - "cas" => 12345, - "expiration" => 10 ]; + "cas" => 12345 ]; + $expiration = 10; return false; }, Memcached::GET_EXTENDED) ); @@ -95,11 +94,11 @@ var_dump ($m->get ($second_key)); var_dump ($m->get ($second_key, null, Memcached::GET_EXTENDED)); try { - $m->get ($third_key, function (Memcached $memc, $key, &$value) { + $m->get ($third_key, function (Memcached $memc, $key, &$value, &$expiration) { $value = [ "value" => "third_ext", - "cas" => "12345", - "expiration" => "10" ]; + "cas" => "12345" ]; + $expiration = 10; throw new Exception ('this is a test'); return true; }, Memcached::GET_EXTENDED); From cfd9c5e9178bd3e1304cdcbdc3596b8369269f1e Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Tue, 28 Mar 2017 22:33:41 -0700 Subject: [PATCH 3/3] More WIP --- php_memcached.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/php_memcached.c b/php_memcached.c index 62f18b74..0999de06 100644 --- a/php_memcached.c +++ b/php_memcached.c @@ -770,7 +770,6 @@ zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcal zval *val = Z_REFVAL(params[2]); expiration = zval_get_long(Z_REFVAL(params[3])); -printf("before with_cas\n"); if (with_cas) { zval *rv = NULL; zval *zv_cas = NULL; @@ -779,19 +778,16 @@ printf("before with_cas\n"); rv = zend_hash_str_find(Z_ARRVAL_P(val), "value", sizeof("value") - 1); zv_cas = zend_hash_str_find(Z_ARRVAL_P(val), "cas", sizeof("cas") - 1); } -printf("after array\n"); if (zv_cas) { cas = s_zval_to_uint64(zv_cas); status = s_memc_write_zval (intern, MEMC_OP_CAS, NULL, key, rv, &flags, expiration, cas); } else { status = s_memc_write_zval (intern, MEMC_OP_SET, NULL, key, rv, &flags, expiration, 0); } -printf("after write_zval\n"); - array_init(value); - s_create_result_array(key, rv, zv_cas, flags, value); - // ZVAL_COPY(value, rv); // FIXME: this needs to be in extended result format + // array_init(value); + // s_create_result_array(key, rv, zv_cas, flags, value); + ZVAL_COPY(value, rv); // FIXME: this needs to be in extended result format } else { -printf("else case\n"); status = s_memc_write_zval (intern, MEMC_OP_SET, NULL, key, val, &flags, expiration, 0); ZVAL_COPY(value, val); } @@ -800,6 +796,22 @@ printf("else case\n"); s_memc_set_status(intern, MEMCACHED_NOTFOUND, 0); } +/* + 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); + + s_uint64_to_zval(&zcas, cas); + + key = zend_string_init (res_key, res_key_len, 0); + retval = result_apply_fn(intern, key, &val, &zcas, flags, context); + + zend_string_release(key); + zval_ptr_dtor(&val); + zval_ptr_dtor(&zcas); +*/ + zval_ptr_dtor(¶ms[0]); zval_ptr_dtor(¶ms[1]); zval_ptr_dtor(¶ms[2]); @@ -1043,11 +1055,9 @@ zend_string *s_zval_to_payload(php_memc_object_t *intern, zval *value, uint32_t (void)s_compress_value (memc_user_data->compression_type, &payload, flags); } -printf("before setting *flags\n"); if (memc_user_data->set_udf_flags >= 0) { MEMC_VAL_SET_USER_FLAGS(*flags, ((uint32_t) memc_user_data->set_udf_flags)); } -printf("after setting *flags\n"); return payload; } @@ -1071,9 +1081,7 @@ zend_bool s_memc_write_zval (php_memc_object_t *intern, php_memc_write_op op, ze zend_long retries = memc_user_data->store_retry_count; if (value) { -printf("before flags\n"); payload = s_zval_to_payload(intern, value, flags); -printf("after flags\n"); } // Only touch has no payload