From: Pierangelo Masarati Date: Wed, 6 Sep 2006 12:06:42 +0000 (+0000) Subject: implement support for unregistering registered stuff X-Git-Tag: OPENLDAP_REL_ENG_2_3_MP~199 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=127ac65c447b8d28ba3cd75e1b8cee28006d5472;p=openldap implement support for unregistering registered stuff --- diff --git a/servers/slapd/back-monitor/cache.c b/servers/slapd/back-monitor/cache.c index 89bfe044b4..3639dd11a6 100644 --- a/servers/slapd/back-monitor/cache.c +++ b/servers/slapd/back-monitor/cache.c @@ -119,6 +119,22 @@ monitor_cache_lock( 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 ); +} + /* * gets an entry from the cache based on the normalized dn * with mutex locked @@ -153,6 +169,109 @@ monitor_cache_get( 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; + + 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; + } + + } + monitor_cache_release( mi, mc->mc_e ); + } + + ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex ); + + return ( *ep == NULL ? -1 : 0 ); +} + /* * If the entry exists in cache, it is returned in locked status; * otherwise, if the parent exists, if it may generate volatile @@ -277,11 +396,18 @@ monitor_entry_destroy( void *v_mc ) mp = ( monitor_entry_t * )mc->mc_e->e_private; if ( mp->mp_cb ) { - if ( mp->mp_cb->mc_free ) { - mp->mp_cb->mc_free( mc->mc_e, - mp->mp_cb->mc_private ); + monitor_callback_t *cb; + + for ( cb = mp->mp_cb; cb != NULL; ) { + monitor_callback_t *next = cb->mc_next; + + if ( cb->mc_free ) { + cb->mc_free( mc->mc_e, cb->mc_private ); + } + ch_free( mp->mp_cb ); + + cb = next; } - ch_free( mp->mp_cb ); } ldap_pvt_thread_mutex_destroy( &mp->mp_mutex ); diff --git a/servers/slapd/back-monitor/database.c b/servers/slapd/back-monitor/database.c index 5d080f60fd..318b242d01 100644 --- a/servers/slapd/back-monitor/database.c +++ b/servers/slapd/back-monitor/database.c @@ -33,14 +33,6 @@ static int monitor_back_add_plugin( monitor_info_t *mi, Backend *be, Entry *e ); #endif /* defined(LDAP_SLAPI) */ -#if 0 /* moved to back-bdb/monitor.c */ -#if defined(SLAPD_BDB) -#include "../back-bdb/back-bdb.h" -#endif /* defined(SLAPD_BDB) */ -#if defined(SLAPD_HDB) -#include "../back-hdb/back-bdb.h" -#endif /* defined(SLAPD_HDB) */ -#endif #if defined(SLAPD_LDAP) #include "../back-ldap/back-ldap.h" #endif /* defined(SLAPD_LDAP) */ @@ -293,54 +285,6 @@ monitor_subsys_database_init( if ( 0 ) { assert( 0 ); -#if 0 /* moved into back-bdb/monitor.c */ -#if defined(SLAPD_BDB) || defined(SLAPD_HDB) - } else if ( strcmp( bi->bi_type, "bdb" ) == 0 - || strcmp( bi->bi_type, "hdb" ) == 0 ) - { - struct berval bv; - ber_len_t pathlen = 0, len = 0; - char path[ PATH_MAX ] = { '\0' }; - struct bdb_info *bdb = (struct bdb_info *) be->be_private; - char *fname = bdb->bi_dbenv_home; - - len = strlen( fname ); - if ( fname[ 0 ] != '/' ) { - /* get full path name */ - getcwd( path, sizeof( path ) ); - pathlen = strlen( path ); - - if ( fname[ 0 ] == '.' && fname[ 1 ] == '/' ) { - fname += 2; - len -= 2; - } - } - - bv.bv_len = STRLENOF( "file://" ) + pathlen - + STRLENOF( "/" ) + len; - bv.bv_val = ch_malloc( bv.bv_len + STRLENOF( "/" ) + 1 ); - AC_MEMCPY( bv.bv_val, "file://", STRLENOF( "file://" ) ); - if ( pathlen ) { - AC_MEMCPY( &bv.bv_val[ STRLENOF( "file://" ) ], - path, pathlen ); - bv.bv_val[ STRLENOF( "file://" ) + pathlen ] = '/'; - pathlen++; - } - AC_MEMCPY( &bv.bv_val[ STRLENOF( "file://" ) + pathlen ], - fname, len ); - if ( bv.bv_val[ bv.bv_len - 1 ] != '/' ) { - bv.bv_val[ bv.bv_len ] = '/'; - bv.bv_len++; - } - bv.bv_val[ bv.bv_len ] = '\0'; - - attr_merge_normalize_one( e, slap_schema.si_ad_labeledURI, - &bv, NULL ); - - ch_free( bv.bv_val ); - -#endif /* defined(SLAPD_BDB) || defined(SLAPD_HDB) */ -#endif #if defined(SLAPD_LDAP) } else if ( strcmp( bi->bi_type, "ldap" ) == 0 ) { ldapinfo_t *li = (ldapinfo_t *)be->be_private; diff --git a/servers/slapd/back-monitor/init.c b/servers/slapd/back-monitor/init.c index 3a3d4b543a..26d7d5edf4 100644 --- a/servers/slapd/back-monitor/init.c +++ b/servers/slapd/back-monitor/init.c @@ -437,7 +437,7 @@ monitor_back_register_entry_parent( "monitor_back_register_entry_parent(base=\"%s\" scope=%s filter=\"%s\"): " "monitor database not configured.\n", BER_BVISNULL( base ) ? "" : base->bv_val, - scope == LDAP_SCOPE_BASE ? "base" : ( scope == LDAP_SCOPE_ONELEVEL ? "one" : "subtree" ), + ldap_pvt_scope2str( scope ), BER_BVISNULL( filter ) ? "" : filter->bv_val ); return -1; } @@ -752,7 +752,7 @@ monitor_back_register_entry_attrs( "monitor database not configured.\n", fname, BER_BVISNULL( base ) ? "" : base->bv_val, - scope == LDAP_SCOPE_BASE ? "base" : ( scope == LDAP_SCOPE_ONELEVEL ? "one" : "subtree" ), + ldap_pvt_scope2str( scope ), BER_BVISNULL( filter ) ? "" : filter->bv_val ); Debug( LDAP_DEBUG_ANY, "%s\n", buf, 0, 0 ); @@ -942,48 +942,210 @@ monitor_back_register_entry_callback( */ int monitor_back_unregister_entry( - Entry **ep, - monitor_callback_t **cbp ) + Entry *target_e ) { - /* TODO */ - return 1; -} + monitor_info_t *mi; -int -monitor_back_unregister_entry_parent( - Entry **ep, - monitor_callback_t **cbp, - struct berval *base, - int scope, - struct berval *filter ) -{ - /* TODO */ - return 1; + if ( be_monitor == NULL ) { + Debug( LDAP_DEBUG_ANY, + "monitor_back_unregister_entry(\"%s\"): " + "monitor database not configured.\n", + target_e->e_name.bv_val, 0, 0 ); + + return -1; + } + + mi = ( monitor_info_t * )be_monitor->be_private; + + assert( mi != NULL ); + + if ( monitor_subsys_opened ) { + Entry *e = NULL; + monitor_entry_t *mp = NULL; + monitor_callback_t *cb = NULL; + + if ( monitor_cache_remove( mi, &target_e->e_nname, &e ) != 0 ) { + /* entry does not exist */ + Debug( LDAP_DEBUG_ANY, + "monitor_back_unregister_entry(\"%s\"): " + "entry removal failed.\n", + target_e->e_name.bv_val, 0, 0 ); + return -1; + } + + mp = (monitor_entry_t *)e->e_private; + assert( mp != NULL ); + + for ( cb = mp->mp_cb; cb != NULL; ) { + monitor_callback_t *next = cb->mc_next; + + if ( cb->mc_free ) { + (void)cb->mc_free( e, cb->mc_private ); + } + ch_free( cb ); + + cb = next; + } + + } else { + /* TODO: remove from limbo */ + return 1; + } + + return 0; } int monitor_back_unregister_entry_attrs( - struct berval *ndn, - Attribute **ap, - monitor_callback_t **cbp, + struct berval *ndn_in, + Attribute *target_a, + monitor_callback_t *target_cb, struct berval *base, int scope, struct berval *filter ) { - /* TODO */ - return 1; + monitor_info_t *mi; + struct berval ndn = BER_BVNULL; + char *fname = ( target_a == NULL ? "callback" : "attrs" ); + + if ( be_monitor == NULL ) { + char buf[ SLAP_TEXT_BUFLEN ]; + + snprintf( buf, sizeof( buf ), + "monitor_back_unregister_entry_%s(base=\"%s\" scope=%s filter=\"%s\"): " + "monitor database not configured.\n", + fname, + BER_BVISNULL( base ) ? "" : base->bv_val, + (char *)ldap_pvt_scope2str( scope ), + BER_BVISNULL( filter ) ? "" : filter->bv_val ); + Debug( LDAP_DEBUG_ANY, "%s\n", buf, 0, 0 ); + + return -1; + } + + mi = ( monitor_info_t * )be_monitor->be_private; + + assert( mi != NULL ); + + if ( ndn_in != NULL ) { + ndn = *ndn_in; + } + + if ( target_a == NULL && target_cb == NULL ) { + /* nothing to do */ + return -1; + } + + if ( ( ndn_in == NULL || BER_BVISNULL( &ndn ) ) + && BER_BVISNULL( filter ) ) + { + /* need a filter */ + Debug( LDAP_DEBUG_ANY, + "monitor_back_unregister_entry_%s(\"\"): " + "need a valid filter\n", + fname, 0, 0 ); + return -1; + } + + if ( monitor_subsys_opened ) { + Entry *e = NULL; + monitor_entry_t *mp = NULL; + int freeit = 0; + + if ( BER_BVISNULL( &ndn ) ) { + if ( monitor_filter2ndn( base, scope, filter, &ndn ) ) { + char buf[ SLAP_TEXT_BUFLEN ]; + + snprintf( buf, sizeof( buf ), + "monitor_back_unregister_entry_%s(\"\"): " + "base=\"%s\" scope=%d filter=\"%s\": " + "unable to find entry\n", + fname, + base->bv_val ? base->bv_val : "\"\"", + scope, filter->bv_val ); + + /* entry does not exist */ + Debug( LDAP_DEBUG_ANY, "%s\n", buf, 0, 0 ); + return -1; + } + + freeit = 1; + } + + if ( monitor_cache_get( mi, &ndn, &e ) != 0 ) { + /* entry does not exist */ + Debug( LDAP_DEBUG_ANY, + "monitor_back_unregister_entry(\"%s\"): " + "entry removal failed.\n", + ndn.bv_val, 0, 0 ); + return -1; + } + + mp = (monitor_entry_t *)e->e_private; + assert( mp != NULL ); + + if ( target_cb != NULL ) { + monitor_callback_t **cbp; + + for ( cbp = &mp->mp_cb; *cbp != NULL; cbp = &(*cbp)->mc_next ) { + if ( *cbp == target_cb ) { + if ( (*cbp)->mc_free ) { + (void)(*cbp)->mc_free( e, (*cbp)->mc_private ); + } + *cbp = (*cbp)->mc_next; + ch_free( target_cb ); + break; + } + } + } + + if ( target_a != NULL ) { + Attribute *a; + + for ( a = target_a; a != NULL; a = a->a_next ) { + Modification mod = { 0 }; + const char *text; + char textbuf[ SLAP_TEXT_BUFLEN ]; + + mod.sm_op = LDAP_MOD_DELETE; + mod.sm_desc = a->a_desc; + mod.sm_values = a->a_vals; + mod.sm_nvalues = a->a_nvals; + + (void)modify_delete_values( e, &mod, 1, + &text, textbuf, sizeof( textbuf ) ); + } + } + + if ( freeit ) { + ber_memfree( ndn.bv_val ); + } + + if ( e ) { + monitor_cache_release( mi, e ); + } + + } else { + /* TODO: remove from limbo */ + return 1; + } + + return 0; } int monitor_back_unregister_entry_callback( struct berval *ndn, - monitor_callback_t **cbp, + monitor_callback_t *cb, struct berval *base, int scope, struct berval *filter ) { - return monitor_back_unregister_entry_attrs( ndn, NULL, cbp, - base, scope, filter ); + /* TODO: lookup entry (by ndn, if not NULL, and/or by callback); + * unregister the callback; if a is not null, unregister the + * given attrs. In any case, call cb->cb_free */ + return monitor_back_unregister_entry_attrs( ndn, + NULL, cb, base, scope, filter ); } monitor_subsys_t * diff --git a/servers/slapd/back-monitor/proto-back-monitor.h b/servers/slapd/back-monitor/proto-back-monitor.h index 3b97e119a2..92f38a9685 100644 --- a/servers/slapd/back-monitor/proto-back-monitor.h +++ b/servers/slapd/back-monitor/proto-back-monitor.h @@ -54,6 +54,11 @@ monitor_cache_get LDAP_P(( struct berval *ndn, Entry **ep )); extern int +monitor_cache_remove LDAP_P(( + monitor_info_t *mi, + struct berval *ndn, + Entry **ep )); +extern int monitor_cache_dn2entry LDAP_P(( Operation *op, SlapReply *rs, @@ -175,27 +180,19 @@ monitor_back_register_entry_callback LDAP_P(( struct berval *filter )); extern int monitor_back_unregister_entry LDAP_P(( - Entry **ep, - monitor_callback_t **cbp )); -extern int -monitor_back_unregister_entry_parent LDAP_P(( - Entry **ep, - monitor_callback_t **cbp, - struct berval *base, - int scope, - struct berval *filter )); + Entry *e )); extern int monitor_back_unregister_entry_attrs LDAP_P(( struct berval *ndn, - Attribute **ap, - monitor_callback_t **cbp, + Attribute *a, + monitor_callback_t *cb, struct berval *base, int scope, struct berval *filter )); extern int monitor_back_unregister_entry_callback LDAP_P(( struct berval *ndn, - monitor_callback_t **cbp, + monitor_callback_t *cb, struct berval *base, int scope, struct berval *filter ));