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