]> git.sur5r.net Git - openldap/commitdiff
implement support for unregistering registered stuff
authorPierangelo Masarati <ando@openldap.org>
Wed, 6 Sep 2006 12:06:42 +0000 (12:06 +0000)
committerPierangelo Masarati <ando@openldap.org>
Wed, 6 Sep 2006 12:06:42 +0000 (12:06 +0000)
servers/slapd/back-monitor/cache.c
servers/slapd/back-monitor/database.c
servers/slapd/back-monitor/init.c
servers/slapd/back-monitor/proto-back-monitor.h

index 89bfe044b49d28ff1bba8f7feec94d993206bbd7..3639dd11a6cc52c8deed40e8a6123bdf047f8cab 100644 (file)
@@ -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 );
index 5d080f60fd6571a220cbae7173ae17ae25a95703..318b242d011229d011ccd76c65efadde90d0d9de 100644 (file)
 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;
index 3a3d4b543a0edc6cdc28d94c07fc8f798bba2b21..26d7d5edf4ca591935d78b02ed74ab0fb80162fd 100644 (file)
@@ -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 *
index 3b97e119a2ad47966b0b7fcf8d96334bde5e1003..92f38a968539dae7570238c5847f899b063ae046 100644 (file)
@@ -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 ));