patch原因:
解决get、delete方法无法区分连接失败和not found的问题
patch内容
本次修改是在memcache-2.2.6 的基础上修改的,我把她修改版本号为 2.2.6.1来使用了,
patch 文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
diff -uN memcache-2.2.6/memcache.c memcache-2.2.6.1/memcache.c --- memcache-2.2.6/memcache.c 2010-10-04 04:57:47.000000000 +0800 +++ memcache-2.2.6.1/memcache.c 2011-08-02 23:44:48.000000000 +0800 @@ -56,6 +56,16 @@ ZEND_DECLARE_MODULE_GLOBALS(memcache) +ZEND_BEGIN_ARG_INFO_EX(arginfo_memcache_get, 0, 0, 1) + ZEND_ARG_INFO(0, key) + ZEND_ARG_INFO(1, flags) +ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_memcache_delete, 0, 0, 1) + ZEND_ARG_INFO(0, key) + ZEND_ARG_INFO(0, time) + ZEND_ARG_INFO(1, error_flag) +ZEND_END_ARG_INFO() + /* {{{ memcache_functions[] */ zend_function_entry memcache_functions[] = { @@ -68,8 +78,8 @@ PHP_FE(memcache_add, NULL) PHP_FE(memcache_set, NULL) PHP_FE(memcache_replace, NULL) - PHP_FE(memcache_get, NULL) - PHP_FE(memcache_delete, NULL) + PHP_FE(memcache_get, arginfo_memcache_get) + PHP_FE(memcache_delete, arginfo_memcache_delete) PHP_FE(memcache_debug, NULL) PHP_FE(memcache_get_stats, NULL) PHP_FE(memcache_get_extended_stats, NULL) @@ -92,8 +102,8 @@ PHP_FALIAS(add, memcache_add, NULL) PHP_FALIAS(set, memcache_set, NULL) PHP_FALIAS(replace, memcache_replace, NULL) - PHP_FALIAS(get, memcache_get, NULL) - PHP_FALIAS(delete, memcache_delete, NULL) + PHP_FALIAS(get, memcache_get, arginfo_memcache_get) + PHP_FALIAS(delete, memcache_delete, arginfo_memcache_delete) PHP_FALIAS(getstats, memcache_get_stats, NULL) PHP_FALIAS(getextendedstats, memcache_get_extended_stats, NULL) PHP_FALIAS(setcompressthreshold, memcache_set_compress_threshold, NULL) @@ -1290,6 +1300,7 @@ /* not found */ if (result == 0) { + flags |= 1 << 29; // flag for not found ZVAL_FALSE(*return_value); } /* read "END" */ @@ -2382,23 +2393,32 @@ long time = 0; char key_tmp[MMC_KEY_MAX_SIZE]; unsigned int key_tmp_len; + zval *error_flag = NULL; if (mmc_object == NULL) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os|l", &mmc_object, memcache_class_entry_ptr, &key, &key_len, &time) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os|lz", &mmc_object, memcache_class_entry_ptr, &key, &key_len, &time, &error_flag) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &key, &key_len, &time) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz", &key, &key_len, &time, &error_flag) == FAILURE) { return; } } + if (error_flag == NULL) { + ALLOC_INIT_ZVAL(error_flag); // init zval + } else { + zval_dtor(error_flag); // if other type then destruct + } + ZVAL_LONG(error_flag, 0); //init to 0 if (!mmc_get_pool(mmc_object, &pool TSRMLS_CC) || !pool->num_servers) { + ZVAL_LONG(error_flag, 1 << 30); //set flag as 1 << 30 for network error RETURN_FALSE; } if (mmc_prepare_key_ex(key, key_len, key_tmp, &key_tmp_len TSRMLS_CC) != MMC_OK) { + ZVAL_LONG(error_flag, 1 << 28); //set flag as 1 << 28 for key prepare fail RETURN_FALSE; } @@ -2410,7 +2430,11 @@ if (result > 0) { RETURN_TRUE; + } else if(result == 0) { // not found + ZVAL_LONG(error_flag, 1 << 29); //set flag as 1 << 29 for not found + RETURN_FALSE; } + ZVAL_LONG(error_flag, 1 << 30); //set flag as 1 << 30 for net work error RETURN_FALSE; } /* }}} */ diff -uN memcache-2.2.6/php_memcache.h memcache-2.2.6.1/php_memcache.h --- memcache-2.2.6/php_memcache.h 2010-10-04 04:57:47.000000000 +0800 +++ memcache-2.2.6.1/php_memcache.h 2011-07-30 21:50:34.000000000 +0800 @@ -63,7 +63,7 @@ PHP_FUNCTION(memcache_flush); PHP_FUNCTION(memcache_setoptimeout); -#define PHP_MEMCACHE_VERSION "2.2.6" +#define PHP_MEMCACHE_VERSION "2.2.6.1" #define MMC_BUF_SIZE 4096 #define MMC_SERIALIZED 1 |
patch说明
修改的地方如下:
1. 添加参数检查(memcache.c), 在 ZEND_DECLARE_MODULE_GLOBALS(memcache) 下面添加:
2. 修改memcache_get、memcache_delete函数的定义:
3. 修改memcache_get 函数的实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/ /这里只添加了一行,其它都不变 int mmc_exec_retrieval_cmd(mmc_pool_t *pool, const char *key, int key_len, zval **return_value, zval *return_flags TSRMLS_DC) /* {{{ */ { //... /* send command and read value */ if ((result = mmc_sendcmd(mmc, command, command_len TSRMLS_CC)) > 0 && (result = mmc_read_value(mmc, NULL, NULL, &value, &value_len, &flags TSRMLS_CC)) >= 0) { /* not found */ if (result == 0) { flags |= 1 << 29; // flag for not found, 此处添加该行 ZVAL_FALSE(*return_value); } //... |
4. 修改delete函数的实现:
这里的error_flag 是新添加的可选参数,与改变量相关的地方都是新添加的
测试脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
<?php define("E_MC_KEY_PREPARE_ERROR", 1<<28); define("E_MC_NO_FOUND", 1<<29); define("E_MC_CONNECT_ERROR", 1<<30); test_delete(); exit; function test_delete() { $m = new Memcache(); $m->addServer("127.0.0.1", 11211); // this is available $result = $m->delete("noexists", 0, $flag); check_error("should no found", $flag); $m->set("exists","I am here",0,600); $result = $m->delete("exists", 0, $flag); check_error("should ok", $flag); $m = new Memcache(); $m->addServer("127.0.0.1", 11219); // this is unavailable $result = $m->delete("noexists", 0, $flag); check_error("should connect error", $flag); $result = @$m->delete("", 0, $flag); // test no flag check_error("should key error", $flag); $result = $m->delete("m", 0); // test no flag echo "it can work without flag argument, that's ok\n"; } function check_error($lable, $flag) { echo $lable .":\t"; if ($flag & E_MC_CONNECT_ERROR) { echo "connect error\n"; } if ($flag & E_MC_NO_FOUND) { echo "no found\n"; } if ($flag & E_MC_KEY_PREPARE_ERROR) { echo "Key is unvalidate\n"; } if ($flag == 0) { echo "OK\n"; } } |
遗留问题
===========================
如果没有第一部分的修改,貌似也是可以的,但是下面三段脚本是值得思考的: