diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | php_redis.h | 4 | ||||
-rw-r--r-- | redis.c | 46 | ||||
-rw-r--r-- | redis_cluster.c | 42 | ||||
-rw-r--r-- | redis_cluster.h | 4 | ||||
-rw-r--r-- | redis_commands.c | 25 | ||||
-rw-r--r-- | redis_commands.h | 9 | ||||
-rw-r--r-- | tests/RedisTest.php | 45 |
8 files changed, 150 insertions, 26 deletions
@@ -16,3 +16,4 @@ mkinstalldirs run-tests.php idea/* .cquery +tags diff --git a/php_redis.h b/php_redis.h index 8dc2f5c6..d6240ec1 100644 --- a/php_redis.h +++ b/php_redis.h @@ -131,6 +131,10 @@ PHP_METHOD(Redis, zRevRank); PHP_METHOD(Redis, zIncrBy); PHP_METHOD(Redis, zInter); PHP_METHOD(Redis, zUnion); +PHP_METHOD(Redis, zPopMax); +PHP_METHOD(Redis, zPopMin); +PHP_METHOD(Redis, bzPopMax); +PHP_METHOD(Redis, bzPopMin); PHP_METHOD(Redis, expireAt); PHP_METHOD(Redis, pexpireAt); PHP_METHOD(Redis, bgrewriteaof); @@ -259,6 +259,8 @@ static zend_function_entry redis_functions[] = { PHP_ME(Redis, blPop, arginfo_blrpop, ZEND_ACC_PUBLIC) PHP_ME(Redis, brPop, arginfo_blrpop, ZEND_ACC_PUBLIC) PHP_ME(Redis, brpoplpush, arginfo_brpoplpush, ZEND_ACC_PUBLIC) + PHP_ME(Redis, bzPopMax, arginfo_blrpop, ZEND_ACC_PUBLIC) + PHP_ME(Redis, bzPopMin, arginfo_blrpop, ZEND_ACC_PUBLIC) PHP_ME(Redis, clearLastError, arginfo_void, ZEND_ACC_PUBLIC) PHP_ME(Redis, client, arginfo_client, ZEND_ACC_PUBLIC) PHP_ME(Redis, close, arginfo_void, ZEND_ACC_PUBLIC) @@ -445,6 +447,8 @@ static zend_function_entry redis_functions[] = { PHP_ME(Redis, zScore, arginfo_key_member, ZEND_ACC_PUBLIC) PHP_ME(Redis, zUnion, arginfo_zstore, ZEND_ACC_PUBLIC) PHP_ME(Redis, zscan, arginfo_kscan, ZEND_ACC_PUBLIC) + PHP_ME(Redis, zPopMax, arginfo_key, ZEND_ACC_PUBLIC) + PHP_ME(Redis, zPopMin, arginfo_key, ZEND_ACC_PUBLIC) PHP_MALIAS(Redis, del, delete, arginfo_del, ZEND_ACC_PUBLIC) PHP_MALIAS(Redis, evaluate, eval, arginfo_eval, ZEND_ACC_PUBLIC) PHP_MALIAS(Redis, evaluateSha, evalsha, arginfo_evalsha, ZEND_ACC_PUBLIC) @@ -1311,14 +1315,14 @@ PHP_METHOD(Redis, rPop) /* {{{ proto string Redis::blPop(string key1, string key2, ..., int timeout) */ PHP_METHOD(Redis, blPop) { - REDIS_PROCESS_CMD(blpop, redis_sock_read_multibulk_reply); + REDIS_PROCESS_KW_CMD("BLPOP", redis_blocking_pop_cmd, redis_sock_read_multibulk_reply); } /* }}} */ /* {{{ proto string Redis::brPop(string key1, string key2, ..., int timeout) */ PHP_METHOD(Redis, brPop) { - REDIS_PROCESS_CMD(brpop, redis_sock_read_multibulk_reply); + REDIS_PROCESS_KW_CMD("BRPOP", redis_blocking_pop_cmd, redis_sock_read_multibulk_reply); } /* }}} */ @@ -2075,6 +2079,44 @@ PHP_METHOD(Redis, zUnion) { REDIS_PROCESS_KW_CMD("ZUNIONSTORE", redis_zinter_cmd, redis_long_response); } +/* {{{ proto array Redis::zPopMax(string key) */ +PHP_METHOD(Redis, zPopMax) +{ + if (ZEND_NUM_ARGS() == 1) { + REDIS_PROCESS_KW_CMD("ZPOPMAX", redis_key_cmd, redis_mbulk_reply_zipped_keys_dbl); + } else if (ZEND_NUM_ARGS() == 2) { + REDIS_PROCESS_KW_CMD("ZPOPMAX", redis_key_long_cmd, redis_mbulk_reply_zipped_keys_dbl); + } else { + ZEND_WRONG_PARAM_COUNT(); + } +} +/* }}} */ + +/* {{{ proto array Redis::zPopMin(string key) */ +PHP_METHOD(Redis, zPopMin) +{ + if (ZEND_NUM_ARGS() == 1) { + REDIS_PROCESS_KW_CMD("ZPOPMIN", redis_key_cmd, redis_mbulk_reply_zipped_keys_dbl); + } else if (ZEND_NUM_ARGS() == 2) { + REDIS_PROCESS_KW_CMD("ZPOPMIN", redis_key_long_cmd, redis_mbulk_reply_zipped_keys_dbl); + } else { + ZEND_WRONG_PARAM_COUNT(); + } +} +/* }}} */ + +/* {{{ proto Redis::bzPopMax(Array(keys) [, timeout]): Array */ +PHP_METHOD(Redis, bzPopMax) { + REDIS_PROCESS_KW_CMD("BZPOPMAX", redis_blocking_pop_cmd, redis_sock_read_multibulk_reply); +} +/* }}} */ + +/* {{{ proto Redis::bzPopMin(Array(keys) [, timeout]): Array */ +PHP_METHOD(Redis, bzPopMin) { + REDIS_PROCESS_KW_CMD("BZPOPMIN", redis_blocking_pop_cmd, redis_sock_read_multibulk_reply); +} +/* }}} */ + /* hashes */ /* {{{ proto long Redis::hset(string key, string mem, string val) */ diff --git a/redis_cluster.c b/redis_cluster.c index 75f4b6ef..4de9d6c3 100644 --- a/redis_cluster.c +++ b/redis_cluster.c @@ -124,6 +124,8 @@ zend_function_entry redis_cluster_functions[] = { PHP_ME(RedisCluster, brpop, arginfo_blrpop, ZEND_ACC_PUBLIC) PHP_ME(RedisCluster, brpoplpush, arginfo_brpoplpush, ZEND_ACC_PUBLIC) PHP_ME(RedisCluster, clearlasterror, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(RedisCluster, bzpopmax, arginfo_blrpop, ZEND_ACC_PUBLIC) + PHP_ME(RedisCluster, bzpopmin, arginfo_blrpop, ZEND_ACC_PUBLIC) PHP_ME(RedisCluster, client, arginfo_key_or_address_variadic, ZEND_ACC_PUBLIC) PHP_ME(RedisCluster, close, arginfo_void, ZEND_ACC_PUBLIC) PHP_ME(RedisCluster, cluster, arginfo_key_or_address_variadic, ZEND_ACC_PUBLIC) @@ -274,6 +276,8 @@ zend_function_entry redis_cluster_functions[] = { PHP_ME(RedisCluster, zincrby, arginfo_zincrby, ZEND_ACC_PUBLIC) PHP_ME(RedisCluster, zinterstore, arginfo_zstore, ZEND_ACC_PUBLIC) PHP_ME(RedisCluster, zlexcount, arginfo_key_min_max, ZEND_ACC_PUBLIC) + PHP_ME(RedisCluster, zpopmax, arginfo_key, ZEND_ACC_PUBLIC) + PHP_ME(RedisCluster, zpopmin, arginfo_key, ZEND_ACC_PUBLIC) PHP_ME(RedisCluster, zrange, arginfo_zrange, ZEND_ACC_PUBLIC) PHP_ME(RedisCluster, zrangebylex, arginfo_zrangebylex, ZEND_ACC_PUBLIC) PHP_ME(RedisCluster, zrangebyscore, arginfo_zrangebyscore, ZEND_ACC_PUBLIC) @@ -1162,13 +1166,13 @@ PHP_METHOD(RedisCluster, rpush) { /* {{{ proto array RedisCluster::blpop(string key1, ... keyN, long timeout) */ PHP_METHOD(RedisCluster, blpop) { - CLUSTER_PROCESS_CMD(blpop, cluster_mbulk_resp, 0); + CLUSTER_PROCESS_KW_CMD("BLPOP", redis_blocking_pop_cmd, cluster_mbulk_resp, 0); } /* }}} */ /* {{{ proto array RedisCluster::brpop(string key1, ... keyN, long timeout */ PHP_METHOD(RedisCluster, brpop) { - CLUSTER_PROCESS_CMD(brpop, cluster_mbulk_resp, 0); + CLUSTER_PROCESS_KW_CMD("BRPOP", redis_blocking_pop_cmd, cluster_mbulk_resp, 0); } /* }}} */ @@ -1751,6 +1755,40 @@ PHP_METHOD(RedisCluster, zremrangebylex) { } /* }}} */ +/* {{{ proto array RedisCluster::zpopmax(string key) */ +PHP_METHOD(RedisCluster, zpopmax) { + if (ZEND_NUM_ARGS() == 1) { + CLUSTER_PROCESS_KW_CMD("ZPOPMAX", redis_key_cmd, cluster_mbulk_zipdbl_resp, 0); + } else if (ZEND_NUM_ARGS() == 2) { + CLUSTER_PROCESS_KW_CMD("ZPOPMAX", redis_key_long_cmd, cluster_mbulk_zipdbl_resp, 0); + } else { + ZEND_WRONG_PARAM_COUNT(); + } +} +/* }}} */ + +/* {{{ proto array RedisCluster::zpopmin(string key) */ +PHP_METHOD(RedisCluster, zpopmin) { + if (ZEND_NUM_ARGS() == 1) { + CLUSTER_PROCESS_KW_CMD("ZPOPMIN", redis_key_cmd, cluster_mbulk_zipdbl_resp, 0); + } else if (ZEND_NUM_ARGS() == 2) { + CLUSTER_PROCESS_KW_CMD("ZPOPMIN", redis_key_long_cmd, cluster_mbulk_zipdbl_resp, 0); + } else { + ZEND_WRONG_PARAM_COUNT(); + } +} +/* }}} */ + +/* {{{ proto array RedisCluster::bzPopMin(Array keys [, timeout]) }}} */ +PHP_METHOD(RedisCluster, bzpopmax) { + CLUSTER_PROCESS_KW_CMD("BZPOPMAX", redis_blocking_pop_cmd, cluster_mbulk_resp, 0); +} + +/* {{{ proto array RedisCluster::bzPopMax(Array keys [, timeout]) }}} */ +PHP_METHOD(RedisCluster, bzpopmin) { + CLUSTER_PROCESS_KW_CMD("BZPOPMIN", redis_blocking_pop_cmd, cluster_mbulk_resp, 0); +} + /* {{{ proto RedisCluster::sort(string key, array options) */ PHP_METHOD(RedisCluster, sort) { redisCluster *c = GET_CONTEXT(); diff --git a/redis_cluster.h b/redis_cluster.h index c8c40ff1..ca76ac8a 100644 --- a/redis_cluster.h +++ b/redis_cluster.h @@ -213,6 +213,10 @@ PHP_METHOD(RedisCluster, restore); PHP_METHOD(RedisCluster, setrange); PHP_METHOD(RedisCluster, smove); PHP_METHOD(RedisCluster, srandmember); +PHP_METHOD(RedisCluster, zpopmin); +PHP_METHOD(RedisCluster, zpopmax); +PHP_METHOD(RedisCluster, bzpopmax); +PHP_METHOD(RedisCluster, bzpopmin); PHP_METHOD(RedisCluster, zrange); PHP_METHOD(RedisCluster, zrevrange); PHP_METHOD(RedisCluster, zrangebyscore); diff --git a/redis_commands.c b/redis_commands.c index 2ad7e212..3c127b82 100644 --- a/redis_commands.c +++ b/redis_commands.c @@ -1251,6 +1251,15 @@ static int gen_varkey_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, return SUCCESS; } +/* Generic handling of every blocking pop command (BLPOP, BZPOP[MIN/MAX], etc */ +int redis_blocking_pop_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, + char *kw, char **cmd, int *cmd_len, short *slot, + void **ctx) +{ + return gen_varkey_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, kw, + strlen(kw), 2, 2, cmd, cmd_len, slot); +} + /* * Commands with specific signatures or that need unique functions because they * have specific processing (argument validation, etc) that make them unique @@ -3044,22 +3053,6 @@ int redis_watch_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, "WATCH", sizeof("WATCH")-1, 1, 0, cmd, cmd_len, slot); } -/* BLPOP */ -int redis_blpop_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, - char **cmd, int *cmd_len, short *slot, void **ctx) -{ - return gen_varkey_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, - "BLPOP", sizeof("BLPOP")-1, 2, 1, cmd, cmd_len, slot); -} - -/* BRPOP */ -int redis_brpop_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, - char **cmd, int *cmd_len, short *slot, void **ctx) -{ - return gen_varkey_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, - "BRPOP", sizeof("BRPOP")-1, 1, 1, cmd, cmd_len, slot); -} - /* SINTER */ int redis_sinter_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char **cmd, int *cmd_len, short *slot, void **ctx) diff --git a/redis_commands.h b/redis_commands.h index 1ef1712c..9a9c777d 100644 --- a/redis_commands.h +++ b/redis_commands.h @@ -78,6 +78,9 @@ int redis_key_val_arr_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, int redis_key_str_arr_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char *kw, char **cmd, int *cmd_len, short *slot, void **ctx); +int redis_blocking_pop_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, + char *kw, char **cmd, int *cmd_len, short *slot, void **ctx); + /* Construct SCAN and similar commands, as well as check iterator */ int redis_scan_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, REDIS_SCAN_TYPE type, char **cmd, int *cmd_len); @@ -226,12 +229,6 @@ int redis_unlink_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, int redis_watch_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char **cmd, int *cmd_len, short *slot, void **ctx); -int redis_blpop_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, - char **cmd, int *cmd_len, short *slot, void **ctx); - -int redis_brpop_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, - char **cmd, int *cmd_len, short *slot, void **ctx); - int redis_sinter_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, char **cmd, int *cmd_len, short *slot, void **ctx); diff --git a/tests/RedisTest.php b/tests/RedisTest.php index b9b65f53..81d49734 100644 --- a/tests/RedisTest.php +++ b/tests/RedisTest.php @@ -2409,6 +2409,51 @@ class Redis_Test extends TestSuite $this->assertEquals($this->redis->zRemRangeByLex('key', '[a', '[c'), 2); } + public function testBZPop() { + if (version_compare($this->version, "5.0.0", "lt")) { + $this->MarkTestSkipped(); + return; + } + + $this->redis->del('{zs}1', '{zs}2'); + $this->redis->zAdd('{zs}1', 0, 'a', 1, 'b', 2, 'c'); + $this->redis->zAdd('{zs}2', 3, 'A', 4, 'B', 5, 'D'); + + $this->assertEquals(Array('{zs}1', 'a', '0'), $this->redis->bzPopMin('{zs}1', '{zs}2', 0)); + $this->assertEquals(Array('{zs}1', 'c', '2'), $this->redis->bzPopMax(Array('{zs}1', '{zs}2'), 0)); + $this->assertEquals(Array('{zs}2', 'A', '3'), $this->redis->bzPopMin('{zs}2', '{zs}1', 0)); + + /* Verify timeout is being sent */ + $this->redis->del('{zs}1', '{zs}2'); + $st = microtime(true) * 1000; + $this->redis->bzPopMin('{zs}1', '{zs}2', 1); + $et = microtime(true) * 1000; + $this->assertTrue($et - $st > 100); + } + + public function testZPop() { + if (version_compare($this->version, "5.0.0", "lt")) { + $this->MarkTestSkipped(); + return; + } + + // zPopMax and zPopMin without a COUNT argument + $this->redis->del('key'); + $this->redis->zAdd('key', 0, 'a', 1, 'b', 2, 'c', 3, 'd', 4, 'e'); + $this->assertTrue(array('e' => 4.0) === $this->redis->zPopMax('key')); + $this->assertTrue(array('a' => 0.0) === $this->redis->zPopMin('key')); + + // zPopMax with a COUNT argument + $this->redis->del('key'); + $this->redis->zAdd('key', 0, 'a', 1, 'b', 2, 'c', 3, 'd', 4, 'e'); + $this->assertTrue(array('e' => 4.0, 'd' => 3.0, 'c' => 2.0) === $this->redis->zPopMax('key', 3)); + + // zPopMin with a COUNT argument + $this->redis->del('key'); + $this->redis->zAdd('key', 0, 'a', 1, 'b', 2, 'c', 3, 'd', 4, 'e'); + $this->assertTrue(array('a' => 0.0, 'b' => 1.0, 'c' => 2.0) === $this->redis->zPopMin('key', 3)); + } + public function testHashes() { $this->redis->del('h', 'key'); $this->assertTrue(0 === $this->redis->hLen('h')); |