diff options
author | michael-grunder <michael.grunder@gmail.com> | 2015-03-07 06:42:32 +0300 |
---|---|---|
committer | michael-grunder <michael.grunder@gmail.com> | 2015-05-06 01:19:29 +0300 |
commit | 7e7eec6281730163eee5f9e36b0be939b9f12485 (patch) | |
tree | 8057fee7be579e12b8cca266db01705b309f01e3 | |
parent | 260852f562a591fb49727ada4451cd9b6ce7ad45 (diff) |
Make RedisCluster::client('list') work like Redis
-rw-r--r-- | cluster_library.c | 25 | ||||
-rw-r--r-- | cluster_library.h | 4 | ||||
-rw-r--r-- | library.c | 55 | ||||
-rw-r--r-- | library.h | 1 | ||||
-rw-r--r-- | redis_cluster.c | 68 |
5 files changed, 124 insertions, 29 deletions
diff --git a/cluster_library.c b/cluster_library.c index 6c40e466..51d2c3d1 100644 --- a/cluster_library.c +++ b/cluster_library.c @@ -1920,6 +1920,31 @@ PHPAPI void cluster_info_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, } } +/* CLIENT LIST response */ +PHPAPI void cluster_client_list_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, + void *ctx) +{ + zval *z_result; + char *info; + + /* Read the bulk response */ + info = redis_sock_read_bulk_reply(c->cmd_sock, c->reply_len TSRMLS_CC); + if (info == NULL) { + CLUSTER_RETURN_FALSE(c); + } + + /* Parse it and free the bulk string */ + z_result = redis_parse_client_list_response(info); + efree(info); + + if (CLUSTER_IS_ATOMIC(c)) { + *return_value = *z_result; + efree(z_result); + } else { + add_next_index_zval(c->multi_resp, z_result); + } +} + /* MULTI BULK response loop where we might pull the next one */ PHPAPI zval *cluster_zval_mbulk_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, int pull, mbulk_cb cb) diff --git a/cluster_library.h b/cluster_library.h index aee2f761..d97de2a4 100644 --- a/cluster_library.h +++ b/cluster_library.h @@ -436,6 +436,10 @@ PHPAPI int cluster_scan_resp(INTERNAL_FUNCTION_PARAMETERS, PHPAPI void cluster_info_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx); +/* CLIENT LIST response handler */ +PHPAPI void cluster_client_list_resp(INTERNAL_FUNCTION_PARAMETERS, + redisCluster *c, void *ctx); + /* MULTI BULK processing callbacks */ int mbulk_resp_loop(RedisSock *redis_sock, zval *z_result, long long count, void *ctx TSRMLS_DC); @@ -1024,20 +1024,31 @@ PHPAPI zval *redis_parse_info_response(char *response) { PHP_REDIS_API void redis_client_list_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab) { char *resp; int resp_len; - zval *z_result, *z_sub_result; + zval *z_ret; - /* Pointers for parsing */ - char *p, *lpos, *kpos = NULL, *vpos = NULL, *p2, *key, *value; + /* Make sure we can read the bulk response from Redis */ + if ((resp = redis_sock_read(redis_sock, &resp_len TSRMLS_CC)) == NULL) { + RETURN_FALSE; + } - /* Key length, done flag */ - int klen = 0, done = 0, is_numeric; + /* Parse it out */ + z_ret = redis_parse_client_list_response(resp); - /* Make sure we can read a response from Redis */ - if((resp = redis_sock_read(redis_sock, &resp_len TSRMLS_CC)) == NULL) { - RETURN_FALSE; + /* Free our response */ + efree(resp); + + /* Return or append depending if we're atomic */ + IF_MULTI_OR_PIPELINE() { + add_next_index_zval(z_tab, z_ret); + } else { + RETVAL_ZVAL(z_ret, 0, 1); } +} + +PHPAPI zval* redis_parse_client_list_response(char *response) { + zval *z_result, *z_sub_result; - /* Allocate memory for our response */ + // Allocate memory for our response MAKE_STD_ZVAL(z_result); array_init(z_result); @@ -1045,8 +1056,9 @@ PHP_REDIS_API void redis_client_list_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSo ALLOC_INIT_ZVAL(z_sub_result); array_init(z_sub_result); - p = resp; - lpos = resp; + // Pointers for parsing + char *p = response, *lpos = response, *p2, *key; + char *kpos = NULL, *vpos = NULL, *value; /* While we've got more to parse */ while(!done) { @@ -1107,9 +1119,11 @@ PHP_REDIS_API void redis_client_list_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSo /* Free our key */ efree(key); } else { - /* Something is wrong */ - efree(resp); - RETURN_FALSE; + // Something is wrong + zval_dtor(z_result); + MAKE_STD_ZVAL(z_result); + ZVAL_BOOL(z_result, 0); + return z_result; } /* Move forward */ @@ -1132,18 +1146,13 @@ PHP_REDIS_API void redis_client_list_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSo p++; } - /* Free our respoonse */ - efree(resp); - - IF_MULTI_OR_PIPELINE() { - add_next_index_zval(z_tab, z_result); - } else { - RETVAL_ZVAL(z_result, 0, 1); - } + /* Return our parsed response */ + return z_result; } PHPAPI void -redis_boolean_response_impl(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx, +redis_boolean_response_impl(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, + zval *z_tab, void *ctx, SuccessCallback success_callback) { @@ -28,6 +28,7 @@ PHPAPI void redis_string_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis PHPAPI void redis_ping_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); PHPAPI void redis_info_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); PHPAPI zval *redis_parse_info_response(char *resp); +PHPAPI zval *redis_parse_client_list_response(char *resp); PHPAPI void redis_type_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); PHPAPI RedisSock* redis_sock_create(char *host, int host_len, unsigned short port, double timeout, int persistent, char *persistent_id, long retry_interval, zend_bool lazy_connect); PHPAPI int redis_sock_connect(RedisSock *redis_sock TSRMLS_DC); diff --git a/redis_cluster.c b/redis_cluster.c index 24243236..63bfeedd 100644 --- a/redis_cluster.c +++ b/redis_cluster.c @@ -2678,6 +2678,68 @@ PHP_METHOD(RedisCluster, info) { } /* }}} */ +/* {{{ proto array RedisCluster::client('list') + * proto bool RedisCluster::client('kill', $ipport) + * proto bool RedisCluster::client('setname', $name) + * proto string RedisCluster::client('getname') + */ +PHP_METHOD(RedisCluster, client) { + redisCluster *c = GET_CONTEXT(); + char *cmd, *opt=NULL, *arg=NULL; + int cmd_len, opt_len, arg_len; + REDIS_REPLY_TYPE rtype; + zval *z_node; + short slot; + cluster_cb cb; + + /* Parse args */ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs|s", &z_node, &opt, + &opt_len, &arg, &arg_len)==FAILURE) + { + RETURN_FALSE; + } + + /* Make sure we can properly resolve the slot */ + slot = cluster_cmd_get_slot(c, z_node TSRMLS_CC); + if(slot<0) RETURN_FALSE; + + /* Construct the command */ + if (ZEND_NUM_ARGS() == 3) { + cmd_len = redis_cmd_format_static(&cmd, "CLIENT", "ss", opt, opt_len, + arg, arg_len); + } else if(ZEND_NUM_ARGS() == 2) { + cmd_len = redis_cmd_format_static(&cmd, "CLIENT", "s", opt, opt_len); + } else { + zend_wrong_param_count(TSRMLS_C); + RETURN_FALSE; + } + + 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 CLIENT command to specific node", 0 TSRMLS_CC); + efree(cmd); + RETURN_FALSE; + } + + /* Handle client list and anything else differently */ + if (opt_len == 4 && !strncasecmp(opt, "list", 4)) { + cb = cluster_client_list_resp; + } else { + cb = cluster_variant_resp; + } + + /* Now enqueue or process response */ + if (CLUSTER_IS_ATOMIC(c)) { + cluster_client_list_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, NULL); + } else { + void *ctx = NULL; + CLUSTER_ENQUEUE_RESPONSE(c, slot, cluster_client_list_resp, ctx); + } + + efree(cmd); +} + /* {{{ proto mixed RedisCluster::cluster(variant) */ PHP_METHOD(RedisCluster, cluster) { cluster_raw_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, "CLUSTER", @@ -2685,12 +2747,6 @@ PHP_METHOD(RedisCluster, cluster) { } /* }}} */ -/* {{{ proto mixed RedisCluster::client(string key, ...) - * proto mixed RedisCluster::client(array host_port, ...) */ -PHP_METHOD(RedisCluster, client) { - cluster_raw_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, "CLIENT", - sizeof("CLIENT")-1); -} /* }}} */ /* {{{ proto mixed RedisCluster::config(string key, ...) |