]> granicus.if.org Git - postgresql/commitdiff
Try to ensure that stats collector's receive buffer size is at least 100KB.
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 30 May 2017 00:27:45 +0000 (20:27 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 30 May 2017 00:27:45 +0000 (20:27 -0400)
Back-patch of commit 8b0b6303e991079726e83d17401405e94da11564.

Discussion: https://postgr.es/m/22173.1494788088@sss.pgh.pa.us

src/backend/postmaster/pgstat.c

index 620ccdeb382b3f29f5a3904c40e5052325110e37..a3edfedc6ff5a4168ae4ac426b9cb4ba0da1fddb 100644 (file)
@@ -92,6 +92,9 @@
 #define PGSTAT_POLL_LOOP_COUNT (PGSTAT_MAX_WAIT_TIME / PGSTAT_RETRY_DELAY)
 #define PGSTAT_INQ_LOOP_COUNT  (PGSTAT_INQ_INTERVAL / PGSTAT_RETRY_DELAY)
 
+/* Minimum receive buffer size for the collector's socket. */
+#define PGSTAT_MIN_RCVBUF              (100 * 1024)
+
 
 /* ----------
  * The initial size hints for the hash tables used in the collector.
@@ -537,6 +540,35 @@ retry2:
                goto startup_failed;
        }
 
+       /*
+        * Try to ensure that the socket's receive buffer is at least
+        * PGSTAT_MIN_RCVBUF bytes, so that it won't easily overflow and lose
+        * data.  Use of UDP protocol means that we are willing to lose data under
+        * heavy load, but we don't want it to happen just because of ridiculously
+        * small default buffer sizes (such as 8KB on older Windows versions).
+        */
+       {
+               int                     old_rcvbuf;
+               int                     new_rcvbuf;
+               ACCEPT_TYPE_ARG3 rcvbufsize = sizeof(old_rcvbuf);
+
+               if (getsockopt(pgStatSock, SOL_SOCKET, SO_RCVBUF,
+                                          (char *) &old_rcvbuf, &rcvbufsize) < 0)
+               {
+                       elog(LOG, "getsockopt(SO_RCVBUF) failed: %m");
+                       /* if we can't get existing size, always try to set it */
+                       old_rcvbuf = 0;
+               }
+
+               new_rcvbuf = PGSTAT_MIN_RCVBUF;
+               if (old_rcvbuf < new_rcvbuf)
+               {
+                       if (setsockopt(pgStatSock, SOL_SOCKET, SO_RCVBUF,
+                                                  (char *) &new_rcvbuf, sizeof(new_rcvbuf)) < 0)
+                               elog(LOG, "setsockopt(SO_RCVBUF) failed: %m");
+               }
+       }
+
        pg_freeaddrinfo_all(hints.ai_family, addrs);
 
        return;