Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a8d1029

Browse files
committed
Redis::client command
1 parent 8d99181 commit a8d1029

9 files changed

Lines changed: 565 additions & 94 deletions

File tree

library.c

Lines changed: 118 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,6 +1196,67 @@ redis_parse_info_response(char *response, zval *z_ret)
11961196
}
11971197
}
11981198

1199+
static void
1200+
redis_parse_client_info(char *info, zval *z_ret)
1201+
{
1202+
char *p1, *s1 = NULL;
1203+
1204+
ZVAL_FALSE(z_ret);
1205+
if ((p1 = php_strtok_r(info, " ", &s1)) != NULL) {
1206+
array_init(z_ret);
1207+
do {
1208+
char *p;
1209+
zend_uchar type;
1210+
zend_long lval;
1211+
double dval;
1212+
if ((p = strchr(p1, '=')) != NULL) {
1213+
type = is_numeric_string(p + 1, strlen(p + 1), &lval, &dval, 0);
1214+
switch (type) {
1215+
case IS_LONG:
1216+
add_assoc_long_ex(z_ret, p1, p - p1, lval);
1217+
break;
1218+
case IS_DOUBLE:
1219+
add_assoc_double_ex(z_ret, p1, p - p1, dval);
1220+
break;
1221+
default:
1222+
add_assoc_string_ex(z_ret, p1, p - p1, p + 1);
1223+
}
1224+
} else {
1225+
add_next_index_string(z_ret, p1);
1226+
}
1227+
} while ((p1 = php_strtok_r(NULL, " ", &s1)) != NULL);
1228+
}
1229+
}
1230+
1231+
static int
1232+
redis_client_info_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx)
1233+
{
1234+
char *resp;
1235+
int resp_len;
1236+
zval z_ret;
1237+
1238+
/* Make sure we can read the bulk response from Redis */
1239+
if ((resp = redis_sock_read(redis_sock, &resp_len)) == NULL) {
1240+
RETVAL_FALSE;
1241+
return FAILURE;
1242+
}
1243+
1244+
/* Parse it out */
1245+
redis_parse_client_info(resp, &z_ret);
1246+
1247+
/* Free our response */
1248+
efree(resp);
1249+
1250+
/* Return or append depending if we're atomic */
1251+
if (IS_ATOMIC(redis_sock)) {
1252+
RETVAL_ZVAL(&z_ret, 0, 1);
1253+
} else {
1254+
add_next_index_zval(z_tab, &z_ret);
1255+
}
1256+
1257+
return SUCCESS;
1258+
}
1259+
11991260
/*
12001261
* Specialized handling of the CLIENT LIST output so it comes out in a simple way for PHP userland code
12011262
* to handle.
@@ -1210,11 +1271,13 @@ redis_client_list_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zva
12101271
if ((resp = redis_sock_read(redis_sock, &resp_len)) == NULL) {
12111272
RETVAL_FALSE;
12121273
return FAILURE;
1274+
} else if (resp_len > 0) {
1275+
/* Parse it out */
1276+
redis_parse_client_list_response(resp, &z_ret);
1277+
} else {
1278+
array_init(&z_ret);
12131279
}
12141280

1215-
/* Parse it out */
1216-
redis_parse_client_list_response(resp, &z_ret);
1217-
12181281
/* Free our response */
12191282
efree(resp);
12201283

@@ -1231,42 +1294,16 @@ redis_client_list_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zva
12311294
PHP_REDIS_API void
12321295
redis_parse_client_list_response(char *response, zval *z_ret)
12331296
{
1234-
char *p1, *s1 = NULL;
1297+
char *p, *s = NULL;
12351298

12361299
ZVAL_FALSE(z_ret);
1237-
if ((p1 = php_strtok_r(response, _NL, &s1)) != NULL) {
1300+
if ((p = php_strtok_r(response, _NL, &s)) != NULL) {
12381301
array_init(z_ret);
12391302
do {
1240-
char *p2, *s2 = NULL;
12411303
zval z_sub;
1242-
1243-
ZVAL_FALSE(&z_sub);
1244-
if ((p2 = php_strtok_r(p1, " ", &s2)) != NULL) {
1245-
array_init(&z_sub);
1246-
do {
1247-
char *p;
1248-
zend_uchar type;
1249-
zend_long lval;
1250-
double dval;
1251-
if ((p = strchr(p2, '=')) != NULL) {
1252-
type = is_numeric_string(p + 1, strlen(p + 1), &lval, &dval, 0);
1253-
switch (type) {
1254-
case IS_LONG:
1255-
add_assoc_long_ex(&z_sub, p2, p - p2, lval);
1256-
break;
1257-
case IS_DOUBLE:
1258-
add_assoc_double_ex(&z_sub, p2, p - p2, dval);
1259-
break;
1260-
default:
1261-
add_assoc_string_ex(&z_sub, p2, p - p2, p + 1);
1262-
}
1263-
} else {
1264-
add_next_index_string(&z_sub, p2);
1265-
}
1266-
} while ((p2 = php_strtok_r(NULL, " ", &s2)) != NULL);
1267-
}
1304+
redis_parse_client_info(p, &z_sub);
12681305
add_next_index_zval(z_ret, &z_sub);
1269-
} while ((p1 = php_strtok_r(NULL, _NL, &s1)) != NULL);
1306+
} while ((p = php_strtok_r(NULL, _NL, &s)) != NULL);
12701307
}
12711308
}
12721309

@@ -1629,6 +1666,54 @@ redis_geosearch_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
16291666
return SUCCESS;
16301667
}
16311668

1669+
static int
1670+
redis_client_trackinginfo_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx)
1671+
{
1672+
int numElems;
1673+
zval z_ret;
1674+
1675+
if (read_mbulk_header(redis_sock, &numElems) < 0) {
1676+
if (IS_ATOMIC(redis_sock)) {
1677+
RETVAL_FALSE;
1678+
} else {
1679+
add_next_index_bool(z_tab, 0);
1680+
}
1681+
return FAILURE;
1682+
}
1683+
1684+
array_init(&z_ret);
1685+
redis_read_multibulk_recursive(redis_sock, numElems, 0, &z_ret);
1686+
array_zip_values_and_scores(redis_sock, &z_ret, 0);
1687+
1688+
if (IS_ATOMIC(redis_sock)) {
1689+
RETVAL_ZVAL(&z_ret, 0, 1);
1690+
} else {
1691+
add_next_index_zval(z_tab, &z_ret);
1692+
}
1693+
1694+
return SUCCESS;
1695+
}
1696+
1697+
PHP_REDIS_API int
1698+
redis_client_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx)
1699+
{
1700+
if (ctx == NULL) {
1701+
return redis_client_info_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, NULL);
1702+
} else if (ctx == PHPREDIS_CTX_PTR) {
1703+
return redis_client_list_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, NULL);
1704+
} else if (ctx == PHPREDIS_CTX_PTR + 1) {
1705+
return redis_boolean_response(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, NULL);
1706+
} else if (ctx == PHPREDIS_CTX_PTR + 2) {
1707+
return redis_long_response(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, NULL);
1708+
} else if (ctx == PHPREDIS_CTX_PTR + 3) {
1709+
return redis_string_response(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, NULL);
1710+
} else if (ctx == PHPREDIS_CTX_PTR + 4) {
1711+
return redis_client_trackinginfo_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, NULL);
1712+
} else {
1713+
ZEND_ASSERT(!"memory corruption?");
1714+
}
1715+
}
1716+
16321717
/* Helper function to consume Redis stream message data. This is useful for
16331718
* multiple stream callers (e.g. XREAD[GROUP], and X[REV]RANGE handlers). */
16341719
PHP_REDIS_API int

library.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ PHP_REDIS_API int redis_geosearch_response(INTERNAL_FUNCTION_PARAMETERS, RedisSo
169169
PHP_REDIS_API int redis_hrandfield_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
170170
PHP_REDIS_API int redis_pop_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
171171
PHP_REDIS_API int redis_lpos_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
172+
PHP_REDIS_API int redis_client_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
172173

173174
/* Helper methods to get configuration values from a HashTable. */
174175

redis.c

Lines changed: 3 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -3286,62 +3286,11 @@ PHP_METHOD(Redis, getAuth) {
32863286
}
32873287
}
32883288

3289-
/*
3290-
* $redis->client('list');
3291-
* $redis->client('info');
3292-
* $redis->client('kill', <ip:port>);
3293-
* $redis->client('setname', <name>);
3294-
* $redis->client('getname');
3295-
*/
3289+
/* {{{ proto mixed Redis::client(string $command, [ $arg1 ... $argN]) */
32963290
PHP_METHOD(Redis, client) {
3297-
zval *object;
3298-
RedisSock *redis_sock;
3299-
char *cmd, *opt = NULL, *arg = NULL;
3300-
size_t opt_len, arg_len;
3301-
int cmd_len;
3302-
3303-
// Parse our method parameters
3304-
if(zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
3305-
"Os|s", &object, redis_ce, &opt, &opt_len,
3306-
&arg, &arg_len) == FAILURE)
3307-
{
3308-
RETURN_FALSE;
3309-
}
3310-
3311-
/* Grab our socket */
3312-
if ((redis_sock = redis_sock_get(object, 0)) == NULL) {
3313-
RETURN_FALSE;
3314-
}
3315-
3316-
/* Build our CLIENT command */
3317-
if (ZEND_NUM_ARGS() == 2) {
3318-
cmd_len = REDIS_SPPRINTF(&cmd, "CLIENT", "ss", opt, opt_len, arg, arg_len);
3319-
} else {
3320-
cmd_len = REDIS_SPPRINTF(&cmd, "CLIENT", "s", opt, opt_len);
3321-
}
3322-
3323-
/* Execute our queue command */
3324-
REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len);
3325-
3326-
/* We handle CLIENT LIST with a custom response function */
3327-
if(!strncasecmp(opt, "list", 4)) {
3328-
if (IS_ATOMIC(redis_sock)) {
3329-
redis_client_list_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU,redis_sock, NULL, NULL);
3330-
}
3331-
REDIS_PROCESS_RESPONSE(redis_client_list_reply);
3332-
} else if (!strncasecmp(opt, "info", 4)) {
3333-
if (IS_ATOMIC(redis_sock)) {
3334-
redis_string_response(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL, NULL);
3335-
}
3336-
REDIS_PROCESS_RESPONSE(redis_string_response);
3337-
} else {
3338-
if (IS_ATOMIC(redis_sock)) {
3339-
redis_read_variant_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU,
3340-
redis_sock,NULL,NULL);
3341-
}
3342-
REDIS_PROCESS_RESPONSE(redis_read_variant_reply);
3343-
}
3291+
REDIS_PROCESS_CMD(client, redis_client_response);
33443292
}
3293+
/* }}} */
33453294

33463295
/* {{{ proto mixed Redis::rawcommand(string $command, [ $arg1 ... $argN]) */
33473296
PHP_METHOD(Redis, rawcommand) {

redis.stub.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public function bzPopMin(string|array $key, string|int $timeout_or_key, mixed ..
6464

6565
public function clearLastError(): bool;
6666

67-
public function client(string $opt, string $arg = null): mixed;
67+
public function client(string $opt, mixed ...$args): mixed;
6868

6969
public function close(): bool;
7070

redis_arginfo.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: 7fc0b991dc8404945a0081aef8a422c9c670eab9 */
2+
* Stub hash: 8d3ef188b058066309394ffaaf00489572d7b629 */
33

44
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis___construct, 0, 0, 0)
55
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 0, "null")
@@ -91,7 +91,7 @@ ZEND_END_ARG_INFO()
9191

9292
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Redis_client, 0, 1, IS_MIXED, 0)
9393
ZEND_ARG_TYPE_INFO(0, opt, IS_STRING, 0)
94-
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, arg, IS_STRING, 0, "null")
94+
ZEND_ARG_VARIADIC_TYPE_INFO(0, args, IS_MIXED, 0)
9595
ZEND_END_ARG_INFO()
9696

9797
#define arginfo_class_Redis_close arginfo_class_Redis_bgSave

0 commit comments

Comments
 (0)