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:
authorEmmanuel Merali <emmanuel@mobli.com>2013-01-21 20:10:16 +0400
committerEmmanuel Merali <emmanuel@mobli.com>2013-01-21 20:10:16 +0400
commit3fb643211e524112bd9a19792f833b12b68de600 (patch)
tree2d597d3871ff3ed51ea41dff069100fdf12d5fbc
parent07369ed1fb25f5a2e9c9040ef1b41b4dcbce0108 (diff)
Retry delay - selectDB on array
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.
-rw-r--r--common.h1
-rw-r--r--library.c1496
-rw-r--r--library.h2
-rw-r--r--redis.c15
-rw-r--r--redis_array.c57
-rw-r--r--redis_array.h1
-rw-r--r--redis_array_impl.c33
-rw-r--r--redis_array_impl.h4
-rw-r--r--redis_session.c9
9 files changed, 853 insertions, 765 deletions
diff --git a/common.h b/common.h
index b48ac75b..fda59c6a 100644
--- a/common.h
+++ b/common.h
@@ -156,6 +156,7 @@ typedef struct {
char *host;
short port;
double timeout;
+ long retry_interval;
int failed;
int status;
int persistent;
diff --git a/library.c b/library.c
index a954787f..15e71e5a 100644
--- a/library.c
+++ b/library.c
@@ -26,76 +26,83 @@ extern zend_class_entry *redis_exception_ce;
extern zend_class_entry *spl_ce_RuntimeException;
PHPAPI void redis_stream_close(RedisSock *redis_sock TSRMLS_DC) {
- if (!redis_sock->persistent) {
- php_stream_close(redis_sock->stream);
- } else {
- php_stream_pclose(redis_sock->stream);
- }
+ if (!redis_sock->persistent) {
+ php_stream_close(redis_sock->stream);
+ } else {
+ php_stream_pclose(redis_sock->stream);
+ }
}
PHPAPI int redis_check_eof(RedisSock *redis_sock TSRMLS_DC)
{
- int eof;
- int count = 0;
-
- if (!redis_sock->stream)
- return -1;
-
- eof = php_stream_eof(redis_sock->stream);
- for (; eof; count++) {
- if((MULTI == redis_sock->mode) || redis_sock->watching || count == 10) { /* too many failures */
- if(redis_sock->stream) { /* close stream if still here */
- redis_stream_close(redis_sock TSRMLS_CC);
- redis_sock->stream = NULL;
- redis_sock->mode = ATOMIC;
- redis_sock->status = REDIS_SOCK_STATUS_FAILED;
- redis_sock->watching = 0;
- }
- zend_throw_exception(redis_exception_ce, "Connection lost", 0 TSRMLS_CC);
- return -1;
- }
- if(redis_sock->stream) { /* close existing stream before reconnecting */
- redis_stream_close(redis_sock TSRMLS_CC);
- redis_sock->stream = NULL;
- redis_sock->mode = ATOMIC;
- redis_sock->watching = 0;
- }
- redis_sock_connect(redis_sock TSRMLS_CC); /* reconnect */
- if(redis_sock->stream) { /* check for EOF again. */
- eof = php_stream_eof(redis_sock->stream);
- }
+ int eof;
+ int count = 0;
+
+ if (!redis_sock->stream) {
+ return -1;
+ }
+
+ eof = php_stream_eof(redis_sock->stream);
+ for (; eof; count++) {
+ if((MULTI == redis_sock->mode) || redis_sock->watching || count == 10) { /* too many failures */
+ if(redis_sock->stream) { /* close stream if still here */
+ redis_stream_close(redis_sock TSRMLS_CC);
+ redis_sock->stream = NULL;
+ redis_sock->mode = ATOMIC;
+ redis_sock->status = REDIS_SOCK_STATUS_FAILED;
+ redis_sock->watching = 0;
+ }
+ zend_throw_exception(redis_exception_ce, "Connection lost", 0 TSRMLS_CC);
+ return -1;
+ }
+ if(redis_sock->stream) { /* close existing stream before reconnecting */
+ redis_stream_close(redis_sock TSRMLS_CC);
+ redis_sock->stream = NULL;
+ 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);
}
+ }
// Reselect the DB.
- if (count && redis_sock->dbNumber) {
- char *cmd, *response;
- int cmd_len, response_len;
+ if (count && redis_sock->dbNumber) {
+ char *cmd, *response;
+ int cmd_len, response_len;
- cmd_len = redis_cmd_format_static(&cmd, "SELECT", "d", redis_sock->dbNumber);
+ cmd_len = redis_cmd_format_static(&cmd, "SELECT", "d", redis_sock->dbNumber);
- if (redis_sock_write(redis_sock, cmd, cmd_len TSRMLS_CC) < 0) {
- efree(cmd);
- return -1;
- }
- efree(cmd);
+ if (redis_sock_write(redis_sock, cmd, cmd_len TSRMLS_CC) < 0) {
+ efree(cmd);
+ return -1;
+ }
+ efree(cmd);
- if ((response = redis_sock_read(redis_sock, &response_len TSRMLS_CC)) == NULL) {
- return -1;
- }
+ if ((response = redis_sock_read(redis_sock, &response_len TSRMLS_CC)) == NULL) {
+ return -1;
+ }
- if (strncmp(response, "+OK", 3)) {
- efree(response);
- return -1;
- }
- efree(response);
+ if (strncmp(response, "+OK", 3)) {
+ efree(response);
+ return -1;
}
+ efree(response);
+ }
- return 0;
+ return 0;
}
PHPAPI zval *redis_sock_read_multibulk_reply_zval(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock) {
char inbuf[1024];
- int numElems;
+ int numElems;
zval *z_tab;
if(-1 == redis_check_eof(redis_sock TSRMLS_CC)) {
@@ -103,7 +110,7 @@ PHPAPI zval *redis_sock_read_multibulk_reply_zval(INTERNAL_FUNCTION_PARAMETERS,
}
if(php_stream_gets(redis_sock->stream, inbuf, 1024) == NULL) {
- redis_stream_close(redis_sock TSRMLS_CC);
+ redis_stream_close(redis_sock TSRMLS_CC);
redis_sock->stream = NULL;
redis_sock->status = REDIS_SOCK_STATUS_FAILED;
redis_sock->mode = ATOMIC;
@@ -122,7 +129,7 @@ PHPAPI zval *redis_sock_read_multibulk_reply_zval(INTERNAL_FUNCTION_PARAMETERS,
redis_sock_read_multibulk_reply_loop(INTERNAL_FUNCTION_PARAM_PASSTHRU,
redis_sock, z_tab, numElems, 1, UNSERIALIZE_ALL);
- return z_tab;
+ return z_tab;
}
/**
@@ -145,13 +152,13 @@ PHPAPI char *redis_sock_read_bulk_reply(RedisSock *redis_sock, int bytes TSRMLS_
char c;
int i;
- reply = emalloc(bytes+1);
+ reply = emalloc(bytes+1);
while(offset < bytes) {
got = php_stream_read(redis_sock->stream, reply + offset, bytes-offset);
if (got <= 0) {
/* Error or EOF */
- zend_throw_exception(redis_exception_ce, "socket error on read socket", 0 TSRMLS_CC);
+ zend_throw_exception(redis_exception_ce, "socket error on read socket", 0 TSRMLS_CC);
break;
}
offset += got;
@@ -179,7 +186,7 @@ PHPAPI char *redis_sock_read(RedisSock *redis_sock, int *buf_len TSRMLS_DC)
}
if(php_stream_gets(redis_sock->stream, inbuf, 1024) == NULL) {
- redis_stream_close(redis_sock TSRMLS_CC);
+ redis_stream_close(redis_sock TSRMLS_CC);
redis_sock->stream = NULL;
redis_sock->status = REDIS_SOCK_STATUS_FAILED;
redis_sock->mode = ATOMIC;
@@ -190,12 +197,12 @@ PHPAPI char *redis_sock_read(RedisSock *redis_sock, int *buf_len TSRMLS_DC)
switch(inbuf[0]) {
case '-':
- err_len = strlen(inbuf+1) - 2;
- redis_sock_set_err(redis_sock, inbuf+1, err_len);
- /* stale data */
- if(memcmp(inbuf + 1, "-ERR SYNC ", 10) == 0) {
- zend_throw_exception(redis_exception_ce, "SYNC with master in progress", 0 TSRMLS_CC);
- }
+ err_len = strlen(inbuf+1) - 2;
+ redis_sock_set_err(redis_sock, inbuf+1, err_len);
+ /* stale data */
+ if(memcmp(inbuf + 1, "-ERR SYNC ", 10) == 0) {
+ zend_throw_exception(redis_exception_ce, "SYNC with master in progress", 0 TSRMLS_CC);
+ }
return NULL;
case '$':
@@ -212,7 +219,7 @@ PHPAPI char *redis_sock_read(RedisSock *redis_sock, int *buf_len TSRMLS_DC)
case '+':
case ':':
- // Single Line Reply
+ // Single Line Reply
/* :123\r\n */
*buf_len = strlen(inbuf) - 2;
if(*buf_len >= 2) {
@@ -223,12 +230,12 @@ PHPAPI char *redis_sock_read(RedisSock *redis_sock, int *buf_len TSRMLS_DC)
}
default:
- zend_throw_exception_ex(
- redis_exception_ce,
- 0 TSRMLS_CC,
- "protocol error, got '%c' as reply type byte\n",
- inbuf[0]
- );
+ zend_throw_exception_ex(
+ redis_exception_ce,
+ 0 TSRMLS_CC,
+ "protocol error, got '%c' as reply type byte\n",
+ inbuf[0]
+ );
}
return NULL;
@@ -245,42 +252,42 @@ void add_constant_long(zend_class_entry *ce, char *name, int value) {
int
integer_length(int i) {
- int sz = 0;
- int ci = abs(i);
- while (ci > 0) {
- ci /= 10;
- sz++;
- }
- if (i == 0) { /* log 0 doesn't make sense. */
- sz = 1;
- } else if (i < 0) { /* allow for neg sign as well. */
- sz++;
- }
- return sz;
+ int sz = 0;
+ int ci = abs(i);
+ while (ci > 0) {
+ ci /= 10;
+ sz++;
+ }
+ if (i == 0) { /* log 0 doesn't make sense. */
+ sz = 1;
+ } else if (i < 0) { /* allow for neg sign as well. */
+ sz++;
+ }
+ return sz;
}
int
redis_cmd_format_header(char **ret, char *keyword, int arg_count) {
- // Our return buffer
- smart_str buf = {0};
-
- // Keyword length
- int l = strlen(keyword);
-
- smart_str_appendc(&buf, '*');
- smart_str_append_long(&buf, arg_count + 1);
- smart_str_appendl(&buf, _NL, sizeof(_NL) -1);
- smart_str_appendc(&buf, '$');
- smart_str_append_long(&buf, l);
- smart_str_appendl(&buf, _NL, sizeof(_NL) -1);
- smart_str_appendl(&buf, keyword, l);
- smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
-
- // Set our return pointer
- *ret = buf.c;
-
- // Return the length
- return buf.len;
+ // Our return buffer
+ smart_str buf = {0};
+
+ // Keyword length
+ int l = strlen(keyword);
+
+ smart_str_appendc(&buf, '*');
+ smart_str_append_long(&buf, arg_count + 1);
+ smart_str_appendl(&buf, _NL, sizeof(_NL) -1);
+ smart_str_appendc(&buf, '$');
+ smart_str_append_long(&buf, l);
+ smart_str_appendl(&buf, _NL, sizeof(_NL) -1);
+ smart_str_appendl(&buf, keyword, l);
+ smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
+
+ // Set our return pointer
+ *ret = buf.c;
+
+ // Return the length
+ return buf.len;
}
int
@@ -290,74 +297,74 @@ redis_cmd_format_static(char **ret, char *keyword, char *format, ...) {
va_list ap;
smart_str buf = {0};
int l = strlen(keyword);
- char *dbl_str;
- int dbl_len;
-
- va_start(ap, format);
-
- /* add header */
- smart_str_appendc(&buf, '*');
- smart_str_append_long(&buf, strlen(format) + 1);
- smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
- smart_str_appendc(&buf, '$');
- smart_str_append_long(&buf, l);
- smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
- smart_str_appendl(&buf, keyword, l);
- smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
-
- while (*p) {
- smart_str_appendc(&buf, '$');
-
- switch(*p) {
- case 's': {
- char *val = va_arg(ap, char*);
- int val_len = va_arg(ap, int);
- smart_str_append_long(&buf, val_len);
- smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
- smart_str_appendl(&buf, val, val_len);
- }
- break;
-
- case 'f':
- case 'F': {
- double d = va_arg(ap, double);
- REDIS_DOUBLE_TO_STRING(dbl_str, dbl_len, d)
- smart_str_append_long(&buf, dbl_len);
- smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
- smart_str_appendl(&buf, dbl_str, dbl_len);
- efree(dbl_str);
- }
- break;
-
- case 'i':
- case 'd': {
- int i = va_arg(ap, int);
- char tmp[32];
- int tmp_len = snprintf(tmp, sizeof(tmp), "%d", i);
- smart_str_append_long(&buf, tmp_len);
- smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
- smart_str_appendl(&buf, tmp, tmp_len);
- }
- break;
- case 'l':
- case 'L': {
- long l = va_arg(ap, long);
- char tmp[32];
- int tmp_len = snprintf(tmp, sizeof(tmp), "%ld", l);
- smart_str_append_long(&buf, tmp_len);
- smart_str_appendl(&buf, _NL, sizeof(_NL) -1);
- smart_str_appendl(&buf, tmp, tmp_len);
- }
- break;
- }
- p++;
- smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
- }
- smart_str_0(&buf);
-
- *ret = buf.c;
-
- return buf.len;
+ char *dbl_str;
+ int dbl_len;
+
+ va_start(ap, format);
+
+ /* add header */
+ smart_str_appendc(&buf, '*');
+ smart_str_append_long(&buf, strlen(format) + 1);
+ smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
+ smart_str_appendc(&buf, '$');
+ smart_str_append_long(&buf, l);
+ smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
+ smart_str_appendl(&buf, keyword, l);
+ smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
+
+ while (*p) {
+ smart_str_appendc(&buf, '$');
+
+ switch(*p) {
+ case 's': {
+ char *val = va_arg(ap, char*);
+ int val_len = va_arg(ap, int);
+ smart_str_append_long(&buf, val_len);
+ smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
+ smart_str_appendl(&buf, val, val_len);
+ }
+ break;
+
+ case 'f':
+ case 'F': {
+ double d = va_arg(ap, double);
+ REDIS_DOUBLE_TO_STRING(dbl_str, dbl_len, d)
+ smart_str_append_long(&buf, dbl_len);
+ smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
+ smart_str_appendl(&buf, dbl_str, dbl_len);
+ efree(dbl_str);
+ }
+ break;
+
+ case 'i':
+ case 'd': {
+ int i = va_arg(ap, int);
+ char tmp[32];
+ int tmp_len = snprintf(tmp, sizeof(tmp), "%d", i);
+ smart_str_append_long(&buf, tmp_len);
+ smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
+ smart_str_appendl(&buf, tmp, tmp_len);
+ }
+ break;
+ case 'l':
+ case 'L': {
+ long l = va_arg(ap, long);
+ char tmp[32];
+ int tmp_len = snprintf(tmp, sizeof(tmp), "%ld", l);
+ smart_str_append_long(&buf, tmp_len);
+ smart_str_appendl(&buf, _NL, sizeof(_NL) -1);
+ smart_str_appendl(&buf, tmp, tmp_len);
+ }
+ break;
+ }
+ p++;
+ smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
+ }
+ smart_str_0(&buf);
+
+ *ret = buf.c;
+
+ return buf.len;
}
/**
@@ -368,119 +375,119 @@ redis_cmd_format_static(char **ret, char *keyword, char *format, ...) {
int
redis_cmd_format(char **ret, char *format, ...) {
- smart_str buf = {0};
- va_list ap;
- char *p = format;
- char *dbl_str;
- int dbl_len;
-
- va_start(ap, format);
-
- while (*p) {
- if (*p == '%') {
- switch (*(++p)) {
- case 's': {
- char *tmp = va_arg(ap, char*);
- int tmp_len = va_arg(ap, int);
- smart_str_appendl(&buf, tmp, tmp_len);
- }
- break;
-
- case 'F':
- case 'f': {
- double d = va_arg(ap, double);
- REDIS_DOUBLE_TO_STRING(dbl_str, dbl_len, d)
- smart_str_append_long(&buf, dbl_len);
- smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
- smart_str_appendl(&buf, dbl_str, dbl_len);
- efree(dbl_str);
- }
- break;
-
- case 'd':
- case 'i': {
- int i = va_arg(ap, int);
- char tmp[32];
- int tmp_len = snprintf(tmp, sizeof(tmp), "%d", i);
- smart_str_appendl(&buf, tmp, tmp_len);
- }
- break;
- }
- } else {
- smart_str_appendc(&buf, *p);
- }
-
- p++;
- }
-
- smart_str_0(&buf);
-
- *ret = buf.c;
-
- return buf.len;
+ smart_str buf = {0};
+ va_list ap;
+ char *p = format;
+ char *dbl_str;
+ int dbl_len;
+
+ va_start(ap, format);
+
+ while (*p) {
+ if (*p == '%') {
+ switch (*(++p)) {
+ case 's': {
+ char *tmp = va_arg(ap, char*);
+ int tmp_len = va_arg(ap, int);
+ smart_str_appendl(&buf, tmp, tmp_len);
+ }
+ break;
+
+ case 'F':
+ case 'f': {
+ double d = va_arg(ap, double);
+ REDIS_DOUBLE_TO_STRING(dbl_str, dbl_len, d)
+ smart_str_append_long(&buf, dbl_len);
+ smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
+ smart_str_appendl(&buf, dbl_str, dbl_len);
+ efree(dbl_str);
+ }
+ break;
+
+ case 'd':
+ case 'i': {
+ int i = va_arg(ap, int);
+ char tmp[32];
+ int tmp_len = snprintf(tmp, sizeof(tmp), "%d", i);
+ smart_str_appendl(&buf, tmp, tmp_len);
+ }
+ break;
+ }
+ } else {
+ smart_str_appendc(&buf, *p);
+ }
+
+ p++;
+ }
+
+ smart_str_0(&buf);
+
+ *ret = buf.c;
+
+ return buf.len;
}
/*
* Append a command sequence to a Redis command
*/
int redis_cmd_append_str(char **cmd, int cmd_len, char *append, int append_len) {
- // Smart string buffer
- smart_str buf = {0};
+ // Smart string buffer
+ smart_str buf = {0};
- // Append the current command to our smart_str
- smart_str_appendl(&buf, *cmd, cmd_len);
+ // Append the current command to our smart_str
+ smart_str_appendl(&buf, *cmd, cmd_len);
- // Append our new command sequence
- smart_str_appendc(&buf, '$');
- smart_str_append_long(&buf, append_len);
- smart_str_appendl(&buf, _NL, sizeof(_NL) -1);
- smart_str_appendl(&buf, append, append_len);
- smart_str_appendl(&buf, _NL, sizeof(_NL) -1);
+ // Append our new command sequence
+ smart_str_appendc(&buf, '$');
+ smart_str_append_long(&buf, append_len);
+ smart_str_appendl(&buf, _NL, sizeof(_NL) -1);
+ smart_str_appendl(&buf, append, append_len);
+ smart_str_appendl(&buf, _NL, sizeof(_NL) -1);
- // Free our old command
- efree(*cmd);
+ // Free our old command
+ efree(*cmd);
- // Set our return pointer
- *cmd = buf.c;
+ // Set our return pointer
+ *cmd = buf.c;
- // Return new command length
- return buf.len;
+ // Return new command length
+ return buf.len;
}
/*
* Append an integer command to a Redis command
*/
int redis_cmd_append_int(char **cmd, int cmd_len, int append) {
- char int_buf[32];
+ char int_buf[32];
- // Conver to an int, capture length
- int int_len = snprintf(int_buf, sizeof(int_buf), "%d", append);
+ // Conver to an int, capture length
+ int int_len = snprintf(int_buf, sizeof(int_buf), "%d", append);
- // Return the new length
- return redis_cmd_append_str(cmd, cmd_len, int_buf, int_len);
+ // Return the new length
+ return redis_cmd_append_str(cmd, cmd_len, int_buf, int_len);
}
PHPAPI void redis_bulk_double_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) {
char *response;
int response_len;
- double ret;
+ double ret;
if ((response = redis_sock_read(redis_sock, &response_len TSRMLS_CC)) == NULL) {
- IF_MULTI_OR_PIPELINE() {
- add_next_index_bool(z_tab, 0);
- } else {
- RETURN_FALSE;
- }
- return;
+ IF_MULTI_OR_PIPELINE() {
+ add_next_index_bool(z_tab, 0);
+ } else {
+ RETURN_FALSE;
+ }
+ return;
}
ret = atof(response);
efree(response);
IF_MULTI_OR_PIPELINE() {
- add_next_index_double(z_tab, ret);
+ add_next_index_double(z_tab, ret);
} else {
- RETURN_DOUBLE(ret);
+ RETURN_DOUBLE(ret);
}
}
@@ -490,41 +497,41 @@ PHPAPI void redis_type_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_s
long l;
if ((response = redis_sock_read(redis_sock, &response_len TSRMLS_CC)) == NULL) {
- IF_MULTI_OR_PIPELINE() {
- add_next_index_bool(z_tab, 0);
- } else {
- RETURN_FALSE;
- }
+ IF_MULTI_OR_PIPELINE() {
+ add_next_index_bool(z_tab, 0);
+ } else {
+ RETURN_FALSE;
+ }
}
if (strncmp(response, "+string", 7) == 0) {
- l = REDIS_STRING;
+ l = REDIS_STRING;
} else if (strncmp(response, "+set", 4) == 0){
- l = REDIS_SET;
+ l = REDIS_SET;
} else if (strncmp(response, "+list", 5) == 0){
- l = REDIS_LIST;
+ l = REDIS_LIST;
} else if (strncmp(response, "+zset", 5) == 0){
- l = REDIS_ZSET;
+ l = REDIS_ZSET;
} else if (strncmp(response, "+hash", 5) == 0){
- l = REDIS_HASH;
+ l = REDIS_HASH;
} else {
- l = REDIS_NOT_FOUND;
+ l = REDIS_NOT_FOUND;
}
efree(response);
IF_MULTI_OR_PIPELINE() {
- add_next_index_long(z_tab, l);
+ add_next_index_long(z_tab, l);
} else {
- RETURN_LONG(l);
+ RETURN_LONG(l);
}
}
PHPAPI void redis_info_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) {
char *response;
int response_len;
- char *pos, *cur;
- char *key, *value, *p;
- int is_numeric;
+ char *pos, *cur;
+ char *key, *value, *p;
+ int is_numeric;
zval *z_multi_result;
if ((response = redis_sock_read(redis_sock, &response_len TSRMLS_CC)) == NULL) {
@@ -540,13 +547,13 @@ PHPAPI void redis_info_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_s
cur = response;
while(1) {
- /* skip comments and empty lines */
- if(*cur == '#' || *cur == '\r') {
- if(!(cur = strchr(cur, '\n')))
- break;
- cur++;
- continue;
- }
+ /* skip comments and empty lines */
+ if(*cur == '#' || *cur == '\r') {
+ if(!(cur = strchr(cur, '\n')))
+ break;
+ cur++;
+ continue;
+ }
/* key */
pos = strchr(cur, ':');
@@ -601,10 +608,10 @@ PHPAPI void redis_boolean_response_impl(INTERNAL_FUNCTION_PARAMETERS, RedisSock
char ret;
if ((response = redis_sock_read(redis_sock, &response_len TSRMLS_CC)) == NULL) {
- IF_MULTI_OR_PIPELINE() {
+ IF_MULTI_OR_PIPELINE() {
add_next_index_bool(z_tab, 0);
- return;
- }
+ return;
+ }
RETURN_FALSE;
}
ret = response[0];
@@ -620,15 +627,15 @@ PHPAPI void redis_boolean_response_impl(INTERNAL_FUNCTION_PARAMETERS, RedisSock
add_next_index_bool(z_tab, 0);
}
} else {
- if (ret == '+') {
+ if (ret == '+') {
if (success_callback != NULL) {
success_callback(redis_sock);
}
- RETURN_TRUE;
- } else {
- RETURN_FALSE;
- }
- }
+ RETURN_TRUE;
+ } else {
+ RETURN_FALSE;
+ }
+ }
}
PHPAPI void redis_boolean_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) {
@@ -641,38 +648,38 @@ PHPAPI void redis_long_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_s
int response_len;
if ((response = redis_sock_read(redis_sock, &response_len TSRMLS_CC)) == NULL) {
- IF_MULTI_OR_PIPELINE() {
- add_next_index_bool(z_tab, 0);
- return;
- } else {
- RETURN_FALSE;
- }
+ IF_MULTI_OR_PIPELINE() {
+ add_next_index_bool(z_tab, 0);
+ return;
+ } else {
+ RETURN_FALSE;
+ }
}
if(response[0] == ':') {
long long ret = atoll(response + 1);
IF_MULTI_OR_PIPELINE() {
- if(ret > LONG_MAX) { /* overflow */
- add_next_index_stringl(z_tab, response+1, response_len-1, 1);
- } else {
- efree(response);
- add_next_index_long(z_tab, (long)ret);
- }
+ if(ret > LONG_MAX) { /* overflow */
+ add_next_index_stringl(z_tab, response+1, response_len-1, 1);
+ } else {
+ efree(response);
+ add_next_index_long(z_tab, (long)ret);
+ }
} else {
- if(ret > LONG_MAX) { /* overflow */
- RETURN_STRINGL(response+1, response_len-1, 1);
- } else {
- efree(response);
- RETURN_LONG((long)ret);
- }
- }
+ if(ret > LONG_MAX) { /* overflow */
+ RETURN_STRINGL(response+1, response_len-1, 1);
+ } else {
+ efree(response);
+ RETURN_LONG((long)ret);
+ }
+ }
} else {
efree(response);
IF_MULTI_OR_PIPELINE() {
add_next_index_null(z_tab);
} else {
- RETURN_FALSE;
- }
+ RETURN_FALSE;
+ }
}
}
@@ -680,20 +687,20 @@ PHPAPI void redis_long_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_s
PHPAPI int redis_sock_read_multibulk_reply_zipped_with_flag(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, int flag) {
- /*
- int ret = redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab TSRMLS_CC);
- array_zip_values_and_scores(return_value, 0);
- */
+ /*
+ int ret = redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab TSRMLS_CC);
+ array_zip_values_and_scores(return_value, 0);
+ */
char inbuf[1024];
- int numElems;
+ int numElems;
zval *z_multi_result;
if(-1 == redis_check_eof(redis_sock TSRMLS_CC)) {
return -1;
}
if(php_stream_gets(redis_sock->stream, inbuf, 1024) == NULL) {
- redis_stream_close(redis_sock TSRMLS_CC);
+ redis_stream_close(redis_sock TSRMLS_CC);
redis_sock->stream = NULL;
redis_sock->status = REDIS_SOCK_STATUS_FAILED;
redis_sock->mode = ATOMIC;
@@ -717,10 +724,10 @@ PHPAPI int redis_sock_read_multibulk_reply_zipped_with_flag(INTERNAL_FUNCTION_PA
IF_MULTI_OR_PIPELINE() {
add_next_index_zval(z_tab, z_multi_result);
} else {
- *return_value = *z_multi_result;
- zval_copy_ctor(return_value);
- zval_dtor(z_multi_result);
- efree(z_multi_result);
+ *return_value = *z_multi_result;
+ zval_copy_ctor(return_value);
+ zval_dtor(z_multi_result);
+ efree(z_multi_result);
}
return 0;
@@ -728,43 +735,43 @@ PHPAPI int redis_sock_read_multibulk_reply_zipped_with_flag(INTERNAL_FUNCTION_PA
PHPAPI int redis_sock_read_multibulk_reply_zipped(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) {
- return redis_sock_read_multibulk_reply_zipped_with_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, 1);
+ return redis_sock_read_multibulk_reply_zipped_with_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, 1);
}
PHPAPI int redis_sock_read_multibulk_reply_zipped_strings(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) {
- return redis_sock_read_multibulk_reply_zipped_with_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, 0);
+ return redis_sock_read_multibulk_reply_zipped_with_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab, 0);
}
PHPAPI void redis_1_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) {
- char *response;
- int response_len;
- char ret;
-
- if ((response = redis_sock_read(redis_sock, &response_len TSRMLS_CC)) == NULL) {
- IF_MULTI_OR_PIPELINE() {
- add_next_index_bool(z_tab, 0);
- return;
- } else {
- RETURN_FALSE;
- }
- }
- ret = response[1];
- efree(response);
-
- IF_MULTI_OR_PIPELINE() {
- if(ret == '1') {
- add_next_index_bool(z_tab, 1);
- } else {
- add_next_index_bool(z_tab, 0);
- }
- } else {
- if (ret == '1') {
- RETURN_TRUE;
- } else {
- RETURN_FALSE;
- }
- }
+ char *response;
+ int response_len;
+ char ret;
+
+ if ((response = redis_sock_read(redis_sock, &response_len TSRMLS_CC)) == NULL) {
+ IF_MULTI_OR_PIPELINE() {
+ add_next_index_bool(z_tab, 0);
+ return;
+ } else {
+ RETURN_FALSE;
+ }
+ }
+ ret = response[1];
+ efree(response);
+
+ IF_MULTI_OR_PIPELINE() {
+ if(ret == '1') {
+ add_next_index_bool(z_tab, 1);
+ } else {
+ add_next_index_bool(z_tab, 0);
+ }
+ } else {
+ if (ret == '1') {
+ RETURN_TRUE;
+ } else {
+ RETURN_FALSE;
+ }
+ }
}
PHPAPI void redis_string_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) {
@@ -775,25 +782,25 @@ PHPAPI void redis_string_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis
if ((response = redis_sock_read(redis_sock, &response_len TSRMLS_CC)) == NULL) {
IF_MULTI_OR_PIPELINE() {
add_next_index_bool(z_tab, 0);
- return;
+ return;
}
RETURN_FALSE;
}
IF_MULTI_OR_PIPELINE() {
- zval *z = NULL;
- if(redis_unserialize(redis_sock, response, response_len, &z TSRMLS_CC) == 1) {
- efree(response);
- add_next_index_zval(z_tab, z);
- } else {
- add_next_index_stringl(z_tab, response, response_len, 0);
- }
+ zval *z = NULL;
+ if(redis_unserialize(redis_sock, response, response_len, &z TSRMLS_CC) == 1) {
+ efree(response);
+ add_next_index_zval(z_tab, z);
+ } else {
+ add_next_index_stringl(z_tab, response, response_len, 0);
+ }
} else {
- if(redis_unserialize(redis_sock, response, response_len, &return_value TSRMLS_CC) == 0) {
- RETURN_STRINGL(response, response_len, 0);
- } else {
- efree(response);
- }
- }
+ if(redis_unserialize(redis_sock, response, response_len, &return_value TSRMLS_CC) == 0) {
+ RETURN_STRINGL(response, response_len, 0);
+ } else {
+ efree(response);
+ }
+ }
}
/* like string response, but never unserialized. */
@@ -805,15 +812,15 @@ PHPAPI void redis_ping_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_s
if ((response = redis_sock_read(redis_sock, &response_len TSRMLS_CC)) == NULL) {
IF_MULTI_OR_PIPELINE() {
add_next_index_bool(z_tab, 0);
- return;
+ return;
}
RETURN_FALSE;
}
IF_MULTI_OR_PIPELINE() {
- add_next_index_stringl(z_tab, response, response_len, 0);
+ add_next_index_stringl(z_tab, response, response_len, 0);
} else {
- RETURN_STRINGL(response, response_len, 0);
- }
+ RETURN_STRINGL(response, response_len, 0);
+ }
}
@@ -821,7 +828,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;
@@ -831,11 +839,11 @@ 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) {
- size_t persistent_id_len = strlen(persistent_id);
+ size_t persistent_id_len = strlen(persistent_id);
redis_sock->persistent_id = ecalloc(persistent_id_len + 1, 1);
memcpy(redis_sock->persistent_id, persistent_id, persistent_id_len);
} else {
@@ -869,8 +877,8 @@ PHPAPI int redis_sock_connect(RedisSock *redis_sock TSRMLS_DC)
struct timeval tv, *tv_ptr = NULL;
char *host = NULL, *persistent_id = NULL, *errstr = NULL;
int host_len, err = 0;
- php_netstream_data_t *sock;
- int tcp_flag = 1;
+ php_netstream_data_t *sock;
+ int tcp_flag = 1;
if (redis_sock->stream != NULL) {
redis_sock_disconnect(redis_sock TSRMLS_CC);
@@ -879,15 +887,15 @@ PHPAPI int redis_sock_connect(RedisSock *redis_sock TSRMLS_DC)
tv.tv_sec = (time_t)redis_sock->timeout;
tv.tv_usec = (int)((redis_sock->timeout - tv.tv_sec) * 1000000);
if(tv.tv_sec != 0 || tv.tv_usec != 0) {
- tv_ptr = &tv;
+ tv_ptr = &tv;
}
if(redis_sock->host[0] == '/' && redis_sock->port < 1) {
- host_len = spprintf(&host, 0, "unix://%s", redis_sock->host);
+ host_len = spprintf(&host, 0, "unix://%s", redis_sock->host);
} else {
- if(redis_sock->port == 0)
- redis_sock->port = 6379;
- host_len = spprintf(&host, 0, "%s:%d", redis_sock->host, redis_sock->port);
+ if(redis_sock->port == 0)
+ redis_sock->port = 6379;
+ host_len = spprintf(&host, 0, "%s:%d", redis_sock->host, redis_sock->port);
}
if (redis_sock->persistent) {
@@ -899,10 +907,10 @@ PHPAPI int redis_sock_connect(RedisSock *redis_sock TSRMLS_DC)
}
redis_sock->stream = php_stream_xport_create(host, host_len, ENFORCE_SAFE_MODE,
- STREAM_XPORT_CLIENT
- | STREAM_XPORT_CONNECT,
- persistent_id, tv_ptr, NULL, &errstr, &err
- );
+ STREAM_XPORT_CLIENT
+ | STREAM_XPORT_CONNECT,
+ persistent_id, tv_ptr, NULL, &errstr, &err
+ );
if (persistent_id) {
efree(persistent_id);
@@ -916,7 +924,7 @@ PHPAPI int redis_sock_connect(RedisSock *redis_sock TSRMLS_DC)
}
/* set TCP_NODELAY */
- sock = (php_netstream_data_t*)redis_sock->stream->abstract;
+ sock = (php_netstream_data_t*)redis_sock->stream->abstract;
setsockopt(sock->socket, IPPROTO_TCP, TCP_NODELAY, (char *) &tcp_flag, sizeof(int));
php_stream_auto_cleanup(redis_sock->stream);
@@ -967,23 +975,23 @@ PHPAPI int redis_sock_server_open(RedisSock *redis_sock, int force_connect TSRML
PHPAPI int redis_sock_disconnect(RedisSock *redis_sock TSRMLS_DC)
{
if (redis_sock == NULL) {
- return 1;
+ return 1;
}
redis_sock->dbNumber = 0;
if (redis_sock->stream != NULL) {
- if (!redis_sock->persistent) {
- redis_sock_write(redis_sock, "QUIT", sizeof("QUIT") - 1 TSRMLS_CC);
- }
+ if (!redis_sock->persistent) {
+ redis_sock_write(redis_sock, "QUIT", sizeof("QUIT") - 1 TSRMLS_CC);
+ }
- redis_sock->status = REDIS_SOCK_STATUS_DISCONNECTED;
+ redis_sock->status = REDIS_SOCK_STATUS_DISCONNECTED;
redis_sock->watching = 0;
- if(redis_sock->stream && !redis_sock->persistent) { /* still valid after the write? */
- php_stream_close(redis_sock->stream);
- }
- redis_sock->stream = NULL;
+ if(redis_sock->stream && !redis_sock->persistent) { /* still valid after the write? */
+ php_stream_close(redis_sock->stream);
+ }
+ redis_sock->stream = NULL;
- return 1;
+ return 1;
}
return 0;
@@ -992,8 +1000,8 @@ PHPAPI int redis_sock_disconnect(RedisSock *redis_sock TSRMLS_DC)
PHPAPI void redis_send_discard(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock)
{
char *cmd;
- int response_len, cmd_len;
- char * response;
+ int response_len, cmd_len;
+ char * response;
cmd_len = redis_cmd_format_static(&cmd, "DISCARD", "");
@@ -1007,41 +1015,41 @@ PHPAPI void redis_send_discard(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_so
RETURN_FALSE;
}
- if(response_len == 3 && strncmp(response, "+OK", 3) == 0) {
- RETURN_TRUE;
- }
- RETURN_FALSE;
+ if(response_len == 3 && strncmp(response, "+OK", 3) == 0) {
+ RETURN_TRUE;
+ }
+ RETURN_FALSE;
}
/**
* redis_sock_set_err
*/
PHPAPI int redis_sock_set_err(RedisSock *redis_sock, const char *msg, int msg_len) {
- // Allocate/Reallocate our last error member
- if(msg != NULL && msg_len > 0) {
- if(redis_sock->err == NULL) {
- redis_sock->err = emalloc(msg_len + 1);
- } else if(msg_len > redis_sock->err_len) {
- redis_sock->err = erealloc(redis_sock->err, msg_len +1);
- }
-
- // Copy in our new error message, set new length, and null terminate
- memcpy(redis_sock->err, msg, msg_len);
- redis_sock->err[msg_len] = '\0';
- redis_sock->err_len = msg_len;
- } else {
- // Free our last error
- if(redis_sock->err != NULL) {
- efree(redis_sock->err);
- }
-
- // Set to null, with zero length
- redis_sock->err = NULL;
- redis_sock->err_len = 0;
- }
-
- // Success
- return 0;
+ // Allocate/Reallocate our last error member
+ if(msg != NULL && msg_len > 0) {
+ if(redis_sock->err == NULL) {
+ redis_sock->err = emalloc(msg_len + 1);
+ } else if(msg_len > redis_sock->err_len) {
+ redis_sock->err = erealloc(redis_sock->err, msg_len +1);
+ }
+
+ // Copy in our new error message, set new length, and null terminate
+ memcpy(redis_sock->err, msg, msg_len);
+ redis_sock->err[msg_len] = '\0';
+ redis_sock->err_len = msg_len;
+ } else {
+ // Free our last error
+ if(redis_sock->err != NULL) {
+ efree(redis_sock->err);
+ }
+
+ // Set to null, with zero length
+ redis_sock->err = NULL;
+ redis_sock->err_len = 0;
+ }
+
+ // Success
+ return 0;
}
/**
@@ -1050,14 +1058,14 @@ PHPAPI int redis_sock_set_err(RedisSock *redis_sock, const char *msg, int msg_le
PHPAPI int redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx)
{
char inbuf[1024];
- int numElems;
+ int numElems;
zval *z_multi_result;
if(-1 == redis_check_eof(redis_sock TSRMLS_CC)) {
return -1;
}
if(php_stream_gets(redis_sock->stream, inbuf, 1024) == NULL) {
- redis_stream_close(redis_sock TSRMLS_CC);
+ redis_stream_close(redis_sock TSRMLS_CC);
redis_sock->stream = NULL;
redis_sock->status = REDIS_SOCK_STATUS_FAILED;
redis_sock->mode = ATOMIC;
@@ -1092,14 +1100,14 @@ PHPAPI int redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSo
PHPAPI int redis_sock_read_multibulk_reply_raw(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx)
{
char inbuf[1024];
- int numElems;
+ int numElems;
zval *z_multi_result;
if(-1 == redis_check_eof(redis_sock TSRMLS_CC)) {
return -1;
}
if(php_stream_gets(redis_sock->stream, inbuf, 1024) == NULL) {
- redis_stream_close(redis_sock TSRMLS_CC);
+ redis_stream_close(redis_sock TSRMLS_CC);
redis_sock->stream = NULL;
redis_sock->status = REDIS_SOCK_STATUS_FAILED;
redis_sock->mode = ATOMIC;
@@ -1138,17 +1146,17 @@ redis_sock_read_multibulk_reply_loop(INTERNAL_FUNCTION_PARAMETERS, RedisSock *re
while(numElems > 0) {
response = redis_sock_read(redis_sock, &response_len TSRMLS_CC);
if(response != NULL) {
- zval *z = NULL;
- int can_unserialize = unwrap_key;
- if(unserialize_even_only == UNSERIALIZE_ONLY_VALUES && numElems % 2 == 0)
- can_unserialize = 0;
-
- if(can_unserialize && redis_unserialize(redis_sock, response, response_len, &z TSRMLS_CC) == 1) {
- efree(response);
- add_next_index_zval(z_tab, z);
- } else {
- add_next_index_stringl(z_tab, response, response_len, 0);
- }
+ zval *z = NULL;
+ int can_unserialize = unwrap_key;
+ if(unserialize_even_only == UNSERIALIZE_ONLY_VALUES && numElems % 2 == 0)
+ can_unserialize = 0;
+
+ if(can_unserialize && redis_unserialize(redis_sock, response, response_len, &z TSRMLS_CC) == 1) {
+ efree(response);
+ add_next_index_zval(z_tab, z);
+ } else {
+ add_next_index_stringl(z_tab, response, response_len, 0);
+ }
} else {
add_next_index_bool(z_tab, 0);
}
@@ -1164,8 +1172,8 @@ PHPAPI int redis_sock_read_multibulk_reply_assoc(INTERNAL_FUNCTION_PARAMETERS, R
{
char inbuf[1024], *response;
int response_len;
- int i, numElems;
- zval *z_multi_result;
+ int i, numElems;
+ zval *z_multi_result;
zval **z_keys = ctx;
@@ -1173,7 +1181,7 @@ PHPAPI int redis_sock_read_multibulk_reply_assoc(INTERNAL_FUNCTION_PARAMETERS, R
return -1;
}
if(php_stream_gets(redis_sock->stream, inbuf, 1024) == NULL) {
- redis_stream_close(redis_sock TSRMLS_CC);
+ redis_stream_close(redis_sock TSRMLS_CC);
redis_sock->stream = NULL;
redis_sock->status = REDIS_SOCK_STATUS_FAILED;
redis_sock->mode = ATOMIC;
@@ -1192,30 +1200,30 @@ PHPAPI int redis_sock_read_multibulk_reply_assoc(INTERNAL_FUNCTION_PARAMETERS, R
for(i = 0; i < numElems; ++i) {
response = redis_sock_read(redis_sock, &response_len TSRMLS_CC);
if(response != NULL) {
- zval *z = NULL;
- if(redis_unserialize(redis_sock, response, response_len, &z TSRMLS_CC) == 1) {
- efree(response);
- add_assoc_zval_ex(z_multi_result, Z_STRVAL_P(z_keys[i]), 1+Z_STRLEN_P(z_keys[i]), z);
- } else {
- add_assoc_stringl_ex(z_multi_result, Z_STRVAL_P(z_keys[i]), 1+Z_STRLEN_P(z_keys[i]), response, response_len, 0);
- }
- } else {
- add_assoc_bool_ex(z_multi_result, Z_STRVAL_P(z_keys[i]), 1+Z_STRLEN_P(z_keys[i]), 0);
- }
- zval_dtor(z_keys[i]);
- efree(z_keys[i]);
+ zval *z = NULL;
+ if(redis_unserialize(redis_sock, response, response_len, &z TSRMLS_CC) == 1) {
+ efree(response);
+ add_assoc_zval_ex(z_multi_result, Z_STRVAL_P(z_keys[i]), 1+Z_STRLEN_P(z_keys[i]), z);
+ } else {
+ add_assoc_stringl_ex(z_multi_result, Z_STRVAL_P(z_keys[i]), 1+Z_STRLEN_P(z_keys[i]), response, response_len, 0);
+ }
+ } else {
+ add_assoc_bool_ex(z_multi_result, Z_STRVAL_P(z_keys[i]), 1+Z_STRLEN_P(z_keys[i]), 0);
+ }
+ zval_dtor(z_keys[i]);
+ efree(z_keys[i]);
}
efree(z_keys);
IF_MULTI_OR_PIPELINE() {
add_next_index_zval(z_tab, z_multi_result);
} else {
- *return_value = *z_multi_result;
- zval_copy_ctor(return_value);
- INIT_PZVAL(return_value);
- zval_dtor(z_multi_result);
- efree(z_multi_result);
- }
+ *return_value = *z_multi_result;
+ zval_copy_ctor(return_value);
+ INIT_PZVAL(return_value);
+ zval_dtor(z_multi_result);
+ efree(z_multi_result);
+ }
return 0;
}
@@ -1224,10 +1232,10 @@ PHPAPI int redis_sock_read_multibulk_reply_assoc(INTERNAL_FUNCTION_PARAMETERS, R
*/
PHPAPI int redis_sock_write(RedisSock *redis_sock, char *cmd, size_t sz TSRMLS_DC)
{
- if(redis_sock && redis_sock->status == REDIS_SOCK_STATUS_DISCONNECTED) {
- zend_throw_exception(redis_exception_ce, "Connection closed", 0 TSRMLS_CC);
- return -1;
- }
+ if(redis_sock && redis_sock->status == REDIS_SOCK_STATUS_DISCONNECTED) {
+ zend_throw_exception(redis_exception_ce, "Connection closed", 0 TSRMLS_CC);
+ return -1;
+ }
if(-1 == redis_check_eof(redis_sock TSRMLS_CC)) {
return -1;
}
@@ -1240,10 +1248,10 @@ PHPAPI int redis_sock_write(RedisSock *redis_sock, char *cmd, size_t sz TSRMLS_D
PHPAPI void redis_free_socket(RedisSock *redis_sock)
{
if(redis_sock->prefix) {
- efree(redis_sock->prefix);
- }
+ efree(redis_sock->prefix);
+ }
if(redis_sock->err) {
- efree(redis_sock->err);
+ efree(redis_sock->err);
}
efree(redis_sock->host);
efree(redis_sock);
@@ -1252,146 +1260,146 @@ PHPAPI void redis_free_socket(RedisSock *redis_sock)
PHPAPI int
redis_serialize(RedisSock *redis_sock, zval *z, char **val, int *val_len TSRMLS_DC) {
#if ZEND_MODULE_API_NO >= 20100000
- php_serialize_data_t ht;
+ php_serialize_data_t ht;
#else
- HashTable ht;
+ HashTable ht;
#endif
- smart_str sstr = {0};
- zval *z_copy;
- size_t sz;
- uint8_t *val8;
-
- switch(redis_sock->serializer) {
- case REDIS_SERIALIZER_NONE:
- switch(Z_TYPE_P(z)) {
-
- case IS_STRING:
- *val = Z_STRVAL_P(z);
- *val_len = Z_STRLEN_P(z);
- return 0;
-
- case IS_OBJECT:
- MAKE_STD_ZVAL(z_copy);
- ZVAL_STRINGL(z_copy, "Object", 6, 1);
- break;
-
- case IS_ARRAY:
- MAKE_STD_ZVAL(z_copy);
- ZVAL_STRINGL(z_copy, "Array", 5, 1);
- break;
-
- default: /* copy */
- MAKE_STD_ZVAL(z_copy);
- *z_copy = *z;
- zval_copy_ctor(z_copy);
- break;
- }
-
- /* return string */
- convert_to_string(z_copy);
- *val = Z_STRVAL_P(z_copy);
- *val_len = Z_STRLEN_P(z_copy);
- efree(z_copy);
- return 1;
-
- case REDIS_SERIALIZER_PHP:
+ smart_str sstr = {0};
+ zval *z_copy;
+ size_t sz;
+ uint8_t *val8;
+
+ switch(redis_sock->serializer) {
+ case REDIS_SERIALIZER_NONE:
+ switch(Z_TYPE_P(z)) {
+
+ case IS_STRING:
+ *val = Z_STRVAL_P(z);
+ *val_len = Z_STRLEN_P(z);
+ return 0;
+
+ case IS_OBJECT:
+ MAKE_STD_ZVAL(z_copy);
+ ZVAL_STRINGL(z_copy, "Object", 6, 1);
+ break;
+
+ case IS_ARRAY:
+ MAKE_STD_ZVAL(z_copy);
+ ZVAL_STRINGL(z_copy, "Array", 5, 1);
+ break;
+
+ default: /* copy */
+ MAKE_STD_ZVAL(z_copy);
+ *z_copy = *z;
+ zval_copy_ctor(z_copy);
+ break;
+ }
+
+ /* return string */
+ convert_to_string(z_copy);
+ *val = Z_STRVAL_P(z_copy);
+ *val_len = Z_STRLEN_P(z_copy);
+ efree(z_copy);
+ return 1;
+
+ case REDIS_SERIALIZER_PHP:
#if ZEND_MODULE_API_NO >= 20100000
- PHP_VAR_SERIALIZE_INIT(ht);
+ PHP_VAR_SERIALIZE_INIT(ht);
#else
- zend_hash_init(&ht, 10, NULL, NULL, 0);
+ zend_hash_init(&ht, 10, NULL, NULL, 0);
#endif
- php_var_serialize(&sstr, &z, &ht TSRMLS_CC);
- *val = sstr.c;
- *val_len = (int)sstr.len;
+ php_var_serialize(&sstr, &z, &ht TSRMLS_CC);
+ *val = sstr.c;
+ *val_len = (int)sstr.len;
#if ZEND_MODULE_API_NO >= 20100000
- PHP_VAR_SERIALIZE_DESTROY(ht);
+ PHP_VAR_SERIALIZE_DESTROY(ht);
#else
- zend_hash_destroy(&ht);
+ zend_hash_destroy(&ht);
#endif
- return 1;
+ return 1;
- case REDIS_SERIALIZER_IGBINARY:
+ case REDIS_SERIALIZER_IGBINARY:
#ifdef HAVE_REDIS_IGBINARY
- if(igbinary_serialize(&val8, (size_t *)&sz, z TSRMLS_CC) == 0) { /* ok */
- *val = (char*)val8;
- *val_len = (int)sz;
- return 1;
- }
+ if(igbinary_serialize(&val8, (size_t *)&sz, z TSRMLS_CC) == 0) { /* ok */
+ *val = (char*)val8;
+ *val_len = (int)sz;
+ return 1;
+ }
#endif
- return 0;
- }
- return 0;
+ return 0;
+ }
+ return 0;
}
PHPAPI int
redis_unserialize(RedisSock *redis_sock, const char *val, int val_len, zval **return_value TSRMLS_DC) {
- php_unserialize_data_t var_hash;
- int ret;
+ php_unserialize_data_t var_hash;
+ int ret;
- switch(redis_sock->serializer) {
- case REDIS_SERIALIZER_NONE:
- return 0;
+ switch(redis_sock->serializer) {
+ case REDIS_SERIALIZER_NONE:
+ return 0;
- case REDIS_SERIALIZER_PHP:
- if(!*return_value) {
- MAKE_STD_ZVAL(*return_value);
- }
+ case REDIS_SERIALIZER_PHP:
+ if(!*return_value) {
+ MAKE_STD_ZVAL(*return_value);
+ }
#if ZEND_MODULE_API_NO >= 20100000
- PHP_VAR_UNSERIALIZE_INIT(var_hash);
+ PHP_VAR_UNSERIALIZE_INIT(var_hash);
#else
- memset(&var_hash, 0, sizeof(var_hash));
+ memset(&var_hash, 0, sizeof(var_hash));
#endif
- if(!php_var_unserialize(return_value, (const unsigned char**)&val,
- (const unsigned char*)val + val_len, &var_hash TSRMLS_CC)) {
- efree(*return_value);
- ret = 0;
- } else {
- ret = 1;
- }
+ if(!php_var_unserialize(return_value, (const unsigned char**)&val,
+ (const unsigned char*)val + val_len, &var_hash TSRMLS_CC)) {
+ efree(*return_value);
+ ret = 0;
+ } else {
+ ret = 1;
+ }
#if ZEND_MODULE_API_NO >= 20100000
- PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
#else
- var_destroy(&var_hash);
+ var_destroy(&var_hash);
#endif
- return ret;
+ return ret;
- case REDIS_SERIALIZER_IGBINARY:
+ case REDIS_SERIALIZER_IGBINARY:
#ifdef HAVE_REDIS_IGBINARY
- if(!*return_value) {
- MAKE_STD_ZVAL(*return_value);
- }
- if(igbinary_unserialize((const uint8_t *)val, (size_t)val_len, return_value TSRMLS_CC) == 0) {
- return 1;
- }
- efree(*return_value);
+ if(!*return_value) {
+ MAKE_STD_ZVAL(*return_value);
+ }
+ if(igbinary_unserialize((const uint8_t *)val, (size_t)val_len, return_value TSRMLS_CC) == 0) {
+ return 1;
+ }
+ efree(*return_value);
#endif
- return 0;
- break;
- }
- return 0;
+ return 0;
+ break;
+ }
+ return 0;
}
PHPAPI int
redis_key_prefix(RedisSock *redis_sock, char **key, int *key_len TSRMLS_DC) {
- int ret_len;
- char *ret;
-
- if(redis_sock->prefix == NULL || redis_sock->prefix_len == 0) {
- return 0;
- }
-
- ret_len = redis_sock->prefix_len + *key_len;
- ret = ecalloc(1 + ret_len, 1);
- memcpy(ret, redis_sock->prefix, redis_sock->prefix_len);
- memcpy(ret + redis_sock->prefix_len, *key, *key_len);
-
- *key = ret;
- *key_len = ret_len;
- return 1;
+ int ret_len;
+ char *ret;
+
+ if(redis_sock->prefix == NULL || redis_sock->prefix_len == 0) {
+ return 0;
+ }
+
+ ret_len = redis_sock->prefix_len + *key_len;
+ ret = ecalloc(1 + ret_len, 1);
+ memcpy(ret, redis_sock->prefix, redis_sock->prefix_len);
+ memcpy(ret + redis_sock->prefix_len, *key, *key_len);
+
+ *key = ret;
+ *key_len = ret_len;
+ return 1;
}
/*
@@ -1401,60 +1409,60 @@ redis_key_prefix(RedisSock *redis_sock, char **key, int *key_len TSRMLS_DC) {
PHPAPI int
redis_sock_gets(RedisSock *redis_sock, char *buf, int buf_size, size_t *line_size TSRMLS_DC) {
// Handle EOF
- if(-1 == redis_check_eof(redis_sock TSRMLS_CC)) {
+ if(-1 == redis_check_eof(redis_sock TSRMLS_CC)) {
return -1;
}
- if(php_stream_get_line(redis_sock->stream, buf, buf_size, line_size) == NULL) {
- // Close, put our socket state into error
- redis_stream_close(redis_sock TSRMLS_CC);
- redis_sock->stream = NULL;
- redis_sock->status = REDIS_SOCK_STATUS_FAILED;
- redis_sock->mode = ATOMIC;
- redis_sock->watching = 0;
+ if(php_stream_get_line(redis_sock->stream, buf, buf_size, line_size) == NULL) {
+ // Close, put our socket state into error
+ redis_stream_close(redis_sock TSRMLS_CC);
+ redis_sock->stream = NULL;
+ redis_sock->status = REDIS_SOCK_STATUS_FAILED;
+ redis_sock->mode = ATOMIC;
+ redis_sock->watching = 0;
- // Throw a read error exception
- zend_throw_exception(redis_exception_ce, "read error on connection", 0 TSRMLS_CC);
- }
+ // Throw a read error exception
+ zend_throw_exception(redis_exception_ce, "read error on connection", 0 TSRMLS_CC);
+ }
- // We don't need \r\n
- *line_size-=2;
- buf[*line_size]='\0';
+ // We don't need \r\n
+ *line_size-=2;
+ buf[*line_size]='\0';
- // Success!
- return 0;
+ // Success!
+ return 0;
}
PHPAPI int
redis_read_reply_type(RedisSock *redis_sock, REDIS_REPLY_TYPE *reply_type, int *reply_info TSRMLS_DC) {
- // Make sure we haven't lost the connection, even trying to reconnect
- if(-1 == redis_check_eof(redis_sock TSRMLS_CC)) {
- // Failure
- return -1;
- }
-
- // Attempt to read the reply-type byte
- if((*reply_type = php_stream_getc(redis_sock->stream)) == EOF) {
- zend_throw_exception(redis_exception_ce, "socket error on read socket", 0 TSRMLS_CC);
- }
-
- // If this is a BULK, MULTI BULK, or simply an INTEGER response, we can extract the value or size info here
- if(*reply_type == TYPE_INT || *reply_type == TYPE_BULK || *reply_type == TYPE_MULTIBULK) {
- // Buffer to hold size information
- char inbuf[255];
-
- // Read up to our newline
- if(php_stream_gets(redis_sock->stream, inbuf, sizeof(inbuf)) < 0) {
- return -1;
- }
-
- // Set our size response
- *reply_info = atoi(inbuf);
- }
-
- // Success!
- return 0;
+ // Make sure we haven't lost the connection, even trying to reconnect
+ if(-1 == redis_check_eof(redis_sock TSRMLS_CC)) {
+ // Failure
+ return -1;
+ }
+
+ // Attempt to read the reply-type byte
+ if((*reply_type = php_stream_getc(redis_sock->stream)) == EOF) {
+ zend_throw_exception(redis_exception_ce, "socket error on read socket", 0 TSRMLS_CC);
+ }
+
+ // If this is a BULK, MULTI BULK, or simply an INTEGER response, we can extract the value or size info here
+ if(*reply_type == TYPE_INT || *reply_type == TYPE_BULK || *reply_type == TYPE_MULTIBULK) {
+ // Buffer to hold size information
+ char inbuf[255];
+
+ // Read up to our newline
+ if(php_stream_gets(redis_sock->stream, inbuf, sizeof(inbuf)) < 0) {
+ return -1;
+ }
+
+ // Set our size response
+ *reply_info = atoi(inbuf);
+ }
+
+ // Success!
+ return 0;
}
/*
@@ -1462,152 +1470,152 @@ redis_read_reply_type(RedisSock *redis_sock, REDIS_REPLY_TYPE *reply_type, int *
*/
PHPAPI int
redis_read_variant_line(RedisSock *redis_sock, REDIS_REPLY_TYPE reply_type, zval **z_ret TSRMLS_DC) {
- // Buffer to read our single line reply
- char inbuf[1024];
- size_t line_size;
-
- // Attempt to read our single line reply
- if(redis_sock_gets(redis_sock, inbuf, sizeof(inbuf), &line_size TSRMLS_CC) < 0) {
- return -1;
- }
-
- // If this is an error response, check if it is a SYNC error, and throw in that case
- if(reply_type == TYPE_ERR) {
- if(memcmp(inbuf, "ERR SYNC", 9) == 0) {
- zend_throw_exception(redis_exception_ce, "SYNC with master in progress", 0 TSRMLS_CC);
- }
-
- // Set our last error
- redis_sock_set_err(redis_sock, inbuf, line_size);
-
- // Set our response to FALSE
- ZVAL_FALSE(*z_ret);
- } else {
- // Set our response to TRUE
- ZVAL_TRUE(*z_ret);
- }
-
- return 0;
+ // Buffer to read our single line reply
+ char inbuf[1024];
+ size_t line_size;
+
+ // Attempt to read our single line reply
+ if(redis_sock_gets(redis_sock, inbuf, sizeof(inbuf), &line_size TSRMLS_CC) < 0) {
+ return -1;
+ }
+
+ // If this is an error response, check if it is a SYNC error, and throw in that case
+ if(reply_type == TYPE_ERR) {
+ if(memcmp(inbuf, "ERR SYNC", 9) == 0) {
+ zend_throw_exception(redis_exception_ce, "SYNC with master in progress", 0 TSRMLS_CC);
+ }
+
+ // Set our last error
+ redis_sock_set_err(redis_sock, inbuf, line_size);
+
+ // Set our response to FALSE
+ ZVAL_FALSE(*z_ret);
+ } else {
+ // Set our response to TRUE
+ ZVAL_TRUE(*z_ret);
+ }
+
+ return 0;
}
PHPAPI int
redis_read_variant_bulk(RedisSock *redis_sock, int size, zval **z_ret TSRMLS_DC) {
- // Attempt to read the bulk reply
- char *bulk_resp = redis_sock_read_bulk_reply(redis_sock, size TSRMLS_CC);
-
- // Set our reply to FALSE on failure, and the string on success
- if(bulk_resp == NULL) {
- ZVAL_FALSE(*z_ret);
- return -1;
- } else {
- ZVAL_STRINGL(*z_ret, bulk_resp, size, 0);
- return 0;
- }
+ // Attempt to read the bulk reply
+ char *bulk_resp = redis_sock_read_bulk_reply(redis_sock, size TSRMLS_CC);
+
+ // Set our reply to FALSE on failure, and the string on success
+ if(bulk_resp == NULL) {
+ ZVAL_FALSE(*z_ret);
+ return -1;
+ } else {
+ ZVAL_STRINGL(*z_ret, bulk_resp, size, 0);
+ return 0;
+ }
}
PHPAPI int
redis_read_multibulk_recursive(RedisSock *redis_sock, int elements, zval **z_ret TSRMLS_DC) {
- int reply_info;
- REDIS_REPLY_TYPE reply_type;
- zval *z_subelem;
-
- // Iterate while we have elements
- while(elements > 0) {
- // Attempt to read our reply type
- if(redis_read_reply_type(redis_sock, &reply_type, &reply_info TSRMLS_CC) < 0) {
- zend_throw_exception_ex(redis_exception_ce, 0 TSRMLS_CC, "protocol error, couldn't parse MULTI-BULK response\n", reply_type);
- return -1;
- }
-
- // Switch on our reply-type byte
- switch(reply_type) {
- case TYPE_ERR:
- case TYPE_LINE:
- ALLOC_INIT_ZVAL(z_subelem);
- redis_read_variant_line(redis_sock, reply_type, &z_subelem TSRMLS_CC);
- add_next_index_zval(*z_ret, z_subelem);
- break;
- case TYPE_INT:
- // Add our long value
- add_next_index_long(*z_ret, reply_info);
- break;
- case TYPE_BULK:
- // Init a zval for our bulk response, read and add it
- ALLOC_INIT_ZVAL(z_subelem);
- redis_read_variant_bulk(redis_sock, reply_info, &z_subelem TSRMLS_CC);
- add_next_index_zval(*z_ret, z_subelem);
- break;
- case TYPE_MULTIBULK:
- // Construct an array for our sub element, and add it, and recurse
- ALLOC_INIT_ZVAL(z_subelem);
- array_init(z_subelem);
- add_next_index_zval(*z_ret, z_subelem);
- redis_read_multibulk_recursive(redis_sock, reply_info, &z_subelem TSRMLS_CC);
- break;
- }
-
- // Decrement our element counter
- elements--;
- }
-
- return 0;
+ int reply_info;
+ REDIS_REPLY_TYPE reply_type;
+ zval *z_subelem;
+
+ // Iterate while we have elements
+ while(elements > 0) {
+ // Attempt to read our reply type
+ if(redis_read_reply_type(redis_sock, &reply_type, &reply_info TSRMLS_CC) < 0) {
+ zend_throw_exception_ex(redis_exception_ce, 0 TSRMLS_CC, "protocol error, couldn't parse MULTI-BULK response\n", reply_type);
+ return -1;
+ }
+
+ // Switch on our reply-type byte
+ switch(reply_type) {
+ case TYPE_ERR:
+ case TYPE_LINE:
+ ALLOC_INIT_ZVAL(z_subelem);
+ redis_read_variant_line(redis_sock, reply_type, &z_subelem TSRMLS_CC);
+ add_next_index_zval(*z_ret, z_subelem);
+ break;
+ case TYPE_INT:
+ // Add our long value
+ add_next_index_long(*z_ret, reply_info);
+ break;
+ case TYPE_BULK:
+ // Init a zval for our bulk response, read and add it
+ ALLOC_INIT_ZVAL(z_subelem);
+ redis_read_variant_bulk(redis_sock, reply_info, &z_subelem TSRMLS_CC);
+ add_next_index_zval(*z_ret, z_subelem);
+ break;
+ case TYPE_MULTIBULK:
+ // Construct an array for our sub element, and add it, and recurse
+ ALLOC_INIT_ZVAL(z_subelem);
+ array_init(z_subelem);
+ add_next_index_zval(*z_ret, z_subelem);
+ redis_read_multibulk_recursive(redis_sock, reply_info, &z_subelem TSRMLS_CC);
+ break;
+ }
+
+ // Decrement our element counter
+ elements--;
+ }
+
+ return 0;
}
PHPAPI int
redis_read_variant_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab) {
- // Reply type, and reply size vars
- REDIS_REPLY_TYPE reply_type;
- int reply_info;
- //char *bulk_resp;
- zval *z_ret;
-
- // Attempt to read our header
- if(redis_read_reply_type(redis_sock, &reply_type, &reply_info TSRMLS_CC) < 0) {
- return -1;
- }
-
- // Our return ZVAL
- MAKE_STD_ZVAL(z_ret);
-
- // Switch based on our top level reply type
- switch(reply_type) {
- case TYPE_ERR:
- case TYPE_LINE:
- redis_read_variant_line(redis_sock, reply_type, &z_ret TSRMLS_CC);
- break;
- case TYPE_INT:
- ZVAL_LONG(z_ret, reply_info);
- break;
- case TYPE_BULK:
- redis_read_variant_bulk(redis_sock, reply_info, &z_ret TSRMLS_CC);
- break;
- case TYPE_MULTIBULK:
- // Initialize an array for our multi-bulk response
- array_init(z_ret);
-
- // If we've got more than zero elements, parse our multi bulk respoinse recursively
- if(reply_info > -1) {
- redis_read_multibulk_recursive(redis_sock, reply_info, &z_ret TSRMLS_CC);
- }
- break;
- default:
- // Protocol error
- zend_throw_exception_ex(redis_exception_ce, 0 TSRMLS_CC, "protocol error, got '%c' as reply-type byte\n", reply_type);
- break;
- }
-
- IF_MULTI_OR_PIPELINE() {
- add_next_index_zval(z_tab, z_ret);
- } else {
- // Set our return value
- *return_value = *z_ret;
- zval_copy_ctor(return_value);
- zval_dtor(z_ret);
- efree(z_ret);
- }
-
- // Success
- return 0;
+ // Reply type, and reply size vars
+ REDIS_REPLY_TYPE reply_type;
+ int reply_info;
+ //char *bulk_resp;
+ zval *z_ret;
+
+ // Attempt to read our header
+ if(redis_read_reply_type(redis_sock, &reply_type, &reply_info TSRMLS_CC) < 0) {
+ return -1;
+ }
+
+ // Our return ZVAL
+ MAKE_STD_ZVAL(z_ret);
+
+ // Switch based on our top level reply type
+ switch(reply_type) {
+ case TYPE_ERR:
+ case TYPE_LINE:
+ redis_read_variant_line(redis_sock, reply_type, &z_ret TSRMLS_CC);
+ break;
+ case TYPE_INT:
+ ZVAL_LONG(z_ret, reply_info);
+ break;
+ case TYPE_BULK:
+ redis_read_variant_bulk(redis_sock, reply_info, &z_ret TSRMLS_CC);
+ break;
+ case TYPE_MULTIBULK:
+ // Initialize an array for our multi-bulk response
+ array_init(z_ret);
+
+ // If we've got more than zero elements, parse our multi bulk respoinse recursively
+ if(reply_info > -1) {
+ redis_read_multibulk_recursive(redis_sock, reply_info, &z_ret TSRMLS_CC);
+ }
+ break;
+ default:
+ // Protocol error
+ zend_throw_exception_ex(redis_exception_ce, 0 TSRMLS_CC, "protocol error, got '%c' as reply-type byte\n", reply_type);
+ break;
+ }
+
+ IF_MULTI_OR_PIPELINE() {
+ add_next_index_zval(z_tab, z_ret);
+ } else {
+ // Set our return value
+ *return_value = *z_ret;
+ zval_copy_ctor(return_value);
+ zval_dtor(z_ret);
+ efree(z_ret);
+ }
+
+ // Success
+ return 0;
}
/* vim: set tabstop=4 softtabstop=4 noexpandtab shiftwidth=4: */
diff --git a/library.h b/library.h
index ea135bfb..20eaa08a 100644
--- a/library.h
+++ b/library.h
@@ -19,7 +19,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);
diff --git a/redis.c b/redis.c
index fd103d30..0562a79b 100644
--- a/redis.c
+++ b/redis.c
@@ -520,7 +520,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)
{
@@ -556,6 +556,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;
@@ -568,9 +569,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;
}
@@ -579,6 +581,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;
}
@@ -595,7 +602,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);
diff --git a/redis_array.c b/redis_array.c
index d0460f10..be95c50d 100644
--- a/redis_array.c
+++ b/redis_array.c
@@ -51,6 +51,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 +193,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 +234,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 +256,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 +703,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 d5370c82..c38e2fe6 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 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 +67,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 +158,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 +225,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 +255,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 +280,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) {
@@ -1112,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..009bac51 100644
--- a/redis_session.c
+++ b/redis_session.c
@@ -206,6 +206,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 +241,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 +260,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 +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);
+ 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);