Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/phpredis/phpredis.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormichael-grunder <michael.grunder@gmail.com>2015-03-07 05:40:16 +0300
committermichael-grunder <michael.grunder@gmail.com>2015-05-06 01:18:02 +0300
commit260852f562a591fb49727ada4451cd9b6ce7ad45 (patch)
treeba51b62847b975ce4da63281ae0540983a8a907b
parent08ecec92a3e3cad1c74bec31e6a74dce03ed3e84 (diff)
Fix INFO command so it works in a MULTi EXEC block
-rw-r--r--cluster_library.c24
-rw-r--r--redis_cluster.c58
-rw-r--r--tests/RedisClusterTest.php13
3 files changed, 63 insertions, 32 deletions
diff --git a/cluster_library.c b/cluster_library.c
index d7addf20..6c40e466 100644
--- a/cluster_library.c
+++ b/cluster_library.c
@@ -1258,6 +1258,17 @@ PHPAPI int cluster_send_slot(redisCluster *c, short slot, char *cmd,
c->cmd_slot = slot;
c->cmd_sock = SLOT_SOCK(c, slot);
+ /* Enable multi mode on this slot if we've been directed to but haven't
+ * send it to this node yet */
+ if (c->flags->mode == MULTI && c->cmd_sock->mode != MULTI) {
+ if (cluster_send_multi(c, slot TSRMLS_CC) == -1) {
+ zend_throw_exception(redis_cluster_exception_ce,
+ "Unable to enter MULTI mode on requested slot",
+ 0 TSRMLS_CC);
+ return -1;
+ }
+ }
+
/* Try the slot */
if(cluster_sock_write(c, cmd, cmd_len, 1 TSRMLS_CC)==-1) {
return -1;
@@ -1411,19 +1422,6 @@ PHPAPI void cluster_bulk_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
add_next_index_stringl(c->multi_resp, resp, c->reply_len, 0);
}
}
-
- /*
- // Return the string if we can unserialize it
- if(redis_unserialize(c->flags, resp, c->reply_len, &z_ret TSRMLS_CC)==0) {
- CLUSTER_RETURN_STRING(c, resp, c->reply_len);
- } else {
- if(CLUSTER_IS_ATOMIC(c)) {
- *return_value = *z_ret;
- } else {
- add_next_index_zval(c->multi_resp, z_ret);
- }
- efree(resp);
- }*/
}
/* Bulk response where we expect a double */
diff --git a/redis_cluster.c b/redis_cluster.c
index e054b4e1..24243236 100644
--- a/redis_cluster.c
+++ b/redis_cluster.c
@@ -2221,32 +2221,43 @@ PHP_METHOD(RedisCluster, discard) {
static short
cluster_cmd_get_slot(redisCluster *c, zval *z_arg TSRMLS_DC)
{
+ int key_len, key_free;
+ zval **z_host, **z_port, *z_tmp = NULL;
short slot;
+ char *key;
/* If it's a string, treat it as a key. Otherwise, look for a two
* element array */
- if(Z_TYPE_P(z_arg)==IS_STRING) {
- char *key = Z_STRVAL_P(z_arg);
- int key_len = Z_STRLEN_P(z_arg), key_free;
+ if(Z_TYPE_P(z_arg)==IS_STRING || Z_TYPE_P(z_arg)==IS_LONG ||
+ Z_TYPE_P(z_arg)==IS_DOUBLE)
+ {
+ /* Allow for any scalar here */
+ if (Z_TYPE_P(z_arg) != IS_STRING) {
+ MAKE_STD_ZVAL(z_tmp);
+ *z_tmp = *z_arg;
+ zval_copy_ctor(z_tmp);
+ convert_to_string(z_tmp);
+ z_arg = z_tmp;
+ }
+
+ key = Z_STRVAL_P(z_arg);
+ key_len = Z_STRLEN_P(z_arg);
/* Hash it */
key_free = redis_key_prefix(c->flags, &key, &key_len);
slot = cluster_hash_key(key, key_len);
if(key_free) efree(key);
- } else {
- zval **z_host, **z_port;
-
- /* We'll need two elements, one string, one long */
- if(Z_TYPE_P(z_arg) != IS_ARRAY ||
- zend_hash_index_find(Z_ARRVAL_P(z_arg),0,(void**)&z_host)==FAILURE ||
- zend_hash_index_find(Z_ARRVAL_P(z_arg),1,(void**)&z_port)==FAILURE ||
- Z_TYPE_PP(z_host)!=IS_STRING || Z_TYPE_PP(z_port)!=IS_LONG)
- {
- php_error_docref(0 TSRMLS_CC, E_WARNING,
- "Directed commands must be passed string key or [host,port]");
- return -1;
- }
+ /* Destroy our temp value if we had to convert it */
+ if (z_tmp) {
+ zval_dtor(z_tmp);
+ efree(z_tmp);
+ }
+ } else if (Z_TYPE_P(z_arg) == IS_ARRAY &&
+ zend_hash_index_find(Z_ARRVAL_P(z_arg),0,(void**)&z_host)!=FAILURE &&
+ zend_hash_index_find(Z_ARRVAL_P(z_arg),1,(void**)&z_port)!=FAILURE &&
+ Z_TYPE_PP(z_host)==IS_STRING && Z_TYPE_PP(z_port)==IS_LONG)
+ {
/* Attempt to find this specific node by host:port */
slot = cluster_find_slot(c,(const char *)Z_STRVAL_PP(z_host),
(unsigned short)Z_LVAL_PP(z_port));
@@ -2256,6 +2267,10 @@ cluster_cmd_get_slot(redisCluster *c, zval *z_arg TSRMLS_DC)
php_error_docref(0 TSRMLS_CC, E_WARNING, "Unknown node %s:%ld",
Z_STRVAL_PP(z_host), Z_LVAL_PP(z_port));
}
+ } else {
+ php_error_docref(0 TSRMLS_CC, E_WARNING,
+ "Direted commands musty be passed a key or [host,port] array");
+ return -1;
}
return slot;
@@ -2618,8 +2633,10 @@ PHP_METHOD(RedisCluster, lastsave) {
* proto array RedisCluster::info(array host_port, [string $arg]) */
PHP_METHOD(RedisCluster, info) {
redisCluster *c = GET_CONTEXT();
+ REDIS_REPLY_TYPE rtype;
char *cmd, *opt=NULL;
int cmd_len, opt_len;
+ void *ctx = NULL;
zval *z_arg;
short slot;
@@ -2643,14 +2660,19 @@ PHP_METHOD(RedisCluster, info) {
cmd_len = redis_cmd_format_static(&cmd, "INFO", "");
}
- if(cluster_send_slot(c, slot, cmd, cmd_len, TYPE_BULK TSRMLS_CC)<0) {
+ rtype = CLUSTER_IS_ATOMIC(c) ? TYPE_BULK : TYPE_LINE;
+ if (cluster_send_slot(c, slot, cmd, cmd_len, rtype TSRMLS_CC)<0) {
zend_throw_exception(redis_cluster_exception_ce,
"Unable to send INFO command to specific node", 0 TSRMLS_CC);
efree(cmd);
RETURN_FALSE;
}
- cluster_info_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, NULL);
+ if (CLUSTER_IS_ATOMIC(c)) {
+ cluster_info_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, NULL);
+ } else {
+ CLUSTER_ENQUEUE_RESPONSE(c, slot, cluster_info_resp, ctx);
+ }
efree(cmd);
}
diff --git a/tests/RedisClusterTest.php b/tests/RedisClusterTest.php
index 690be418..acda8fc4 100644
--- a/tests/RedisClusterTest.php
+++ b/tests/RedisClusterTest.php
@@ -32,7 +32,6 @@ class Redis_Cluster_Test extends Redis_Test {
public function testWait() { return $this->markTestSkipped(); }
public function testSelect() { return $this->markTestSkipped(); }
public function testReconnectSelect() { return $this->markTestSkipped(); }
- public function testIntrospection() { return $this->markTestSkipped(); }
/* Skips for now, which need attention */
public function testClient() { return $this->markTestSkipped(); }
@@ -297,6 +296,18 @@ class Redis_Cluster_Test extends Redis_Test {
$this->assertTrue(1 === $this->redis->evalsha($sha,Array($str_key), 1));
}
+ /* Cluster specific introspection stuff */
+ public function testIntrospection() {
+ $arr_masters = $this->redis->_masters();
+ $this->assertTrue(is_array($arr_masters));
+
+ foreach ($arr_masters as $arr_info) {
+ $this->assertTrue(is_array($arr_info));
+ $this->assertTrue(is_string($arr_info[0]));
+ $this->assertTrue(is_long($arr_info[1]));
+ }
+ }
+
protected function genKeyName($i_key_idx, $i_type) {
switch ($i_type) {
case Redis::REDIS_STRING: