diff options
-rw-r--r-- | common.h | 4 | ||||
-rw-r--r-- | library.c | 5 | ||||
-rw-r--r-- | redis.c | 1 | ||||
-rw-r--r-- | redis_commands.c | 28 |
4 files changed, 36 insertions, 2 deletions
@@ -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; /* }}} */ @@ -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); @@ -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) { |