diff options
-rw-r--r-- | README.markdown | 20 | ||||
-rw-r--r-- | arrays.markdown | 2 | ||||
-rw-r--r-- | library.c | 3 | ||||
-rw-r--r-- | php_redis.h | 1 | ||||
-rw-r--r-- | redis.c | 27 | ||||
-rw-r--r-- | redis_array.c | 14 | ||||
-rw-r--r-- | redis_array_impl.c | 41 | ||||
-rw-r--r-- | redis_array_impl.h | 2 | ||||
-rw-r--r-- | tests/TestRedis.php | 16 | ||||
-rw-r--r-- | tests/array-tests.php | 8 |
10 files changed, 111 insertions, 23 deletions
diff --git a/README.markdown b/README.markdown index 5b8bdd2e..5f017af9 100644 --- a/README.markdown +++ b/README.markdown @@ -2486,7 +2486,7 @@ $redis->script('exists', $script1, [$script2, $script3, ...]); ## getLastError ##### Description -The last error message (if any) returned from a SCRIPT call +The last error message (if any) ##### Parameters *none* ##### Return Value @@ -2498,6 +2498,24 @@ $err = $redis->getLastError(); // "ERR Error compiling script (new function): user_script:1: '=' expected near '-'" </pre> +## clearLastError +##### Description +Clear the last error message +##### Parameters +*none* +##### Return Value +*BOOL* TRUE +##### Examples +<pre> +$redis->set('x', 'a'); +$redis->incr('x'); +$err = $redis->getLastError(); +// "ERR value is not an integer or out of range" +$redis->clearLastError(); +$err = $redis->getLastError(); +// NULL +</pre> + ## _prefix ##### Description A utility method to prefix the value with the prefix setting for phpredis. diff --git a/arrays.markdown b/arrays.markdown index b7031fed..4c1f899d 100644 --- a/arrays.markdown +++ b/arrays.markdown @@ -73,7 +73,7 @@ For instance, the keys “{user:1}:name” and “{user:1}:email” will be stor ## Migrating keys -When a node is added or removed from a ring, RedisArray instances must be instanciated with a “previous” list of nodes. A single call to `$ra->_rehash()` causes all the keys to be redistributed according to the new list of nodes. Passing a callback function to `_rehash()` makes it possible to track the progress of that operation: the function is called with a node name and a number of keys that will be examined. +When a node is added or removed from a ring, RedisArray instances must be instanciated with a “previous” list of nodes. A single call to `$ra->_rehash()` causes all the keys to be redistributed according to the new list of nodes. Passing a callback function to `_rehash()` makes it possible to track the progress of that operation: the function is called with a node name and a number of keys that will be examined, e.g. `_rehash(function ($host, $count){ ... });`. It is possible to automate this process, by setting `'autorehash' => TRUE` in the constructor options. This will cause keys to be migrated when they need to be read from the previous array. @@ -172,6 +172,7 @@ PHPAPI char *redis_sock_read(RedisSock *redis_sock, int *buf_len TSRMLS_DC) { char inbuf[1024]; char *resp = NULL; + size_t err_len; if(-1 == redis_check_eof(redis_sock TSRMLS_CC)) { return NULL; @@ -189,6 +190,8 @@ PHPAPI char *redis_sock_read(RedisSock *redis_sock, int *buf_len TSRMLS_DC) switch(inbuf[0]) { case '-': + err_len = strlen(inbuf+1) - 2; + redis_sock_set_err(redis_sock, inbuf+1, err_len); /* stale data */ if(memcmp(inbuf + 1, "-ERR SYNC ", 10) == 0) { zend_throw_exception(redis_exception_ce, "SYNC with master in progress", 0 TSRMLS_CC); diff --git a/php_redis.h b/php_redis.h index 5ffe5c31..24f00215 100644 --- a/php_redis.h +++ b/php_redis.h @@ -139,6 +139,7 @@ PHP_METHOD(Redis, migrate); PHP_METHOD(Redis, time); PHP_METHOD(Redis, getLastError); +PHP_METHOD(Redis, clearLastError); PHP_METHOD(Redis, _prefix); PHP_METHOD(Redis, _unserialize); @@ -222,6 +222,7 @@ static zend_function_entry redis_functions[] = { PHP_ME(Redis, migrate, NULL, ZEND_ACC_PUBLIC) PHP_ME(Redis, getLastError, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Redis, clearLastError, NULL, ZEND_ACC_PUBLIC) PHP_ME(Redis, _prefix, NULL, ZEND_ACC_PUBLIC) PHP_ME(Redis, _unserialize, NULL, ZEND_ACC_PUBLIC) @@ -6182,6 +6183,32 @@ PHP_METHOD(Redis, getLastError) { } /* + * {{{ proto Redis::clearLastError() + */ +PHP_METHOD(Redis, clearLastError) { + zval *object; + RedisSock *redis_sock; + + // Grab our object + if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &object, redis_ce) == FAILURE) { + RETURN_FALSE; + } + // Grab socket + if(redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) { + RETURN_FALSE; + } + + // Clear error message + if(redis_sock->err) { + efree(redis_sock->err); + } + redis_sock->err = NULL; + + RETURN_TRUE; +} + + +/* * {{{ proto Redis::time() */ PHP_METHOD(Redis, time) { diff --git a/redis_array.c b/redis_array.c index 7964c818..380c53c1 100644 --- a/redis_array.c +++ b/redis_array.c @@ -499,11 +499,13 @@ PHP_METHOD(RedisArray, _distributor) PHP_METHOD(RedisArray, _rehash) { - zval *object, *z_cb = NULL; + zval *object; RedisArray *ra; + zend_fcall_info z_cb; + zend_fcall_info_cache z_cb_cache; - if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|z", - &object, redis_array_ce, &z_cb) == FAILURE) { + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|f", + &object, redis_array_ce, &z_cb, &z_cb_cache) == FAILURE) { RETURN_FALSE; } @@ -511,7 +513,11 @@ PHP_METHOD(RedisArray, _rehash) RETURN_FALSE; } - ra_rehash(ra, z_cb TSRMLS_CC); + if (ZEND_NUM_ARGS() == 0) { + ra_rehash(ra, NULL, NULL TSRMLS_CC); + } else { + ra_rehash(ra, &z_cb, &z_cb_cache TSRMLS_CC); + } } static void multihost_distribute(INTERNAL_FUNCTION_PARAMETERS, const char *method_name) diff --git a/redis_array_impl.c b/redis_array_impl.c index 7968a8b5..d5370c82 100644 --- a/redis_array_impl.c +++ b/redis_array_impl.c @@ -1105,24 +1105,37 @@ ra_move_key(const char *key, int key_len, zval *z_from, zval *z_to TSRMLS_DC) { } /* callback with the current progress, with hostname and count */ -static void zval_rehash_callback(zval *z_cb, const char *hostname, long count TSRMLS_DC) { +static void zval_rehash_callback(zend_fcall_info *z_cb, zend_fcall_info_cache *z_cb_cache, + const char *hostname, long count TSRMLS_DC) { - zval z_ret, *z_args[2]; + zval *z_ret = NULL, **z_args[2]; + zval *z_host, *z_count; + + z_cb->retval_ptr_ptr = &z_ret; + z_cb->params = &z_args; + z_cb->param_count = 2; + z_cb->no_separation = 0; /* run cb(hostname, count) */ - MAKE_STD_ZVAL(z_args[0]); - ZVAL_STRING(z_args[0], hostname, 0); - MAKE_STD_ZVAL(z_args[1]); - ZVAL_LONG(z_args[1], count); - call_user_function(EG(function_table), NULL, z_cb, &z_ret, 2, z_args TSRMLS_CC); + MAKE_STD_ZVAL(z_host); + ZVAL_STRING(z_host, hostname, 0); + z_args[0] = &z_host; + MAKE_STD_ZVAL(z_count); + ZVAL_LONG(z_count, count); + z_args[1] = &z_count; + + zend_call_function(z_cb, z_cb_cache TSRMLS_CC); /* cleanup */ - efree(z_args[0]); - efree(z_args[1]); + efree(z_host); + efree(z_count); + if(z_ret) + efree(z_ret); } static void -ra_rehash_server(RedisArray *ra, zval *z_redis, const char *hostname, zend_bool b_index, zval *z_cb TSRMLS_DC) { +ra_rehash_server(RedisArray *ra, zval *z_redis, const char *hostname, zend_bool b_index, + zend_fcall_info *z_cb, zend_fcall_info_cache *z_cb_cache TSRMLS_DC) { char **keys; int *key_lens; @@ -1138,8 +1151,8 @@ ra_rehash_server(RedisArray *ra, zval *z_redis, const char *hostname, zend_bool } /* callback */ - if(z_cb) { - zval_rehash_callback(z_cb, hostname, count TSRMLS_CC); + if(z_cb && z_cb_cache) { + zval_rehash_callback(z_cb, z_cb_cache, hostname, count TSRMLS_CC); } /* for each key, redistribute */ @@ -1163,7 +1176,7 @@ ra_rehash_server(RedisArray *ra, zval *z_redis, const char *hostname, zend_bool } void -ra_rehash(RedisArray *ra, zval *z_cb TSRMLS_DC) { +ra_rehash(RedisArray *ra, zend_fcall_info *z_cb, zend_fcall_info_cache *z_cb_cache TSRMLS_DC) { int i; @@ -1172,7 +1185,7 @@ ra_rehash(RedisArray *ra, zval *z_cb TSRMLS_DC) { return; /* TODO: compare the two rings for equality */ for(i = 0; i < ra->prev->count; ++i) { - ra_rehash_server(ra, ra->prev->redis[i], ra->prev->hosts[i], ra->index, z_cb TSRMLS_CC); + ra_rehash_server(ra, ra->prev->redis[i], ra->prev->hosts[i], ra->index, z_cb, z_cb_cache TSRMLS_CC); } } diff --git a/redis_array_impl.h b/redis_array_impl.h index 3cbe3f02..0e00258c 100644 --- a/redis_array_impl.h +++ b/redis_array_impl.h @@ -24,6 +24,6 @@ void ra_index_discard(zval *z_redis, zval *return_value TSRMLS_DC); void ra_index_unwatch(zval *z_redis, zval *return_value TSRMLS_DC); zend_bool ra_is_write_cmd(RedisArray *ra, const char *cmd, int cmd_len); -void ra_rehash(RedisArray *ra, zval *z_cb TSRMLS_DC); +void ra_rehash(RedisArray *ra, zend_fcall_info *z_cb, zend_fcall_info_cache *z_cb_cache TSRMLS_DC); #endif diff --git a/tests/TestRedis.php b/tests/TestRedis.php index 663b808a..192dd556 100644 --- a/tests/TestRedis.php +++ b/tests/TestRedis.php @@ -3023,8 +3023,20 @@ class Redis_Test extends TestSuite $this->redis->eval("not-a-lua-script"); // Now we should have an error - $this->assertTrue(strlen($this->redis->getLastError()) > 0); - } + $evalError = $this->redis->getLastError(); + $this->assertTrue(strlen($evalError) > 0); + + // test getLastError with a regular command + $this->redis->set('x', 'a'); + $this->assertFalse($this->redis->incr('x')); + $incrError = $this->redis->getLastError(); + $this->assertTrue($incrError !== $evalError); // error has changed + $this->assertTrue(strlen($incrError) > 0); + + // clear error + $this->redis->clearLastError(); + $this->assertTrue($this->redis->getLastError() === NULL); + } // Helper function to compare nested results -- from the php.net array_diff page, I believe private function array_diff_recursive($aArray1, $aArray2) { diff --git a/tests/array-tests.php b/tests/array-tests.php index 2429cab9..2f72155a 100644 --- a/tests/array-tests.php +++ b/tests/array-tests.php @@ -289,6 +289,14 @@ class Redis_Rehashing_Test extends TestSuite $this->ra->_rehash(); // this will redistribute the keys } + public function testRehashWithCallback() { + $total = 0; + $this->ra->_rehash(function ($host, $count) use (&$total) { + $total += $count; + }); + $this->assertTrue($total > 0); + } + public function testReadRedistributedKeys() { $this->readAllvalues(); // we shouldn't have any missed reads now. } |