Apache HTTPD
util_ldap_cache_mgr.c
Go to the documentation of this file.
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_mgr.c: LDAP cache manager 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 "httpd.h"
26#include "util_ldap.h"
27#include "util_ldap_cache.h"
28#include <apr_strings.h>
29
31
32#if APR_HAS_LDAP
33
34/* only here until strdup is gone */
35#include <string.h>
36
37/* here till malloc is gone */
38#include <stdlib.h>
39
40static const unsigned long primes[] =
41{
42 11,
43 19,
44 37,
45 73,
46 109,
47 163,
48 251,
49 367,
50 557,
51 823,
52 1237,
53 1861,
54 2777,
55 4177,
56 6247,
57 9371,
58 14057,
59 21089,
60 31627,
61 47431,
62 71143,
63 106721,
64 160073,
65 240101,
66 360163,
67 540217,
68 810343,
69 1215497,
70 1823231,
71 2734867,
72 4102283,
73 6153409,
74 9230113,
75 13845163,
76 0
77};
78
79void util_ald_free(util_ald_cache_t *cache, const void *ptr)
80{
81#if APR_HAS_SHARED_MEMORY
82 if (cache->rmm_addr) {
83 if (ptr)
84 /* Free in shared memory */
85 apr_rmm_free(cache->rmm_addr, apr_rmm_offset_get(cache->rmm_addr, (void *)ptr));
86 }
87 else {
88 if (ptr)
89 /* Cache shm is not used */
90 free((void *)ptr);
91 }
92#else
93 if (ptr)
94 free((void *)ptr);
95#endif
96}
97
98void *util_ald_alloc(util_ald_cache_t *cache, unsigned long size)
99{
100 if (0 == size)
101 return NULL;
102#if APR_HAS_SHARED_MEMORY
103 if (cache->rmm_addr) {
104 /* allocate from shared memory */
106 return block ? (void *)apr_rmm_addr_get(cache->rmm_addr, block) : NULL;
107 }
108 else {
109 /* Cache shm is not used */
110 return (void *)calloc(sizeof(char), size);
111 }
112#else
113 return (void *)calloc(sizeof(char), size);
114#endif
115}
116
117const char *util_ald_strdup(util_ald_cache_t *cache, const char *s)
118{
119#if APR_HAS_SHARED_MEMORY
120 if (cache->rmm_addr) {
121 /* allocate from shared memory */
122 apr_rmm_off_t block = apr_rmm_calloc(cache->rmm_addr, strlen(s)+1);
123 char *buf = block ? (char *)apr_rmm_addr_get(cache->rmm_addr, block) : NULL;
124 if (buf) {
125 strcpy(buf, s);
126 return buf;
127 }
128 else {
129 return NULL;
130 }
131 }
132 else {
133 /* Cache shm is not used */
134 return strdup(s);
135 }
136#else
137 return strdup(s);
138#endif
139}
140
141/*
142 * Duplicate a subgroupList from one compare entry to another.
143 * Returns: ptr to a new copy of the subgroupList or NULL if allocation failed.
144 */
146{
147 int i = 0;
149
150 if (!sgl_in) {
151 return NULL;
152 }
153
155 if (sgl_out) {
156 sgl_out->subgroupDNs = util_ald_alloc(cache, sizeof(char *) * sgl_in->len);
157 if (sgl_out->subgroupDNs) {
158 for (i = 0; i < sgl_in->len; i++) {
159 sgl_out->subgroupDNs[i] = util_ald_strdup(cache, sgl_in->subgroupDNs[i]);
160 if (!sgl_out->subgroupDNs[i]) {
161 /* We ran out of SHM, delete the strings we allocated for the SGL */
162 for (i = (i - 1); i >= 0; i--) {
163 util_ald_free(cache, sgl_out->subgroupDNs[i]);
164 }
165 util_ald_free(cache, sgl_out->subgroupDNs);
167 sgl_out = NULL;
168 break;
169 }
170 }
171 /* We were able to allocate new strings for all the subgroups */
172 if (sgl_out != NULL) {
173 sgl_out->len = sgl_in->len;
174 }
175 }
176 }
177
178 return sgl_out;
179}
180
181/*
182 * Delete an entire subgroupList.
183 */
185{
186 int i = 0;
187 if (sgl == NULL || *sgl == NULL) {
188 return;
189 }
190
191 for (i = 0; i < (*sgl)->len; i++) {
192 util_ald_free(cache, (*sgl)->subgroupDNs[i]);
193 }
195}
196
197/*
198 * Computes the hash on a set of strings. The first argument is the number
199 * of strings to hash, the rest of the args are strings.
200 * Algorithm taken from glibc.
201 */
202unsigned long util_ald_hash_string(int nstr, ...)
203{
204 int i;
206 unsigned long h=0, g;
207 char *str, *p;
208
210 for (i=0; i < nstr; ++i) {
211 str = va_arg(args, char *);
212 for (p = str; *p; ++p) {
213 h = ( h << 4 ) + *p;
214 if ( ( g = h & 0xf0000000 ) ) {
215 h = h ^ (g >> 24);
216 h = h ^ g;
217 }
218 }
219 }
220 va_end(args);
221
222 return h;
223}
224
225
226/*
227 Purges a cache that has gotten full. We keep track of the time that we
228 added the entry that made the cache 3/4 full, then delete all entries
229 that were added before that time. It's pretty simplistic, but time to
230 purge is only O(n), which is more important.
231*/
233{
234 unsigned long i;
235 util_cache_node_t *p, *q, **pp;
237
238 if (!cache)
239 return;
240
241 now = cache->last_purge = apr_time_now();
242 cache->npurged = 0;
243 cache->numpurges++;
244
245 /* If the marktime is farther back than TTL from now,
246 move the marktime forward to include additional expired entries.
247 */
248 if (now - cache->ttl > cache->marktime) {
249 cache->marktime = now - cache->ttl;
250 }
251
252 for (i=0; i < cache->size; ++i) {
253 pp = cache->nodes + i;
254 p = *pp;
255 while (p != NULL) {
256 if (p->add_time < cache->marktime) {
257 q = p->next;
258 (*cache->free)(cache, p->payload);
260 cache->numentries--;
261 cache->npurged++;
262 p = *pp = q;
263 }
264 else {
265 pp = &(p->next);
266 p = *pp;
267 }
268 }
269 }
270
271 now = apr_time_now();
272 cache->avg_purgetime =
273 ((now - cache->last_purge) + (cache->avg_purgetime * (cache->numpurges-1))) /
274 cache->numpurges;
275}
276
277
278/*
279 * create caches
280 */
282{
283 util_url_node_t curl;
287
288 /* create the three caches */
290 st->search_cache_size,
291 st->search_cache_ttl,
298 st->compare_cache_size,
299 st->compare_cache_ttl,
306 st->compare_cache_size,
307 st->compare_cache_ttl,
313
314 /* check that all the caches initialised successfully */
316 /* The contents of this structure will be duplicated in shared
317 memory during the insert. So use stack memory rather than
318 pool memory to avoid a memory leak. */
319 memset (&curl, 0, sizeof(util_url_node_t));
320 curl.url = url;
321 curl.search_cache = search_cache;
322 curl.compare_cache = compare_cache;
323 curl.dn_compare_cache = dn_compare_cache;
324
325 return util_ald_cache_insert(st->util_ldap_cache, &curl);
326 }
327 else {
328 /* util_ald_destroy_cache is a noop for a NULL argument. */
332
333 return NULL;
334 }
335}
336
337
339 long cache_size,
340 long cache_ttl,
341 unsigned long (*hashfunc)(void *),
342 int (*comparefunc)(void *, void *),
343 void * (*copyfunc)(util_ald_cache_t *cache, void *),
344 void (*freefunc)(util_ald_cache_t *cache, void *),
345 void (*displayfunc)(request_rec *r, util_ald_cache_t *cache, void *))
346{
348 unsigned long i;
349#if APR_HAS_SHARED_MEMORY
351#endif
352
353 if (cache_size <= 0)
354 return NULL;
355
356#if APR_HAS_SHARED_MEMORY
357 if (!st->cache_rmm) {
359 }
360 else {
361 block = apr_rmm_calloc(st->cache_rmm, sizeof(util_ald_cache_t));
363 }
364#else
366#endif
367 if (!cache)
368 return NULL;
369
370#if APR_HAS_SHARED_MEMORY
371 cache->rmm_addr = st->cache_rmm;
372 cache->shm_addr = st->cache_shm;
373#endif
374 cache->maxentries = cache_size;
375 cache->numentries = 0;
376 cache->size = cache_size / 3;
377 if (cache->size < 64)
378 cache->size = 64;
379 for (i = 0; primes[i] && primes[i] < cache->size; ++i)
380 ;
381 cache->size = primes[i] ? primes[i] : primes[i-1];
382
383 cache->nodes = (util_cache_node_t **)util_ald_alloc(cache, cache->size * sizeof(util_cache_node_t *));
384 if (!cache->nodes) {
385 /* This frees cache in the right way even if !APR_HAS_SHARED_MEMORY or !st->cache_rmm */
387 return NULL;
388 }
389
390 for (i=0; i < cache->size; ++i)
391 cache->nodes[i] = NULL;
392
393 cache->hash = hashfunc;
394 cache->compare = comparefunc;
395 cache->copy = copyfunc;
396 cache->free = freefunc;
397 cache->display = displayfunc;
398
399
400 cache->fullmark = cache->maxentries / 4 * 3;
401 cache->marktime = 0;
402 cache->ttl = cache_ttl;
403 cache->avg_purgetime = 0.0;
404 cache->numpurges = 0;
405 cache->last_purge = 0;
406 cache->npurged = 0;
407
408 cache->fetches = 0;
409 cache->hits = 0;
410 cache->inserts = 0;
411 cache->removes = 0;
412
413 return cache;
414}
415
417{
418 unsigned long i;
419 util_cache_node_t *p, *q;
420
421 if (cache == NULL)
422 return;
423
424 for (i = 0; i < cache->size; ++i) {
425 p = cache->nodes[i];
426 q = NULL;
427 while (p != NULL) {
428 q = p->next;
429 (*cache->free)(cache, p->payload);
431 p = q;
432 }
433 }
434 util_ald_free(cache, cache->nodes);
436}
437
439{
440 unsigned long hashval;
442
443 if (cache == NULL)
444 return NULL;
445
446 cache->fetches++;
447
448 hashval = (*cache->hash)(payload) % cache->size;
449
450 for (p = cache->nodes[hashval];
451 p && !(*cache->compare)(p->payload, payload);
452 p = p->next) ;
453
454 if (p != NULL) {
455 cache->hits++;
456 return p->payload;
457 }
458 else {
459 return NULL;
460 }
461}
462
463/*
464 * Insert an item into the cache.
465 * *** Does not catch duplicates!!! ***
466 */
468{
469 unsigned long hashval;
470 void *tmp_payload;
471 util_cache_node_t *node;
472
473 /* sanity check */
474 if (cache == NULL || payload == NULL) {
475 return NULL;
476 }
477
478 /* check if we are full - if so, try purge */
479 if (cache->numentries >= cache->maxentries) {
481 if (cache->numentries >= cache->maxentries) {
482 /* if the purge was not effective, we leave now to avoid an overflow */
484 "Purge of LDAP cache failed");
485 return NULL;
486 }
487 }
488
490 sizeof(util_cache_node_t));
491 if (node == NULL) {
492 /*
493 * XXX: The cache management should be rewritten to work
494 * properly when LDAPSharedCacheSize is too small.
495 */
497 "LDAPSharedCacheSize is too small. Increase it or "
498 "reduce LDAPCacheEntries/LDAPOpCacheEntries!");
499 if (cache->numentries < cache->fullmark) {
500 /*
501 * We have not even reached fullmark, trigger a complete purge.
502 * This is still better than not being able to add new entries
503 * at all.
504 */
505 cache->marktime = apr_time_now();
506 }
509 sizeof(util_cache_node_t));
510 if (node == NULL) {
512 "Could not allocate memory for LDAP cache entry");
513 return NULL;
514 }
515 }
516
517 /* Take a copy of the payload before proceeding. */
518 tmp_payload = (*cache->copy)(cache, payload);
519 if (tmp_payload == NULL) {
520 /*
521 * XXX: The cache management should be rewritten to work
522 * properly when LDAPSharedCacheSize is too small.
523 */
525 "LDAPSharedCacheSize is too small. Increase it or "
526 "reduce LDAPCacheEntries/LDAPOpCacheEntries!");
527 if (cache->numentries < cache->fullmark) {
528 /*
529 * We have not even reached fullmark, trigger a complete purge.
530 * This is still better than not being able to add new entries
531 * at all.
532 */
533 cache->marktime = apr_time_now();
534 }
536 tmp_payload = (*cache->copy)(cache, payload);
537 if (tmp_payload == NULL) {
539 "Could not allocate memory for LDAP cache value");
540 util_ald_free(cache, node);
541 return NULL;
542 }
543 }
545
546 /* populate the entry */
547 cache->inserts++;
548 hashval = (*cache->hash)(payload) % cache->size;
549 node->add_time = apr_time_now();
550 node->payload = payload;
551 node->next = cache->nodes[hashval];
552 cache->nodes[hashval] = node;
553
554 /* if we reach the full mark, note the time we did so
555 * for the benefit of the purge function
556 */
557 if (++cache->numentries == cache->fullmark) {
558 cache->marktime=apr_time_now();
559 }
560
561 return node->payload;
562}
563
565{
566 unsigned long hashval;
567 util_cache_node_t *p, *q;
568
569 if (cache == NULL)
570 return;
571
572 cache->removes++;
573 hashval = (*cache->hash)(payload) % cache->size;
574 for (p = cache->nodes[hashval], q=NULL;
575 p && !(*cache->compare)(p->payload, payload);
576 p = p->next) {
577 q = p;
578 }
579
580 /* If p is null, it means that we couldn't find the node, so just return */
581 if (p == NULL)
582 return;
583
584 if (q == NULL) {
585 /* We found the node, and it's the first in the list */
586 cache->nodes[hashval] = p->next;
587 }
588 else {
589 /* We found the node and it's not the first in the list */
590 q->next = p->next;
591 }
592 (*cache->free)(cache, p->payload);
594 cache->numentries--;
595}
596
598{
599 unsigned long i;
600 int totchainlen = 0;
601 int nchains = 0;
602 double chainlen;
604 char *buf, *buf2;
605 apr_pool_t *p = r->pool;
606
607 if (cache == NULL) {
608 return "";
609 }
610
611 for (i=0; i < cache->size; ++i) {
612 if (cache->nodes[i] != NULL) {
613 nchains++;
614 for (n = cache->nodes[i];
615 n != NULL && n != n->next;
616 n = n->next) {
617 totchainlen++;
618 }
619 }
620 }
621 chainlen = nchains? (double)totchainlen / (double)nchains : 0;
622
623 if (id) {
625 "<a href=\"%s?%s\">%s</a>",
627 id,
628 name);
629 }
630 else {
631 buf2 = name;
632 }
633
635 "<tr valign='top'>"
636 "<td nowrap>%s</td>"
637 "<td align='right' nowrap>%lu (%.0f%% full)</td>"
638 "<td align='right'>%.1f</td>"
639 "<td align='right'>%lu/%lu</td>"
640 "<td align='right'>%.0f%%</td>"
641 "<td align='right'>%lu/%lu</td>",
642 buf2,
643 cache->numentries,
644 (double)cache->numentries / (double)cache->maxentries * 100.0,
645 chainlen,
646 cache->hits,
647 cache->fetches,
648 (cache->fetches > 0 ? (double)(cache->hits) / (double)(cache->fetches) * 100.0 : 100.0),
649 cache->inserts,
650 cache->removes);
651
652 if (cache->numpurges) {
654
655 apr_ctime(str_ctime, cache->last_purge);
657 "%s"
658 "<td align='right'>%lu</td>\n"
659 "<td align='right' nowrap>%s</td>\n",
660 buf,
661 cache->numpurges,
662 str_ctime);
663 }
664 else {
666 "%s<td colspan='2' align='center'>(none)</td>\n",
667 buf);
668 }
669
670 buf = apr_psprintf(p, "%s<td align='right'>%.2gms</td>\n</tr>", buf, cache->avg_purgetime);
671
672 return buf;
673}
674
676{
677 unsigned long i,j;
678 char *buf, *t1, *t2, *t3;
679 char *id1, *id2, *id3;
680 char *argfmt = "cache=%s&id=%d&off=%d";
681 char *scanfmt = "cache=%4s&id=%u&off=%u%1s";
682 apr_pool_t *pool = r->pool;
685
686 util_ald_cache_t *util_ldap_cache = st->util_ldap_cache;
687
688
689 if (!util_ldap_cache) {
690 ap_rputs("<tr valign='top'><td nowrap colspan=7>Cache has not been enabled/initialised.</td></tr>", r);
691 return NULL;
692 }
693
694 if (r->args && strlen(r->args)) {
695 char cachetype[5], lint[2];
696 unsigned int id, off;
698
699 if ((3 == sscanf(r->args, scanfmt, cachetype, &id, &off, lint)) &&
701
702 if ((p = util_ldap_cache->nodes[id]) != NULL) {
703 n = (util_url_node_t *)p->payload;
704 buf = (char*)n->url;
705 }
706 else {
707 buf = "";
708 }
709
711 "<p>\n"
712 "<table border='0'>\n"
713 "<tr>\n"
714 "<td bgcolor='#000000'><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Cache Name:</b></font></td>"
715 "<td bgcolor='#ffffff'><font size='-1' face='Arial,Helvetica' color='#000000'><b>%s (%s)</b></font></td>"
716 "</tr>\n"
717 "</table>\n</p>\n",
718 buf,
719 cachetype[0] == 'm'? "Main" :
720 (cachetype[0] == 's' ? "Search" :
721 (cachetype[0] == 'c' ? "Compares" : "DNCompares")));
722
723 switch (cachetype[0]) {
724 case 'm':
725 if (util_ldap_cache->marktime) {
727 }
728 else
729 date_str[0] = 0;
730
732 "<p>\n"
733 "<table border='0'>\n"
734 "<tr>\n"
735 "<td bgcolor='#000000'><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Size:</b></font></td>"
736 "<td bgcolor='#ffffff'><font size='-1' face='Arial,Helvetica' color='#000000'><b>%ld</b></font></td>"
737 "</tr>\n"
738 "<tr>\n"
739 "<td bgcolor='#000000'><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Max Entries:</b></font></td>"
740 "<td bgcolor='#ffffff'><font size='-1' face='Arial,Helvetica' color='#000000'><b>%ld</b></font></td>"
741 "</tr>\n"
742 "<tr>\n"
743 "<td bgcolor='#000000'><font size='-1' face='Arial,Helvetica' color='#ffffff'><b># Entries:</b></font></td>"
744 "<td bgcolor='#ffffff'><font size='-1' face='Arial,Helvetica' color='#000000'><b>%ld</b></font></td>"
745 "</tr>\n"
746 "<tr>\n"
747 "<td bgcolor='#000000'><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>TTL (sec):</b></font></td>"
748 "<td bgcolor='#ffffff'><font size='-1' face='Arial,Helvetica' color='#000000'><b>%" APR_TIME_T_FMT "</b></font></td>"
749 "</tr>\n"
750 "<tr>\n"
751 "<td bgcolor='#000000'><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Full Mark:</b></font></td>"
752 "<td bgcolor='#ffffff'><font size='-1' face='Arial,Helvetica' color='#000000'><b>%ld</b></font></td>"
753 "</tr>\n"
754 "<tr>\n"
755 "<td bgcolor='#000000'><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Full Mark Time:</b></font></td>"
756 "<td bgcolor='#ffffff'><font size='-1' face='Arial,Helvetica' color='#000000'><b>%s</b></font></td>"
757 "</tr>\n"
758 "</table>\n</p>\n",
759 util_ldap_cache->size,
760 util_ldap_cache->maxentries,
761 util_ldap_cache->numentries,
763 util_ldap_cache->fullmark,
764 date_str);
765
766 ap_rputs("<p>\n"
767 "<table border='0'>\n"
768 "<tr bgcolor='#000000'>\n"
769 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>LDAP URL</b></font></td>"
770 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Size</b></font></td>"
771 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Max Entries</b></font></td>"
772 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b># Entries</b></font></td>"
773 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>TTL (sec)</b></font></td>"
774 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Full Mark</b></font></td>"
775 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Full Mark Time</b></font></td>"
776 "</tr>\n", r
777 );
778 for (i=0; i < util_ldap_cache->size; ++i) {
779 for (p = util_ldap_cache->nodes[i]; p != NULL; p = p->next) {
780
781 (*util_ldap_cache->display)(r, util_ldap_cache, p->payload);
782 }
783 }
784 ap_rputs("</table>\n</p>\n", r);
785
786
787 break;
788 case 's':
789 ap_rputs("<p>\n"
790 "<table border='0'>\n"
791 "<tr bgcolor='#000000'>\n"
792 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>LDAP Filter</b></font></td>"
793 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>User Name</b></font></td>"
794 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Last Bind</b></font></td>"
795 "</tr>\n", r
796 );
797 if (n) {
798 for (i=0; i < n->search_cache->size; ++i) {
799 for (p = n->search_cache->nodes[i]; p != NULL; p = p->next) {
800
801 (*n->search_cache->display)(r, n->search_cache, p->payload);
802 }
803 }
804 }
805 ap_rputs("</table>\n</p>\n", r);
806 break;
807 case 'c':
808 ap_rputs("<p>\n"
809 "<table border='0'>\n"
810 "<tr bgcolor='#000000'>\n"
811 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>DN</b></font></td>"
812 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Attribute</b></font></td>"
813 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Value</b></font></td>"
814 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Last Compare</b></font></td>"
815 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Result</b></font></td>"
816 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Sub-groups?</b></font></td>"
817 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>S-G Checked?</b></font></td>"
818 "</tr>\n", r
819 );
820 if (n) {
821 for (i=0; i < n->compare_cache->size; ++i) {
822 for (p = n->compare_cache->nodes[i]; p != NULL; p = p->next) {
823
824 (*n->compare_cache->display)(r, n->compare_cache, p->payload);
825 }
826 }
827 }
828 ap_rputs("</table>\n</p>\n", r);
829 break;
830 case 'd':
831 ap_rputs("<p>\n"
832 "<table border='0'>\n"
833 "<tr bgcolor='#000000'>\n"
834 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Require DN</b></font></td>"
835 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Actual DN</b></font></td>"
836 "</tr>\n", r
837 );
838 if (n) {
839 for (i=0; i < n->dn_compare_cache->size; ++i) {
840 for (p = n->dn_compare_cache->nodes[i]; p != NULL; p = p->next) {
841
842 (*n->dn_compare_cache->display)(r, n->dn_compare_cache, p->payload);
843 }
844 }
845 }
846 ap_rputs("</table>\n</p>\n", r);
847 break;
848 default:
849 break;
850 }
851
852 }
853 else {
854 buf = "";
855 }
856 }
857 else {
858 ap_rputs("<p>\n"
859 "<table border='0'>\n"
860 "<tr bgcolor='#000000'>\n"
861 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Cache Name</b></font></td>"
862 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Entries</b></font></td>"
863 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Avg. Chain Len.</b></font></td>"
864 "<td colspan='2'><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Hits</b></font></td>"
865 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Ins/Rem</b></font></td>"
866 "<td colspan='2'><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Purges</b></font></td>"
867 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Avg Purge Time</b></font></td>"
868 "</tr>\n", r
869 );
870
871
872 id1 = apr_psprintf(pool, argfmt, "main", 0, 0);
873 buf = util_ald_cache_display_stats(r, st->util_ldap_cache, "LDAP URL Cache", id1);
874
875 for (i=0; i < util_ldap_cache->size; ++i) {
876 for (p = util_ldap_cache->nodes[i],j=0; p != NULL; p = p->next,j++) {
877
878 n = (util_url_node_t *)p->payload;
879
880 t1 = apr_psprintf(pool, "%s (Searches)", n->url);
881 t2 = apr_psprintf(pool, "%s (Compares)", n->url);
882 t3 = apr_psprintf(pool, "%s (DNCompares)", n->url);
883 id1 = apr_psprintf(pool, argfmt, "srch", i, j);
884 id2 = apr_psprintf(pool, argfmt, "cmpr", i, j);
885 id3 = apr_psprintf(pool, argfmt, "dncp", i, j);
886
887 buf = apr_psprintf(pool, "%s\n\n"
888 "%s\n\n"
889 "%s\n\n"
890 "%s\n\n",
891 buf,
892 util_ald_cache_display_stats(r, n->search_cache, t1, id1),
893 util_ald_cache_display_stats(r, n->compare_cache, t2, id2),
894 util_ald_cache_display_stats(r, n->dn_compare_cache, t3, id3)
895 );
896 }
897 }
898 ap_rputs(buf, r);
899 ap_rputs("</table>\n</p>\n", r);
900 }
901
902 return buf;
903}
904
905#endif /* APR_HAS_LDAP */
int n
Definition ap_regex.h:278
char * strdup(const char *str)
APR Strings library.
#define APLOG_USE_MODULE(foo)
request_rec * r
#define APLOGNO(n)
Definition http_log.h:117
#define APLOG_ERR
Definition http_log.h:67
#define ap_log_error
Definition http_log.h:370
#define APLOG_MARK
Definition http_log.h:283
#define APLOG_WARNING
Definition http_log.h:68
const unsigned char * buf
Definition util_md5.h:50
int ap_rprintf(request_rec *r, const char *fmt,...) __attribute__((format(printf
static APR_INLINE int ap_rputs(const char *str, request_rec *r)
const char * url
Definition apr_escape.h:120
apr_size_t apr_rmm_off_t
Definition apr_rmm.h:43
#define ap_escape_uri(ppool, path)
Definition httpd.h:1836
#define ap_escape_html(p, s)
Definition httpd.h:1860
apr_size_t size
const char int apr_pool_t * pool
Definition apr_cstr.h:84
const apr_hash_t * h
Definition apr_hash.h:97
const char apr_uint32_t * id
const char * s
Definition apr_strings.h:95
const char const char *const * args
#define APR_CTIME_LEN
Definition apr_time.h:198
#define APR_TIME_T_FMT
Definition apr_time.h:52
apr_int64_t apr_time_t
Definition apr_time.h:45
#define apr_time_sec(time)
Definition apr_time.h:63
HTTP Daemon routines.
apr_pool_t * p
Definition md_event.c:32
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
char * name
A structure that represents the current request.
Definition httpd.h:845
char * uri
Definition httpd.h:1016
apr_pool_t * pool
Definition httpd.h:847
char * args
Definition httpd.h:1026
static apr_table_t * t1
Definition testtable.c:34
static apr_time_t now
Definition testtime.c:33
apr_status_t apr_ctime(char *date_str, apr_time_t t)
Definition timestr.c:90
#define str
Apache LDAP library.
This switches LDAP support on or off.