Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/phpredis/phpredis.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormichael-grunder <michael.grunder@gmail.com>2013-04-28 22:10:32 +0400
committermichael-grunder <michael.grunder@gmail.com>2013-04-28 22:10:32 +0400
commitf9f2dc0dbf02394ef221b3b1ef8fc67a73b722de (patch)
tree2d53c95d37a9e7af92b7de0482906f4a4fd46e5d
parent4c16a303efdde3d3c41d8f6c44a24cec2d45ae22 (diff)
parent3e6d5b60d66e0a5b31080a7109c412b0ce6358e6 (diff)
Merge branch 'release/2.2.3'2.2.3
-rw-r--r--README.markdown29
-rw-r--r--common.h1
-rw-r--r--library.c136
-rw-r--r--library.h3
-rw-r--r--php_redis.h4
-rw-r--r--redis.c70
-rw-r--r--redis_array.c58
-rw-r--r--redis_array.h1
-rw-r--r--redis_array_impl.c34
-rw-r--r--redis_array_impl.h4
-rw-r--r--redis_session.c10
-rw-r--r--rpm/php-redis.spec2
-rw-r--r--tests/TestRedis.php26
13 files changed, 350 insertions, 28 deletions
diff --git a/README.markdown b/README.markdown
index bb403d2f..0f4d9cb4 100644
--- a/README.markdown
+++ b/README.markdown
@@ -2522,7 +2522,6 @@ $redis->zAdd('key', 2, 'val2');
$redis->zAdd('key', 10, 'val10');
$redis->zRangeByScore('key', 0, 3); /* array('val0', 'val2') */
$redis->zRangeByScore('key', 0, 3, array('withscores' => TRUE); /* array('val0' => 0, 'val2' => 2) */
-$redis->zRangeByScore('key', 0, 3, array('limit' => array(1, 1)); /* array('val2' => 2) */
$redis->zRangeByScore('key', 0, 3, array('limit' => array(1, 1)); /* array('val2') */
$redis->zRangeByScore('key', 0, 3, array('withscores' => TRUE, 'limit' => array(1, 1)); /* array('val2' => 2) */
~~~
@@ -2889,6 +2888,34 @@ $redis->script('exists', $script1, [$script2, $script3, ...]);
* SCRIPT KILL will return true if a script was able to be killed and false if not
* SCRIPT EXISTS will return an array with TRUE or FALSE for each passed script
+### client
+-----
+_**Description**_: Issue the CLIENT command with various arguments.
+
+The Redis CLIENT command can be used in four ways.
+* CLIENT LIST
+* CLIENT GETNAME
+* CLIENT SETNAME [name]
+* CLIENT KILL [ip:port]
+
+##### *Usage*
+~~~
+$redis->client('list'); // Get a list of clients
+$redis->client('getname'); // Get the name of the current connection
+$redis->client('setname', 'somename'); // Set the name of the current connection
+$redis->client('kill', <ip:port>); // Kill the process at ip:port
+~~~
+
+##### *Return value*
+This will vary depending on which client command was executed.
+
+* CLIENT LIST will return an array of arrays with client information.
+* CLIENT GETNAME will return the client name or false if none has been set
+* CLIENT SETNAME will return true if it can be set and false if not
+* CLIENT KILL will return true if the client can be killed, and false if not
+
+Note: phpredis will attempt to reconnect so you can actually kill your own connection
+but may not notice losing it!
### getLastError
-----
_**Description**_: The last error message (if any)
diff --git a/common.h b/common.h
index 33d60ce6..2abb4209 100644
--- a/common.h
+++ b/common.h
@@ -160,6 +160,7 @@ typedef struct {
char *auth;
double timeout;
double read_timeout;
+ long retry_interval;
int failed;
int status;
int persistent;
diff --git a/library.c b/library.c
index 32f77cd6..8a35ffda 100644
--- a/library.c
+++ b/library.c
@@ -38,8 +38,9 @@ PHPAPI int redis_check_eof(RedisSock *redis_sock TSRMLS_DC)
int eof;
int count = 0;
- if (!redis_sock->stream)
+ if (!redis_sock->stream) {
return -1;
+ }
eof = php_stream_eof(redis_sock->stream);
for (; eof; count++) {
@@ -60,6 +61,12 @@ PHPAPI int redis_check_eof(RedisSock *redis_sock TSRMLS_DC)
redis_sock->mode = ATOMIC;
redis_sock->watching = 0;
}
+ // Wait for a while before trying to reconnect
+ if (redis_sock->retry_interval) {
+ // Random factor to avoid having several (or many) concurrent connections trying to reconnect at the same time
+ long retry_interval = (count ? redis_sock->retry_interval : (random() % redis_sock->retry_interval));
+ usleep(retry_interval);
+ }
redis_sock_connect(redis_sock TSRMLS_CC); /* reconnect */
if(redis_sock->stream) { /* check for EOF again. */
eof = php_stream_eof(redis_sock->stream);
@@ -608,6 +615,128 @@ PHPAPI void redis_info_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_s
}
}
+/*
+ * Specialized handling of the CLIENT LIST output so it comes out in a simple way for PHP userland code
+ * to handle.
+ */
+PHPAPI 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;
+
+ // Make sure we can read a response from Redis
+ if((resp = redis_sock_read(redis_sock, &resp_len TSRMLS_CC)) == NULL) {
+ RETURN_FALSE;
+ }
+
+ // Allocate memory for our response
+ MAKE_STD_ZVAL(z_result);
+ array_init(z_result);
+
+ // Allocate memory for one user (there should be at least one, namely us!)
+ ALLOC_INIT_ZVAL(z_sub_result);
+ array_init(z_sub_result);
+
+ // Pointers for parsing
+ char *p = resp, *lpos = resp, *kpos = NULL, *vpos = NULL, *p2, *key, *value;
+
+ // Key length, done flag
+ int klen, done = 0, is_numeric;
+
+ // While we've got more to parse
+ while(!done) {
+ // What character are we on
+ switch(*p) {
+ /* We're done */
+ case '\0':
+ done = 1;
+ break;
+ /* \n, ' ' mean we can pull a k/v pair */
+ case '\n':
+ case ' ':
+ // Grab our value
+ vpos = lpos;
+
+ // There is some communication error or Redis bug if we don't
+ // have a key and value, but check anyway.
+ if(kpos && vpos) {
+ // Allocate, copy in our key
+ key = emalloc(klen + 1);
+ strncpy(key, kpos, klen);
+ key[klen] = 0;
+
+ // Allocate, copy in our value
+ value = emalloc(p-lpos+1);
+ strncpy(value,lpos,p-lpos+1);
+ value[p-lpos]=0;
+
+ // Treat numbers as numbers, strings as strings
+ is_numeric = 1;
+ for(p2 = value; *p; ++p) {
+ if(*p < '0' || *p > '9') {
+ is_numeric = 0;
+ break;
+ }
+ }
+
+ // Add as a long or string, depending
+ if(is_numeric == 1) {
+ add_assoc_long(z_sub_result, key, atol(value));
+ efree(value);
+ } else {
+ add_assoc_string(z_sub_result, key, value, 0);
+ }
+
+ // If we hit a '\n', then we can add this user to our list
+ if(*p == '\n') {
+ // Add our user
+ add_next_index_zval(z_result, z_sub_result);
+
+ // If we have another user, make another one
+ if(*(p+1) != '\0') {
+ ALLOC_INIT_ZVAL(z_sub_result);
+ array_init(z_sub_result);
+ }
+ }
+
+ // Free our key
+ efree(key);
+ } else {
+ // Something is wrong
+ efree(resp);
+ RETURN_FALSE;
+ }
+
+ // Move forward
+ lpos = p + 1;
+
+ break;
+ /* We can pull the key and null terminate at our sep */
+ case '=':
+ // Key, key length
+ kpos = lpos;
+ klen = p - lpos;
+
+ // Move forward
+ lpos = p + 1;
+
+ break;
+ }
+
+ // Increment
+ 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);
+ }
+}
+
PHPAPI void redis_boolean_response_impl(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx, SuccessCallback success_callback) {
char *response;
@@ -840,7 +969,8 @@ PHPAPI void redis_ping_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_s
* redis_sock_create
*/
PHPAPI RedisSock* redis_sock_create(char *host, int host_len, unsigned short port,
- double timeout, int persistent, char *persistent_id)
+ double timeout, int persistent, char *persistent_id,
+ long retry_interval)
{
RedisSock *redis_sock;
@@ -850,7 +980,7 @@ PHPAPI RedisSock* redis_sock_create(char *host, int host_len, unsigned short por
redis_sock->status = REDIS_SOCK_STATUS_DISCONNECTED;
redis_sock->watching = 0;
redis_sock->dbNumber = 0;
-
+ redis_sock->retry_interval = retry_interval * 1000;
redis_sock->persistent = persistent;
if(persistent_id) {
diff --git a/library.h b/library.h
index d730b96b..0ee1f6fe 100644
--- a/library.h
+++ b/library.h
@@ -20,7 +20,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 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);
+PHPAPI RedisSock* redis_sock_create(char *host, int host_len, unsigned short port, double timeout, int persistent, char *persistent_id, long retry_interval);
PHPAPI int redis_sock_connect(RedisSock *redis_sock TSRMLS_DC);
PHPAPI int redis_sock_server_open(RedisSock *redis_sock, int force_connect TSRMLS_DC);
PHPAPI int redis_sock_disconnect(RedisSock *redis_sock TSRMLS_DC);
@@ -59,6 +59,7 @@ PHPAPI int redis_read_variant_bulk(RedisSock *redis_sock, int size, zval **z_ret
PHPAPI int redis_read_multibulk_recursive(RedisSock *redis_sock, int elements, zval **z_ret TSRMLS_DC);
PHPAPI int redis_read_variant_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab);
+PHPAPI void redis_client_list_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab);
#if ZEND_MODULE_API_NO >= 20100000
#define REDIS_DOUBLE_TO_STRING(dbl_str, dbl_len, dbl) \
diff --git a/php_redis.h b/php_redis.h
index 6ed4babe..a8f99be0 100644
--- a/php_redis.h
+++ b/php_redis.h
@@ -181,6 +181,8 @@ PHP_METHOD(Redis, setOption);
PHP_METHOD(Redis, config);
+PHP_METHOD(Redis, client);
+
PHP_METHOD(Redis, getHost);
PHP_METHOD(Redis, getPort);
PHP_METHOD(Redis, getDBNum);
@@ -254,7 +256,7 @@ extern zend_module_entry redis_module_entry;
#define phpext_redis_ptr redis_module_ptr
-#define PHP_REDIS_VERSION "2.2.2"
+#define PHP_REDIS_VERSION "2.2.3"
#endif
diff --git a/redis.c b/redis.c
index aef1613d..181a65fc 100644
--- a/redis.c
+++ b/redis.c
@@ -16,6 +16,7 @@
| Original author: Alfonso Jimenez <yo@alfonsojimenez.com> |
| Maintainer: Nicolas Favre-Felix <n.favre-felix@owlient.eu> |
| Maintainer: Nasreddine Bouafif <n.bouafif@owlient.eu> |
+ | Maintainer: Michael Grunder <michael.grunder@gmail.com |
+----------------------------------------------------------------------+
*/
@@ -227,6 +228,7 @@ static zend_function_entry redis_functions[] = {
PHP_ME(Redis, _prefix, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Redis, _unserialize, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Redis, client, NULL, ZEND_ACC_PUBLIC)
/* options */
PHP_ME(Redis, getOption, NULL, ZEND_ACC_PUBLIC)
@@ -554,7 +556,7 @@ PHP_METHOD(Redis,__destruct) {
}
}
-/* {{{ proto boolean Redis::connect(string host, int port [, double timeout])
+/* {{{ proto boolean Redis::connect(string host, int port [, double timeout [, long retry_interval]])
*/
PHP_METHOD(Redis, connect)
{
@@ -590,6 +592,7 @@ PHPAPI int redis_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) {
int host_len, id;
char *host = NULL;
long port = -1;
+ long retry_interval = 0;
char *persistent_id = NULL;
int persistent_id_len = -1;
@@ -602,9 +605,10 @@ PHPAPI int redis_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) {
persistent = 0;
#endif
- if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|lds",
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|ldsl",
&object, redis_ce, &host, &host_len, &port,
- &timeout, &persistent_id, &persistent_id_len) == FAILURE) {
+ &timeout, &persistent_id, &persistent_id_len,
+ &retry_interval) == FAILURE) {
return FAILURE;
}
@@ -613,6 +617,11 @@ PHPAPI int redis_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) {
return FAILURE;
}
+ if (retry_interval < 0L || retry_interval > INT_MAX) {
+ zend_throw_exception(redis_exception_ce, "Invalid retry interval", 0 TSRMLS_CC);
+ return FAILURE;
+ }
+
if(port == -1 && host_len && host[0] != '/') { /* not unix socket, set to default value */
port = 6379;
}
@@ -629,7 +638,7 @@ PHPAPI int redis_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) {
zend_clear_exception(TSRMLS_C); /* clear exception triggered by non-existent socket during connect(). */
}
- redis_sock = redis_sock_create(host, host_len, port, timeout, persistent, persistent_id);
+ redis_sock = redis_sock_create(host, host_len, port, timeout, persistent, persistent_id, retry_interval);
if (redis_sock_server_open(redis_sock, 1 TSRMLS_CC) < 0) {
redis_free_socket(redis_sock);
@@ -6456,5 +6465,56 @@ PHP_METHOD(Redis, getAuth) {
}
}
-/* vim: set tabstop=4 softtabstop=4 noexpandtab shiftwidth=4: */
+/*
+ * $redis->client('list');
+ * $redis->client('kill', <ip:port>);
+ * $redis->client('setname', <name>);
+ * $redis->client('getname');
+ */
+PHP_METHOD(Redis, client) {
+ zval *object;
+ RedisSock *redis_sock;
+ char *cmd, *opt=NULL, *arg=NULL;
+ int cmd_len, opt_len, arg_len;
+
+ // Parse our method parameters
+ if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|s",
+ &object, redis_ce, &opt, &opt_len, &arg, &arg_len) == FAILURE)
+ {
+ RETURN_FALSE;
+ }
+
+ // Grab our socket
+ if(redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) {
+ RETURN_FALSE;
+ }
+
+ // Build our CLIENT command
+ if(ZEND_NUM_ARGS() == 2) {
+ cmd_len = redis_cmd_format_static(&cmd, "CLIENT", "ss", opt, opt_len,
+ arg, arg_len);
+ } else {
+ cmd_len = redis_cmd_format_static(&cmd, "CLIENT", "s", opt, opt_len);
+ }
+
+ // Handle CLIENT LIST specifically
+ int is_list = !strncasecmp(opt, "list", 4);
+
+ // Execute our queue command
+ REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len);
+
+ // We handle CLIENT LIST with a custom response function
+ if(!strncasecmp(opt, "list", 4)) {
+ IF_ATOMIC() {
+ redis_client_list_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU,redis_sock,NULL);
+ }
+ REDIS_PROCESS_RESPONSE(redis_client_list_reply);
+ } else {
+ IF_ATOMIC() {
+ redis_read_variant_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU,redis_sock,NULL);
+ }
+ REDIS_PROCESS_RESPONSE(redis_read_variant_reply);
+ }
+}
+/* vim: set tabstop=4 softtabstops=4 noexpandtab shiftwidth=4: */
diff --git a/redis_array.c b/redis_array.c
index d0460f10..9c414292 100644
--- a/redis_array.c
+++ b/redis_array.c
@@ -13,6 +13,7 @@
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Nicolas Favre-Felix <n.favre-felix@owlient.eu> |
+ | Maintainer: Michael Grunder <michael.grunder@gmail.com> |
+----------------------------------------------------------------------+
*/
@@ -51,6 +52,7 @@ zend_function_entry redis_array_functions[] = {
PHP_ME(RedisArray, _rehash, NULL, ZEND_ACC_PUBLIC)
/* special implementation for a few functions */
+ PHP_ME(RedisArray, select, NULL, ZEND_ACC_PUBLIC)
PHP_ME(RedisArray, info, NULL, ZEND_ACC_PUBLIC)
PHP_ME(RedisArray, ping, NULL, ZEND_ACC_PUBLIC)
PHP_ME(RedisArray, mget, NULL, ZEND_ACC_PUBLIC)
@@ -192,6 +194,7 @@ PHP_METHOD(RedisArray, __construct)
RedisArray *ra = NULL;
zend_bool b_index = 0, b_autorehash = 0;
HashTable *hPrev = NULL, *hOpts = NULL;
+ long l_retry_interval = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|a", &z0, &z_opts) == FAILURE) {
RETURN_FALSE;
@@ -232,6 +235,19 @@ PHP_METHOD(RedisArray, __construct)
if(FAILURE != zend_hash_find(hOpts, "autorehash", sizeof("autorehash"), (void**)&zpData) && Z_TYPE_PP(zpData) == IS_BOOL) {
b_autorehash = Z_BVAL_PP(zpData);
}
+
+ /* extract retry_interval option. */
+ zval **z_retry_interval_pp;
+ if (FAILURE != zend_hash_find(hOpts, "retry_interval", sizeof("retry_interval"), (void**)&z_retry_interval_pp)) {
+ if (Z_TYPE_PP(z_retry_interval_pp) == IS_LONG || Z_TYPE_PP(z_retry_interval_pp) == IS_STRING) {
+ if (Z_TYPE_PP(z_retry_interval_pp) == IS_LONG) {
+ l_retry_interval = Z_LVAL_PP(z_retry_interval_pp);
+ }
+ else {
+ l_retry_interval = atol(Z_STRVAL_PP(z_retry_interval_pp));
+ }
+ }
+ }
}
/* extract either name of list of hosts from z0 */
@@ -241,7 +257,7 @@ PHP_METHOD(RedisArray, __construct)
break;
case IS_ARRAY:
- ra = ra_make_array(Z_ARRVAL_P(z0), z_fun, z_dist, hPrev, b_index TSRMLS_CC);
+ ra = ra_make_array(Z_ARRVAL_P(z0), z_fun, z_dist, hPrev, b_index, l_retry_interval TSRMLS_CC);
break;
default:
@@ -688,6 +704,46 @@ PHP_METHOD(RedisArray, setOption)
efree(z_args[0]);
efree(z_args[1]);
}
+
+PHP_METHOD(RedisArray, select)
+{
+ zval *object, z_fun, *z_tmp, *z_args[2];
+ int i;
+ RedisArray *ra;
+ long opt;
+
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol",
+ &object, redis_array_ce, &opt) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ if (redis_array_get(object, &ra TSRMLS_CC) < 0) {
+ RETURN_FALSE;
+ }
+
+ /* prepare call */
+ ZVAL_STRING(&z_fun, "select", 0);
+
+ /* copy args */
+ MAKE_STD_ZVAL(z_args[0]);
+ ZVAL_LONG(z_args[0], opt);
+
+ array_init(return_value);
+ for(i = 0; i < ra->count; ++i) {
+
+ MAKE_STD_ZVAL(z_tmp);
+
+ /* Call each node in turn */
+ call_user_function(&redis_ce->function_table, &ra->redis[i],
+ &z_fun, z_tmp, 1, z_args TSRMLS_CC);
+
+ add_assoc_zval(return_value, ra->hosts[i], z_tmp);
+ }
+
+ /* cleanup */
+ efree(z_args[0]);
+}
+
#define HANDLE_MULTI_EXEC(cmd) do {\
if (redis_array_get(getThis(), &ra TSRMLS_CC) >= 0 && ra->z_multi_exec) {\
int i, num_varargs;\
diff --git a/redis_array.h b/redis_array.h
index bc7fdd88..b2c7d86a 100644
--- a/redis_array.h
+++ b/redis_array.h
@@ -15,6 +15,7 @@ PHP_METHOD(RedisArray, _function);
PHP_METHOD(RedisArray, _distributor);
PHP_METHOD(RedisArray, _rehash);
+PHP_METHOD(RedisArray, select);
PHP_METHOD(RedisArray, info);
PHP_METHOD(RedisArray, ping);
PHP_METHOD(RedisArray, mget);
diff --git a/redis_array_impl.c b/redis_array_impl.c
index 0c361d74..bafcbd49 100644
--- a/redis_array_impl.c
+++ b/redis_array_impl.c
@@ -13,6 +13,7 @@
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Nicolas Favre-Felix <n.favre-felix@owlient.eu> |
+ | Maintainer: Michael Grunder <michael.grunder@gmail.com> |
+----------------------------------------------------------------------+
*/
#include "redis_array_impl.h"
@@ -29,7 +30,7 @@ extern int le_redis_sock;
extern zend_class_entry *redis_ce;
RedisArray*
-ra_load_hosts(RedisArray *ra, HashTable *hosts TSRMLS_DC)
+ra_load_hosts(RedisArray *ra, HashTable *hosts, long retry_interval TSRMLS_DC)
{
int i, host_len, id;
int count = zend_hash_num_elements(hosts);
@@ -67,7 +68,7 @@ ra_load_hosts(RedisArray *ra, HashTable *hosts TSRMLS_DC)
call_user_function(&redis_ce->function_table, &ra->redis[i], &z_cons, &z_ret, 0, NULL TSRMLS_CC);
/* create socket */
- redis_sock = redis_sock_create(host, host_len, port, 0, 0, NULL); /* TODO: persistence? */
+ redis_sock = redis_sock_create(host, host_len, port, 0, 0, NULL, retry_interval); /* TODO: persistence? */
/* connect */
redis_sock_server_open(redis_sock, 1 TSRMLS_CC);
@@ -158,9 +159,11 @@ RedisArray *ra_load_array(const char *name TSRMLS_DC) {
zval *z_params_funs, **z_data_pp, *z_fun = NULL, *z_dist = NULL;
zval *z_params_index;
zval *z_params_autorehash;
+ zval *z_params_retry_interval;
RedisArray *ra = NULL;
zend_bool b_index = 0, b_autorehash = 0;
+ long l_retry_interval = 0;
HashTable *hHosts = NULL, *hPrev = NULL;
/* find entry */
@@ -223,8 +226,23 @@ RedisArray *ra_load_array(const char *name TSRMLS_DC) {
}
}
+ /* find retry interval option */
+ MAKE_STD_ZVAL(z_params_retry_interval);
+ array_init(z_params_retry_interval);
+ sapi_module.treat_data(PARSE_STRING, estrdup(INI_STR("redis.arrays.retryinterval")), z_params_retry_interval TSRMLS_CC);
+ if (zend_hash_find(Z_ARRVAL_P(z_params_retry_interval), name, strlen(name) + 1, (void **) &z_data_pp) != FAILURE) {
+ if (Z_TYPE_PP(z_data_pp) == IS_LONG || Z_TYPE_PP(z_data_pp) == IS_STRING) {
+ if (Z_TYPE_PP(z_data_pp) == IS_LONG) {
+ l_retry_interval = Z_LVAL_PP(z_data_pp);
+ }
+ else {
+ l_retry_interval = atol(Z_STRVAL_PP(z_data_pp));
+ }
+ }
+ }
+
/* create RedisArray object */
- ra = ra_make_array(hHosts, z_fun, z_dist, hPrev, b_index TSRMLS_CC);
+ ra = ra_make_array(hHosts, z_fun, z_dist, hPrev, b_index, l_retry_interval TSRMLS_CC);
ra->auto_rehash = b_autorehash;
/* cleanup */
@@ -238,12 +256,14 @@ RedisArray *ra_load_array(const char *name TSRMLS_DC) {
efree(z_params_index);
zval_dtor(z_params_autorehash);
efree(z_params_autorehash);
+ zval_dtor(z_params_retry_interval);
+ efree(z_params_retry_interval);
return ra;
}
RedisArray *
-ra_make_array(HashTable *hosts, zval *z_fun, zval *z_dist, HashTable *hosts_prev, zend_bool b_index TSRMLS_DC) {
+ra_make_array(HashTable *hosts, zval *z_fun, zval *z_dist, HashTable *hosts_prev, zend_bool b_index, long retry_interval TSRMLS_DC) {
int count = zend_hash_num_elements(hosts);
@@ -261,10 +281,10 @@ ra_make_array(HashTable *hosts, zval *z_fun, zval *z_dist, HashTable *hosts_prev
/* init array data structures */
ra_init_function_table(ra);
- if(NULL == ra_load_hosts(ra, hosts TSRMLS_CC)) {
+ if(NULL == ra_load_hosts(ra, hosts, retry_interval TSRMLS_CC)) {
return NULL;
}
- ra->prev = hosts_prev ? ra_make_array(hosts_prev, z_fun, z_dist, NULL, b_index TSRMLS_CC) : NULL;
+ ra->prev = hosts_prev ? ra_make_array(hosts_prev, z_fun, z_dist, NULL, b_index, retry_interval TSRMLS_CC) : NULL;
/* copy function if provided */
if(z_fun) {
@@ -1111,7 +1131,7 @@ static void zval_rehash_callback(zend_fcall_info *z_cb, zend_fcall_info_cache *z
zval *z_host, *z_count;
z_cb->retval_ptr_ptr = &z_ret;
- z_cb->params = &z_args;
+ z_cb->params = (struct _zval_struct ***)&z_args;
z_cb->param_count = 2;
z_cb->no_separation = 0;
diff --git a/redis_array_impl.h b/redis_array_impl.h
index 0e00258c..8dd5201b 100644
--- a/redis_array_impl.h
+++ b/redis_array_impl.h
@@ -5,9 +5,9 @@
#include "common.h"
#include "redis_array.h"
-RedisArray* ra_load_hosts(RedisArray *ra, HashTable *hosts TSRMLS_DC);
+RedisArray *ra_load_hosts(RedisArray *ra, HashTable *hosts, long retry_interval TSRMLS_DC);
RedisArray *ra_load_array(const char *name TSRMLS_DC);
-RedisArray *ra_make_array(HashTable *hosts, zval *z_fun, zval *z_dist, HashTable *hosts_prev, zend_bool b_index TSRMLS_DC);
+RedisArray *ra_make_array(HashTable *hosts, zval *z_fun, zval *z_dist, HashTable *hosts_prev, zend_bool b_index, long retry_interval TSRMLS_DC);
zval *ra_find_node_by_name(RedisArray *ra, const char *host, int host_len TSRMLS_DC);
zval *ra_find_node(RedisArray *ra, const char *key, int key_len, int *out_pos TSRMLS_DC);
void ra_init_function_table(RedisArray *ra);
diff --git a/redis_session.c b/redis_session.c
index 95d90533..4e633fc9 100644
--- a/redis_session.c
+++ b/redis_session.c
@@ -16,6 +16,7 @@
| Original author: Alfonso Jimenez <yo@alfonsojimenez.com> |
| Maintainer: Nicolas Favre-Felix <n.favre-felix@owlient.eu> |
| Maintainer: Nasreddine Bouafif <n.bouafif@owlient.eu> |
+ | Maintainer: Michael Grunder <michael.grunder@gmail.com> |
+----------------------------------------------------------------------+
*/
@@ -206,6 +207,7 @@ PS_OPEN_FUNC(redis)
int persistent = 0;
int database = -1;
char *prefix = NULL, *auth = NULL, *persistent_id = NULL;
+ long retry_interval = 0;
/* translate unix: into file: */
if (!strncmp(save_path+i, "unix:", sizeof("unix:")-1)) {
@@ -240,7 +242,6 @@ PS_OPEN_FUNC(redis)
convert_to_long_ex(param);
weight = Z_LVAL_PP(param);
}
-
if (zend_hash_find(Z_ARRVAL_P(params), "timeout", sizeof("timeout"), (void **) &param) != FAILURE) {
timeout = atof(Z_STRVAL_PP(param));
}
@@ -260,13 +261,10 @@ PS_OPEN_FUNC(redis)
convert_to_long_ex(param);
database = Z_LVAL_PP(param);
}
-
- /* // not supported yet
if (zend_hash_find(Z_ARRVAL_P(params), "retry_interval", sizeof("retry_interval"), (void **) &param) != FAILURE) {
convert_to_long_ex(param);
retry_interval = Z_LVAL_PP(param);
}
- */
zval_ptr_dtor(&params);
}
@@ -280,9 +278,9 @@ PS_OPEN_FUNC(redis)
RedisSock *redis_sock;
if(url->host) {
- redis_sock = redis_sock_create(url->host, strlen(url->host), url->port, timeout, persistent, persistent_id);
+ redis_sock = redis_sock_create(url->host, strlen(url->host), url->port, timeout, persistent, persistent_id, retry_interval);
} else { /* unix */
- redis_sock = redis_sock_create(url->path, strlen(url->path), 0, timeout, persistent, persistent_id);
+ redis_sock = redis_sock_create(url->path, strlen(url->path), 0, timeout, persistent, persistent_id, retry_interval);
}
redis_pool_add(pool, redis_sock, weight, database, prefix, auth TSRMLS_CC);
diff --git a/rpm/php-redis.spec b/rpm/php-redis.spec
index 633e3ed2..714854bc 100644
--- a/rpm/php-redis.spec
+++ b/rpm/php-redis.spec
@@ -3,7 +3,7 @@
%global php_version %(php-config --version 2>/dev/null || echo 0)
Name: php-redis
-Version: 2.2.2
+Version: 2.2.3
Release: 1%{?dist}
Summary: The phpredis extension provides an API for communicating with the Redis key-value store.
diff --git a/tests/TestRedis.php b/tests/TestRedis.php
index db9099ba..20fdb358 100644
--- a/tests/TestRedis.php
+++ b/tests/TestRedis.php
@@ -1650,6 +1650,32 @@ class Redis_Test extends TestSuite
$this->assertTrue(FALSE === $this->redis->persist('x')); // false if the key doesn’t exist.
}
+ public function testClient() {
+ /* CLIENT SETNAME */
+ $this->assertTrue($this->redis->client('setname', 'phpredis_unit_tests'));
+
+ /* CLIENT LIST */
+ $arr_clients = $this->redis->client('list');
+ $this->assertTrue(is_array($arr_clients));
+
+ // Figure out which ip:port is us!
+ $str_addr = NULL;
+ foreach($arr_clients as $arr_client) {
+ if($arr_client['name'] == 'phpredis_unit_tests') {
+ $str_addr = $arr_client['addr'];
+ }
+ }
+
+ // We should have found our connection
+ $this->assertFalse(empty($str_addr));
+
+ /* CLIENT GETNAME */
+ $this->assertTrue($this->redis->client('getname'), 'phpredis_unit_tests');
+
+ /* CLIENT KILL -- phpredis will reconnect, so we can do this */
+ $this->assertTrue($this->redis->client('kill', $str_addr));
+ }
+
public function testinfo() {
$info = $this->redis->info();