]> git.sur5r.net Git - openldap/blob - servers/slapd/connection.c
Update configure to handle DEC OSF1 3.2 special cases.
[openldap] / servers / slapd / connection.c
1 #include "portable.h"
2
3 #include <stdio.h>
4
5 #include <ac/errno.h>
6 #include <ac/signal.h>
7 #include <ac/socket.h>
8 #include <ac/string.h>
9 #include <ac/time.h>
10
11 #include "slap.h"
12
13 extern Operation        *op_add();
14 extern int              active_threads;
15 extern pthread_mutex_t  active_threads_mutex;
16 extern pthread_mutex_t  new_conn_mutex;
17 extern long             ops_initiated;
18 extern long             ops_completed;
19 extern pthread_mutex_t  ops_mutex;
20 extern pthread_t        listener_tid;
21
22 struct co_arg {
23         Connection      *co_conn;
24         Operation       *co_op;
25 };
26
27 /*
28  * connection_activity - handle the request operation op on connection
29  * conn.  This routine figures out what kind of operation it is and
30  * calls the appropriate stub to handle it.
31  */
32
33 static void
34 connection_operation( struct co_arg *arg )
35 {
36         unsigned long   len;
37
38         pthread_mutex_lock( &arg->co_conn->c_opsmutex );
39         arg->co_conn->c_opsinitiated++;
40         pthread_mutex_unlock( &arg->co_conn->c_opsmutex );
41
42         pthread_mutex_lock( &ops_mutex );
43         ops_initiated++;
44         pthread_mutex_unlock( &ops_mutex );
45
46         switch ( arg->co_op->o_tag ) {
47         case LDAP_REQ_BIND:
48                 do_bind( arg->co_conn, arg->co_op );
49                 break;
50
51 #ifdef LDAP_COMPAT30
52         case LDAP_REQ_UNBIND_30:
53 #endif
54         case LDAP_REQ_UNBIND:
55                 do_unbind( arg->co_conn, arg->co_op );
56                 break;
57
58         case LDAP_REQ_ADD:
59                 do_add( arg->co_conn, arg->co_op );
60                 break;
61
62 #ifdef LDAP_COMPAT30
63         case LDAP_REQ_DELETE_30:
64 #endif
65         case LDAP_REQ_DELETE:
66                 do_delete( arg->co_conn, arg->co_op );
67                 break;
68
69         case LDAP_REQ_MODRDN:
70                 do_modrdn( arg->co_conn, arg->co_op );
71                 break;
72
73         case LDAP_REQ_MODIFY:
74                 do_modify( arg->co_conn, arg->co_op );
75                 break;
76
77         case LDAP_REQ_COMPARE:
78                 do_compare( arg->co_conn, arg->co_op );
79                 break;
80
81         case LDAP_REQ_SEARCH:
82                 do_search( arg->co_conn, arg->co_op );
83                 break;
84
85 #ifdef LDAP_COMPAT30
86         case LDAP_REQ_ABANDON_30:
87 #endif
88         case LDAP_REQ_ABANDON:
89                 do_abandon( arg->co_conn, arg->co_op );
90                 break;
91
92         default:
93                 Debug( LDAP_DEBUG_ANY, "unknown request 0x%x\n",
94                     arg->co_op->o_tag, 0, 0 );
95                 break;
96         }
97
98         pthread_mutex_lock( &arg->co_conn->c_opsmutex );
99         arg->co_conn->c_opscompleted++;
100         op_delete( &arg->co_conn->c_ops, arg->co_op );
101         pthread_mutex_unlock( &arg->co_conn->c_opsmutex );
102
103         free( (char *) arg );
104
105         pthread_mutex_lock( &ops_mutex );
106         ops_completed++;
107         pthread_mutex_unlock( &ops_mutex );
108
109         pthread_mutex_lock( &active_threads_mutex );
110         active_threads--;
111         pthread_mutex_unlock( &active_threads_mutex );
112 }
113
114 void
115 connection_activity(
116     Connection *conn
117 )
118 {
119         pthread_attr_t  attr;
120         struct co_arg   *arg;
121         unsigned long   tag, len;
122         long            msgid;
123         BerElement      *ber;
124         char            *tmpdn;
125
126         if ( conn->c_currentber == NULL && (conn->c_currentber = ber_alloc())
127             == NULL ) {
128                 Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
129                 return;
130         }
131
132         errno = 0;
133         if ( (tag = ber_get_next( &conn->c_sb, &len, conn->c_currentber ))
134             != LDAP_TAG_MESSAGE ) {
135                 Debug( LDAP_DEBUG_TRACE,
136                     "ber_get_next on fd %d failed errno %d (%s)\n",
137                     conn->c_sb.sb_sd, errno, errno > -1 && errno < sys_nerr ?
138                     sys_errlist[errno] : "unknown" );
139                 Debug( LDAP_DEBUG_TRACE, "*** got %d of %d so far\n",
140                     conn->c_currentber->ber_rwptr - conn->c_currentber->ber_buf,
141                     conn->c_currentber->ber_len, 0 );
142
143                 if ( errno != EWOULDBLOCK && errno != EAGAIN ) {
144                         /* log, close and send error */
145                         ber_free( conn->c_currentber, 1 );
146                         conn->c_currentber = NULL;
147
148                         close_connection( conn, conn->c_connid, -1 );
149                 }
150
151                 return;
152         }
153         ber = conn->c_currentber;
154         conn->c_currentber = NULL;
155
156         if ( (tag = ber_get_int( ber, &msgid )) != LDAP_TAG_MSGID ) {
157                 /* log, close and send error */
158                 Debug( LDAP_DEBUG_ANY, "ber_get_int returns 0x%x\n", tag, 0,
159                     0 );
160                 ber_free( ber, 1 );
161
162                 close_connection( conn, conn->c_connid, -1 );
163                 return;
164         }
165
166         if ( (tag = ber_peek_tag( ber, &len )) == LBER_ERROR ) {
167                 /* log, close and send error */
168                 Debug( LDAP_DEBUG_ANY, "ber_peek_tag returns 0x%x\n", tag, 0,
169                     0 );
170                 ber_free( ber, 1 );
171
172                 close_connection( conn, conn->c_connid, -1 );
173                 return;
174         }
175
176 #ifdef LDAP_COMPAT30
177         if ( conn->c_version == 30 ) {
178                 (void) ber_skip_tag( ber, &len );
179         }
180 #endif
181
182         arg = (struct co_arg *) ch_malloc( sizeof(struct co_arg) );
183         arg->co_conn = conn;
184
185         pthread_mutex_lock( &conn->c_dnmutex );
186         if ( conn->c_dn != NULL ) {
187                 tmpdn = strdup( conn->c_dn );
188         } else {
189                 tmpdn = NULL;
190         }
191         pthread_mutex_unlock( &conn->c_dnmutex );
192
193         pthread_mutex_lock( &conn->c_opsmutex );
194         arg->co_op = op_add( &conn->c_ops, ber, msgid, tag, tmpdn,
195             conn->c_opsinitiated, conn->c_connid );
196         pthread_mutex_unlock( &conn->c_opsmutex );
197
198         if ( tmpdn != NULL ) {
199                 free( tmpdn );
200         }
201
202         pthread_attr_init( &attr );
203         pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );
204 #if !defined(HAVE_PTHREADS_D4)
205         /* POSIX_THREADS or compatible
206          * This is a draft 10 or standard pthreads implementation
207          */
208         if ( pthread_create( &arg->co_op->o_tid, &attr,
209             connection_operation, (void *) arg ) != 0 ) {
210                 Debug( LDAP_DEBUG_ANY, "pthread_create failed\n", 0, 0, 0 );
211         } else {
212                 pthread_mutex_lock( &active_threads_mutex );
213                 active_threads++;
214                 pthread_mutex_unlock( &active_threads_mutex );
215         }
216 #else   /* pthread draft4  */
217         /*
218          * This is a draft 4 or earlier pthreads implementation
219          */
220         if ( pthread_create( &arg->co_op->o_tid, attr,
221             connection_operation, (void *) arg ) != 0 ) {
222                 Debug( LDAP_DEBUG_ANY, "pthread_create failed\n", 0, 0, 0 );
223         } else {
224                 pthread_mutex_lock( &active_threads_mutex );
225                 active_threads++;
226                 pthread_mutex_unlock( &active_threads_mutex );
227         }
228 #endif  /* pthread draft4 */
229         pthread_attr_destroy( &attr );
230 }