1 /* init.c - initialize bdb backend */
2 /* $OpenLDAP: pkg/ldap/servers/slapd/back-bdb/init.c,v 1.247.2.11 2008/02/11 23:26:45 kurt Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2000-2008 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
20 #include <ac/string.h>
21 #include <ac/unistd.h>
22 #include <ac/stdlib.h>
31 static const struct bdbi_database
{
36 } bdbi_databases
[] = {
37 { "id2entry" BDB_SUFFIX
, BER_BVC("id2entry"), DB_BTREE
, 0 },
38 { "dn2id" BDB_SUFFIX
, BER_BVC("dn2id"), DB_BTREE
, 0 },
39 { NULL
, BER_BVNULL
, 0, 0 }
42 typedef void * db_malloc(size_t);
43 typedef void * db_realloc(void *, size_t);
45 #define bdb_db_init BDB_SYMBOL(db_init)
46 #define bdb_db_open BDB_SYMBOL(db_open)
47 #define bdb_db_close BDB_SYMBOL(db_close)
50 bdb_db_init( BackendDB
*be
, ConfigReply
*cr
)
55 Debug( LDAP_DEBUG_TRACE
,
56 LDAP_XSTRING(bdb_db_init
) ": Initializing " BDB_UCTYPE
" database\n",
59 /* allocate backend-database-specific stuff */
60 bdb
= (struct bdb_info
*) ch_calloc( 1, sizeof(struct bdb_info
) );
62 /* DBEnv parameters */
63 bdb
->bi_dbenv_home
= ch_strdup( SLAPD_DEFAULT_DB_DIR
);
64 bdb
->bi_dbenv_xflags
= 0;
65 bdb
->bi_dbenv_mode
= SLAPD_DEFAULT_DB_MODE
;
67 bdb
->bi_cache
.c_maxsize
= DEFAULT_CACHE_SIZE
;
68 bdb
->bi_cache
.c_minfree
= 1;
70 bdb
->bi_lock_detect
= DB_LOCK_DEFAULT
;
71 bdb
->bi_search_stack_depth
= DEFAULT_SEARCH_STACK_DEPTH
;
72 bdb
->bi_search_stack
= NULL
;
74 ldap_pvt_thread_mutex_init( &bdb
->bi_database_mutex
);
75 ldap_pvt_thread_mutex_init( &bdb
->bi_lastid_mutex
);
77 ldap_pvt_thread_mutex_init( &bdb
->bi_modrdns_mutex
);
79 ldap_pvt_thread_mutex_init( &bdb
->bi_cache
.c_lru_mutex
);
80 ldap_pvt_thread_mutex_init( &bdb
->bi_cache
.c_count_mutex
);
81 ldap_pvt_thread_mutex_init( &bdb
->bi_cache
.c_eifree_mutex
);
82 ldap_pvt_thread_mutex_init( &bdb
->bi_cache
.c_dntree
.bei_kids_mutex
);
83 ldap_pvt_thread_rdwr_init ( &bdb
->bi_cache
.c_rwlock
);
84 ldap_pvt_thread_rdwr_init( &bdb
->bi_idl_tree_rwlock
);
85 ldap_pvt_thread_mutex_init( &bdb
->bi_idl_tree_lrulock
);
88 be
->be_cf_ocs
= be
->bd_info
->bi_cf_ocs
;
90 #ifndef BDB_MULTIPLE_SUFFIXES
91 SLAP_DBFLAGS( be
) |= SLAP_DBFLAG_ONE_SUFFIX
;
94 rc
= bdb_monitor_db_init( be
);
100 bdb_db_close( BackendDB
*be
, ConfigReply
*cr
);
103 bdb_db_open( BackendDB
*be
, ConfigReply
*cr
)
106 struct bdb_info
*bdb
= (struct bdb_info
*) be
->be_private
;
107 struct stat stat1
, stat2
;
109 char path
[MAXPATHLEN
];
112 int do_recover
= 0, do_alock_recover
= 0;
113 int alockt
, quick
= 0;
115 if ( be
->be_suffix
== NULL
) {
116 Debug( LDAP_DEBUG_ANY
,
117 LDAP_XSTRING(bdb_db_open
) ": need suffix.\n",
122 Debug( LDAP_DEBUG_ARGS
,
123 LDAP_XSTRING(bdb_db_open
) ": \"%s\"\n",
124 be
->be_suffix
[0].bv_val
, 0, 0 );
126 /* Check existence of dbenv_home. Any error means trouble */
127 rc
= stat( bdb
->bi_dbenv_home
, &stat1
);
129 Debug( LDAP_DEBUG_ANY
,
130 LDAP_XSTRING(bdb_db_open
) ": database \"%s\": "
131 "cannot access database directory \"%s\" (%d).\n",
132 be
->be_suffix
[0].bv_val
, bdb
->bi_dbenv_home
, errno
);
136 /* Perform database use arbitration/recovery logic */
137 alockt
= (slapMode
& SLAP_TOOL_READONLY
) ? ALOCK_LOCKED
: ALOCK_UNIQUE
;
138 if ( slapMode
& SLAP_TOOL_QUICK
) {
139 alockt
|= ALOCK_NOSAVE
;
143 rc
= alock_open( &bdb
->bi_alock_info
,
145 bdb
->bi_dbenv_home
, alockt
);
147 /* alockt is TRUE if the existing environment was created in Quick mode */
148 alockt
= (rc
& ALOCK_NOSAVE
) ? 1 : 0;
151 if( rc
== ALOCK_RECOVER
) {
152 Debug( LDAP_DEBUG_ANY
,
153 LDAP_XSTRING(bdb_db_open
) ": database \"%s\": "
154 "unclean shutdown detected; attempting recovery.\n",
155 be
->be_suffix
[0].bv_val
, 0, 0 );
156 do_alock_recover
= 1;
157 do_recover
= DB_RECOVER
;
158 } else if( rc
== ALOCK_BUSY
) {
159 Debug( LDAP_DEBUG_ANY
,
160 LDAP_XSTRING(bdb_db_open
) ": database \"%s\": "
161 "database already in use.\n",
162 be
->be_suffix
[0].bv_val
, 0, 0 );
164 } else if( rc
!= ALOCK_CLEAN
) {
165 Debug( LDAP_DEBUG_ANY
,
166 LDAP_XSTRING(bdb_db_open
) ": database \"%s\": "
167 "alock package is unstable.\n",
168 be
->be_suffix
[0].bv_val
, 0, 0 );
173 * The DB_CONFIG file may have changed. If so, recover the
174 * database so that new settings are put into effect. Also
175 * note the possible absence of DB_CONFIG in the log.
177 if( stat( bdb
->bi_db_config_path
, &stat1
) == 0 ) {
179 char *ptr
= lutil_strcopy(path
, bdb
->bi_dbenv_home
);
180 *ptr
++ = LDAP_DIRSEP
[0];
181 strcpy( ptr
, "__db.001" );
182 if( stat( path
, &stat2
) == 0 ) {
183 if( stat2
.st_mtime
< stat1
.st_mtime
) {
184 Debug( LDAP_DEBUG_ANY
,
185 LDAP_XSTRING(bdb_db_open
) ": DB_CONFIG for suffix \"%s\" has changed.\n",
186 be
->be_suffix
[0].bv_val
, 0, 0 );
188 Debug( LDAP_DEBUG_ANY
,
189 "Cannot use Quick mode; perform manual recovery first.\n",
191 slapMode
^= SLAP_TOOL_QUICK
;
195 Debug( LDAP_DEBUG_ANY
,
196 "Performing database recovery to activate new settings.\n",
199 do_recover
= DB_RECOVER
;
205 Debug( LDAP_DEBUG_ANY
,
206 LDAP_XSTRING(bdb_db_open
) ": warning - no DB_CONFIG file found "
207 "in directory %s: (%d).\n"
208 "Expect poor performance for suffix \"%s\".\n",
209 bdb
->bi_dbenv_home
, errno
, be
->be_suffix
[0].bv_val
);
212 /* Always let slapcat run, regardless of environment state.
213 * This can be used to cause a cache flush after an unclean
216 if ( do_recover
&& ( slapMode
& SLAP_TOOL_READONLY
)) {
217 Debug( LDAP_DEBUG_ANY
,
218 LDAP_XSTRING(bdb_db_open
) ": database \"%s\": "
219 "recovery skipped in read-only mode. "
220 "Run manual recovery if errors are encountered.\n",
221 be
->be_suffix
[0].bv_val
, 0, 0 );
226 /* An existing environment in Quick mode has nothing to recover. */
227 if ( alockt
&& do_recover
) {
228 Debug( LDAP_DEBUG_ANY
,
229 LDAP_XSTRING(bdb_db_open
) ": database \"%s\": "
230 "cannot recover, database must be reinitialized.\n",
231 be
->be_suffix
[0].bv_val
, 0, 0 );
236 rc
= db_env_create( &bdb
->bi_dbenv
, 0 );
238 Debug( LDAP_DEBUG_ANY
,
239 LDAP_XSTRING(bdb_db_open
) ": database \"%s\": "
240 "db_env_create failed: %s (%d).\n",
241 be
->be_suffix
[0].bv_val
, db_strerror(rc
), rc
);
246 strcpy( path
, bdb
->bi_dbenv_home
);
250 dbhome
= bdb
->bi_dbenv_home
;
253 /* If existing environment is clean but doesn't support
254 * currently requested modes, remove it.
256 if ( !do_recover
&& ( alockt
^ quick
)) {
258 rc
= bdb
->bi_dbenv
->remove( bdb
->bi_dbenv
, dbhome
, DB_FORCE
);
260 Debug( LDAP_DEBUG_ANY
,
261 LDAP_XSTRING(bdb_db_open
) ": database \"%s\": "
262 "dbenv remove failed: %s (%d).\n",
263 be
->be_suffix
[0].bv_val
, db_strerror(rc
), rc
);
264 bdb
->bi_dbenv
= NULL
;
267 rc
= db_env_create( &bdb
->bi_dbenv
, 0 );
269 Debug( LDAP_DEBUG_ANY
,
270 LDAP_XSTRING(bdb_db_open
) ": database \"%s\": "
271 "db_env_create failed: %s (%d).\n",
272 be
->be_suffix
[0].bv_val
, db_strerror(rc
), rc
);
277 bdb
->bi_dbenv
->set_errpfx( bdb
->bi_dbenv
, be
->be_suffix
[0].bv_val
);
278 bdb
->bi_dbenv
->set_errcall( bdb
->bi_dbenv
, bdb_errcall
);
280 bdb
->bi_dbenv
->set_lk_detect( bdb
->bi_dbenv
, bdb
->bi_lock_detect
);
282 if ( !BER_BVISNULL( &bdb
->bi_db_crypt_key
)) {
283 rc
= bdb
->bi_dbenv
->set_encrypt( bdb
->bi_dbenv
, bdb
->bi_db_crypt_key
.bv_val
,
286 Debug( LDAP_DEBUG_ANY
,
287 LDAP_XSTRING(bdb_db_open
) ": database \"%s\": "
288 "dbenv set_encrypt failed: %s (%d).\n",
289 be
->be_suffix
[0].bv_val
, db_strerror(rc
), rc
);
294 /* One long-lived TXN per thread, two TXNs per write op */
295 bdb
->bi_dbenv
->set_tx_max( bdb
->bi_dbenv
, connection_pool_max
* 3 );
297 if( bdb
->bi_dbenv_xflags
!= 0 ) {
298 rc
= bdb
->bi_dbenv
->set_flags( bdb
->bi_dbenv
,
299 bdb
->bi_dbenv_xflags
, 1);
301 Debug( LDAP_DEBUG_ANY
,
302 LDAP_XSTRING(bdb_db_open
) ": database \"%s\": "
303 "dbenv_set_flags failed: %s (%d).\n",
304 be
->be_suffix
[0].bv_val
, db_strerror(rc
), rc
);
309 #define BDB_TXN_FLAGS (DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN)
311 Debug( LDAP_DEBUG_TRACE
,
312 LDAP_XSTRING(bdb_db_open
) ": database \"%s\": "
314 be
->be_suffix
[0].bv_val
, bdb
->bi_dbenv_home
, 0);
316 flags
= DB_INIT_MPOOL
| DB_CREATE
| DB_THREAD
;
319 flags
|= BDB_TXN_FLAGS
;
321 /* If a key was set, use shared memory for the BDB environment */
322 if ( bdb
->bi_shm_key
) {
323 bdb
->bi_dbenv
->set_shm_key( bdb
->bi_dbenv
, bdb
->bi_shm_key
);
324 flags
|= DB_SYSTEM_MEM
;
326 rc
= (bdb
->bi_dbenv
->open
)( bdb
->bi_dbenv
, dbhome
,
327 flags
| do_recover
, bdb
->bi_dbenv_mode
);
330 /* Regular open failed, probably a missing shm environment.
331 * Start over, do a recovery.
333 if ( !do_recover
&& bdb
->bi_shm_key
) {
334 bdb
->bi_dbenv
->close( bdb
->bi_dbenv
, 0 );
335 rc
= db_env_create( &bdb
->bi_dbenv
, 0 );
337 Debug( LDAP_DEBUG_ANY
, LDAP_XSTRING(bdb_db_open
)
338 ": database \"%s\": "
339 "shared memory env open failed, assuming stale env.\n",
340 be
->be_suffix
[0].bv_val
, 0, 0 );
344 Debug( LDAP_DEBUG_ANY
,
345 LDAP_XSTRING(bdb_db_open
) ": database \"%s\" cannot be %s, err %d. "
346 "Restore from backup!\n",
347 be
->be_suffix
[0].bv_val
, do_recover
? "recovered" : "opened", rc
);
351 if ( do_alock_recover
&& alock_recover (&bdb
->bi_alock_info
) != 0 ) {
352 Debug( LDAP_DEBUG_ANY
,
353 LDAP_XSTRING(bdb_db_open
) ": database \"%s\": alock_recover failed\n",
354 be
->be_suffix
[0].bv_val
, 0, 0 );
359 #ifdef SLAP_ZONE_ALLOC
360 if ( bdb
->bi_cache
.c_maxsize
) {
361 bdb
->bi_cache
.c_zctx
= slap_zn_mem_create(
362 SLAP_ZONE_INITSIZE
, SLAP_ZONE_MAXSIZE
,
363 SLAP_ZONE_DELTA
, SLAP_ZONE_SIZE
);
367 /* Default dncache to 2x entrycache */
368 if ( bdb
->bi_cache
.c_maxsize
&& !bdb
->bi_cache
.c_eimax
) {
369 bdb
->bi_cache
.c_eimax
= bdb
->bi_cache
.c_maxsize
* 2;
372 if ( bdb
->bi_idl_cache_max_size
) {
373 bdb
->bi_idl_tree
= NULL
;
374 bdb
->bi_idl_cache_size
= 0;
377 flags
= DB_THREAD
| bdb
->bi_db_opflags
;
379 #ifdef DB_AUTO_COMMIT
381 flags
|= DB_AUTO_COMMIT
;
384 bdb
->bi_databases
= (struct bdb_db_info
**) ch_malloc(
385 BDB_INDICES
* sizeof(struct bdb_db_info
*) );
387 /* open (and create) main database */
388 for( i
= 0; bdbi_databases
[i
].name
.bv_val
; i
++ ) {
389 struct bdb_db_info
*db
;
391 db
= (struct bdb_db_info
*) ch_calloc(1, sizeof(struct bdb_db_info
));
393 rc
= db_create( &db
->bdi_db
, bdb
->bi_dbenv
, 0 );
395 snprintf(cr
->msg
, sizeof(cr
->msg
),
396 "database \"%s\": db_create(%s) failed: %s (%d).",
397 be
->be_suffix
[0].bv_val
,
398 bdb
->bi_dbenv_home
, db_strerror(rc
), rc
);
399 Debug( LDAP_DEBUG_ANY
,
400 LDAP_XSTRING(bdb_db_open
) ": %s\n",
405 if( !BER_BVISNULL( &bdb
->bi_db_crypt_key
)) {
406 rc
= db
->bdi_db
->set_flags( db
->bdi_db
, DB_ENCRYPT
);
408 snprintf(cr
->msg
, sizeof(cr
->msg
),
409 "database \"%s\": db set_flags(DB_ENCRYPT)(%s) failed: %s (%d).",
410 be
->be_suffix
[0].bv_val
,
411 bdb
->bi_dbenv_home
, db_strerror(rc
), rc
);
412 Debug( LDAP_DEBUG_ANY
,
413 LDAP_XSTRING(bdb_db_open
) ": %s\n",
419 if( i
== BDB_ID2ENTRY
) {
420 if ( slapMode
& SLAP_TOOL_MODE
)
421 db
->bdi_db
->mpf
->set_priority( db
->bdi_db
->mpf
,
422 DB_PRIORITY_VERY_LOW
);
424 rc
= db
->bdi_db
->set_pagesize( db
->bdi_db
,
425 BDB_ID2ENTRY_PAGESIZE
);
426 if ( slapMode
& SLAP_TOOL_READMAIN
) {
432 rc
= db
->bdi_db
->set_flags( db
->bdi_db
,
433 DB_DUP
| DB_DUPSORT
);
435 if ( slapMode
& SLAP_TOOL_READONLY
) {
441 rc
= db
->bdi_db
->set_dup_compare( db
->bdi_db
,
443 if ( slapMode
& (SLAP_TOOL_READONLY
|SLAP_TOOL_READMAIN
) ) {
449 rc
= db
->bdi_db
->set_pagesize( db
->bdi_db
,
454 strcpy( path
, bdbi_databases
[i
].file
);
456 rc
= DB_OPEN( db
->bdi_db
,
458 /* bdbi_databases[i].name, */ NULL
,
459 bdbi_databases
[i
].type
,
460 bdbi_databases
[i
].flags
| flags
,
461 bdb
->bi_dbenv_mode
);
463 rc
= DB_OPEN( db
->bdi_db
,
464 bdbi_databases
[i
].file
,
465 /* bdbi_databases[i].name, */ NULL
,
466 bdbi_databases
[i
].type
,
467 bdbi_databases
[i
].flags
| flags
,
468 bdb
->bi_dbenv_mode
);
472 snprintf( cr
->msg
, sizeof(cr
->msg
), "database \"%s\": "
473 "db_open(%s/%s) failed: %s (%d).",
474 be
->be_suffix
[0].bv_val
,
475 bdb
->bi_dbenv_home
, bdbi_databases
[i
].file
,
476 db_strerror(rc
), rc
);
477 Debug( LDAP_DEBUG_ANY
,
478 LDAP_XSTRING(bdb_db_open
) ": %s\n",
480 db
->bdi_db
->close( db
->bdi_db
, 0 );
484 flags
&= ~(DB_CREATE
| DB_RDONLY
);
485 db
->bdi_name
= bdbi_databases
[i
].name
;
486 bdb
->bi_databases
[i
] = db
;
489 bdb
->bi_databases
[i
] = NULL
;
490 bdb
->bi_ndatabases
= i
;
493 rc
= bdb_last_id( be
, NULL
);
495 snprintf( cr
->msg
, sizeof(cr
->msg
), "database \"%s\": "
496 "last_id(%s) failed: %s (%d).",
497 be
->be_suffix
[0].bv_val
, bdb
->bi_dbenv_home
,
498 db_strerror(rc
), rc
);
499 Debug( LDAP_DEBUG_ANY
,
500 LDAP_XSTRING(bdb_db_open
) ": %s\n",
506 #if DB_VERSION_FULL >= 0x04060012
508 XLOCK_ID(bdb
->bi_dbenv
, &lid
);
509 __lock_getlocker(bdb
->bi_dbenv
->lk_handle
, lid
, 0, &bdb
->bi_cache
.c_locker
);
511 XLOCK_ID(bdb
->bi_dbenv
, &bdb
->bi_cache
.c_locker
);
515 entry_prealloc( bdb
->bi_cache
.c_maxsize
);
516 attr_prealloc( bdb
->bi_cache
.c_maxsize
* 20 );
518 /* setup for empty-DN contexts */
519 if ( BER_BVISEMPTY( &be
->be_nsuffix
[0] )) {
520 rc
= bdb_id2entry( be
, NULL
, 0, 0, &e
);
525 ber_dupbv( &e
->e_name
, (struct berval
*)&slap_empty_bv
);
526 ber_dupbv( &e
->e_nname
, (struct berval
*)&slap_empty_bv
);
528 e
->e_ocflags
= SLAP_OC_GLUE
|SLAP_OC__END
;
529 e
->e_private
= &bdb
->bi_cache
.c_dntree
;
530 bdb
->bi_cache
.c_dntree
.bei_e
= e
;
533 rc
= bdb_monitor_db_open( be
);
538 bdb
->bi_flags
|= BDB_IS_OPEN
;
543 bdb_db_close( be
, NULL
);
548 bdb_db_close( BackendDB
*be
, ConfigReply
*cr
)
551 struct bdb_info
*bdb
= (struct bdb_info
*) be
->be_private
;
552 struct bdb_db_info
*db
;
553 bdb_idl_cache_entry_t
*entry
, *next_entry
;
555 /* monitor handling */
556 (void)bdb_monitor_db_close( be
);
559 Entry
*e
= bdb
->bi_cache
.c_dntree
.bei_e
;
561 bdb
->bi_cache
.c_dntree
.bei_e
= NULL
;
563 bdb_entry_return( e
);
567 bdb
->bi_flags
&= ~BDB_IS_OPEN
;
569 ber_bvarray_free( bdb
->bi_db_config
);
570 bdb
->bi_db_config
= NULL
;
572 while( bdb
->bi_databases
&& bdb
->bi_ndatabases
-- ) {
573 db
= bdb
->bi_databases
[bdb
->bi_ndatabases
];
574 rc
= db
->bdi_db
->close( db
->bdi_db
, 0 );
575 /* Lower numbered names are not strdup'd */
576 if( bdb
->bi_ndatabases
>= BDB_NDB
)
577 free( db
->bdi_name
.bv_val
);
580 free( bdb
->bi_databases
);
581 bdb
->bi_databases
= NULL
;
583 bdb_cache_release_all (&bdb
->bi_cache
);
585 if ( bdb
->bi_idl_cache_size
) {
586 avl_free( bdb
->bi_idl_tree
, NULL
);
587 bdb
->bi_idl_tree
= NULL
;
588 entry
= bdb
->bi_idl_lru_head
;
590 next_entry
= entry
->idl_lru_next
;
593 free( entry
->kstr
.bv_val
);
596 } while ( entry
!= bdb
->bi_idl_lru_head
);
597 bdb
->bi_idl_lru_head
= bdb
->bi_idl_lru_tail
= NULL
;
600 /* close db environment */
601 if( bdb
->bi_dbenv
) {
602 /* Free cache locker if we enabled locking */
603 if ( !( slapMode
& SLAP_TOOL_QUICK
) && bdb
->bi_cache
.c_locker
) {
604 #if DB_VERSION_FULL >= 0x04060012
605 XLOCK_ID_FREE(bdb
->bi_dbenv
, bdb
->bi_cache
.c_locker
->id
);
607 XLOCK_ID_FREE(bdb
->bi_dbenv
, bdb
->bi_cache
.c_locker
);
609 bdb
->bi_cache
.c_locker
= 0;
611 #ifdef BDB_REUSE_LOCKERS
612 bdb_locker_flush( bdb
->bi_dbenv
);
614 /* force a checkpoint, but not if we were ReadOnly,
615 * and not in Quick mode since there are no transactions there.
617 if ( !( slapMode
& ( SLAP_TOOL_QUICK
|SLAP_TOOL_READONLY
))) {
618 rc
= TXN_CHECKPOINT( bdb
->bi_dbenv
, 0, 0, DB_FORCE
);
620 Debug( LDAP_DEBUG_ANY
,
621 "bdb_db_close: database \"%s\": "
622 "txn_checkpoint failed: %s (%d).\n",
623 be
->be_suffix
[0].bv_val
, db_strerror(rc
), rc
);
627 rc
= bdb
->bi_dbenv
->close( bdb
->bi_dbenv
, 0 );
628 bdb
->bi_dbenv
= NULL
;
630 Debug( LDAP_DEBUG_ANY
,
631 "bdb_db_close: database \"%s\": "
632 "close failed: %s (%d)\n",
633 be
->be_suffix
[0].bv_val
, db_strerror(rc
), rc
);
638 rc
= alock_close( &bdb
->bi_alock_info
, slapMode
& SLAP_TOOL_QUICK
);
640 Debug( LDAP_DEBUG_ANY
,
641 "bdb_db_close: database \"%s\": alock_close failed\n",
642 be
->be_suffix
[0].bv_val
, 0, 0 );
650 bdb_db_destroy( BackendDB
*be
, ConfigReply
*cr
)
652 struct bdb_info
*bdb
= (struct bdb_info
*) be
->be_private
;
654 /* monitor handling */
655 (void)bdb_monitor_db_destroy( be
);
657 if( bdb
->bi_dbenv_home
) ch_free( bdb
->bi_dbenv_home
);
658 if( bdb
->bi_db_config_path
) ch_free( bdb
->bi_db_config_path
);
660 bdb_attr_index_destroy( bdb
);
662 ldap_pvt_thread_rdwr_destroy ( &bdb
->bi_cache
.c_rwlock
);
663 ldap_pvt_thread_mutex_destroy( &bdb
->bi_cache
.c_lru_mutex
);
664 ldap_pvt_thread_mutex_destroy( &bdb
->bi_cache
.c_count_mutex
);
665 ldap_pvt_thread_mutex_destroy( &bdb
->bi_cache
.c_eifree_mutex
);
666 ldap_pvt_thread_mutex_destroy( &bdb
->bi_cache
.c_dntree
.bei_kids_mutex
);
668 ldap_pvt_thread_mutex_destroy( &bdb
->bi_modrdns_mutex
);
670 ldap_pvt_thread_mutex_destroy( &bdb
->bi_lastid_mutex
);
671 ldap_pvt_thread_mutex_destroy( &bdb
->bi_database_mutex
);
672 ldap_pvt_thread_rdwr_destroy( &bdb
->bi_idl_tree_rwlock
);
673 ldap_pvt_thread_mutex_destroy( &bdb
->bi_idl_tree_lrulock
);
676 be
->be_private
= NULL
;
687 static char *controls
[] = {
689 LDAP_CONTROL_MANAGEDSAIT
,
691 LDAP_CONTROL_PAGEDRESULTS
,
692 LDAP_CONTROL_PRE_READ
,
693 LDAP_CONTROL_POST_READ
,
694 LDAP_CONTROL_SUBENTRIES
,
695 LDAP_CONTROL_X_PERMISSIVE_MODIFY
,
697 LDAP_CONTROL_X_TXN_SPEC
,
702 /* initialize the underlying database system */
703 Debug( LDAP_DEBUG_TRACE
,
704 LDAP_XSTRING(bdb_back_initialize
) ": initialize "
705 BDB_UCTYPE
" backend\n", 0, 0, 0 );
708 SLAP_BFLAG_INCREMENT
|
709 SLAP_BFLAG_SUBENTRIES
|
711 SLAP_BFLAG_REFERRALS
;
713 bi
->bi_controls
= controls
;
715 { /* version check */
716 int major
, minor
, patch
, ver
;
717 char *version
= db_version( &major
, &minor
, &patch
);
721 /* All our stdio does an ASCII to EBCDIC conversion on
722 * the output. Strings from the BDB library are already
723 * in EBCDIC; we have to go back and forth...
725 strcpy( v2
, version
);
730 ver
= (major
<< 24) | (minor
<< 16) | patch
;
731 if( ver
!= DB_VERSION_FULL
) {
732 /* fail if a versions don't match */
733 Debug( LDAP_DEBUG_ANY
,
734 LDAP_XSTRING(bdb_back_initialize
) ": "
735 "BDB library version mismatch:"
736 " expected " DB_VERSION_STRING
","
737 " got %s\n", version
, 0, 0 );
741 Debug( LDAP_DEBUG_TRACE
, LDAP_XSTRING(bdb_back_initialize
)
742 ": %s\n", version
, 0, 0 );
745 db_env_set_func_free( ber_memfree
);
746 db_env_set_func_malloc( (db_malloc
*)ber_memalloc
);
747 db_env_set_func_realloc( (db_realloc
*)ber_memrealloc
);
749 /* This is a no-op on a NO_THREAD build. Leave the default
750 * alone so that BDB will sleep on interprocess conflicts.
752 db_env_set_func_yield( ldap_pvt_thread_yield
);
760 bi
->bi_db_init
= bdb_db_init
;
761 bi
->bi_db_config
= config_generic_wrapper
;
762 bi
->bi_db_open
= bdb_db_open
;
763 bi
->bi_db_close
= bdb_db_close
;
764 bi
->bi_db_destroy
= bdb_db_destroy
;
766 bi
->bi_op_add
= bdb_add
;
767 bi
->bi_op_bind
= bdb_bind
;
768 bi
->bi_op_compare
= bdb_compare
;
769 bi
->bi_op_delete
= bdb_delete
;
770 bi
->bi_op_modify
= bdb_modify
;
771 bi
->bi_op_modrdn
= bdb_modrdn
;
772 bi
->bi_op_search
= bdb_search
;
774 bi
->bi_op_unbind
= 0;
776 bi
->bi_extended
= bdb_extended
;
778 bi
->bi_chk_referrals
= bdb_referrals
;
779 bi
->bi_operational
= bdb_operational
;
780 bi
->bi_has_subordinates
= bdb_hasSubordinates
;
781 bi
->bi_entry_release_rw
= bdb_entry_release
;
782 bi
->bi_entry_get_rw
= bdb_entry_get
;
785 * hooks for slap tools
787 bi
->bi_tool_entry_open
= bdb_tool_entry_open
;
788 bi
->bi_tool_entry_close
= bdb_tool_entry_close
;
789 bi
->bi_tool_entry_first
= bdb_tool_entry_next
;
790 bi
->bi_tool_entry_next
= bdb_tool_entry_next
;
791 bi
->bi_tool_entry_get
= bdb_tool_entry_get
;
792 bi
->bi_tool_entry_put
= bdb_tool_entry_put
;
793 bi
->bi_tool_entry_reindex
= bdb_tool_entry_reindex
;
794 bi
->bi_tool_sync
= 0;
795 bi
->bi_tool_dn2id_get
= bdb_tool_dn2id_get
;
796 bi
->bi_tool_entry_modify
= bdb_tool_entry_modify
;
798 bi
->bi_connection_init
= 0;
799 bi
->bi_connection_destroy
= 0;
801 rc
= bdb_back_init_cf( bi
);
806 #if (SLAPD_BDB == SLAPD_MOD_DYNAMIC && !defined(BDB_HIER)) || \
807 (SLAPD_HDB == SLAPD_MOD_DYNAMIC && defined(BDB_HIER))
809 /* conditionally define the init_module() function */
811 SLAP_BACKEND_INIT_MODULE( hdb
)
812 #else /* !BDB_HIER */
813 SLAP_BACKEND_INIT_MODULE( bdb
)
814 #endif /* !BDB_HIER */
816 #endif /* SLAPD_[BH]DB == SLAPD_MOD_DYNAMIC */