diff options
author | michael-grunder <michael.grunder@gmail.com> | 2014-07-09 02:37:01 +0400 |
---|---|---|
committer | michael-grunder <michael.grunder@gmail.com> | 2015-05-06 01:02:04 +0300 |
commit | ba9485d7ef881a99539882bba60106759cbc12e7 (patch) | |
tree | 82a677572ec2d870178a7c4b11662c516795363b /cluster_library.c | |
parent | b0152f2c0d40eb0cb6f6e5ed52c529d7e8302772 (diff) |
EVAL/EVALSHA
Implemented EVAL and EVALSHA commands for cluster. Thes commands
present a bit of an issue from the context of a client. Given that
the code being executed can be any arbitrary LUA code, phpredis can't
always protect against trying to access keys that live on a different
cluster node, especially if the "keys count" isn't passed correctly,
or in cases where the keys are generated in the script.
Work in progress, but there is unlikely a perfect solution to this
at all, given the nature of Redis Cluster and LUA execution.
Diffstat (limited to 'cluster_library.c')
-rw-r--r-- | cluster_library.c | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/cluster_library.c b/cluster_library.c index 49682b9b..a44f4ea2 100644 --- a/cluster_library.c +++ b/cluster_library.c @@ -1611,6 +1611,97 @@ PHPAPI void cluster_unsub_resp(INTERNAL_FUNCTION_PARAMETERS, } } +/* Recursive MULTI BULK -> PHP style response handling */ +static void cluster_mbulk_variant_resp(clusterReply *r, zval *z_ret) +{ + zval *z_sub_ele; + + switch(r->type) { + case TYPE_INT: + add_next_index_long(z_ret, r->integer); + break; + case TYPE_LINE: + add_next_index_bool(z_ret, 1); + break; + case TYPE_BULK: + add_next_index_stringl(z_ret, r->str, r->len, 0); + break; + case TYPE_MULTIBULK: + MAKE_STD_ZVAL(z_sub_ele); + array_init(z_sub_ele); + cluster_mbulk_variant_resp(r, z_sub_ele); + add_next_index_zval(z_ret, z_sub_ele); + break; + default: + add_next_index_bool(z_ret, 0); + break; + } +} + +/* Variant response handling, for things like EVAL and various other responses + * where we just map the replies from Redis type values to PHP ones directly. */ +PHPAPI void cluster_variant_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, + void *ctx) +{ + clusterReply *r; + zval *z_arr; + + // Make sure we can read it + if((r = cluster_read_resp(c TSRMLS_CC))==NULL) { + CLUSTER_RETURN_FALSE(c); + } + + // Handle ATOMIC vs. MULTI mode in a seperate switch + if(CLUSTER_IS_ATOMIC(c)) { + switch(r->type) { + case TYPE_INT: + RETVAL_LONG(r->integer); + break; + case TYPE_LINE: + RETVAL_TRUE; + break; + case TYPE_BULK: + RETVAL_STRINGL(r->str, r->len, 0); + break; + case TYPE_MULTIBULK: + MAKE_STD_ZVAL(z_arr); + array_init(z_arr); + cluster_mbulk_variant_resp(r, z_arr); + + *return_value = *z_arr; + efree(z_arr); + break; + default: + RETVAL_FALSE; + break; + } + } else { + switch(r->type) { + case TYPE_INT: + add_next_index_long(c->multi_resp, r->integer); + break; + case TYPE_LINE: + add_next_index_bool(c->multi_resp, 1); + break; + case TYPE_BULK: + add_next_index_stringl(c->multi_resp, r->str, r->len, 0); + break; + case TYPE_MULTIBULK: + MAKE_STD_ZVAL(z_arr); + array_init(z_arr); + cluster_mbulk_variant_resp(r, z_arr); + add_next_index_zval(c->multi_resp, z_arr); + break; + default: + add_next_index_bool(c->multi_resp, 0); + break; + } + } + + // Free our response structs, but not allocated data itself + cluster_free_reply(r, 0); +} + /* Generic MULTI BULK response processor */ PHPAPI void cluster_gen_mbulk_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, mbulk_cb cb, void *ctx) |