]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-monitor/init.c
Merge branch 'mdb.master' of ssh://git-master.openldap.org/~git/git/openldap
[openldap] / servers / slapd / back-monitor / init.c
index e2ef03be88bbaebb3fe9b66a601a029bab8770dc..c2b0b7ef23626d1479c011362d8a31c2b5ac0451 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2001-2007 The OpenLDAP Foundation.
+ * Copyright 2001-2011 The OpenLDAP Foundation.
  * Portions Copyright 2001-2003 Pierangelo Masarati.
  * All rights reserved.
  *
@@ -52,10 +52,10 @@ static const monitor_extra_t monitor_extra = {
        monitor_back_get_subsys_by_dn,
 
        monitor_back_register_subsys,
-       NULL,   /* monitor_back_register_backend */
-       NULL,   /* monitor_back_register_database */
-       NULL,   /* monitor_back_register_overlay_info */
-       NULL,   /* monitor_back_register_overlay */
+       monitor_back_register_backend,
+       monitor_back_register_database,
+       monitor_back_register_overlay_info,
+       monitor_back_register_overlay,
        monitor_back_register_entry,
        monitor_back_register_entry_parent,
        monitor_back_register_entry_attrs,
@@ -225,6 +225,12 @@ static struct monitor_subsys_t known_monitor_subsys[] = {
                }, { NULL }
 };
 
+int
+monitor_subsys_is_opened( void )
+{
+       return monitor_subsys_opened;
+}
+
 int
 monitor_back_register_subsys(
        monitor_subsys_t        *ms )
@@ -249,7 +255,7 @@ monitor_back_register_subsys(
        /* if a subsystem is registered __AFTER__ subsystem 
         * initialization (depending on the sequence the databases
         * are listed in slapd.conf), init it */
-       if ( monitor_subsys_opened ) {
+       if ( monitor_subsys_is_opened() ) {
 
                /* FIXME: this should only be possible
                 * if be_monitor is already initialized */
@@ -269,14 +275,23 @@ enum {
        LIMBO_ENTRY,
        LIMBO_ENTRY_PARENT,
        LIMBO_ATTRS,
-       LIMBO_CB
+       LIMBO_CB,
+       LIMBO_BACKEND,
+       LIMBO_DATABASE,
+       LIMBO_OVERLAY_INFO,
+       LIMBO_OVERLAY,
+
+       LIMBO_LAST
 };
 
 typedef struct entry_limbo_t {
        int                     el_type;
+       BackendInfo             *el_bi;
+       BackendDB               *el_be;
+       slap_overinst           *el_on;
        Entry                   *el_e;
        Attribute               *el_a;
-       struct berval           el_ndn;
+       struct berval           *el_ndn;
        struct berval           el_nbase;
        int                     el_scope;
        struct berval           el_filter;
@@ -292,6 +307,110 @@ monitor_back_is_configured( void )
        return be_monitor != NULL;
 }
 
+int
+monitor_back_register_backend(
+       BackendInfo             *bi )
+{
+       return -1;
+}
+
+int
+monitor_back_register_overlay_info(
+       slap_overinst           *on )
+{
+       return -1;
+}
+
+int
+monitor_back_register_backend_limbo(
+       BackendInfo             *bi )
+{
+       return -1;
+}
+
+int
+monitor_back_register_database_limbo(
+       BackendDB               *be,
+       struct berval           *ndn_out )
+{
+       entry_limbo_t   **elpp, el = { 0 };
+       monitor_info_t  *mi;
+
+       if ( be_monitor == NULL ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "monitor_back_register_database_limbo: "
+                       "monitor database not configured.\n",
+                       0, 0, 0 );
+               return -1;
+       }
+
+       mi = ( monitor_info_t * )be_monitor->be_private;
+
+
+       el.el_type = LIMBO_DATABASE;
+
+       el.el_be = be->bd_self;
+       el.el_ndn = ndn_out;
+       
+       for ( elpp = &mi->mi_entry_limbo;
+                       *elpp;
+                       elpp = &(*elpp)->el_next )
+               /* go to last */;
+
+       *elpp = (entry_limbo_t *)ch_malloc( sizeof( entry_limbo_t ) );
+
+       el.el_next = NULL;
+       **elpp = el;
+
+       return 0;
+}
+
+int
+monitor_back_register_overlay_info_limbo(
+       slap_overinst           *on )
+{
+       return -1;
+}
+
+int
+monitor_back_register_overlay_limbo(
+       BackendDB               *be,
+       struct slap_overinst    *on,
+       struct berval           *ndn_out )
+{
+       entry_limbo_t   **elpp, el = { 0 };
+       monitor_info_t  *mi;
+
+       if ( be_monitor == NULL ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "monitor_back_register_overlay_limbo: "
+                       "monitor database not configured.\n",
+                       0, 0, 0 );
+               return -1;
+       }
+
+       mi = ( monitor_info_t * )be_monitor->be_private;
+
+
+       el.el_type = LIMBO_OVERLAY;
+
+       el.el_be = be->bd_self;
+       el.el_on = on;
+       el.el_ndn = ndn_out;
+       
+       for ( elpp = &mi->mi_entry_limbo;
+                       *elpp;
+                       elpp = &(*elpp)->el_next )
+               /* go to last */;
+
+       *elpp = (entry_limbo_t *)ch_malloc( sizeof( entry_limbo_t ) );
+
+       el.el_next = NULL;
+       **elpp = el;
+
+       return 0;
+}
+
 int
 monitor_back_register_entry(
        Entry                   *e,
@@ -315,7 +434,7 @@ monitor_back_register_entry(
        assert( e != NULL );
        assert( e->e_private == NULL );
        
-       if ( monitor_subsys_opened ) {
+       if ( monitor_subsys_is_opened() ) {
                Entry           *e_parent = NULL,
                                *e_new = NULL,
                                **ep = NULL;
@@ -437,7 +556,7 @@ done:;
                el.el_mss = mss;
                el.el_flags = flags;
 
-               for ( elpp = (entry_limbo_t **)&mi->mi_entry_limbo;
+               for ( elpp = &mi->mi_entry_limbo;
                                *elpp;
                                elpp = &(*elpp)->el_next )
                        /* go to last */;
@@ -494,7 +613,7 @@ monitor_back_register_entry_parent(
                return -1;
        }
 
-       if ( monitor_subsys_opened ) {
+       if ( monitor_subsys_is_opened() ) {
                Entry           *e_parent = NULL,
                                *e_new = NULL,
                                **ep = NULL;
@@ -651,7 +770,7 @@ done:;
                el.el_mss = mss;
                el.el_flags = flags;
 
-               for ( elpp = (entry_limbo_t **)&mi->mi_entry_limbo;
+               for ( elpp = &mi->mi_entry_limbo;
                                *elpp;
                                elpp = &(*elpp)->el_next )
                        /* go to last */;
@@ -711,7 +830,7 @@ monitor_search2ndn(
        OperationBuffer opbuf;
        Operation       *op;
        void    *thrctx;
-       SlapReply       rs = { 0 };
+       SlapReply       rs = { REP_RESULT };
        slap_callback   cb = { NULL, monitor_search2ndn_cb, NULL, NULL };
        int             rc;
 
@@ -721,9 +840,9 @@ monitor_search2ndn(
                return -1;
        }
 
-       op = (Operation *) &opbuf;
        thrctx = ldap_pvt_thread_pool_context();
-       connection_fake_init( &conn, op, thrctx );
+       connection_fake_init2( &conn, &opbuf, thrctx, 0 );
+       op = &opbuf.ob_op;
 
        op->o_tag = LDAP_REQ_SEARCH;
 
@@ -774,7 +893,7 @@ monitor_search2ndn(
 
 cleanup:;
        if ( op->ors_filter != NULL ) {
-               filter_free_x( op, op->ors_filter );
+               filter_free_x( op, op->ors_filter, 1 );
        }
        if ( !BER_BVISNULL( &op->ors_filterstr ) ) {
                op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
@@ -862,7 +981,7 @@ monitor_back_register_entry_attrs(
                return -1;
        }
 
-       if ( monitor_subsys_opened ) {
+       if ( monitor_subsys_is_opened() ) {
                Entry                   *e = NULL;
                Attribute               **atp = NULL;
                monitor_entry_t         *mp = NULL;
@@ -970,9 +1089,7 @@ done:;
                entry_limbo_t   **elpp, el = { 0 };
 
                el.el_type = LIMBO_ATTRS;
-               if ( !BER_BVISNULL( &ndn ) ) {
-                       ber_dupbv( &el.el_ndn, &ndn );
-               }
+               el.el_ndn = ndn_in;
                if ( !BER_BVISNULL( nbase ) ) {
                        ber_dupbv( &el.el_nbase, nbase);
                }
@@ -984,23 +1101,13 @@ done:;
                el.el_a = attrs_dup( a );
                el.el_cb = cb;
 
-               for ( elpp = (entry_limbo_t **)&mi->mi_entry_limbo;
+               for ( elpp = &mi->mi_entry_limbo;
                                *elpp;
                                elpp = &(*elpp)->el_next )
                        /* go to last */;
 
                *elpp = (entry_limbo_t *)ch_malloc( sizeof( entry_limbo_t ) );
                if ( *elpp == NULL ) {
-                       el.el_e->e_private = NULL;
-                       entry_free( el.el_e );
-                       return -1;
-               }
-
-               if ( *elpp != NULL ) {
-                       el.el_next = NULL;
-                       **elpp = el;
-
-               } else {
                        if ( !BER_BVISNULL( &el.el_filter ) ) {
                                ch_free( el.el_filter.bv_val );
                        }
@@ -1010,11 +1117,11 @@ done:;
                        if ( !BER_BVISNULL( &el.el_nbase ) ) {
                                ch_free( &el.el_nbase.bv_val );
                        }
-                       if ( !BER_BVISNULL( &el.el_ndn ) ) {
-                               ch_free( el.el_ndn.bv_val );
-                       }
                        return -1;
                }
+
+               el.el_next = NULL;
+               **elpp = el;
        }
 
        return 0;
@@ -1062,7 +1169,7 @@ monitor_back_unregister_entry(
 
        assert( mi != NULL );
 
-       if ( monitor_subsys_opened ) {
+       if ( monitor_subsys_is_opened() ) {
                Entry                   *e = NULL;
                monitor_entry_t         *mp = NULL;
                monitor_callback_t      *cb = NULL;
@@ -1097,7 +1204,7 @@ monitor_back_unregister_entry(
        } else {
                entry_limbo_t   **elpp;
 
-               for ( elpp = (entry_limbo_t **)&mi->mi_entry_limbo;
+               for ( elpp = &mi->mi_entry_limbo;
                        *elpp;
                        elpp = &(*elpp)->el_next )
                {
@@ -1111,6 +1218,9 @@ monitor_back_unregister_entry(
                                for ( cb = elp->el_cb; cb; cb = next ) {
                                        /* FIXME: call callbacks? */
                                        next = cb->mc_next;
+                                       if ( cb->mc_dispose ) {
+                                               cb->mc_dispose( &cb->mc_private );
+                                       }
                                        ch_free( cb );
                                }
                                assert( elp->el_e != NULL );
@@ -1175,7 +1285,7 @@ monitor_back_unregister_entry_parent(
                return -1;
        }
 
-       if ( monitor_subsys_opened ) {
+       if ( monitor_subsys_is_opened() ) {
                Entry                   *e = NULL;
                monitor_entry_t         *mp = NULL;
 
@@ -1228,7 +1338,7 @@ monitor_back_unregister_entry_parent(
        } else {
                entry_limbo_t   **elpp;
 
-               for ( elpp = (entry_limbo_t **)&mi->mi_entry_limbo;
+               for ( elpp = &mi->mi_entry_limbo;
                        *elpp;
                        elpp = &(*elpp)->el_next )
                {
@@ -1245,6 +1355,9 @@ monitor_back_unregister_entry_parent(
                                for ( cb = elp->el_cb; cb; cb = next ) {
                                        /* FIXME: call callbacks? */
                                        next = cb->mc_next;
+                                       if ( cb->mc_dispose ) {
+                                               cb->mc_dispose( &cb->mc_private );
+                                       }
                                        ch_free( cb );
                                }
                                assert( elp->el_e != NULL );
@@ -1330,7 +1443,7 @@ monitor_back_unregister_entry_attrs(
                return -1;
        }
 
-       if ( monitor_subsys_opened ) {
+       if ( monitor_subsys_is_opened() ) {
                Entry                   *e = NULL;
                monitor_entry_t         *mp = NULL;
                int                     freeit = 0;
@@ -1404,14 +1517,12 @@ monitor_back_unregister_entry_attrs(
                        ber_memfree( ndn.bv_val );
                }
 
-               if ( e ) {
-                       monitor_cache_release( mi, e );
-               }
+               monitor_cache_release( mi, e );
 
        } else {
                entry_limbo_t   **elpp;
 
-               for ( elpp = (entry_limbo_t **)&mi->mi_entry_limbo;
+               for ( elpp = &mi->mi_entry_limbo;
                        *elpp;
                        elpp = &(*elpp)->el_next )
                {
@@ -1427,6 +1538,9 @@ monitor_back_unregister_entry_attrs(
                                for ( cb = elp->el_cb; cb; cb = next ) {
                                        /* FIXME: call callbacks? */
                                        next = cb->mc_next;
+                                       if ( cb->mc_dispose ) {
+                                               cb->mc_dispose( &cb->mc_private );
+                                       }
                                        ch_free( cb );
                                }
                                assert( elp->el_e == NULL );
@@ -1807,6 +1921,15 @@ monitor_back_initialize(
                        "SINGLE-VALUE "
                        "USAGE dSAOperation )", SLAP_AT_HIDE,
                        offsetof(monitor_info_t, mi_ad_monitorRuntimeConfig) },
+               { "( 1.3.6.1.4.1.4203.666.1.55.30 "
+                       "NAME 'monitorSuperiorDN' "
+                       "DESC 'monitor superior DN' "
+                       /* "SUP distinguishedName " */
+                       "EQUALITY distinguishedNameMatch "
+                       "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
+                       "NO-USER-MODIFICATION "
+                       "USAGE dSAOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
+                       offsetof(monitor_info_t, mi_ad_monitorSuperiorDN) },
                { NULL, 0, -1 }
        };
 
@@ -1921,7 +2044,7 @@ monitor_back_initialize(
 
        bi->bi_extended = 0;
 
-       bi->bi_entry_release_rw = 0;
+       bi->bi_entry_release_rw = monitor_back_release;
        bi->bi_chk_referrals = 0;
        bi->bi_operational = monitor_back_operational;
 
@@ -1931,13 +2054,13 @@ monitor_back_initialize(
        bi->bi_tool_entry_open = 0;
        bi->bi_tool_entry_close = 0;
        bi->bi_tool_entry_first = 0;
+       bi->bi_tool_entry_first_x = 0;
        bi->bi_tool_entry_next = 0;
        bi->bi_tool_entry_get = 0;
        bi->bi_tool_entry_put = 0;
        bi->bi_tool_entry_reindex = 0;
        bi->bi_tool_sync = 0;
        bi->bi_tool_dn2id_get = 0;
-       bi->bi_tool_id2entry_get = 0;
        bi->bi_tool_entry_modify = 0;
 
        bi->bi_connection_init = 0;
@@ -1960,7 +2083,8 @@ monitor_back_initialize(
 
 int
 monitor_back_db_init(
-       BackendDB       *be )
+       BackendDB       *be,
+       ConfigReply     *c)
 {
        int                     rc;
        struct berval           dn = BER_BVC( SLAPD_MONITOR_DN ),
@@ -1971,23 +2095,24 @@ monitor_back_db_init(
        monitor_subsys_t        *ms;
 
        /*
-        * register subsys
+        * database monitor can be defined once only
         */
-       for ( ms = known_monitor_subsys; ms->mss_name != NULL; ms++ ) {
-               if ( monitor_back_register_subsys( ms ) ) {
-                       return -1;
+       if ( be_monitor != NULL ) {
+               if (c) {
+                       snprintf(c->msg, sizeof(c->msg),"only one monitor database allowed");
                }
+               return( -1 );
        }
+       be_monitor = be;
 
        /*
-        * database monitor can be defined once only
+        * register subsys
         */
-       if ( be_monitor != NULL ) {
-               Debug( LDAP_DEBUG_ANY,
-                       "only one monitor database is allowed\n", 0, 0, 0 );
-               return( -1 );
+       for ( ms = known_monitor_subsys; ms->mss_name != NULL; ms++ ) {
+               if ( monitor_back_register_subsys( ms ) ) {
+                       return -1;
+               }
        }
-       be_monitor = be;
 
        /* indicate system schema supported */
        SLAP_BFLAGS(be) |= SLAP_BFLAG_MONITOR;
@@ -2009,7 +2134,7 @@ monitor_back_db_init(
 
        be->be_private = &monitor_info;
 
-       be2 = select_backend( &ndn, 0, 0 );
+       be2 = select_backend( &ndn, 0 );
        if ( be2 != be ) {
                char    *type = be2->bd_info->bi_type;
 
@@ -2018,19 +2143,57 @@ monitor_back_db_init(
                        type = oi->oi_orig->bi_type;
                }
 
-               Debug( LDAP_DEBUG_ANY,
-                       "\"monitor\" database serving namingContext \"%s\" "
-                       "is hidden by \"%s\" database serving namingContext \"%s\".\n",
-                       pdn.bv_val, type, be2->be_nsuffix[ 0 ].bv_val );
+               if (c) {
+                       snprintf(c->msg, sizeof(c->msg),
+                                       "\"monitor\" database serving namingContext \"%s\" "
+                                       "is hidden by \"%s\" database serving namingContext \"%s\".\n",
+                                       pdn.bv_val, type, be2->be_nsuffix[ 0 ].bv_val );
+               }
                return -1;
        }
 
        return 0;
 }
 
+static void
+monitor_back_destroy_limbo_entry(
+       entry_limbo_t   *el,
+       int             dispose )
+{
+       if ( el->el_e ) {
+               entry_free( el->el_e );
+       }
+       if ( el->el_a ) {
+               attrs_free( el->el_a );
+       }
+       if ( !BER_BVISNULL( &el->el_nbase ) ) {
+               ber_memfree( el->el_nbase.bv_val );
+       }
+       if ( !BER_BVISNULL( &el->el_filter ) ) {
+               ber_memfree( el->el_filter.bv_val );
+       }
+
+       /* NOTE: callbacks are not copied; so only free them
+        * if disposing of */
+       if ( el->el_cb && dispose != 0 ) {
+               monitor_callback_t *next;
+
+               for ( ; el->el_cb; el->el_cb = next ) {
+                       next = el->el_cb->mc_next;
+                       if ( el->el_cb->mc_dispose ) {
+                               el->el_cb->mc_dispose( &el->el_cb->mc_private );
+                       }
+                       ch_free( el->el_cb );
+               }
+       }
+
+       ch_free( el );
+}
+
 int
 monitor_back_db_open(
-       BackendDB       *be )
+       BackendDB       *be,
+       ConfigReply     *cr)
 {
        monitor_info_t          *mi = (monitor_info_t *)be->be_private;
        struct monitor_subsys_t **ms;
@@ -2038,10 +2201,7 @@ monitor_back_db_open(
        monitor_entry_t         *mp;
        int                     i;
        struct berval           bv, rdn = BER_BVC(SLAPD_MONITOR_DN);
-       struct tm               *tms;
-#ifdef HAVE_GMTIME_R
-       struct tm               tm_buf;
-#endif
+       struct tm               tms;
        static char             tmbuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];
        struct berval   desc[] = {
                BER_BVC("This subtree contains monitoring/managing objects."),
@@ -2050,6 +2210,8 @@ monitor_back_db_open(
                " attributes, which must be explicitly requested."),
                BER_BVNULL };
 
+       int                     retcode = 0;
+
        assert( be_monitor != NULL );
        if ( be != be_monitor ) {
                be_monitor = be;
@@ -2058,27 +2220,8 @@ monitor_back_db_open(
        /*
         * Start
         */
-#ifndef HAVE_GMTIME_R
-       ldap_pvt_thread_mutex_lock( &gmtime_mutex );
-#endif
-#ifdef HACK_LOCAL_TIME
-# ifdef HAVE_LOCALTIME_R
-       tms = localtime_r( &starttime, &tm_buf );
-# else
-       tms = localtime( &starttime );
-# endif /* HAVE_LOCALTIME_R */
-       lutil_localtime( tmbuf, sizeof(tmbuf), tms, -timezone );
-#else /* !HACK_LOCAL_TIME */
-# ifdef HAVE_GMTIME_R
-       tms = gmtime_r( &starttime, &tm_buf );
-# else
-       tms = gmtime( &starttime );
-# endif /* HAVE_GMTIME_R */
-       lutil_gentime( tmbuf, sizeof(tmbuf), tms );
-#endif /* !HACK_LOCAL_TIME */
-#ifndef HAVE_GMTIME_R
-       ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
-#endif
+       ldap_pvt_gmtime( &starttime, &tms );
+       lutil_gentime( tmbuf, sizeof(tmbuf), &tms );
 
        mi->mi_startTime.bv_val = tmbuf;
        mi->mi_startTime.bv_len = strlen( tmbuf );
@@ -2219,8 +2362,7 @@ monitor_back_db_open(
         * opens the monitor backend subsystems
         */
        for ( ms = monitor_subsys; ms[ 0 ] != NULL; ms++ ) {
-               if ( ms[ 0 ]->mss_open && ( *ms[ 0 ]->mss_open )( be, ms[ 0 ] ) )
-               {
+               if ( ms[ 0 ]->mss_open && ms[ 0 ]->mss_open( be, ms[ 0 ] ) ) {
                        return( -1 );
                }
                ms[ 0 ]->mss_flags |= MONITOR_F_OPENED;
@@ -2229,7 +2371,7 @@ monitor_back_db_open(
        monitor_subsys_opened = 1;
 
        if ( mi->mi_entry_limbo ) {
-               entry_limbo_t   *el = (entry_limbo_t *)mi->mi_entry_limbo;
+               entry_limbo_t   *el = mi->mi_entry_limbo;
 
                for ( ; el; ) {
                        entry_limbo_t   *tmp;
@@ -2258,7 +2400,7 @@ monitor_back_db_open(
 
                        case LIMBO_ATTRS:
                                rc = monitor_back_register_entry_attrs(
-                                               &el->el_ndn,
+                                               el->el_ndn,
                                                el->el_a,
                                                el->el_cb,
                                                &el->el_nbase,
@@ -2268,48 +2410,47 @@ monitor_back_db_open(
 
                        case LIMBO_CB:
                                rc = monitor_back_register_entry_callback(
-                                               &el->el_ndn,
+                                               el->el_ndn,
                                                el->el_cb,
                                                &el->el_nbase,
                                                el->el_scope,
                                                &el->el_filter );
                                break;
 
+                       case LIMBO_BACKEND:
+                               rc = monitor_back_register_backend( el->el_bi );
+                               break;
+
+                       case LIMBO_DATABASE:
+                               rc = monitor_back_register_database( el->el_be, el->el_ndn );
+                               break;
+
+                       case LIMBO_OVERLAY_INFO:
+                               rc = monitor_back_register_overlay_info( el->el_on );
+                               break;
+
+                       case LIMBO_OVERLAY:
+                               rc = monitor_back_register_overlay( el->el_be, el->el_on, el->el_ndn );
+                               break;
+
                        default:
                                assert( 0 );
                        }
 
-                       if ( el->el_e ) {
-                               entry_free( el->el_e );
-                       }
-                       if ( el->el_a ) {
-                               attrs_free( el->el_a );
-                       }
-                       if ( !BER_BVISNULL( &el->el_ndn ) ) {
-                               ber_memfree( el->el_ndn.bv_val );
-                       }
-                       if ( !BER_BVISNULL( &el->el_nbase ) ) {
-                               ber_memfree( el->el_nbase.bv_val );
-                       }
-                       if ( !BER_BVISNULL( &el->el_filter ) ) {
-                               ber_memfree( el->el_filter.bv_val );
-                       }
-                       if ( el->el_cb && rc != 0 ) {
-                               if ( el->el_cb->mc_dispose ) {
-                                       el->el_cb->mc_dispose( &el->el_cb->mc_private );
-                               }
-                               ch_free( el->el_cb );
-                       }
-
                        tmp = el;
                        el = el->el_next;
-                       ch_free( tmp );
+                       monitor_back_destroy_limbo_entry( tmp, rc );
+
+                       if ( rc != 0 ) {
+                               /* try all, but report error at end */
+                               retcode = 1;
+                       }
                }
 
                mi->mi_entry_limbo = NULL;
        }
 
-       return( 0 );
+       return retcode;
 }
 
 int
@@ -2346,7 +2487,8 @@ monitor_back_db_config(
 
 int
 monitor_back_db_destroy(
-       BackendDB       *be )
+       BackendDB       *be,
+       ConfigReply     *cr)
 {
        monitor_info_t  *mi = ( monitor_info_t * )be->be_private;
 
@@ -2376,6 +2518,16 @@ monitor_back_db_destroy(
 
                ch_free( monitor_subsys );
        }
+
+       if ( mi->mi_entry_limbo ) {
+               entry_limbo_t   *el = mi->mi_entry_limbo;
+
+               for ( ; el; ) {
+                       entry_limbo_t *tmp = el;
+                       el = el->el_next;
+                       monitor_back_destroy_limbo_entry( tmp, 1 );
+               }
+       }
        
        ldap_pvt_thread_mutex_destroy( &monitor_info.mi_cache_mutex );