Skip to content

Commit 260852f

Browse files
Fix INFO command so it works in a MULTi EXEC block
1 parent 08ecec9 commit 260852f

File tree

3 files changed

+63
-32
lines changed

3 files changed

+63
-32
lines changed

cluster_library.c

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,6 +1258,17 @@ PHPAPI int cluster_send_slot(redisCluster *c, short slot, char *cmd,
12581258
c->cmd_slot = slot;
12591259
c->cmd_sock = SLOT_SOCK(c, slot);
12601260

1261+
/* Enable multi mode on this slot if we've been directed to but haven't
1262+
* send it to this node yet */
1263+
if (c->flags->mode == MULTI && c->cmd_sock->mode != MULTI) {
1264+
if (cluster_send_multi(c, slot TSRMLS_CC) == -1) {
1265+
zend_throw_exception(redis_cluster_exception_ce,
1266+
"Unable to enter MULTI mode on requested slot",
1267+
0 TSRMLS_CC);
1268+
return -1;
1269+
}
1270+
}
1271+
12611272
/* Try the slot */
12621273
if(cluster_sock_write(c, cmd, cmd_len, 1 TSRMLS_CC)==-1) {
12631274
return -1;
@@ -1411,19 +1422,6 @@ PHPAPI void cluster_bulk_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
14111422
add_next_index_stringl(c->multi_resp, resp, c->reply_len, 0);
14121423
}
14131424
}
1414-
1415-
/*
1416-
// Return the string if we can unserialize it
1417-
if(redis_unserialize(c->flags, resp, c->reply_len, &z_ret TSRMLS_CC)==0) {
1418-
CLUSTER_RETURN_STRING(c, resp, c->reply_len);
1419-
} else {
1420-
if(CLUSTER_IS_ATOMIC(c)) {
1421-
*return_value = *z_ret;
1422-
} else {
1423-
add_next_index_zval(c->multi_resp, z_ret);
1424-
}
1425-
efree(resp);
1426-
}*/
14271425
}
14281426

14291427
/* Bulk response where we expect a double */

redis_cluster.c

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2221,32 +2221,43 @@ PHP_METHOD(RedisCluster, discard) {
22212221
static short
22222222
cluster_cmd_get_slot(redisCluster *c, zval *z_arg TSRMLS_DC)
22232223
{
2224+
int key_len, key_free;
2225+
zval **z_host, **z_port, *z_tmp = NULL;
22242226
short slot;
2227+
char *key;
22252228

22262229
/* If it's a string, treat it as a key. Otherwise, look for a two
22272230
* element array */
2228-
if(Z_TYPE_P(z_arg)==IS_STRING) {
2229-
char *key = Z_STRVAL_P(z_arg);
2230-
int key_len = Z_STRLEN_P(z_arg), key_free;
2231+
if(Z_TYPE_P(z_arg)==IS_STRING || Z_TYPE_P(z_arg)==IS_LONG ||
2232+
Z_TYPE_P(z_arg)==IS_DOUBLE)
2233+
{
2234+
/* Allow for any scalar here */
2235+
if (Z_TYPE_P(z_arg) != IS_STRING) {
2236+
MAKE_STD_ZVAL(z_tmp);
2237+
*z_tmp = *z_arg;
2238+
zval_copy_ctor(z_tmp);
2239+
convert_to_string(z_tmp);
2240+
z_arg = z_tmp;
2241+
}
2242+
2243+
key = Z_STRVAL_P(z_arg);
2244+
key_len = Z_STRLEN_P(z_arg);
22312245

22322246
/* Hash it */
22332247
key_free = redis_key_prefix(c->flags, &key, &key_len);
22342248
slot = cluster_hash_key(key, key_len);
22352249
if(key_free) efree(key);
2236-
} else {
2237-
zval **z_host, **z_port;
2238-
2239-
/* We'll need two elements, one string, one long */
2240-
if(Z_TYPE_P(z_arg) != IS_ARRAY ||
2241-
zend_hash_index_find(Z_ARRVAL_P(z_arg),0,(void**)&z_host)==FAILURE ||
2242-
zend_hash_index_find(Z_ARRVAL_P(z_arg),1,(void**)&z_port)==FAILURE ||
2243-
Z_TYPE_PP(z_host)!=IS_STRING || Z_TYPE_PP(z_port)!=IS_LONG)
2244-
{
2245-
php_error_docref(0 TSRMLS_CC, E_WARNING,
2246-
"Directed commands must be passed string key or [host,port]");
2247-
return -1;
2248-
}
22492250

2251+
/* Destroy our temp value if we had to convert it */
2252+
if (z_tmp) {
2253+
zval_dtor(z_tmp);
2254+
efree(z_tmp);
2255+
}
2256+
} else if (Z_TYPE_P(z_arg) == IS_ARRAY &&
2257+
zend_hash_index_find(Z_ARRVAL_P(z_arg),0,(void**)&z_host)!=FAILURE &&
2258+
zend_hash_index_find(Z_ARRVAL_P(z_arg),1,(void**)&z_port)!=FAILURE &&
2259+
Z_TYPE_PP(z_host)==IS_STRING && Z_TYPE_PP(z_port)==IS_LONG)
2260+
{
22502261
/* Attempt to find this specific node by host:port */
22512262
slot = cluster_find_slot(c,(const char *)Z_STRVAL_PP(z_host),
22522263
(unsigned short)Z_LVAL_PP(z_port));
@@ -2256,6 +2267,10 @@ cluster_cmd_get_slot(redisCluster *c, zval *z_arg TSRMLS_DC)
22562267
php_error_docref(0 TSRMLS_CC, E_WARNING, "Unknown node %s:%ld",
22572268
Z_STRVAL_PP(z_host), Z_LVAL_PP(z_port));
22582269
}
2270+
} else {
2271+
php_error_docref(0 TSRMLS_CC, E_WARNING,
2272+
"Direted commands musty be passed a key or [host,port] array");
2273+
return -1;
22592274
}
22602275

22612276
return slot;
@@ -2618,8 +2633,10 @@ PHP_METHOD(RedisCluster, lastsave) {
26182633
* proto array RedisCluster::info(array host_port, [string $arg]) */
26192634
PHP_METHOD(RedisCluster, info) {
26202635
redisCluster *c = GET_CONTEXT();
2636+
REDIS_REPLY_TYPE rtype;
26212637
char *cmd, *opt=NULL;
26222638
int cmd_len, opt_len;
2639+
void *ctx = NULL;
26232640
zval *z_arg;
26242641
short slot;
26252642

@@ -2643,14 +2660,19 @@ PHP_METHOD(RedisCluster, info) {
26432660
cmd_len = redis_cmd_format_static(&cmd, "INFO", "");
26442661
}
26452662

2646-
if(cluster_send_slot(c, slot, cmd, cmd_len, TYPE_BULK TSRMLS_CC)<0) {
2663+
rtype = CLUSTER_IS_ATOMIC(c) ? TYPE_BULK : TYPE_LINE;
2664+
if (cluster_send_slot(c, slot, cmd, cmd_len, rtype TSRMLS_CC)<0) {
26472665
zend_throw_exception(redis_cluster_exception_ce,
26482666
"Unable to send INFO command to specific node", 0 TSRMLS_CC);
26492667
efree(cmd);
26502668
RETURN_FALSE;
26512669
}
26522670

2653-
cluster_info_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, NULL);
2671+
if (CLUSTER_IS_ATOMIC(c)) {
2672+
cluster_info_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, NULL);
2673+
} else {
2674+
CLUSTER_ENQUEUE_RESPONSE(c, slot, cluster_info_resp, ctx);
2675+
}
26542676

26552677
efree(cmd);
26562678
}

tests/RedisClusterTest.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ public function testSortDesc() { return $this->markTestSkipped(); }
3232
public function testWait() { return $this->markTestSkipped(); }
3333
public function testSelect() { return $this->markTestSkipped(); }
3434
public function testReconnectSelect() { return $this->markTestSkipped(); }
35-
public function testIntrospection() { return $this->markTestSkipped(); }
3635

3736
/* Skips for now, which need attention */
3837
public function testClient() { return $this->markTestSkipped(); }
@@ -297,6 +296,18 @@ public function testEvalSHA() {
297296
$this->assertTrue(1 === $this->redis->evalsha($sha,Array($str_key), 1));
298297
}
299298

299+
/* Cluster specific introspection stuff */
300+
public function testIntrospection() {
301+
$arr_masters = $this->redis->_masters();
302+
$this->assertTrue(is_array($arr_masters));
303+
304+
foreach ($arr_masters as $arr_info) {
305+
$this->assertTrue(is_array($arr_info));
306+
$this->assertTrue(is_string($arr_info[0]));
307+
$this->assertTrue(is_long($arr_info[1]));
308+
}
309+
}
310+
300311
protected function genKeyName($i_key_idx, $i_type) {
301312
switch ($i_type) {
302313
case Redis::REDIS_STRING:

0 commit comments

Comments
 (0)