X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fconnection.c;h=eecf90409b9cb09c3cf6ed5179cb9609d6463704;hb=fb2e448e877a8a387084dde517362c9f7bf1b6b7;hp=aead5521da9f073c29467d1749de1e109ca95373;hpb=1cf58aba1c53f5f1def4c35b2c51a37c6beb504f;p=openldap diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c index aead5521da..eecf90409b 100644 --- a/servers/slapd/connection.c +++ b/servers/slapd/connection.c @@ -1,7 +1,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 1998-2006 The OpenLDAP Foundation. + * Copyright 1998-2007 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,33 +43,10 @@ #include "slapi/slapi.h" #endif -#ifdef SLAP_MULTI_CONN_ARRAY -/* for Multiple Connection Arrary (MCA) Support */ -static ldap_pvt_thread_mutex_t* connections_mutex; -static Connection **connections = NULL; - -/* set to the number of processors (round up to a power of 2) */ -# define NUM_CONNECTION_ARRAY 4 - -/* partition the array in a modulo manner */ -# define MCA_conn_array_id(fd) ((int)(fd)%NUM_CONNECTION_ARRAY) -# define MCA_conn_array_element_id(fd) ((int)(fd)/NUM_CONNECTION_ARRAY) -# define MCA_ARRAY_SIZE ((int)(MCA_conn_array_element_id(dtblsize) + (MCA_conn_array_id(dtblsize) ? 1 : 0))) -# define MCA_conn_check(fd) (dtblsize > 0 && (fd) >= 0 && (fd) < (MCA_ARRAY_SIZE*NUM_CONNECTION_ARRAY)) -# define MCA_GET_CONNECTION(fd) (&(connections[MCA_conn_array_id(fd)]) \ - [MCA_conn_array_element_id(fd)]) -# define MCA_GET_CONN_MUTEX(fd) (&connections_mutex[MCA_conn_array_id(fd)]) - -#else /* protected by connections_mutex */ static ldap_pvt_thread_mutex_t connections_mutex; static Connection *connections = NULL; -# define MCA_conn_check(fd) (dtblsize > 0 && (fd) < dtblsize) -# define MCA_GET_CONNECTION(fd) (&connections[s]) -# define MCA_GET_CONN_MUTEX(fd) (&connections_mutex) -#endif - static ldap_pvt_thread_mutex_t conn_nextid_mutex; static unsigned long conn_nextid = 0; @@ -79,6 +56,7 @@ static const char conn_lost_str[] = "connection lost"; #define SLAP_C_UNINITIALIZED 0x00 /* MUST BE ZERO (0) */ #define SLAP_C_UNUSED 0x01 #define SLAP_C_USED 0x02 +#define SLAP_C_PENDING 0x03 /* connection state (protected by c_mutex ) */ #define SLAP_C_INVALID 0x00 /* MUST BE ZERO (0) */ @@ -134,69 +112,6 @@ static ldap_pvt_thread_start_t connection_operation; * Initialize connection management infrastructure. */ int connections_init(void) -#ifdef SLAP_MULTI_CONN_ARRAY -{ - int i, j; - Connection* conn; - - assert( connections == NULL ); - - if( connections != NULL) { - Debug( LDAP_DEBUG_ANY, "connections_init: already initialized.\n", - 0, 0, 0 ); - return -1; - } - - connections_mutex = (ldap_pvt_thread_mutex_t*) ch_calloc( - NUM_CONNECTION_ARRAY, sizeof(ldap_pvt_thread_mutex_t) ); - if( connections_mutex == NULL ) { - Debug( LDAP_DEBUG_ANY, "connections_init: " - "allocation of connection mutexes failed\n", 0, 0, 0 ); - return -1; - } - - connections = (Connection**) ch_calloc( - NUM_CONNECTION_ARRAY, sizeof(Connection*)); - if( connections == NULL ) { - Debug( LDAP_DEBUG_ANY, "connections_init: " - "allocation of connection[%d] failed\n", 0, 0, 0 ); - return -1; - } - - for ( i = 0; i < NUM_CONNECTION_ARRAY; i++ ) { - ldap_pvt_thread_mutex_init( connections_mutex+i ); - connections[i] = (Connection*) ch_calloc( - MCA_ARRAY_SIZE, sizeof(Connection) ); - if( connections[i] == NULL ) { - Debug( LDAP_DEBUG_ANY, "connections_init: " - "allocation (%d*%ld) of connection array[%d] failed\n", - dtblsize, (long) sizeof(Connection), i ); - return -1; - } - } - - /* should check return of every call */ - ldap_pvt_thread_mutex_init( &conn_nextid_mutex ); - - assert( connections[0]->c_struct_state == SLAP_C_UNINITIALIZED ); - assert( connections[NUM_CONNECTION_ARRAY-1]->c_struct_state == - SLAP_C_UNINITIALIZED ); - - for ( i = 0; i < NUM_CONNECTION_ARRAY; i++ ) { - conn = connections[i]; - for ( j = 0; j < MCA_ARRAY_SIZE; j++ ) { - conn[j].c_conn_idx = j; - } - } - - /* - * per entry initialization of the Connection array initialization - * will be done by connection_init() - */ - - return 0; -} -#else { int i; @@ -233,57 +148,12 @@ int connections_init(void) return 0; } -#endif /* * Destroy connection management infrastructure. */ int connections_destroy(void) -#ifdef SLAP_MULTI_CONN_ARRAY -{ - int i; - ber_socket_t j; - - if( connections == NULL) { - Debug( LDAP_DEBUG_ANY, "connections_destroy: nothing to destroy.\n", - 0, 0, 0 ); - return -1; - } - - for ( i = 0; i < NUM_CONNECTION_ARRAY; i++ ) { - Connection* conn = connections[i]; - for ( j = 0; j < MCA_ARRAY_SIZE; j++ ) { - if( conn[j].c_struct_state != SLAP_C_UNINITIALIZED ) { - ber_sockbuf_free( conn[j].c_sb ); - ldap_pvt_thread_mutex_destroy( &conn[j].c_mutex ); - ldap_pvt_thread_mutex_destroy( &conn[j].c_write_mutex ); - ldap_pvt_thread_cond_destroy( &conn[j].c_write_cv ); -#ifdef LDAP_SLAPI - if ( slapi_plugins_used ) { - slapi_int_free_object_extensions( SLAPI_X_EXT_CONNECTION, - &conn[j] ); - } -#endif - } - } - } - - for ( i = 0; i < NUM_CONNECTION_ARRAY; i++ ) { - free( connections[i] ); - connections[i] = NULL; - ldap_pvt_thread_mutex_destroy( &connections_mutex[i] ); - } - - free( connections ); - free( connections_mutex ); - - ldap_pvt_thread_mutex_destroy( &conn_nextid_mutex ); - - return 0; - -} -#else { ber_socket_t i; @@ -317,75 +187,35 @@ int connections_destroy(void) ldap_pvt_thread_mutex_destroy( &conn_nextid_mutex ); return 0; } -#endif /* * shutdown all connections */ int connections_shutdown(void) -#ifdef SLAP_MULTI_CONN_ARRAY -{ - int i; - ber_socket_t j; - - for ( i = 0; i < NUM_CONNECTION_ARRAY; i++ ) { - Connection* conn = connections[i]; - ldap_pvt_thread_mutex_lock( &connections_mutex[i] ); - for ( j = 0; j < MCA_ARRAY_SIZE; j++ ) { - if( conn[j].c_struct_state != SLAP_C_USED ) { - continue; - } - /* give persistent clients a chance to cleanup */ - if( conn[j].c_conn_state == SLAP_C_CLIENT ) { - ldap_pvt_thread_pool_submit( &connection_pool, - conn[j].c_clientfunc, conn[j].c_clientarg ); - continue; - } - - ldap_pvt_thread_mutex_lock( &conn[j].c_mutex ); - /* connections_mutex and c_mutex are locked */ - connection_closing( &conn[j], "connection shutdown" ); - connection_close( &conn[j] ); - ldap_pvt_thread_mutex_unlock( &conn[j].c_mutex ); - } - - ldap_pvt_thread_mutex_unlock( &connections_mutex[i] ); - } - - return 0; - -} -#else { ber_socket_t i; - ldap_pvt_thread_mutex_lock( &connections_mutex ); - for ( i = 0; i < dtblsize; i++ ) { - if( connections[i].c_struct_state != SLAP_C_USED ) { - continue; - } - /* 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 ); - continue; + 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 ); } - - ldap_pvt_thread_mutex_lock( &connections[i].c_mutex ); - - /* connections_mutex and c_mutex are locked */ - connection_closing( &connections[i], "slapd shutdown" ); - connection_close( &connections[i] ); - - ldap_pvt_thread_mutex_unlock( &connections[i].c_mutex ); } - ldap_pvt_thread_mutex_unlock( &connections_mutex ); - return 0; } -#endif /* * Timeout idle connections. @@ -420,8 +250,6 @@ int connections_timeout_idle(time_t now) static Connection* connection_get( ber_socket_t s ) { - /* connections_mutex should be locked by caller */ - Connection *c; Debug( LDAP_DEBUG_ARGS, @@ -433,15 +261,19 @@ static Connection* connection_get( ber_socket_t s ) if(s == AC_SOCKET_INVALID) return NULL; #ifndef HAVE_WINSOCK - assert( MCA_conn_check( s ) ); - c = MCA_GET_CONNECTION(s); + assert( s < dtblsize ); + c = &connections[s]; #else c = NULL; { ber_socket_t i, sd; + ldap_pvt_thread_mutex_lock( &connections_mutex ); for(i=0; ic_struct_state != SLAP_C_UNINITIALIZED ); - ldap_pvt_thread_mutex_lock( &c->c_mutex ); + assert( c->c_struct_state != SLAP_C_UNINITIALIZED ); + ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_GET_FD, &sd ); +#ifdef HAVE_WINSOCK + /* Avoid race condition after releasing + * connections_mutex + */ + if ( sd != s ) { + ldap_pvt_thread_mutex_unlock( &c->c_mutex ); + return NULL; + } +#endif if( c->c_struct_state != SLAP_C_USED ) { /* connection must have been closed due to resched */ @@ -528,6 +370,7 @@ long connection_init( { unsigned long id; Connection *c; + int doinit = 0; assert( connections != NULL ); @@ -548,24 +391,29 @@ long connection_init( assert( s >= 0 ); #ifndef HAVE_WINSOCK assert( s < dtblsize ); -#endif - - ldap_pvt_thread_mutex_lock( MCA_GET_CONN_MUTEX(s) ); - -#ifndef HAVE_WINSOCK - assert( MCA_conn_check( s ) ); - c = MCA_GET_CONNECTION(s); + c = &connections[s]; + if( c->c_struct_state == SLAP_C_UNINITIALIZED ) { + doinit = 1; + } else { + assert( c->c_struct_state == SLAP_C_UNUSED ); + } #else { ber_socket_t i; c = NULL; + ldap_pvt_thread_mutex_lock( &connections_mutex ); for( i=0; i < dtblsize; i++) { ber_socket_t sd; + if ( connections[i].c_struct_state == SLAP_C_PENDING ) + continue; + if( connections[i].c_struct_state == SLAP_C_UNINITIALIZED ) { assert( connections[i].c_sb == 0 ); c = &connections[i]; + c->c_struct_state = SLAP_C_PENDING; + doinit = 1; break; } @@ -578,6 +426,7 @@ long connection_init( if( connections[i].c_struct_state == SLAP_C_UNUSED ) { assert( sd == AC_SOCKET_INVALID ); c = &connections[i]; + c->c_struct_state = SLAP_C_PENDING; break; } @@ -587,20 +436,18 @@ long connection_init( assert( connections[i].c_conn_state != SLAP_C_INVALID ); assert( sd != AC_SOCKET_INVALID ); } + ldap_pvt_thread_mutex_unlock( &connections_mutex ); if( c == NULL ) { Debug( LDAP_DEBUG_ANY, "connection_init(%d): connection table full " "(%d/%d)\n", s, i, dtblsize); - ldap_pvt_thread_mutex_unlock( &connections_mutex ); return -1; } } #endif - assert( c != NULL ); - - if( c->c_struct_state == SLAP_C_UNINITIALIZED ) { + if( doinit ) { c->c_send_ldap_result = slap_send_ldap_result; c->c_send_search_entry = slap_send_search_entry; c->c_send_search_reference = slap_send_search_reference; @@ -650,13 +497,10 @@ long connection_init( slapi_int_create_object_extensions( SLAPI_X_EXT_CONNECTION, c ); } #endif - - c->c_struct_state = SLAP_C_UNUSED; } ldap_pvt_thread_mutex_lock( &c->c_mutex ); - assert( c->c_struct_state == SLAP_C_UNUSED ); assert( BER_BVISNULL( &c->c_authmech ) ); assert( BER_BVISNULL( &c->c_dn ) ); assert( BER_BVISNULL( &c->c_ndn ) ); @@ -687,7 +531,6 @@ long connection_init( c->c_close_reason = "?"; /* should never be needed */ ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_FD, &s ); ldap_pvt_thread_mutex_unlock( &c->c_mutex ); - ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) ); return 0; } @@ -776,7 +619,6 @@ long connection_init( slapd_add_internal( s, 1 ); ldap_pvt_thread_mutex_unlock( &c->c_mutex ); - ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) ); backend_connection_init(c); @@ -819,10 +661,10 @@ void connection2anonymous( Connection *c ) static void connection_destroy( Connection *c ) { - /* note: connections_mutex should be locked by caller */ ber_socket_t sd; unsigned long connid; const char *close_reason; + Sockbuf *sb; assert( connections != NULL ); assert( c != NULL ); @@ -841,6 +683,10 @@ connection_destroy( Connection *c ) connid = c->c_connid; close_reason = c->c_close_reason; + ldap_pvt_thread_mutex_lock( &connections_mutex ); + c->c_struct_state = SLAP_C_PENDING; + ldap_pvt_thread_mutex_unlock( &connections_mutex ); + backend_connection_destroy(c); c->c_protocol = 0; @@ -873,37 +719,40 @@ connection_destroy( Connection *c ) c->c_currentber = NULL; } - ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_GET_FD, &sd ); - slapd_sd_lock(); - ber_sockbuf_free( c->c_sb ); - if ( sd != AC_SOCKET_INVALID ) { - slapd_remove( sd, 1, 0, 1 ); - Statslog( LDAP_DEBUG_STATS, (close_reason - ? "conn=%lu fd=%ld closed (%s)\n" - : "conn=%lu fd=%ld closed\n"), - connid, (long) sd, close_reason, 0, 0 ); - } else { - slapd_sd_unlock(); +#ifdef LDAP_SLAPI + /* call destructors, then constructors; avoids unnecessary allocation */ + if ( slapi_plugins_used ) { + slapi_int_clear_object_extensions( SLAPI_X_EXT_CONNECTION, c ); } +#endif - c->c_sb = ber_sockbuf_alloc( ); + c->c_conn_state = SLAP_C_INVALID; + c->c_struct_state = SLAP_C_UNUSED; + c->c_close_reason = "?"; /* should never be needed */ + sb = c->c_sb; + c->c_sb = ber_sockbuf_alloc( ); { ber_len_t max = sockbuf_max_incoming; ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max ); } - c->c_conn_state = SLAP_C_INVALID; - c->c_struct_state = SLAP_C_UNUSED; - c->c_close_reason = "?"; /* should never be needed */ + ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); -#ifdef LDAP_SLAPI - /* call destructors, then constructors; avoids unnecessary allocation */ - if ( slapi_plugins_used ) { - slapi_int_clear_object_extensions( SLAPI_X_EXT_CONNECTION, c ); + /* c must be fully reset by this point; when we call slapd_remove + * it may get immediately reused by a new connection. + */ + if ( sd != AC_SOCKET_INVALID ) { + slapd_remove( sd, sb, 1, 0, 0 ); + + if ( close_reason == NULL ) { + close_reason = ""; + } + + Statslog( LDAP_DEBUG_STATS, "conn=%lu fd=%ld closed (%s)\n", + connid, (long) sd, close_reason, 0, 0 ); } -#endif } int connection_state_closing( Connection *c ) @@ -984,18 +833,25 @@ void connection_closing( Connection *c, const char *why ) c->c_close_reason = why; /* don't listen on this port anymore */ - slapd_clr_read( sd, 1 ); + slapd_clr_read( sd, 0 ); /* abandon active operations */ connection_abandon( c ); /* wake write blocked operations */ - slapd_clr_write( sd, 1 ); if ( c->c_writewaiter ) { ldap_pvt_thread_cond_signal( &c->c_write_cv ); + /* ITS#4667 this may allow another thread to drop into + * connection_resched / connection_close before we + * finish, but that's OK. + */ + slapd_clr_write( sd, 1 ); ldap_pvt_thread_mutex_unlock( &c->c_mutex ); - ldap_pvt_thread_yield(); + ldap_pvt_thread_mutex_lock( &c->c_write_mutex ); ldap_pvt_thread_mutex_lock( &c->c_mutex ); + ldap_pvt_thread_mutex_unlock( &c->c_write_mutex ); + } else { + slapd_clr_write( sd, 1 ); } } else if( why == NULL && c->c_close_reason == conn_lost_str ) { @@ -1004,19 +860,31 @@ void connection_closing( Connection *c, const char *why ) } } -static void connection_close( Connection *c ) +static void +connection_close( Connection *c ) { - ber_socket_t sd; + ber_socket_t sd = AC_SOCKET_INVALID; assert( connections != NULL ); assert( c != NULL ); + + /* ITS#4667 we may have gotten here twice */ + if ( c->c_conn_state == SLAP_C_INVALID ) + return; + assert( c->c_struct_state == SLAP_C_USED ); assert( c->c_conn_state == SLAP_C_CLOSING ); - /* note: connections_mutex and c_mutex should be locked by caller */ + /* NOTE: c_mutex should be locked by caller */ - ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_GET_FD, &sd ); - if( !LDAP_STAILQ_EMPTY(&c->c_ops) ) { + /* NOTE: don't get the file descriptor if not needed */ + if ( LogTest( LDAP_DEBUG_TRACE ) ) { + ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_GET_FD, &sd ); + } + + if ( !LDAP_STAILQ_EMPTY(&c->c_ops) || + !LDAP_STAILQ_EMPTY(&c->c_pending_ops) ) + { Debug( LDAP_DEBUG_TRACE, "connection_close: deferring conn=%lu sd=%d\n", c->c_connid, sd, 0 ); @@ -1025,6 +893,7 @@ static void connection_close( Connection *c ) Debug( LDAP_DEBUG_TRACE, "connection_close: conn=%lu sd=%d\n", c->c_connid, sd, 0 ); + connection_destroy( c ); } @@ -1044,71 +913,21 @@ unsigned long connections_nextid(void) Connection* connection_first( ber_socket_t *index ) { -#ifdef SLAP_MULTI_CONN_ARRAY - int conn_array_id; -#endif - assert( connections != NULL ); assert( index != NULL ); -#ifdef SLAP_MULTI_CONN_ARRAY - for ( conn_array_id = 0; - conn_array_id < NUM_CONNECTION_ARRAY; - conn_array_id++ ) - { - ldap_pvt_thread_mutex_lock( &connections_mutex[ conn_array_id ] ); - } -#else ldap_pvt_thread_mutex_lock( &connections_mutex ); -#endif - - *index = 0; - - return connection_next(NULL, index); -} - -Connection* connection_next( Connection *c, ber_socket_t *index ) -#ifdef SLAP_MULTI_CONN_ARRAY -{ - Connection* conn; - - assert( connections != NULL ); - assert( index != NULL ); - assert( *index >= 0 && *index <= dtblsize ); - - if( c != NULL ) ldap_pvt_thread_mutex_unlock( &c->c_mutex ); - - c = NULL; - - for(; *index < dtblsize; (*index)++) { - assert( MCA_conn_check( *index ) ); - conn = MCA_GET_CONNECTION(*index); - if( conn->c_struct_state == SLAP_C_UNINITIALIZED ) { - assert( conn->c_conn_state == SLAP_C_INVALID ); -#ifndef HAVE_WINSOCK - continue; -#else + for( *index = 0; *index < dtblsize; (*index)++) { + if( connections[*index].c_struct_state != SLAP_C_UNINITIALIZED ) { break; -#endif } - - if( conn->c_struct_state == SLAP_C_USED ) { - assert( conn->c_conn_state != SLAP_C_INVALID ); - c = conn; - (*index)++; - break; - } - - assert( conn->c_struct_state == SLAP_C_UNUSED ); - assert( conn->c_conn_state == SLAP_C_INVALID ); } + ldap_pvt_thread_mutex_unlock( &connections_mutex ); - if( c != NULL ) ldap_pvt_thread_mutex_lock( &c->c_mutex ); - - return c; - + return connection_next(NULL, index); } -#else + +Connection* connection_next( Connection *c, ber_socket_t *index ) { assert( connections != NULL ); assert( index != NULL ); @@ -1118,51 +937,51 @@ Connection* connection_next( Connection *c, ber_socket_t *index ) c = NULL; + ldap_pvt_thread_mutex_lock( &connections_mutex ); for(; *index < dtblsize; (*index)++) { + int c_struct; if( connections[*index].c_struct_state == SLAP_C_UNINITIALIZED ) { assert( connections[*index].c_conn_state == SLAP_C_INVALID ); -#ifndef HAVE_WINSOCK - continue; -#else +#ifdef HAVE_WINSOCK break; +#else + continue; #endif } if( connections[*index].c_struct_state == SLAP_C_USED ) { assert( connections[*index].c_conn_state != SLAP_C_INVALID ); c = &connections[(*index)++]; + if ( ldap_pvt_thread_mutex_trylock( &c->c_mutex )) { + /* avoid deadlock */ + ldap_pvt_thread_mutex_unlock( &connections_mutex ); + ldap_pvt_thread_mutex_lock( &c->c_mutex ); + ldap_pvt_thread_mutex_lock( &connections_mutex ); + if ( c->c_struct_state != SLAP_C_USED ) { + ldap_pvt_thread_mutex_unlock( &c->c_mutex ); + c = NULL; + continue; + } + } break; } - assert( connections[*index].c_struct_state == SLAP_C_UNUSED ); + c_struct = connections[*index].c_struct_state; + if ( c_struct == SLAP_C_PENDING ) + continue; + assert( c_struct == SLAP_C_UNUSED ); assert( connections[*index].c_conn_state == SLAP_C_INVALID ); } - if( c != NULL ) ldap_pvt_thread_mutex_lock( &c->c_mutex ); + ldap_pvt_thread_mutex_unlock( &connections_mutex ); return c; } -#endif void connection_done( Connection *c ) { -#ifdef SLAP_MULTI_CONN_ARRAY - int conn_array_id; -#endif - assert( connections != NULL ); if( c != NULL ) ldap_pvt_thread_mutex_unlock( &c->c_mutex ); - -#ifdef SLAP_MULTI_CONN_ARRAY - for ( conn_array_id = 0; - conn_array_id < NUM_CONNECTION_ARRAY; - conn_array_id++ ) - { - ldap_pvt_thread_mutex_unlock( &connections_mutex[ conn_array_id ] ); - } -#else - ldap_pvt_thread_mutex_unlock( &connections_mutex ); -#endif } /* @@ -1199,7 +1018,7 @@ void connection_done( Connection *c ) /* * NOTE: keep in sync with enum in slapd.h */ -static int (*opfun[])( Operation *op, SlapReply *rs ) = { +static BI_op_func *opfun[] = { do_bind, do_unbind, do_add, @@ -1220,7 +1039,7 @@ connection_operation( void *ctx, void *arg_v ) Operation *op = arg_v; SlapReply rs = {REP_RESULT}; ber_tag_t tag = op->o_tag; - int opidx = -1; + slap_op_t opidx = SLAP_OP_LAST; Connection *conn = op->o_conn; void *memctx = NULL; void *memctx_null = NULL; @@ -1303,53 +1122,8 @@ connection_operation( void *ctx, void *arg_v ) } } - switch ( tag ) { - case LDAP_REQ_BIND: - opidx = SLAP_OP_BIND; - break; - - case LDAP_REQ_UNBIND: - opidx = SLAP_OP_UNBIND; - break; - - case LDAP_REQ_ADD: - opidx = SLAP_OP_ADD; - break; - - case LDAP_REQ_DELETE: - opidx = SLAP_OP_DELETE; - break; - - case LDAP_REQ_MODRDN: - opidx = SLAP_OP_MODRDN; - break; - - case LDAP_REQ_MODIFY: - opidx = SLAP_OP_MODIFY; - break; - - case LDAP_REQ_COMPARE: - opidx = SLAP_OP_COMPARE; - break; - - case LDAP_REQ_SEARCH: - opidx = SLAP_OP_SEARCH; - break; - - case LDAP_REQ_ABANDON: - opidx = SLAP_OP_ABANDON; - break; - - case LDAP_REQ_EXTENDED: - opidx = SLAP_OP_EXTENDED; - break; - - default: - /* not reachable */ - assert( 0 ); - } - - assert( opidx > -1 ); + opidx = slap_req2op( tag ); + assert( opidx != SLAP_OP_LAST ); INCR_OP_INITIATED( opidx ); rc = (*(opfun[opidx]))( op, &rs ); @@ -1357,7 +1131,7 @@ operations_error: if ( rc == SLAPD_DISCONNECT ) { tag = LBER_ERROR; - } else if ( opidx > -1 ) { + } else if ( opidx != SLAP_OP_LAST ) { /* increment completed operations count * only if operation was initiated * and rc != SLAPD_DISCONNECT */ @@ -1371,6 +1145,7 @@ operations_error: op->o_cancel = LDAP_TOO_LATE; } } + while ( op->o_cancel != SLAP_CANCEL_NONE && op->o_cancel != SLAP_CANCEL_DONE ) { @@ -1435,6 +1210,7 @@ void connection_client_stop( ber_socket_t s ) { Connection *c; + Sockbuf *sb; /* get (locked) connection */ c = connection_get( s ); @@ -1445,14 +1221,13 @@ void connection_client_stop( c->c_conn_state = SLAP_C_INVALID; c->c_struct_state = SLAP_C_UNUSED; c->c_close_reason = "?"; /* should never be needed */ - slapd_sd_lock(); - ber_sockbuf_free( c->c_sb ); - slapd_remove( s, 0, 1, 1 ); + sb = c->c_sb; c->c_sb = ber_sockbuf_alloc( ); { ber_len_t max = sockbuf_max_incoming; ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max ); } + slapd_remove( s, sb, 0, 1, 0 ); connection_return( c ); } @@ -1524,8 +1299,6 @@ int connection_read(ber_socket_t s) assert( connections != NULL ); - ldap_pvt_thread_mutex_lock( MCA_GET_CONN_MUTEX(s) ); - /* get (locked) connection */ c = connection_get( s ); @@ -1534,7 +1307,6 @@ int connection_read(ber_socket_t s) "connection_read(%ld): no connection!\n", (long) s, 0, 0 ); - ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) ); return -1; } @@ -1544,12 +1316,7 @@ int connection_read(ber_socket_t s) Debug( LDAP_DEBUG_TRACE, "connection_read(%d): closing, ignoring input for id=%lu\n", s, c->c_connid, 0 ); - -#ifdef SLAP_LIGHTWEIGHT_DISPATCHER - slapd_set_read( s, 1 ); -#endif connection_return( c ); - ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) ); return 0; } @@ -1564,7 +1331,6 @@ int connection_read(ber_socket_t s) c->c_clientfunc, c->c_clientarg ); #endif connection_return( c ); - ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) ); return 0; } @@ -1582,31 +1348,10 @@ int connection_read(ber_socket_t s) s, rc, c->c_connid ); c->c_needs_tls_accept = 0; - /* connections_mutex and c_mutex are locked */ + /* c_mutex is locked */ connection_closing( c, "TLS negotiation failure" ); - -#if 0 - { - struct timeval tv; - fd_set rfd; - /* Drain input before close, to allow SSL error codes - * to propagate to client. */ - FD_ZERO(&rfd); - FD_SET(s, &rfd); - for (rc=1; rc>0;) { - tv.tv_sec = 1; - tv.tv_usec = 0; - rc = select(s+1, &rfd, NULL, NULL, &tv); - if (rc == 1) { - ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DRAIN, NULL); - } - } - } -#endif - connection_close( c ); connection_return( c ); - ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) ); return 0; } else if ( rc == 0 ) { @@ -1637,15 +1382,13 @@ int connection_read(ber_socket_t s) } /* if success and data is ready, fall thru to data input loop */ - if( rc != 0 || - !ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DATA_READY, NULL ) ) + if( !ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DATA_READY, NULL ) ) { #ifdef SLAP_LIGHTWEIGHT_DISPATCHER slapd_set_read( s, 1 ); #endif connection_return( c ); - ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) ); return 0; } } @@ -1660,7 +1403,6 @@ int connection_read(ber_socket_t s) #endif connection_return( c ); - ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) ); return 0; } @@ -1673,11 +1415,10 @@ int connection_read(ber_socket_t s) "error=%d id=%lu, closing\n", s, rc, c->c_connid ); - /* connections_mutex and c_mutex are locked */ + /* c_mutex is locked */ connection_closing( c, "SASL layer install failure" ); connection_close( c ); connection_return( c ); - ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) ); return 0; } } @@ -1703,15 +1444,14 @@ int connection_read(ber_socket_t s) #endif if( rc < 0 ) { - Debug( LDAP_DEBUG_TRACE, + Debug( LDAP_DEBUG_CONNS, "connection_read(%d): input error=%d id=%lu, closing.\n", s, rc, c->c_connid ); - /* connections_mutex and c_mutex are locked */ + /* c_mutex is locked */ connection_closing( c, conn_lost_str ); connection_close( c ); connection_return( c ); - ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) ); return 0; } @@ -1732,7 +1472,6 @@ int connection_read(ber_socket_t s) #endif connection_return( c ); - ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) ); return 0; } @@ -1763,7 +1502,7 @@ connection_input( Connection *conn ) return -1; } - errno = 0; + sock_errset(0); #ifdef LDAP_CONNECTIONLESS if ( conn->c_is_udp ) { @@ -1783,16 +1522,16 @@ connection_input( Connection *conn ) tag = ber_get_next( conn->c_sb, &len, conn->c_currentber ); if ( tag != LDAP_TAG_MESSAGE ) { - int err = errno; + int err = sock_errno(); ber_socket_t sd; ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_GET_FD, &sd ); - Debug( LDAP_DEBUG_TRACE, - "ber_get_next on fd %d failed errno=%d (%s)\n", - sd, err, sock_errstr(err) ); if ( err != EWOULDBLOCK && err != EAGAIN ) { /* log, close and send error */ + Debug( LDAP_DEBUG_TRACE, + "ber_get_next on fd %d failed errno=%d (%s)\n", + sd, err, sock_errstr(err) ); ber_free( conn->c_currentber, 1 ); conn->c_currentber = NULL; @@ -1969,39 +1708,13 @@ connection_resched( Connection *conn ) Operation *op; if( conn->c_conn_state == SLAP_C_CLOSING ) { - int rc; ber_socket_t sd; ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_GET_FD, &sd ); - /* use trylock to avoid possible deadlock */ - rc = ldap_pvt_thread_mutex_trylock( MCA_GET_CONN_MUTEX( sd ) ); - - if( rc ) { - Debug( LDAP_DEBUG_TRACE, - "connection_resched: reaquiring locks conn=%lu sd=%d\n", - conn->c_connid, sd, 0 ); - /* - * reaquire locks in the right order... - * this may allow another thread to close this connection, - * so recheck state below. - */ - ldap_pvt_thread_mutex_unlock( &conn->c_mutex ); - ldap_pvt_thread_mutex_lock( MCA_GET_CONN_MUTEX ( sd ) ); - ldap_pvt_thread_mutex_lock( &conn->c_mutex ); - } - - if( conn->c_conn_state != SLAP_C_CLOSING ) { - Debug( LDAP_DEBUG_TRACE, "connection_resched: " - "closed by other thread conn=%lu sd=%d\n", - conn->c_connid, sd, 0 ); - } else { - Debug( LDAP_DEBUG_TRACE, "connection_resched: " - "attempting closing conn=%lu sd=%d\n", - conn->c_connid, sd, 0 ); - connection_close( conn ); - } - - ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX( sd ) ); + Debug( LDAP_DEBUG_TRACE, "connection_resched: " + "attempting closing conn=%lu sd=%d\n", + conn->c_connid, sd, 0 ); + connection_close( conn ); return 0; } @@ -2046,13 +1759,17 @@ static int connection_bind_cleanup_cb( Operation *op, SlapReply *rs ) { op->o_conn->c_sasl_bindop = NULL; + ch_free( op->o_callback ); + op->o_callback = NULL; + return SLAP_CB_CONTINUE; } static int connection_bind_cb( Operation *op, SlapReply *rs ) { ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex ); - op->o_conn->c_conn_state = SLAP_C_ACTIVE; + if ( op->o_conn->c_conn_state == SLAP_C_BINDING ) + op->o_conn->c_conn_state = SLAP_C_ACTIVE; op->o_conn->c_sasl_bind_in_progress = ( rs->sr_err == LDAP_SASL_BIND_IN_PROGRESS ); @@ -2181,14 +1898,11 @@ int connection_write(ber_socket_t s) slapd_clr_write( s, 0 ); - ldap_pvt_thread_mutex_lock( MCA_GET_CONN_MUTEX( s ) ); - c = connection_get( s ); if( c == NULL ) { Debug( LDAP_DEBUG_ANY, "connection_write(%ld): no connection!\n", (long)s, 0, 0 ); - ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX( s ) ); return -1; } @@ -2228,7 +1942,6 @@ int connection_write(ber_socket_t s) } connection_return( c ); - ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) ); return 0; }