13 /* protected by connections_mutex */
14 static ldap_pvt_thread_mutex_t connections_mutex;
15 static Connection *connections = NULL;
16 static int conn_index = -1;
17 static long conn_nextid = 0;
19 /* structure state (protected by connections_mutex) */
20 #define SLAP_C_UNINITIALIZED 0x0 /* MUST BE ZERO (0) */
21 #define SLAP_C_UNUSED 0x1
22 #define SLAP_C_USED 0x2
24 /* connection state (protected by c_mutex ) */
25 #define SLAP_C_INVALID 0x0 /* MUST BE ZERO (0) */
26 #define SLAP_C_INACTIVE 0x1 /* zero threads */
27 #define SLAP_C_ACTIVE 0x2 /* one or more threads */
28 #define SLAP_C_BINDING 0x3 /* binding */
29 #define SLAP_C_CLOSING 0x4 /* closing */
31 static Connection* connection_get( int s );
33 static int connection_input( Connection *c );
35 static int connection_op_activate( Connection *conn, Operation *op );
36 static int connection_resched( Connection *conn );
44 * Initialize connection management infrastructure.
46 int connections_init(void)
50 assert( connections == NULL );
52 if( connections != NULL) { /* probably should assert this */
53 Debug( LDAP_DEBUG_ANY, "connections_init: already initialized.\n",
58 /* should check return of every call */
59 ldap_pvt_thread_mutex_init( &connections_mutex );
61 connections = (Connection *) calloc( dtblsize, sizeof(Connection) );
63 if( connections == NULL ) {
64 Debug( LDAP_DEBUG_ANY,
65 "connections_init: allocation (%d*%ld) of connection array failed.\n",
66 dtblsize, (long) sizeof(Connection), 0 );
71 * per entry initialization of the Connection array initialization
72 * will be done by connection_init()
78 static Connection* connection_get( int s )
82 assert( connections != NULL );
89 assert( connections[s].c_struct_state == SLAP_C_USED );
90 assert( connections[s].c_conn_state != SLAP_C_INVALID );
91 assert( connections[s].c_sb.sb_sd != -1 );
98 for(i=0; i<dtblsize; i++) {
99 if( connections[i].c_struct_state == SLAP_C_STRUCT_UNINITIALIZED ) {
100 assert( connections[i].c_conn_state == SLAP_C_INVALID );
101 assert( connections[s].c_sb.sb_sd == 0 );
105 if( connections[i].c_struct_state == SLAP_C_STRUCT_UNUSED ) {
106 assert( connections[i].c_conn_state == SLAP_C_INVALID );
107 assert( connections[s].c_sb.sb_sd == -1 );
111 assert( connections[i].c_struct_state == SLAP_C_STRUCT_USED );
112 assert( connections[i].c_conn_state != SLAP_C_INVALID );
113 assert( connections[s].c_sb.sb_sd != -1 );
115 if( connections[i].c_sb.sb_sd == s ) {
124 /* we do this BEFORE locking to aid in debugging */
125 Debug( LDAP_DEBUG_TRACE,
126 "connection_get(%d): got connid=%ld\n",
129 ldap_pvt_thread_mutex_lock( &c->c_mutex );
134 static void connection_return( Connection *c )
136 ldap_pvt_thread_mutex_unlock( &c->c_mutex );
139 long connection_init(
146 assert( connections != NULL );
154 assert( s < dtblsize );
157 ldap_pvt_thread_mutex_lock( &connections_mutex );
166 for( i=0; i < dtblsize; i++ {
167 if( connections[i].c_struct_state == SLAP_C_UNINITIALIZED ) {
168 assert( connections[i].c_sb.sb_sd == 0 );
173 if( connections[i].c_struct_state == SLAP_C_UNUSED ) {
174 assert( connections[i].c_sb.sb_sd == -1 );
179 assert( connections[i].c_struct_state == SLAP_C_USED );
180 assert( connections[i].c_conn_state != SLAP_C_INVALID );
181 assert( connections[i].c_sb.sb_sd != -1 );
185 ldap_pvt_thread_mutex_unlock( &connections_mutex );
192 assert( c->c_struct_state != SLAP_C_USED );
193 assert( c->c_conn_state == SLAP_C_INVALID );
195 if( c->c_struct_state == SLAP_C_UNINITIALIZED ) {
198 c->c_client_name = NULL;
199 c->c_client_addr = NULL;
201 c->c_pending_ops = NULL;
203 lber_pvt_sb_init( &c->c_sb );
205 /* should check status of thread calls */
206 ldap_pvt_thread_mutex_init( &c->c_mutex );
207 ldap_pvt_thread_mutex_init( &c->c_write_mutex );
208 ldap_pvt_thread_cond_init( &c->c_write_cv );
210 c->c_struct_state = SLAP_C_UNUSED;
213 ldap_pvt_thread_mutex_lock( &c->c_mutex );
215 assert( c->c_struct_state == SLAP_C_UNUSED );
216 assert( c->c_dn == NULL );
217 assert( c->c_cdn == NULL );
218 assert( c->c_client_name == NULL );
219 assert( c->c_client_addr == NULL );
220 assert( c->c_ops == NULL );
221 assert( c->c_pending_ops == NULL );
223 c->c_client_name = ch_strdup( name == NULL ? "" : name );
224 c->c_client_addr = ch_strdup( addr );
226 c->c_n_ops_received = 0;
228 c->c_n_ops_executing = 0;
229 c->c_n_ops_pending = 0;
230 c->c_n_ops_completed = 0;
233 c->c_starttime = slap_get_time();
235 lber_pvt_sb_set_desc( &c->c_sb, s );
236 lber_pvt_sb_set_io( &c->c_sb, &lber_pvt_sb_io_tcp, NULL );
238 if( lber_pvt_sb_set_nonblock( &c->c_sb, 1 ) < 0 ) {
239 Debug( LDAP_DEBUG_ANY,
240 "connection_init(%d, %s, %s): set nonblocking failed\n",
241 s, c->c_client_name, c->c_client_addr);
244 id = c->c_connid = conn_nextid++;
246 c->c_conn_state = SLAP_C_INACTIVE;
247 c->c_struct_state = SLAP_C_USED;
249 ldap_pvt_thread_mutex_unlock( &c->c_mutex );
250 ldap_pvt_thread_mutex_unlock( &connections_mutex );
256 connection_destroy( Connection *c )
258 assert( connections != NULL );
260 assert( c->c_struct_state != SLAP_C_UNUSED );
261 assert( c->c_conn_state != SLAP_C_INVALID );
262 assert( c->c_ops == NULL );
264 c->c_struct_state = SLAP_C_UNUSED;
265 c->c_conn_state = SLAP_C_INVALID;
272 if(c->c_dn != NULL) {
276 if(c->c_cdn != NULL) {
280 if(c->c_client_name != NULL) {
281 free(c->c_client_name);
282 c->c_client_name = NULL;
284 if(c->c_client_addr != NULL) {
285 free(c->c_client_addr);
286 c->c_client_addr = NULL;
289 if ( lber_pvt_sb_in_use(&c->c_sb) ) {
290 int sd = lber_pvt_sb_get_desc(&c->c_sb);
293 lber_pvt_sb_close( &c->c_sb );
295 Statslog( LDAP_DEBUG_STATS,
296 "conn=%d fd=%d closed.\n",
297 c->c_connid, sd, 0, 0, 0 );
300 lber_pvt_sb_destroy( &c->c_sb );
303 void connection_closing( Connection *c )
305 assert( connections != NULL );
307 assert( c->c_struct_state == SLAP_C_USED );
308 assert( c->c_conn_state != SLAP_C_INVALID );
310 if( c->c_conn_state != SLAP_C_CLOSING ) {
311 /* don't listen on this port anymore */
312 slapd_clr_read( c->c_sb.sb_sd, 1 );
313 c->c_conn_state = SLAP_C_CLOSING;
317 static void connection_close( Connection *c )
319 assert( connections != NULL );
321 assert( c->c_struct_state == SLAP_C_USED );
322 assert( c->c_conn_state == SLAP_C_CLOSING );
324 if( c->c_ops != NULL ) {
325 Debug( LDAP_DEBUG_TRACE,
326 "connection_close: deferring conn=%ld sd=%d.\n",
327 c->c_connid, c->c_sb.sb_sd, 0 );
332 Debug( LDAP_DEBUG_TRACE, "connection_close: conn=%ld sd=%d.\n",
333 c->c_connid, c->c_sb.sb_sd, 0 );
335 connection_destroy( c );
338 long connections_nextid(void)
341 assert( connections != NULL );
343 ldap_pvt_thread_mutex_lock( &connections_mutex );
347 ldap_pvt_thread_mutex_unlock( &connections_mutex );
352 Connection* connection_first(void)
354 assert( connections != NULL );
356 ldap_pvt_thread_mutex_lock( &connections_mutex );
358 assert( conn_index == -1 );
361 return connection_next(NULL);
364 Connection* connection_next(Connection *c)
366 assert( connections != NULL );
367 assert( conn_index != -1 );
368 assert( conn_index <= dtblsize );
371 ldap_pvt_thread_mutex_unlock( &c->c_mutex );
376 for(; conn_index < dtblsize; conn_index++) {
377 if( connections[conn_index].c_struct_state == SLAP_C_UNINITIALIZED ) {
378 assert( connections[conn_index].c_conn_state == SLAP_C_INVALID );
386 if( connections[conn_index].c_struct_state == SLAP_C_USED ) {
387 assert( connections[conn_index].c_conn_state != SLAP_C_INVALID );
388 c = &connections[conn_index++];
392 assert( connections[conn_index].c_struct_state == SLAP_C_UNUSED );
393 assert( connections[conn_index].c_conn_state == SLAP_C_INVALID );
397 ldap_pvt_thread_mutex_lock( &c->c_mutex );
403 void connection_done(Connection *c)
405 assert( connections != NULL );
406 assert( conn_index != -1 );
407 assert( conn_index <= dtblsize );
410 ldap_pvt_thread_mutex_unlock( &c->c_mutex );
414 ldap_pvt_thread_mutex_unlock( &connections_mutex );
418 * connection_activity - handle the request operation op on connection
419 * conn. This routine figures out what kind of operation it is and
420 * calls the appropriate stub to handle it.
424 connection_operation( void *arg_v )
426 struct co_arg *arg = arg_v;
427 int tag = arg->co_op->o_tag;
428 Connection *conn = arg->co_conn;
431 ldap_pvt_thread_mutex_lock( &ops_mutex );
433 ldap_pvt_thread_mutex_unlock( &ops_mutex );
438 do_bind( conn, arg->co_op );
442 case LDAP_REQ_UNBIND_30:
444 case LDAP_REQ_UNBIND:
445 do_unbind( conn, arg->co_op );
449 do_add( conn, arg->co_op );
453 case LDAP_REQ_DELETE_30:
455 case LDAP_REQ_DELETE:
456 do_delete( conn, arg->co_op );
459 case LDAP_REQ_MODRDN:
460 do_modrdn( conn, arg->co_op );
463 case LDAP_REQ_MODIFY:
464 do_modify( conn, arg->co_op );
467 case LDAP_REQ_COMPARE:
468 do_compare( conn, arg->co_op );
471 case LDAP_REQ_SEARCH:
472 do_search( conn, arg->co_op );
476 case LDAP_REQ_ABANDON_30:
478 case LDAP_REQ_ABANDON:
479 do_abandon( conn, arg->co_op );
483 Debug( LDAP_DEBUG_ANY, "unknown request 0x%lx\n",
484 arg->co_op->o_tag, 0, 0 );
489 ldap_pvt_thread_mutex_lock( &ops_mutex );
491 ldap_pvt_thread_mutex_unlock( &ops_mutex );
494 ldap_pvt_thread_mutex_lock( &conn->c_mutex );
497 conn->c_ops_completed++;
500 slap_op_remove( &conn->c_ops, arg->co_op );
501 slap_op_free( arg->co_op );
504 free( (char *) arg );
509 case LDAP_REQ_UNBIND_30:
511 case LDAP_REQ_UNBIND:
512 connection_closing( conn );
516 if( conn->c_conn_state == SLAP_C_BINDING) {
517 conn->c_conn_state = SLAP_C_ACTIVE;
521 if( conn->c_conn_state == SLAP_C_CLOSING ) {
522 Debug( LDAP_DEBUG_TRACE,
523 "connection_operation: attempting closing conn=%ld sd=%d.\n",
524 conn->c_connid, conn->c_sb.sb_sd, 0 );
526 connection_close( conn );
529 ldap_pvt_thread_mutex_lock( &active_threads_mutex );
531 if( active_threads < 1 ) {
532 ldap_pvt_thread_cond_signal(&active_threads_cond);
534 ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
536 connection_resched( conn );
538 ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
543 int connection_read(int s)
547 assert( connections != NULL );
549 ldap_pvt_thread_mutex_lock( &connections_mutex );
551 c = connection_get( s );
553 Debug( LDAP_DEBUG_ANY,
554 "connection_read(%d): no connection!\n",
559 Debug( LDAP_DEBUG_TRACE,
560 "connection_read(%d): checking for input on id=%ld\n",
563 #define CONNECTION_INPUT_LOOP 1
565 #ifdef DATA_READY_LOOP
566 while(!rc && lber_pvt_sb_data_ready(&c->c_sb))
567 #elif CONNECTION_INPUT_LOOP
571 rc = connection_input( c );
575 Debug( LDAP_DEBUG_TRACE,
576 "connection_read(%d): input error id=%ld, closing.\n",
579 connection_closing( c );
580 connection_close( c );
583 connection_return( c );
584 ldap_pvt_thread_mutex_unlock( &connections_mutex );
594 unsigned long tag, len;
598 if ( conn->c_currentber == NULL && (conn->c_currentber = ber_alloc())
600 Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
605 if ( (tag = ber_get_next( &conn->c_sb, &len, conn->c_currentber ))
606 != LDAP_TAG_MESSAGE )
608 Debug( LDAP_DEBUG_TRACE,
609 "ber_get_next on fd %d failed errno %d (%s)\n",
610 lber_pvt_sb_get_desc(&conn->c_sb), errno,
611 errno > -1 && errno < sys_nerr ? sys_errlist[errno] : "unknown" );
612 Debug( LDAP_DEBUG_TRACE,
613 "\t*** got %ld of %lu so far\n",
614 (long)(conn->c_currentber->ber_rwptr - conn->c_currentber->ber_buf),
615 conn->c_currentber->ber_len, 0 );
617 if ( errno != EWOULDBLOCK && errno != EAGAIN ) {
618 /* log, close and send error */
619 ber_free( conn->c_currentber, 1 );
620 conn->c_currentber = NULL;
628 ber = conn->c_currentber;
629 conn->c_currentber = NULL;
631 if ( (tag = ber_get_int( ber, &msgid )) != LDAP_TAG_MSGID ) {
632 /* log, close and send error */
633 Debug( LDAP_DEBUG_ANY, "ber_get_int returns 0x%lx\n", tag, 0,
639 if ( (tag = ber_peek_tag( ber, &len )) == LBER_ERROR ) {
640 /* log, close and send error */
641 Debug( LDAP_DEBUG_ANY, "ber_peek_tag returns 0x%lx\n", tag, 0,
649 if ( conn->c_version == 30 ) {
650 (void) ber_skip_tag( ber, &len );
654 op = slap_op_alloc( ber, msgid, tag, conn->c_n_ops_received++ );
656 if ( conn->c_conn_state == SLAP_C_BINDING
657 || conn->c_conn_state == SLAP_C_CLOSING )
659 Debug( LDAP_DEBUG_ANY, "deferring operation\n", 0, 0, 0 );
660 slap_op_add( &conn->c_pending_ops, op );
663 connection_op_activate( conn, op );
667 if ( conn->c_struct_state != SLAP_C_USED ) {
668 /* connection must have got closed underneath us */
672 assert( conn->c_struct_state == SLAP_C_USED );
678 connection_resched( Connection *conn )
682 if( conn->c_conn_state != SLAP_C_ACTIVE ) {
683 /* other states need different handling */
687 for( op = slap_op_pop( &conn->c_pending_ops );
689 op = slap_op_pop( &conn->c_pending_ops ) )
691 connection_op_activate( conn, op );
693 if ( conn->c_conn_state == SLAP_C_BINDING ) {
699 static int connection_op_activate( Connection *conn, Operation *op )
704 unsigned long tag = op->o_tag;
706 if ( conn->c_dn != NULL ) {
707 tmpdn = ch_strdup( conn->c_dn );
712 arg = (struct co_arg *) ch_malloc( sizeof(struct co_arg) );
716 arg->co_op->o_dn = ch_strdup( tmpdn != NULL ? tmpdn : "" );
717 arg->co_op->o_ndn = dn_normalize_case( ch_strdup( arg->co_op->o_dn ) );
719 slap_op_add( &conn->c_ops, arg->co_op );
721 if(tag == LDAP_REQ_BIND) {
722 conn->c_conn_state = SLAP_C_BINDING;
725 if ( tmpdn != NULL ) {
729 ldap_pvt_thread_mutex_lock( &active_threads_mutex );
731 ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
733 status = ldap_pvt_thread_create( &arg->co_op->o_tid, 1,
734 connection_operation, (void *) arg );
737 Debug( LDAP_DEBUG_ANY,
738 "ldap_pvt_thread_create failed (%d)\n", status, 0, 0 );
740 /* should move op to pending list */
746 int connection_write(int s)
749 assert( connections != NULL );
751 ldap_pvt_thread_mutex_lock( &connections_mutex );
753 c = connection_get( s );
755 Debug( LDAP_DEBUG_ANY,
756 "connection_write(%d): no connection!\n",
761 Debug( LDAP_DEBUG_TRACE,
762 "connection_write(%d): waking output for id=%ld\n",
765 ldap_pvt_thread_cond_signal( &c->c_write_cv );
767 connection_return( c );
768 ldap_pvt_thread_mutex_unlock( &connections_mutex );