Skip to content

Commit

Permalink
Fix INFO command so it works in a MULTi EXEC block
Browse files Browse the repository at this point in the history
  • Loading branch information
michael-grunder committed May 5, 2015
1 parent 08ecec9 commit 260852f
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 32 deletions.
24 changes: 11 additions & 13 deletions cluster_library.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 */
Expand Down
58 changes: 40 additions & 18 deletions redis_cluster.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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;
Expand Down Expand Up @@ -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;

Expand All @@ -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);
}
Expand Down
13 changes: 12 additions & 1 deletion tests/RedisClusterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ public function testSortDesc() { return $this->markTestSkipped(); }
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(); }
Expand Down Expand Up @@ -297,6 +296,18 @@ public function testEvalSHA() {
$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:
Expand Down

0 comments on commit 260852f

Please sign in to comment.