1 /* config.c - bdb backend configuration file routine */
2 /* $OpenLDAP: pkg/ldap/servers/slapd/back-bdb/config.c,v 1.91.2.11 2008/04/14 21:28:42 quanah 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>.
21 #include <ac/string.h>
32 # define SLAP_BDB_ALLOW_DIRTY_READ
35 #define bdb_cf_gen BDB_SYMBOL(cf_gen)
36 #define bdb_cf_cleanup BDB_SYMBOL(cf_cleanup)
37 #define bdb_checkpoint BDB_SYMBOL(checkpoint)
38 #define bdb_online_index BDB_SYMBOL(online_index)
40 static ConfigDriver bdb_cf_gen
;
55 static ConfigTable bdbcfg
[] = {
56 { "directory", "dir", 2, 2, 0, ARG_STRING
|ARG_MAGIC
|BDB_DIRECTORY
,
57 bdb_cf_gen
, "( OLcfgDbAt:0.1 NAME 'olcDbDirectory' "
58 "DESC 'Directory for database content' "
59 "EQUALITY caseIgnoreMatch "
60 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
61 { "cachefree", "size", 2, 2, 0, ARG_UINT
|ARG_OFFSET
,
62 (void *)offsetof(struct bdb_info
, bi_cache
.c_minfree
),
63 "( OLcfgDbAt:1.11 NAME 'olcDbCacheFree' "
64 "DESC 'Number of extra entries to free when max is reached' "
65 "SYNTAX OMsInteger SINGLE-VALUE )", NULL
, NULL
},
66 { "cachesize", "size", 2, 2, 0, ARG_UINT
|ARG_OFFSET
,
67 (void *)offsetof(struct bdb_info
, bi_cache
.c_maxsize
),
68 "( OLcfgDbAt:1.1 NAME 'olcDbCacheSize' "
69 "DESC 'Entry cache size in entries' "
70 "SYNTAX OMsInteger SINGLE-VALUE )", NULL
, NULL
},
71 { "checkpoint", "kbyte> <min", 3, 3, 0, ARG_MAGIC
|BDB_CHKPT
,
72 bdb_cf_gen
, "( OLcfgDbAt:1.2 NAME 'olcDbCheckpoint' "
73 "DESC 'Database checkpoint interval in kbytes and minutes' "
74 "SYNTAX OMsDirectoryString SINGLE-VALUE )",NULL
, NULL
},
75 { "cryptfile", "file", 2, 2, 0, ARG_STRING
|ARG_MAGIC
|BDB_CRYPTFILE
,
76 bdb_cf_gen
, "( OLcfgDbAt:1.13 NAME 'olcDbCryptFile' "
77 "DESC 'Pathname of file containing the DB encryption key' "
78 "SYNTAX OMsDirectoryString SINGLE-VALUE )",NULL
, NULL
},
79 { "cryptkey", "key", 2, 2, 0, ARG_BERVAL
|ARG_MAGIC
|BDB_CRYPTKEY
,
80 bdb_cf_gen
, "( OLcfgDbAt:1.14 NAME 'olcDbCryptKey' "
81 "DESC 'DB encryption key' "
82 "SYNTAX OMsOctetString SINGLE-VALUE )",NULL
, NULL
},
83 { "dbconfig", "DB_CONFIG setting", 1, 0, 0, ARG_MAGIC
|BDB_CONFIG
,
84 bdb_cf_gen
, "( OLcfgDbAt:1.3 NAME 'olcDbConfig' "
85 "DESC 'BerkeleyDB DB_CONFIG configuration directives' "
86 "SYNTAX OMsIA5String X-ORDERED 'VALUES' )", NULL
, NULL
},
87 { "dbnosync", NULL
, 1, 2, 0, ARG_ON_OFF
|ARG_MAGIC
|BDB_NOSYNC
,
88 bdb_cf_gen
, "( OLcfgDbAt:1.4 NAME 'olcDbNoSync' "
89 "DESC 'Disable synchronous database writes' "
90 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL
, NULL
},
91 { "dirtyread", NULL
, 1, 2, 0,
92 #ifdef SLAP_BDB_ALLOW_DIRTY_READ
93 ARG_ON_OFF
|ARG_MAGIC
|BDB_DIRTYR
, bdb_cf_gen
,
97 "( OLcfgDbAt:1.5 NAME 'olcDbDirtyRead' "
98 "DESC 'Allow reads of uncommitted data' "
99 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL
, NULL
},
100 { "dncachesize", "size", 2, 2, 0, ARG_UINT
|ARG_OFFSET
,
101 (void *)offsetof(struct bdb_info
, bi_cache
.c_eimax
),
102 "( OLcfgDbAt:1.12 NAME 'olcDbDNcacheSize' "
103 "DESC 'DN cache size' "
104 "SYNTAX OMsInteger SINGLE-VALUE )", NULL
, NULL
},
105 { "idlcachesize", "size", 2, 2, 0, ARG_UINT
|ARG_OFFSET
,
106 (void *)offsetof(struct bdb_info
, bi_idl_cache_max_size
),
107 "( OLcfgDbAt:1.6 NAME 'olcDbIDLcacheSize' "
108 "DESC 'IDL cache size in IDLs' "
109 "SYNTAX OMsInteger SINGLE-VALUE )", NULL
, NULL
},
110 { "index", "attr> <[pres,eq,approx,sub]", 2, 3, 0, ARG_MAGIC
|BDB_INDEX
,
111 bdb_cf_gen
, "( OLcfgDbAt:0.2 NAME 'olcDbIndex' "
112 "DESC 'Attribute index parameters' "
113 "EQUALITY caseIgnoreMatch "
114 "SYNTAX OMsDirectoryString )", NULL
, NULL
},
115 { "linearindex", NULL
, 1, 2, 0, ARG_ON_OFF
|ARG_OFFSET
,
116 (void *)offsetof(struct bdb_info
, bi_linear_index
),
117 "( OLcfgDbAt:1.7 NAME 'olcDbLinearIndex' "
118 "DESC 'Index attributes one at a time' "
119 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL
, NULL
},
120 { "lockdetect", "policy", 2, 2, 0, ARG_MAGIC
|BDB_LOCKD
,
121 bdb_cf_gen
, "( OLcfgDbAt:1.8 NAME 'olcDbLockDetect' "
122 "DESC 'Deadlock detection algorithm' "
123 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
124 { "mode", "mode", 2, 2, 0, ARG_INT
|ARG_OFFSET
,
125 (void *)offsetof(struct bdb_info
, bi_dbenv_mode
),
126 "( OLcfgDbAt:0.3 NAME 'olcDbMode' "
127 "DESC 'Unix permissions of database files' "
128 "SYNTAX OMsInteger SINGLE-VALUE )", NULL
, NULL
},
129 { "searchstack", "depth", 2, 2, 0, ARG_INT
|ARG_MAGIC
|BDB_SSTACK
,
130 bdb_cf_gen
, "( OLcfgDbAt:1.9 NAME 'olcDbSearchStack' "
131 "DESC 'Depth of search stack in IDLs' "
132 "SYNTAX OMsInteger SINGLE-VALUE )", NULL
, NULL
},
133 { "shm_key", "key", 2, 2, 0, ARG_LONG
|ARG_OFFSET
,
134 (void *)offsetof(struct bdb_info
, bi_shm_key
),
135 "( OLcfgDbAt:1.10 NAME 'olcDbShmKey' "
136 "DESC 'Key for shared memory region' "
137 "SYNTAX OMsInteger SINGLE-VALUE )", NULL
, NULL
},
138 { NULL
, NULL
, 0, 0, 0, ARG_IGNORED
,
139 NULL
, NULL
, NULL
, NULL
}
142 static ConfigOCs bdbocs
[] = {
146 "NAME 'olcHdbConfig' "
147 "DESC 'HDB backend configuration' "
150 "NAME 'olcBdbConfig' "
151 "DESC 'BDB backend configuration' "
153 "SUP olcDatabaseConfig "
154 "MUST olcDbDirectory "
155 "MAY ( olcDbCacheSize $ olcDbCheckpoint $ olcDbConfig $ "
156 "olcDbCryptFile $ olcDbCryptKey $ "
157 "olcDbNoSync $ olcDbDirtyRead $ olcDbIDLcacheSize $ "
158 "olcDbIndex $ olcDbLinearIndex $ olcDbLockDetect $ "
159 "olcDbMode $ olcDbSearchStack $ olcDbShmKey $ "
160 "olcDbCacheFree $ olcDbDNcacheSize ) )",
161 Cft_Database
, bdbcfg
},
165 static slap_verbmasks bdb_lockd
[] = {
166 { BER_BVC("default"), DB_LOCK_DEFAULT
},
167 { BER_BVC("oldest"), DB_LOCK_OLDEST
},
168 { BER_BVC("random"), DB_LOCK_RANDOM
},
169 { BER_BVC("youngest"), DB_LOCK_YOUNGEST
},
170 { BER_BVC("fewest"), DB_LOCK_MINLOCKS
},
174 /* perform periodic checkpoints */
176 bdb_checkpoint( void *ctx
, void *arg
)
178 struct re_s
*rtask
= arg
;
179 struct bdb_info
*bdb
= rtask
->arg
;
181 TXN_CHECKPOINT( bdb
->bi_dbenv
, bdb
->bi_txn_cp_kbyte
,
182 bdb
->bi_txn_cp_min
, 0 );
183 ldap_pvt_thread_mutex_lock( &slapd_rq
.rq_mutex
);
184 ldap_pvt_runqueue_stoptask( &slapd_rq
, rtask
);
185 ldap_pvt_thread_mutex_unlock( &slapd_rq
.rq_mutex
);
189 /* reindex entries on the fly */
191 bdb_online_index( void *ctx
, void *arg
)
193 struct re_s
*rtask
= arg
;
194 BackendDB
*be
= rtask
->arg
;
195 struct bdb_info
*bdb
= be
->be_private
;
197 Connection conn
= {0};
198 OperationBuffer opbuf
;
211 connection_fake_init( &conn
, &opbuf
, ctx
);
221 key
.size
= key
.ulen
= sizeof(ID
);
222 key
.flags
= DB_DBT_USERMEM
;
224 data
.flags
= DB_DBT_USERMEM
| DB_DBT_PARTIAL
;
225 data
.dlen
= data
.ulen
= 0;
228 if ( slapd_shutdown
)
231 rc
= TXN_BEGIN( bdb
->bi_dbenv
, NULL
, &txn
, bdb
->bi_db_opflags
);
234 locker
= TXN_ID( txn
);
237 BDB_ID2DISK( id
, &nid
);
238 rc
= bdb
->bi_id2entry
->bdi_db
->cursor(
239 bdb
->bi_id2entry
->bdi_db
, txn
, &curs
, bdb
->bi_db_opflags
);
244 rc
= curs
->c_get( curs
, &key
, &data
, DB_SET_RANGE
);
245 curs
->c_close( curs
);
248 if ( rc
== DB_NOTFOUND
)
250 if ( rc
== DB_LOCK_DEADLOCK
) {
251 ldap_pvt_thread_yield();
256 BDB_DISK2ID( &nid
, &id
);
260 rc
= bdb_cache_find_id( op
, txn
, id
, &ei
, 0, locker
, &lock
);
263 if ( rc
== DB_LOCK_DEADLOCK
) {
264 ldap_pvt_thread_yield();
267 if ( rc
== DB_NOTFOUND
) {
275 rc
= bdb_index_entry( op
, txn
, BDB_INDEX_UPDATE_OP
, ei
->bei_e
);
276 if ( rc
== DB_LOCK_DEADLOCK
) {
278 ldap_pvt_thread_yield();
282 rc
= TXN_COMMIT( txn
, 0 );
292 for ( i
= 0; i
< bdb
->bi_nattrs
; i
++ ) {
293 if ( bdb
->bi_attrs
[ i
]->ai_indexmask
& BDB_INDEX_DELETING
294 || bdb
->bi_attrs
[ i
]->ai_newmask
== 0 )
298 bdb
->bi_attrs
[ i
]->ai_indexmask
= bdb
->bi_attrs
[ i
]->ai_newmask
;
299 bdb
->bi_attrs
[ i
]->ai_newmask
= 0;
302 ldap_pvt_thread_mutex_lock( &slapd_rq
.rq_mutex
);
303 ldap_pvt_runqueue_stoptask( &slapd_rq
, rtask
);
304 bdb
->bi_index_task
= NULL
;
305 ldap_pvt_runqueue_remove( &slapd_rq
, rtask
);
306 ldap_pvt_thread_mutex_unlock( &slapd_rq
.rq_mutex
);
311 /* Cleanup loose ends after Modify completes */
313 bdb_cf_cleanup( ConfigArgs
*c
)
315 struct bdb_info
*bdb
= c
->be
->be_private
;
318 if ( bdb
->bi_flags
& BDB_UPD_CONFIG
) {
319 if ( bdb
->bi_db_config
) {
321 FILE *f
= fopen( bdb
->bi_db_config_path
, "w" );
323 for (i
=0; bdb
->bi_db_config
[i
].bv_val
; i
++)
324 fprintf( f
, "%s\n", bdb
->bi_db_config
[i
].bv_val
);
328 unlink( bdb
->bi_db_config_path
);
330 bdb
->bi_flags
^= BDB_UPD_CONFIG
;
333 if ( bdb
->bi_flags
& BDB_DEL_INDEX
) {
334 bdb_attr_flush( bdb
);
335 bdb
->bi_flags
^= BDB_DEL_INDEX
;
338 if ( bdb
->bi_flags
& BDB_RE_OPEN
) {
339 bdb
->bi_flags
^= BDB_RE_OPEN
;
340 rc
= c
->be
->bd_info
->bi_db_close( c
->be
, &c
->reply
);
342 rc
= c
->be
->bd_info
->bi_db_open( c
->be
, &c
->reply
);
343 /* If this fails, we need to restart */
346 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
),
347 "failed to reopen database, rc=%d", rc
);
348 Debug( LDAP_DEBUG_ANY
, LDAP_XSTRING(bdb_cf_cleanup
)
349 ": %s\n", c
->cr_msg
, 0, 0 );
357 bdb_cf_gen( ConfigArgs
*c
)
359 struct bdb_info
*bdb
= c
->be
->be_private
;
362 if ( c
->op
== SLAP_CONFIG_EMIT
) {
366 if ( bdb
->bi_txn_cp
) {
369 bv
.bv_len
= sprintf( buf
, "%d %d", bdb
->bi_txn_cp_kbyte
,
370 bdb
->bi_txn_cp_min
);
372 value_add_one( &c
->rvalue_vals
, &bv
);
379 if ( bdb
->bi_db_crypt_file
) {
380 c
->value_string
= ch_strdup( bdb
->bi_db_crypt_file
);
386 /* If a crypt file has been set, its contents are copied here.
387 * But we don't want the key to be incorporated here.
390 if ( !bdb
->bi_db_crypt_file
&& !BER_BVISNULL( &bdb
->bi_db_crypt_key
)) {
391 value_add_one( &c
->rvalue_vals
, &bdb
->bi_db_crypt_key
);
398 if ( bdb
->bi_dbenv_home
) {
399 c
->value_string
= ch_strdup( bdb
->bi_dbenv_home
);
406 if ( !( bdb
->bi_flags
& BDB_IS_OPEN
)
407 && !bdb
->bi_db_config
)
409 char buf
[SLAP_TEXT_BUFLEN
];
410 FILE *f
= fopen( bdb
->bi_db_config_path
, "r" );
414 bdb
->bi_flags
|= BDB_HAS_CONFIG
;
415 while ( fgets( buf
, sizeof(buf
), f
)) {
416 ber_str2bv( buf
, 0, 1, &bv
);
417 if ( bv
.bv_len
> 0 && bv
.bv_val
[bv
.bv_len
-1] == '\n' ) {
419 bv
.bv_val
[bv
.bv_len
] = '\0';
421 /* shouldn't need this, but ... */
422 if ( bv
.bv_len
> 0 && bv
.bv_val
[bv
.bv_len
-1] == '\r' ) {
424 bv
.bv_val
[bv
.bv_len
] = '\0';
426 ber_bvarray_add( &bdb
->bi_db_config
, &bv
);
431 if ( bdb
->bi_db_config
) {
436 for (i
=0; !BER_BVISNULL(&bdb
->bi_db_config
[i
]); i
++) {
437 bv
.bv_len
= sprintf( bv
.bv_val
, "{%d}%s", i
,
438 bdb
->bi_db_config
[i
].bv_val
);
439 value_add_one( &c
->rvalue_vals
, &bv
);
442 if ( !c
->rvalue_vals
) rc
= 1;
446 if ( bdb
->bi_dbenv_xflags
& DB_TXN_NOSYNC
)
451 bdb_attr_index_unparse( bdb
, &c
->rvalue_vals
);
452 if ( !c
->rvalue_vals
) rc
= 1;
457 if ( bdb
->bi_lock_detect
!= DB_LOCK_DEFAULT
) {
459 for (i
=0; !BER_BVISNULL(&bdb_lockd
[i
].word
); i
++) {
460 if ( bdb
->bi_lock_detect
== bdb_lockd
[i
].mask
) {
461 value_add_one( &c
->rvalue_vals
, &bdb_lockd
[i
].word
);
470 c
->value_int
= bdb
->bi_search_stack_depth
;
474 } else if ( c
->op
== LDAP_MOD_DELETE
) {
477 /* single-valued no-ops */
483 if ( bdb
->bi_txn_cp_task
) {
484 struct re_s
*re
= bdb
->bi_txn_cp_task
;
485 bdb
->bi_txn_cp_task
= NULL
;
486 ldap_pvt_thread_mutex_lock( &slapd_rq
.rq_mutex
);
487 if ( ldap_pvt_runqueue_isrunning( &slapd_rq
, re
) )
488 ldap_pvt_runqueue_stoptask( &slapd_rq
, re
);
489 ldap_pvt_runqueue_remove( &slapd_rq
, re
);
490 ldap_pvt_thread_mutex_unlock( &slapd_rq
.rq_mutex
);
496 ber_bvarray_free( bdb
->bi_db_config
);
497 bdb
->bi_db_config
= NULL
;
500 ch_free( bdb
->bi_db_config
[i
].bv_val
);
501 for (; bdb
->bi_db_config
[i
].bv_val
; i
++)
502 bdb
->bi_db_config
[i
] = bdb
->bi_db_config
[i
+1];
504 bdb
->bi_flags
|= BDB_UPD_CONFIG
;
505 c
->cleanup
= bdb_cf_cleanup
;
507 /* Doesn't really make sense to change these on the fly;
508 * the entire DB must be dumped and reloaded
511 if ( bdb
->bi_db_crypt_file
) {
512 ch_free( bdb
->bi_db_crypt_file
);
513 bdb
->bi_db_crypt_file
= NULL
;
517 if ( !BER_BVISNULL( &bdb
->bi_db_crypt_key
)) {
518 ch_free( bdb
->bi_db_crypt_key
.bv_val
);
519 BER_BVZERO( &bdb
->bi_db_crypt_key
);
523 bdb
->bi_flags
|= BDB_RE_OPEN
;
524 bdb
->bi_flags
^= BDB_HAS_CONFIG
;
525 ch_free( bdb
->bi_dbenv_home
);
526 bdb
->bi_dbenv_home
= NULL
;
527 ch_free( bdb
->bi_db_config_path
);
528 bdb
->bi_db_config_path
= NULL
;
529 c
->cleanup
= bdb_cf_cleanup
;
530 ldap_pvt_thread_pool_purgekey( bdb
->bi_dbenv
);
533 bdb
->bi_dbenv
->set_flags( bdb
->bi_dbenv
, DB_TXN_NOSYNC
, 0 );
536 if ( c
->valx
== -1 ) {
539 /* delete all (FIXME) */
540 for ( i
= 0; i
< bdb
->bi_nattrs
; i
++ ) {
541 bdb
->bi_attrs
[i
]->ai_indexmask
|= BDB_INDEX_DELETING
;
543 bdb
->bi_flags
|= BDB_DEL_INDEX
;
544 c
->cleanup
= bdb_cf_cleanup
;
547 struct berval bv
, def
= BER_BVC("default");
550 for (ptr
= c
->line
; !isspace( (unsigned char) *ptr
); ptr
++);
553 bv
.bv_len
= ptr
- bv
.bv_val
;
554 if ( bvmatch( &bv
, &def
)) {
555 bdb
->bi_defaultmask
= 0;
562 sep
= bv
.bv_val
[ bv
.bv_len
];
563 bv
.bv_val
[ bv
.bv_len
] = '\0';
564 attrs
= ldap_str2charray( bv
.bv_val
, "," );
566 for ( i
= 0; attrs
[ i
]; i
++ ) {
567 AttributeDescription
*ad
= NULL
;
571 slap_str2ad( attrs
[ i
], &ad
, &text
);
572 /* if we got here... */
573 assert( ad
!= NULL
);
575 ai
= bdb_attr_mask( bdb
, ad
);
576 /* if we got here... */
577 assert( ai
!= NULL
);
579 ai
->ai_indexmask
|= BDB_INDEX_DELETING
;
580 bdb
->bi_flags
|= BDB_DEL_INDEX
;
581 c
->cleanup
= bdb_cf_cleanup
;
584 bv
.bv_val
[ bv
.bv_len
] = sep
;
585 ldap_charray_free( attrs
);
597 if ( lutil_atolx( &l
, c
->argv
[1], 0 ) != 0 ) {
598 fprintf( stderr
, "%s: "
599 "invalid kbyte \"%s\" in \"checkpoint\".\n",
600 c
->log
, c
->argv
[1] );
603 bdb
->bi_txn_cp_kbyte
= l
;
604 if ( lutil_atolx( &l
, c
->argv
[2], 0 ) != 0 ) {
605 fprintf( stderr
, "%s: "
606 "invalid minutes \"%s\" in \"checkpoint\".\n",
607 c
->log
, c
->argv
[2] );
610 bdb
->bi_txn_cp_min
= l
;
611 /* If we're in server mode and time-based checkpointing is enabled,
612 * submit a task to perform periodic checkpoints.
614 if ((slapMode
& SLAP_SERVER_MODE
) && bdb
->bi_txn_cp_min
) {
615 struct re_s
*re
= bdb
->bi_txn_cp_task
;
617 re
->interval
.tv_sec
= bdb
->bi_txn_cp_min
* 60;
619 if ( c
->be
->be_suffix
== NULL
|| BER_BVISNULL( &c
->be
->be_suffix
[0] ) ) {
620 fprintf( stderr
, "%s: "
621 "\"checkpoint\" must occur after \"suffix\".\n",
625 ldap_pvt_thread_mutex_lock( &slapd_rq
.rq_mutex
);
626 bdb
->bi_txn_cp_task
= ldap_pvt_runqueue_insert( &slapd_rq
,
627 bdb
->bi_txn_cp_min
* 60, bdb_checkpoint
, bdb
,
628 LDAP_XSTRING(bdb_checkpoint
), c
->be
->be_suffix
[0].bv_val
);
629 ldap_pvt_thread_mutex_unlock( &slapd_rq
.rq_mutex
);
638 if ( c
->op
== SLAP_CONFIG_ADD
) {
639 ptr
+= STRLENOF("dbconfig");
640 while (!isspace((unsigned char)*ptr
)) ptr
++;
641 while (isspace((unsigned char)*ptr
)) ptr
++;
644 if ( bdb
->bi_flags
& BDB_IS_OPEN
) {
645 bdb
->bi_flags
|= BDB_UPD_CONFIG
;
646 c
->cleanup
= bdb_cf_cleanup
;
648 /* If we're just starting up...
651 /* If a DB_CONFIG file exists, or we don't know the path
652 * to the DB_CONFIG file, ignore these directives
654 if (( bdb
->bi_flags
& BDB_HAS_CONFIG
) || !bdb
->bi_db_config_path
)
656 f
= fopen( bdb
->bi_db_config_path
, "a" );
658 /* FIXME: EBCDIC probably needs special handling */
659 fprintf( f
, "%s\n", ptr
);
663 ber_str2bv( ptr
, 0, 1, &bv
);
664 ber_bvarray_add( &bdb
->bi_db_config
, &bv
);
669 rc
= lutil_get_filed_password( c
->value_string
, &bdb
->bi_db_crypt_key
);
671 bdb
->bi_db_crypt_file
= c
->value_string
;
675 /* Cannot set key if file was already set */
677 if ( bdb
->bi_db_crypt_file
) {
680 bdb
->bi_db_crypt_key
= c
->value_bv
;
684 case BDB_DIRECTORY
: {
686 char *ptr
, *testpath
;
689 len
= strlen( c
->value_string
);
690 testpath
= ch_malloc( len
+ STRLENOF(LDAP_DIRSEP
) + STRLENOF("DUMMY") + 1 );
691 ptr
= lutil_strcopy( testpath
, c
->value_string
);
692 *ptr
++ = LDAP_DIRSEP
[0];
693 strcpy( ptr
, "DUMMY" );
694 f
= fopen( testpath
, "w" );
701 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "%s: invalid path: %s",
702 c
->log
, strerror( errno
));
703 Debug( LDAP_DEBUG_ANY
, "%s\n", c
->cr_msg
, 0, 0 );
707 if ( bdb
->bi_dbenv_home
)
708 ch_free( bdb
->bi_dbenv_home
);
709 bdb
->bi_dbenv_home
= c
->value_string
;
711 /* See if a DB_CONFIG file already exists here */
712 if ( bdb
->bi_db_config_path
)
713 ch_free( bdb
->bi_db_config_path
);
714 bdb
->bi_db_config_path
= ch_malloc( len
+
715 STRLENOF(LDAP_DIRSEP
) + STRLENOF("DB_CONFIG") + 1 );
716 ptr
= lutil_strcopy( bdb
->bi_db_config_path
, bdb
->bi_dbenv_home
);
717 *ptr
++ = LDAP_DIRSEP
[0];
718 strcpy( ptr
, "DB_CONFIG" );
720 f
= fopen( bdb
->bi_db_config_path
, "r" );
722 bdb
->bi_flags
|= BDB_HAS_CONFIG
;
730 bdb
->bi_dbenv_xflags
|= DB_TXN_NOSYNC
;
732 bdb
->bi_dbenv_xflags
&= ~DB_TXN_NOSYNC
;
733 if ( bdb
->bi_flags
& BDB_IS_OPEN
) {
734 bdb
->bi_dbenv
->set_flags( bdb
->bi_dbenv
, DB_TXN_NOSYNC
,
740 rc
= bdb_attr_index_config( bdb
, c
->fname
, c
->lineno
,
741 c
->argc
- 1, &c
->argv
[1] );
743 if( rc
!= LDAP_SUCCESS
) return 1;
744 if (( bdb
->bi_flags
& BDB_IS_OPEN
) && !bdb
->bi_index_task
) {
745 /* Start the task as soon as we finish here. Set a long
746 * interval (10 hours) so that it only gets scheduled once.
748 if ( c
->be
->be_suffix
== NULL
|| BER_BVISNULL( &c
->be
->be_suffix
[0] ) ) {
749 fprintf( stderr
, "%s: "
750 "\"index\" must occur after \"suffix\".\n",
754 ldap_pvt_thread_mutex_lock( &slapd_rq
.rq_mutex
);
755 bdb
->bi_index_task
= ldap_pvt_runqueue_insert( &slapd_rq
, 36000,
756 bdb_online_index
, c
->be
,
757 LDAP_XSTRING(bdb_online_index
), c
->be
->be_suffix
[0].bv_val
);
758 ldap_pvt_thread_mutex_unlock( &slapd_rq
.rq_mutex
);
763 rc
= verb_to_mask( c
->argv
[1], bdb_lockd
);
764 if ( BER_BVISNULL(&bdb_lockd
[rc
].word
) ) {
765 fprintf( stderr
, "%s: "
766 "bad policy (%s) in \"lockDetect <policy>\" line\n",
767 c
->log
, c
->argv
[1] );
770 bdb
->bi_lock_detect
= rc
;
774 if ( c
->value_int
< MINIMUM_SEARCH_STACK_DEPTH
) {
776 "%s: depth %d too small, using %d\n",
777 c
->log
, c
->value_int
, MINIMUM_SEARCH_STACK_DEPTH
);
778 c
->value_int
= MINIMUM_SEARCH_STACK_DEPTH
;
780 bdb
->bi_search_stack_depth
= c
->value_int
;
786 int bdb_back_init_cf( BackendInfo
*bi
)
789 bi
->bi_cf_ocs
= bdbocs
;
791 rc
= config_register_schema( bdbcfg
, bdbocs
);