+static int
+bdb_db_close( BackendDB *be )
+{
+ int rc;
+ struct bdb_info *bdb = (struct bdb_info *) be->be_private;
+ struct bdb_db_info *db;
+
+ while( 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 );
+ free( db );
+ }
+ free( bdb->bi_databases );
+ bdb_attr_index_destroy( bdb->bi_attrs );
+
+ bdb_cache_release_all (&bdb->bi_cache);
+
+ return 0;
+}
+
+static int
+bdb_db_destroy( BackendDB *be )
+{
+ int rc;
+ struct bdb_info *bdb = (struct bdb_info *) be->be_private;
+
+ /* close db environment */
+ if( bdb->bi_dbenv ) {
+ /* force a checkpoint */
+ rc = TXN_CHECKPOINT( bdb->bi_dbenv, 0, 0, DB_FORCE );
+ if( rc != 0 ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "init", LDAP_LEVEL_ERR, "bdb_db_destroy: txn_checkpoint failed: %s (%d)\n", db_strerror(rc), rc ));
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "bdb_db_destroy: txn_checkpoint failed: %s (%d)\n",
+ db_strerror(rc), rc, 0 );
+#endif
+ }
+
+ bdb_cache_release_all (&bdb->bi_cache);
+
+ rc = bdb->bi_dbenv->close( bdb->bi_dbenv, 0 );
+ bdb->bi_dbenv = NULL;
+ if( rc != 0 ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "init", LDAP_LEVEL_ERR, "bdb_db_destroy: close failed: %s (%d)\n", db_strerror(rc), rc ));
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "bdb_db_destroy: close failed: %s (%d)\n",
+ db_strerror(rc), rc, 0 );
+#endif
+ return rc;
+ }
+ }
+
+#ifdef BDB_HIER
+ ldap_pvt_thread_rdwr_destroy( &bdb->bi_tree_rdwr );
+#endif
+ ldap_pvt_thread_rdwr_destroy ( &bdb->bi_cache.c_rwlock );
+ ldap_pvt_thread_mutex_destroy( &bdb->bi_cache.lru_mutex );
+ ldap_pvt_thread_mutex_destroy( &bdb->bi_lastid_mutex );
+ ldap_pvt_thread_mutex_destroy( &bdb->bi_database_mutex );
+
+ return 0;
+}
+
+#ifdef SLAPD_BDB_DYNAMIC
+int back_bdb_LTX_init_module( int argc, char *argv[] ) {
+ BackendInfo bi;
+
+ memset( &bi, '\0', sizeof(bi) );
+ bi.bi_type = "bdb";
+ bi.bi_init = bdb_initialize;
+
+ backend_add( &bi );
+ return 0;
+}
+#endif /* SLAPD_BDB_DYNAMIC */
+