8000 Merged changes from @mobli · devsnippet/phpredis@6d3c999 · GitHub
[go: up one dir, main page]

Skip to content

Commit 6d3c999

Browse files
Emmanuel Meralimichael-grunder
Emmanuel Merali
authored andcommitted
Merged changes from @mobli
New select DB command to RedisArray - Added retry delay on reconnect Added the possibility to delay each reconnection attempt, including a random factor to prevent several or many concurrent connections from trying to reconnect at the same time. Added the select command to RedisArray to select a DB on every connections in one instruction. Also, fixed a compiler warning: redis_array_impl.c:1115:15: warning: incompatible pointer types assigning to 'zval **' (aka 'struct _zval_struct **') from 'zval **(*)[2]' [-Wincompatible-pointer-types] Conflicts: common.h
1 parent a4784b4 commit 6d3c999

File tree

9 files changed

+112
-24
lines changed

9 files changed

+112
-24
lines changed

common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ typedef struct {
159159
short port;
160160
double timeout;
161161
double read_timeout;
162+
long retry_interval;
162163
int failed;
163164
int status;
164165
int persistent;

library.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ PHPAPI int redis_check_eof(RedisSock *redis_sock TSRMLS_DC)
3838
int eof;
3939
int count = 0;
4040

41-
if (!redis_sock->stream)
41+
if (!redis_sock->stream) {
4242
return -1;
43+
}
4344

4445
eof = php_stream_eof(redis_sock->stream);
4546
for (; eof; count++) {
@@ -60,6 +61,12 @@ PHPAPI int redis_check_eof(RedisSock *redis_sock TSRMLS_DC)
6061
redis_sock->mode = ATOMIC;
6162
redis_sock->watching = 0;
6263
}
64+
// Wait for a while before trying to reconnect
65+
if (redis_sock->retry_interval) {
66+
// Random factor to avoid having several (or many) concurrent connections trying to reconnect at the same time
67+
long retry_interval = (count ? redis_sock->retry_interval : (random() % redis_sock->retry_interval));
68+
usleep(retry_interval);
69+
}
6370
redis_sock_connect(redis_sock TSRMLS_CC); /* reconnect */
6471
if(redis_sock->stream) { /* check for EOF again. */
6572
eof = php_stream_eof(redis_sock->stream);
@@ -962,7 +969,8 @@ PHPAPI void redis_ping_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_s
962969
* redis_sock_create
963970
*/
964971
PHPAPI RedisSock* redis_sock_create(char *host, int host_len, unsigned short port,
965-
double timeout, int persistent, char *persistent_id)
972+
double timeout, int persistent, char *persistent_id,
973+
long retry_interval)
966974
{
967975
RedisSock *redis_sock;
968976

@@ -972,7 +980,7 @@ PHPAPI RedisSock* redis_sock_create(char *host, int host_len, unsigned short por
972980
redis_sock->status = REDIS_SOCK_STATUS_DISCONNECTED;
973981
redis_sock->watching = 0;
974982
redis_sock->dbNumber = 0;
975-
983+
redis_sock->retry_interval = retry_interval * 1000;
976984
redis_sock->persistent = persistent;
977985

978986
if(persistent_id) {

library.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ PHPAPI void redis_string_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis
2020
PHPAPI void redis_ping_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
2121
PHPAPI void redis_info_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
2222
PHPAPI void redis_type_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx);
23-
PHPAPI RedisSock* redis_sock_create(char *host, int host_len, unsigned short port, double timeout, int persistent, char *persistent_id);
23+
PHPAPI RedisSock* redis_sock_create(char *host, int host_len, unsigned short port, double timeout, int persistent, char *persistent_id, long retry_interval);
2424
PHPAPI int redis_sock_connect(RedisSock *redis_sock TSRMLS_DC);
2525
PHPAPI int redis_sock_server_open(RedisSock *redis_sock, int force_connect TSRMLS_DC);
2626
PHPAPI int redis_sock_disconnect(RedisSock *redis_sock TSRMLS_DC);

redis.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ PHP_METHOD(Redis,__destruct) {
522522
}
523523
}
524524

525-
/* {{{ proto boolean Redis::connect(string host, int port [, double timeout])
525+
/* {{{ proto boolean Redis::connect(string host, int port [, double timeout [, long retry_interval]])
526526
*/
527527
PHP_METHOD(Redis, connect)
528528
{
@@ -558,6 +558,7 @@ PHPAPI int redis_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) {
558558
int host_len, id;
559559
char *host = NULL;
560560
long port = -1;
561+
long retry_interval = 0;
561562

562563
char *persistent_id = NULL;
563564
int persistent_id_len = -1;
@@ -570,9 +571,10 @@ PHPAPI int redis_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) {
570571
persistent = 0;
571572
#endif
572573

573-
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|lds",
574+
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|ldsl",
574575
&object, redis_ce, &host, &host_len, &port,
575-
&timeout, &persistent_id, &persistent_id_len) == FAILURE) {
576+
&timeout, &persistent_id, &persistent_id_len,
577+
&retry_interval) == FAILURE) {
576578
return FAILURE;
577579
}
578580

@@ -581,6 +583,11 @@ PHPAPI int redis_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) {
581583
return FAILURE;
582584
}
583585

586+
if (retry_interval < 0L || retry_interval > INT_MAX) {
587+
zend_throw_exception(redis_exception_ce, "Invalid retry interval", 0 TSRMLS_CC);
588+
return FAILURE;
589+
}
590+
584591
if(port == -1 && host_len && host[0] != '/') { /* not unix socket, set to default value */
585592
port = 6379;
586593
}
@@ -597,7 +604,7 @@ PHPAPI int redis_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) {
597604
zend_clear_exception(TSRMLS_C); /* clear exception triggered by non-existent socket during connect(). */
598605
}
599606

600-
redis_sock = redis_sock_create(host, host_len, port, timeout, persistent, persistent_id);
607+
redis_sock = redis_sock_create(host, host_len, port, timeout, persistent, persistent_id, retry_interval);
601608

602609
if (redis_sock_server_open(redis_sock, 1 TSRMLS_CC) < 0) {
603610
redis_free_socket(redis_sock);

redis_array.c

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ zend_function_entry redis_array_functions[] = {
5151
PHP_ME(RedisArray, _rehash, NULL, ZEND_ACC_PUBLIC)
5252

5353
/* special implementation for a few functions */
54+
PHP_ME(RedisArray, select, NULL, ZEND_ACC_PUBLIC)
5455
PHP_ME(RedisArray, info, NULL, ZEND_ACC_PUBLIC)
5556
PHP_ME(RedisArray, ping, NULL, ZEND_ACC_PUBLIC)
5657
PHP_ME(RedisArray, mget, NULL, ZEND_ACC_PUBLIC)
@@ -192,6 +193,7 @@ PHP_METHOD(RedisArray, __construct)
192193
RedisArray *ra = NULL;
193194
zend_bool b_index = 0, b_autorehash = 0;
194195
HashTable *hPrev = NULL, *hOpts = NULL;
196+
long l_retry_interval = 0;
195197

196198
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|a", &z0, &z_opts) == FAILURE) {
197199
RETURN_FALSE;
@@ -232,6 +234,19 @@ PHP_METHOD(RedisArray, __construct)
232234
if(FAILURE != zend_hash_find(hOpts, "autorehash", sizeof("autorehash"), (void**)&zpData) && Z_TYPE_PP(zpData) == IS_BOOL) {
233235
b_autorehash = Z_BVAL_PP(zpData);
234236
}
237+
238+
/* extract retry_interval option. */
239+
zval **z_retry_interval_pp;
240+
if (FAILURE != zend_hash_find(hOpts, "retry_interval", sizeof("retry_interval"), (void**)&z_retry_interval_pp)) {
241+
if (Z_TYPE_PP(z_retry_interval_pp) == IS_LONG || Z_TYPE_PP(z_retry_interval_pp) == IS_STRING) {
242+
if (Z_TYPE_PP(z_retry_interval_pp) == IS_LONG) {
243+
l_retry_interval = Z_LVAL_PP(z_retry_interval_pp);
244+
}
245+
else {
246+
l_retry_interval = atol(Z_STRVAL_PP(z_retry_interval_pp));
247+
}
248+
}
249+
}
235250
}
236251

237252
/* extract either name of list of hosts from z0 */
@@ -241,7 +256,7 @@ PHP_METHOD(RedisArray, __construct)
241256
break;
242257

243258
case IS_ARRAY:
244-
ra = ra_make_array(Z_ARRVAL_P(z0), z_fun, z_dist, hPrev, b_index TSRMLS_CC);
259+
ra = ra_make_array(Z_ARRVAL_P(z0), z_fun, z_dist, hPrev, b_index, l_retry_interval TSRMLS_CC);
245260
break;
246261

247262
default:
@@ -688,6 +703,46 @@ PHP_METHOD(RedisArray, setOption)
688703
efree(z_args[0]);
689704
efree(z_args[1]);
690705
}
706+
707+
PHP_METHOD(RedisArray, select)
708+
{
709+
zval *object, z_fun, *z_tmp, *z_args[2];
710+
int i;
711+
RedisArray *ra;
712+
long opt;
713+
714+
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol",
715+
&object, redis_array_ce, &opt) == FAILURE) {
716+
RETURN_FALSE;
717+
}
718+
719+
if (redis_array_get(object, &ra TSRMLS_CC) < 0) {
720+
RETURN_FALSE;
721+
}
722+
723+
/* prepare call */
724+
ZVAL_STRING(&z_fun, "select", 0);
725+
726+
/* copy args */
727+
MAKE_STD_ZVAL(z_args[0]);
728+
ZVAL_LONG(z_args[0], opt);
729+
730+
array_init(return_value);
731+
for(i = 0; i < ra->count; ++i) {
732+
733+
MAKE_STD_ZVAL(z_tmp);
734+
735+
/* Call each node in turn */
736+
call_user_function(&redis_ce->function_table, &ra->redis[i],
737+
&z_fun, z_tmp, 1, z_args TSRMLS_CC);
738+
739+
add_assoc_zval(return_value, ra->hosts[i], z_tmp);
740+
}
741+
742+
/* cleanup */
743+
efree(z_args[0]);
744+
}
745+
691746
#define HANDLE_MULTI_EXEC(cmd) do {\
692747
if (redis_array_get(getThis(), &ra TSRMLS_CC) >= 0 && ra->z_multi_exec) {\
693748
int i, num_varargs;\

redis_array.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ PHP_METHOD(RedisArray, _function);
1515
PHP_METHOD(RedisArray, _distributor);
1616
PHP_METHOD(RedisArray, _rehash);
1717

18+
PHP_METHOD(RedisArray, select);
1819
PHP_METHOD(RedisArray, info);
1920
PHP_METHOD(RedisArray, ping);
2021
PHP_METHOD(RedisArray, mget);

redis_array_impl.c

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ extern int le_redis_sock;
2929
extern zend_class_entry *redis_ce;
3030

3131
RedisArray*
32-
ra_load_hosts(RedisArray *ra, HashTable *hosts TSRMLS_DC)
32+
ra_load_hosts(RedisArray *ra, HashTable *hosts, long retry_interval TSRMLS_DC)
3333
{
3434
int i, host_len, id;
3535
int count = zend_hash_num_elements(hosts);
@@ -67,7 +67,7 @@ ra_load_hosts(RedisArray *ra, HashTable *hosts TSRMLS_DC)
6767
call_user_function(&redis_ce->function_table, &ra->redis[i], &z_cons, &z_ret, 0, NULL TSRMLS_CC);
6868

6969
/* create socket */
70-
redis_sock = redis_sock_create(host, host_len, port, 0, 0, NULL); /* TODO: persistence? */
70+
redis_sock = redis_sock_create(host, host_len, port, 0, 0, NULL, retry_interval); /* TODO: persistence? */
7171

7272
/* connect */
7373
redis_sock_server_open(redis_sock, 1 TSRMLS_CC);
@@ -158,9 +158,11 @@ RedisArray *ra_load_array(const char *name TSRMLS_DC) {
158158
zval *z_params_funs, **z_data_pp, *z_fun = NULL, *z_dist = NULL;
159159
zval *z_params_index;
160160
zval *z_params_autorehash;
161+
zval *z_params_retry_interval;
161162
RedisArray *ra = NULL;
162163

163164
zend_bool b_index = 0, b_autorehash = 0;
165+
long l_retry_interval = 0;
164166
HashTable *hHosts = NULL, *hPrev = NULL;
165167

166168
/* find entry */
@@ -223,8 +225,23 @@ RedisArray *ra_load_array(const char *name TSRMLS_DC) {
223225
}
224226
}
225227

228+
/* find retry interval option */
229+
MAKE_STD_ZVAL(z_params_retry_interval);
230+
array_init(z_params_retry_interval);
231+
sapi_module.treat_data(PARSE_STRING, estrdup(INI_STR("redis.arrays.retryinterval")), z_params_retry_interval TSRMLS_CC);
232+
if (zend_hash_find(Z_ARRVAL_P(z_params_retry_interval), name, strlen(name) + 1, (void **) &z_data_pp) != FAILURE) {
233+
if (Z_TYPE_PP(z_data_pp) == IS_LONG || Z_TYPE_PP(z_data_pp) == IS_STRING) {
234+
if (Z_TYPE_PP(z_data_pp) == IS_LONG) {
235+
l_retry_interval = Z_LVAL_PP(z_data_pp);
236+
}
237+
else {
238+
l_retry_interval = atol(Z_STRVAL_PP(z_data_pp));
239+
}
240+
}
241+
}
242+
226243
/* create RedisArray object */
227-
ra = ra_make_array(hHosts, z_fun, z_dist, hPrev, b_index TSRMLS_CC);
244+
ra = ra_make_array(hHosts, z_fun, z_dist, hPrev, b_index, l_retry_interval TSRMLS_CC);
228245
ra->auto_rehash = b_autorehash;
229246

230247
/* cleanup */
@@ -238,12 +255,14 @@ RedisArray *ra_load_array(const char *name TSRMLS_DC) {
238255
efree(z_params_index);
239256
zval_dtor(z_params_autorehash);
240257
efree(z_params_autorehash);
258+
zval_dtor(z_params_retry_interval);
259+
efree(z_params_retry_interval);
241260

242261
return ra;
243262
}
244263

245264
RedisArray *
246-
ra_make_array(HashTable *hosts, zval *z_fun, zval *z_dist, HashTable *hosts_prev, zend_bool b_index TSRMLS_DC) {
265+
ra_make_array(HashTable *hosts, zval *z_fun, zval *z_dist, HashTable *hosts_prev, zend_bool b_index, long retry_interval TSRMLS_DC) {
247266

248267
int count = zend_hash_num_elements(hosts);
249268

@@ -261,10 +280,10 @@ ra_make_array(HashTable *hosts, zval *z_fun, zval *z_dist, HashTable *hosts_prev
261280
/* init array data structures */
262281
ra_init_function_table(ra);
263282

264-
if(NULL == ra_load_hosts(ra, hosts TSRMLS_CC)) {
283+
if(NULL == ra_load_hosts(ra, hosts, retry_interval TSRMLS_CC)) {
265284
return NULL;
266285
}
267-
ra->prev = hosts_prev ? ra_make_array(hosts_prev, z_fun, z_dist, NULL, b_index TSRMLS_CC) : NULL;
286+
ra->prev = hosts_prev ? ra_make_array(hosts_prev, z_fun, z_dist, NULL, b_index, retry_interval TSRMLS_CC) : NULL;
268287

269288
/* copy function if provided */
270289
if(z_fun) {
@@ -1112,7 +1131,7 @@ static void zval_rehash_callback(zend_fcall_info *z_cb, zend_fcall_info_cache *z
11121131
zval *z_host, *z_count;
11131132

11141133
z_cb->retval_ptr_ptr = &z_ret;
1115-
z_cb->params = &z_args;
1134+
z_cb->params = (struct _zval_struct ***)&z_args;
11161135
z_cb->param_count = 2;
11171136
z_cb->no_separation = 0;
11181137

redis_array_impl.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
#include "common.h"
66
#include "redis_array.h"
77

8-
RedisArray* ra_load_hosts(RedisArray *ra, HashTable *hosts TSRMLS_DC);
8+
RedisArray *ra_load_hosts(RedisArray *ra, HashTable *hosts, long retry_interval TSRMLS_DC);
99
RedisArray *ra_load_array(const char *name TSRMLS_DC);
10-
RedisArray *ra_make_array(HashTable *hosts, zval *z_fun, zval *z_dist, HashTable *hosts_prev, zend_bool b_index TSRMLS_DC);
10+
RedisArray *ra_make_array(HashTable *hosts, zval *z_fun, zval *z_dist, HashTable *hosts_prev, zend_bool b_index, long retry_interval TSRMLS_DC);
1111
zval *ra_find_node_by_name(RedisArray *ra, const char *host, int host_len TSRMLS_DC);
1212
zval *ra_find_node(RedisArray *ra, const char *key, int key_len, int *out_pos TSRMLS_DC);
1313
void ra_init_function_table(RedisArray *ra);

redis_session.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ PS_OPEN_FUNC(redis)
206206
int persistent = 0;
207207
int database = -1;
208208
char *prefix = NULL, *auth = NULL, *persistent_id = NULL;
209+
long retry_interval = 0;
209210

210211
/* translate unix: into file: */
211212
if (!strncmp(save_path+i, "unix:", sizeof("unix:")-1)) {
@@ -240,7 +241,6 @@ PS_OPEN_FUNC(redis)
240241
convert_to_long_ex(param);
241242
weight = Z_LVAL_PP(param);
242243
}
243-
244244
if (zend_hash_find(Z_ARRVAL_P(params), "timeout", sizeof("timeout"), (void **) &param) != FAILURE) {
245245
timeout = atof(Z_STRVAL_PP(param));
246246
}
@@ -260,13 +260,10 @@ PS_OPEN_FUNC(redis)
260260
convert_to_long_ex(param);
261261
database = Z_LVAL_PP(param);
262262
}
263-
264-
/* // not supported yet
265263
if (zend_hash_find(Z_ARRVAL_P(params), "retry_interval", sizeof("retry_interval"), (void **) &param) != FAILURE) {
266264
convert_to_long_ex(param);
267265
retry_interval = Z_LVAL_PP(param);
268266
}
269-
*/
270267

271268
zval_ptr_dtor(&params);
272269
}
@@ -280,9 +277,9 @@ PS_OPEN_FUNC(redis)
280277

281278
RedisSock *redis_sock;
282279
if(url->host) {
283-
redis_sock = redis_sock_create(url->host, strlen(url->host), url->port, timeout, persistent, persistent_id);
280+
redis_sock = redis_sock_create(url->host, strlen(url->host), url->port, timeout, persistent, persistent_id, retry_interval);
284281
} else { /* unix */
285-
redis_sock = redis_sock_create(url->path, strlen(url->path), 0, timeout, persistent, persistent_id);
282+
redis_sock = redis_sock_create(url->path, strlen(url->path), 0, timeout, persistent, persistent_id, retry_interval);
286283
}
287284
redis_pool_add(pool, redis_sock, weight, database, prefix, auth TSRMLS_CC);
288285

0 commit comments

Comments
 (0)
0