On Sat, Feb 13, 2010 at 2:13 AM, Euler Taveira de Oliveira
<[email protected]> 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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers