aboutsummaryrefslogtreecommitdiff
path: root/src/backend/libpq/pqcomm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/libpq/pqcomm.c')
-rw-r--r--src/backend/libpq/pqcomm.c213
1 files changed, 211 insertions, 2 deletions
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index ce321af4b13..43c2a88a451 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -30,7 +30,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/libpq/pqcomm.c,v 1.176 2005/02/22 04:35:57 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/libpq/pqcomm.c,v 1.177 2005/07/30 15:17:20 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -87,7 +87,7 @@
#include "libpq/libpq.h"
#include "miscadmin.h"
#include "storage/ipc.h"
-
+#include "utils/guc.h"
/*
* Configuration options
@@ -594,6 +594,19 @@ StreamConnection(int server_fd, Port *port)
elog(LOG, "setsockopt(SO_KEEPALIVE) failed: %m");
return STATUS_ERROR;
}
+
+ /* Set default keepalive parameters. This should also catch
+ * misconfigurations (non-zero values when socket options aren't
+ * supported)
+ */
+ if (pq_setkeepalivesidle(tcp_keepalives_idle, port) != STATUS_OK)
+ return STATUS_ERROR;
+
+ if (pq_setkeepalivesinterval(tcp_keepalives_interval, port) != STATUS_OK)
+ return STATUS_ERROR;
+
+ if (pq_setkeepalivescount(tcp_keepalives_count, port) != STATUS_OK)
+ return STATUS_ERROR;
}
return STATUS_OK;
@@ -1158,3 +1171,199 @@ pq_endcopyout(bool errorAbort)
/* in non-error case, copy.c will have emitted the terminator line */
DoingCopyOut = false;
}
+
+int
+pq_getkeepalivesidle(Port *port)
+{
+#ifdef TCP_KEEPIDLE
+ if (IS_AF_UNIX(port->laddr.addr.ss_family))
+ return 0;
+
+ if (port->keepalives_idle != 0)
+ return port->keepalives_idle;
+
+ if (port->default_keepalives_idle == 0)
+ {
+ socklen_t size = sizeof(port->default_keepalives_idle);
+ if (getsockopt(port->sock, SOL_TCP, TCP_KEEPIDLE,
+ (char *) &port->default_keepalives_idle,
+ &size) < 0)
+ {
+ elog(LOG, "getsockopt(TCP_KEEPIDLE) failed: %m");
+ return -1;
+ }
+ }
+
+ return port->default_keepalives_idle;
+#else
+ return 0;
+#endif
+}
+
+int
+pq_setkeepalivesidle(int idle, Port *port)
+{
+ if (IS_AF_UNIX(port->laddr.addr.ss_family))
+ return STATUS_OK;
+
+#ifdef TCP_KEEPIDLE
+ if (idle == port->keepalives_idle)
+ return STATUS_OK;
+
+ if (port->default_keepalives_idle == 0)
+ {
+ if (pq_getkeepalivesidle(port) < 0)
+ return STATUS_ERROR;
+ }
+
+ if (idle == 0)
+ idle = port->default_keepalives_idle;
+
+ if (setsockopt(port->sock, SOL_TCP, TCP_KEEPIDLE,
+ (char *) &idle, sizeof(idle)) < 0)
+ {
+ elog(LOG, "setsockopt(TCP_KEEPIDLE) failed: %m");
+ return STATUS_ERROR;
+ }
+
+ port->keepalives_idle = idle;
+#else
+ if (idle != 0)
+ {
+ elog(LOG, "setsockopt(TCP_KEEPIDLE) not supported");
+ return STATUS_ERROR;
+ }
+#endif
+
+ return STATUS_OK;
+}
+
+int
+pq_getkeepalivesinterval(Port *port)
+{
+#ifdef TCP_KEEPINTVL
+ if (IS_AF_UNIX(port->laddr.addr.ss_family))
+ return 0;
+
+ if (port->keepalives_interval != 0)
+ return port->keepalives_interval;
+
+ if (port->default_keepalives_interval == 0)
+ {
+ socklen_t size = sizeof(port->default_keepalives_interval);
+ if (getsockopt(port->sock, SOL_TCP, TCP_KEEPINTVL,
+ (char *) &port->default_keepalives_interval,
+ &size) < 0)
+ {
+ elog(LOG, "getsockopt(TCP_KEEPINTVL) failed: %m");
+ return -1;
+ }
+ }
+
+ return port->default_keepalives_interval;
+#else
+ return 0;
+#endif
+}
+
+int
+pq_setkeepalivesinterval(int interval, Port *port)
+{
+ if (IS_AF_UNIX(port->laddr.addr.ss_family))
+ return STATUS_OK;
+
+#ifdef TCP_KEEPINTVL
+ if (interval == port->keepalives_interval)
+ return STATUS_OK;
+
+ if (port->default_keepalives_interval == 0) {
+ if (pq_getkeepalivesinterval(port) < 0)
+ return STATUS_ERROR;
+ }
+
+ if (interval == 0)
+ interval = port->default_keepalives_interval;
+
+ if (setsockopt(port->sock, SOL_TCP, TCP_KEEPINTVL,
+ (char *) &interval, sizeof(interval)) < 0)
+ {
+ elog(LOG, "setsockopt(TCP_KEEPINTVL) failed: %m");
+ return STATUS_ERROR;
+ }
+
+ port->keepalives_interval = interval;
+#else
+ if (interval != 0)
+ {
+ elog(LOG, "setsockopt(TCP_KEEPINTVL) not supported");
+ return STATUS_ERROR;
+ }
+#endif
+
+ return STATUS_OK;
+}
+
+int
+pq_getkeepalivescount(Port *port)
+{
+#ifdef TCP_KEEPCNT
+ if (IS_AF_UNIX(port->laddr.addr.ss_family))
+ return 0;
+
+ if (port->keepalives_count != 0)
+ return port->keepalives_count;
+
+ if (port->default_keepalives_count == 0)
+ {
+ socklen_t size = sizeof(port->default_keepalives_count);
+ if (getsockopt(port->sock, SOL_TCP, TCP_KEEPCNT,
+ (char *) &port->default_keepalives_count,
+ &size) < 0)
+ {
+ elog(LOG, "getsockopt(TCP_KEEPCNT) failed: %m");
+ return -1;
+ }
+ }
+
+ return port->default_keepalives_count;
+#else
+ return 0;
+#endif
+}
+
+int
+pq_setkeepalivescount(int count, Port *port)
+{
+ if (IS_AF_UNIX(port->laddr.addr.ss_family))
+ return STATUS_OK;
+
+#ifdef TCP_KEEPCNT
+ if (count == port->keepalives_count)
+ return STATUS_OK;
+
+ if (port->default_keepalives_count == 0) {
+ if (pq_getkeepalivescount(port) < 0)
+ return STATUS_ERROR;
+ }
+
+ if (count == 0)
+ count = port->default_keepalives_count;
+
+ if (setsockopt(port->sock, SOL_TCP, TCP_KEEPCNT,
+ (char *) &count, sizeof(count)) < 0)
+ {
+ elog(LOG, "setsockopt(TCP_KEEPCNT) failed: %m");
+ return STATUS_ERROR;
+ }
+
+ port->keepalives_count = count;
+#else
+ if (count != 0)
+ {
+ elog(LOG, "setsockopt(TCP_KEEPCNT) not supported");
+ return STATUS_ERROR;
+ }
+#endif
+
+ return STATUS_OK;
+}