13 static int connection_op_activate( Connection *conn, Operation *op );
14 static int connection_resched( Connection *conn );
22 * connection_activity - handle the request operation op on connection
23 * conn. This routine figures out what kind of operation it is and
24 * calls the appropriate stub to handle it.
28 connection_operation( void *arg_v )
30 struct co_arg *arg = arg_v;
31 int tag = arg->co_op->o_tag;
32 Connection *conn = arg->co_conn;
34 ldap_pvt_thread_mutex_lock( &conn->c_opsmutex );
35 conn->c_ops_received++;
36 ldap_pvt_thread_mutex_unlock( &conn->c_opsmutex );
38 ldap_pvt_thread_mutex_lock( &ops_mutex );
40 ldap_pvt_thread_mutex_unlock( &ops_mutex );
44 do_bind( conn, arg->co_op );
48 case LDAP_REQ_UNBIND_30:
51 do_unbind( conn, arg->co_op );
55 do_add( conn, arg->co_op );
59 case LDAP_REQ_DELETE_30:
62 do_delete( conn, arg->co_op );
66 do_modrdn( conn, arg->co_op );
70 do_modify( conn, arg->co_op );
73 case LDAP_REQ_COMPARE:
74 do_compare( conn, arg->co_op );
78 do_search( conn, arg->co_op );
82 case LDAP_REQ_ABANDON_30:
84 case LDAP_REQ_ABANDON:
85 do_abandon( conn, arg->co_op );
89 Debug( LDAP_DEBUG_ANY, "unknown request 0x%lx\n",
90 arg->co_op->o_tag, 0, 0 );
94 ldap_pvt_thread_mutex_lock( &ops_mutex );
96 ldap_pvt_thread_mutex_unlock( &ops_mutex );
98 ldap_pvt_thread_mutex_lock( &conn->c_opsmutex );
99 conn->c_ops_completed++;
101 slap_op_remove( &conn->c_ops, arg->co_op );
102 slap_op_free( arg->co_op );
105 free( (char *) arg );
108 if((tag == LDAP_REQ_BIND) && (conn->c_state == SLAP_C_BINDING)) {
109 conn->c_state = SLAP_C_ACTIVE;
112 ldap_pvt_thread_mutex_unlock( &conn->c_opsmutex );
114 ldap_pvt_thread_mutex_lock( &active_threads_mutex );
116 if( active_threads < 1 ) {
117 ldap_pvt_thread_cond_signal(&active_threads_cond);
119 ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
121 connection_resched( conn );
132 unsigned long tag, len;
136 if ( conn->c_currentber == NULL && (conn->c_currentber = ber_alloc())
138 Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
143 if ( (tag = ber_get_next( &conn->c_sb, &len, conn->c_currentber ))
144 != LDAP_TAG_MESSAGE ) {
145 Debug( LDAP_DEBUG_TRACE,
146 "ber_get_next on fd %d failed errno %d (%s)\n",
147 lber_pvt_sb_get_desc(&conn->c_sb), errno, errno > -1 && errno < sys_nerr ?
148 sys_errlist[errno] : "unknown" );
149 Debug( LDAP_DEBUG_TRACE, "*** got %ld of %lu so far\n",
150 (long)(conn->c_currentber->ber_rwptr - conn->c_currentber->ber_buf),
151 conn->c_currentber->ber_len, 0 );
153 if ( errno != EWOULDBLOCK && errno != EAGAIN ) {
154 /* log, close and send error */
155 ber_free( conn->c_currentber, 1 );
156 conn->c_currentber = NULL;
158 close_connection( conn, conn->c_connid, -1 );
163 ber = conn->c_currentber;
164 conn->c_currentber = NULL;
166 if ( (tag = ber_get_int( ber, &msgid )) != LDAP_TAG_MSGID ) {
167 /* log, close and send error */
168 Debug( LDAP_DEBUG_ANY, "ber_get_int returns 0x%lx\n", tag, 0,
172 close_connection( conn, conn->c_connid, -1 );
176 if ( (tag = ber_peek_tag( ber, &len )) == LBER_ERROR ) {
177 /* log, close and send error */
178 Debug( LDAP_DEBUG_ANY, "ber_peek_tag returns 0x%lx\n", tag, 0,
182 close_connection( conn, conn->c_connid, -1 );
187 if ( conn->c_version == 30 ) {
188 (void) ber_skip_tag( ber, &len );
192 op = slap_op_alloc( ber, msgid, tag,
193 conn->c_ops_received, conn->c_connid );
195 if ( conn->c_state == SLAP_C_BINDING ) {
196 /* connection is binding to a dn, make 'em wait */
197 ldap_pvt_thread_mutex_lock( &conn->c_opsmutex );
198 slap_op_add( &conn->c_pending_ops, op );
200 Debug( LDAP_DEBUG_ANY, "deferring operation\n", 0, 0, 0 );
202 ldap_pvt_thread_mutex_unlock( &conn->c_opsmutex );
207 connection_op_activate( conn, op );
211 connection_resched( Connection *conn )
215 if( conn->c_state != SLAP_C_ACTIVE ) {
216 /* other states need different handling */
220 ldap_pvt_thread_mutex_lock( &conn->c_opsmutex );
222 for( op = slap_op_pop( &conn->c_pending_ops );
224 op = slap_op_pop( &conn->c_pending_ops ) )
226 ldap_pvt_thread_mutex_unlock( &conn->c_opsmutex );
228 connection_op_activate( conn, op );
230 ldap_pvt_thread_mutex_lock( &conn->c_opsmutex );
232 if ( conn->c_state == SLAP_C_BINDING ) {
237 ldap_pvt_thread_mutex_unlock( &conn->c_opsmutex );
240 static int connection_op_activate( Connection *conn, Operation *op )
245 unsigned long tag = op->o_tag;
247 ldap_pvt_thread_mutex_lock( &conn->c_dnmutex );
248 if ( conn->c_dn != NULL ) {
249 tmpdn = ch_strdup( conn->c_dn );
253 ldap_pvt_thread_mutex_unlock( &conn->c_dnmutex );
255 arg = (struct co_arg *) ch_malloc( sizeof(struct co_arg) );
259 arg->co_op->o_dn = ch_strdup( tmpdn != NULL ? tmpdn : "" );
260 arg->co_op->o_ndn = dn_normalize_case( ch_strdup( arg->co_op->o_dn ) );
262 ldap_pvt_thread_mutex_lock( &conn->c_opsmutex );
264 slap_op_add( &conn->c_ops, arg->co_op );
266 if(tag == LDAP_REQ_BIND) {
267 conn->c_state = SLAP_C_BINDING;
270 ldap_pvt_thread_mutex_unlock( &conn->c_opsmutex );
272 if ( tmpdn != NULL ) {
276 ldap_pvt_thread_mutex_lock( &active_threads_mutex );
278 ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
280 status = ldap_pvt_thread_create( &arg->co_op->o_tid, 1,
281 connection_operation, (void *) arg );
284 Debug( LDAP_DEBUG_ANY, "ldap_pvt_thread_create failed (%d)\n", status, 0, 0 );