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

Skip to content

Commit 2a0d1c1

Browse files
yatsukhnenkomichael-grunder
authored andcommitted
Refactor PubSub command
1 parent cc2383f commit 2a0d1c1

6 files changed

Lines changed: 105 additions & 113 deletions

File tree

library.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,22 @@ redis_sock_read_scan_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
455455
}
456456
}
457457

458+
PHP_REDIS_API int
459+
redis_pubsub_response(INTERNAL_FUNCTION_PARAMETERS,
460+
RedisSock *redis_sock, zval *z_tab, void *ctx)
461+
{
462+
if (ctx == NULL) {
463+
return redis_long_response(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, NULL);
464+
} else if (ctx == PHPREDIS_CTX_PTR) {
465+
return redis_read_variant_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, NULL);
466+
} else if (ctx == PHPREDIS_CTX_PTR + 1) {
467+
return redis_mbulk_reply_zipped_keys_int(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, NULL);
468+
} else {
469+
ZEND_ASSERT(!"memory corruption?");
470+
return FAILURE;
471+
}
472+
}
473+
458474
static void
459475
ht_free_subs(zval *data)
460476
{
@@ -1354,6 +1370,7 @@ redis_zrandmember_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
13541370
return redis_mbulk_reply_zipped_keys_dbl(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, NULL);
13551371
} else {
13561372
ZEND_ASSERT(!"memory corruption?");
1373+
return FAILURE;
13571374
}
13581375
}
13591376

@@ -1366,6 +1383,7 @@ redis_zdiff_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *
13661383
return redis_mbulk_reply_zipped_keys_dbl(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, NULL);
13671384
} else {
13681385
ZEND_ASSERT(!"memory corruption?");
1386+
return FAILURE;
13691387
}
13701388
}
13711389

@@ -1378,6 +1396,7 @@ redis_set_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_
13781396
return redis_string_response(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, NULL);
13791397
} else {
13801398
ZEND_ASSERT(!"memory corruption?");
1399+
return FAILURE;
13811400
}
13821401
}
13831402

@@ -1392,6 +1411,7 @@ redis_hrandfield_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, z
13921411
return redis_mbulk_reply_zipped_raw(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, NULL);
13931412
} else {
13941413
ZEND_ASSERT(!"memory corruption?");
1414+
return FAILURE;
13951415
}
13961416
}
13971417

@@ -1404,6 +1424,7 @@ redis_pop_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_
14041424
return redis_mbulk_reply_raw(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, NULL);
14051425
} else {
14061426
ZEND_ASSERT(!"memory corruption?");
1427+
return FAILURE;
14071428
}
14081429
}
14091430

@@ -1447,6 +1468,7 @@ redis_lpos_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z
14471468
}
14481469
} else {
14491470
ZEND_ASSERT(!"memory corruption?");
1471+
return FAILURE;
14501472
}
14511473

14521474
if (IS_ATOMIC(redis_sock)) {

library.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ PHP_REDIS_API int redis_xclaim_reply(INTERNAL_FUNCTION_PARAMETERS,
109109
PHP_REDIS_API int redis_xinfo_reply(INTERNAL_FUNCTION_PARAMETERS,
110110
RedisSock *redis_sock, zval *z_tab, void *ctx);
111111

112+
PHP_REDIS_API int redis_pubsub_response(INTERNAL_FUNCTION_PARAMETERS,
113+
RedisSock *redis_sock, zval *z_tab, void *ctx);
112114
PHP_REDIS_API int redis_subscribe_response(INTERNAL_FUNCTION_PARAMETERS,
113115
RedisSock *redis_sock, zval *z_tab, void *ctx);
114116
PHP_REDIS_API int redis_unsubscribe_response(INTERNAL_FUNCTION_PARAMETERS,

redis.c

Lines changed: 1 addition & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -2707,122 +2707,13 @@ PHP_METHOD(Redis, wait) {
27072707
REDIS_PROCESS_RESPONSE(redis_long_response);
27082708
}
27092709

2710-
/* Construct a PUBSUB command */
2711-
PHP_REDIS_API int
2712-
redis_build_pubsub_cmd(RedisSock *redis_sock, char **ret, PUBSUB_TYPE type,
2713-
zval *arg)
2714-
{
2715-
HashTable *ht_chan;
2716-
zval *z_ele;
2717-
smart_string cmd = {0};
2718-
2719-
if (type == PUBSUB_CHANNELS) {
2720-
if (arg) {
2721-
/* With a pattern */
2722-
return REDIS_SPPRINTF(ret, "PUBSUB", "sk", "CHANNELS", sizeof("CHANNELS") - 1,
2723-
Z_STRVAL_P(arg), Z_STRLEN_P(arg));
2724-
} else {
2725-
/* No pattern */
2726-
return REDIS_SPPRINTF(ret, "PUBSUB", "s", "CHANNELS", sizeof("CHANNELS") - 1);
2727-
}
2728-
} else if (type == PUBSUB_NUMSUB) {
2729-
ht_chan = Z_ARRVAL_P(arg);
2730-
2731-
// Add PUBSUB and NUMSUB bits
2732-
redis_cmd_init_sstr(&cmd, zend_hash_num_elements(ht_chan)+1, "PUBSUB", sizeof("PUBSUB")-1);
2733-
redis_cmd_append_sstr(&cmd, "NUMSUB", sizeof("NUMSUB")-1);
2734-
2735-
/* Iterate our elements */
2736-
ZEND_HASH_FOREACH_VAL(ht_chan, z_ele) {
2737-
zend_string *zstr = zval_get_string(z_ele);
2738-
redis_cmd_append_sstr_key(&cmd, ZSTR_VAL(zstr), ZSTR_LEN(zstr), redis_sock, NULL);
2739-
zend_string_release(zstr);
2740-
} ZEND_HASH_FOREACH_END();
2741-
2742-
/* Set return */
2743-
*ret = cmd.c;
2744-
return cmd.len;
2745-
} else if (type == PUBSUB_NUMPAT) {
2746-
return REDIS_SPPRINTF(ret, "PUBSUB", "s", "NUMPAT", sizeof("NUMPAT") - 1);
2747-
}
2748-
2749-
/* Shouldn't ever happen */
2750-
return -1;
2751-
}
2752-
27532710
/*
27542711
* {{{ proto Redis::pubsub("channels", pattern);
27552712
* proto Redis::pubsub("numsub", Array channels);
27562713
* proto Redis::pubsub("numpat"); }}}
27572714
*/
27582715
PHP_METHOD(Redis, pubsub) {
2759-
zval *object;
2760-
RedisSock *redis_sock;
2761-
char *keyword, *cmd;
2762-
int cmd_len;
2763-
size_t kw_len;
2764-
PUBSUB_TYPE type;
2765-
zval *arg = NULL;
2766-
2767-
// Parse arguments
2768-
if(zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
2769-
"Os|z", &object, redis_ce, &keyword,
2770-
&kw_len, &arg)==FAILURE)
2771-
{
2772-
RETURN_FALSE;
2773-
}
2774-
2775-
/* Validate our sub command keyword, and that we've got proper arguments */
2776-
if(!strncasecmp(keyword, "channels", sizeof("channels"))) {
2777-
/* One (optional) string argument */
2778-
if(arg && Z_TYPE_P(arg) != IS_STRING) {
2779-
RETURN_FALSE;
2780-
}
2781-
type = PUBSUB_CHANNELS;
2782-
} else if(!strncasecmp(keyword, "numsub", sizeof("numsub"))) {
2783-
/* One array argument */
2784-
if(ZEND_NUM_ARGS() < 2 || Z_TYPE_P(arg) != IS_ARRAY ||
2785-
zend_hash_num_elements(Z_ARRVAL_P(arg)) == 0)
2786-
{
2787-
RETURN_FALSE;
2788-
}
2789-
type = PUBSUB_NUMSUB;
2790-
} else if(!strncasecmp(keyword, "numpat", sizeof("numpat"))) {
2791-
type = PUBSUB_NUMPAT;
2792-
} else {
2793-
/* Invalid keyword */
2794-
RETURN_FALSE;
2795-
}
2796-
2797-
/* Grab our socket context object */
2798-
if ((redis_sock = redis_sock_get(object, 0)) == NULL) {
2799-
RETURN_FALSE;
2800-
}
2801-
2802-
/* Construct our "PUBSUB" command */
2803-
cmd_len = redis_build_pubsub_cmd(redis_sock, &cmd, type, arg);
2804-
2805-
REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len);
2806-
2807-
if(type == PUBSUB_NUMSUB) {
2808-
if (IS_ATOMIC(redis_sock)) {
2809-
if(redis_mbulk_reply_zipped_keys_int(INTERNAL_FUNCTION_PARAM_PASSTHRU,
2810-
redis_sock, NULL, NULL) < 0)
2811-
{
2812-
RETURN_FALSE;
2813-
}
2814-
}
2815-
REDIS_PROCESS_RESPONSE(redis_mbulk_reply_zipped_keys_int);
2816-
} else {
2817-
if (IS_ATOMIC(redis_sock)) {
2818-
if(redis_read_variant_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU,
2819-
redis_sock, NULL, NULL) < 0)
2820-
{
2821-
RETURN_FALSE;
2822-
}
2823-
}
2824-
REDIS_PROCESS_RESPONSE(redis_read_variant_reply);
2825-
}
2716+
REDIS_PROCESS_CMD(pubsub, redis_pubsub_response);
28262717
}
28272718

28282719
/* {{{ proto variant Redis::eval(string script, [array keys, long num_keys]) */

redis_commands.c

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1373,7 +1373,81 @@ redis_zinterunionstore_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
13731373
return SUCCESS;
13741374
}
13751375

1376-
/* SUBSCRIBE/PSUBSCRIBE */
1376+
int redis_pubsub_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
1377+
char **cmd, int *cmd_len, short *slot, void **ctx)
1378+
{
1379+
HashTable *channels = NULL;
1380+
smart_string cmdstr = {0};
1381+
zend_string *op, *pattern = NULL;
1382+
zval *arg = NULL, *z_chan;
1383+
1384+
ZEND_PARSE_PARAMETERS_START(1, 2)
1385+
Z_PARAM_STR(op)
1386+
Z_PARAM_OPTIONAL
1387+
Z_PARAM_ZVAL(arg)
1388+
ZEND_PARSE_PARAMETERS_END_EX(return FAILURE);
1389+
1390+
if (zend_string_equals_literal_ci(op, "NUMPAT")) {
1391+
*ctx = NULL;
1392+
} else if (zend_string_equals_literal_ci(op, "CHANNELS") ||
1393+
zend_string_equals_literal_ci(op, "SHARDCHANNELS")
1394+
) {
1395+
if (arg != NULL) {
1396+
if (Z_TYPE_P(arg) != IS_STRING) {
1397+
php_error_docref(NULL, E_WARNING, "Invalid patern value");
1398+
return FAILURE;
1399+
}
1400+
pattern = zval_get_string(arg);
1401+
}
1402+
*ctx = PHPREDIS_CTX_PTR;
1403+
} else if (zend_string_equals_literal_ci(op, "NUMSUB") ||
1404+
zend_string_equals_literal_ci(op, "SHARDNUMSUB")
1405+
) {
1406+
if (arg != NULL) {
1407+
if (Z_TYPE_P(arg) != IS_ARRAY) {
1408+
php_error_docref(NULL, E_WARNING, "Invalid channels value");
1409+
return FAILURE;
1410+
}
1411+
channels = Z_ARRVAL_P(arg);
1412+
}
1413+
*ctx = PHPREDIS_CTX_PTR + 1;
1414+
} else {
1415+
php_error_docref(NULL, E_WARNING, "Unknown PUBSUB operation '%s'", ZSTR_VAL(op));
1416+
return FAILURE;
1417+
}
1418+
1419+
REDIS_CMD_INIT_SSTR_STATIC(&cmdstr, 1 + !!pattern + (channels ? zend_hash_num_elements(channels) : 0), "PUBSUB");
1420+
redis_cmd_append_sstr_zstr(&cmdstr, op);
1421+
1422+
if (pattern != NULL) {
1423+
redis_cmd_append_sstr_zstr(&cmdstr, pattern);
1424+
zend_string_release(pattern);
1425+
} else if (channels != NULL) {
1426+
ZEND_HASH_FOREACH_VAL(channels, z_chan) {
1427+
// We want to deal with strings here
1428+
zend_string *zstr = zval_get_string(z_chan);
1429+
1430+
// Grab channel name, prefix if required
1431+
char *key = ZSTR_VAL(zstr);
1432+
size_t key_len = ZSTR_LEN(zstr);
1433+
int key_free = redis_key_prefix(redis_sock, &key, &key_len);
1434+
1435+
// Add this channel
1436+
redis_cmd_append_sstr(&cmdstr, key, key_len);
1437+
1438+
zend_string_release(zstr);
1439+
// Free our key if it was prefixed
1440+
if (key_free) efree(key);
1441+
} ZEND_HASH_FOREACH_END();
1442+
}
1443+
1444+
*cmd = cmdstr.c;
1445+
*cmd_len = cmdstr.len;
1446+
1447+
return SUCCESS;
1448+
}
1449+
1450+
/* SUBSCRIBE/PSUBSCRIBE/SSUBSCRIBE */
13771451
int redis_subscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
13781452
char *kw, char **cmd, int *cmd_len, short *slot,
13791453
void **ctx)

redis_commands.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ int redis_mpop_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw
139139
int redis_restore_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
140140
char **cmd, int *cmd_len, short *slot, void **ctx);
141141

142+
int redis_pubsub_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
143+
char **cmd, int *cmd_len, short *slot, void **ctx);
144+
142145
int redis_subscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
143146
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
144147

tests/RedisTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,8 @@ public function testPubSub() {
202202
$this->assertTrue(is_int($result));
203203

204204
// Invalid calls
205-
$this->assertFalse($this->redis->pubsub("notacommand"));
206-
$this->assertFalse($this->redis->pubsub("numsub", "not-an-array"));
205+
$this->assertFalse(@$this->redis->pubsub("notacommand"));
206+
$this->assertFalse(@$this->redis->pubsub("numsub", "not-an-array"));
207207
}
208208

209209
/* These test cases were generated randomly. We're just trying to test

0 commit comments

Comments
 (0)