/*
 * shutdown all connections
 */
int connections_shutdown(void)
{
	ber_socket_t i;

	for ( i = 0; i < dtblsize; i++ ) {
		if( connections[i].c_struct_state != SLAP_C_UNINITIALIZED ) {
			ldap_pvt_thread_mutex_lock( &connections[i].c_mutex );
			if( connections[i].c_struct_state == SLAP_C_USED ) {

				/* give persistent clients a chance to cleanup */
				if( connections[i].c_conn_state == SLAP_C_CLIENT ) {
					ldap_pvt_thread_pool_submit( &connection_pool,
					connections[i].c_clientfunc, connections[i].c_clientarg );
				} else {
					/* c_mutex is locked */
					connection_closing( &connections[i], "slapd shutdown" );
					connection_close( &connections[i] );
				}
			}
			ldap_pvt_thread_mutex_unlock( &connections[i].c_mutex );
		}
	}

	return 0;
}
/*
 * Timeout idle connections.
 */
int connections_timeout_idle(time_t now)
{
	int i = 0;
	int connindex;
	Connection* c;

	for( c = connection_first( &connindex );
		c != NULL;
		c = connection_next( c, &connindex ) )
	{
		/* Don't timeout a slow-running request or a persistent
		 * outbound connection */
		if( c->c_n_ops_executing || c->c_conn_state == SLAP_C_CLIENT ) {
			continue;
		}

		if( difftime( c->c_activitytime+global_idletimeout, now) < 0 ) {
			/* close it */
			connection_closing( c, "idletimeout" );
			connection_close( c );
			i++;
		}
	}
	connection_done( c );

	return i;
}
Example #3
0
static long send_ldap_ber(
	Operation *op,
	BerElement *ber )
{
	Connection *conn = op->o_conn;
	ber_len_t bytes;
	long ret = 0;

	ber_get_option( ber, LBER_OPT_BER_BYTES_TO_WRITE, &bytes );

	/* write only one pdu at a time - wait til it's our turn */
	ldap_pvt_thread_mutex_lock( &conn->c_write1_mutex );
	if (( op->o_abandon && !op->o_cancel ) || !connection_valid( conn ) ||
		conn->c_writers < 0 ) {
		ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
		return 0;
	}

	conn->c_writers++;

	while ( conn->c_writers > 0 && conn->c_writing ) {
		ldap_pvt_thread_cond_wait( &conn->c_write1_cv, &conn->c_write1_mutex );
	}

	/* connection was closed under us */
	if ( conn->c_writers < 0 ) {
		/* we're the last waiter, let the closer continue */
		if ( conn->c_writers == -1 )
			ldap_pvt_thread_cond_signal( &conn->c_write1_cv );
		conn->c_writers++;
		ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
		return 0;
	}

	/* Our turn */
	conn->c_writing = 1;

	/* write the pdu */
	while( 1 ) {
		int err;

		if ( ber_flush2( conn->c_sb, ber, LBER_FLUSH_FREE_NEVER ) == 0 ) {
			ret = bytes;
			break;
		}

		err = sock_errno();

		/*
		 * we got an error.  if it's ewouldblock, we need to
		 * wait on the socket being writable.  otherwise, figure
		 * it's a hard error and return.
		 */

		Debug( LDAP_DEBUG_CONNS, "ber_flush2 failed errno=%d reason=\"%s\"\n",
		    err, sock_errstr(err) );

		if ( err != EWOULDBLOCK && err != EAGAIN ) {
			conn->c_writers--;
			conn->c_writing = 0;
			ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
			ldap_pvt_thread_mutex_lock( &conn->c_mutex );
			connection_closing( conn, "connection lost on write" );

			ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
			return -1;
		}

		/* wait for socket to be write-ready */
		slap_writewait_play( op );
		ldap_pvt_thread_mutex_lock( &conn->c_write2_mutex );
		conn->c_writewaiter = 1;
		slapd_set_write( conn->c_sd, 2 );

		ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
		ldap_pvt_thread_pool_idle( &connection_pool );
		ldap_pvt_thread_cond_wait( &conn->c_write2_cv, &conn->c_write2_mutex );
		conn->c_writewaiter = 0;
		ldap_pvt_thread_mutex_unlock( &conn->c_write2_mutex );
		ldap_pvt_thread_pool_unidle( &connection_pool );
		ldap_pvt_thread_mutex_lock( &conn->c_write1_mutex );
		if ( conn->c_writers < 0 ) {
			ret = 0;
			break;
		}
	}

	conn->c_writing = 0;
	if ( conn->c_writers < 0 ) {
		conn->c_writers++;
		if ( !conn->c_writers )
			ldap_pvt_thread_cond_signal( &conn->c_write1_cv );
	} else {
		conn->c_writers--;
		ldap_pvt_thread_cond_signal( &conn->c_write1_cv );
	}
	ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );

	return ret;
}