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:
-rw-r--r--common.h4
-rw-r--r--library.c5
-rw-r--r--redis.c1
-rw-r--r--redis_commands.c28
4 files changed, 36 insertions, 2 deletions
diff --git a/common.h b/common.h
index bdb99b09..708b1e1e 100644
--- a/common.h
+++ b/common.h
@@ -478,7 +478,8 @@ typedef enum _PUBSUB_TYPE {
#define REDIS_OPT_READ_TIMEOUT 3
#define REDIS_OPT_SCAN 4
#define REDIS_OPT_FAILOVER 5
-#define REDIS_OPT_COMPRESSION 6
+#define REDIS_OPT_TCP_KEEPALIVE 6
+#define REDIS_OPT_COMPRESSION 7
/* cluster options */
#define REDIS_FAILOVER_NONE 0
@@ -674,6 +675,7 @@ typedef struct {
int scan;
int readonly;
+ int tcp_keepalive;
} RedisSock;
/* }}} */
diff --git a/library.c b/library.c
index 959a7ade..b5940196 100644
--- a/library.c
+++ b/library.c
@@ -1402,6 +1402,7 @@ redis_sock_create(char *host, int host_len, unsigned short port,
redis_sock->scan = REDIS_SCAN_NORETRY;
redis_sock->readonly = 0;
+ redis_sock->tcp_keepalive = 0;
return redis_sock;
}
@@ -1470,11 +1471,13 @@ PHP_REDIS_API int redis_sock_connect(RedisSock *redis_sock TSRMLS_DC)
return -1;
}
- /* Attempt to set TCP_NODELAY if we're not using a unix socket. */
+ /* Attempt to set TCP_NODELAY/TCP_KEEPALIVE if we're not using a unix socket. */
sock = (php_netstream_data_t*)redis_sock->stream->abstract;
if (!usocket) {
err = setsockopt(sock->socket, IPPROTO_TCP, TCP_NODELAY, (char *) &tcp_flag, sizeof(int));
PHPREDIS_NOTUSED(err);
+ err = setsockopt(sock->socket, SOL_SOCKET, SO_KEEPALIVE, (const void *) &redis_sock->tcp_keepalive, sizeof(int));
+ PHPREDIS_NOTUSED(err);
}
php_stream_auto_cleanup(redis_sock->stream);
diff --git a/redis.c b/redis.c
index 18e7ef90..df18decd 100644
--- a/redis.c
+++ b/redis.c
@@ -678,6 +678,7 @@ static void add_class_constants(zend_class_entry *ce, int is_cluster TSRMLS_DC)
zend_declare_class_constant_long(ce, ZEND_STRL("OPT_SERIALIZER"), REDIS_OPT_SERIALIZER TSRMLS_CC);
zend_declare_class_constant_long(ce, ZEND_STRL("OPT_PREFIX"), REDIS_OPT_PREFIX TSRMLS_CC);
zend_declare_class_constant_long(ce, ZEND_STRL("OPT_READ_TIMEOUT"), REDIS_OPT_READ_TIMEOUT TSRMLS_CC);
+ zend_declare_class_constant_long(ce, ZEND_STRL("OPT_TCP_KEEPALIVE"), REDIS_OPT_TCP_KEEPALIVE TSRMLS_CC);
zend_declare_class_constant_long(ce, ZEND_STRL("OPT_COMPRESSION"), REDIS_OPT_COMPRESSION TSRMLS_CC);
/* serializer */
diff --git a/redis_commands.c b/redis_commands.c
index 26cd9f9d..5e25a3fe 100644
--- a/redis_commands.c
+++ b/redis_commands.c
@@ -23,6 +23,10 @@
#endif
#include "redis_commands.h"
+
+#include "php_network.h"
+#include <netinet/tcp.h> /* TCP_KEEPALIVE */
+
#include <zend_exceptions.h>
/* Local passthrough macro for command construction. Given that these methods
@@ -3038,6 +3042,8 @@ void redis_getoption_handler(INTERNAL_FUNCTION_PARAMETERS,
RETURN_NULL();
case REDIS_OPT_READ_TIMEOUT:
RETURN_DOUBLE(redis_sock->read_timeout);
+ case REDIS_OPT_TCP_KEEPALIVE:
+ RETURN_LONG(redis_sock->tcp_keepalive);
case REDIS_OPT_SCAN:
RETURN_LONG(redis_sock->scan);
case REDIS_OPT_FAILOVER:
@@ -3055,6 +3061,8 @@ void redis_setoption_handler(INTERNAL_FUNCTION_PARAMETERS,
char *val_str;
struct timeval read_tv;
strlen_t val_len;
+ int tcp_keepalive = 0;
+ php_netstream_data_t *sock;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &option,
&val_str, &val_len) == FAILURE)
@@ -3105,6 +3113,26 @@ void redis_setoption_handler(INTERNAL_FUNCTION_PARAMETERS,
&read_tv);
}
RETURN_TRUE;
+ case REDIS_OPT_TCP_KEEPALIVE:
+
+ /* Don't set TCP_KEEPALIVE if we're using a unix socket. */
+ if (ZSTR_VAL(redis_sock->host)[0] == '/' && redis_sock->port < 1) {
+ RETURN_FALSE;
+ }
+ tcp_keepalive = atol(val_str) > 0 ? 1 : 0;
+ if (redis_sock->tcp_keepalive == tcp_keepalive) {
+ RETURN_TRUE;
+ }
+ if(redis_sock->stream) {
+ /* set TCP_KEEPALIVE */
+ sock = (php_netstream_data_t*)redis_sock->stream->abstract;
+ if (setsockopt(sock->socket, SOL_SOCKET, SO_KEEPALIVE, (const void*) &tcp_keepalive,
+ sizeof(int)) == -1) {
+ RETURN_FALSE;
+ }
+ redis_sock->tcp_keepalive = tcp_keepalive;
+ }
+ RETURN_TRUE;
case REDIS_OPT_SCAN:
val_long = atol(val_str);
if(val_long==REDIS_SCAN_NORETRY || val_long==REDIS_SCAN_RETRY) {