Set TCP keepalive by default.
authorHiroshi Inoue <inoue@tpf.co.jp>
Tue, 14 Jan 2014 10:54:28 +0000 (19:54 +0900)
committerHiroshi Inoue <inoue@tpf.co.jp>
Tue, 14 Jan 2014 10:54:28 +0000 (19:54 +0900)
connection.c
connection.h
dlg_specific.c
dlg_specific.h
socket.c
socket.h

index 28e2636745b59a9212d490b49fd2c1749122faec..054f1c9935972b8fc96156bccd7533ea7576318d 100644 (file)
@@ -300,6 +300,8 @@ CC_conninfo_init(ConnInfo *conninfo, UInt4 option)
    conninfo->cvt_null_date_string = -1;
    conninfo->autocommit_public = SQL_AUTOCOMMIT_ON;
    conninfo->accessible_only = -1;
+   conninfo->ignore_round_trip_time = -1;
+   conninfo->disable_keepalive = -1;
    conninfo->gssauth_use_gssapi = -1;
 #ifdef _HANDLE_ENLIST_IN_DTC_
    conninfo->xa_opt = -1;
@@ -351,6 +353,8 @@ CC_copy_conninfo(ConnInfo *ci, const ConnInfo *sci)
    CORR_VALCPY(cvt_null_date_string);
    CORR_VALCPY(autocommit_public);
    CORR_VALCPY(accessible_only);
+   CORR_VALCPY(ignore_round_trip_time);
+   CORR_VALCPY(disable_keepalive);
    CORR_VALCPY(gssauth_use_gssapi);
    CORR_VALCPY(extra_opts);
 #ifdef _HANDLE_ENLIST_IN_DTC_
@@ -1249,6 +1253,10 @@ mylog("!!! usrname=%s server=%s\n", usrname, ci->server);
        {
            opts[cnt] = "gsslib";   vals[cnt++] = "gssapi";
        }
+       if (ci->disable_keepalive)
+       {
+           opts[cnt] = "keepalives";   vals[cnt++] = "0";
+       }
    }
    else
    {
index 7d055d42e3d70b1f99dc80c64d4c1272e8816b70..16cf87e13d56475b7c1bdec9217ea0bdc1eef7df 100644 (file)
@@ -315,6 +315,8 @@ typedef struct
    signed char cvt_null_date_string;
    signed char autocommit_public;
    signed char accessible_only;
+   signed char ignore_round_trip_time;
+   signed char disable_keepalive;
    signed char gssauth_use_gssapi;
    UInt4       extra_opts;
 #ifdef _HANDLE_ENLIST_IN_DTC_
index 009a2bff3fae3ef10be5a4d7d03f1e0f9a39b7be..96057ca50e361f268cadae60a888f20a61e560ef 100644 (file)
@@ -32,21 +32,39 @@ static void encode(const pgNAME, UCHAR *out, int outlen);
 static pgNAME decode(const UCHAR *in);
 static pgNAME decode_or_remove_braces(const UCHAR *in);
 
-#define    OVR_EXTRA_BITS (BIT_FORCEABBREVCONNSTR | BIT_FAKE_MSS | BIT_BDE_ENVIRONMENT | BIT_CVT_NULL_DATE | BIT_ACCESSIBLE_ONLY)
+#define    OVR_EXTRA_BITS (BIT_FORCEABBREVCONNSTR | BIT_FAKE_MSS | BIT_BDE_ENVIRONMENT | BIT_CVT_NULL_DATE | BIT_ACCESSIBLE_ONLY | BIT_IGNORE_ROUND_TRIP_TIME | BIT_DISABLE_KEEPALIVE)
 UInt4  getExtraOptions(const ConnInfo *ci)
 {
    UInt4   flag = ci->extra_opts & (~OVR_EXTRA_BITS);
 
    if (ci->force_abbrev_connstr > 0)
        flag |= BIT_FORCEABBREVCONNSTR;
+   else if (ci->force_abbrev_connstr == 0)
+       flag &= (~BIT_FORCEABBREVCONNSTR);
    if (ci->fake_mss > 0)
        flag |= BIT_FAKE_MSS;
+   else if (ci->fake_mss == 0)
+       flag &= (~BIT_FAKE_MSS);
    if (ci->bde_environment > 0)
        flag |= BIT_BDE_ENVIRONMENT;
+   else if (ci->bde_environment == 0)
+       flag &= (~BIT_BDE_ENVIRONMENT);
    if (ci->cvt_null_date_string > 0)
        flag |= BIT_CVT_NULL_DATE;
+   else if (ci->cvt_null_date_string == 0)
+       flag &= (~BIT_CVT_NULL_DATE);
    if (ci->accessible_only > 0)
        flag |= BIT_ACCESSIBLE_ONLY;
+   else if (ci->accessible_only == 0)
+       flag &= (~BIT_ACCESSIBLE_ONLY);
+   if (ci->ignore_round_trip_time > 0)
+       flag |= BIT_IGNORE_ROUND_TRIP_TIME;
+   else if (ci->ignore_round_trip_time == 0)
+       flag &= (~BIT_IGNORE_ROUND_TRIP_TIME);
+   if (ci->disable_keepalive > 0)
+       flag |= BIT_DISABLE_KEEPALIVE;
+   else if (ci->disable_keepalive == 0)
+       flag &= (~BIT_DISABLE_KEEPALIVE);
        
    return flag;
 }
@@ -70,6 +88,10 @@ static UInt4 replaceExtraOptions(ConnInfo *ci, UInt4 flag, BOOL overwrite)
        ci->cvt_null_date_string = (0 != (flag & BIT_CVT_NULL_DATE));
    if (overwrite || ci->accessible_only < 0)
        ci->accessible_only = (0 != (flag & BIT_ACCESSIBLE_ONLY));
+   if (overwrite || ci->ignore_round_trip_time < 0)
+       ci->ignore_round_trip_time = (0 != (flag & BIT_IGNORE_ROUND_TRIP_TIME));
+   if (overwrite || ci->disable_keepalive < 0)
+       ci->disable_keepalive = (0 != (flag & BIT_DISABLE_KEEPALIVE));
        
    return (ci->extra_opts = getExtraOptions(ci));
 }
@@ -119,6 +141,10 @@ UInt4  add_removeExtraOptions(ConnInfo *ci, UInt4 aflag, UInt4 dflag)
        ci->cvt_null_date_string = TRUE;
    if (0 != (aflag & BIT_ACCESSIBLE_ONLY))
        ci->accessible_only = TRUE;
+   if (0 != (aflag & BIT_IGNORE_ROUND_TRIP_TIME))
+       ci->ignore_round_trip_time = TRUE;
+   if (0 != (aflag & BIT_DISABLE_KEEPALIVE))
+       ci->disable_keepalive = TRUE;
    if (0 != (dflag & BIT_FORCEABBREVCONNSTR))
        ci->force_abbrev_connstr = FALSE;
    if (0 != (dflag & BIT_FAKE_MSS))
@@ -127,6 +153,10 @@ UInt4  add_removeExtraOptions(ConnInfo *ci, UInt4 aflag, UInt4 dflag)
        ci->cvt_null_date_string = FALSE;
    if (0 != (dflag & BIT_ACCESSIBLE_ONLY))
        ci->accessible_only = FALSE;
+   if (0 != (dflag & BIT_IGNORE_ROUND_TRIP_TIME))
+       ci->ignore_round_trip_time = FALSE;
+   if (0 != (dflag & BIT_DISABLE_KEEPALIVE))
+       ci->disable_keepalive = FALSE;
 
    return (ci->extra_opts = getExtraOptions(ci));
 }
@@ -765,6 +795,12 @@ getDSNdefaults(ConnInfo *ci)
        ci->bde_environment = 0;
    if (ci->cvt_null_date_string < 0)
        ci->cvt_null_date_string = 0;
+   if (ci->accessible_only < 0)
+       ci->accessible_only = 0;
+   if (ci->ignore_round_trip_time < 0)
+       ci->ignore_round_trip_time = 0;
+   if (ci->disable_keepalive < 0)
+       ci->disable_keepalive = 0;
 #ifdef _HANDLE_ENLIST_IN_DTC_
    if (ci->xa_opt < 0)
        ci->xa_opt = DEFAULT_XAOPT;
index c781717826d690111f22f2e143301053396b5201..0c82634eac2b996bbdd84711dc50e30c6ab3065a 100644 (file)
@@ -203,6 +203,7 @@ const char *GetXaLibPath();
 #define    BIT_CVT_NULL_DATE           (1L << 3)
 #define    BIT_ACCESSIBLE_ONLY         (1L << 4)
 #define    BIT_IGNORE_ROUND_TRIP_TIME      (1L << 5)
+#define    BIT_DISABLE_KEEPALIVE           (1L << 6)
 
 /* Connection Defaults */
 #define DEFAULT_PORT               "5432"
index 50d8a981f474b09fb8f65dac6671a3073dc67c0c..df810b0bd75eb2fb4dd2b606a8289b350ddd2297 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -99,9 +99,15 @@ SOCK_Constructor(const ConnectionClass *conn)
        rv->buffer_read_in = 0;
 
        if (conn)
+       {
            rv->buffer_size = conn->connInfo.drivers.socket_buffersize;
+           rv->keepalive = !conn->connInfo.disable_keepalive;
+       }
        else
+       {
            rv->buffer_size = globals.socket_buffersize;
+           rv->keepalive = TRUE;
+       }
        rv->buffer_in = (UCHAR *) malloc(rv->buffer_size);
        if (!rv->buffer_in)
        {
@@ -295,7 +301,9 @@ SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname, long tim
        rest.ai_socktype = SOCK_STREAM;
        rest.ai_family = AF_UNSPEC;
        snprintf(portstr, sizeof(portstr), "%d", port);
+#ifdef AI_NUMERICSERV
        rest.ai_flags |= AI_NUMERICSERV;
+#endif /* AI_NUMERICSERV */
        if (is_numeric_address(hostname))
            /* don't resolve address in getaddrinfo() if not necessary */
            rest.ai_flags |= AI_NUMERICHOST;
@@ -349,6 +357,21 @@ retry:
        }
    }
 #endif /* TCP_NODELAY */
+#ifdef SO_KEEPALIVE
+   if (family != AF_UNIX && self->keepalive)
+   {
+       int i;
+       socklen_t   len;
+
+       i = 1;
+       len = sizeof(i);
+       if (setsockopt(self->socket, SOL_SOCKET, SO_KEEPALIVE, (char *) &i, len) < 0)
+       {
+           SOCK_set_error(self, SOCKET_COULD_NOT_CONNECT, "Could not set socket to SO_KEEPALIVE.");
+           goto cleanup;
+       }
+   }
+#endif /* SO_KEEPALIVE */
 #ifdef WIN32
    {
        long    ioctlsocket_ret = 1;
index 3940175565a8721d08b32f6053134a372dd3b0de..1a5dba2bf6d9a550e4dd531fd80337d7b188a3b2 100644 (file)
--- a/socket.h
+++ b/socket.h
@@ -178,6 +178,7 @@ struct SocketClass_
 
    char        reverse;    /* used to handle Postgres 6.2 protocol
                        * (reverse byte order) */
+   char        keepalive;  /* TCP keepalive */
 };
 
 #define SOCK_get_char(self)    (SOCK_get_next_byte(self, FALSE))