slap_ssf_t local_ssf = LDAP_PVT_SASL_LOCAL_SSF;
struct runqueue_s slapd_rq;
+#ifdef LDAP_TCP_BUFFER
+int slapd_tcp_rmem;
+int slapd_tcp_wmem;
+#endif /* LDAP_TCP_BUFFER */
+
Listener **slap_listeners = NULL;
#ifndef SLAPD_LISTEN_BACKLOG
;
static int emfile;
+static time_t chk_writetime;
+
static volatile int waking;
#ifdef NO_THREADS
#define WAKE_LISTENER(w) do { \
/***************************************
* Use epoll infrastructure - epoll(4) *
***************************************/
-
-#undef SLAP_EVENT_ACK /* events trigger once per descriptor */
-
# define SLAP_EVENT_FNAME "epoll"
# define SLAP_EVENTS_ARE_INDEXED 0
# define SLAP_EPOLL_SOCK_IX(s) (slap_daemon.sd_index[(s)])
int rc; \
SLAP_EPOLL_SOCK_IX((s)) = slap_daemon.sd_nfds; \
SLAP_EPOLL_SOCK_EP((s)).data.ptr = (l) ? (l) : (void *)(&SLAP_EPOLL_SOCK_IX(s)); \
- SLAP_EPOLL_SOCK_EV((s)) = EPOLLIN|EPOLLET; \
+ SLAP_EPOLL_SOCK_EV((s)) = EPOLLIN; \
rc = epoll_ctl(slap_daemon.sd_epfd, EPOLL_CTL_ADD, \
(s), &SLAP_EPOLL_SOCK_EP((s))); \
if ( rc == 0 ) { \
} while (0)
#elif defined(SLAP_X_DEVPOLL) && defined(HAVE_DEVPOLL)
+
/*************************************************************
* Use Solaris' (>= 2.7) /dev/poll infrastructure - poll(7d) *
*************************************************************/
-
-#define SLAP_EVENT_ACK 1 /* events keep signalling unless we stop them */
-
# define SLAP_EVENT_FNAME "/dev/poll"
# define SLAP_EVENTS_ARE_INDEXED 0
/*
} while (0)
#else /* ! epoll && ! /dev/poll */
-
-#define SLAP_EVENT_ACK 1 /* events keep signalling unless we stop them */
-
# ifdef HAVE_WINSOCK
# define SLAP_EVENT_FNAME "WSselect"
/* Winsock provides a "select" function but its fd_sets are
slap_daemon.sd_flags = (char *)(slapd_ws_sockets + dtblsize); \
slap_daemon.sd_rflags = slap_daemon.sd_flags + dtblsize; \
memset( slapd_ws_sockets, -1, dtblsize * sizeof(SOCKET) ); \
+ memset( slap_daemon.sd_flags, 0, dtblsize ); \
slapd_ws_sockets[0] = wake_sds[0]; \
slapd_ws_sockets[1] = wake_sds[1]; \
wake_sds[0] = 0; \
for ( i = 0; slapd_srvurls[i] != NULL; i++ ) {
if ( strcmp( slapd_srvurls[i], "ldap:///" ) == 0 ) {
slapd_srvurls[i] = (char *) ch_realloc( slapd_srvurls[i],
- strlen( global_host ) +
+ global_host_bv.bv_len +
sizeof( LDAP_SRVTYPE_PREFIX ) );
strcpy( lutil_strcopy(slapd_srvurls[i],
- LDAP_SRVTYPE_PREFIX ), global_host );
+ LDAP_SRVTYPE_PREFIX ), global_host_bv.bv_val );
} else if ( strcmp( slapd_srvurls[i], "ldaps:///" ) == 0 ) {
slapd_srvurls[i] = (char *) ch_realloc( slapd_srvurls[i],
- strlen( global_host ) +
+ global_host_bv.bv_len +
sizeof( LDAPS_SRVTYPE_PREFIX ) );
strcpy( lutil_strcopy(slapd_srvurls[i],
- LDAPS_SRVTYPE_PREFIX ), global_host );
+ LDAPS_SRVTYPE_PREFIX ), global_host_bv.bv_val );
}
}
WAKE_LISTENER(wake || slapd_gentle_shutdown == 2);
}
-void
-slapd_ack_write( ber_socket_t s, int wake )
-{
-#ifdef SLAP_EVENT_ACK
- ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
-
- if ( SLAP_SOCK_IS_WRITE( s )) {
- assert( SLAP_SOCK_IS_ACTIVE( s ));
-
- SLAP_SOCK_CLR_WRITE( s );
- slap_daemon.sd_nwriters--;
- }
-
- ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
-#endif
- WAKE_LISTENER(wake);
-}
-
void
slapd_clr_write( ber_socket_t s, int wake )
{
SLAP_SOCK_SET_WRITE( s );
slap_daemon.sd_nwriters++;
}
+ if (( wake & 2 ) && global_writetimeout && !chk_writetime ) {
+ chk_writetime = slap_get_time();
+ }
ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
WAKE_LISTENER(wake);
}
int
-slapd_ack_read( ber_socket_t s, int wake )
+slapd_clr_read( ber_socket_t s, int wake )
{
-#ifdef SLAP_EVENT_ACK
int rc = 1;
ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
if ( !rc )
WAKE_LISTENER(wake);
return rc;
-#else
- return 0;
-#endif
}
-int
-slapd_clr_read( ber_socket_t s, int wake )
+void
+slapd_set_read( ber_socket_t s, int wake )
{
- int rc = 1;
+ int do_wake = 1;
ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
- if ( SLAP_SOCK_IS_ACTIVE( s )) {
- SLAP_SOCK_CLR_READ( s );
- rc = 0;
+ if( SLAP_SOCK_IS_ACTIVE( s ) && !SLAP_SOCK_IS_READ( s )) {
+ SLAP_SOCK_SET_READ( s );
+ } else {
+ do_wake = 0;
}
ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
- if ( !rc )
+ if ( do_wake )
WAKE_LISTENER(wake);
- return rc;
}
-void
-slapd_set_read( ber_socket_t s, int wake )
+time_t
+slapd_get_writetime()
{
+ time_t cur;
ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
+ cur = chk_writetime;
+ ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
+ return cur;
+}
- assert( SLAP_SOCK_IS_ACTIVE( s ));
- if (!SLAP_SOCK_IS_READ( s )) SLAP_SOCK_SET_READ( s );
-
+void
+slapd_clr_writetime( time_t old )
+{
+ ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
+ if ( chk_writetime == old )
+ chk_writetime = 0;
ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
- WAKE_LISTENER(wake);
}
static void
}
#endif /* HAVE_TLS */
+#ifdef LDAP_TCP_BUFFER
+ l.sl_tcp_rmem = 0;
+ l.sl_tcp_wmem = 0;
+#endif /* LDAP_TCP_BUFFER */
+
port = (unsigned short) lud->lud_port;
tmp = ldap_pvt_url_scheme2proto(lud->lud_scheme);
* create/unlink the socket; likely need exec perms to access
* the socket (ITS#4709) */
{
- mode_t old_umask;
+ mode_t old_umask = 0;
if ( (*sal)->sa_family == AF_LOCAL ) {
old_umask = umask( 0 );
#endif /* LDAP_PF_LOCAL */
rc = bind( s, *sal, addrlen );
#ifdef LDAP_PF_LOCAL
- if ( (*sal)->sa_family == AF_LOCAL ) {
+ if ( old_umask != 0 ) {
umask( old_umask );
}
}
"daemon: lutil_pair() failed rc=%d\n", rc, 0, 0 );
return rc;
}
+ ber_pvt_socket_set_nonblock( wake_sds[1], 1 );
SLAP_SOCK_INIT;
{
connections_destroy();
#ifdef HAVE_WINSOCK
- if ( wake_sds[1] != INVALID_SOCKET && wake_sds[1] != wake_sds[0] )
+ if ( wake_sds[1] != INVALID_SOCKET &&
+ SLAP_FD2SOCK( wake_sds[1] ) != SLAP_FD2SOCK( wake_sds[0] ))
#endif /* HAVE_WINSOCK */
tcp_close( SLAP_FD2SOCK(wake_sds[1]) );
#ifdef HAVE_WINSOCK
{
int l;
time_t last_idle_check = 0;
- struct timeval idle;
int ebadf = 0;
#define SLAPD_IDLE_CHECK_LIMIT 4
if ( global_idletimeout > 0 ) {
last_idle_check = slap_get_time();
- /* Set the select timeout.
- * Don't just truncate, preserve the fractions of
- * seconds to prevent sleeping for zero time.
- */
- idle.tv_sec = global_idletimeout / SLAPD_IDLE_CHECK_LIMIT;
- idle.tv_usec = global_idletimeout - \
- ( idle.tv_sec * SLAPD_IDLE_CHECK_LIMIT );
- idle.tv_usec *= 1000000 / SLAPD_IDLE_CHECK_LIMIT;
- } else {
- idle.tv_sec = 0;
- idle.tv_usec = 0;
}
slapd_add( wake_sds[0], 0, NULL );
continue;
#endif /* LDAP_CONNECTIONLESS */
+ /* FIXME: TCP-only! */
+#ifdef LDAP_TCP_BUFFER
+ if ( 1 ) {
+ int origsize, size, realsize, rc;
+ socklen_t optlen;
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ size = 0;
+ if ( slap_listeners[l]->sl_tcp_rmem > 0 ) {
+ size = slap_listeners[l]->sl_tcp_rmem;
+ } else if ( slapd_tcp_rmem > 0 ) {
+ size = slapd_tcp_rmem;
+ }
+
+ if ( size > 0 ) {
+ optlen = sizeof( origsize );
+ rc = getsockopt( SLAP_FD2SOCK( slap_listeners[l]->sl_sd ),
+ SOL_SOCKET,
+ SO_RCVBUF,
+ (void *)&origsize,
+ &optlen );
+
+ if ( rc ) {
+ int err = sock_errno();
+ Debug( LDAP_DEBUG_ANY,
+ "slapd_daemon_task: getsockopt(SO_RCVBUF) failed errno=%d (%s)\n",
+ err, sock_errstr(err), 0 );
+ }
+
+ optlen = sizeof( size );
+ rc = setsockopt( SLAP_FD2SOCK( slap_listeners[l]->sl_sd ),
+ SOL_SOCKET,
+ SO_RCVBUF,
+ (const void *)&size,
+ optlen );
+
+ if ( rc ) {
+ int err = sock_errno();
+ Debug( LDAP_DEBUG_ANY,
+ "slapd_daemon_task: setsockopt(SO_RCVBUF) failed errno=%d (%s)\n",
+ err, sock_errstr(err), 0 );
+ }
+
+ optlen = sizeof( realsize );
+ rc = getsockopt( SLAP_FD2SOCK( slap_listeners[l]->sl_sd ),
+ SOL_SOCKET,
+ SO_RCVBUF,
+ (void *)&realsize,
+ &optlen );
+
+ if ( rc ) {
+ int err = sock_errno();
+ Debug( LDAP_DEBUG_ANY,
+ "slapd_daemon_task: getsockopt(SO_RCVBUF) failed errno=%d (%s)\n",
+ err, sock_errstr(err), 0 );
+ }
+
+ snprintf( buf, sizeof( buf ),
+ "url=%s (#%d) RCVBUF original size=%d requested size=%d real size=%d",
+ slap_listeners[l]->sl_url.bv_val, l, origsize, size, realsize );
+ Debug( LDAP_DEBUG_ANY,
+ "slapd_daemon_task: %s\n",
+ buf, 0, 0 );
+ }
+
+ size = 0;
+ if ( slap_listeners[l]->sl_tcp_wmem > 0 ) {
+ size = slap_listeners[l]->sl_tcp_wmem;
+ } else if ( slapd_tcp_wmem > 0 ) {
+ size = slapd_tcp_wmem;
+ }
+
+ if ( size > 0 ) {
+ optlen = sizeof( origsize );
+ rc = getsockopt( SLAP_FD2SOCK( slap_listeners[l]->sl_sd ),
+ SOL_SOCKET,
+ SO_SNDBUF,
+ (void *)&origsize,
+ &optlen );
+
+ if ( rc ) {
+ int err = sock_errno();
+ Debug( LDAP_DEBUG_ANY,
+ "slapd_daemon_task: getsockopt(SO_SNDBUF) failed errno=%d (%s)\n",
+ err, sock_errstr(err), 0 );
+ }
+
+ optlen = sizeof( size );
+ rc = setsockopt( SLAP_FD2SOCK( slap_listeners[l]->sl_sd ),
+ SOL_SOCKET,
+ SO_SNDBUF,
+ (const void *)&size,
+ optlen );
+
+ if ( rc ) {
+ int err = sock_errno();
+ Debug( LDAP_DEBUG_ANY,
+ "slapd_daemon_task: setsockopt(SO_SNDBUF) failed errno=%d (%s)",
+ err, sock_errstr(err), 0 );
+ }
+
+ optlen = sizeof( realsize );
+ rc = getsockopt( SLAP_FD2SOCK( slap_listeners[l]->sl_sd ),
+ SOL_SOCKET,
+ SO_SNDBUF,
+ (void *)&realsize,
+ &optlen );
+
+ if ( rc ) {
+ int err = sock_errno();
+ Debug( LDAP_DEBUG_ANY,
+ "slapd_daemon_task: getsockopt(SO_SNDBUF) failed errno=%d (%s)\n",
+ err, sock_errstr(err), 0 );
+ }
+
+ snprintf( buf, sizeof( buf ),
+ "url=%s (#%d) SNDBUF original size=%d requested size=%d real size=%d",
+ slap_listeners[l]->sl_url.bv_val, l, origsize, size, realsize );
+ Debug( LDAP_DEBUG_ANY,
+ "slapd_daemon_task: %s\n",
+ buf, 0, 0 );
+ }
+ }
+#endif /* LDAP_TCP_BUFFER */
+
if ( listen( SLAP_FD2SOCK( slap_listeners[l]->sl_sd ), SLAPD_LISTEN_BACKLOG ) == -1 ) {
int err = sock_errno();
now = slap_get_time();
- if ( ( global_idletimeout > 0 ) &&
- difftime( last_idle_check +
- global_idletimeout/SLAPD_IDLE_CHECK_LIMIT, now ) < 0 )
- {
- connections_timeout_idle( now );
- last_idle_check = now;
+ if ( global_idletimeout > 0 || chk_writetime ) {
+ int check = 0;
+ /* Set the select timeout.
+ * Don't just truncate, preserve the fractions of
+ * seconds to prevent sleeping for zero time.
+ */
+ if ( chk_writetime ) {
+ tv.tv_sec = global_writetimeout;
+ tv.tv_usec = 0;
+ if ( difftime( chk_writetime, now ) < 0 )
+ check = 2;
+ } else {
+ tv.tv_sec = global_idletimeout / SLAPD_IDLE_CHECK_LIMIT;
+ tv.tv_usec = global_idletimeout - \
+ ( tv.tv_sec * SLAPD_IDLE_CHECK_LIMIT );
+ tv.tv_usec *= 1000000 / SLAPD_IDLE_CHECK_LIMIT;
+ if ( difftime( last_idle_check +
+ global_idletimeout/SLAPD_IDLE_CHECK_LIMIT, now ) < 0 )
+ check = 1;
+ }
+ if ( check ) {
+ connections_timeout_idle( now );
+ last_idle_check = now;
+ }
+ } else {
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
}
- tv = idle;
#ifdef SIGHUP
if ( slapd_gentle_shutdown ) {
nfds = SLAP_EVENT_MAX;
- if ( global_idletimeout && slap_daemon.sd_nactives ) at = 1;
+ if (( chk_writetime || global_idletimeout ) && slap_daemon.sd_nactives ) at = 1;
ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
#endif /* LDAP_DEBUG */
for ( i = 0; i < ns; i++ ) {
- int rc = 1, fd, w = 0;
+ int rc = 1, fd, w = 0, r = 0;
if ( SLAP_EVENT_IS_LISTENER( i ) ) {
rc = slap_listener_activate( SLAP_EVENT_LISTENER( i ) );
}
}
/* If event is a read */
- if ( SLAP_EVENT_IS_READ( i ) ) {
+ if ( SLAP_EVENT_IS_READ( i ))
+ r = 1;
+ if ( r || !w ) {
Debug( LDAP_DEBUG_CONNS,
"daemon: read active on %d\n",
fd, 0, 0 );
- SLAP_EVENT_CLR_READ( i );
+ if ( r ) {
+ SLAP_EVENT_CLR_READ( i );
+ } else {
+#ifdef HAVE_EPOLL
+ /* Don't keep reporting the hangup
+ */
+ if ( SLAP_SOCK_IS_ACTIVE( fd )) {
+ SLAP_EPOLL_SOCK_SET( fd, EPOLLET );
+ }
+#endif
+ }
connection_read_activate( fd );
- } else if ( !w ) {
- Debug( LDAP_DEBUG_CONNS,
- "daemon: hangup on %d\n", fd, 0, 0 );
- connection_hangup( fd );
}
}
}
RETSIGTYPE
slap_sig_shutdown( int sig )
{
+ int save_errno = errno;
+
#if 0
Debug(LDAP_DEBUG_TRACE, "slap_sig_shutdown: signal %d\n", sig, 0, 0);
#endif
/* reinstall self */
(void) SIGNAL_REINSTALL( sig, slap_sig_shutdown );
+
+ errno = save_errno;
}
RETSIGTYPE
slap_sig_wake( int sig )
{
+ int save_errno = errno;
+
WAKE_LISTENER(1);
/* reinstall self */
(void) SIGNAL_REINSTALL( sig, slap_sig_wake );
+
+ errno = save_errno;
}