X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fback-monitor%2Fcache.c;h=fa4d72ab07f16759b71c1ccf18b2b7e84b1a1e21;hb=cb24efd2879f0f025114df8c9212d48bd0c32517;hp=4f4ad05b2b49281ce4cee0e6c9cfce9cf9e2e898;hpb=70884b88608ec83c4bed4ecc37a5f4256643816b;p=openldap diff --git a/servers/slapd/back-monitor/cache.c b/servers/slapd/back-monitor/cache.c index 4f4ad05b2b..fa4d72ab07 100644 --- a/servers/slapd/back-monitor/cache.c +++ b/servers/slapd/back-monitor/cache.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2001-2004 The OpenLDAP Foundation. + * Copyright 2001-2011 The OpenLDAP Foundation. * Portions Copyright 2001-2003 Pierangelo Masarati. * All rights reserved. * @@ -44,9 +44,8 @@ typedef struct monitor_cache_t { */ int monitor_cache_cmp( - const void *c1, - const void *c2 -) + const void *c1, + const void *c2 ) { monitor_cache_t *cc1 = ( monitor_cache_t * )c1; monitor_cache_t *cc2 = ( monitor_cache_t * )c2; @@ -62,9 +61,8 @@ monitor_cache_cmp( */ int monitor_cache_dup( - void *c1, - void *c2 -) + void *c1, + void *c2 ) { monitor_cache_t *cc1 = ( monitor_cache_t * )c1; monitor_cache_t *cc2 = ( monitor_cache_t * )c2; @@ -80,9 +78,8 @@ monitor_cache_dup( */ int monitor_cache_add( - monitor_info_t *mi, - Entry *e -) + monitor_info_t *mi, + Entry *e ) { monitor_cache_t *mc; monitor_entry_t *mp; @@ -92,7 +89,6 @@ monitor_cache_add( assert( e != NULL ); mp = ( monitor_entry_t *)e->e_private; - ldap_pvt_thread_mutex_init( &mp->mp_mutex ); mc = ( monitor_cache_t * )ch_malloc( sizeof( monitor_cache_t ) ); mc->mc_ndn = e->e_nname; @@ -110,18 +106,33 @@ monitor_cache_add( */ int monitor_cache_lock( - Entry *e -) + Entry *e ) { - monitor_entry_t *mp; + monitor_entry_t *mp; - assert( e != NULL ); - assert( e->e_private != NULL ); + assert( e != NULL ); + assert( e->e_private != NULL ); - mp = ( monitor_entry_t * )e->e_private; - ldap_pvt_thread_mutex_lock( &mp->mp_mutex ); + mp = ( monitor_entry_t * )e->e_private; + ldap_pvt_thread_mutex_lock( &mp->mp_mutex ); - return( 0 ); + return( 0 ); +} + +/* + * tries to lock the entry (no r/w) + */ +int +monitor_cache_trylock( + Entry *e ) +{ + monitor_entry_t *mp; + + assert( e != NULL ); + assert( e->e_private != NULL ); + + mp = ( monitor_entry_t * )e->e_private; + return ldap_pvt_thread_mutex_trylock( &mp->mp_mutex ); } /* @@ -130,10 +141,9 @@ monitor_cache_lock( */ int monitor_cache_get( - monitor_info_t *mi, - struct berval *ndn, - Entry **ep -) + monitor_info_t *mi, + struct berval *ndn, + Entry **ep ) { monitor_cache_t tmp_mc, *mc; @@ -141,24 +151,133 @@ monitor_cache_get( assert( ndn != NULL ); assert( ep != NULL ); + *ep = NULL; + tmp_mc.mc_ndn = *ndn; +retry:; ldap_pvt_thread_mutex_lock( &mi->mi_cache_mutex ); mc = ( monitor_cache_t * )avl_find( mi->mi_cache, ( caddr_t )&tmp_mc, monitor_cache_cmp ); if ( mc != NULL ) { /* entry is returned with mutex locked */ - monitor_cache_lock( mc->mc_e ); - ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex ); + if ( monitor_cache_trylock( mc->mc_e ) ) { + ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex ); + ldap_pvt_thread_yield(); + goto retry; + } *ep = mc->mc_e; - - return( 0 ); } - + ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex ); + + return ( *ep == NULL ? -1 : 0 ); +} + +/* + * gets an entry from the cache based on the normalized dn + * with mutex locked + */ +int +monitor_cache_remove( + monitor_info_t *mi, + struct berval *ndn, + Entry **ep ) +{ + monitor_cache_t tmp_mc, *mc; + struct berval pndn; + + assert( mi != NULL ); + assert( ndn != NULL ); + assert( ep != NULL ); + *ep = NULL; - return( -1 ); + dnParent( ndn, &pndn ); + +retry:; + ldap_pvt_thread_mutex_lock( &mi->mi_cache_mutex ); + + tmp_mc.mc_ndn = *ndn; + mc = ( monitor_cache_t * )avl_find( mi->mi_cache, + ( caddr_t )&tmp_mc, monitor_cache_cmp ); + + if ( mc != NULL ) { + monitor_cache_t *pmc; + + if ( monitor_cache_trylock( mc->mc_e ) ) { + ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex ); + goto retry; + } + + tmp_mc.mc_ndn = pndn; + pmc = ( monitor_cache_t * )avl_find( mi->mi_cache, + ( caddr_t )&tmp_mc, monitor_cache_cmp ); + if ( pmc != NULL ) { + monitor_entry_t *mp = (monitor_entry_t *)mc->mc_e->e_private, + *pmp = (monitor_entry_t *)pmc->mc_e->e_private; + Entry **entryp; + + if ( monitor_cache_trylock( pmc->mc_e ) ) { + monitor_cache_release( mi, mc->mc_e ); + ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex ); + goto retry; + } + + for ( entryp = &pmp->mp_children; *entryp != NULL; ) { + monitor_entry_t *next = (monitor_entry_t *)(*entryp)->e_private; + if ( next == mp ) { + *entryp = next->mp_next; + entryp = NULL; + break; + } + + entryp = &next->mp_next; + } + + if ( entryp != NULL ) { + Debug( LDAP_DEBUG_ANY, + "monitor_cache_remove(\"%s\"): " + "not in parent's list\n", + ndn->bv_val, 0, 0 ); + } + + /* either succeeded, and the entry is no longer + * in its parent's list, or failed, and the + * entry is neither mucked with nor returned */ + monitor_cache_release( mi, pmc->mc_e ); + + if ( entryp == NULL ) { + monitor_cache_t *tmpmc; + + tmp_mc.mc_ndn = *ndn; + tmpmc = avl_delete( &mi->mi_cache, + ( caddr_t )&tmp_mc, monitor_cache_cmp ); + assert( tmpmc == mc ); + + *ep = mc->mc_e; + ch_free( mc ); + mc = NULL; + + /* NOTE: we destroy the mutex, but otherwise + * leave the private data around; specifically, + * callbacks need be freed by someone else */ + + ldap_pvt_thread_mutex_destroy( &mp->mp_mutex ); + mp->mp_next = NULL; + mp->mp_children = NULL; + } + + } + + if ( mc ) { + monitor_cache_release( mi, mc->mc_e ); + } + } + + ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex ); + + return ( *ep == NULL ? -1 : 0 ); } /* @@ -169,11 +288,11 @@ monitor_cache_get( */ int monitor_cache_dn2entry( - Operation *op, - struct berval *ndn, - Entry **ep, - Entry **matched -) + Operation *op, + SlapReply *rs, + struct berval *ndn, + Entry **ep, + Entry **matched ) { monitor_info_t *mi = (monitor_info_t *)op->o_bd->be_private; int rc; @@ -188,6 +307,10 @@ monitor_cache_dn2entry( *matched = NULL; + if ( !dnIsSuffix( ndn, &op->o_bd->be_nsuffix[ 0 ] ) ) { + return( -1 ); + } + rc = monitor_cache_get( mi, ndn, ep ); if ( !rc && *ep != NULL ) { return( 0 ); @@ -201,7 +324,7 @@ monitor_cache_dn2entry( dnParent( ndn, &p_ndn ); } - rc = monitor_cache_dn2entry( op, &p_ndn, &e_parent, matched ); + rc = monitor_cache_dn2entry( op, rs, &p_ndn, &e_parent, matched ); if ( rc || e_parent == NULL ) { return( -1 ); } @@ -210,11 +333,13 @@ monitor_cache_dn2entry( rc = -1; if ( mp->mp_flags & MONITOR_F_VOLATILE_CH ) { /* parent entry generates volatile children */ - rc = monitor_entry_create( op, ndn, e_parent, ep ); + rc = monitor_entry_create( op, rs, ndn, e_parent, ep ); } if ( !rc ) { + monitor_cache_lock( *ep ); monitor_cache_release( mi, e_parent ); + } else { *matched = e_parent; } @@ -229,8 +354,7 @@ monitor_cache_dn2entry( int monitor_cache_release( monitor_info_t *mi, - Entry *e -) + Entry *e ) { monitor_entry_t *mp; @@ -249,7 +373,9 @@ monitor_cache_release( mc = avl_delete( &mi->mi_cache, ( caddr_t )&tmp_mc, monitor_cache_cmp ); ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex ); - ch_free( mc ); + if ( mc != NULL ) { + ch_free( mc ); + } ldap_pvt_thread_mutex_unlock( &mp->mp_mutex ); ldap_pvt_thread_mutex_destroy( &mp->mp_mutex ); @@ -265,3 +391,59 @@ monitor_cache_release( return( 0 ); } +static void +monitor_entry_destroy( void *v_mc ) +{ + monitor_cache_t *mc = (monitor_cache_t *)v_mc; + + if ( mc->mc_e != NULL ) { + monitor_entry_t *mp; + + assert( mc->mc_e->e_private != NULL ); + + mp = ( monitor_entry_t * )mc->mc_e->e_private; + + if ( mp->mp_cb ) { + monitor_callback_t *cb; + + for ( cb = mp->mp_cb; cb != NULL; ) { + monitor_callback_t *next = cb->mc_next; + + if ( cb->mc_free ) { + (void)cb->mc_free( mc->mc_e, &cb->mc_private ); + } + ch_free( mp->mp_cb ); + + cb = next; + } + } + + ldap_pvt_thread_mutex_destroy( &mp->mp_mutex ); + + ch_free( mp ); + mc->mc_e->e_private = NULL; + entry_free( mc->mc_e ); + } + + ch_free( mc ); +} + +int +monitor_cache_destroy( + monitor_info_t *mi ) +{ + if ( mi->mi_cache ) { + avl_free( mi->mi_cache, monitor_entry_destroy ); + } + + return 0; +} + +int monitor_back_release( + Operation *op, + Entry *e, + int rw ) +{ + monitor_info_t *mi = ( monitor_info_t * )op->o_bd->be_private; + return monitor_cache_release( mi, e ); +}