@ -171,9 +171,102 @@ WaitEventSet *FeBeWaitSet;
void
pq_init ( void )
{
Port * port = MyProcPort ;
int socket_pos PG_USED_FOR_ASSERTS_ONLY ;
int latch_pos PG_USED_FOR_ASSERTS_ONLY ;
/* fill in the server (local) address */
port - > laddr . salen = sizeof ( port - > laddr . addr ) ;
if ( getsockname ( port - > sock ,
( struct sockaddr * ) & port - > laddr . addr ,
& port - > laddr . salen ) < 0 )
{
ereport ( FATAL ,
( errmsg ( " %s() failed: %m " , " getsockname " ) ) ) ;
}
/* select NODELAY and KEEPALIVE options if it's a TCP connection */
if ( port - > laddr . addr . ss_family ! = AF_UNIX )
{
int on ;
# ifdef WIN32
int oldopt ;
int optlen ;
int newopt ;
# endif
# ifdef TCP_NODELAY
on = 1 ;
if ( setsockopt ( port - > sock , IPPROTO_TCP , TCP_NODELAY ,
( char * ) & on , sizeof ( on ) ) < 0 )
{
ereport ( FATAL ,
( errmsg ( " %s(%s) failed: %m " , " setsockopt " , " TCP_NODELAY " ) ) ) ;
}
# endif
on = 1 ;
if ( setsockopt ( port - > sock , SOL_SOCKET , SO_KEEPALIVE ,
( char * ) & on , sizeof ( on ) ) < 0 )
{
ereport ( FATAL ,
( errmsg ( " %s(%s) failed: %m " , " setsockopt " , " SO_KEEPALIVE " ) ) ) ;
}
# ifdef WIN32
/*
* This is a Win32 socket optimization . The OS send buffer should be
* large enough to send the whole Postgres send buffer in one go , or
* performance suffers . The Postgres send buffer can be enlarged if a
* very large message needs to be sent , but we won ' t attempt to
* enlarge the OS buffer if that happens , so somewhat arbitrarily
* ensure that the OS buffer is at least PQ_SEND_BUFFER_SIZE * 4.
* ( That ' s 32 kB with the current default ) .
*
* The default OS buffer size used to be 8 kB in earlier Windows
* versions , but was raised to 64 kB in Windows 2012. So it shouldn ' t
* be necessary to change it in later versions anymore . Changing it
* unnecessarily can even reduce performance , because setting
* SO_SNDBUF in the application disables the " dynamic send buffering "
* feature that was introduced in Windows 7. So before fiddling with
* SO_SNDBUF , check if the current buffer size is already large enough
* and only increase it if necessary .
*
* See https : //support.microsoft.com/kb/823764/EN-US/ and
* https : //msdn.microsoft.com/en-us/library/bb736549%28v=vs.85%29.aspx
*/
optlen = sizeof ( oldopt ) ;
if ( getsockopt ( port - > sock , SOL_SOCKET , SO_SNDBUF , ( char * ) & oldopt ,
& optlen ) < 0 )
{
ereport ( FATAL ,
( errmsg ( " %s(%s) failed: %m " , " getsockopt " , " SO_SNDBUF " ) ) ) ;
}
newopt = PQ_SEND_BUFFER_SIZE * 4 ;
if ( oldopt < newopt )
{
if ( setsockopt ( port - > sock , SOL_SOCKET , SO_SNDBUF , ( char * ) & newopt ,
sizeof ( newopt ) ) < 0 )
{
ereport ( FATAL ,
( errmsg ( " %s(%s) failed: %m " , " setsockopt " , " SO_SNDBUF " ) ) ) ;
}
}
# endif
/*
* Also apply the current keepalive parameters . If we fail to set a
* parameter , don ' t error out , because these aren ' t universally
* supported . ( Note : you might think we need to reset the GUC
* variables to 0 in such a case , but it ' s not necessary because the
* show hooks for these variables report the truth anyway . )
*/
( void ) pq_setkeepalivesidle ( tcp_keepalives_idle , port ) ;
( void ) pq_setkeepalivesinterval ( tcp_keepalives_interval , port ) ;
( void ) pq_setkeepalivescount ( tcp_keepalives_count , port ) ;
( void ) pq_settcpusertimeout ( tcp_user_timeout , port ) ;
}
/* initialize state variables */
PqSendBufferSize = PQ_SEND_BUFFER_SIZE ;
PqSendBuffer = MemoryContextAlloc ( TopMemoryContext , PqSendBufferSize ) ;
@ -191,7 +284,7 @@ pq_init(void)
* writes .
*/
# ifndef WIN32
if ( ! pg_set_noblock ( MyProcP ort- > sock ) )
if ( ! pg_set_noblock ( p ort- > sock ) )
ereport ( FATAL ,
( errmsg ( " could not set socket to nonblocking mode: %m " ) ) ) ;
# endif
@ -199,13 +292,13 @@ pq_init(void)
# ifndef WIN32
/* Don't give the socket to any subprograms we execute. */
if ( fcntl ( MyProcP ort- > sock , F_SETFD , FD_CLOEXEC ) < 0 )
if ( fcntl ( p ort- > sock , F_SETFD , FD_CLOEXEC ) < 0 )
elog ( FATAL , " fcntl(F_SETFD) failed on socket: %m " ) ;
# endif
FeBeWaitSet = CreateWaitEventSet ( NULL , FeBeWaitSetNEvents ) ;
socket_pos = AddWaitEventToSet ( FeBeWaitSet , WL_SOCKET_WRITEABLE ,
MyProcP ort- > sock , NULL , NULL ) ;
p ort- > sock , NULL , NULL ) ;
latch_pos = AddWaitEventToSet ( FeBeWaitSet , WL_LATCH_SET , PGINVALID_SOCKET ,
MyLatch , NULL ) ;
AddWaitEventToSet ( FeBeWaitSet , WL_POSTMASTER_DEATH , PGINVALID_SOCKET ,
@ -713,103 +806,6 @@ StreamConnection(pgsocket server_fd, Port *port)
return STATUS_ERROR ;
}
/* fill in the server (local) address */
port - > laddr . salen = sizeof ( port - > laddr . addr ) ;
if ( getsockname ( port - > sock ,
( struct sockaddr * ) & port - > laddr . addr ,
& port - > laddr . salen ) < 0 )
{
ereport ( LOG ,
( errmsg ( " %s() failed: %m " , " getsockname " ) ) ) ;
return STATUS_ERROR ;
}
/* select NODELAY and KEEPALIVE options if it's a TCP connection */
if ( port - > laddr . addr . ss_family ! = AF_UNIX )
{
int on ;
# ifdef WIN32
int oldopt ;
int optlen ;
int newopt ;
# endif
# ifdef TCP_NODELAY
on = 1 ;
if ( setsockopt ( port - > sock , IPPROTO_TCP , TCP_NODELAY ,
( char * ) & on , sizeof ( on ) ) < 0 )
{
ereport ( LOG ,
( errmsg ( " %s(%s) failed: %m " , " setsockopt " , " TCP_NODELAY " ) ) ) ;
return STATUS_ERROR ;
}
# endif
on = 1 ;
if ( setsockopt ( port - > sock , SOL_SOCKET , SO_KEEPALIVE ,
( char * ) & on , sizeof ( on ) ) < 0 )
{
ereport ( LOG ,
( errmsg ( " %s(%s) failed: %m " , " setsockopt " , " SO_KEEPALIVE " ) ) ) ;
return STATUS_ERROR ;
}
# ifdef WIN32
/*
* This is a Win32 socket optimization . The OS send buffer should be
* large enough to send the whole Postgres send buffer in one go , or
* performance suffers . The Postgres send buffer can be enlarged if a
* very large message needs to be sent , but we won ' t attempt to
* enlarge the OS buffer if that happens , so somewhat arbitrarily
* ensure that the OS buffer is at least PQ_SEND_BUFFER_SIZE * 4.
* ( That ' s 32 kB with the current default ) .
*
* The default OS buffer size used to be 8 kB in earlier Windows
* versions , but was raised to 64 kB in Windows 2012. So it shouldn ' t
* be necessary to change it in later versions anymore . Changing it
* unnecessarily can even reduce performance , because setting
* SO_SNDBUF in the application disables the " dynamic send buffering "
* feature that was introduced in Windows 7. So before fiddling with
* SO_SNDBUF , check if the current buffer size is already large enough
* and only increase it if necessary .
*
* See https : //support.microsoft.com/kb/823764/EN-US/ and
* https : //msdn.microsoft.com/en-us/library/bb736549%28v=vs.85%29.aspx
*/
optlen = sizeof ( oldopt ) ;
if ( getsockopt ( port - > sock , SOL_SOCKET , SO_SNDBUF , ( char * ) & oldopt ,
& optlen ) < 0 )
{
ereport ( LOG ,
( errmsg ( " %s(%s) failed: %m " , " getsockopt " , " SO_SNDBUF " ) ) ) ;
return STATUS_ERROR ;
}
newopt = PQ_SEND_BUFFER_SIZE * 4 ;
if ( oldopt < newopt )
{
if ( setsockopt ( port - > sock , SOL_SOCKET , SO_SNDBUF , ( char * ) & newopt ,
sizeof ( newopt ) ) < 0 )
{
ereport ( LOG ,
( errmsg ( " %s(%s) failed: %m " , " setsockopt " , " SO_SNDBUF " ) ) ) ;
return STATUS_ERROR ;
}
}
# endif
/*
* Also apply the current keepalive parameters . If we fail to set a
* parameter , don ' t error out , because these aren ' t universally
* supported . ( Note : you might think we need to reset the GUC
* variables to 0 in such a case , but it ' s not necessary because the
* show hooks for these variables report the truth anyway . )
*/
( void ) pq_setkeepalivesidle ( tcp_keepalives_idle , port ) ;
( void ) pq_setkeepalivesinterval ( tcp_keepalives_interval , port ) ;
( void ) pq_setkeepalivescount ( tcp_keepalives_count , port ) ;
( void ) pq_settcpusertimeout ( tcp_user_timeout , port ) ;
}
return STATUS_OK ;
}