bottleneck testcase based on rubbos
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / modules / experimental / util_ldap_cache.c
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /*
18  * util_ldap_cache.c: LDAP cache things
19  * 
20  * Original code from auth_ldap module for Apache v1.3:
21  * Copyright 1998, 1999 Enbridge Pipelines Inc. 
22  * Copyright 1999-2001 Dave Carrigan
23  */
24
25 #include <apr_ldap.h>
26 #include <apr_strings.h>
27 #include "util_ldap.h"
28 #include "util_ldap_cache.h"
29
30 #ifdef APU_HAS_LDAP
31
32 #if APR_HAS_SHARED_MEMORY
33 #define MODLDAP_SHMEM_CACHE "/tmp/mod_ldap_cache"
34 #endif
35
36 /* ------------------------------------------------------------------ */
37
38 unsigned long util_ldap_url_node_hash(void *n)
39 {
40     util_url_node_t *node = (util_url_node_t *)n;
41     return util_ald_hash_string(1, node->url);
42 }
43
44 int util_ldap_url_node_compare(void *a, void *b)
45 {
46     util_url_node_t *na = (util_url_node_t *)a;
47     util_url_node_t *nb = (util_url_node_t *)b;
48
49     return(strcmp(na->url, nb->url) == 0);
50 }
51
52 void *util_ldap_url_node_copy(util_ald_cache_t *cache, void *c)
53 {
54     util_url_node_t *n = (util_url_node_t *)c;
55     util_url_node_t *node = (util_url_node_t *)util_ald_alloc(cache, sizeof(util_url_node_t));
56
57     if (node) {
58         if (!(node->url = util_ald_strdup(cache, n->url))) {
59             util_ald_free(cache, node->url);
60             return NULL;
61         }
62         node->search_cache = n->search_cache;
63         node->compare_cache = n->compare_cache;
64         node->dn_compare_cache = n->dn_compare_cache;
65         return node;
66     }
67     else {
68         return NULL;
69     }
70 }
71
72 void util_ldap_url_node_free(util_ald_cache_t *cache, void *n)
73 {
74     util_url_node_t *node = (util_url_node_t *)n;
75
76     util_ald_free(cache, node->url);
77     util_ald_destroy_cache(node->search_cache);
78     util_ald_destroy_cache(node->compare_cache);
79     util_ald_destroy_cache(node->dn_compare_cache);
80     util_ald_free(cache, node);
81 }
82
83 void util_ldap_url_node_display(request_rec *r, util_ald_cache_t *cache, void *n)
84 {
85     util_url_node_t *node = (util_url_node_t *)n;
86     char date_str[APR_CTIME_LEN+1];
87     char *buf;
88     const char *type_str;
89     util_ald_cache_t *cache_node;
90     int x;
91
92     for (x=0;x<3;x++) {
93         switch (x) {
94             case 0:
95                 cache_node = node->search_cache;
96                 type_str = "Searches";
97                 break;
98             case 1:
99                 cache_node = node->compare_cache;
100                 type_str = "Compares";
101                 break;
102             case 2:
103                 cache_node = node->dn_compare_cache;
104                 type_str = "DN Compares";
105                 break;
106         }
107         
108         if (cache_node->marktime) {
109             apr_ctime(date_str, cache_node->marktime);
110         }
111         else 
112             date_str[0] = 0;
113
114         buf = apr_psprintf(r->pool, 
115                  "<tr valign='top'>"
116                  "<td nowrap>%s (%s)</td>"
117                  "<td nowrap>%ld</td>"
118                  "<td nowrap>%ld</td>"
119                  "<td nowrap>%ld</td>"
120                  "<td nowrap>%ld</td>"
121                  "<td nowrap>%s</td>"
122                  "<tr>",
123              node->url,
124              type_str,
125              cache_node->size,
126              cache_node->maxentries,
127              cache_node->numentries,
128              cache_node->fullmark,
129              date_str);
130     
131         ap_rputs(buf, r);
132     }
133
134 }
135
136 /* ------------------------------------------------------------------ */
137
138 /* Cache functions for search nodes */
139 unsigned long util_ldap_search_node_hash(void *n)
140 {
141     util_search_node_t *node = (util_search_node_t *)n;
142     return util_ald_hash_string(1, ((util_search_node_t *)(node))->username);
143 }
144
145 int util_ldap_search_node_compare(void *a, void *b)
146 {
147     return(strcmp(((util_search_node_t *)a)->username,
148                   ((util_search_node_t *)b)->username) == 0);
149 }
150
151 void *util_ldap_search_node_copy(util_ald_cache_t *cache, void *c)
152 {
153     util_search_node_t *node = (util_search_node_t *)c;
154     util_search_node_t *newnode = util_ald_alloc(cache, sizeof(util_search_node_t));
155
156     /* safety check */
157     if (newnode) {
158
159         /* copy vals */
160         if (node->vals) {
161             int k = node->numvals;
162             int i = 0;
163             if (!(newnode->vals = util_ald_alloc(cache, sizeof(char *) * (k+1)))) {
164                 util_ldap_search_node_free(cache, newnode);
165                 return NULL;
166             }
167             newnode->numvals = node->numvals;
168             for (;k;k--) {
169                 if (node->vals[i]) {
170                     if (!(newnode->vals[i] = util_ald_strdup(cache, node->vals[i]))) {
171                         util_ldap_search_node_free(cache, newnode);
172                         return NULL;
173                     }
174                 }
175                 else
176                     newnode->vals[i] = NULL;
177                 i++;
178             }
179         }
180         else {
181             newnode->vals = NULL;
182         }
183         if (!(newnode->username = util_ald_strdup(cache, node->username)) ||
184             !(newnode->dn = util_ald_strdup(cache, node->dn)) ) {
185             util_ldap_search_node_free(cache, newnode);
186             return NULL;
187         }
188         if(node->bindpw) {
189             if(!(newnode->bindpw = util_ald_strdup(cache, node->bindpw))) {
190                 util_ldap_search_node_free(cache, newnode);
191                 return NULL;
192             }
193         } else {
194             newnode->bindpw = NULL;
195         }
196         newnode->lastbind = node->lastbind;
197
198     }
199     return (void *)newnode;
200 }
201
202 void util_ldap_search_node_free(util_ald_cache_t *cache, void *n)
203 {
204     int i = 0;
205     util_search_node_t *node = (util_search_node_t *)n;
206     int k = node->numvals;
207
208     if (node->vals) {
209         for (;k;k--,i++) {
210             if (node->vals[i]) {
211                 util_ald_free(cache, node->vals[i]);
212             }
213         }
214         util_ald_free(cache, node->vals);
215     }
216     util_ald_free(cache, node->username);
217     util_ald_free(cache, node->dn);
218     util_ald_free(cache, node->bindpw);
219     util_ald_free(cache, node);
220 }
221
222 void util_ldap_search_node_display(request_rec *r, util_ald_cache_t *cache, void *n)
223 {
224     util_search_node_t *node = (util_search_node_t *)n;
225     char date_str[APR_CTIME_LEN+1];
226     char *buf;
227
228     apr_ctime(date_str, node->lastbind);
229
230     buf = apr_psprintf(r->pool, 
231              "<tr valign='top'>"
232              "<td nowrap>%s</td>"
233              "<td nowrap>%s</td>"
234              "<td nowrap>%s</td>"
235              "<tr>",
236          node->username,
237          node->dn,
238          date_str);
239
240     ap_rputs(buf, r);
241 }
242
243 /* ------------------------------------------------------------------ */
244
245 unsigned long util_ldap_compare_node_hash(void *n)
246 {
247     util_compare_node_t *node = (util_compare_node_t *)n;
248     return util_ald_hash_string(3, node->dn, node->attrib, node->value);
249 }
250
251 int util_ldap_compare_node_compare(void *a, void *b)
252 {
253     util_compare_node_t *na = (util_compare_node_t *)a;
254     util_compare_node_t *nb = (util_compare_node_t *)b;
255     return (strcmp(na->dn, nb->dn) == 0 &&
256             strcmp(na->attrib, nb->attrib) == 0 &&
257             strcmp(na->value, nb->value) == 0);
258 }
259
260 void *util_ldap_compare_node_copy(util_ald_cache_t *cache, void *c)
261 {
262     util_compare_node_t *n = (util_compare_node_t *)c;
263     util_compare_node_t *node = (util_compare_node_t *)util_ald_alloc(cache, sizeof(util_compare_node_t));
264
265     if (node) {
266         if (!(node->dn = util_ald_strdup(cache, n->dn)) ||
267             !(node->attrib = util_ald_strdup(cache, n->attrib)) ||
268             !(node->value = util_ald_strdup(cache, n->value))) {
269             util_ldap_compare_node_free(cache, node);
270             return NULL;
271         }
272         node->lastcompare = n->lastcompare;
273         node->result = n->result;
274         return node;
275     }
276     else {
277         return NULL;
278     }
279 }
280
281 void util_ldap_compare_node_free(util_ald_cache_t *cache, void *n)
282 {
283     util_compare_node_t *node = (util_compare_node_t *)n;
284     util_ald_free(cache, node->dn);
285     util_ald_free(cache, node->attrib);
286     util_ald_free(cache, node->value);
287     util_ald_free(cache, node);
288 }
289
290 void util_ldap_compare_node_display(request_rec *r, util_ald_cache_t *cache, void *n)
291 {
292     util_compare_node_t *node = (util_compare_node_t *)n;
293     char date_str[APR_CTIME_LEN+1];
294     char *buf, *cmp_result;
295
296     apr_ctime(date_str, node->lastcompare);
297
298     if (node->result == LDAP_COMPARE_TRUE) {
299         cmp_result = "LDAP_COMPARE_TRUE";
300     }
301     else if (node->result == LDAP_COMPARE_FALSE) {
302         cmp_result = "LDAP_COMPARE_FALSE";
303     }
304     else {
305         cmp_result = apr_itoa(r->pool, node->result);
306     }
307
308     buf = apr_psprintf(r->pool, 
309              "<tr valign='top'>"
310              "<td nowrap>%s</td>"
311              "<td nowrap>%s</td>"
312              "<td nowrap>%s</td>"
313              "<td nowrap>%s</td>"
314              "<td nowrap>%s</td>"
315              "<tr>",
316          node->dn,
317          node->attrib,
318          node->value,
319          date_str,
320          cmp_result);
321
322     ap_rputs(buf, r);
323 }
324
325 /* ------------------------------------------------------------------ */
326
327 unsigned long util_ldap_dn_compare_node_hash(void *n)
328 {
329     return util_ald_hash_string(1, ((util_dn_compare_node_t *)n)->reqdn);
330 }
331
332 int util_ldap_dn_compare_node_compare(void *a, void *b)
333 {
334     return (strcmp(((util_dn_compare_node_t *)a)->reqdn,
335                    ((util_dn_compare_node_t *)b)->reqdn) == 0);
336 }
337
338 void *util_ldap_dn_compare_node_copy(util_ald_cache_t *cache, void *c)
339 {
340     util_dn_compare_node_t *n = (util_dn_compare_node_t *)c;
341     util_dn_compare_node_t *node = (util_dn_compare_node_t *)util_ald_alloc(cache, sizeof(util_dn_compare_node_t));
342     if (node) {
343         if (!(node->reqdn = util_ald_strdup(cache, n->reqdn)) ||
344             !(node->dn = util_ald_strdup(cache, n->dn))) {
345             util_ldap_dn_compare_node_free(cache, node);
346             return NULL;
347         }
348         return node;
349     }
350     else {
351         return NULL;
352     }
353 }
354
355 void util_ldap_dn_compare_node_free(util_ald_cache_t *cache, void *n)
356 {
357     util_dn_compare_node_t *node = (util_dn_compare_node_t *)n;
358     util_ald_free(cache, node->reqdn);
359     util_ald_free(cache, node->dn);
360     util_ald_free(cache, node);
361 }
362
363 void util_ldap_dn_compare_node_display(request_rec *r, util_ald_cache_t *cache, void *n)
364 {
365     util_dn_compare_node_t *node = (util_dn_compare_node_t *)n;
366     char *buf;
367
368     buf = apr_psprintf(r->pool, 
369              "<tr valign='top'>"
370              "<td nowrap>%s</td>"
371              "<td nowrap>%s</td>"
372              "<tr>",
373          node->reqdn,
374          node->dn);
375
376     ap_rputs(buf, r);
377 }
378
379
380 /* ------------------------------------------------------------------ */
381 apr_status_t util_ldap_cache_child_kill(void *data);
382 apr_status_t util_ldap_cache_module_kill(void *data);
383
384 apr_status_t util_ldap_cache_module_kill(void *data)
385 {
386     util_ldap_state_t *st = (util_ldap_state_t *)data;
387
388     util_ald_destroy_cache(st->util_ldap_cache);
389 #if APR_HAS_SHARED_MEMORY
390     if (st->cache_rmm != NULL) {
391         apr_rmm_destroy (st->cache_rmm);
392         st->cache_rmm = NULL;
393     }
394     if (st->cache_shm != NULL) {
395         apr_status_t result = apr_shm_destroy(st->cache_shm);
396         st->cache_shm = NULL;
397         apr_file_remove(st->cache_file, st->pool);
398         return result;
399     }
400 #endif
401     return APR_SUCCESS;
402 }
403
404 apr_status_t util_ldap_cache_init(apr_pool_t *pool, util_ldap_state_t *st)
405 {
406 #if APR_HAS_SHARED_MEMORY
407     apr_status_t result;
408     apr_size_t size;
409
410     size = APR_ALIGN_DEFAULT(st->cache_bytes);
411
412     result = apr_shm_create(&st->cache_shm, size, st->cache_file, st->pool);
413     if (result == APR_EEXIST) {
414         /*
415          * The cache could have already been created (i.e. we may be a child process).  See
416          * if we can attach to the existing shared memory
417          */
418         result = apr_shm_attach(&st->cache_shm, st->cache_file, st->pool);
419     } 
420     if (result != APR_SUCCESS) {
421         return result;
422     }
423
424     /* Determine the usable size of the shm segment. */
425     size = apr_shm_size_get(st->cache_shm);
426
427     /* This will create a rmm "handler" to get into the shared memory area */
428     result = apr_rmm_init(&st->cache_rmm, NULL, 
429                           apr_shm_baseaddr_get(st->cache_shm), size, 
430                           st->pool);
431     if (result != APR_SUCCESS) {
432         return result;
433     }
434
435 #endif
436
437     apr_pool_cleanup_register(st->pool, st , util_ldap_cache_module_kill, apr_pool_cleanup_null);
438
439     st->util_ldap_cache =
440         util_ald_create_cache(st,
441                               util_ldap_url_node_hash,
442                               util_ldap_url_node_compare,
443                               util_ldap_url_node_copy,
444                               util_ldap_url_node_free,
445                               util_ldap_url_node_display);
446     return APR_SUCCESS;
447 }
448
449
450 #endif /* APU_HAS_LDAP */