Skip to Content.
Sympa Menu

freetds - [freetds] [PATCH] Configurable TCP KeepAlives

freetds AT lists.ibiblio.org

Subject: FreeTDS Development Group

List archive

Chronological Thread  
  • From: "Andrew Victor" <avictor.za AT gmail.com>
  • To: freetds AT lists.ibiblio.org
  • Subject: [freetds] [PATCH] Configurable TCP KeepAlives
  • Date: Fri, 8 Aug 2008 10:12:50 +0200

hi,

The TCP KeepAlive is currently enabled, but uses the standard OS
setting of 2 hours.
It can be useful to detect sooner if the SQL server has disappeared or
closed the connection.

The attached patch allows the TCP KeepAlive settings to be
configurable via the freetds.conf file.
The new settings are:
keepalive idle (seconds)
keepalive interval (seconds)
keepalive count (counter)

If any of the above values are not configured, then the OS default will be
used.


Regards,
Andrew Victor
diff -urN freetds-0.82/include/tds.h freetds-0.82.new/include/tds.h
--- freetds-0.82/include/tds.h	2008-08-07 17:40:59.000000000 +0200
+++ freetds-0.82.new/include/tds.h	2008-08-07 17:41:46.000000000 +0200
@@ -806,6 +806,10 @@
 #define TDS_STR_ENCRYPTION_OFF	 "off"
 #define TDS_STR_ENCRYPTION_REQUEST "request"
 #define TDS_STR_ENCRYPTION_REQUIRE "require"
+/* keepalive */
+#define TDS_KEEPALIVE_IDLE "keepalive idle"
+#define TDS_KEEPALIVE_INTERVAL "keepalive interval"
+#define TDS_KEEPALIVE_COUNT "keepalive count"
 
 
 /* TODO do a better check for alignment than this */
@@ -878,6 +882,11 @@
 	int broken_dates;
 	int broken_money;
 	int emul_little_endian;
+
+	/* tcp keepalive */
+	int keepalive_idle;
+	int keepalive_interval;
+	int keepalive_count;
 } TDSCONNECTION;
 
 typedef struct tds_locale
@@ -1329,6 +1338,10 @@
 	/* timeout stuff from Jeff */
 	TDS_INT query_timeout;
 	TDSENV env;
+	/* keepalive info */
+	int keepalive_idle;
+	int keepalive_interval;
+	int keepalive_count;
 
 	/* dynamic placeholder stuff */
 	/*@dependent@*/ TDSDYNAMIC *cur_dyn;	/**< dynamic structure in use */
diff -urN freetds-0.82/src/tds/config.c freetds-0.82.new/src/tds/config.c
--- freetds-0.82/src/tds/config.c	2007-12-23 23:12:02.000000000 +0200
+++ freetds-0.82.new/src/tds/config.c	2008-08-07 17:30:53.000000000 +0200
@@ -532,6 +532,12 @@
 		tds_dstr_copy(&connection->instance_name, value);
 	} else if (!strcmp(option, TDS_STR_ENCRYPTION)) {
 		tds_config_encryption(value, connection);
+	} else if (!strcmp(option, TDS_KEEPALIVE_IDLE)) {
+		connection->keepalive_idle = atoi(value);
+	} else if (!strcmp(option, TDS_KEEPALIVE_INTERVAL)) {
+		connection->keepalive_interval = atoi(value);
+	} else if (!strcmp(option, TDS_KEEPALIVE_COUNT)) {
+		connection->keepalive_count = atoi(value);
 	} else {
 		tdsdump_log(TDS_DBG_INFO1, "UNRECOGNIZED option '%s' ... ignoring.\n", option);
 	}
diff -urN freetds-0.82/src/tds/login.c freetds-0.82.new/src/tds/login.c
--- freetds-0.82/src/tds/login.c	2007-12-31 12:06:50.000000000 +0200
+++ freetds-0.82.new/src/tds/login.c	2008-08-07 17:31:21.000000000 +0200
@@ -399,6 +399,11 @@
 	/* Jeff's hack - begin */
 	tds->query_timeout = connect_timeout ? connect_timeout : connection->query_timeout;
 	/* end */
+
+	/* setup keepalive times */
+	tds->keepalive_idle = connection->keepalive_idle;
+	tds->keepalive_interval = connection->keepalive_interval;
+	tds->keepalive_count = connection->keepalive_count;
 
 	/* verify that ip_addr is not empty */
 	if (tds_dstr_isempty(&connection->ip_addr)) {
diff -urN freetds-0.82/src/tds/mem.c freetds-0.82.new/src/tds/mem.c
--- freetds-0.82/src/tds/mem.c	2007-12-31 12:06:50.000000000 +0200
+++ freetds-0.82.new/src/tds/mem.c	2008-08-07 17:39:01.000000000 +0200
@@ -747,6 +747,9 @@
 	connection->minor_version = TDS_DEF_MINOR;
 	connection->port = TDS_DEF_PORT;
 	connection->block_size = 0;
+	connection->keepalive_idle = 0;
+	connection->keepalive_interval = 0;
+	connection->keepalive_count = 0;
 	/* TODO use system default ?? */
 	if (!tds_dstr_copy(&connection->client_charset, "ISO-8859-1"))
 		goto Cleanup;
@@ -975,6 +978,10 @@
 	tds_socket->s = INVALID_SOCKET;
 	tds_socket->state = TDS_DEAD;
 	tds_socket->env_chg_func = NULL;
+	/* keepalive */
+	tds_socket->keepalive_idle = 0;
+	tds_socket->keepalive_interval = 0;
+	tds_socket->keepalive_count = 0;
 	return tds_socket;
       Cleanup:
 	tds_free_socket(tds_socket);
diff -urN freetds-0.82/src/tds/net.c freetds-0.82.new/src/tds/net.c
--- freetds-0.82/src/tds/net.c	2008-08-07 17:40:59.000000000 +0200
+++ freetds-0.82.new/src/tds/net.c	2008-08-07 17:40:12.000000000 +0200
@@ -220,6 +220,27 @@
 #ifdef SO_KEEPALIVE
 	len = 1;
 	setsockopt(tds->s, SOL_SOCKET, SO_KEEPALIVE, (const void *) &len, sizeof(len));
+
+	/* Amount to time before starting to send keepalives */
+	if (tds->keepalive_idle > 0) {
+		tdsdump_log(TDS_DBG_NETWORK, "TDS: Setting keeplive idle interval: %i\n", tds->keepalive_idle);
+		len = tds->keepalive_idle;
+		setsockopt(tds->s, SOL_TCP, TCP_KEEPIDLE, (const void *) &len, sizeof(len));
+	}
+
+	/* Interval at which to send keepalive packets */
+	if (tds->keepalive_interval > 0) {
+		tdsdump_log(TDS_DBG_NETWORK, "TDS: Setting keeplive probe interval: %i\n", tds->keepalive_interval);
+		len = tds->keepalive_interval;
+		setsockopt(tds->s, SOL_TCP, TCP_KEEPINTVL, (const void *) &len, sizeof(len));
+	}
+
+	/* Number of keepalive packets to send */
+	if (tds->keepalive_count > 0) {
+		tdsdump_log(TDS_DBG_NETWORK, "TDS: Setting keeplive probe count: %i\n", tds->keepalive_count);
+		len = tds->keepalive_count;
+		setsockopt(tds->s, SOL_TCP, TCP_KEEPCNT, (const void *) &len, sizeof(len));
+	}
 #endif
 
 	len = 1;
@@ -300,6 +321,24 @@
 		goto not_available;
 	}
 
+#ifdef SO_KEEPALIVE
+	len = 0;
+	getsockopt(tds->s, SOL_SOCKET, SO_KEEPALIVE, (void *) &len, &optlen);
+	tdsdump_log(TDS_DBG_NETWORK, "TDS: KeepAlives: %s\n", (len) ? "yes" : "no");
+
+	len = 0;
+	getsockopt(tds->s, SOL_TCP, TCP_KEEPIDLE, (void *) &len, &optlen);
+	tdsdump_log(TDS_DBG_NETWORK, "TDS: KeepAlive Idle: %i\n", len);
+
+	len = 0;
+	getsockopt(tds->s, SOL_TCP, TCP_KEEPINTVL, (void *) &len, &optlen);
+	tdsdump_log(TDS_DBG_NETWORK, "TDS: KeepAlive Interval: %i\n", len);
+
+	len = 0;
+	getsockopt(tds->s, SOL_TCP, TCP_KEEPCNT, (void *) &len, &optlen);
+	tdsdump_log(TDS_DBG_NETWORK, "TDS: KeepAlive Count: %i\n", len);
+#endif
+
 	tdsdump_log(TDS_DBG_ERROR, "tds_open_socket() succeeded\n");
 	return TDS_SUCCEED;
 	



Archive powered by MHonArc 2.6.24.

Top of Page