@@ -171,9 +171,102 @@ WaitEventSet *FeBeWaitSet;
171171void
172172pq_init (void )
173173{
174+ Port * port = MyProcPort ;
174175 int socket_pos PG_USED_FOR_ASSERTS_ONLY ;
175176 int latch_pos PG_USED_FOR_ASSERTS_ONLY ;
176177
178+ /* fill in the server (local) address */
179+ port -> laddr .salen = sizeof (port -> laddr .addr );
180+ if (getsockname (port -> sock ,
181+ (struct sockaddr * ) & port -> laddr .addr ,
182+ & port -> laddr .salen ) < 0 )
183+ {
184+ ereport (FATAL ,
185+ (errmsg ("%s() failed: %m" , "getsockname" )));
186+ }
187+
188+ /* select NODELAY and KEEPALIVE options if it's a TCP connection */
189+ if (port -> laddr .addr .ss_family != AF_UNIX )
190+ {
191+ int on ;
192+ #ifdef WIN32
193+ int oldopt ;
194+ int optlen ;
195+ int newopt ;
196+ #endif
197+
198+ #ifdef TCP_NODELAY
199+ on = 1 ;
200+ if (setsockopt (port -> sock , IPPROTO_TCP , TCP_NODELAY ,
201+ (char * ) & on , sizeof (on )) < 0 )
202+ {
203+ ereport (FATAL ,
204+ (errmsg ("%s(%s) failed: %m" , "setsockopt" , "TCP_NODELAY" )));
205+ }
206+ #endif
207+ on = 1 ;
208+ if (setsockopt (port -> sock , SOL_SOCKET , SO_KEEPALIVE ,
209+ (char * ) & on , sizeof (on )) < 0 )
210+ {
211+ ereport (FATAL ,
212+ (errmsg ("%s(%s) failed: %m" , "setsockopt" , "SO_KEEPALIVE" )));
213+ }
214+
215+ #ifdef WIN32
216+
217+ /*
218+ * This is a Win32 socket optimization. The OS send buffer should be
219+ * large enough to send the whole Postgres send buffer in one go, or
220+ * performance suffers. The Postgres send buffer can be enlarged if a
221+ * very large message needs to be sent, but we won't attempt to
222+ * enlarge the OS buffer if that happens, so somewhat arbitrarily
223+ * ensure that the OS buffer is at least PQ_SEND_BUFFER_SIZE * 4.
224+ * (That's 32kB with the current default).
225+ *
226+ * The default OS buffer size used to be 8kB in earlier Windows
227+ * versions, but was raised to 64kB in Windows 2012. So it shouldn't
228+ * be necessary to change it in later versions anymore. Changing it
229+ * unnecessarily can even reduce performance, because setting
230+ * SO_SNDBUF in the application disables the "dynamic send buffering"
231+ * feature that was introduced in Windows 7. So before fiddling with
232+ * SO_SNDBUF, check if the current buffer size is already large enough
233+ * and only increase it if necessary.
234+ *
235+ * See https://support.microsoft.com/kb/823764/EN-US/ and
236+ * https://msdn.microsoft.com/en-us/library/bb736549%28v=vs.85%29.aspx
237+ */
238+ optlen = sizeof (oldopt );
239+ if (getsockopt (port -> sock , SOL_SOCKET , SO_SNDBUF , (char * ) & oldopt ,
240+ & optlen ) < 0 )
241+ {
242+ ereport (FATAL ,
243+ (errmsg ("%s(%s) failed: %m" , "getsockopt" , "SO_SNDBUF" )));
244+ }
245+ newopt = PQ_SEND_BUFFER_SIZE * 4 ;
246+ if (oldopt < newopt )
247+ {
248+ if (setsockopt (port -> sock , SOL_SOCKET , SO_SNDBUF , (char * ) & newopt ,
249+ sizeof (newopt )) < 0 )
250+ {
251+ ereport (FATAL ,
252+ (errmsg ("%s(%s) failed: %m" , "setsockopt" , "SO_SNDBUF" )));
253+ }
254+ }
255+ #endif
256+
257+ /*
258+ * Also apply the current keepalive parameters. If we fail to set a
259+ * parameter, don't error out, because these aren't universally
260+ * supported. (Note: you might think we need to reset the GUC
261+ * variables to 0 in such a case, but it's not necessary because the
262+ * show hooks for these variables report the truth anyway.)
263+ */
264+ (void ) pq_setkeepalivesidle (tcp_keepalives_idle , port );
265+ (void ) pq_setkeepalivesinterval (tcp_keepalives_interval , port );
266+ (void ) pq_setkeepalivescount (tcp_keepalives_count , port );
267+ (void ) pq_settcpusertimeout (tcp_user_timeout , port );
268+ }
269+
177270 /* initialize state variables */
178271 PqSendBufferSize = PQ_SEND_BUFFER_SIZE ;
179272 PqSendBuffer = MemoryContextAlloc (TopMemoryContext , PqSendBufferSize );
@@ -191,21 +284,21 @@ pq_init(void)
191284 * writes.
192285 */
193286#ifndef WIN32
194- if (!pg_set_noblock (MyProcPort -> sock ))
287+ if (!pg_set_noblock (port -> sock ))
195288 ereport (FATAL ,
196289 (errmsg ("could not set socket to nonblocking mode: %m" )));
197290#endif
198291
199292#ifndef WIN32
200293
201294 /* Don't give the socket to any subprograms we execute. */
202- if (fcntl (MyProcPort -> sock , F_SETFD , FD_CLOEXEC ) < 0 )
295+ if (fcntl (port -> sock , F_SETFD , FD_CLOEXEC ) < 0 )
203296 elog (FATAL , "fcntl(F_SETFD) failed on socket: %m" );
204297#endif
205298
206299 FeBeWaitSet = CreateWaitEventSet (NULL , FeBeWaitSetNEvents );
207300 socket_pos = AddWaitEventToSet (FeBeWaitSet , WL_SOCKET_WRITEABLE ,
208- MyProcPort -> sock , NULL , NULL );
301+ port -> sock , NULL , NULL );
209302 latch_pos = AddWaitEventToSet (FeBeWaitSet , WL_LATCH_SET , PGINVALID_SOCKET ,
210303 MyLatch , NULL );
211304 AddWaitEventToSet (FeBeWaitSet , WL_POSTMASTER_DEATH , PGINVALID_SOCKET ,
@@ -713,103 +806,6 @@ StreamConnection(pgsocket server_fd, Port *port)
713806 return STATUS_ERROR ;
714807 }
715808
716- /* fill in the server (local) address */
717- port -> laddr .salen = sizeof (port -> laddr .addr );
718- if (getsockname (port -> sock ,
719- (struct sockaddr * ) & port -> laddr .addr ,
720- & port -> laddr .salen ) < 0 )
721- {
722- ereport (LOG ,
723- (errmsg ("%s() failed: %m" , "getsockname" )));
724- return STATUS_ERROR ;
725- }
726-
727- /* select NODELAY and KEEPALIVE options if it's a TCP connection */
728- if (port -> laddr .addr .ss_family != AF_UNIX )
729- {
730- int on ;
731- #ifdef WIN32
732- int oldopt ;
733- int optlen ;
734- int newopt ;
735- #endif
736-
737- #ifdef TCP_NODELAY
738- on = 1 ;
739- if (setsockopt (port -> sock , IPPROTO_TCP , TCP_NODELAY ,
740- (char * ) & on , sizeof (on )) < 0 )
741- {
742- ereport (LOG ,
743- (errmsg ("%s(%s) failed: %m" , "setsockopt" , "TCP_NODELAY" )));
744- return STATUS_ERROR ;
745- }
746- #endif
747- on = 1 ;
748- if (setsockopt (port -> sock , SOL_SOCKET , SO_KEEPALIVE ,
749- (char * ) & on , sizeof (on )) < 0 )
750- {
751- ereport (LOG ,
752- (errmsg ("%s(%s) failed: %m" , "setsockopt" , "SO_KEEPALIVE" )));
753- return STATUS_ERROR ;
754- }
755-
756- #ifdef WIN32
757-
758- /*
759- * This is a Win32 socket optimization. The OS send buffer should be
760- * large enough to send the whole Postgres send buffer in one go, or
761- * performance suffers. The Postgres send buffer can be enlarged if a
762- * very large message needs to be sent, but we won't attempt to
763- * enlarge the OS buffer if that happens, so somewhat arbitrarily
764- * ensure that the OS buffer is at least PQ_SEND_BUFFER_SIZE * 4.
765- * (That's 32kB with the current default).
766- *
767- * The default OS buffer size used to be 8kB in earlier Windows
768- * versions, but was raised to 64kB in Windows 2012. So it shouldn't
769- * be necessary to change it in later versions anymore. Changing it
770- * unnecessarily can even reduce performance, because setting
771- * SO_SNDBUF in the application disables the "dynamic send buffering"
772- * feature that was introduced in Windows 7. So before fiddling with
773- * SO_SNDBUF, check if the current buffer size is already large enough
774- * and only increase it if necessary.
775- *
776- * See https://support.microsoft.com/kb/823764/EN-US/ and
777- * https://msdn.microsoft.com/en-us/library/bb736549%28v=vs.85%29.aspx
778- */
779- optlen = sizeof (oldopt );
780- if (getsockopt (port -> sock , SOL_SOCKET , SO_SNDBUF , (char * ) & oldopt ,
781- & optlen ) < 0 )
782- {
783- ereport (LOG ,
784- (errmsg ("%s(%s) failed: %m" , "getsockopt" , "SO_SNDBUF" )));
785- return STATUS_ERROR ;
786- }
787- newopt = PQ_SEND_BUFFER_SIZE * 4 ;
788- if (oldopt < newopt )
789- {
790- if (setsockopt (port -> sock , SOL_SOCKET , SO_SNDBUF , (char * ) & newopt ,
791- sizeof (newopt )) < 0 )
792- {
793- ereport (LOG ,
794- (errmsg ("%s(%s) failed: %m" , "setsockopt" , "SO_SNDBUF" )));
795- return STATUS_ERROR ;
796- }
797- }
798- #endif
799-
800- /*
801- * Also apply the current keepalive parameters. If we fail to set a
802- * parameter, don't error out, because these aren't universally
803- * supported. (Note: you might think we need to reset the GUC
804- * variables to 0 in such a case, but it's not necessary because the
805- * show hooks for these variables report the truth anyway.)
806- */
807- (void ) pq_setkeepalivesidle (tcp_keepalives_idle , port );
808- (void ) pq_setkeepalivesinterval (tcp_keepalives_interval , port );
809- (void ) pq_setkeepalivescount (tcp_keepalives_count , port );
810- (void ) pq_settcpusertimeout (tcp_user_timeout , port );
811- }
812-
813809 return STATUS_OK ;
814810}
815811
0 commit comments