]> git.sur5r.net Git - openldap/blob - libraries/librewrite/session.c
reworking of threads in session handling
[openldap] / libraries / librewrite / session.c
1 /******************************************************************************
2  *
3  * Copyright (C) 2000 Pierangelo Masarati, <ando@sys-net.it>
4  * All rights reserved.
5  *
6  * Permission is granted to anyone to use this software for any purpose
7  * on any computer system, and to alter it and redistribute it, subject
8  * to the following restrictions:
9  *
10  * 1. The author is not responsible for the consequences of use of this
11  * software, no matter how awful, even if they arise from flaws in it.
12  *
13  * 2. The origin of this software must not be misrepresented, either by
14  * explicit claim or by omission.  Since few users ever read sources,
15  * credits should appear in the documentation.
16  *
17  * 3. Altered versions must be plainly marked as such, and must not be
18  * misrepresented as being the original software.  Since few users
19  * ever read sources, credits should appear in the documentation.
20  * 
21  * 4. This notice may not be removed or altered.
22  *
23  ******************************************************************************/
24
25 #include <portable.h>
26
27 #include "rewrite-int.h"
28
29 /*
30  * Compares two cookies
31  */
32 static int
33 rewrite_cookie_cmp(
34                 const void *c1,
35                 const void *c2
36 )
37 {
38         const struct rewrite_session *s1, *s2;
39
40         s1 = ( const struct rewrite_session * )c1;
41         s2 = ( const struct rewrite_session * )c2;
42
43         assert( s1 != NULL );
44         assert( s2 != NULL );
45         assert( s1->ls_cookie != NULL );
46         assert( s2->ls_cookie != NULL );
47
48         return ( ( s1->ls_cookie < s2->ls_cookie ) ? -1 :
49                         ( ( s1->ls_cookie > s2->ls_cookie ) ? 1 : 0 ) );
50 }
51
52 /*
53  * Duplicate cookies?
54  */
55 static int
56 rewrite_cookie_dup(
57                 void *c1,
58                 void *c2
59 )
60 {
61         struct rewrite_session *s1, *s2;
62
63         s1 = ( struct rewrite_session * )c1;
64         s2 = ( struct rewrite_session * )c2;
65         
66         assert( s1 != NULL );
67         assert( s2 != NULL );
68         assert( s1->ls_cookie != NULL );
69         assert( s2->ls_cookie != NULL );
70         
71         assert( s1->ls_cookie != s2->ls_cookie );
72         
73         return ( ( s1->ls_cookie == s2->ls_cookie ) ? -1 : 0 );
74 }
75
76 /*
77  * Inits a session
78  */
79 struct rewrite_session *
80 rewrite_session_init(
81                 struct rewrite_info *info,
82                 const void *cookie
83 )
84 {
85         struct rewrite_session  *session, tmp;
86         int                     rc;
87
88         assert( info != NULL );
89         assert( cookie != NULL );
90
91 #ifdef USE_REWRITE_LDAP_PVT_THREADS
92         ldap_pvt_thread_rdwr_wlock( &info->li_cookies_mutex );
93 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
94
95         tmp.ls_cookie = ( void * )cookie;
96         session = ( struct rewrite_session * )avl_find( info->li_cookies, 
97                         ( caddr_t )&tmp, rewrite_cookie_cmp );
98         if ( session ) {
99                 session->ls_count++;
100 #ifdef USE_REWRITE_LDAP_PVT_THREADS
101                 ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex );
102 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
103                 return session;
104         }
105                 
106         session = calloc( sizeof( struct rewrite_session ), 1 );
107         if ( session == NULL ) {
108                 return NULL;
109         }
110         session->ls_cookie = ( void * )cookie;
111         session->ls_count = 1;
112         
113 #ifdef USE_REWRITE_LDAP_PVT_THREADS
114         if ( ldap_pvt_thread_mutex_init( &session->ls_mutex ) ) {
115                 free( session );
116                 return NULL;
117         }
118         if ( ldap_pvt_thread_rdwr_init( &session->ls_vars_mutex ) ) {
119                 ldap_pvt_thread_mutex_destroy( &session->ls_mutex );
120                 free( session );
121                 return NULL;
122         }
123 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
124
125         rc = avl_insert( &info->li_cookies, ( caddr_t )session,
126                         rewrite_cookie_cmp, rewrite_cookie_dup );
127         info->li_num_cookies++;
128
129 #ifdef USE_REWRITE_LDAP_PVT_THREADS
130         ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex );
131 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
132         
133         if ( rc != 0 ) {
134 #ifdef USE_REWRITE_LDAP_PVT_THREADS
135                 ldap_pvt_thread_rdwr_destroy( &session->ls_vars_mutex );
136                 ldap_pvt_thread_mutex_destroy( &session->ls_mutex );
137 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
138
139                 free( session );
140                 return NULL;
141         }
142         
143         return session;
144 }
145
146 /*
147  * Fetches a session
148  */
149 struct rewrite_session *
150 rewrite_session_find(
151                 struct rewrite_info *info,
152                 const void *cookie
153 )
154 {
155         struct rewrite_session *session, tmp;
156
157         assert( info != NULL );
158         assert( cookie != NULL );
159         
160         tmp.ls_cookie = ( void * )cookie;
161 #ifdef USE_REWRITE_LDAP_PVT_THREADS
162         ldap_pvt_thread_rdwr_rlock( &info->li_cookies_mutex );
163 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
164         session = ( struct rewrite_session * )avl_find( info->li_cookies,
165                         ( caddr_t )&tmp, rewrite_cookie_cmp );
166 #ifdef USE_REWRITE_LDAP_PVT_THREADS
167         if ( session ) {
168                 ldap_pvt_thread_mutex_lock( &session->ls_mutex );
169         }
170         ldap_pvt_thread_rdwr_runlock( &info->li_cookies_mutex );
171 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
172
173         return session;
174 }
175
176 /*
177  * Returns a session
178  */
179 void
180 rewrite_session_return(
181                 struct rewrite_info *info,
182                 struct rewrite_session *session
183 )
184 {
185         assert( session );
186         ldap_pvt_thread_mutex_unlock( &session->ls_mutex );
187 }
188
189 /*
190  * Defines and inits a var with session scope
191  */
192 int
193 rewrite_session_var_set(
194                 struct rewrite_info *info,
195                 const void *cookie,
196                 const char *name,
197                 const char *value
198 )
199 {
200         struct rewrite_session *session;
201         struct rewrite_var *var;
202
203         assert( info != NULL );
204         assert( cookie != NULL );
205         assert( name != NULL );
206         assert( value != NULL );
207
208         session = rewrite_session_find( info, cookie );
209         if ( session == NULL ) {
210                 session = rewrite_session_init( info, cookie );
211         }
212
213 #ifdef USE_REWRITE_LDAP_PVT_THREADS
214         ldap_pvt_thread_rdwr_wlock( &session->ls_vars_mutex );
215 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
216
217         var = rewrite_var_find( session->ls_vars, name );
218         if ( var != NULL ) {
219                 assert( var->lv_value.bv_val != NULL );
220                 free( var->lv_value.bv_val );
221                 var->lv_value.bv_val = strdup( value );
222                 var->lv_value.bv_len = strlen( value );
223         } else {
224                 var = rewrite_var_insert( &session->ls_vars, name, value );
225                 if ( var == NULL ) {
226 #ifdef USE_REWRITE_LDAP_PVT_THREADS
227                         ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex );
228 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
229                         rewrite_session_return( info, session );
230                         return REWRITE_ERR;
231                 }
232         }       
233         
234 #ifdef USE_REWRITE_LDAP_PVT_THREADS
235         ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex );
236 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
237
238         rewrite_session_return( info, session );
239
240         return REWRITE_SUCCESS;
241 }
242
243 /*
244  * Gets a var with session scope
245  */
246 int
247 rewrite_session_var_get(
248                 struct rewrite_info *info,
249                 const void *cookie,
250                 const char *name,
251                 struct berval *value
252 )
253 {
254         struct rewrite_session *session;
255         struct rewrite_var *var;
256
257         assert( info != NULL );
258         assert( cookie != NULL );
259         assert( name != NULL );
260         assert( value != NULL );
261
262         value->bv_val = NULL;
263         value->bv_len = 0;
264         
265         if ( cookie == NULL ) {
266                 return REWRITE_ERR;
267         }
268
269         session = rewrite_session_find( info, cookie );
270         if ( session == NULL ) {
271                 return REWRITE_ERR;
272         }
273
274 #ifdef USE_REWRITE_LDAP_PVT_THREADS
275         ldap_pvt_thread_rdwr_rlock( &session->ls_vars_mutex );
276 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
277         
278         var = rewrite_var_find( session->ls_vars, name );
279         if ( var == NULL ) {
280                 
281 #ifdef USE_REWRITE_LDAP_PVT_THREADS
282                 ldap_pvt_thread_rdwr_runlock( &session->ls_vars_mutex );
283 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
284
285                 rewrite_session_return( info, session );
286
287                 return REWRITE_ERR;
288         } else {
289                 value->bv_val = strdup( var->lv_value.bv_val );
290                 value->bv_len = var->lv_value.bv_len;
291         }
292         
293 #ifdef USE_REWRITE_LDAP_PVT_THREADS
294         ldap_pvt_thread_rdwr_runlock( &session->ls_vars_mutex );
295 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
296
297         rewrite_session_return( info, session );
298         
299         return REWRITE_SUCCESS;
300 }
301
302 /*
303  * Deletes a session
304  */
305 int
306 rewrite_session_delete(
307                 struct rewrite_info *info,
308                 const void *cookie
309 )
310 {
311         struct rewrite_session *session, tmp;
312
313         assert( info != NULL );
314         assert( cookie != NULL );
315
316         tmp.ls_cookie = ( void * )cookie;
317         
318         session = rewrite_session_find( info, cookie );
319
320         if ( session != NULL ) {
321                 if ( --session->ls_count > 0 ) {
322                         rewrite_session_return( info, session );
323                         return REWRITE_SUCCESS;
324                 }
325
326 #ifdef USE_REWRITE_LDAP_PVT_THREADS
327                 ldap_pvt_thread_rdwr_wlock( &session->ls_vars_mutex );
328 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
329
330                 rewrite_var_delete( session->ls_vars );
331
332 #ifdef USE_REWRITE_LDAP_PVT_THREADS
333                 ldap_pvt_thread_rdwr_destroy( &session->ls_vars_mutex );
334                 ldap_pvt_thread_mutex_destroy( &session->ls_mutex );
335 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
336         }
337
338 #ifdef USE_REWRITE_LDAP_PVT_THREADS
339         ldap_pvt_thread_rdwr_wlock( &info->li_cookies_mutex );
340 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
341
342         assert( info->li_num_cookies > 0 );
343         info->li_num_cookies--;
344         
345         /*
346          * There is nothing to delete in the return value
347          */
348         avl_delete( &info->li_cookies, ( caddr_t )&tmp, rewrite_cookie_cmp );
349         free( session );
350
351 #ifdef USE_REWRITE_LDAP_PVT_THREADS
352         ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex );
353 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
354
355         return REWRITE_SUCCESS;
356 }
357
358 /*
359  * Destroys the cookie tree
360  */
361 int
362 rewrite_session_destroy(
363                 struct rewrite_info *info
364 )
365 {
366         int count;
367
368         assert( info != NULL );
369         
370 #ifdef USE_REWRITE_LDAP_PVT_THREADS
371         ldap_pvt_thread_rdwr_wlock( &info->li_cookies_mutex );
372 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
373
374         /*
375          * Should call per-session destruction routine ...
376          */
377         
378         count = avl_free( info->li_cookies, NULL );
379         info->li_cookies = NULL;
380
381         fprintf( stderr, "count = %d; num_cookies = %d\n", 
382                         count, info->li_num_cookies );
383         
384         assert( count == info->li_num_cookies );
385         info->li_num_cookies = 0;
386
387 #ifdef USE_REWRITE_LDAP_PVT_THREADS
388         ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex );
389 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
390
391         return REWRITE_SUCCESS;
392 }
393