Beispiel #1
0
static void
target_free(
		struct metatarget *lt
)
{
	if ( lt->uri ) {
		free( lt->uri );
	}
	if ( lt->psuffix.bv_val ) {
		free( lt->psuffix.bv_val );
	}
	if ( lt->suffix.bv_val ) {
		free( lt->suffix.bv_val );
	}
	if ( lt->binddn.bv_val ) {
		free( lt->binddn.bv_val );
	}
	if ( lt->bindpw.bv_val ) {
		free( lt->bindpw.bv_val );
	}
	if ( lt->pseudorootdn.bv_val ) {
		free( lt->pseudorootdn.bv_val );
	}
	if ( lt->pseudorootpw.bv_val ) {
		free( lt->pseudorootpw.bv_val );
	}
	if ( lt->rwinfo ) {
		rewrite_info_delete( lt->rwinfo );
	}
	avl_free( lt->oc_map.remap, NULL );
	avl_free( lt->oc_map.map, mapping_free );
	avl_free( lt->at_map.remap, NULL );
	avl_free( lt->at_map.map, mapping_free );
}
Beispiel #2
0
/*
 * Inits the info
 */
struct rewrite_info *
rewrite_info_init(
		int mode
)
{
	struct rewrite_info *info;
	struct rewrite_context *context;

	switch ( mode ) {
	case REWRITE_MODE_ERR:
	case REWRITE_MODE_OK:
	case REWRITE_MODE_COPY_INPUT:
	case REWRITE_MODE_USE_DEFAULT:
		break;
	default:
		mode = REWRITE_MODE_USE_DEFAULT;
		break;
		/* return NULL */
	}

	/*
	 * Resets the running context for parsing ...
	 */
	rewrite_int_curr_context = NULL;

	info = calloc( sizeof( struct rewrite_info ), 1 );
	if ( info == NULL ) {
		return NULL;
	}

	info->li_state = REWRITE_DEFAULT;
	info->li_max_passes = REWRITE_MAX_PASSES;
	info->li_max_passes_per_rule = REWRITE_MAX_PASSES;
	info->li_rewrite_mode = mode;

	/*
	 * Add the default (empty) rule
	 */
	context = rewrite_context_create( info, REWRITE_DEFAULT_CONTEXT );
	if ( context == NULL ) {
		free( info );
		return NULL;
	}

#ifdef USE_REWRITE_LDAP_PVT_THREADS
	if ( ldap_pvt_thread_rdwr_init( &info->li_cookies_mutex ) ) {
		avl_free( info->li_context, rewrite_context_free );
		free( info );
		return NULL;
	}
	if ( ldap_pvt_thread_rdwr_init( &info->li_params_mutex ) ) {
		ldap_pvt_thread_rdwr_destroy( &info->li_cookies_mutex );
		avl_free( info->li_context, rewrite_context_free );
		free( info );
		return NULL;
	}
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
	
	return info;
}
Beispiel #3
0
void
meta_back_map_free( struct ldapmap *lm )
{
	avl_free( lm->remap, mapping_dst_free );
	avl_free( lm->map, mapping_free );
	lm->remap = NULL;
	lm->map = NULL;
}
Beispiel #4
0
static void
target_free(
	metatarget_t	*mt )
{
	if ( mt->mt_uri ) {
		free( mt->mt_uri );
		ldap_pvt_thread_mutex_destroy( &mt->mt_uri_mutex );
	}
	if ( mt->mt_subtree ) {
		meta_subtree_destroy( mt->mt_subtree );
		mt->mt_subtree = NULL;
	}
	if ( !BER_BVISNULL( &mt->mt_psuffix ) ) {
		free( mt->mt_psuffix.bv_val );
	}
	if ( !BER_BVISNULL( &mt->mt_nsuffix ) ) {
		free( mt->mt_nsuffix.bv_val );
	}
	if ( !BER_BVISNULL( &mt->mt_binddn ) ) {
		free( mt->mt_binddn.bv_val );
	}
	if ( !BER_BVISNULL( &mt->mt_bindpw ) ) {
		free( mt->mt_bindpw.bv_val );
	}
	if ( !BER_BVISNULL( &mt->mt_idassert_authcID ) ) {
		ch_free( mt->mt_idassert_authcID.bv_val );
	}
	if ( !BER_BVISNULL( &mt->mt_idassert_authcDN ) ) {
		ch_free( mt->mt_idassert_authcDN.bv_val );
	}
	if ( !BER_BVISNULL( &mt->mt_idassert_passwd ) ) {
		ch_free( mt->mt_idassert_passwd.bv_val );
	}
	if ( !BER_BVISNULL( &mt->mt_idassert_authzID ) ) {
		ch_free( mt->mt_idassert_authzID.bv_val );
	}
	if ( !BER_BVISNULL( &mt->mt_idassert_sasl_mech ) ) {
		ch_free( mt->mt_idassert_sasl_mech.bv_val );
	}
	if ( !BER_BVISNULL( &mt->mt_idassert_sasl_realm ) ) {
		ch_free( mt->mt_idassert_sasl_realm.bv_val );
	}
	if ( mt->mt_idassert_authz != NULL ) {
		ber_bvarray_free( mt->mt_idassert_authz );
	}
	if ( mt->mt_rwmap.rwm_rw ) {
		rewrite_info_delete( &mt->mt_rwmap.rwm_rw );
	}
	avl_free( mt->mt_rwmap.rwm_oc.remap, mapping_dst_free );
	avl_free( mt->mt_rwmap.rwm_oc.map, mapping_free );
	avl_free( mt->mt_rwmap.rwm_at.remap, mapping_dst_free );
	avl_free( mt->mt_rwmap.rwm_at.map, mapping_free );

	free( mt );
}
Beispiel #5
0
void
avl_free(avl_tree_t *root){

	if(root == NULL){
		return;
	}
	avl_free(root->left);
	avl_free(root->right);
	avl_free_node(root);

}
Beispiel #6
0
/*
 * Destroys the cookie tree
 */
int
rewrite_session_destroy(
		struct rewrite_info *info
)
{
	int count;

	assert( info != NULL );
	
#ifdef USE_REWRITE_LDAP_PVT_THREADS
	ldap_pvt_thread_rdwr_wlock( &info->li_cookies_mutex );
#endif /* USE_REWRITE_LDAP_PVT_THREADS */

	/*
	 * Should call per-session destruction routine ...
	 */
	
	count = avl_free( info->li_cookies, rewrite_session_free );
	info->li_cookies = NULL;

#if 0
	fprintf( stderr, "count = %d; num_cookies = %d\n", 
			count, info->li_num_cookies );
#endif
	
	assert( count == info->li_num_cookies );
	info->li_num_cookies = 0;

#ifdef USE_REWRITE_LDAP_PVT_THREADS
	ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex );
#endif /* USE_REWRITE_LDAP_PVT_THREADS */

	return REWRITE_SUCCESS;
}
Beispiel #7
0
/* Free up the FM.  If kFin is non-NULL, it is applied to keys
   before the FM is deleted; ditto with vFin for vals. */
void deleteFM ( WordFM* fm, void(*kFin)(Word), void(*vFin)(Word) )
{
    void(*dealloc)(void*) = fm->dealloc;
    avl_free( fm->root, kFin, vFin, dealloc );
    memset(fm, 0, sizeof(WordFM) );
    dealloc(fm);
}
Beispiel #8
0
int
meta_back_db_destroy(
    Backend	*be
)
{
	struct metainfo *li;

	if ( be->be_private ) {
		int i;

		li = ( struct metainfo * )be->be_private;

		/*
		 * Destroy the connection tree
		 */
		ldap_pvt_thread_mutex_lock( &li->conn_mutex );

		if ( li->conntree ) {
			avl_free( li->conntree, conn_free );
		}

		/*
		 * Destroy the per-target stuff (assuming there's at
		 * least one ...)
		 */
		for ( i = 0; i < li->ntargets; i++ ) {
			target_free( li->targets[ i ] );
			free( li->targets[ i ] );
		}

		free( li->targets );

		ldap_pvt_thread_mutex_lock( &li->cache.mutex );
		if ( li->cache.tree ) {
			avl_free( li->cache.tree, meta_dncache_free );
		}
		
		ldap_pvt_thread_mutex_unlock( &li->cache.mutex );
		ldap_pvt_thread_mutex_destroy( &li->cache.mutex );

		ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
		ldap_pvt_thread_mutex_destroy( &li->conn_mutex );
	}

	free( be->be_private );
	return 0;
}
Beispiel #9
0
/*
 * Deletes a var tree
 */
int
rewrite_var_delete(
		Avlnode *tree
)
{
	avl_free( tree, rewrite_var_free );
	return REWRITE_SUCCESS;
}
Beispiel #10
0
int
ldap_back_db_destroy( Backend *be, ConfigReply *cr )
{
	if ( be->be_private ) {
		ldapinfo_t	*li = ( ldapinfo_t * )be->be_private;
		unsigned	i;

		(void)ldap_back_monitor_db_destroy( be );

		ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );

		if ( li->li_uri != NULL ) {
			ch_free( li->li_uri );
			li->li_uri = NULL;

			assert( li->li_bvuri != NULL );
			ber_bvarray_free( li->li_bvuri );
			li->li_bvuri = NULL;
		}

		bindconf_free( &li->li_tls );
		bindconf_free( &li->li_acl );
		bindconf_free( &li->li_idassert.si_bc );

		if ( li->li_idassert_authz != NULL ) {
			ber_bvarray_free( li->li_idassert_authz );
			li->li_idassert_authz = NULL;
		}
               	if ( li->li_conninfo.lai_tree ) {
			avl_free( li->li_conninfo.lai_tree, ldap_back_conn_free );
		}
		for ( i = LDAP_BACK_PCONN_FIRST; i < LDAP_BACK_PCONN_LAST; i++ ) {
			while ( !LDAP_TAILQ_EMPTY( &li->li_conn_priv[ i ].lic_priv ) ) {
				ldapconn_t	*lc = LDAP_TAILQ_FIRST( &li->li_conn_priv[ i ].lic_priv );

				LDAP_TAILQ_REMOVE( &li->li_conn_priv[ i ].lic_priv, lc, lc_q );
				ldap_back_conn_free( lc );
			}
		}
		if ( LDAP_BACK_QUARANTINE( li ) ) {
			slap_retry_info_destroy( &li->li_quarantine );
			ldap_pvt_thread_mutex_destroy( &li->li_quarantine_mutex );
		}

		ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
		ldap_pvt_thread_mutex_destroy( &li->li_conninfo.lai_mutex );
		ldap_pvt_thread_mutex_destroy( &li->li_uri_mutex );

		for ( i = 0; i < SLAP_OP_LAST; i++ ) {
			ldap_pvt_mp_clear( li->li_ops_completed[ i ] );
		}
		ldap_pvt_thread_mutex_destroy( &li->li_counter_mutex );
	}

	ch_free( be->be_private );

	return 0;
}
Beispiel #11
0
void
valuetree_free( Avlnode **valuetreep )
{
	if ( valuetreep != NULL && *valuetreep != NULL )
	{
		avl_free( *valuetreep, valuetree_node_free );
		*valuetreep = NULL;
	}
}
Beispiel #12
0
static void avl_free ( AvlNode* nd,
                       void(*kFin)(Word),
                       void(*vFin)(Word),
                       void(*dealloc)(void*) )
{
    if (!nd)
        return;
    if (nd->left)
        avl_free(nd->left, kFin, vFin, dealloc);
    if (nd->right)
        avl_free(nd->right, kFin, vFin, dealloc);
    if (kFin)
        kFin( nd->key );
    if (vFin)
        vFin( nd->val );
    memset(nd, 0, sizeof(AvlNode));
    dealloc(nd);
}
Beispiel #13
0
static void avl_free ( AvlNode* nd, 
                       void(*kFin)(UWord),
                       void(*vFin)(UWord),
                       void(*dealloc)(void*) )
{
   if (!nd)
      return;
   if (nd->child[0])
      avl_free(nd->child[0], kFin, vFin, dealloc);
   if (nd->child[1])
      avl_free(nd->child[1], kFin, vFin, dealloc);
   if (kFin)
      kFin( nd->key );
   if (vFin)
      vFin( nd->val );
   VG_(memset)(nd, 0, sizeof(AvlNode));
   dealloc(nd);
}
Beispiel #14
0
int
monitor_cache_destroy(
	monitor_info_t	*mi )
{
	if ( mi->mi_cache ) {
		avl_free( mi->mi_cache, monitor_entry_destroy );
	}

	return 0;
}
Beispiel #15
0
/* free a tree */
void
avlDestroy(AvlTree t)
{
    if (t != AVL_EMPTY) {
        avlDestroy(t->child[0]);
        t->child[0] = AVL_EMPTY;
        avlDestroy(t->child[1]);
        t->child[1] = AVL_EMPTY;
        avl_free(t);
    }
}
Beispiel #16
0
/* Frees storage allocated for |tree|.
   If |destroy != NULL|, applies it to each data item in inorder. */
void map_destroy( map_t tree, value_destroy_func destroy)
{
	struct avl_node *p, *q;

	for (p = tree->avl_root; p != NULL; p = q)
		if (p->avl_link[0] == NULL) {
			q = p->avl_link[1];
			if (destroy != NULL && p->val != NULL)
				destroy(p->val);
			if( !(tree->flags & AVLMAP_NO_DUPLICATE ) )
				avl_free( p->key.s,tree->flags);
			avl_free( p, tree->flags );
		} else {
			q = p->avl_link[0];
			p->avl_link[0] = q->avl_link[1];
			q->avl_link[1] = p;
		}

	avl_free( tree, tree->flags );
}
Beispiel #17
0
int
avl_free( Avlnode *root, AVL_FREE dfree )
{
	int	nleft, nright;

	if ( root == 0 )
		return( 0 );

	nleft = nright = 0;
	if ( root->avl_left != 0 )
		nleft = avl_free( root->avl_left, dfree );

	if ( root->avl_right != 0 )
		nright = avl_free( root->avl_right, dfree );

	if ( dfree )
		(*dfree)( root->avl_data );
	ber_memfree( root );

	return( nleft + nright + 1 );
}
Beispiel #18
0
void
slapi_ch_stop_recording()
{
#if defined(_WIN32) && defined(DEBUG)
    PR_Lock( mr_tree_lock );
	recording= 0;
    avl_apply( mr_tree, memory_record_dump, NULL, STOP_TRAVERSAL, AVL_INORDER );
    avl_free( mr_tree, memory_record_delete );
	mr_tree= NULL;
    PR_Unlock( mr_tree_lock );
#endif
}
Beispiel #19
0
/*
 * Cleans up the info structure
 */
int
rewrite_info_delete(
		struct rewrite_info **pinfo
)
{
	struct rewrite_info	*info;

	assert( pinfo != NULL );
	assert( *pinfo != NULL );

	info = *pinfo;
	
	if ( info->li_context ) {
		avl_free( info->li_context, rewrite_context_free );
	}
	info->li_context = NULL;

	if ( info->li_maps ) {
		avl_free( info->li_maps, rewrite_builtin_map_free );
	}
	info->li_maps = NULL;

	rewrite_session_destroy( info );

#ifdef USE_REWRITE_LDAP_PVT_THREADS
	ldap_pvt_thread_rdwr_destroy( &info->li_cookies_mutex );
#endif /* USE_REWRITE_LDAP_PVT_THREADS */

	rewrite_param_destroy( info );
	
#ifdef USE_REWRITE_LDAP_PVT_THREADS
	ldap_pvt_thread_rdwr_destroy( &info->li_params_mutex );
#endif /* USE_REWRITE_LDAP_PVT_THREADS */

	free( info );
	*pinfo = NULL;

	return REWRITE_SUCCESS;
}
Beispiel #20
0
int
avl_free( Avlnode *root, IFP dfree )
{
	int	nleft, nright;

	if ( root == 0 )
		return( 0 );

	nleft = nright = 0;
	if ( root->avl_left != 0 )
		nleft = avl_free( root->avl_left, dfree );

	if ( root->avl_right != 0 )
		nright = avl_free( root->avl_right, dfree );

	if ( dfree )
		(*dfree)( root->avl_data );

	free( (char *)root );

	return( nleft + nright + 1 );
}
/*
 * call from within bdb_db_destroy()
 */
int
bdb_monitor_db_destroy( BackendDB *be )
{
#ifdef BDB_MONITOR_IDX
	struct bdb_info		*bdb = (struct bdb_info *) be->be_private;

	/* TODO: free tree */
	ldap_pvt_thread_mutex_destroy( &bdb->bi_idx_mutex );
	avl_free( bdb->bi_idx, ch_free );
#endif /* BDB_MONITOR_IDX */

	return 0;
}
Beispiel #22
0
static int
bdb_tool_idl_flush_db( DB *db, bdb_tool_idl_cache *ic )
{
	Avlnode *root = db->app_private;
	int rc;

	db->app_private = ic;
	rc = avl_apply( root, bdb_tool_idl_flush_one, db, -1, AVL_INORDER );
	avl_free( root, NULL );
	db->app_private = NULL;
	if ( rc != -1 )
		rc = 0;
	return rc;
}
/*
 * entry_dispose
 * -------------------
 *
 * INPUT: pointer to entry to be disposed of
 *
 */
void entry_dispose(const void *elt)
{
  const entry *bbr;

  DLOG("entry_dispose()");
  bbr = elt;

  /* free the entry struct itself */
  free(bbr->key);
  avl_free(bbr->data);
  free(bbr);

  DLOG("entry_dispose: returning void");
}
Beispiel #24
0
/* delete the given value */
tw_event *
avlDelete(AvlTree *t, tw_event *key)
{
    tw_event *target = NULL;
    AvlTree oldroot;
    
    if (*t == AVL_EMPTY) {
        tw_error(TW_LOC, "We never look for non-existent events!");
        return target;
    }
    
    if (key->recv_ts == (*t)->key->recv_ts) {
        // We have a timestamp tie, check the event ID
        if (key->event_id == (*t)->key->event_id) {
            // We have a event ID tie, check the send_pe
            if (key->send_pe == (*t)->key->send_pe) {
                // This is actually the one we want to delete
                target = (*t)->key;
                /* do we have a right child? */
                if ((*t)->child[1] != AVL_EMPTY) {
                    /* give root min value in right subtree */
                    (*t)->key = avlDeleteMin(&(*t)->child[1]);
                }
                else {
                    /* splice out root */
                    oldroot = (*t);
                    *t = (*t)->child[0];
                    avl_free(oldroot);
                }
            }
            else {
                // Timestamp and event IDs are the same, but different send_pe
                target = avlDelete(&(*t)->child[key->send_pe > (*t)->key->send_pe], key);
            }
        }
        else {
            // Timestamps are the same but event IDs differ
            target = avlDelete(&(*t)->child[key->event_id > (*t)->key->event_id], key);
        }
    }
    else {
        // Timestamps are different
        target = avlDelete(&(*t)->child[key->recv_ts > (*t)->key->recv_ts], key);
    }
    
    avlRebalance(t);
    
    return target;
}
Beispiel #25
0
/*
 * call from within bdb_db_destroy()
 */
int
bdb_monitor_db_destroy( BackendDB *be )
{
	if ( SLAP_GLUE_SUBORDINATE( be ) ) {
		return 0;
	}

#ifdef BDB_MONITOR_IDX
	{
		struct bdb_info		*bdb = (struct bdb_info *) be->be_private;

		/* TODO: free tree */
		ldap_pvt_thread_mutex_destroy( &bdb->bi_idx_mutex );
		avl_free( bdb->bi_idx, ch_free );
	}
#endif /* BDB_MONITOR_IDX */

	return 0;
}
Beispiel #26
0
static int
ldap_distproc_db_destroy(
	BackendDB	*be,
	ConfigReply	*cr )
{
	slap_overinst	*on = (slap_overinst *) be->bd_info;
	ldap_distproc_t	*lc = (ldap_distproc_t *)on->on_bi.bi_private;

	int		rc;

	rc = ldap_distproc_db_func( be, db_destroy );

	if ( lc ) {
		avl_free( lc->lc_lai.lai_tree, NULL );
		ldap_pvt_thread_mutex_destroy( &lc->lc_lai.lai_mutex );
		ch_free( lc );
	}

	return rc;
}
Beispiel #27
0
/*
 * Destroys the parameter tree
 */
int
rewrite_param_destroy(
		struct rewrite_info *info
)
{
	int count;

	assert( info != NULL );
	
#ifdef USE_REWRITE_LDAP_PVT_THREADS
	ldap_pvt_thread_rdwr_wlock( &info->li_params_mutex );
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
	
	count = avl_free( info->li_params, rewrite_param_free );
	info->li_params = NULL;

#ifdef USE_REWRITE_LDAP_PVT_THREADS
	ldap_pvt_thread_rdwr_wunlock( &info->li_params_mutex );
#endif /* USE_REWRITE_LDAP_PVT_THREADS */

	return REWRITE_SUCCESS;
}
Beispiel #28
0
/* delete and return minimum value in a tree */
tw_event *
avlDeleteMin(AvlTree *t)
{
    AvlTree oldroot;
    tw_event *event_with_lowest_ts = NULL;
    
    assert(t != AVL_EMPTY);
    
    if ((*t)->child[0] == AVL_EMPTY) {
        /* root is min value */
        oldroot = *t;
        event_with_lowest_ts = oldroot->key;
        *t = oldroot->child[1];
        avl_free(oldroot);
    }
    else {
        /* min value is in left subtree */
        event_with_lowest_ts = avlDeleteMin(&(*t)->child[0]);
    }
    
    avlRebalance(t);
    return event_with_lowest_ts;
}
Beispiel #29
0
int
main( int argc, char **argv )
{
	Avlnode	*tree = NULL;
	char	command[ 10 ];
	char	name[ 80 ];
	char	*p;

	printf( "> " );
	while ( fgets( command, sizeof( command ), stdin ) != NULL ) {
		switch( *command ) {
		case 'n':	/* new tree */
			( void ) avl_free( tree, free );
			tree = NULL;
			break;
		case 'p':	/* print */
			( void ) myprint( tree );
			break;
		case 't':	/* traverse with first, next */
#ifdef AVL_NONREENTRANT
			printf( "***\n" );
			for ( p = (char * ) avl_getfirst( tree );
			    p != NULL;
				p = (char *) avl_getnext())
				printf( "%s\n", p );
			printf( "***\n" );
#else
			printf( "*** reentrant interface not implemented ***" );
#endif
			break;
		case 'f':	/* find */
			printf( "data? " );
			if ( fgets( name, sizeof( name ), stdin ) == NULL )
				exit( EXIT_SUCCESS );
			name[ strlen( name ) - 1 ] = '\0';
			if ( (p = (char *) avl_find( tree, name, avl_strcmp ))
			    == NULL )
				printf( "Not found.\n\n" );
			else
				printf( "%s\n\n", p );
			break;
		case 'i':	/* insert */
			printf( "data? " );
			if ( fgets( name, sizeof( name ), stdin ) == NULL )
				exit( EXIT_SUCCESS );
			name[ strlen( name ) - 1 ] = '\0';
			if ( avl_insert( &tree, strdup( name ), avl_strcmp, 
			    avl_dup_error ) != 0 )
				printf( "\nNot inserted!\n" );
			break;
		case 'd':	/* delete */
			printf( "data? " );
			if ( fgets( name, sizeof( name ), stdin ) == NULL )
				exit( EXIT_SUCCESS );
			name[ strlen( name ) - 1 ] = '\0';
			if ( avl_delete( &tree, name, avl_strcmp ) == NULL )
				printf( "\nNot found!\n" );
			break;
		case 'q':	/* quit */
			exit( EXIT_SUCCESS );
			break;
		case '\n':
			break;
		default:
			printf("Commands: insert, delete, print, new, quit\n");
		}

		printf( "> " );
	}

	return( 0 );
}
Beispiel #30
0
static int
bdb_db_close( BackendDB *be, ConfigReply *cr )
{
	int rc;
	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
	struct bdb_db_info *db;
	bdb_idl_cache_entry_t *entry, *next_entry;

	/* monitor handling */
	(void)bdb_monitor_db_close( be );

	{
		Entry *e = bdb->bi_cache.c_dntree.bei_e;
		if ( e ) {
			bdb->bi_cache.c_dntree.bei_e = NULL;
			e->e_private = NULL;
			bdb_entry_return( e );
		}
	}

	bdb->bi_flags &= ~BDB_IS_OPEN;

	ber_bvarray_free( bdb->bi_db_config );
	bdb->bi_db_config = NULL;

	if( bdb->bi_dbenv ) {
		/* Free cache locker if we enabled locking.
		 * TXNs must all be closed before DBs...
		 */
		if ( !( slapMode & SLAP_TOOL_QUICK ) && bdb->bi_cache.c_txn ) {
			TXN_ABORT( bdb->bi_cache.c_txn );
			bdb->bi_cache.c_txn = NULL;
		}
		bdb_reader_flush( bdb->bi_dbenv );
	}

	while( bdb->bi_databases && bdb->bi_ndatabases-- ) {
		db = bdb->bi_databases[bdb->bi_ndatabases];
		rc = db->bdi_db->close( db->bdi_db, 0 );
		/* Lower numbered names are not strdup'd */
		if( bdb->bi_ndatabases >= BDB_NDB )
			free( db->bdi_name.bv_val );
		free( db );
	}
	free( bdb->bi_databases );
	bdb->bi_databases = NULL;

	bdb_cache_release_all (&bdb->bi_cache);

	if ( bdb->bi_idl_cache_size ) {
		avl_free( bdb->bi_idl_tree, NULL );
		bdb->bi_idl_tree = NULL;
		entry = bdb->bi_idl_lru_head;
		do {
			next_entry = entry->idl_lru_next;
			if ( entry->idl )
				free( entry->idl );
			free( entry->kstr.bv_val );
			free( entry );
			entry = next_entry;
		} while ( entry != bdb->bi_idl_lru_head );
		bdb->bi_idl_lru_head = bdb->bi_idl_lru_tail = NULL;
	}

	/* close db environment */
	if( bdb->bi_dbenv ) {
		/* force a checkpoint, but not if we were ReadOnly,
		 * and not in Quick mode since there are no transactions there.
		 */
		if ( !( slapMode & ( SLAP_TOOL_QUICK|SLAP_TOOL_READONLY ))) {
			rc = TXN_CHECKPOINT( bdb->bi_dbenv, 0, 0, DB_FORCE );
			if( rc != 0 ) {
				Debug( LDAP_DEBUG_ANY,
					"bdb_db_close: database \"%s\": "
					"txn_checkpoint failed: %s (%d).\n",
					be->be_suffix[0].bv_val, db_strerror(rc), rc );
			}
		}

		rc = bdb->bi_dbenv->close( bdb->bi_dbenv, 0 );
		bdb->bi_dbenv = NULL;
		if( rc != 0 ) {
			Debug( LDAP_DEBUG_ANY,
				"bdb_db_close: database \"%s\": "
				"close failed: %s (%d)\n",
				be->be_suffix[0].bv_val, db_strerror(rc), rc );
			return rc;
		}
	}

	rc = alock_close( &bdb->bi_alock_info, slapMode & SLAP_TOOL_QUICK );
	if( rc != 0 ) {
		Debug( LDAP_DEBUG_ANY,
			"bdb_db_close: database \"%s\": alock_close failed\n",
			be->be_suffix[0].bv_val, 0, 0 );
		return -1;
	}

	return 0;
}