|
30 | 30 | * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
31 | 31 | * Portions Copyright (c) 1994, Regents of the University of California
|
32 | 32 | *
|
33 |
| - * $PostgreSQL: pgsql/src/backend/libpq/pqcomm.c,v 1.176 2005/02/22 04:35:57 momjian Exp $ |
| 33 | + * $PostgreSQL: pgsql/src/backend/libpq/pqcomm.c,v 1.177 2005/07/30 15:17:20 momjian Exp $ |
34 | 34 | *
|
35 | 35 | *-------------------------------------------------------------------------
|
36 | 36 | */
|
|
87 | 87 | #include "libpq/libpq.h"
|
88 | 88 | #include "miscadmin.h"
|
89 | 89 | #include "storage/ipc.h"
|
90 |
| - |
| 90 | +#include "utils/guc.h" |
91 | 91 |
|
92 | 92 | /*
|
93 | 93 | * Configuration options
|
@@ -594,6 +594,19 @@ StreamConnection(int server_fd, Port *port)
|
594 | 594 | elog(LOG, "setsockopt(SO_KEEPALIVE) failed: %m");
|
595 | 595 | return STATUS_ERROR;
|
596 | 596 | }
|
| 597 | + |
| 598 | + /* Set default keepalive parameters. This should also catch |
| 599 | + * misconfigurations (non-zero values when socket options aren't |
| 600 | + * supported) |
| 601 | + */ |
| 602 | + if (pq_setkeepalivesidle(tcp_keepalives_idle, port) != STATUS_OK) |
| 603 | + return STATUS_ERROR; |
| 604 | + |
| 605 | + if (pq_setkeepalivesinterval(tcp_keepalives_interval, port) != STATUS_OK) |
| 606 | + return STATUS_ERROR; |
| 607 | + |
| 608 | + if (pq_setkeepalivescount(tcp_keepalives_count, port) != STATUS_OK) |
| 609 | + return STATUS_ERROR; |
597 | 610 | }
|
598 | 611 |
|
599 | 612 | return STATUS_OK;
|
@@ -1158,3 +1171,199 @@ pq_endcopyout(bool errorAbort)
|
1158 | 1171 | /* in non-error case, copy.c will have emitted the terminator line */
|
1159 | 1172 | DoingCopyOut = false;
|
1160 | 1173 | }
|
| 1174 | + |
| 1175 | +int |
| 1176 | +pq_getkeepalivesidle(Port *port) |
| 1177 | +{ |
| 1178 | +#ifdef TCP_KEEPIDLE |
| 1179 | + if (IS_AF_UNIX(port->laddr.addr.ss_family)) |
| 1180 | + return 0; |
| 1181 | + |
| 1182 | + if (port->keepalives_idle != 0) |
| 1183 | + return port->keepalives_idle; |
| 1184 | + |
| 1185 | + if (port->default_keepalives_idle == 0) |
| 1186 | + { |
| 1187 | + socklen_t size = sizeof(port->default_keepalives_idle); |
| 1188 | + if (getsockopt(port->sock, SOL_TCP, TCP_KEEPIDLE, |
| 1189 | + (char *) &port->default_keepalives_idle, |
| 1190 | + &size) < 0) |
| 1191 | + { |
| 1192 | + elog(LOG, "getsockopt(TCP_KEEPIDLE) failed: %m"); |
| 1193 | + return -1; |
| 1194 | + } |
| 1195 | + } |
| 1196 | + |
| 1197 | + return port->default_keepalives_idle; |
| 1198 | +#else |
| 1199 | + return 0; |
| 1200 | +#endif |
| 1201 | +} |
| 1202 | + |
| 1203 | +int |
| 1204 | +pq_setkeepalivesidle(int idle, Port *port) |
| 1205 | +{ |
| 1206 | + if (IS_AF_UNIX(port->laddr.addr.ss_family)) |
| 1207 | + return STATUS_OK; |
| 1208 | + |
| 1209 | +#ifdef TCP_KEEPIDLE |
| 1210 | + if (idle == port->keepalives_idle) |
| 1211 | + return STATUS_OK; |
| 1212 | + |
| 1213 | + if (port->default_keepalives_idle == 0) |
| 1214 | + { |
| 1215 | + if (pq_getkeepalivesidle(port) < 0) |
| 1216 | + return STATUS_ERROR; |
| 1217 | + } |
| 1218 | + |
| 1219 | + if (idle == 0) |
| 1220 | + idle = port->default_keepalives_idle; |
| 1221 | + |
| 1222 | + if (setsockopt(port->sock, SOL_TCP, TCP_KEEPIDLE, |
| 1223 | + (char *) &idle, sizeof(idle)) < 0) |
| 1224 | + { |
| 1225 | + elog(LOG, "setsockopt(TCP_KEEPIDLE) failed: %m"); |
| 1226 | + return STATUS_ERROR; |
| 1227 | + } |
| 1228 | + |
| 1229 | + port->keepalives_idle = idle; |
| 1230 | +#else |
| 1231 | + if (idle != 0) |
| 1232 | + { |
| 1233 | + elog(LOG, "setsockopt(TCP_KEEPIDLE) not supported"); |
| 1234 | + return STATUS_ERROR; |
| 1235 | + } |
| 1236 | +#endif |
| 1237 | + |
| 1238 | + return STATUS_OK; |
| 1239 | +} |
| 1240 | + |
| 1241 | +int |
| 1242 | +pq_getkeepalivesinterval(Port *port) |
| 1243 | +{ |
| 1244 | +#ifdef TCP_KEEPINTVL |
| 1245 | + if (IS_AF_UNIX(port->laddr.addr.ss_family)) |
| 1246 | + return 0; |
| 1247 | + |
| 1248 | + if (port->keepalives_interval != 0) |
| 1249 | + return port->keepalives_interval; |
| 1250 | + |
| 1251 | + if (port->default_keepalives_interval == 0) |
| 1252 | + { |
| 1253 | + socklen_t size = sizeof(port->default_keepalives_interval); |
| 1254 | + if (getsockopt(port->sock, SOL_TCP, TCP_KEEPINTVL, |
| 1255 | + (char *) &port->default_keepalives_interval, |
| 1256 | + &size) < 0) |
| 1257 | + { |
| 1258 | + elog(LOG, "getsockopt(TCP_KEEPINTVL) failed: %m"); |
| 1259 | + return -1; |
| 1260 | + } |
| 1261 | + } |
| 1262 | + |
| 1263 | + return port->default_keepalives_interval; |
| 1264 | +#else |
| 1265 | + return 0; |
| 1266 | +#endif |
| 1267 | +} |
| 1268 | + |
| 1269 | +int |
| 1270 | +pq_setkeepalivesinterval(int interval, Port *port) |
| 1271 | +{ |
| 1272 | + if (IS_AF_UNIX(port->laddr.addr.ss_family)) |
| 1273 | + return STATUS_OK; |
| 1274 | + |
| 1275 | +#ifdef TCP_KEEPINTVL |
| 1276 | + if (interval == port->keepalives_interval) |
| 1277 | + return STATUS_OK; |
| 1278 | + |
| 1279 | + if (port->default_keepalives_interval == 0) { |
| 1280 | + if (pq_getkeepalivesinterval(port) < 0) |
| 1281 | + return STATUS_ERROR; |
| 1282 | + } |
| 1283 | + |
| 1284 | + if (interval == 0) |
| 1285 | + interval = port->default_keepalives_interval; |
| 1286 | + |
| 1287 | + if (setsockopt(port->sock, SOL_TCP, TCP_KEEPINTVL, |
| 1288 | + (char *) &interval, sizeof(interval)) < 0) |
| 1289 | + { |
| 1290 | + elog(LOG, "setsockopt(TCP_KEEPINTVL) failed: %m"); |
| 1291 | + return STATUS_ERROR; |
| 1292 | + } |
| 1293 | + |
| 1294 | + port->keepalives_interval = interval; |
| 1295 | +#else |
| 1296 | + if (interval != 0) |
| 1297 | + { |
| 1298 | + elog(LOG, "setsockopt(TCP_KEEPINTVL) not supported"); |
| 1299 | + return STATUS_ERROR; |
| 1300 | + } |
| 1301 | +#endif |
| 1302 | + |
| 1303 | + return STATUS_OK; |
| 1304 | +} |
| 1305 | + |
| 1306 | +int |
| 1307 | +pq_getkeepalivescount(Port *port) |
| 1308 | +{ |
| 1309 | +#ifdef TCP_KEEPCNT |
| 1310 | + if (IS_AF_UNIX(port->laddr.addr.ss_family)) |
| 1311 | + return 0; |
| 1312 | + |
| 1313 | + if (port->keepalives_count != 0) |
| 1314 | + return port->keepalives_count; |
| 1315 | + |
| 1316 | + if (port->default_keepalives_count == 0) |
| 1317 | + { |
| 1318 | + socklen_t size = sizeof(port->default_keepalives_count); |
| 1319 | + if (getsockopt(port->sock, SOL_TCP, TCP_KEEPCNT, |
| 1320 | + (char *) &port->default_keepalives_count, |
| 1321 | + &size) < 0) |
| 1322 | + { |
| 1323 | + elog(LOG, "getsockopt(TCP_KEEPCNT) failed: %m"); |
| 1324 | + return -1; |
| 1325 | + } |
| 1326 | + } |
| 1327 | + |
| 1328 | + return port->default_keepalives_count; |
| 1329 | +#else |
| 1330 | + return 0; |
| 1331 | +#endif |
| 1332 | +} |
| 1333 | + |
| 1334 | +int |
| 1335 | +pq_setkeepalivescount(int count, Port *port) |
| 1336 | +{ |
| 1337 | + if (IS_AF_UNIX(port->laddr.addr.ss_family)) |
| 1338 | + return STATUS_OK; |
| 1339 | + |
| 1340 | +#ifdef TCP_KEEPCNT |
| 1341 | + if (count == port->keepalives_count) |
| 1342 | + return STATUS_OK; |
| 1343 | + |
| 1344 | + if (port->default_keepalives_count == 0) { |
| 1345 | + if (pq_getkeepalivescount(port) < 0) |
| 1346 | + return STATUS_ERROR; |
| 1347 | + } |
| 1348 | + |
| 1349 | + if (count == 0) |
| 1350 | + count = port->default_keepalives_count; |
| 1351 | + |
| 1352 | + if (setsockopt(port->sock, SOL_TCP, TCP_KEEPCNT, |
| 1353 | + (char *) &count, sizeof(count)) < 0) |
| 1354 | + { |
| 1355 | + elog(LOG, "setsockopt(TCP_KEEPCNT) failed: %m"); |
| 1356 | + return STATUS_ERROR; |
| 1357 | + } |
| 1358 | + |
| 1359 | + port->keepalives_count = count; |
| 1360 | +#else |
| 1361 | + if (count != 0) |
| 1362 | + { |
| 1363 | + elog(LOG, "setsockopt(TCP_KEEPCNT) not supported"); |
| 1364 | + return STATUS_ERROR; |
| 1365 | + } |
| 1366 | +#endif |
| 1367 | + |
| 1368 | + return STATUS_OK; |
| 1369 | +} |
0 commit comments