From c0763ba1579fbad705cd29e256fb083376fb0e07 Mon Sep 17 00:00:00 2001 From: Shehjar Tikoo Date: Tue, 18 May 2010 02:20:17 +0000 Subject: socket: Support TCP-KEEPALIVE Introduces two new socket options: 1. transport.socket.keepalive: bool Sets keepalive on a transport. On by default. 2. transport.socket.keepalive-interval: integer Number of seconds between each keepalive message on the socket. Default in linux is 2 hours. To change that value for a given transport, use this option. Integer value is interval in seconds. Signed-off-by: Shehjar Tikoo Signed-off-by: Anand V. Avati BUG: 754 (enable tcp keepalive) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=754 --- transport/socket/src/socket.c | 80 +++++++++++++++++++++++++++++++++++++++++++ transport/socket/src/socket.h | 4 +++ 2 files changed, 84 insertions(+) diff --git a/transport/socket/src/socket.c b/transport/socket/src/socket.c index 28b828f29a2..4d4b01b5cf8 100644 --- a/transport/socket/src/socket.c +++ b/transport/socket/src/socket.c @@ -245,6 +245,38 @@ __socket_nodelay (int fd) return ret; } + +int +__socket_keepalive (int fd, int keepalive_intvl) +{ + int on = 1; + int ret = -1; + + ret = setsockopt (fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)); + if (ret == -1) + goto err; + + if (keepalive_intvl == GF_USE_DEFAULT_KEEPALIVE) + goto done; + + ret = setsockopt (fd, SOL_TCP, TCP_KEEPIDLE, &keepalive_intvl, + sizeof (keepalive_intvl)); + if (ret == -1) + goto err; + + ret = setsockopt (fd, SOL_TCP, TCP_KEEPINTVL, &keepalive_intvl, + sizeof (keepalive_intvl)); + if (ret == -1) + goto err; +done: + gf_log ("", GF_LOG_TRACE, "Keep-alive enabled for socket %d, interval " + "%d", fd, keepalive_intvl); + +err: + return ret; +} + + int __socket_connect_finish (int fd) { @@ -891,6 +923,15 @@ socket_server_event_handler (int fd, int idx, void *data, } } + if (priv->keepalive) { + ret = __socket_keepalive (new_sock, + priv->keepaliveintvl); + if (ret == -1) + gf_log (this->xl->name, GF_LOG_ERROR, + "Failed to set keep-alive: %s", + strerror (errno)); + } + new_trans = CALLOC (1, sizeof (*new_trans)); new_trans->xl = this->xl; new_trans->fini = this->fini; @@ -1067,6 +1108,15 @@ socket_connect (transport_t *this) } } + if (priv->keepalive) { + ret = __socket_keepalive (priv->sock, + priv->keepaliveintvl); + if (ret == -1) + gf_log (this->xl->name, GF_LOG_ERROR, + "Failed to set keep-alive: %s", + strerror (errno)); + } + SA (&this->myinfo.sockaddr)->sa_family = SA (&this->peerinfo.sockaddr)->sa_family; @@ -1369,6 +1419,7 @@ socket_init (transport_t *this) gf_boolean_t tmp_bool = 0; uint64_t windowsize = GF_DEFAULT_SOCKET_WINDOW_SIZE; char *optstr = NULL; + uint32_t keepalive = 0; if (this->private) { gf_log (this->xl->name, GF_LOG_DEBUG, @@ -1449,6 +1500,29 @@ socket_init (transport_t *this) priv->lowlat = 1; } + /* Enable Keep-alive by default. */ + priv->keepalive = 1; + priv->keepaliveintvl = GF_USE_DEFAULT_KEEPALIVE; + if (dict_get_str (this->xl->options, "transport.socket.keepalive", + &optstr) == 0) { + if (gf_string2boolean (optstr, &tmp_bool) == -1) { + gf_log (this->xl->name, GF_LOG_ERROR, + "'transport.socket.keepalive' takes only " + "boolean options, not taking any action"); + tmp_bool = 1; + } + + if (!tmp_bool) + priv->keepalive = 0; + + } + + if (dict_get_uint32 (this->xl->options, + "transport.socket.keepalive-interval", + &keepalive) == 0) { + priv->keepaliveintvl = keepalive; + } + priv->windowsize = (int)windowsize; this->private = priv; @@ -1525,6 +1599,12 @@ struct volume_options options[] = { { .key = {"transport.socket.lowlat"}, .type = GF_OPTION_TYPE_BOOL }, + { .key = {"transport.socket.keepalive"}, + .type = GF_OPTION_TYPE_BOOL + }, + { .key = {"transport.socket.keepalive-interval"}, + .type = GF_OPTION_TYPE_INT + }, { .key = {NULL} } }; diff --git a/transport/socket/src/socket.h b/transport/socket/src/socket.h index 44715697db1..5a287a72c98 100644 --- a/transport/socket/src/socket.h +++ b/transport/socket/src/socket.h @@ -52,6 +52,8 @@ #define GF_MAX_SOCKET_WINDOW_SIZE (1 * GF_UNIT_MB) #define GF_MIN_SOCKET_WINDOW_SIZE (128 * GF_UNIT_KB) +#define GF_USE_DEFAULT_KEEPALIVE (-1) + typedef enum { SOCKET_PROTO_STATE_NADA = 0, SOCKET_PROTO_STATE_HEADER_COMING, @@ -118,6 +120,8 @@ typedef struct { int windowsize; char lowlat; char nodelay; + int keepalive; + int keepaliveintvl; } socket_private_t; -- cgit