]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/init.c
cleanup bind
[openldap] / servers / slapd / back-bdb / init.c
1 /* init.c - initialize bdb backend */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11 #include <ac/string.h>
12 #include <ac/unistd.h>
13 #include <ac/stdlib.h>
14
15 #include "back-bdb.h"
16 #include "external.h"
17 #include <lutil.h>
18
19 static struct bdbi_database {
20         char *file;
21         char *name;
22         int type;
23         int flags;
24 } bdbi_databases[] = {
25         { "id2entry" BDB_SUFFIX, "id2entry", DB_BTREE, 0 },
26 #ifdef BDB_HIER
27         { "id2parent" BDB_SUFFIX, "id2parent", DB_BTREE, 0 },
28 #else
29         { "dn2id" BDB_SUFFIX, "dn2id", DB_BTREE, 0 },
30 #endif
31         { NULL, NULL, 0, 0 }
32 };
33
34 struct berval bdb_uuid = { 0, NULL };
35
36 typedef void * db_malloc(size_t);
37 typedef void * db_realloc(void *, size_t);
38
39 #if 0
40 static int
41 bdb_open( BackendInfo *bi )
42 {
43         return 0;
44 }
45
46 static int
47 bdb_destroy( BackendInfo *bi )
48 {
49         return 0;
50 }
51
52 static int
53 bdb_close( BackendInfo *bi )
54 {
55         /* terminate the underlying database system */
56         return 0;
57 }
58 #endif
59
60 static int
61 bdb_db_init( BackendDB *be )
62 {
63         struct bdb_info *bdb;
64
65 #ifdef NEW_LOGGING
66         LDAP_LOG( BACK_BDB, ENTRY, "bdb_db_init", 0, 0, 0 );
67 #else
68         Debug( LDAP_DEBUG_ANY,
69                 "bdb_db_init: Initializing BDB database\n",
70                 0, 0, 0 );
71 #endif
72
73         /* indicate system schema supported */
74         be->be_flags |=
75 #ifdef BDB_SUBENTRIES
76                 SLAP_BFLAG_SUBENTRIES |
77 #endif
78 #ifdef BDB_ALIASES
79                 SLAP_BFLAG_ALIASES |
80 #endif
81                 SLAP_BFLAG_REFERRALS;
82
83         /* allocate backend-database-specific stuff */
84         bdb = (struct bdb_info *) ch_calloc( 1, sizeof(struct bdb_info) );
85
86         /* DBEnv parameters */
87         bdb->bi_dbenv_home = ch_strdup( SLAPD_DEFAULT_DB_DIR );
88         bdb->bi_dbenv_xflags = 0;
89         bdb->bi_dbenv_mode = SLAPD_DEFAULT_DB_MODE;
90
91         bdb->bi_cache.c_maxsize = DEFAULT_CACHE_SIZE;
92
93         bdb->bi_lock_detect = DB_LOCK_DEFAULT;
94         bdb->bi_search_stack_depth = DEFAULT_SEARCH_STACK_DEPTH;
95         bdb->bi_search_stack = NULL;
96
97 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
98         LDAP_LIST_INIT (&bdb->psearch_list);
99 #endif
100
101         ldap_pvt_thread_mutex_init( &bdb->bi_database_mutex );
102         ldap_pvt_thread_mutex_init( &bdb->bi_lastid_mutex );
103         ldap_pvt_thread_mutex_init( &bdb->bi_cache.lru_mutex );
104         ldap_pvt_thread_rdwr_init ( &bdb->bi_cache.c_rwlock );
105 #ifdef BDB_HIER
106         ldap_pvt_thread_rdwr_init( &bdb->bi_tree_rdwr );
107 #endif
108
109         be->be_private = bdb;
110
111         return 0;
112 }
113
114 int
115 bdb_bt_compare(
116         DB *db, 
117         const DBT *usrkey,
118         const DBT *curkey
119 )
120 {
121         unsigned char *u, *c;
122         int i, x;
123
124         u = usrkey->data;
125         c = curkey->data;
126
127 #ifdef WORDS_BIGENDIAN
128         for( i = 0; i < (int)sizeof(ID); i++)
129 #else
130         for( i = sizeof(ID)-1; i >= 0; i--)
131 #endif
132         {
133                 x = u[i] - c[i];
134                 if( x ) return x;
135         }
136
137         return 0;
138 }
139
140 static int
141 bdb_db_open( BackendDB *be )
142 {
143         int rc, i;
144         struct bdb_info *bdb = (struct bdb_info *) be->be_private;
145         u_int32_t flags;
146 #ifdef HAVE_EBCDIC
147         char path[MAXPATHLEN];
148 #endif
149
150 #ifdef NEW_LOGGING
151         LDAP_LOG( BACK_BDB, ARGS, 
152                 "bdb_db_open: %s\n", be->be_suffix[0].bv_val, 0, 0 );
153 #else
154         Debug( LDAP_DEBUG_ARGS,
155                 "bdb_db_open: %s\n",
156                 be->be_suffix[0].bv_val, 0, 0 );
157 #endif
158
159 #ifndef BDB_MULTIPLE_SUFFIXES
160         if ( be->be_suffix[1].bv_val ) {
161 #ifdef NEW_LOGGING
162         LDAP_LOG( BACK_BDB, ERR, 
163                 "bdb_db_open: only one suffix allowed\n", 0, 0, 0 );
164 #else
165         Debug( LDAP_DEBUG_ANY,
166                 "bdb_db_open: only one suffix allowed\n", 0, 0, 0 );
167 #endif
168                 return -1;
169         }
170 #endif
171         /* we should check existance of dbenv_home and db_directory */
172
173         rc = db_env_create( &bdb->bi_dbenv, 0 );
174         if( rc != 0 ) {
175 #ifdef NEW_LOGGING
176                 LDAP_LOG( BACK_BDB, ERR, 
177                         "bdb_db_open: db_env_create failed: %s (%d)\n", 
178                         db_strerror(rc), rc, 0 );
179 #else
180                 Debug( LDAP_DEBUG_ANY,
181                         "bdb_db_open: db_env_create failed: %s (%d)\n",
182                         db_strerror(rc), rc, 0 );
183 #endif
184                 return rc;
185         }
186
187         flags = DB_INIT_MPOOL | DB_THREAD | DB_CREATE
188                 | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN;
189         
190 #if 0
191         /* Never do automatic recovery, must perform it manually.
192          * Otherwise restarting with gentlehup will corrupt the
193          * database.
194          */
195         if( !(slapMode & SLAP_TOOL_MODE) ) flags |= DB_RECOVER;
196 #endif
197
198         bdb->bi_dbenv->set_errpfx( bdb->bi_dbenv, be->be_suffix[0].bv_val );
199         bdb->bi_dbenv->set_errcall( bdb->bi_dbenv, bdb_errcall );
200         bdb->bi_dbenv->set_lk_detect( bdb->bi_dbenv, bdb->bi_lock_detect );
201
202 #ifdef SLAP_IDL_CACHE
203         if ( bdb->bi_idl_cache_max_size ) {
204                 ldap_pvt_thread_mutex_init( &bdb->bi_idl_tree_mutex );
205                 bdb->bi_idl_cache_size = 0;
206         }
207 #endif
208
209 #ifdef BDB_SUBDIRS
210         {
211                 char dir[MAXPATHLEN];
212                 size_t len = strlen( bdb->bi_dbenv_home );
213
214                 strcpy( dir, bdb->bi_dbenv_home );
215                 strcat( &dir[len], BDB_TMP_SUBDIR );
216                 
217                 rc = bdb->bi_dbenv->set_tmp_dir( bdb->bi_dbenv, dir );
218                 if( rc != 0 ) {
219 #ifdef NEW_LOGGING
220                         LDAP_LOG( BACK_BDB, ERR, 
221                                 "bdb_db_open: set_tmp_dir(%s) failed: %s (%d)\n", 
222                                 dir, db_strerror(rc), rc );
223 #else
224                         Debug( LDAP_DEBUG_ANY,
225                                 "bdb_db_open: set_tmp_dir(%s) failed: %s (%d)\n",
226                                 dir, db_strerror(rc), rc );
227 #endif
228                         return rc;
229                 }
230
231                 strcat( &dir[len], BDB_LG_SUBDIR );
232
233                 rc = bdb->bi_dbenv->set_lg_dir( bdb->bi_dbenv, dir );
234                 if( rc != 0 ) {
235 #ifdef NEW_LOGGING
236                         LDAP_LOG( BACK_BDB, ERR, 
237                                 "bdb_db_open: set_lg_dir(%s) failed: %s (%d)\n", 
238                                 dir, db_strerror(rc), rc );
239 #else
240                         Debug( LDAP_DEBUG_ANY,
241                                 "bdb_db_open: set_lg_dir(%s) failed: %s (%d)\n",
242                                 dir, db_strerror(rc), rc );
243 #endif
244                         return rc;
245                 }
246
247                 strcat( &dir[len], BDB_DATA_SUBDIR );
248
249                 rc = bdb->bi_dbenv->set_data_dir( bdb->bi_dbenv, dir );
250                 if( rc != 0 ) {
251 #ifdef NEW_LOGGING
252                         LDAP_LOG( BACK_BDB, ERR, 
253                                 "bdb_db_open: set_data_dir(%s) failed: %s (%d)\n",
254                                 dir, db_strerror(rc), rc );
255 #else
256                         Debug( LDAP_DEBUG_ANY,
257                                 "bdb_db_open: set_data_dir(%s) failed: %s (%d)\n",
258                                 dir, db_strerror(rc), rc );
259 #endif
260                         return rc;
261                 }
262         }
263 #endif
264
265 #ifdef NEW_LOGGING
266         LDAP_LOG( BACK_BDB, DETAIL1, 
267                 "bdb_db_open: dbenv_open %s\n", bdb->bi_dbenv_home, 0, 0 );
268 #else
269         Debug( LDAP_DEBUG_TRACE,
270                 "bdb_db_open: dbenv_open(%s)\n",
271                 bdb->bi_dbenv_home, 0, 0);
272 #endif
273
274 #ifdef HAVE_EBCDIC
275         strcpy( path, bdb->bi_dbenv_home );
276         __atoe( path );
277         rc = bdb->bi_dbenv->open( bdb->bi_dbenv,
278                 path,
279                 flags,
280                 bdb->bi_dbenv_mode );
281 #else
282         rc = bdb->bi_dbenv->open( bdb->bi_dbenv,
283                 bdb->bi_dbenv_home,
284                 flags,
285                 bdb->bi_dbenv_mode );
286 #endif
287         if( rc != 0 ) {
288 #ifdef NEW_LOGGING
289                 LDAP_LOG( BACK_BDB, ERR, 
290                         "bdb_db_open: dbenv_open failed: %s (%d)\n", 
291                         db_strerror(rc), rc, 0 );
292 #else
293                 Debug( LDAP_DEBUG_ANY,
294                         "bdb_db_open: dbenv_open failed: %s (%d)\n",
295                         db_strerror(rc), rc, 0 );
296 #endif
297                 return rc;
298         }
299
300         if( bdb->bi_dbenv_xflags != 0 ) {
301                 rc = bdb->bi_dbenv->set_flags( bdb->bi_dbenv,
302                         bdb->bi_dbenv_xflags, 1);
303                 if( rc != 0 ) {
304 #ifdef NEW_LOGGING
305                         LDAP_LOG( BACK_BDB, ERR, 
306                                 "bdb_db_open: dbenv_set_flags failed: %s (%d)\n", 
307                                 db_strerror(rc), rc, 0 );
308 #else
309                         Debug( LDAP_DEBUG_ANY,
310                                 "bdb_db_open: dbenv_set_flags failed: %s (%d)\n",
311                                 db_strerror(rc), rc, 0 );
312 #endif
313                         return rc;
314                 }
315         }
316
317         flags = DB_THREAD | DB_CREATE | bdb->bi_db_opflags;
318
319         bdb->bi_databases = (struct bdb_db_info **) ch_malloc(
320                 BDB_INDICES * sizeof(struct bdb_db_info *) );
321
322         /* open (and create) main database */
323         for( i = 0; bdbi_databases[i].name; i++ ) {
324                 struct bdb_db_info *db;
325
326                 db = (struct bdb_db_info *) ch_calloc(1, sizeof(struct bdb_db_info));
327
328                 rc = db_create( &db->bdi_db, bdb->bi_dbenv, 0 );
329                 if( rc != 0 ) {
330 #ifdef NEW_LOGGING
331                         LDAP_LOG( BACK_BDB, ERR, 
332                                 "bdb_db_open: db_create(%s) failed: %s (%d)\n", 
333                                 bdb->bi_dbenv_home, db_strerror(rc), rc );
334 #else
335                         Debug( LDAP_DEBUG_ANY,
336                                 "bdb_db_open: db_create(%s) failed: %s (%d)\n",
337                                 bdb->bi_dbenv_home, db_strerror(rc), rc );
338 #endif
339                         return rc;
340                 }
341
342                 if( i == BDB_ID2ENTRY ) {
343                         rc = db->bdi_db->set_bt_compare( db->bdi_db,
344                                 bdb_bt_compare );
345                         rc = db->bdi_db->set_pagesize( db->bdi_db,
346                                 BDB_ID2ENTRY_PAGESIZE );
347                 } else {
348 #ifdef BDB_HIER
349                         rc = db->bdi_db->set_bt_compare( db->bdi_db,
350                                 bdb_bt_compare );
351 #else
352                         rc = db->bdi_db->set_flags( db->bdi_db, 
353                                 DB_DUP | DB_DUPSORT );
354                         rc = db->bdi_db->set_dup_compare( db->bdi_db,
355                                 bdb_bt_compare );
356 #endif
357                         rc = db->bdi_db->set_pagesize( db->bdi_db,
358                                 BDB_PAGESIZE );
359                 }
360
361 #ifdef HAVE_EBCDIC
362                 strcpy( path, bdbi_databases[i].file );
363                 __atoe( path );
364                 rc = DB_OPEN( db->bdi_db, 
365                         path,
366                 /*      bdbi_databases[i].name, */ NULL,
367                         bdbi_databases[i].type,
368                         bdbi_databases[i].flags | flags,
369                         bdb->bi_dbenv_mode );
370 #else
371                 rc = DB_OPEN( db->bdi_db, 
372                         bdbi_databases[i].file,
373                 /*      bdbi_databases[i].name, */ NULL,
374                         bdbi_databases[i].type,
375                         bdbi_databases[i].flags | flags,
376                         bdb->bi_dbenv_mode );
377 #endif
378
379                 if( rc != 0 ) {
380 #ifdef NEW_LOGGING
381                         LDAP_LOG( BACK_BDB, ERR, 
382                                 "bdb_db_open: db_create(%s) failed: %s (%d)\n", 
383                                 bdb->bi_dbenv_home, db_strerror(rc), rc );
384 #else
385                         Debug( LDAP_DEBUG_ANY,
386                                 "bdb_db_open: db_open(%s) failed: %s (%d)\n",
387                                 bdb->bi_dbenv_home, db_strerror(rc), rc );
388 #endif
389                         return rc;
390                 }
391
392                 db->bdi_name = bdbi_databases[i].name;
393                 bdb->bi_databases[i] = db;
394         }
395
396         bdb->bi_databases[i] = NULL;
397         bdb->bi_ndatabases = i;
398
399         /* get nextid */
400         rc = bdb_last_id( be, NULL );
401         if( rc != 0 ) {
402 #ifdef NEW_LOGGING
403                         LDAP_LOG( BACK_BDB, ERR, 
404                                 "bdb_db_open: last_id(%s) failed: %s (%d)\n", 
405                                 bdb->bi_dbenv_home, db_strerror(rc), rc );
406 #else
407                 Debug( LDAP_DEBUG_ANY,
408                         "bdb_db_open: last_id(%s) failed: %s (%d)\n",
409                         bdb->bi_dbenv_home, db_strerror(rc), rc );
410 #endif
411                 return rc;
412         }
413
414         /* <insert> open (and create) index databases */
415 #ifdef BDB_HIER
416         rc = bdb_build_tree( be );
417 #endif
418         return 0;
419 }
420
421 static int
422 bdb_db_close( BackendDB *be )
423 {
424         int rc;
425         struct bdb_info *bdb = (struct bdb_info *) be->be_private;
426         struct bdb_db_info *db;
427 #ifdef SLAP_IDL_CACHE
428         bdb_idl_cache_entry_t *entry, *next_entry;
429 #endif
430
431         while( bdb->bi_ndatabases-- ) {
432                 db = bdb->bi_databases[bdb->bi_ndatabases];
433                 rc = db->bdi_db->close( db->bdi_db, 0 );
434                 /* Lower numbered names are not strdup'd */
435                 if( bdb->bi_ndatabases >= BDB_NDB )
436                         free( db->bdi_name );
437                 free( db );
438         }
439         free( bdb->bi_databases );
440         bdb_attr_index_destroy( bdb->bi_attrs );
441
442         bdb_cache_release_all (&bdb->bi_cache);
443
444 #ifdef SLAP_IDL_CACHE
445         ldap_pvt_thread_mutex_lock ( &bdb->bi_idl_tree_mutex );
446         entry = bdb->bi_idl_lru_head;
447         while ( entry != NULL ) {
448                 next_entry = entry->idl_lru_next;
449                 free( entry->idl );
450                 free( entry->kstr.bv_val );
451                 free( entry );
452                 entry = next_entry;
453         }
454         ldap_pvt_thread_mutex_unlock ( &bdb->bi_idl_tree_mutex );
455 #endif
456
457         return 0;
458 }
459
460 static int
461 bdb_db_destroy( BackendDB *be )
462 {
463         int rc;
464         struct bdb_info *bdb = (struct bdb_info *) be->be_private;
465
466         /* close db environment */
467         if( bdb->bi_dbenv ) {
468                 /* force a checkpoint */
469                 rc = TXN_CHECKPOINT( bdb->bi_dbenv, 0, 0, DB_FORCE );
470                 if( rc != 0 ) {
471 #ifdef NEW_LOGGING
472                         LDAP_LOG( BACK_BDB, ERR, 
473                                 "bdb_db_destroy: txn_checkpoint failed: %s (%d)\n",
474                                 db_strerror(rc), rc, 0 );
475 #else
476                         Debug( LDAP_DEBUG_ANY,
477                                 "bdb_db_destroy: txn_checkpoint failed: %s (%d)\n",
478                                 db_strerror(rc), rc, 0 );
479 #endif
480                 }
481
482                 bdb_cache_release_all (&bdb->bi_cache);
483
484                 rc = bdb->bi_dbenv->close( bdb->bi_dbenv, 0 );
485                 bdb->bi_dbenv = NULL;
486                 if( rc != 0 ) {
487 #ifdef NEW_LOGGING
488                         LDAP_LOG( BACK_BDB, ERR, 
489                                 "bdb_db_destroy: close failed: %s (%d)\n", 
490                                 db_strerror(rc), rc, 0 );
491 #else
492                         Debug( LDAP_DEBUG_ANY,
493                                 "bdb_db_destroy: close failed: %s (%d)\n",
494                                 db_strerror(rc), rc, 0 );
495 #endif
496                         return rc;
497                 }
498         }
499
500         if( bdb->bi_dbenv_home ) ch_free( bdb->bi_dbenv_home );
501
502 #ifdef BDB_HIER
503         ldap_pvt_thread_rdwr_destroy( &bdb->bi_tree_rdwr );
504 #endif
505         ldap_pvt_thread_rdwr_destroy ( &bdb->bi_cache.c_rwlock );
506         ldap_pvt_thread_mutex_destroy( &bdb->bi_cache.lru_mutex );
507         ldap_pvt_thread_mutex_destroy( &bdb->bi_lastid_mutex );
508         ldap_pvt_thread_mutex_destroy( &bdb->bi_database_mutex );
509
510         ch_free( bdb );
511         be->be_private = NULL;
512
513         return 0;
514 }
515
516 #ifdef SLAPD_BDB_DYNAMIC
517 int back_bdb_LTX_init_module( int argc, char *argv[] ) {
518         BackendInfo bi;
519
520         memset( &bi, '\0', sizeof(bi) );
521         bi.bi_type = "bdb";
522         bi.bi_init = bdb_initialize;
523
524         backend_add( &bi );
525         return 0;
526 }
527 #endif /* SLAPD_BDB_DYNAMIC */
528
529 int
530 bdb_initialize(
531         BackendInfo     *bi
532 )
533 {
534         static char *controls[] = {
535                 LDAP_CONTROL_MANAGEDSAIT,
536                 LDAP_CONTROL_NOOP,
537 #ifdef LDAP_CONTROL_PAGEDRESULTS
538                 LDAP_CONTROL_PAGEDRESULTS,
539 #endif
540                 LDAP_CONTROL_VALUESRETURNFILTER,
541 #ifdef LDAP_CONTROL_SUBENTRIES
542                 LDAP_CONTROL_SUBENTRIES,
543 #endif
544 #ifdef LDAP_CLIENT_UPDATE
545                 LDAP_CONTROL_CLIENT_UPDATE,
546 #endif
547                 NULL
548         };
549
550         bi->bi_controls = controls;
551
552         /* initialize the underlying database system */
553 #ifdef NEW_LOGGING
554         LDAP_LOG( BACK_BDB, ENTRY, "bdb_db_initialize\n", 0, 0, 0 );
555 #else
556         Debug( LDAP_DEBUG_TRACE, "bdb_initialize: initialize BDB backend\n",
557                 0, 0, 0 );
558 #endif
559
560         {       /* version check */
561                 int major, minor, patch;
562                 char *version = db_version( &major, &minor, &patch );
563 #ifdef HAVE_EBCDIC
564                 char v2[1024];
565
566                 /* All our stdio does an ASCII to EBCDIC conversion on
567                  * the output. Strings from the BDB library are already
568                  * in EBCDIC; we have to go back and forth...
569                  */
570                 strcpy( v2, version );
571                 __etoa( v2 );
572                 version = v2;
573 #endif
574
575                 if( major != DB_VERSION_MAJOR ||
576                         minor != DB_VERSION_MINOR ||
577                         patch < DB_VERSION_PATCH )
578                 {
579 #ifdef NEW_LOGGING
580                         LDAP_LOG( BACK_BDB, ERR, 
581                                 "bdb_db_initialize: version mismatch: "
582                                 "\texpected: %s \tgot: %s\n", DB_VERSION_STRING, version, 0 );
583 #else
584                         Debug( LDAP_DEBUG_ANY,
585                                 "bdb_initialize: version mismatch\n"
586                                 "\texpected: " DB_VERSION_STRING "\n"
587                                 "\tgot: %s \n", version, 0, 0 );
588 #endif
589                 }
590
591 #ifdef NEW_LOGGING
592                 LDAP_LOG( BACK_BDB, DETAIL1, 
593                         "bdb_db_initialize: %s\n", version, 0, 0 );
594 #else
595                 Debug( LDAP_DEBUG_ANY, "bdb_initialize: %s\n",
596                         version, 0, 0 );
597 #endif
598         }
599
600         db_env_set_func_free( ber_memfree );
601         db_env_set_func_malloc( (db_malloc *)ber_memalloc );
602         db_env_set_func_realloc( (db_realloc *)ber_memrealloc );
603 #ifndef NO_THREAD
604         /* This is a no-op on a NO_THREAD build. Leave the default
605          * alone so that BDB will sleep on interprocess conflicts.
606          */
607         db_env_set_func_yield( ldap_pvt_thread_yield );
608 #endif
609
610         {
611                 static char uuidbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE ];
612
613                 bdb_uuid.bv_len = lutil_uuidstr( uuidbuf, sizeof( uuidbuf ));
614                 bdb_uuid.bv_val = uuidbuf;
615         }
616
617         bi->bi_open = 0;
618         bi->bi_close = 0;
619         bi->bi_config = 0;
620         bi->bi_destroy = 0;
621
622         bi->bi_db_init = bdb_db_init;
623         bi->bi_db_config = bdb_db_config;
624         bi->bi_db_open = bdb_db_open;
625         bi->bi_db_close = bdb_db_close;
626         bi->bi_db_destroy = bdb_db_destroy;
627
628         bi->bi_op_add = bdb_add;
629         bi->bi_op_bind = bdb_bind;
630         bi->bi_op_compare = bdb_compare;
631         bi->bi_op_delete = bdb_delete;
632         bi->bi_op_modify = bdb_modify;
633         bi->bi_op_modrdn = bdb_modrdn;
634         bi->bi_op_search = bdb_search;
635
636         bi->bi_op_unbind = 0;
637
638 #ifdef LDAP_CLIENT_UPDATE
639         bi->bi_op_abandon = bdb_abandon;
640         bi->bi_op_cancel = bdb_cancel;
641 #else
642         bi->bi_op_abandon = 0;
643         bi->bi_op_cancel = 0;
644 #endif
645
646         bi->bi_extended = bdb_extended;
647
648 #if 1
649         /*
650          * these routines (and their callers) are not yet designed
651          * to work with transaction.  Using them may cause deadlock.
652          */
653         bi->bi_acl_group = bdb_group;
654         bi->bi_acl_attribute = bdb_attribute;
655 #else
656         bi->bi_acl_group = 0;
657         bi->bi_acl_attribute = 0;
658 #endif
659
660         bi->bi_chk_referrals = bdb_referrals;
661         bi->bi_operational = bdb_operational;
662         bi->bi_has_subordinates = bdb_hasSubordinates;
663         bi->bi_entry_release_rw = bdb_entry_release;
664
665         /*
666          * hooks for slap tools
667          */
668         bi->bi_tool_entry_open = bdb_tool_entry_open;
669         bi->bi_tool_entry_close = bdb_tool_entry_close;
670         bi->bi_tool_entry_first = bdb_tool_entry_next;
671         bi->bi_tool_entry_next = bdb_tool_entry_next;
672         bi->bi_tool_entry_get = bdb_tool_entry_get;
673         bi->bi_tool_entry_put = bdb_tool_entry_put;
674         bi->bi_tool_entry_reindex = bdb_tool_entry_reindex;
675         bi->bi_tool_sync = 0;
676
677         bi->bi_connection_init = 0;
678         bi->bi_connection_destroy = 0;
679
680         return 0;
681 }