/* * 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; }
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; }