init.c 16.8 KB
Newer Older
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1
2
/* init.c - initialize bdb backend */
/* $OpenLDAP$ */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
3
4
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 *
Kurt Zeilenga's avatar
Kurt Zeilenga committed
5
 * Copyright 2000-2005 The OpenLDAP Foundation.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
6
7
8
9
10
11
12
13
14
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
 *
 * A copy of this license is available in the file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * <http://www.OpenLDAP.org/license.html>.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
15
16
17
18
19
20
 */

#include "portable.h"

#include <stdio.h>
#include <ac/string.h>
Howard Chu's avatar
Howard Chu committed
21
22
#include <ac/unistd.h>
#include <ac/stdlib.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
23
24

#include "back-bdb.h"
Kurt Zeilenga's avatar
Kurt Zeilenga committed
25
#include "external.h"
26
#include <lutil.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
27

28
static const struct bdbi_database {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
29
30
31
32
	char *file;
	char *name;
	int type;
	int flags;
33
} bdbi_databases[] = {
34
	{ "id2entry" BDB_SUFFIX, "id2entry", DB_BTREE, 0 },
35
	{ "dn2id" BDB_SUFFIX, "dn2id", DB_BTREE, 0 },
36
	{ NULL, NULL, 0, 0 }
Kurt Zeilenga's avatar
Kurt Zeilenga committed
37
38
};

Kurt Zeilenga's avatar
Kurt Zeilenga committed
39
struct berval bdb_uuid = BER_BVNULL;
40

41
42
43
typedef void * db_malloc(size_t);
typedef void * db_realloc(void *, size_t);

44
#if 0
Kurt Zeilenga's avatar
Kurt Zeilenga committed
45
static int
Kurt Zeilenga's avatar
Kurt Zeilenga committed
46
bdb_open( BackendInfo *bi )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
47
{
48
49
50
51
52
53
	return 0;
}

static int
bdb_destroy( BackendInfo *bi )
{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
54
55
56
	return 0;
}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
57
static int
Kurt Zeilenga's avatar
Kurt Zeilenga committed
58
bdb_close( BackendInfo *bi )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
59
60
61
62
{
	/* terminate the underlying database system */
	return 0;
}
63
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
64

Kurt Zeilenga's avatar
Kurt Zeilenga committed
65
static int
66
bdb_db_init( BackendDB *be )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
67
{
68
	struct bdb_info	*bdb;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
69

Kurt Zeilenga's avatar
Kurt Zeilenga committed
70
	Debug( LDAP_DEBUG_ANY,
Howard Chu's avatar
Howard Chu committed
71
72
		LDAP_XSTRING(bdb_db_init) ": Initializing "
		BDB_UCTYPE " database\n", 0, 0, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
73

Kurt Zeilenga's avatar
Kurt Zeilenga committed
74
	/* allocate backend-database-specific stuff */
75
	bdb = (struct bdb_info *) ch_calloc( 1, sizeof(struct bdb_info) );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
76
77

	/* DBEnv parameters */
78
	bdb->bi_dbenv_home = ch_strdup( SLAPD_DEFAULT_DB_DIR );
79
	bdb->bi_dbenv_xflags = 0;
80
	bdb->bi_dbenv_mode = SLAPD_DEFAULT_DB_MODE;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
81

82
83
	bdb->bi_cache.c_maxsize = DEFAULT_CACHE_SIZE;

84
	bdb->bi_lock_detect = DB_LOCK_DEFAULT;
85
86
	bdb->bi_search_stack_depth = DEFAULT_SEARCH_STACK_DEPTH;
	bdb->bi_search_stack = NULL;
87

88
	LDAP_LIST_INIT (&bdb->bi_psearch_list);
89

90
	ldap_pvt_thread_mutex_init( &bdb->bi_database_mutex );
91
	ldap_pvt_thread_mutex_init( &bdb->bi_lastid_mutex );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
92
	ldap_pvt_thread_rdwr_init ( &bdb->bi_pslist_rwlock );
93
94
95
#ifdef BDB_HIER
	ldap_pvt_thread_mutex_init( &bdb->bi_modrdns_mutex );
#endif
96
	ldap_pvt_thread_mutex_init( &bdb->bi_cache.lru_mutex );
Howard Chu's avatar
Howard Chu committed
97
	ldap_pvt_thread_mutex_init( &bdb->bi_cache.c_dntree.bei_kids_mutex );
98
	ldap_pvt_thread_rdwr_init ( &bdb->bi_cache.c_rwlock );
99

100
	be->be_private = bdb;
101

Kurt Zeilenga's avatar
Kurt Zeilenga committed
102
103
104
	return 0;
}

105
106
107
int
bdb_bt_compare(
	DB *db, 
108
	const DBT *usrkey,
109
	const DBT *curkey )
110
{
111
112
	unsigned char *u, *c;
	int i, x;
113
114
115
116
117

	u = usrkey->data;
	c = curkey->data;

#ifdef WORDS_BIGENDIAN
118
	for( i = 0; i < (int)sizeof(ID); i++)
119
120
121
122
#else
	for( i = sizeof(ID)-1; i >= 0; i--)
#endif
	{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
123
124
		x = u[i] - c[i];
		if( x ) return x;
125
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
126

127
	return 0;
128
129
}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
130
static int
Kurt Zeilenga's avatar
Kurt Zeilenga committed
131
bdb_db_open( BackendDB *be )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
132
{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
133
	int rc, i;
134
	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
135
	u_int32_t flags;
Howard Chu's avatar
Howard Chu committed
136
137
138
#ifdef HAVE_EBCDIC
	char path[MAXPATHLEN];
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
139

140
141
142
143
144
145
146
	if ( be->be_suffix == NULL ) {
		Debug( LDAP_DEBUG_ANY,
			"bdb_db_open: need suffix\n",
			0, 0, 0 );
		return -1;
	}

147
148
	Debug( LDAP_DEBUG_ARGS,
		"bdb_db_open: %s\n",
149
		be->be_suffix[0].bv_val, 0, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
150

151
152
#ifndef BDB_MULTIPLE_SUFFIXES
	if ( be->be_suffix[1].bv_val ) {
153
154
		Debug( LDAP_DEBUG_ANY,
			"bdb_db_open: only one suffix allowed\n", 0, 0, 0 );
155
156
157
		return -1;
	}
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
158
159
	/* we should check existance of dbenv_home and db_directory */

160
	rc = db_env_create( &bdb->bi_dbenv, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
161
162
	if( rc != 0 ) {
		Debug( LDAP_DEBUG_ANY,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
163
			"bdb_db_open: db_env_create failed: %s (%d)\n",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
164
165
166
167
			db_strerror(rc), rc, 0 );
		return rc;
	}

168
	flags = DB_INIT_MPOOL | DB_THREAD | DB_CREATE
169
170
		| DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN;
	
171
172
173
174
#if 0
	/* Never do automatic recovery, must perform it manually.
	 * Otherwise restarting with gentlehup will corrupt the
	 * database.
175
176
	 */
	if( !(slapMode & SLAP_TOOL_MODE) ) flags |= DB_RECOVER;
177
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
178

179
180
181
182
183
184
	/* If a key was set, use shared memory for the BDB environment */
	if ( bdb->bi_shm_key ) {
		bdb->bi_dbenv->set_shm_key( bdb->bi_dbenv, bdb->bi_shm_key );
		flags |= DB_SYSTEM_MEM;
	}

185
	bdb->bi_dbenv->set_errpfx( bdb->bi_dbenv, be->be_suffix[0].bv_val );
186
	bdb->bi_dbenv->set_errcall( bdb->bi_dbenv, bdb_errcall );
187
	bdb->bi_dbenv->set_lk_detect( bdb->bi_dbenv, bdb->bi_lock_detect );
188

189
190
191
	/* One long-lived TXN per thread, two TXNs per write op */
	bdb->bi_dbenv->set_tx_max( bdb->bi_dbenv, connection_pool_max * 3 );

192
	if ( bdb->bi_idl_cache_max_size ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
193
		bdb->bi_idl_tree = NULL;
194
		ldap_pvt_thread_rdwr_init( &bdb->bi_idl_tree_rwlock );
195
		ldap_pvt_thread_mutex_init( &bdb->bi_idl_tree_lrulock );
196
197
198
		bdb->bi_idl_cache_size = 0;
	}

199
#ifdef BDB_SUBDIRS
200
	{
Howard Chu's avatar
Howard Chu committed
201
		char dir[MAXPATHLEN], *ptr;
202
		
Howard Chu's avatar
Howard Chu committed
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
		if (bdb->bi_dbenv_home[0] == '.') {
			/* If home is a relative path, relative subdirs
			 * are just concat'd by BDB. We don't want the
			 * path to be concat'd twice, e.g.
			 * ./test-db/./test-db/tmp
			 */
			ptr = dir;
		} else {
			ptr = lutil_strcopy( dir, bdb->bi_dbenv_home );
			*ptr++ = LDAP_DIRSEP[0];
#ifdef HAVE_EBCDIC
			__atoe( dir );
#endif
		}

		strcpy( ptr, BDB_TMP_SUBDIR );
#ifdef HAVE_EBCDIC
		__atoe( ptr );
#endif
222
		rc = bdb->bi_dbenv->set_tmp_dir( bdb->bi_dbenv, dir );
223
224
		if( rc != 0 ) {
			Debug( LDAP_DEBUG_ANY,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
225
				"bdb_db_open: set_tmp_dir(%s) failed: %s (%d)\n",
226
				dir, db_strerror(rc), rc );
227
228
			return rc;
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
229

Howard Chu's avatar
Howard Chu committed
230
231
232
233
		strcpy( ptr, BDB_LG_SUBDIR );
#ifdef HAVE_EBCDIC
		__atoe( ptr );
#endif
234
235
236
		rc = bdb->bi_dbenv->set_lg_dir( bdb->bi_dbenv, dir );
		if( rc != 0 ) {
			Debug( LDAP_DEBUG_ANY,
237
				"bdb_db_open: set_lg_dir(%s) failed: %s (%d)\n",
238
239
240
				dir, db_strerror(rc), rc );
			return rc;
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
241

Howard Chu's avatar
Howard Chu committed
242
243
244
245
		strcpy( ptr, BDB_DATA_SUBDIR );
#ifdef HAVE_EBCDIC
		__atoe( ptr );
#endif
246
247
248
		rc = bdb->bi_dbenv->set_data_dir( bdb->bi_dbenv, dir );
		if( rc != 0 ) {
			Debug( LDAP_DEBUG_ANY,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
249
				"bdb_db_open: set_data_dir(%s) failed: %s (%d)\n",
250
251
252
				dir, db_strerror(rc), rc );
			return rc;
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
253
	}
254
255
#endif

Howard Chu's avatar
Howard Chu committed
256
257
258
259
260
261
262
263
264
265
266
	if( bdb->bi_dbenv_xflags != 0 ) {
		rc = bdb->bi_dbenv->set_flags( bdb->bi_dbenv,
			bdb->bi_dbenv_xflags, 1);
		if( rc != 0 ) {
			Debug( LDAP_DEBUG_ANY,
				"bdb_db_open: dbenv_set_flags failed: %s (%d)\n",
				db_strerror(rc), rc, 0 );
			return rc;
		}
	}

267
	Debug( LDAP_DEBUG_TRACE,
268
		"bdb_db_open: dbenv_open(%s)\n",
269
		bdb->bi_dbenv_home, 0, 0);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
270

Howard Chu's avatar
Howard Chu committed
271
272
273
274
275
276
277
278
#ifdef HAVE_EBCDIC
	strcpy( path, bdb->bi_dbenv_home );
	__atoe( path );
	rc = bdb->bi_dbenv->open( bdb->bi_dbenv,
		path,
		flags,
		bdb->bi_dbenv_mode );
#else
279
280
	rc = bdb->bi_dbenv->open( bdb->bi_dbenv,
		bdb->bi_dbenv_home,
281
		flags,
282
		bdb->bi_dbenv_mode );
Howard Chu's avatar
Howard Chu committed
283
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
284
285
	if( rc != 0 ) {
		Debug( LDAP_DEBUG_ANY,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
286
			"bdb_db_open: dbenv_open failed: %s (%d)\n",
287
			db_strerror(rc), rc, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
288
289
290
		return rc;
	}

291
	flags = DB_THREAD | bdb->bi_db_opflags;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
292

293
294
295
	bdb->bi_databases = (struct bdb_db_info **) ch_malloc(
		BDB_INDICES * sizeof(struct bdb_db_info *) );

Kurt Zeilenga's avatar
Kurt Zeilenga committed
296
	/* open (and create) main database */
297
	for( i = 0; bdbi_databases[i].name; i++ ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
298
299
300
301
302
303
304
		struct bdb_db_info *db;

		db = (struct bdb_db_info *) ch_calloc(1, sizeof(struct bdb_db_info));

		rc = db_create( &db->bdi_db, bdb->bi_dbenv, 0 );
		if( rc != 0 ) {
			Debug( LDAP_DEBUG_ANY,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
305
				"bdb_db_open: db_create(%s) failed: %s (%d)\n",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
306
307
308
309
				bdb->bi_dbenv_home, db_strerror(rc), rc );
			return rc;
		}

310
311
312
		if( i == BDB_ID2ENTRY ) {
			rc = db->bdi_db->set_bt_compare( db->bdi_db,
				bdb_bt_compare );
313
314
			rc = db->bdi_db->set_pagesize( db->bdi_db,
				BDB_ID2ENTRY_PAGESIZE );
315
316
317
318
319
			if ( slapMode & SLAP_TOOL_READMAIN ) {
				flags |= DB_RDONLY;
			} else {
				flags |= DB_CREATE;
			}
320
		} else {
321
			rc = db->bdi_db->set_flags( db->bdi_db, 
322
				DB_DUP | DB_DUPSORT );
Howard Chu's avatar
Howard Chu committed
323
#ifndef BDB_HIER
Howard Chu's avatar
Howard Chu committed
324
325
			rc = db->bdi_db->set_dup_compare( db->bdi_db,
				bdb_bt_compare );
326
327
328
329
330
			if ( slapMode & SLAP_TOOL_READONLY ) {
				flags |= DB_RDONLY;
			} else {
				flags |= DB_CREATE;
			}
Howard Chu's avatar
Howard Chu committed
331
332
#else
			rc = db->bdi_db->set_dup_compare( db->bdi_db,
333
				bdb_dup_compare );
Howard Chu's avatar
Howard Chu committed
334
335
			rc = db->bdi_db->set_bt_compare( db->bdi_db,
				bdb_bt_compare );
336
337
338
339
340
			if ( slapMode & (SLAP_TOOL_READONLY|SLAP_TOOL_READMAIN) ) {
				flags |= DB_RDONLY;
			} else {
				flags |= DB_CREATE;
			}
Howard Chu's avatar
Howard Chu committed
341
#endif
342
343
344
345
			rc = db->bdi_db->set_pagesize( db->bdi_db,
				BDB_PAGESIZE );
		}

Howard Chu's avatar
Howard Chu committed
346
347
348
#ifdef HAVE_EBCDIC
		strcpy( path, bdbi_databases[i].file );
		__atoe( path );
349
		rc = DB_OPEN( db->bdi_db,
Howard Chu's avatar
Howard Chu committed
350
351
352
			path,
		/*	bdbi_databases[i].name, */ NULL,
			bdbi_databases[i].type,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
353
			bdbi_databases[i].flags | flags,
Howard Chu's avatar
Howard Chu committed
354
355
			bdb->bi_dbenv_mode );
#else
356
		rc = DB_OPEN( db->bdi_db,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
357
			bdbi_databases[i].file,
358
		/*	bdbi_databases[i].name, */ NULL,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
359
			bdbi_databases[i].type,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
360
			bdbi_databases[i].flags | flags,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
361
			bdb->bi_dbenv_mode );
Howard Chu's avatar
Howard Chu committed
362
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
363
364
365

		if( rc != 0 ) {
			Debug( LDAP_DEBUG_ANY,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
366
				"bdb_db_open: db_open(%s) failed: %s (%d)\n",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
367
368
369
				bdb->bi_dbenv_home, db_strerror(rc), rc );
			return rc;
		}
370

371
		flags &= ~(DB_CREATE | DB_RDONLY);
372
		db->bdi_name = bdbi_databases[i].name;
373
		bdb->bi_databases[i] = db;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
374
375
	}

376
377
378
	bdb->bi_databases[i] = NULL;
	bdb->bi_ndatabases = i;

Kurt Zeilenga's avatar
Kurt Zeilenga committed
379
380
381
382
383
384
385
386
387
	/* get nextid */
	rc = bdb_last_id( be, NULL );
	if( rc != 0 ) {
		Debug( LDAP_DEBUG_ANY,
			"bdb_db_open: last_id(%s) failed: %s (%d)\n",
			bdb->bi_dbenv_home, db_strerror(rc), rc );
		return rc;
	}

388
	XLOCK_ID(bdb->bi_dbenv, &bdb->bi_cache.c_locker);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
389

Kurt Zeilenga's avatar
Kurt Zeilenga committed
390
	/* <insert> open (and create) index databases */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
391
392
393
	return 0;
}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
394
static int
Kurt Zeilenga's avatar
Kurt Zeilenga committed
395
bdb_db_close( BackendDB *be )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
396
397
{
	int rc;
398
	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
Howard Chu's avatar
Howard Chu committed
399
	struct bdb_db_info *db;
400
	bdb_idl_cache_entry_t *entry, *next_entry;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
401

Kurt Zeilenga's avatar
Kurt Zeilenga committed
402
	while( bdb->bi_ndatabases-- ) {
Howard Chu's avatar
Howard Chu committed
403
404
		db = bdb->bi_databases[bdb->bi_ndatabases];
		rc = db->bdi_db->close( db->bdi_db, 0 );
405
406
		/* Lower numbered names are not strdup'd */
		if( bdb->bi_ndatabases >= BDB_NDB )
Howard Chu's avatar
Howard Chu committed
407
408
			free( db->bdi_name );
		free( db );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
409
	}
Howard Chu's avatar
Howard Chu committed
410
411
	free( bdb->bi_databases );
	bdb_attr_index_destroy( bdb->bi_attrs );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
412

413
414
	bdb_cache_release_all (&bdb->bi_cache);

415
416
	if ( bdb->bi_idl_cache_max_size ) {
		ldap_pvt_thread_rdwr_wlock ( &bdb->bi_idl_tree_rwlock );
417
		avl_free( bdb->bi_idl_tree, NULL );
418
419
420
		entry = bdb->bi_idl_lru_head;
		while ( entry != NULL ) {
			next_entry = entry->idl_lru_next;
421
422
			if ( entry->idl )
				free( entry->idl );
423
424
425
426
427
			free( entry->kstr.bv_val );
			free( entry );
			entry = next_entry;
		}
		ldap_pvt_thread_rdwr_wunlock ( &bdb->bi_idl_tree_rwlock );
428
	}
429

430
431
432
	if ( bdb->bi_dbenv ) {
		XLOCK_ID_FREE(bdb->bi_dbenv, bdb->bi_cache.c_locker);
	}
433

Kurt Zeilenga's avatar
Kurt Zeilenga committed
434
435
436
437
	return 0;
}

static int
Kurt Zeilenga's avatar
Kurt Zeilenga committed
438
bdb_db_destroy( BackendDB *be )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
439
440
441
{
	int rc;
	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
442
443
444
	Operation *ps = NULL;
	Operation *psn = NULL;
	void *saved_tmpmemctx = NULL;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
445

446
	/* close db environment */
447
	if( bdb->bi_dbenv ) {
Howard Chu's avatar
Howard Chu committed
448
449
450
451
452
453
454
455
		/* force a checkpoint, but not if we were ReadOnly. */
		if ( !( slapMode & SLAP_TOOL_READONLY )) {
			rc = TXN_CHECKPOINT( bdb->bi_dbenv, 0, 0, DB_FORCE );
			if( rc != 0 ) {
				Debug( LDAP_DEBUG_ANY,
					"bdb_db_destroy: txn_checkpoint failed: %s (%d)\n",
					db_strerror(rc), rc, 0 );
			}
456
457
		}

458
459
460
461
462
463
464
465
		rc = bdb->bi_dbenv->close( bdb->bi_dbenv, 0 );
		bdb->bi_dbenv = NULL;
		if( rc != 0 ) {
			Debug( LDAP_DEBUG_ANY,
				"bdb_db_destroy: close failed: %s (%d)\n",
				db_strerror(rc), rc, 0 );
			return rc;
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
466
467
	}

Howard Chu's avatar
Howard Chu committed
468
469
	if( bdb->bi_dbenv_home ) ch_free( bdb->bi_dbenv_home );

470
471
	ldap_pvt_thread_rdwr_destroy ( &bdb->bi_cache.c_rwlock );
	ldap_pvt_thread_mutex_destroy( &bdb->bi_cache.lru_mutex );
Howard Chu's avatar
Howard Chu committed
472
	ldap_pvt_thread_mutex_destroy( &bdb->bi_cache.c_dntree.bei_kids_mutex );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
473
	ldap_pvt_thread_rdwr_destroy ( &bdb->bi_pslist_rwlock );
474
475
476
#ifdef BDB_HIER
	ldap_pvt_thread_mutex_destroy( &bdb->bi_modrdns_mutex );
#endif
477
	ldap_pvt_thread_mutex_destroy( &bdb->bi_lastid_mutex );
478
	ldap_pvt_thread_mutex_destroy( &bdb->bi_database_mutex );
Howard Chu's avatar
Howard Chu committed
479
480
481
482
	if ( bdb->bi_idl_cache_max_size ) {
		ldap_pvt_thread_rdwr_destroy( &bdb->bi_idl_tree_rwlock );
		ldap_pvt_thread_mutex_destroy( &bdb->bi_idl_tree_lrulock );
	}
483

484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
	ps = LDAP_LIST_FIRST( &bdb->bi_psearch_list );

	if ( ps ) {
		psn = LDAP_LIST_NEXT( ps, o_ps_link );
		if ( ps->o_savmemctx ) {
			ps->o_tmpmemctx = ps->o_savmemctx;
			ps->o_tmpmfuncs = &sl_mfuncs;
			ber_set_option(ps->o_ber, LBER_OPT_BER_MEMCTX, &ps->o_savmemctx);
		}
		saved_tmpmemctx = ps->o_tmpmemctx;

		if (!BER_BVISNULL(&ps->o_req_dn)) {
			slap_sl_free( ps->o_req_dn.bv_val, ps->o_tmpmemctx);
		}
		if (!BER_BVISNULL(&ps->o_req_ndn)) {
			slap_sl_free( ps->o_req_ndn.bv_val, ps->o_tmpmemctx);
		}
		if (!BER_BVISNULL(&ps->ors_filterstr)) {
			slap_sl_free( ps->ors_filterstr.bv_val, ps->o_tmpmemctx);
		}
		if (ps->ors_filter != NULL) {
			filter_free_x( ps, ps->ors_filter );
		}
		if (ps->ors_attrs != NULL) {
			ps->o_tmpfree(ps->ors_attrs, ps->o_tmpmemctx);
		}

		slap_op_free( ps );

		if ( saved_tmpmemctx ) {
			sl_mem_destroy( NULL, saved_tmpmemctx );
		}
	}

	while ( psn ) {
		ps = psn;
		psn = LDAP_LIST_NEXT( ps, o_ps_link );

		if ( ps->o_savmemctx ) {
			ps->o_tmpmemctx = ps->o_savmemctx;
			ps->o_tmpmfuncs = &sl_mfuncs;
			ber_set_option(ps->o_ber, LBER_OPT_BER_MEMCTX, &ps->o_savmemctx);
		}
		saved_tmpmemctx = ps->o_tmpmemctx;

		if (!BER_BVISNULL(&ps->o_req_dn)) {
			slap_sl_free( ps->o_req_dn.bv_val, ps->o_tmpmemctx);
		}
		if (!BER_BVISNULL(&ps->o_req_ndn)) {
			slap_sl_free( ps->o_req_ndn.bv_val, ps->o_tmpmemctx);
		}
		if (!BER_BVISNULL(&ps->ors_filterstr)) {
			slap_sl_free( ps->ors_filterstr.bv_val, ps->o_tmpmemctx);
		}
		if (ps->ors_filter != NULL) {
			filter_free_x( ps, ps->ors_filter );
		}
		if (ps->ors_attrs != NULL) {
			ps->o_tmpfree(ps->ors_attrs, ps->o_tmpmemctx);
		}

		slap_op_free( ps );

		if ( saved_tmpmemctx ) {
			sl_mem_destroy( NULL, saved_tmpmemctx );
		}
	}

Howard Chu's avatar
Howard Chu committed
552
553
554
	ch_free( bdb );
	be->be_private = NULL;

Kurt Zeilenga's avatar
Kurt Zeilenga committed
555
556
	return 0;
}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
557

Kurt Zeilenga's avatar
Kurt Zeilenga committed
558
559
#if	(SLAPD_BDB == SLAPD_MOD_DYNAMIC && !defined(BDB_HIER)) || \
	(SLAPD_HDB == SLAPD_MOD_DYNAMIC && defined(BDB_HIER))
Kurt Zeilenga's avatar
Kurt Zeilenga committed
560
int init_module( int argc, char *argv[] ) {
561
	BackendInfo bi;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
562

563
	memset( &bi, '\0', sizeof(bi) );
564
565
566
#ifdef BDB_HIER
	bi.bi_type = "hdb";
#else
567
	bi.bi_type = "bdb";
568
#endif
569
	bi.bi_init = bdb_initialize;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
570

571
572
	backend_add( &bi );
	return 0;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
573
}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
574
#endif /* SLAPD_BDB */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
575
576

int
Kurt Zeilenga's avatar
Kurt Zeilenga committed
577
bdb_initialize(
578
	BackendInfo	*bi )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
579
{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
580
	static char *controls[] = {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
581
		LDAP_CONTROL_ASSERT,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
582
583
		LDAP_CONTROL_MANAGEDSAIT,
		LDAP_CONTROL_NOOP,
584
585
586
		LDAP_CONTROL_PAGEDRESULTS,
#ifdef LDAP_CONTROL_SUBENTRIES
		LDAP_CONTROL_SUBENTRIES,
587
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
588
 		LDAP_CONTROL_VALUESRETURNFILTER,
589
590
591
#ifdef LDAP_CONTROL_X_PERMISSIVE_MODIFY
		LDAP_CONTROL_X_PERMISSIVE_MODIFY,
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
592
593
594
595
		NULL
	};

	/* initialize the underlying database system */
Howard Chu's avatar
Howard Chu committed
596
597
598
	Debug( LDAP_DEBUG_TRACE,
		LDAP_XSTRING(bdb_back_initialize) ": initialize " 
		BDB_UCTYPE " backend\n", 0, 0, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
599

600
601
602
603
604
605
606
607
608
609
	bi->bi_flags |=
		SLAP_BFLAG_INCREMENT |
#ifdef BDB_SUBENTRIES
		SLAP_BFLAG_SUBENTRIES |
#endif
		SLAP_BFLAG_ALIASES |
		SLAP_BFLAG_REFERRALS;

	bi->bi_controls = controls;

Kurt Zeilenga's avatar
Kurt Zeilenga committed
610
	{	/* version check */
611
		int major, minor, patch, ver;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
612
		char *version = db_version( &major, &minor, &patch );
Howard Chu's avatar
Howard Chu committed
613
614
615
616
617
618
619
620
621
622
623
#ifdef HAVE_EBCDIC
		char v2[1024];

		/* All our stdio does an ASCII to EBCDIC conversion on
		 * the output. Strings from the BDB library are already
		 * in EBCDIC; we have to go back and forth...
		 */
		strcpy( v2, version );
		__etoa( v2 );
		version = v2;
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
624

625
626
		ver = (major << 24) | (minor << 16) | patch;
		if( ver < DB_VERSION_FULL )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
627
628
		{
			Debug( LDAP_DEBUG_ANY,
Howard Chu's avatar
Howard Chu committed
629
630
				LDAP_XSTRING(bdb_back_initialize) ": "
				"BDB library version mismatch:"
Kurt Zeilenga's avatar
Kurt Zeilenga committed
631
632
				" expected " DB_VERSION_STRING ","
				" got %s\n", version, 0, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
633
634
		}

Howard Chu's avatar
Howard Chu committed
635
		Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_back_initialize)
Howard Chu's avatar
Howard Chu committed
636
			": %s\n", version, 0, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
637
638
	}

Howard Chu's avatar
Howard Chu committed
639
640
641
	db_env_set_func_free( ber_memfree );
	db_env_set_func_malloc( (db_malloc *)ber_memalloc );
	db_env_set_func_realloc( (db_realloc *)ber_memrealloc );
642
643
644
645
#ifndef NO_THREAD
	/* This is a no-op on a NO_THREAD build. Leave the default
	 * alone so that BDB will sleep on interprocess conflicts.
	 */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
646
	db_env_set_func_yield( ldap_pvt_thread_yield );
647
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
648
649

	{
650
		static char uuidbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE ];
Kurt Zeilenga's avatar
Kurt Zeilenga committed
651
652
653
654
655
656

		bdb_uuid.bv_len = lutil_uuidstr( uuidbuf, sizeof( uuidbuf ));
		bdb_uuid.bv_val = uuidbuf;
	}

	bi->bi_open = 0;
657
	bi->bi_close = 0;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
658
	bi->bi_config = 0;
659
	bi->bi_destroy = 0;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
660

Kurt Zeilenga's avatar
Kurt Zeilenga committed
661
	bi->bi_db_init = bdb_db_init;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
662
	bi->bi_db_config = bdb_db_config;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
663
664
665
	bi->bi_db_open = bdb_db_open;
	bi->bi_db_close = bdb_db_close;
	bi->bi_db_destroy = bdb_db_destroy;
666

Kurt Zeilenga's avatar
Kurt Zeilenga committed
667
	bi->bi_op_add = bdb_add;
668
	bi->bi_op_bind = bdb_bind;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
669
670
	bi->bi_op_compare = bdb_compare;
	bi->bi_op_delete = bdb_delete;
671
672
	bi->bi_op_modify = bdb_modify;
	bi->bi_op_modrdn = bdb_modrdn;
673
674
	bi->bi_op_search = bdb_search;

Howard Chu's avatar
Howard Chu committed
675
	bi->bi_op_unbind = 0;
676
677

	bi->bi_op_abandon = bdb_abandon;
Howard Chu's avatar
Howard Chu committed
678
	bi->bi_op_cancel = bdb_abandon;
679
680

	bi->bi_extended = bdb_extended;
Howard Chu's avatar
Howard Chu committed
681

682
	bi->bi_chk_referrals = bdb_referrals;
683
	bi->bi_operational = bdb_operational;
684
	bi->bi_has_subordinates = bdb_hasSubordinates;
685
	bi->bi_entry_release_rw = bdb_entry_release;
686
	bi->bi_entry_get_rw = bdb_entry_get;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
687
688
689
690

	/*
	 * hooks for slap tools
	 */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
691
692
693
694
695
696
	bi->bi_tool_entry_open = bdb_tool_entry_open;
	bi->bi_tool_entry_close = bdb_tool_entry_close;
	bi->bi_tool_entry_first = bdb_tool_entry_next;
	bi->bi_tool_entry_next = bdb_tool_entry_next;
	bi->bi_tool_entry_get = bdb_tool_entry_get;
	bi->bi_tool_entry_put = bdb_tool_entry_put;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
697
	bi->bi_tool_entry_reindex = bdb_tool_entry_reindex;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
698
	bi->bi_tool_sync = 0;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
699
700
701
	bi->bi_tool_dn2id_get = bdb_tool_dn2id_get;
	bi->bi_tool_id2entry_get = bdb_tool_id2entry_get;
	bi->bi_tool_entry_modify = bdb_tool_entry_modify;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
702
703
704
705
706
707

	bi->bi_connection_init = 0;
	bi->bi_connection_destroy = 0;

	return 0;
}