1 /* cache.c - routines to maintain an in-core cache of entries */
2 /* $OpenLDAP: pkg/ldap/servers/slapd/back-monitor/cache.c,v 1.27.2.5 2008/05/01 21:25:42 quanah Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2001-2008 The OpenLDAP Foundation.
6 * Portions Copyright 2001-2003 Pierangelo Masarati.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
13 * A copy of this license is available in file LICENSE in the
14 * top-level directory of the distribution or, alternatively, at
15 * <http://www.OpenLDAP.org/license.html>.
18 * This work was initially developed by Pierangelo Masarati for inclusion
19 * in OpenLDAP Software.
25 #include "ac/string.h"
29 #include "back-monitor.h"
32 * The cache maps DNs to Entries.
33 * Each entry, on turn, holds the list of its children in the e_private field.
34 * This is used by search operation to perform onelevel and subtree candidate
37 typedef struct monitor_cache_t
{
43 * compares entries based on the dn
50 monitor_cache_t
*cc1
= ( monitor_cache_t
* )c1
;
51 monitor_cache_t
*cc2
= ( monitor_cache_t
* )c2
;
54 * case sensitive, because the dn MUST be normalized
56 return ber_bvcmp( &cc1
->mc_ndn
, &cc2
->mc_ndn
);
60 * checks for duplicate entries
67 monitor_cache_t
*cc1
= ( monitor_cache_t
* )c1
;
68 monitor_cache_t
*cc2
= ( monitor_cache_t
* )c2
;
71 * case sensitive, because the dn MUST be normalized
73 return ber_bvcmp( &cc1
->mc_ndn
, &cc2
->mc_ndn
) == 0 ? -1 : 0;
77 * adds an entry to the cache and inits the mutex
91 mp
= ( monitor_entry_t
*)e
->e_private
;
93 mc
= ( monitor_cache_t
* )ch_malloc( sizeof( monitor_cache_t
) );
94 mc
->mc_ndn
= e
->e_nname
;
96 ldap_pvt_thread_mutex_lock( &mi
->mi_cache_mutex
);
97 rc
= avl_insert( &mi
->mi_cache
, ( caddr_t
)mc
,
98 monitor_cache_cmp
, monitor_cache_dup
);
99 ldap_pvt_thread_mutex_unlock( &mi
->mi_cache_mutex
);
105 * locks the entry (no r/w)
114 assert( e
->e_private
!= NULL
);
116 mp
= ( monitor_entry_t
* )e
->e_private
;
117 ldap_pvt_thread_mutex_lock( &mp
->mp_mutex
);
123 * tries to lock the entry (no r/w)
126 monitor_cache_trylock(
132 assert( e
->e_private
!= NULL
);
134 mp
= ( monitor_entry_t
* )e
->e_private
;
135 return ldap_pvt_thread_mutex_trylock( &mp
->mp_mutex
);
139 * gets an entry from the cache based on the normalized dn
148 monitor_cache_t tmp_mc
, *mc
;
150 assert( mi
!= NULL
);
151 assert( ndn
!= NULL
);
152 assert( ep
!= NULL
);
156 tmp_mc
.mc_ndn
= *ndn
;
158 ldap_pvt_thread_mutex_lock( &mi
->mi_cache_mutex
);
159 mc
= ( monitor_cache_t
* )avl_find( mi
->mi_cache
,
160 ( caddr_t
)&tmp_mc
, monitor_cache_cmp
);
163 /* entry is returned with mutex locked */
164 if ( monitor_cache_trylock( mc
->mc_e
) ) {
165 ldap_pvt_thread_mutex_unlock( &mi
->mi_cache_mutex
);
166 ldap_pvt_thread_yield();
172 ldap_pvt_thread_mutex_unlock( &mi
->mi_cache_mutex
);
174 return ( *ep
== NULL
? -1 : 0 );
178 * gets an entry from the cache based on the normalized dn
182 monitor_cache_remove(
187 monitor_cache_t tmp_mc
, *mc
;
190 assert( mi
!= NULL
);
191 assert( ndn
!= NULL
);
192 assert( ep
!= NULL
);
196 dnParent( ndn
, &pndn
);
199 ldap_pvt_thread_mutex_lock( &mi
->mi_cache_mutex
);
201 tmp_mc
.mc_ndn
= *ndn
;
202 mc
= ( monitor_cache_t
* )avl_find( mi
->mi_cache
,
203 ( caddr_t
)&tmp_mc
, monitor_cache_cmp
);
206 monitor_cache_t
*pmc
;
208 if ( monitor_cache_trylock( mc
->mc_e
) ) {
209 ldap_pvt_thread_mutex_unlock( &mi
->mi_cache_mutex
);
213 tmp_mc
.mc_ndn
= pndn
;
214 pmc
= ( monitor_cache_t
* )avl_find( mi
->mi_cache
,
215 ( caddr_t
)&tmp_mc
, monitor_cache_cmp
);
217 monitor_entry_t
*mp
= (monitor_entry_t
*)mc
->mc_e
->e_private
,
218 *pmp
= (monitor_entry_t
*)pmc
->mc_e
->e_private
;
221 if ( monitor_cache_trylock( pmc
->mc_e
) ) {
222 monitor_cache_release( mi
, mc
->mc_e
);
223 ldap_pvt_thread_mutex_unlock( &mi
->mi_cache_mutex
);
227 for ( entryp
= &pmp
->mp_children
; *entryp
!= NULL
; ) {
228 monitor_entry_t
*next
= (monitor_entry_t
*)(*entryp
)->e_private
;
230 *entryp
= next
->mp_next
;
235 entryp
= &next
->mp_next
;
238 if ( entryp
!= NULL
) {
239 Debug( LDAP_DEBUG_ANY
,
240 "monitor_cache_remove(\"%s\"): "
241 "not in parent's list\n",
245 /* either succeeded, and the entry is no longer
246 * in its parent's list, or failed, and the
247 * entry is neither mucked with nor returned */
248 monitor_cache_release( mi
, pmc
->mc_e
);
250 if ( entryp
== NULL
) {
251 monitor_cache_t
*tmpmc
;
253 tmp_mc
.mc_ndn
= *ndn
;
254 tmpmc
= avl_delete( &mi
->mi_cache
,
255 ( caddr_t
)&tmp_mc
, monitor_cache_cmp
);
256 assert( tmpmc
== mc
);
262 /* NOTE: we destroy the mutex, but otherwise
263 * leave the private data around; specifically,
264 * callbacks need be freed by someone else */
266 ldap_pvt_thread_mutex_destroy( &mp
->mp_mutex
);
268 mp
->mp_children
= NULL
;
274 monitor_cache_release( mi
, mc
->mc_e
);
278 ldap_pvt_thread_mutex_unlock( &mi
->mi_cache_mutex
);
280 return ( *ep
== NULL
? -1 : 0 );
284 * If the entry exists in cache, it is returned in locked status;
285 * otherwise, if the parent exists, if it may generate volatile
286 * descendants an attempt to generate the required entry is
287 * performed and, if successful, the entry is returned
290 monitor_cache_dn2entry(
297 monitor_info_t
*mi
= (monitor_info_t
*)op
->o_bd
->be_private
;
299 struct berval p_ndn
= BER_BVNULL
;
303 assert( mi
!= NULL
);
304 assert( ndn
!= NULL
);
305 assert( ep
!= NULL
);
306 assert( matched
!= NULL
);
310 if ( !dnIsSuffix( ndn
, &op
->o_bd
->be_nsuffix
[ 0 ] ) ) {
314 rc
= monitor_cache_get( mi
, ndn
, ep
);
315 if ( !rc
&& *ep
!= NULL
) {
319 /* try with parent/ancestors */
320 if ( BER_BVISNULL( ndn
) ) {
321 BER_BVSTR( &p_ndn
, "" );
324 dnParent( ndn
, &p_ndn
);
327 rc
= monitor_cache_dn2entry( op
, rs
, &p_ndn
, &e_parent
, matched
);
328 if ( rc
|| e_parent
== NULL
) {
332 mp
= ( monitor_entry_t
* )e_parent
->e_private
;
334 if ( mp
->mp_flags
& MONITOR_F_VOLATILE_CH
) {
335 /* parent entry generates volatile children */
336 rc
= monitor_entry_create( op
, rs
, ndn
, e_parent
, ep
);
340 monitor_cache_lock( *ep
);
341 monitor_cache_release( mi
, e_parent
);
351 * releases the lock of the entry; if it is marked as volatile, it is
355 monitor_cache_release(
361 assert( mi
!= NULL
);
363 assert( e
->e_private
!= NULL
);
365 mp
= ( monitor_entry_t
* )e
->e_private
;
367 if ( mp
->mp_flags
& MONITOR_F_VOLATILE
) {
368 monitor_cache_t
*mc
, tmp_mc
;
370 /* volatile entries do not return to cache */
371 ldap_pvt_thread_mutex_lock( &mi
->mi_cache_mutex
);
372 tmp_mc
.mc_ndn
= e
->e_nname
;
373 mc
= avl_delete( &mi
->mi_cache
,
374 ( caddr_t
)&tmp_mc
, monitor_cache_cmp
);
375 ldap_pvt_thread_mutex_unlock( &mi
->mi_cache_mutex
);
380 ldap_pvt_thread_mutex_unlock( &mp
->mp_mutex
);
381 ldap_pvt_thread_mutex_destroy( &mp
->mp_mutex
);
389 ldap_pvt_thread_mutex_unlock( &mp
->mp_mutex
);
395 monitor_entry_destroy( void *v_mc
)
397 monitor_cache_t
*mc
= (monitor_cache_t
*)v_mc
;
399 if ( mc
->mc_e
!= NULL
) {
402 assert( mc
->mc_e
->e_private
!= NULL
);
404 mp
= ( monitor_entry_t
* )mc
->mc_e
->e_private
;
407 monitor_callback_t
*cb
;
409 for ( cb
= mp
->mp_cb
; cb
!= NULL
; ) {
410 monitor_callback_t
*next
= cb
->mc_next
;
413 (void)cb
->mc_free( mc
->mc_e
, &cb
->mc_private
);
415 ch_free( mp
->mp_cb
);
421 ldap_pvt_thread_mutex_destroy( &mp
->mp_mutex
);
424 mc
->mc_e
->e_private
= NULL
;
425 entry_free( mc
->mc_e
);
432 monitor_cache_destroy(
435 if ( mi
->mi_cache
) {
436 avl_free( mi
->mi_cache
, monitor_entry_destroy
);