On Sat, Feb 13, 2010 at 2:13 AM, Euler Taveira de Oliveira <eu...@timbira.com> wrote: > Marko Kreen escreveu: >> 3) Support all 3 parameters (keepidle, keepintvl, keepcnt) >> and ignore parameters not supported by OS. >> > +1. AFAIR, we already do that for the backend.
+1 from me, too. Here is the patch which provides those three parameters as conninfo options. Should this patch be added into the first CommitFest for v9.1? Regards, -- Fujii Masao NIPPON TELEGRAPH AND TELEPHONE CORPORATION NTT Open Source Software Center
*** a/doc/src/sgml/libpq.sgml --- b/doc/src/sgml/libpq.sgml *************** *** 280,285 **** --- 280,327 ---- </listitem> </varlistentry> + <varlistentry id="libpq-keepalives-idle" xreflabel="keepalives_idle"> + <term><literal>keepalives_idle</literal></term> + <listitem> + <para> + On systems that support the <symbol>TCP_KEEPIDLE</symbol> socket option, + specifies the number of seconds between sending keepalives on an otherwise + idle connection. A value of zero uses the system default. + If <symbol>TCP_KEEPIDLE</symbol> is not supported, this parameter must be + zero or must not be specified. This parameter is ignored for connections + made via a Unix-domain socket. + </para> + </listitem> + </varlistentry> + + <varlistentry id="libpq-keepalives-interval" xreflabel="keepalives_interval"> + <term><literal>keepalives_interval</literal></term> + <listitem> + <para> + On systems that support the <symbol>TCP_KEEPINTVL</symbol> socket option, + specifies how long, in seconds, to wait for a response to a keepalive before + retransmitting. A value of zero uses the system default. + If <symbol>TCP_KEEPINTVL</symbol> is not supported, this parameter must be + zero or must not be specified. This parameter is ignored for connections + made via a Unix-domain socket. + </para> + </listitem> + </varlistentry> + + <varlistentry id="libpq-keepalives-count" xreflabel="keepalives_count"> + <term><literal>keepalives_count</literal></term> + <listitem> + <para> + On systems that support the <symbol>TCP_KEEPCNT</symbol> socket option, + specifies how many keepalives can be lost before the connection is + considered dead. A value of zero uses the system default. + If <symbol>TCP_KEEPCNT</symbol> is not supported, this parameter must be + zero or must not be specified. This parameter is ignored for connections + made via a Unix-domain socket. + </para> + </listitem> + </varlistentry> + <varlistentry id="libpq-connect-tty" xreflabel="tty"> <term><literal>tty</literal></term> <listitem> *************** *** 6013,6018 **** myEventProc(PGEventId evtId, void *evtInfo, void *passThrough) --- 6055,6090 ---- <listitem> <para> <indexterm> + <primary><envar>PGKEEPALIVESIDLE</envar></primary> + </indexterm> + <envar>PGKEEPALIVESIDLE</envar> behaves the same as the <xref + linkend="libpq-keepalives-idle"> connection parameter. + </para> + </listitem> + + <listitem> + <para> + <indexterm> + <primary><envar>PGKEEPALIVESINTERVAL</envar></primary> + </indexterm> + <envar>PGKEEPALIVESINTERVAL</envar> behaves the same as the <xref + linkend="libpq-keepalives-interval"> connection parameter. + </para> + </listitem> + + <listitem> + <para> + <indexterm> + <primary><envar>PGKEEPALIVESCOUNT</envar></primary> + </indexterm> + <envar>PGKEEPALIVESCOUNT</envar> behaves the same as the <xref + linkend="libpq-keepalives-count"> connection parameter. + </para> + </listitem> + + <listitem> + <para> + <indexterm> <primary><envar>PGSSLMODE</envar></primary> </indexterm> <envar>PGSSLMODE</envar> behaves the same as the <xref *** a/src/interfaces/libpq/fe-connect.c --- b/src/interfaces/libpq/fe-connect.c *************** *** 180,185 **** static const PQconninfoOption PQconninfoOptions[] = { --- 180,194 ---- {"fallback_application_name", NULL, NULL, NULL, "Fallback-Application-Name", "", 64}, + {"keepalives_idle", "PGKEEPALIVESIDLE", NULL, NULL, + "TCP-Keepalive-Idle", "", 10}, /* strlen(INT32_MAX) == 10 */ + + {"keepalives_interval", "PGKEEPALIVESINTERVAL", NULL, NULL, + "TCP-Keepalive-Interval", "", 10}, /* strlen(INT32_MAX) == 10 */ + + {"keepalives_count", "PGKEEPALIVESCOUNT", NULL, NULL, + "TCP-Keepalive-Count", "", 10}, /* strlen(INT32_MAX) == 10 */ + #ifdef USE_SSL /* *************** *** 547,552 **** fillPGconn(PGconn *conn, PQconninfoOption *connOptions) --- 556,567 ---- conn->pgpass = tmp ? strdup(tmp) : NULL; tmp = conninfo_getval(connOptions, "connect_timeout"); conn->connect_timeout = tmp ? strdup(tmp) : NULL; + tmp = conninfo_getval(connOptions, "keepalives_idle"); + conn->keepalives_idle = tmp ? strdup(tmp) : NULL; + tmp = conninfo_getval(connOptions, "keepalives_interval"); + conn->keepalives_interval = tmp ? strdup(tmp) : NULL; + tmp = conninfo_getval(connOptions, "keepalives_count"); + conn->keepalives_count = tmp ? strdup(tmp) : NULL; tmp = conninfo_getval(connOptions, "sslmode"); conn->sslmode = tmp ? strdup(tmp) : NULL; tmp = conninfo_getval(connOptions, "sslkey"); *************** *** 937,942 **** connectFailureMessage(PGconn *conn, int errorno) --- 952,1065 ---- } + static int + setKeepalivesIdle(PGconn *conn) + { + int idle; + + if (conn->keepalives_idle == NULL || IS_AF_UNIX(conn->laddr.addr.ss_family)) + return 1; + + idle = atoi(conn->keepalives_idle); + if (idle < 0) + idle = 0; + + #ifdef TCP_KEEPIDLE + if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPIDLE, + (char *) &idle, sizeof(idle)) < 0) + { + char sebuf[256]; + + appendPQExpBuffer(&conn->errorMessage, + libpq_gettext("setsockopt(TCP_KEEPIDLE) failed: %s\n"), + SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); + return 0; + } + #else + if (idle != 0) + { + appendPQExpBuffer(&conn->errorMessage, + libpq_gettext("setsockopt(TCP_KEEPIDLE) not supported")); + return 0; + } + #endif + + return 1; + } + + + static int + setKeepalivesInterval(PGconn *conn) + { + int interval; + + if (conn->keepalives_interval == NULL || IS_AF_UNIX(conn->laddr.addr.ss_family)) + return 1; + + interval = atoi(conn->keepalives_interval); + if (interval < 0) + interval = 0; + + #ifdef TCP_KEEPINTVL + if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPINTVL, + (char *) &interval, sizeof(interval)) < 0) + { + char sebuf[256]; + + appendPQExpBuffer(&conn->errorMessage, + libpq_gettext("setsockopt(TCP_KEEPINTVL) failed: %s\n"), + SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); + return 0; + } + #else + if (interval != 0) + { + appendPQExpBuffer(&conn->errorMessage, + libpq_gettext("setsockopt(TCP_KEEPINTVL) not supported")); + return 0; + } + #endif + + return 1; + } + + + static int + setKeepalivesCount(PGconn *conn) + { + int count; + + if (conn->keepalives_count == NULL || IS_AF_UNIX(conn->laddr.addr.ss_family)) + return 1; + + count = atoi(conn->keepalives_count); + if (count < 0) + count = 0; + + #ifdef TCP_KEEPCNT + if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPCNT, + (char *) &count, sizeof(count)) < 0) + { + char sebuf[256]; + + appendPQExpBuffer(&conn->errorMessage, + libpq_gettext("setsockopt(TCP_KEEPCNT) failed: %s\n"), + SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); + return 0; + } + #else + if (count != 0) + { + appendPQExpBuffer(&conn->errorMessage, + libpq_gettext("setsockopt(TCP_KEEPCNT) not supported")); + return 0; + } + #endif + + return 1; + } + + /* ---------- * connectDBStart - * Begin the process of making a connection to the backend. *************** *** 1285,1292 **** keep_going: /* We will come back to here until there is /* * Select socket options: no delay of outgoing data for ! * TCP sockets, nonblock mode, close-on-exec. Fail if any ! * of this fails. */ if (!IS_AF_UNIX(addr_cur->ai_family)) { --- 1408,1415 ---- /* * Select socket options: no delay of outgoing data for ! * TCP sockets, nonblock mode, close-on-exec and keepalives. ! * Fail if any of this fails. */ if (!IS_AF_UNIX(addr_cur->ai_family)) { *************** *** 1322,1327 **** keep_going: /* We will come back to here until there is --- 1445,1476 ---- } #endif /* F_SETFD */ + if (!IS_AF_UNIX(conn->laddr.addr.ss_family)) + { + int on; + + on = 1; + if (setsockopt(conn->sock, SOL_SOCKET, SO_KEEPALIVE, + (char *) &on, sizeof(on)) < 0) + { + appendPQExpBuffer(&conn->errorMessage, + libpq_gettext("setsockopt(SO_KEEPALIVE) failed: %s\n"), + SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); + closesocket(conn->sock); + conn->sock = -1; + conn->addr_cur = addr_cur->ai_next; + continue; + } + } + if (!setKeepalivesIdle(conn) || !setKeepalivesInterval(conn) || + !setKeepalivesCount(conn)) + { + closesocket(conn->sock); + conn->sock = -1; + conn->addr_cur = addr_cur->ai_next; + continue; + } + /*---------- * We have three methods of blocking SIGPIPE during * send() calls to this socket: *************** *** 2280,2285 **** freePGconn(PGconn *conn) --- 2429,2440 ---- free(conn->pguser); if (conn->pgpass) free(conn->pgpass); + if (conn->keepalives_idle) + free(conn->keepalives_idle); + if (conn->keepalives_interval) + free(conn->keepalives_interval); + if (conn->keepalives_count) + free(conn->keepalives_count); if (conn->sslmode) free(conn->sslmode); if (conn->sslcert) *** a/src/interfaces/libpq/libpq-int.h --- b/src/interfaces/libpq/libpq-int.h *************** *** 301,306 **** struct pg_conn --- 301,309 ---- char *replication; /* connect as the replication standby? */ char *pguser; /* Postgres username and password, if any */ char *pgpass; + char *keepalives_idle; /* time between issuing TCP keepalives */ + char *keepalives_interval; /* time between TCP keepalive retransmits */ + char *keepalives_count; /* maximum number of TCP keepalive retransmits */ char *sslmode; /* SSL mode (require,prefer,allow,disable) */ char *sslkey; /* client key filename */ char *sslcert; /* client certificate filename */
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers