]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldbm/cache.c
Should be in releng
[openldap] / servers / slapd / back-ldbm / cache.c
1 /* cache.c - routines to maintain an in-core cache of entries */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 1998-2003 The OpenLDAP Foundation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
12  * A copy of this license is available in the file LICENSE in the
13  * top-level directory of the distribution or, alternatively, at
14  * <http://www.OpenLDAP.org/license.html>.
15  */
16
17 #include "portable.h"
18
19 #include <stdio.h>
20
21 #include <ac/errno.h>
22 #include <ac/string.h>
23 #include <ac/socket.h>
24
25 #include "slap.h"
26
27 #include "back-ldbm.h"
28
29 /* LDBM backend specific entry info -- visible only to the cache */
30 typedef struct ldbm_entry_info {
31         /*
32          * These items are specific to the LDBM backend and should
33          * be hidden.  Backend cache lock required to access.
34          */
35         int             lei_state;      /* for the cache */
36 #define CACHE_ENTRY_UNDEFINED   0
37 #define CACHE_ENTRY_CREATING    1
38 #define CACHE_ENTRY_READY       2
39 #define CACHE_ENTRY_DELETED     3
40 #define CACHE_ENTRY_COMMITTED   4
41         
42         int             lei_refcnt;     /* # threads ref'ing this entry */
43         Entry   *lei_lrunext;   /* for cache lru list */
44         Entry   *lei_lruprev;
45 } EntryInfo;
46 #undef LEI
47 #define LEI(e)  ((EntryInfo *) ((e)->e_private))
48
49 static int      cache_delete_entry_internal(Cache *cache, Entry *e);
50 #ifdef LDAP_DEBUG
51 static void     lru_print(Cache *cache);
52 #endif
53
54 static int
55 cache_entry_private_init( Entry*e )
56 {
57         assert( e->e_private == NULL );
58
59         if( e->e_private != NULL ) {
60                 /* this should never happen */
61                 return 1;
62         }
63
64         e->e_private = ch_calloc(1, sizeof(struct ldbm_entry_info));
65
66         return 0;
67 }
68
69 /*
70  * marks an entry in CREATING state as committed, so it is really returned
71  * to the cache. Otherwise an entry in CREATING state is removed.
72  * Makes e_private be destroyed at the following cache_return_entry_w,
73  * but lets the entry untouched (owned by someone else)
74  */
75 void
76 cache_entry_commit( Entry *e )
77 {
78         assert( e );
79         assert( e->e_private );
80         assert( LEI(e)->lei_state == CACHE_ENTRY_CREATING );
81         /* assert( LEI(e)->lei_refcnt == 1 ); */
82
83         LEI(e)->lei_state = CACHE_ENTRY_COMMITTED;
84 }
85
86 static int
87 cache_entry_private_destroy( Entry*e )
88 {
89         assert( e->e_private );
90
91         free( e->e_private );
92         e->e_private = NULL;
93         return 0;
94 }
95
96 void
97 cache_return_entry_rw( Cache *cache, Entry *e, int rw )
98 {
99         ID id;
100         int refcnt, freeit = 1;
101
102         /* set cache mutex */
103         ldap_pvt_thread_mutex_lock( &cache->c_mutex );
104
105         assert( e->e_private );
106
107         id = e->e_id;
108         refcnt = --LEI(e)->lei_refcnt;
109
110         /*
111          * if the entry is returned when in CREATING state, it is deleted
112          * but not freed because it may belong to someone else (do_add,
113          * for instance)
114          */
115         if (  LEI(e)->lei_state == CACHE_ENTRY_CREATING ) {
116                 cache_delete_entry_internal( cache, e );
117                 freeit = 0;
118                 /* now the entry is in DELETED state */
119         }
120
121         if ( LEI(e)->lei_state == CACHE_ENTRY_COMMITTED ) {
122                 LEI(e)->lei_state = CACHE_ENTRY_READY;
123
124                 /* free cache mutex */
125                 ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
126
127 #ifdef NEW_LOGGING
128                 LDAP_LOG( CACHE, DETAIL1, 
129                            "cache_return_entry_rw: return (%ld):%s, refcnt=%d\n",
130                            id, rw ? "w" : "r", refcnt );
131 #else
132                 Debug( LDAP_DEBUG_TRACE,
133                         "====> cache_return_entry_%s( %ld ): created (%d)\n",
134                         rw ? "w" : "r", id, refcnt );
135 #endif
136
137         } else if ( LEI(e)->lei_state == CACHE_ENTRY_DELETED ) {
138                 if( refcnt > 0 ) {
139                         /* free cache mutex */
140                         ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
141
142 #ifdef NEW_LOGGING
143                         LDAP_LOG( CACHE, DETAIL1, 
144                                    "cache_return_entry_rw: %ld, delete pending (%d).\n",
145                                    id, refcnt, 0 );
146 #else
147                         Debug( LDAP_DEBUG_TRACE,
148                                 "====> cache_return_entry_%s( %ld ): delete pending (%d)\n",
149                                 rw ? "w" : "r", id, refcnt );
150 #endif
151
152                 } else {
153                         cache_entry_private_destroy( e );
154                         if ( freeit ) {
155                                 entry_free( e );
156                         }
157
158                         /* free cache mutex */
159                         ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
160
161 #ifdef NEW_LOGGING
162                         LDAP_LOG( CACHE, DETAIL1,
163                                 "cache_return_entry_rw: (%ld): deleted (%d)\n", id, refcnt, 0 );
164 #else
165                         Debug( LDAP_DEBUG_TRACE,
166                                 "====> cache_return_entry_%s( %ld ): deleted (%d)\n",
167                                 rw ? "w" : "r", id, refcnt );
168 #endif
169                 }
170
171         } else {
172                 /* free cache mutex */
173                 ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
174
175 #ifdef NEW_LOGGING
176                 LDAP_LOG( CACHE, DETAIL1, 
177                            "cache_return_entry_rw: ID %ld:%s returned (%d)\n",
178                            id, rw ? "w": "r", refcnt );
179 #else
180                 Debug( LDAP_DEBUG_TRACE,
181                         "====> cache_return_entry_%s( %ld ): returned (%d)\n",
182                         rw ? "w" : "r", id, refcnt);
183 #endif
184         }
185 }
186
187 #define LRU_DELETE( cache, e ) do { \
188         if ( LEI(e)->lei_lruprev != NULL ) { \
189                 LEI(LEI(e)->lei_lruprev)->lei_lrunext = LEI(e)->lei_lrunext; \
190         } else { \
191                 (cache)->c_lruhead = LEI(e)->lei_lrunext; \
192         } \
193         if ( LEI(e)->lei_lrunext != NULL ) { \
194                 LEI(LEI(e)->lei_lrunext)->lei_lruprev = LEI(e)->lei_lruprev; \
195         } else { \
196                 (cache)->c_lrutail = LEI(e)->lei_lruprev; \
197         } \
198 } while(0)
199
200 #define LRU_ADD( cache, e ) do { \
201         LEI(e)->lei_lrunext = (cache)->c_lruhead; \
202         if ( LEI(e)->lei_lrunext != NULL ) { \
203                 LEI(LEI(e)->lei_lrunext)->lei_lruprev = (e); \
204         } \
205         (cache)->c_lruhead = (e); \
206         LEI(e)->lei_lruprev = NULL; \
207         if ( (cache)->c_lrutail == NULL ) { \
208                 (cache)->c_lrutail = (e); \
209         } \
210 } while(0)
211
212 /*
213  * cache_add_entry_rw - create and lock an entry in the cache
214  * returns:     0       entry has been created and locked
215  *              1       entry already existed
216  *              -1      something bad happened
217  */
218 int
219 cache_add_entry_rw(
220     Cache       *cache,
221     Entry               *e,
222         int             rw
223 )
224 {
225         int     i, rc;
226         Entry   *ee;
227
228 #ifdef NEW_LOGGING
229         LDAP_LOG( CACHE, ENTRY, 
230                    "cache_add_entry_rw: add (%s):%s to cache\n",
231                    e->e_dn, rw ? "w" : "r", 0 );
232 #endif
233         /* set cache mutex */
234         ldap_pvt_thread_mutex_lock( &cache->c_mutex );
235
236         assert( e->e_private == NULL );
237
238         if( cache_entry_private_init(e) != 0 ) {
239                 /* free cache mutex */
240                 ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
241
242 #ifdef NEW_LOGGING
243                 LDAP_LOG( CACHE, ERR, 
244                            "cache_add_entry_rw: add (%s):%ld private init failed!\n",
245                            e->e_dn, e->e_id, 0 );
246 #else
247                 Debug( LDAP_DEBUG_ANY,
248                         "====> cache_add_entry( %ld ): \"%s\": private init failed!\n",
249                     e->e_id, e->e_dn, 0 );
250 #endif
251
252                 return( -1 );
253         }
254
255         if ( avl_insert( &cache->c_dntree, (caddr_t) e,
256                          entry_dn_cmp, avl_dup_error ) != 0 )
257         {
258                 /* free cache mutex */
259                 ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
260
261 #ifdef NEW_LOGGING
262                 LDAP_LOG( CACHE, DETAIL1, 
263                         "cache_add_entry: (%s):%ld already in cache.\n", 
264                         e->e_dn, e->e_id, 0 );
265 #else
266                 Debug( LDAP_DEBUG_TRACE,
267                         "====> cache_add_entry( %ld ): \"%s\": already in dn cache\n",
268                     e->e_id, e->e_dn, 0 );
269 #endif
270
271                 cache_entry_private_destroy(e);
272
273                 return( 1 );
274         }
275
276         /* id tree */
277         if ( avl_insert( &cache->c_idtree, (caddr_t) e,
278                          entry_id_cmp, avl_dup_error ) != 0 )
279         {
280 #ifdef NEW_LOGGING
281                 LDAP_LOG( CACHE, DETAIL1, 
282                         "cache_add_entry: (%s):%ls already in cache.\n", 
283                         e->e_dn, e->e_id, 0 );
284 #else
285                 Debug( LDAP_DEBUG_ANY,
286                         "====> cache_add_entry( %ld ): \"%s\": already in id cache\n",
287                     e->e_id, e->e_dn, 0 );
288 #endif
289
290                 /* delete from dn tree inserted above */
291                 if ( avl_delete( &cache->c_dntree, (caddr_t) e,
292                                  entry_dn_cmp ) == NULL )
293                 {
294 #ifdef NEW_LOGGING
295                         LDAP_LOG( CACHE, INFO, 
296                                 "cache_add_entry: can't delete (%s) from cache.\n", 
297                                 e->e_dn, 0, 0 );
298 #else
299                         Debug( LDAP_DEBUG_ANY, "====> can't delete from dn cache\n",
300                             0, 0, 0 );
301 #endif
302                 }
303
304                 cache_entry_private_destroy(e);
305
306                 /* free cache mutex */
307                 ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
308                 return( -1 );
309         }
310
311         /* put the entry into 'CREATING' state */
312         /* will be marked after when entry is returned */
313         LEI(e)->lei_state = CACHE_ENTRY_CREATING;
314         LEI(e)->lei_refcnt = 1;
315
316         /* lru */
317         LRU_ADD( cache, e );
318         if ( ++cache->c_cursize > cache->c_maxsize ) {
319                 /*
320                  * find the lru entry not currently in use and delete it.
321                  * in case a lot of entries are in use, only look at the
322                  * first 10 on the tail of the list.
323                  */
324                 i = 0;
325                 while ( cache->c_lrutail != NULL &&
326                         LEI(cache->c_lrutail)->lei_refcnt != 0 &&
327                         i < 10 )
328                 {
329                         /* move this in-use entry to the front of the q */
330                         ee = cache->c_lrutail;
331                         LRU_DELETE( cache, ee );
332                         LRU_ADD( cache, ee );
333                         i++;
334                 }
335
336                 /*
337                  * found at least one to delete - try to get back under
338                  * the max cache size.
339                  */
340                 while ( cache->c_lrutail != NULL &&
341                         LEI(cache->c_lrutail)->lei_refcnt == 0 &&
342                         cache->c_cursize > cache->c_maxsize )
343                 {
344                         e = cache->c_lrutail;
345
346                         /* delete from cache and lru q */
347                         /* XXX do we need rc ? */
348                         rc = cache_delete_entry_internal( cache, e );
349                         cache_entry_private_destroy( e );
350                         entry_free( e );
351                 }
352         }
353
354         /* free cache mutex */
355         ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
356         return( 0 );
357 }
358
359 /*
360  * cache_update_entry - update a LOCKED entry which has been deleted.
361  * returns:     0       entry has been created and locked
362  *              1       entry already existed
363  *              -1      something bad happened
364  */
365 int
366 cache_update_entry(
367     Cache       *cache,
368     Entry               *e
369 )
370 {
371         int     i, rc;
372         Entry   *ee;
373
374         /* set cache mutex */
375         ldap_pvt_thread_mutex_lock( &cache->c_mutex );
376
377         assert( e->e_private );
378
379         if ( avl_insert( &cache->c_dntree, (caddr_t) e,
380                          entry_dn_cmp, avl_dup_error ) != 0 )
381         {
382 #ifdef NEW_LOGGING
383                 LDAP_LOG( CACHE, DETAIL1, 
384                            "cache_update_entry: (%s):%ld already in dn cache\n",
385                            e->e_dn, e->e_id, 0 );
386 #else
387                 Debug( LDAP_DEBUG_TRACE,
388                         "====> cache_update_entry( %ld ): \"%s\": already in dn cache\n",
389                     e->e_id, e->e_dn, 0 );
390 #endif
391
392                 /* free cache mutex */
393                 ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
394                 return( 1 );
395         }
396
397         /* id tree */
398         if ( avl_insert( &cache->c_idtree, (caddr_t) e,
399                          entry_id_cmp, avl_dup_error ) != 0 )
400         {
401 #ifdef NEW_LOGGING
402                 LDAP_LOG( CACHE, DETAIL1, 
403                            "cache_update_entry: (%s)%ld already in id cache\n",
404                            e->e_dn, e->e_id, 0 );
405 #else
406                 Debug( LDAP_DEBUG_ANY,
407                         "====> cache_update_entry( %ld ): \"%s\": already in id cache\n",
408                     e->e_id, e->e_dn, 0 );
409 #endif
410
411                 /* delete from dn tree inserted above */
412                 if ( avl_delete( &cache->c_dntree, (caddr_t) e,
413                                  entry_dn_cmp ) == NULL )
414                 {
415 #ifdef NEW_LOGGING
416                         LDAP_LOG( CACHE, INFO, 
417                                 "cache_update_entry: can't delete (%s)%ld from dn cache.\n",
418                                 e->e_dn, e->e_id, 0 );
419 #else
420                         Debug( LDAP_DEBUG_ANY, "====> can't delete from dn cache\n",
421                             0, 0, 0 );
422 #endif
423                 }
424
425                 /* free cache mutex */
426                 ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
427                 return( -1 );
428         }
429
430         /* put the entry into 'CREATING' state */
431         /* will be marked after when entry is returned */
432         LEI(e)->lei_state = CACHE_ENTRY_CREATING;
433
434         /* lru */
435         LRU_ADD( cache, e );
436         if ( ++cache->c_cursize > cache->c_maxsize ) {
437                 /*
438                  * find the lru entry not currently in use and delete it.
439                  * in case a lot of entries are in use, only look at the
440                  * first 10 on the tail of the list.
441                  */
442                 i = 0;
443                 while ( cache->c_lrutail != NULL &&
444                         LEI(cache->c_lrutail)->lei_refcnt != 0 &&
445                         i < 10 )
446                 {
447                         /* move this in-use entry to the front of the q */
448                         ee = cache->c_lrutail;
449                         LRU_DELETE( cache, ee );
450                         LRU_ADD( cache, ee );
451                         i++;
452                 }
453
454                 /*
455                  * found at least one to delete - try to get back under
456                  * the max cache size.
457                  */
458                 while ( cache->c_lrutail != NULL &&
459                         LEI(cache->c_lrutail)->lei_refcnt == 0 &&
460                         cache->c_cursize > cache->c_maxsize )
461                 {
462                         e = cache->c_lrutail;
463
464                         /* delete from cache and lru q */
465                         /* XXX do we need rc ? */
466                         rc = cache_delete_entry_internal( cache, e );
467                         cache_entry_private_destroy( e );
468                         entry_free( e );
469                 }
470         }
471
472         /* free cache mutex */
473         ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
474         return( 0 );
475 }
476
477 ID
478 cache_find_entry_ndn2id(
479         Backend         *be,
480     Cache       *cache,
481     struct berval       *ndn
482 )
483 {
484         Entry           e, *ep;
485         ID                      id;
486         int count = 0;
487
488         /* this function is always called with normalized DN */
489         e.e_nname = *ndn;
490
491 try_again:
492         /* set cache mutex */
493         ldap_pvt_thread_mutex_lock( &cache->c_mutex );
494
495         if ( (ep = (Entry *) avl_find( cache->c_dntree, (caddr_t) &e,
496                                        entry_dn_cmp )) != NULL )
497         {
498                 int state;
499                 count++;
500
501                 /*
502                  * ep now points to an unlocked entry
503                  * we do not need to lock the entry if we only
504                  * check the state, refcnt, LRU, and id.
505                  */
506                 assert( ep->e_private );
507
508                 /* save id */
509                 id = ep->e_id;
510                 state = LEI(ep)->lei_state;
511
512                 /*
513                  * entry is deleted or not fully created yet
514                  */
515                 if ( state != CACHE_ENTRY_READY ) {
516                         assert(state != CACHE_ENTRY_UNDEFINED);
517
518                         /* free cache mutex */
519                         ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
520
521 #ifdef NEW_LOGGING
522                         LDAP_LOG( CACHE, INFO, 
523                                    "cache_find_entry_ndn2id: (%s) %ld not ready: %d\n",
524                                    ndn->bv_val, id, state );
525 #else
526                         Debug(LDAP_DEBUG_TRACE,
527                                 "====> cache_find_entry_ndn2id(\"%s\"): %ld (not ready) %d\n",
528                                 ndn->bv_val, id, state);
529 #endif
530
531                         ldap_pvt_thread_yield();
532                         goto try_again;
533                 }
534
535                 /* lru */
536                 LRU_DELETE( cache, ep );
537                 LRU_ADD( cache, ep );
538                 
539                 /* free cache mutex */
540                 ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
541
542 #ifdef NEW_LOGGING
543                 LDAP_LOG( CACHE, DETAIL1, 
544                            "cache_find_entry_ndn2id: (%s): %ld %d tries\n",
545                            ndn->bv_val, id, count );
546 #else
547                 Debug(LDAP_DEBUG_TRACE,
548                         "====> cache_find_entry_ndn2id(\"%s\"): %ld (%d tries)\n",
549                         ndn->bv_val, id, count);
550 #endif
551
552         } else {
553                 /* free cache mutex */
554                 ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
555                 id = NOID;
556         }
557
558         return( id );
559 }
560
561 /*
562  * cache_find_entry_id - find an entry in the cache, given id
563  */
564
565 Entry *
566 cache_find_entry_id(
567         Cache   *cache,
568         ID                              id,
569         int                             rw
570 )
571 {
572         Entry   e;
573         Entry   *ep;
574         int     count = 0;
575
576         e.e_id = id;
577
578 try_again:
579         /* set cache mutex */
580         ldap_pvt_thread_mutex_lock( &cache->c_mutex );
581
582         if ( (ep = (Entry *) avl_find( cache->c_idtree, (caddr_t) &e,
583                                        entry_id_cmp )) != NULL )
584         {
585                 int state;
586                 ID      ep_id;
587
588                 count++;
589
590                 assert( ep->e_private );
591
592                 ep_id = ep->e_id; 
593                 state = LEI(ep)->lei_state;
594
595                 /*
596                  * entry is deleted or not fully created yet
597                  */
598                 if ( state != CACHE_ENTRY_READY ) {
599                         assert(state != CACHE_ENTRY_UNDEFINED);
600
601                         /* free cache mutex */
602                         ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
603
604 #ifdef NEW_LOGGING
605                         LDAP_LOG( CACHE, INFO, 
606                                    "cache_find_entry_id: (%ld)->%ld not ready (%d).\n",
607                                    id, ep_id, state );
608                                    
609 #else
610                         Debug(LDAP_DEBUG_TRACE,
611                                 "====> cache_find_entry_id( %ld ): %ld (not ready) %d\n",
612                                 id, ep_id, state);
613 #endif
614
615                         ldap_pvt_thread_yield();
616                         goto try_again;
617                 }
618
619                 /* lru */
620                 LRU_DELETE( cache, ep );
621                 LRU_ADD( cache, ep );
622                 
623                 LEI(ep)->lei_refcnt++;
624
625                 /* free cache mutex */
626                 ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
627
628 #ifdef NEW_LOGGING
629                 LDAP_LOG( CACHE, DETAIL1, 
630                            "cache_find_entry_id: %ld -> %s  found %d tries.\n",
631                            ep_id, ep->e_dn, count );
632 #else
633                 Debug(LDAP_DEBUG_TRACE,
634                         "====> cache_find_entry_id( %ld ) \"%s\" (found) (%d tries)\n",
635                         ep_id, ep->e_dn, count);
636 #endif
637
638                 return( ep );
639         }
640
641         /* free cache mutex */
642         ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
643
644         return( NULL );
645 }
646
647 /*
648  * cache_delete_entry - delete the entry e from the cache.  the caller
649  * should have obtained e (increasing its ref count) via a call to one
650  * of the cache_find_* routines.  the caller should *not* call the
651  * cache_return_entry() routine prior to calling cache_delete_entry().
652  * it performs this function.
653  *
654  * returns:     0       e was deleted ok
655  *              1       e was not in the cache
656  *              -1      something bad happened
657  */
658 int
659 cache_delete_entry(
660     Cache       *cache,
661     Entry               *e
662 )
663 {
664         int     rc;
665
666         /* set cache mutex */
667         ldap_pvt_thread_mutex_lock( &cache->c_mutex );
668
669         assert( e->e_private );
670
671 #ifdef NEW_LOGGING
672         LDAP_LOG( CACHE, ENTRY, 
673                 "cache_delete_entry: delete %ld.\n", e->e_id, 0, 0 );
674 #else
675         Debug( LDAP_DEBUG_TRACE, "====> cache_delete_entry( %ld )\n",
676                 e->e_id, 0, 0 );
677 #endif
678
679         rc = cache_delete_entry_internal( cache, e );
680
681         /* free cache mutex */
682         ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
683         return( rc );
684 }
685
686 static int
687 cache_delete_entry_internal(
688     Cache       *cache,
689     Entry               *e
690 )
691 {
692         int rc = 0;     /* return code */
693
694         /* dn tree */
695         if ( avl_delete( &cache->c_dntree, (caddr_t) e, entry_dn_cmp ) == NULL )
696         {
697                 rc = -1;
698         }
699
700         /* id tree */
701         if ( avl_delete( &cache->c_idtree, (caddr_t) e, entry_id_cmp ) == NULL )
702         {
703                 rc = -1;
704         }
705
706         if (rc != 0) {
707                 return rc;
708         }
709
710         /* lru */
711         LRU_DELETE( cache, e );
712         cache->c_cursize--;
713
714         /*
715          * flag entry to be freed later by a call to cache_return_entry()
716          */
717         LEI(e)->lei_state = CACHE_ENTRY_DELETED;
718
719         return( 0 );
720 }
721
722 void
723 cache_release_all( Cache *cache )
724 {
725         Entry *e;
726         int rc;
727
728         /* set cache mutex */
729         ldap_pvt_thread_mutex_lock( &cache->c_mutex );
730
731 #ifdef NEW_LOGGING
732         LDAP_LOG( CACHE, ENTRY, "cache_release_all: enter\n" , 0, 0, 0);
733 #else
734         Debug( LDAP_DEBUG_TRACE, "====> cache_release_all\n", 0, 0, 0 );
735 #endif
736
737
738         while ( (e = cache->c_lrutail) != NULL && LEI(e)->lei_refcnt == 0 ) {
739                 /* delete from cache and lru q */
740                 /* XXX do we need rc ? */
741                 rc = cache_delete_entry_internal( cache, e );
742                 cache_entry_private_destroy( e );
743                 entry_free( e );
744         }
745
746         if ( cache->c_cursize ) {
747 #ifdef NEW_LOGGING
748                 LDAP_LOG( CACHE, INFO,
749                          "cache_release_all: Entry cache could not be emptied.\n", 0, 0, 0);
750 #else
751                 Debug( LDAP_DEBUG_TRACE, "Entry-cache could not be emptied\n", 0, 0, 0 );
752 #endif
753         }
754
755         /* free cache mutex */
756         ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
757 }
758
759 #ifdef LDAP_DEBUG
760 static void
761 lru_print( Cache *cache )
762 {
763         Entry   *e;
764
765         fprintf( stderr, "LRU queue (head to tail):\n" );
766         for ( e = cache->c_lruhead; e != NULL; e = LEI(e)->lei_lrunext ) {
767                 fprintf( stderr, "\tdn \"%20s\" id %ld refcnt %d\n",
768                         e->e_dn, e->e_id, LEI(e)->lei_refcnt );
769         }
770         fprintf( stderr, "LRU queue (tail to head):\n" );
771         for ( e = cache->c_lrutail; e != NULL; e = LEI(e)->lei_lruprev ) {
772                 fprintf( stderr, "\tdn \"%20s\" id %ld refcnt %d\n",
773                         e->e_dn, e->e_id, LEI(e)->lei_refcnt );
774         }
775 }
776 #endif