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
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
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 );
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) */
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;
"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;
}
"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 );
*/
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 *