~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to modules/ldap/util_ldap_cache_mgr.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
30
#if APR_HAS_LDAP
 
31
 
 
32
/* only here until strdup is gone */
 
33
#include <string.h>
 
34
 
 
35
/* here till malloc is gone */
 
36
#include <stdlib.h>
 
37
 
 
38
static const unsigned long primes[] =
 
39
{
 
40
  11,
 
41
  19,
 
42
  37,
 
43
  73,
 
44
  109,
 
45
  163,
 
46
  251,
 
47
  367,
 
48
  557,
 
49
  823,
 
50
  1237,
 
51
  1861,
 
52
  2777,
 
53
  4177,
 
54
  6247,
 
55
  9371,
 
56
  14057,
 
57
  21089,
 
58
  31627,
 
59
  47431,
 
60
  71143,
 
61
  106721,
 
62
  160073,
 
63
  240101,
 
64
  360163,
 
65
  540217,
 
66
  810343,
 
67
  1215497,
 
68
  1823231,
 
69
  2734867,
 
70
  4102283,
 
71
  6153409,
 
72
  9230113,
 
73
  13845163,
 
74
  0
 
75
};
 
76
 
 
77
void util_ald_free(util_ald_cache_t *cache, const void *ptr)
 
78
{
 
79
#if APR_HAS_SHARED_MEMORY
 
80
    if (cache->rmm_addr) {
 
81
        if (ptr)
 
82
            /* Free in shared memory */
 
83
            apr_rmm_free(cache->rmm_addr, apr_rmm_offset_get(cache->rmm_addr, (void *)ptr));
 
84
    }
 
85
    else {
 
86
        if (ptr)
 
87
            /* Cache shm is not used */
 
88
            free((void *)ptr);
 
89
    }
 
90
#else
 
91
    if (ptr)
 
92
        free((void *)ptr);
 
93
#endif
 
94
}
 
95
 
 
96
void *util_ald_alloc(util_ald_cache_t *cache, unsigned long size)
 
97
{
 
98
    if (0 == size)
 
99
        return NULL;
 
100
#if APR_HAS_SHARED_MEMORY
 
101
    if (cache->rmm_addr) {
 
102
        /* allocate from shared memory */
 
103
        apr_rmm_off_t block = apr_rmm_calloc(cache->rmm_addr, size);
 
104
        return block ? (void *)apr_rmm_addr_get(cache->rmm_addr, block) : NULL;
 
105
    }
 
106
    else {
 
107
        /* Cache shm is not used */
 
108
        return (void *)calloc(sizeof(char), size);
 
109
    }
 
110
#else
 
111
    return (void *)calloc(sizeof(char), size);
 
112
#endif
 
113
}
 
114
 
 
115
const char *util_ald_strdup(util_ald_cache_t *cache, const char *s)
 
116
{
 
117
#if APR_HAS_SHARED_MEMORY
 
118
    if (cache->rmm_addr) {
 
119
        /* allocate from shared memory */
 
120
        apr_rmm_off_t block = apr_rmm_calloc(cache->rmm_addr, strlen(s)+1);
 
121
        char *buf = block ? (char *)apr_rmm_addr_get(cache->rmm_addr, block) : NULL;
 
122
        if (buf) {
 
123
            strcpy(buf, s);
 
124
            return buf;
 
125
        }
 
126
        else {
 
127
            return NULL;
 
128
        }
 
129
    } else {
 
130
        /* Cache shm is not used */
 
131
        return strdup(s);
 
132
    }
 
133
#else
 
134
    return strdup(s);
 
135
#endif
 
136
}
 
137
 
 
138
 
 
139
/*
 
140
 * Computes the hash on a set of strings. The first argument is the number
 
141
 * of strings to hash, the rest of the args are strings.
 
142
 * Algorithm taken from glibc.
 
143
 */
 
144
unsigned long util_ald_hash_string(int nstr, ...)
 
145
{
 
146
    int i;
 
147
    va_list args;
 
148
    unsigned long h=0, g;
 
149
    char *str, *p;
 
150
 
 
151
    va_start(args, nstr);
 
152
    for (i=0; i < nstr; ++i) {
 
153
        str = va_arg(args, char *);
 
154
        for (p = str; *p; ++p) {
 
155
            h = ( h << 4 ) + *p;
 
156
            if ( ( g = h & 0xf0000000 ) ) {
 
157
                h = h ^ (g >> 24);
 
158
                h = h ^ g;
 
159
            }
 
160
        }
 
161
    }
 
162
    va_end(args);
 
163
 
 
164
    return h;
 
165
}
 
166
 
 
167
 
 
168
/*
 
169
  Purges a cache that has gotten full. We keep track of the time that we
 
170
  added the entry that made the cache 3/4 full, then delete all entries
 
171
  that were added before that time. It's pretty simplistic, but time to
 
172
  purge is only O(n), which is more important.
 
173
*/
 
174
void util_ald_cache_purge(util_ald_cache_t *cache)
 
175
{
 
176
    unsigned long i;
 
177
    util_cache_node_t *p, *q, **pp;
 
178
    apr_time_t t;
 
179
 
 
180
    if (!cache)
 
181
        return;
 
182
 
 
183
    cache->last_purge = apr_time_now();
 
184
    cache->npurged = 0;
 
185
    cache->numpurges++;
 
186
 
 
187
    for (i=0; i < cache->size; ++i) {
 
188
        pp = cache->nodes + i;
 
189
        p = *pp;
 
190
        while (p != NULL) {
 
191
            if (p->add_time < cache->marktime) {
 
192
                q = p->next;
 
193
                (*cache->free)(cache, p->payload);
 
194
                util_ald_free(cache, p);
 
195
                cache->numentries--;
 
196
                cache->npurged++;
 
197
                p = *pp = q;
 
198
            }
 
199
            else {
 
200
                pp = &(p->next);
 
201
                p = *pp;
 
202
            }
 
203
        }
 
204
    }
 
205
 
 
206
    t = apr_time_now();
 
207
    cache->avg_purgetime =
 
208
         ((t - cache->last_purge) + (cache->avg_purgetime * (cache->numpurges-1))) /
 
209
         cache->numpurges;
 
210
}
 
211
 
 
212
 
 
213
/*
 
214
 * create caches
 
215
 */
 
216
util_url_node_t *util_ald_create_caches(util_ldap_state_t *st, const char *url)
 
217
{
 
218
    util_url_node_t curl, *newcurl = NULL;
 
219
    util_ald_cache_t *search_cache;
 
220
    util_ald_cache_t *compare_cache;
 
221
    util_ald_cache_t *dn_compare_cache;
 
222
 
 
223
    /* create the three caches */
 
224
    search_cache = util_ald_create_cache(st,
 
225
                      st->search_cache_size,
 
226
                      util_ldap_search_node_hash,
 
227
                      util_ldap_search_node_compare,
 
228
                      util_ldap_search_node_copy,
 
229
                      util_ldap_search_node_free,
 
230
                      util_ldap_search_node_display);
 
231
    compare_cache = util_ald_create_cache(st,
 
232
                      st->compare_cache_size,
 
233
                      util_ldap_compare_node_hash,
 
234
                      util_ldap_compare_node_compare,
 
235
                      util_ldap_compare_node_copy,
 
236
                      util_ldap_compare_node_free,
 
237
                      util_ldap_compare_node_display);
 
238
    dn_compare_cache = util_ald_create_cache(st,
 
239
                      st->compare_cache_size,
 
240
                      util_ldap_dn_compare_node_hash,
 
241
                      util_ldap_dn_compare_node_compare,
 
242
                      util_ldap_dn_compare_node_copy,
 
243
                      util_ldap_dn_compare_node_free,
 
244
                      util_ldap_dn_compare_node_display);
 
245
 
 
246
    /* check that all the caches initialised successfully */
 
247
    if (search_cache && compare_cache && dn_compare_cache) {
 
248
 
 
249
        /* The contents of this structure will be duplicated in shared
 
250
           memory during the insert.  So use stack memory rather than
 
251
           pool memory to avoid a memory leak. */
 
252
        memset (&curl, 0, sizeof(util_url_node_t));
 
253
        curl.url = url;
 
254
        curl.search_cache = search_cache;
 
255
        curl.compare_cache = compare_cache;
 
256
        curl.dn_compare_cache = dn_compare_cache;
 
257
 
 
258
        newcurl = util_ald_cache_insert(st->util_ldap_cache, &curl);
 
259
 
 
260
    }
 
261
 
 
262
    return newcurl;
 
263
}
 
264
 
 
265
 
 
266
util_ald_cache_t *util_ald_create_cache(util_ldap_state_t *st,
 
267
                                long cache_size,
 
268
                                unsigned long (*hashfunc)(void *),
 
269
                                int (*comparefunc)(void *, void *),
 
270
                                void * (*copyfunc)(util_ald_cache_t *cache, void *),
 
271
                                void (*freefunc)(util_ald_cache_t *cache, void *),
 
272
                                void (*displayfunc)(request_rec *r, util_ald_cache_t *cache, void *))
 
273
{
 
274
    util_ald_cache_t *cache;
 
275
    unsigned long i;
 
276
 
 
277
    if (cache_size <= 0)
 
278
        return NULL;
 
279
 
 
280
#if APR_HAS_SHARED_MEMORY
 
281
    if (!st->cache_rmm) {
 
282
        return NULL;
 
283
    }
 
284
    else {
 
285
        apr_rmm_off_t block = apr_rmm_calloc(st->cache_rmm, sizeof(util_ald_cache_t));
 
286
        cache = block ? (util_ald_cache_t *)apr_rmm_addr_get(st->cache_rmm, block) : NULL;
 
287
    }
 
288
#else
 
289
    cache = (util_ald_cache_t *)calloc(sizeof(util_ald_cache_t), 1);
 
290
#endif
 
291
    if (!cache)
 
292
        return NULL;
 
293
 
 
294
#if APR_HAS_SHARED_MEMORY
 
295
    cache->rmm_addr = st->cache_rmm;
 
296
    cache->shm_addr = st->cache_shm;
 
297
#endif
 
298
    cache->maxentries = cache_size;
 
299
    cache->numentries = 0;
 
300
    cache->size = cache_size / 3;
 
301
    if (cache->size < 64) cache->size = 64;
 
302
        for (i = 0; primes[i] && primes[i] < cache->size; ++i) ;
 
303
            cache->size = primes[i]? primes[i] : primes[i-1];
 
304
 
 
305
    cache->nodes = (util_cache_node_t **)util_ald_alloc(cache, cache->size * sizeof(util_cache_node_t *));
 
306
    if (!cache->nodes) {
 
307
        util_ald_free(cache, cache);
 
308
        return NULL;
 
309
    }
 
310
 
 
311
    for (i=0; i < cache->size; ++i)
 
312
        cache->nodes[i] = NULL;
 
313
 
 
314
    cache->hash = hashfunc;
 
315
    cache->compare = comparefunc;
 
316
    cache->copy = copyfunc;
 
317
    cache->free = freefunc;
 
318
    cache->display = displayfunc;
 
319
 
 
320
    cache->fullmark = cache->maxentries / 4 * 3;
 
321
    cache->marktime = 0;
 
322
    cache->avg_purgetime = 0.0;
 
323
    cache->numpurges = 0;
 
324
    cache->last_purge = 0;
 
325
    cache->npurged = 0;
 
326
 
 
327
    cache->fetches = 0;
 
328
    cache->hits = 0;
 
329
    cache->inserts = 0;
 
330
    cache->removes = 0;
 
331
 
 
332
    return cache;
 
333
}
 
334
 
 
335
void util_ald_destroy_cache(util_ald_cache_t *cache)
 
336
{
 
337
    unsigned long i;
 
338
    util_cache_node_t *p, *q;
 
339
 
 
340
    if (cache == NULL)
 
341
        return;
 
342
 
 
343
    for (i = 0; i < cache->size; ++i) {
 
344
        p = cache->nodes[i];
 
345
        q = NULL;
 
346
        while (p != NULL) {
 
347
            q = p->next;
 
348
           (*cache->free)(cache, p->payload);
 
349
           util_ald_free(cache, p);
 
350
           p = q;
 
351
        }
 
352
    }
 
353
    util_ald_free(cache, cache->nodes);
 
354
    util_ald_free(cache, cache);
 
355
}
 
356
 
 
357
void *util_ald_cache_fetch(util_ald_cache_t *cache, void *payload)
 
358
{
 
359
    unsigned long hashval;
 
360
    util_cache_node_t *p;
 
361
 
 
362
    if (cache == NULL)
 
363
        return NULL;
 
364
 
 
365
    cache->fetches++;
 
366
 
 
367
    hashval = (*cache->hash)(payload) % cache->size;
 
368
    for (p = cache->nodes[hashval];
 
369
         p && !(*cache->compare)(p->payload, payload);
 
370
    p = p->next) ;
 
371
 
 
372
    if (p != NULL) {
 
373
        cache->hits++;
 
374
        return p->payload;
 
375
    }
 
376
    else {
 
377
        return NULL;
 
378
    }
 
379
}
 
380
 
 
381
/*
 
382
 * Insert an item into the cache.
 
383
 * *** Does not catch duplicates!!! ***
 
384
 */
 
385
void *util_ald_cache_insert(util_ald_cache_t *cache, void *payload)
 
386
{
 
387
    unsigned long hashval;
 
388
    util_cache_node_t *node;
 
389
 
 
390
    /* sanity check */
 
391
    if (cache == NULL || payload == NULL) {
 
392
        return NULL;
 
393
    }
 
394
 
 
395
    /* check if we are full - if so, try purge */
 
396
    if (cache->numentries >= cache->maxentries) {
 
397
        util_ald_cache_purge(cache);
 
398
        if (cache->numentries >= cache->maxentries) {
 
399
            /* if the purge was not effective, we leave now to avoid an overflow */
 
400
            return NULL;
 
401
        }
 
402
    }
 
403
 
 
404
    /* should be safe to add an entry */
 
405
    if ((node = (util_cache_node_t *)util_ald_alloc(cache, sizeof(util_cache_node_t))) == NULL) {
 
406
        return NULL;
 
407
    }
 
408
 
 
409
    /* Take a copy of the payload before proceeeding. */
 
410
    payload = (*cache->copy)(cache, payload);
 
411
    if (!payload) {
 
412
        util_ald_free(cache, node);
 
413
        return NULL;
 
414
    }
 
415
 
 
416
    /* populate the entry */
 
417
    cache->inserts++;
 
418
    hashval = (*cache->hash)(payload) % cache->size;
 
419
    node->add_time = apr_time_now();
 
420
    node->payload = payload;
 
421
    node->next = cache->nodes[hashval];
 
422
    cache->nodes[hashval] = node;
 
423
 
 
424
    /* if we reach the full mark, note the time we did so
 
425
     * for the benefit of the purge function
 
426
     */
 
427
    if (++cache->numentries == cache->fullmark) {
 
428
        cache->marktime=apr_time_now();
 
429
    }
 
430
 
 
431
    return node->payload;
 
432
}
 
433
 
 
434
void util_ald_cache_remove(util_ald_cache_t *cache, void *payload)
 
435
{
 
436
    unsigned long hashval;
 
437
    util_cache_node_t *p, *q;
 
438
 
 
439
    if (cache == NULL)
 
440
        return;
 
441
 
 
442
    cache->removes++;
 
443
    hashval = (*cache->hash)(payload) % cache->size;
 
444
    for (p = cache->nodes[hashval], q=NULL;
 
445
         p && !(*cache->compare)(p->payload, payload);
 
446
         p = p->next) {
 
447
         q = p;
 
448
    }
 
449
 
 
450
    /* If p is null, it means that we couldn't find the node, so just return */
 
451
    if (p == NULL)
 
452
        return;
 
453
 
 
454
    if (q == NULL) {
 
455
        /* We found the node, and it's the first in the list */
 
456
        cache->nodes[hashval] = p->next;
 
457
    }
 
458
    else {
 
459
        /* We found the node and it's not the first in the list */
 
460
        q->next = p->next;
 
461
    }
 
462
    (*cache->free)(cache, p->payload);
 
463
    util_ald_free(cache, p);
 
464
    cache->numentries--;
 
465
}
 
466
 
 
467
char *util_ald_cache_display_stats(request_rec *r, util_ald_cache_t *cache, char *name, char *id)
 
468
{
 
469
    unsigned long i;
 
470
    int totchainlen = 0;
 
471
    int nchains = 0;
 
472
    double chainlen;
 
473
    util_cache_node_t *n;
 
474
    char *buf, *buf2;
 
475
    apr_pool_t *p = r->pool;
 
476
 
 
477
    if (cache == NULL) {
 
478
        return "";
 
479
    }
 
480
 
 
481
    for (i=0; i < cache->size; ++i) {
 
482
        if (cache->nodes[i] != NULL) {
 
483
            nchains++;
 
484
            for (n = cache->nodes[i];
 
485
                 n != NULL && n != n->next;
 
486
                 n = n->next) {
 
487
                totchainlen++;
 
488
            }
 
489
        }
 
490
    }
 
491
    chainlen = nchains? (double)totchainlen / (double)nchains : 0;
 
492
 
 
493
    if (id) {
 
494
        buf2 = apr_psprintf(p,
 
495
                 "<a href=\"%s?%s\">%s</a>",
 
496
             r->uri,
 
497
             id,
 
498
             name);
 
499
    }
 
500
    else {
 
501
        buf2 = name;
 
502
    }
 
503
 
 
504
    buf = apr_psprintf(p,
 
505
             "<tr valign='top'>"
 
506
             "<td nowrap>%s</td>"
 
507
             "<td align='right' nowrap>%lu (%.0f%% full)</td>"
 
508
             "<td align='right'>%.1f</td>"
 
509
             "<td align='right'>%lu/%lu</td>"
 
510
             "<td align='right'>%.0f%%</td>"
 
511
             "<td align='right'>%lu/%lu</td>",
 
512
         buf2,
 
513
         cache->numentries,
 
514
         (double)cache->numentries / (double)cache->maxentries * 100.0,
 
515
         chainlen,
 
516
         cache->hits,
 
517
         cache->fetches,
 
518
         (cache->fetches > 0 ? (double)(cache->hits) / (double)(cache->fetches) * 100.0 : 100.0),
 
519
         cache->inserts,
 
520
         cache->removes);
 
521
 
 
522
    if (cache->numpurges) {
 
523
        char str_ctime[APR_CTIME_LEN];
 
524
 
 
525
        apr_ctime(str_ctime, cache->last_purge);
 
526
        buf = apr_psprintf(p,
 
527
                 "%s"
 
528
                 "<td align='right'>%lu</td>\n"
 
529
                 "<td align='right' nowrap>%s</td>\n",
 
530
             buf,
 
531
             cache->numpurges,
 
532
             str_ctime);
 
533
    }
 
534
    else {
 
535
        buf = apr_psprintf(p,
 
536
                 "%s<td colspan='2' align='center'>(none)</td>\n",
 
537
             buf);
 
538
    }
 
539
 
 
540
    buf = apr_psprintf(p, "%s<td align='right'>%.2gms</td>\n</tr>", buf, cache->avg_purgetime);
 
541
 
 
542
    return buf;
 
543
}
 
544
 
 
545
char *util_ald_cache_display(request_rec *r, util_ldap_state_t *st)
 
546
{
 
547
    unsigned long i,j;
 
548
    char *buf, *t1, *t2, *t3;
 
549
    char *id1, *id2, *id3;
 
550
    char *argfmt = "cache=%s&id=%d&off=%d";
 
551
    char *scanfmt = "cache=%4s&id=%u&off=%u%1s";
 
552
    apr_pool_t *pool = r->pool;
 
553
    util_cache_node_t *p = NULL;
 
554
    util_url_node_t *n = NULL;
 
555
 
 
556
    util_ald_cache_t *util_ldap_cache = st->util_ldap_cache;
 
557
 
 
558
 
 
559
    if (!util_ldap_cache) {
 
560
        return "<tr valign='top'><td nowrap colspan=7>Cache has not been enabled/initialised.</td></tr>";
 
561
    }
 
562
 
 
563
    if (r->args && strlen(r->args)) {
 
564
        char cachetype[5], lint[2];
 
565
        unsigned int id, off;
 
566
        char date_str[APR_CTIME_LEN+1];
 
567
 
 
568
        if ((3 == sscanf(r->args, scanfmt, cachetype, &id, &off, lint)) &&
 
569
            (id < util_ldap_cache->size)) {
 
570
 
 
571
            if ((p = util_ldap_cache->nodes[id]) != NULL) {
 
572
                n = (util_url_node_t *)p->payload;
 
573
                buf = (char*)n->url;
 
574
            }
 
575
            else {
 
576
                buf = "";
 
577
            }
 
578
 
 
579
            ap_rprintf(r,
 
580
                       "<p>\n"
 
581
                       "<table border='0'>\n"
 
582
                       "<tr>\n"
 
583
                       "<td bgcolor='#000000'><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Cache Name:</b></font></td>"
 
584
                       "<td bgcolor='#ffffff'><font size='-1' face='Arial,Helvetica' color='#000000'><b>%s (%s)</b></font></td>"
 
585
                       "</tr>\n"
 
586
                       "</table>\n</p>\n",
 
587
                       buf,
 
588
                       cachetype[0] == 'm'? "Main" :
 
589
                       (cachetype[0] == 's' ? "Search" :
 
590
                        (cachetype[0] == 'c' ? "Compares" : "DNCompares")));
 
591
 
 
592
            switch (cachetype[0]) {
 
593
                case 'm':
 
594
                    if (util_ldap_cache->marktime) {
 
595
                        apr_ctime(date_str, util_ldap_cache->marktime);
 
596
                    }
 
597
                    else
 
598
                        date_str[0] = 0;
 
599
 
 
600
                    ap_rprintf(r,
 
601
                               "<p>\n"
 
602
                               "<table border='0'>\n"
 
603
                               "<tr>\n"
 
604
                               "<td bgcolor='#000000'><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Size:</b></font></td>"
 
605
                               "<td bgcolor='#ffffff'><font size='-1' face='Arial,Helvetica' color='#000000'><b>%ld</b></font></td>"
 
606
                               "</tr>\n"
 
607
                               "<tr>\n"
 
608
                               "<td bgcolor='#000000'><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Max Entries:</b></font></td>"
 
609
                               "<td bgcolor='#ffffff'><font size='-1' face='Arial,Helvetica' color='#000000'><b>%ld</b></font></td>"
 
610
                               "</tr>\n"
 
611
                               "<tr>\n"
 
612
                               "<td bgcolor='#000000'><font size='-1' face='Arial,Helvetica' color='#ffffff'><b># Entries:</b></font></td>"
 
613
                               "<td bgcolor='#ffffff'><font size='-1' face='Arial,Helvetica' color='#000000'><b>%ld</b></font></td>"
 
614
                               "</tr>\n"
 
615
                               "<tr>\n"
 
616
                               "<td bgcolor='#000000'><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Full Mark:</b></font></td>"
 
617
                               "<td bgcolor='#ffffff'><font size='-1' face='Arial,Helvetica' color='#000000'><b>%ld</b></font></td>"
 
618
                               "</tr>\n"
 
619
                               "<tr>\n"
 
620
                               "<td bgcolor='#000000'><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Full Mark Time:</b></font></td>"
 
621
                               "<td bgcolor='#ffffff'><font size='-1' face='Arial,Helvetica' color='#000000'><b>%s</b></font></td>"
 
622
                               "</tr>\n"
 
623
                               "</table>\n</p>\n",
 
624
                               util_ldap_cache->size,
 
625
                               util_ldap_cache->maxentries,
 
626
                               util_ldap_cache->numentries,
 
627
                               util_ldap_cache->fullmark,
 
628
                               date_str);
 
629
 
 
630
                    ap_rputs("<p>\n"
 
631
                             "<table border='0'>\n"
 
632
                             "<tr bgcolor='#000000'>\n"
 
633
                             "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>LDAP URL</b></font></td>"
 
634
                             "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Size</b></font></td>"
 
635
                             "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Max Entries</b></font></td>"
 
636
                             "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b># Entries</b></font></td>"
 
637
                             "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Full Mark</b></font></td>"
 
638
                             "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Full Mark Time</b></font></td>"
 
639
                             "</tr>\n", r
 
640
                            );
 
641
                    for (i=0; i < util_ldap_cache->size; ++i) {
 
642
                        for (p = util_ldap_cache->nodes[i]; p != NULL; p = p->next) {
 
643
 
 
644
                            (*util_ldap_cache->display)(r, util_ldap_cache, p->payload);
 
645
                        }
 
646
                    }
 
647
                    ap_rputs("</table>\n</p>\n", r);
 
648
 
 
649
 
 
650
                    break;
 
651
                case 's':
 
652
                    ap_rputs("<p>\n"
 
653
                             "<table border='0'>\n"
 
654
                             "<tr bgcolor='#000000'>\n"
 
655
                             "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>LDAP Filter</b></font></td>"
 
656
                             "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>User Name</b></font></td>"
 
657
                             "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Last Bind</b></font></td>"
 
658
                             "</tr>\n", r
 
659
                            );
 
660
                    if (n) {
 
661
                        for (i=0; i < n->search_cache->size; ++i) {
 
662
                            for (p = n->search_cache->nodes[i]; p != NULL; p = p->next) {
 
663
 
 
664
                                (*n->search_cache->display)(r, n->search_cache, p->payload);
 
665
                            }
 
666
                        }
 
667
                    }
 
668
                    ap_rputs("</table>\n</p>\n", r);
 
669
                    break;
 
670
                case 'c':
 
671
                    ap_rputs("<p>\n"
 
672
                             "<table border='0'>\n"
 
673
                             "<tr bgcolor='#000000'>\n"
 
674
                             "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>DN</b></font></td>"
 
675
                             "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Attribute</b></font></td>"
 
676
                             "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Value</b></font></td>"
 
677
                             "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Last Compare</b></font></td>"
 
678
                             "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Result</b></font></td>"
 
679
                             "</tr>\n", r
 
680
                            );
 
681
                    if (n) {
 
682
                        for (i=0; i < n->compare_cache->size; ++i) {
 
683
                            for (p = n->compare_cache->nodes[i]; p != NULL; p = p->next) {
 
684
 
 
685
                                (*n->compare_cache->display)(r, n->compare_cache, p->payload);
 
686
                            }
 
687
                        }
 
688
                    }
 
689
                    ap_rputs("</table>\n</p>\n", r);
 
690
                    break;
 
691
                case 'd':
 
692
                    ap_rputs("<p>\n"
 
693
                             "<table border='0'>\n"
 
694
                             "<tr bgcolor='#000000'>\n"
 
695
                             "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Require DN</b></font></td>"
 
696
                             "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Actual DN</b></font></td>"
 
697
                             "</tr>\n", r
 
698
                            );
 
699
                    if (n) {
 
700
                        for (i=0; i < n->dn_compare_cache->size; ++i) {
 
701
                            for (p = n->dn_compare_cache->nodes[i]; p != NULL; p = p->next) {
 
702
 
 
703
                                (*n->dn_compare_cache->display)(r, n->dn_compare_cache, p->payload);
 
704
                            }
 
705
                        }
 
706
                    }
 
707
                    ap_rputs("</table>\n</p>\n", r);
 
708
                    break;
 
709
                default:
 
710
                    break;
 
711
            }
 
712
 
 
713
        }
 
714
        else {
 
715
            buf = "";
 
716
        }
 
717
    }
 
718
    else {
 
719
        ap_rputs("<p>\n"
 
720
                 "<table border='0'>\n"
 
721
                 "<tr bgcolor='#000000'>\n"
 
722
                 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Cache Name</b></font></td>"
 
723
                 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Entries</b></font></td>"
 
724
                 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Avg. Chain Len.</b></font></td>"
 
725
                 "<td colspan='2'><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Hits</b></font></td>"
 
726
                 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Ins/Rem</b></font></td>"
 
727
                 "<td colspan='2'><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Purges</b></font></td>"
 
728
                 "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Avg Purge Time</b></font></td>"
 
729
                 "</tr>\n", r
 
730
                );
 
731
 
 
732
 
 
733
        id1 = apr_psprintf(pool, argfmt, "main", 0, 0);
 
734
        buf = util_ald_cache_display_stats(r, st->util_ldap_cache, "LDAP URL Cache", id1);
 
735
 
 
736
        for (i=0; i < util_ldap_cache->size; ++i) {
 
737
            for (p = util_ldap_cache->nodes[i],j=0; p != NULL; p = p->next,j++) {
 
738
 
 
739
                n = (util_url_node_t *)p->payload;
 
740
 
 
741
                t1 = apr_psprintf(pool, "%s (Searches)", n->url);
 
742
                t2 = apr_psprintf(pool, "%s (Compares)", n->url);
 
743
                t3 = apr_psprintf(pool, "%s (DNCompares)", n->url);
 
744
                id1 = apr_psprintf(pool, argfmt, "srch", i, j);
 
745
                id2 = apr_psprintf(pool, argfmt, "cmpr", i, j);
 
746
                id3 = apr_psprintf(pool, argfmt, "dncp", i, j);
 
747
 
 
748
                buf = apr_psprintf(pool, "%s\n\n"
 
749
                                         "%s\n\n"
 
750
                                         "%s\n\n"
 
751
                                         "%s\n\n",
 
752
                                         buf,
 
753
                                         util_ald_cache_display_stats(r, n->search_cache, t1, id1),
 
754
                                         util_ald_cache_display_stats(r, n->compare_cache, t2, id2),
 
755
                                         util_ald_cache_display_stats(r, n->dn_compare_cache, t3, id3)
 
756
                                  );
 
757
            }
 
758
        }
 
759
        ap_rputs(buf, r);
 
760
        ap_rputs("</table>\n</p>\n", r);
 
761
    }
 
762
 
 
763
    return buf;
 
764
}
 
765
 
 
766
#endif /* APR_HAS_LDAP */