diff options
-rw-r--r-- | README.markdown | 4 | ||||
-rw-r--r-- | arrays.markdown | 18 | ||||
-rw-r--r-- | common.h | 1 | ||||
-rw-r--r-- | library.c | 4 | ||||
-rw-r--r-- | library.h | 2 | ||||
-rw-r--r-- | redis.c | 9 | ||||
-rw-r--r-- | redis_array.c | 10 | ||||
-rw-r--r-- | redis_array_impl.c | 33 | ||||
-rw-r--r-- | redis_array_impl.h | 4 | ||||
-rw-r--r-- | redis_session.c | 4 |
10 files changed, 69 insertions, 20 deletions
diff --git a/README.markdown b/README.markdown index bd5a067b..b0ee36f7 100644 --- a/README.markdown +++ b/README.markdown @@ -164,6 +164,8 @@ _**Description**_: Connects to a Redis instance. *host*: string. can be a host, or the path to a unix domain socket *port*: int, optional *timeout*: float, value in seconds (optional, default is 0 meaning unlimited) +*reserved*: should be NULL if retry_interval is specified +*retry_interval*: int, value in milliseconds (optional) ##### *Return value* @@ -176,6 +178,7 @@ $redis->connect('127.0.0.1', 6379); $redis->connect('127.0.0.1'); // port 6379 by default $redis->connect('127.0.0.1', 6379, 2.5); // 2.5 sec timeout. $redis->connect('/tmp/redis.sock'); // unix domain socket. +$redis->connect('127.0.0.1', 6379, 1, NULL, 100); // 1 sec timeout, 100ms delay between reconnection attempts. ~~~ ### pconnect, popen @@ -198,6 +201,7 @@ persistent equivalents. *port*: int, optional *timeout*: float, value in seconds (optional, default is 0 meaning unlimited) *persistent_id*: string. identity for the requested persistent connection +*retry_interval*: int, value in milliseconds (optional) ##### *Return value* diff --git a/arrays.markdown b/arrays.markdown index 16c9601c..de326e9c 100644 --- a/arrays.markdown +++ b/arrays.markdown @@ -17,7 +17,7 @@ There are several ways of creating Redis arrays; they can be pre-defined in red #### Declaring a new array with a list of nodes <pre> -$ra = new RedisArray(array("host1", "host2:63792, "host2:6380")); +$ra = new RedisArray(array("host1", "host2:63792", "host2:6380")); </pre> @@ -26,7 +26,7 @@ $ra = new RedisArray(array("host1", "host2:63792, "host2:6380")); function extract_key_part($k) { return substr($k, 0, 3); // hash only on first 3 characters. } -$ra = new RedisArray(array("host1", "host2:63792, "host2:6380"), array("function" => "extract_key_part")); +$ra = new RedisArray(array("host1", "host2:63792", "host2:6380"), array("function" => "extract_key_part")); </pre> #### Defining a "previous" array when nodes are added or removed. @@ -34,7 +34,19 @@ When a new node is added to an array, phpredis needs to know about it. The old l <pre> // adding host3 to a ring containing host1 and host2. Read commands will look in the previous ring if the data is not found in the main ring. -$ra = new RedisArray(array('host1', 'host2', 'host3'), array('previous' => array('host1', 'host2'))); +$ra = new RedisArray(array("host1", "host2", "host3"), array("previous" => array("host1", "host2"))); +</pre> + +#### Specifying the "retry_interval" parameter +The retry_interval is used to specify a delay in milliseconds between reconnection attempts in case the client loses connection with a server +<pre> +$ra = new RedisArray(array("host1", "host2:63792", "host2:6380"), array("retry_timeout" => 100))); +</pre> + +#### Specifying the "lazy_connect" parameter +This option is useful when a cluster has many shards but not of them are necessarily used at one time. +<pre> +$ra = new RedisArray(array("host1", "host2:63792", "host2:6380"), array("lazy_connect" => true))); </pre> #### Defining arrays in Redis.ini @@ -181,6 +181,7 @@ typedef struct { char *err; int err_len; + zend_bool lazy_connect; } RedisSock; /* }}} */ @@ -848,7 +848,8 @@ PHPAPI void redis_ping_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_s */ PHPAPI RedisSock* redis_sock_create(char *host, int host_len, unsigned short port, double timeout, int persistent, char *persistent_id, - long retry_interval) + long retry_interval, + zend_bool lazy_connect) { RedisSock *redis_sock; @@ -860,6 +861,7 @@ PHPAPI RedisSock* redis_sock_create(char *host, int host_len, unsigned short por redis_sock->dbNumber = 0; redis_sock->retry_interval = retry_interval * 1000; redis_sock->persistent = persistent; + redis_sock->lazy_connect = lazy_connect; if(persistent_id) { size_t persistent_id_len = strlen(persistent_id); @@ -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, long retry_interval); +PHPAPI RedisSock* redis_sock_create(char *host, int host_len, unsigned short port, double timeout, int persistent, char *persistent_id, long retry_interval, zend_bool lazy_connect); 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); @@ -377,6 +377,13 @@ PHPAPI int redis_sock_get(zval *id, RedisSock **redis_sock TSRMLS_DC, int no_thr } return -1; } + if ((*redis_sock)->lazy_connect) + { + (*redis_sock)->lazy_connect = 0; + if (redis_sock_server_open(*redis_sock, 1 TSRMLS_CC) < 0) { + return -1; + } + } return Z_LVAL_PP(socket); } @@ -603,7 +610,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, retry_interval); + redis_sock = redis_sock_create(host, host_len, port, timeout, persistent, persistent_id, retry_interval, 0); if (redis_sock_server_open(redis_sock, 1 TSRMLS_CC) < 0) { redis_free_socket(redis_sock); diff --git a/redis_array.c b/redis_array.c index be95c50d..fb507f55 100644 --- a/redis_array.c +++ b/redis_array.c @@ -194,6 +194,7 @@ PHP_METHOD(RedisArray, __construct) zend_bool b_index = 0, b_autorehash = 0; HashTable *hPrev = NULL, *hOpts = NULL; long l_retry_interval = 0; + zend_bool b_lazy_connect = 0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|a", &z0, &z_opts) == FAILURE) { RETURN_FALSE; @@ -236,7 +237,7 @@ PHP_METHOD(RedisArray, __construct) } /* extract retry_interval option. */ - zval **z_retry_interval_pp; + 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) { @@ -247,6 +248,11 @@ PHP_METHOD(RedisArray, __construct) } } } + + /* extract lazy connect option. */ + if(FAILURE != zend_hash_find(hOpts, "lazy_connect", sizeof("lazy_connect"), (void**)&zpData) && Z_TYPE_PP(zpData) == IS_BOOL) { + b_lazy_connect = Z_BVAL_PP(zpData); + } } /* extract either name of list of hosts from z0 */ @@ -256,7 +262,7 @@ PHP_METHOD(RedisArray, __construct) break; case IS_ARRAY: - ra = ra_make_array(Z_ARRVAL_P(z0), z_fun, z_dist, hPrev, b_index, l_retry_interval TSRMLS_CC); + ra = ra_make_array(Z_ARRVAL_P(z0), z_fun, z_dist, hPrev, b_index, l_retry_interval, b_lazy_connect TSRMLS_CC); break; default: diff --git a/redis_array_impl.c b/redis_array_impl.c index c38e2fe6..f804f475 100644 --- a/redis_array_impl.c +++ b/redis_array_impl.c @@ -29,7 +29,7 @@ extern int le_redis_sock; extern zend_class_entry *redis_ce; RedisArray* -ra_load_hosts(RedisArray *ra, HashTable *hosts, long retry_interval TSRMLS_DC) +ra_load_hosts(RedisArray *ra, HashTable *hosts, long retry_interval, zend_bool lazy_connect TSRMLS_DC) { int i, host_len, id; int count = zend_hash_num_elements(hosts); @@ -67,10 +67,13 @@ ra_load_hosts(RedisArray *ra, HashTable *hosts, long retry_interval 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, retry_interval); /* TODO: persistence? */ + redis_sock = redis_sock_create(host, host_len, port, 0, 0, NULL, retry_interval, lazy_connect); /* TODO: persistence? */ - /* connect */ - redis_sock_server_open(redis_sock, 1 TSRMLS_CC); + if (!lazy_connect) + { + /* connect */ + redis_sock_server_open(redis_sock, 1 TSRMLS_CC); + } /* attach */ #if PHP_VERSION_ID >= 50400 @@ -159,10 +162,12 @@ RedisArray *ra_load_array(const char *name TSRMLS_DC) { zval *z_params_index; zval *z_params_autorehash; zval *z_params_retry_interval; + zval *z_params_lazy_connect; RedisArray *ra = NULL; zend_bool b_index = 0, b_autorehash = 0; long l_retry_interval = 0; + zend_bool b_lazy_connect = 0; HashTable *hHosts = NULL, *hPrev = NULL; /* find entry */ @@ -240,8 +245,18 @@ RedisArray *ra_load_array(const char *name TSRMLS_DC) { } } + /* find retry interval option */ + MAKE_STD_ZVAL(z_params_lazy_connect); + array_init(z_params_lazy_connect); + sapi_module.treat_data(PARSE_STRING, estrdup(INI_STR("redis.arrays.lazyconnect")), z_params_lazy_connect TSRMLS_CC); + if (zend_hash_find(Z_ARRVAL_P(z_params_lazy_connect), name, strlen(name) + 1, (void **) &z_data_pp) != FAILURE) { + if(Z_TYPE_PP(z_data_pp) == IS_STRING && strncmp(Z_STRVAL_PP(z_data_pp), "1", 1) == 0) { + b_lazy_connect = 1; + } + } + /* create RedisArray object */ - ra = ra_make_array(hHosts, z_fun, z_dist, hPrev, b_index, l_retry_interval TSRMLS_CC); + ra = ra_make_array(hHosts, z_fun, z_dist, hPrev, b_index, l_retry_interval, b_lazy_connect TSRMLS_CC); ra->auto_rehash = b_autorehash; /* cleanup */ @@ -257,12 +272,14 @@ RedisArray *ra_load_array(const char *name TSRMLS_DC) { efree(z_params_autorehash); zval_dtor(z_params_retry_interval); efree(z_params_retry_interval); + zval_dtor(z_params_lazy_connect); + efree(z_params_lazy_connect); return ra; } RedisArray * -ra_make_array(HashTable *hosts, zval *z_fun, zval *z_dist, HashTable *hosts_prev, zend_bool b_index, long retry_interval TSRMLS_DC) { +ra_make_array(HashTable *hosts, zval *z_fun, zval *z_dist, HashTable *hosts_prev, zend_bool b_index, long retry_interval, zend_bool lazy_connect TSRMLS_DC) { int count = zend_hash_num_elements(hosts); @@ -280,10 +297,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, retry_interval TSRMLS_CC)) { + if(NULL == ra_load_hosts(ra, hosts, retry_interval, lazy_connect TSRMLS_CC)) { return NULL; } - ra->prev = hosts_prev ? ra_make_array(hosts_prev, z_fun, z_dist, NULL, b_index, retry_interval TSRMLS_CC) : NULL; + ra->prev = hosts_prev ? ra_make_array(hosts_prev, z_fun, z_dist, NULL, b_index, retry_interval, lazy_connect TSRMLS_CC) : NULL; /* copy function if provided */ if(z_fun) { diff --git a/redis_array_impl.h b/redis_array_impl.h index 8dd5201b..62531405 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, long retry_interval TSRMLS_DC); +RedisArray *ra_load_hosts(RedisArray *ra, HashTable *hosts, long retry_interval, zend_bool lazy_connect 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, long retry_interval TSRMLS_DC); +RedisArray *ra_make_array(HashTable *hosts, zval *z_fun, zval *z_dist, HashTable *hosts_prev, zend_bool b_index, long retry_interval, zend_bool lazy_connect 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 009bac51..5261e68d 100644 --- a/redis_session.c +++ b/redis_session.c @@ -277,9 +277,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, retry_interval); + redis_sock = redis_sock_create(url->host, strlen(url->host), url->port, timeout, persistent, persistent_id, retry_interval, 0); } else { /* unix */ - redis_sock = redis_sock_create(url->path, strlen(url->path), 0, timeout, persistent, persistent_id, retry_interval); + redis_sock = redis_sock_create(url->path, strlen(url->path), 0, timeout, persistent, persistent_id, retry_interval, 0); } redis_pool_add(pool, redis_sock, weight, database, prefix, auth TSRMLS_CC); |