]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/init.c
ed28d77a312ad523e6ed5209ff98d3d3979df338
[openldap] / servers / slapd / back-bdb / init.c
1 /* init.c - initialize bdb backend */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2000 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
13 #include "back-bdb.h"
14 #include "external.h"
15
16 static struct bdbi_database {
17         char *file;
18         char *name;
19         int type;
20         int flags;
21 } bdbi_databases[] = {
22         { "nextid" BDB_SUFFIX, "nextid", DB_BTREE, 0 },
23         { "dn2entry" BDB_SUFFIX, "dn2entry", DB_BTREE, 0 },
24         { "id2entry" BDB_SUFFIX, "id2entry", DB_BTREE, 0 },
25         { NULL, NULL, 0, 0 }
26 };
27
28 #if 0
29 static int
30 bdb_destroy( BackendInfo *bi )
31 {
32         return 0;
33 }
34
35 static int
36 bdb_open( BackendInfo *bi )
37 {
38         /* initialize the underlying database system */
39         Debug( LDAP_DEBUG_TRACE, "bdb_open: initialize BDB backend\n",
40                 0, 0, 0 );
41
42         return 0;
43 }
44
45 static int
46 bdb_close( BackendInfo *bi )
47 {
48         /* terminate the underlying database system */
49         return 0;
50 }
51 #endif
52
53 static int
54 bdb_db_init( BackendDB *be )
55 {
56         struct bdb_info *bdb;
57
58         Debug( LDAP_DEBUG_ANY,
59                 "bdb_db_init: Initializing BDB database\n",
60                 0, 0, 0 );
61
62         /* allocate backend-database-specific stuff */
63         bdb = (struct bdb_info *) ch_calloc( 1, sizeof(struct bdb_info) );
64
65         /* DBEnv parameters */
66         bdb->bi_dbenv_home = ch_strdup( BDB_DBENV_HOME );
67         bdb->bi_dbenv_xflags = 0;
68         bdb->bi_dbenv_mode = DEFAULT_MODE;
69
70 #ifndef NO_THREADS
71         bdb->bi_lock_detect = DB_LOCK_NORUN;
72 #endif
73
74         be->be_private = bdb;
75         return 0;
76 }
77
78 #ifndef NO_THREADS
79 static void *lock_detect_task( void *arg )
80 {
81         struct bdb_info *bdb = (struct bdb_info *) arg;
82
83         while( bdb->bi_dbenv != NULL ) {
84                 int rc;
85                 sleep( bdb->bi_lock_detect_seconds );
86
87                 rc = lock_detect( bdb->bi_dbenv, 0,
88                         bdb->bi_lock_detect, NULL );
89
90                 if( rc != 0 ) {
91                         break;
92                 }
93         }
94
95         return NULL;
96 }
97 #endif
98
99 static int
100 bdb_db_open( BackendDB *be )
101 {
102         int rc, i;
103         struct bdb_info *bdb = (struct bdb_info *) be->be_private;
104         u_int32_t flags;
105
106         Debug( LDAP_DEBUG_ARGS,
107                 "bdb_db_open: %s\n",
108                 be->be_suffix[0], 0, 0 );
109
110         /* we should check existance of dbenv_home and db_directory */
111
112         rc = db_env_create( &bdb->bi_dbenv, 0 );
113         if( rc != 0 ) {
114                 Debug( LDAP_DEBUG_ANY,
115                         "bdb_db_open: db_env_create failed: %s (%d)\n",
116                         db_strerror(rc), rc, 0 );
117                 return rc;
118         }
119
120         flags = DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN | 
121                 DB_THREAD | DB_CREATE | DB_RECOVER;
122
123         bdb->bi_dbenv->set_errpfx( bdb->bi_dbenv, be->be_suffix[0] );
124         bdb->bi_dbenv->set_errcall( bdb->bi_dbenv, bdb_errcall );
125
126 #ifdef BDB_SUBDIRS
127         {
128                 char dir[MAXPATHLEN];
129                 size_t len = strlen( bdb->bi_dbenv_home );
130
131                 strcpy( dir, bdb->bi_dbenv_home );
132                 strcat( &dir[len], BDB_TMP_SUBDIR );
133                 
134                 rc = bdb->bi_dbenv->set_tmp_dir( bdb->bi_dbenv, dir );
135                 if( rc != 0 ) {
136                         Debug( LDAP_DEBUG_ANY,
137                                 "bdb_db_open: set_tmp_dir(%s) failed: %s (%d)\n",
138                                 dir, db_strerror(rc), rc );
139                         return rc;
140                 }
141
142                 strcat( &dir[len], BDB_LG_SUBDIR );
143
144                 rc = bdb->bi_dbenv->set_lg_dir( bdb->bi_dbenv, dir );
145                 if( rc != 0 ) {
146                         Debug( LDAP_DEBUG_ANY,
147                                 "bdb_db_open: set_lg_dir(%s) failed: %s (%d)\n",
148                                 dir, db_strerror(rc), rc );
149                         return rc;
150                 }
151
152                 strcat( &dir[len], BDB_DATA_SUBDIR );
153
154                 rc = bdb->bi_dbenv->set_data_dir( bdb->bi_dbenv, dir );
155                 if( rc != 0 ) {
156                         Debug( LDAP_DEBUG_ANY,
157                                 "bdb_db_open: set_data_dir(%s) failed: %s (%d)\n",
158                                 dir, db_strerror(rc), rc );
159                         return rc;
160                 }
161         }
162 #endif
163
164         Debug( LDAP_DEBUG_TRACE,
165                 "bdb_db_open: dbenv_open(%s)\n",
166                 bdb->bi_dbenv_home, 0, 0);
167
168         rc = bdb->bi_dbenv->open( bdb->bi_dbenv,
169                 bdb->bi_dbenv_home,
170                 flags | bdb->bi_dbenv_xflags,
171                 bdb->bi_dbenv_mode );
172         if( rc != 0 ) {
173                 Debug( LDAP_DEBUG_ANY,
174                         "bdb_db_open: dbenv_open failed: %s (%d)\n",
175                         db_strerror(rc), rc, 0 );
176                 return rc;
177         }
178
179         flags = DB_THREAD | DB_CREATE;
180
181         bdb->bi_databases = (struct bdb_db_info **) ch_malloc(
182                 BDB_INDICES * sizeof(struct bdb_db_info *) );
183
184         /* open (and create) main database */
185         for( i = 0; bdbi_databases[i].name; i++ ) {
186                 struct bdb_db_info *db;
187
188                 db = (struct bdb_db_info *) ch_calloc(1, sizeof(struct bdb_db_info));
189
190                 rc = db_create( &db->bdi_db, bdb->bi_dbenv, 0 );
191                 if( rc != 0 ) {
192                         Debug( LDAP_DEBUG_ANY,
193                                 "bdb_db_open: db_create(%s) failed: %s (%d)\n",
194                                 bdb->bi_dbenv_home, db_strerror(rc), rc );
195                         return rc;
196                 }
197
198                 rc = db->bdi_db->open( db->bdi_db,
199                         bdbi_databases[i].file,
200                         bdbi_databases[i].name,
201                         bdbi_databases[i].type,
202                         bdbi_databases[i].flags | flags,
203                         bdb->bi_dbenv_mode );
204
205                 if( rc != 0 ) {
206                         Debug( LDAP_DEBUG_ANY,
207                                 "bdb_db_open: db_open(%s) failed: %s (%d)\n",
208                                 bdb->bi_dbenv_home, db_strerror(rc), rc );
209                         return rc;
210                 }
211
212                 db->bdi_name = bdbi_databases[i].name;
213                 bdb->bi_databases[i] = db;
214         }
215
216         bdb->bi_databases[i] = NULL;
217         bdb->bi_ndatabases = i;
218
219         /* get nextid */
220         rc = bdb_last_id( be, NULL );
221         if( rc != 0 ) {
222                 Debug( LDAP_DEBUG_ANY,
223                         "bdb_db_open: last_id(%s) failed: %s (%d)\n",
224                         bdb->bi_dbenv_home, db_strerror(rc), rc );
225                 return rc;
226         }
227
228         /* <insert> open (and create) index databases */
229
230 #ifndef NO_THREADS
231         if( bdb->bi_lock_detect != DB_LOCK_NORUN ) {
232                 /* listener as a separate THREAD */
233                 rc = ldap_pvt_thread_create( &bdb->bi_lock_detect_tid,
234                         1, lock_detect_task, bdb );
235         }
236 #endif
237         return 0;
238 }
239
240 static int
241 bdb_db_close( BackendDB *be )
242 {
243         int rc;
244         struct bdb_info *bdb = (struct bdb_info *) be->be_private;
245
246         /* force a checkpoint */
247         rc = txn_checkpoint( bdb->bi_dbenv, 0, 0, DB_FORCE );
248         if( rc != 0 ) {
249                 Debug( LDAP_DEBUG_ANY,
250                         "bdb_db_destroy: txn_checkpoint failed: %s (%d)\n",
251                         db_strerror(rc), rc, 0 );
252                 return rc;
253         }
254
255         while( bdb->bi_ndatabases-- ) {
256                 rc = bdb->bi_databases[bdb->bi_ndatabases]->bdi_db->close(
257                         bdb->bi_databases[bdb->bi_ndatabases]->bdi_db, 0 );
258         }
259
260         return 0;
261 }
262
263 static int
264 bdb_db_destroy( BackendDB *be )
265 {
266         int rc;
267         struct bdb_info *bdb = (struct bdb_info *) be->be_private;
268
269         /* close db environment */
270         if( bdb->bi_dbenv ) {
271                 rc = bdb->bi_dbenv->close( bdb->bi_dbenv, 0 );
272                 bdb->bi_dbenv = NULL;
273                 if( rc != 0 ) {
274                         Debug( LDAP_DEBUG_ANY,
275                                 "bdb_db_destroy: close failed: %s (%d)\n",
276                                 db_strerror(rc), rc, 0 );
277                         return rc;
278                 }
279         }
280
281         return 0;
282 }
283
284 #ifdef SLAPD_BDB_DYNAMIC
285 int back_bdb_LTX_init_module( int argc, char *argv[] ) {
286         BackendInfo bi;
287
288         memset( &bi, '\0', sizeof(bi) );
289         bi.bi_type = "bdb";
290         bi.bi_init = bdb_initialize;
291
292         backend_add( &bi );
293         return 0;
294 }
295 #endif /* SLAPD_BDB_DYNAMIC */
296
297 int
298 bdb_initialize(
299         BackendInfo     *bi
300 )
301 {
302         static char *controls[] = {
303                 LDAP_CONTROL_MANAGEDSAIT,
304                 NULL
305         };
306
307         {       /* version check */
308                 int major, minor, patch;
309                 char *version = db_version( &major, &minor, &patch );
310
311                 if( major != DB_VERSION_MAJOR ||
312                         minor != DB_VERSION_MINOR ||
313                         patch < DB_VERSION_PATCH )
314                 {
315                         Debug( LDAP_DEBUG_ANY,
316                                 "bi_back_initialize: version mismatch\n"
317                                 "\texpected: " DB_VERSION_STRING "\n"
318                                 "\tgot: %s \n", version, 0, 0 );
319                 }
320
321                 Debug( LDAP_DEBUG_ANY, "bdb_initialize: %s\n",
322                         version, 0, 0 );
323         }
324
325 #if 0
326         db_env_set_func_malloc( ch_malloc );
327         db_env_set_func_realloc( ch_realloc );
328         db_env_set_func_free( ch_free );
329 #endif
330
331         db_env_set_func_yield( ldap_pvt_thread_yield );
332
333         bi->bi_controls = controls;
334
335         bi->bi_open = 0;
336         bi->bi_close = 0;
337         bi->bi_config = 0;
338         bi->bi_destroy = 0;
339
340         bi->bi_db_init = bdb_db_init;
341         bi->bi_db_config = bdb_db_config;
342         bi->bi_db_open = bdb_db_open;
343         bi->bi_db_close = bdb_db_close;
344         bi->bi_db_destroy = bdb_db_destroy;
345
346         bi->bi_op_add = bdb_add;
347         bi->bi_op_bind = bdb_bind;
348         bi->bi_op_compare = bdb_compare;
349         bi->bi_op_delete = bdb_delete;
350         bi->bi_op_modify = bdb_modify;
351         bi->bi_op_modrdn = bdb_modrdn;
352         bi->bi_op_search = bdb_search;
353
354 #if 0
355         bi->bi_op_unbind = bdb_unbind;
356         bi->bi_op_abandon = bdb_abandon;
357
358         bi->bi_extended = bdb_extended;
359
360         bi->bi_acl_group = bdb_group;
361         bi->bi_acl_attribute = bdb_attribute;
362 #endif
363         bi->bi_chk_referrals = bdb_referrals;
364
365         bi->bi_entry_release_rw = 0;
366
367         /*
368          * hooks for slap tools
369          */
370         bi->bi_tool_entry_open = bdb_tool_entry_open;
371         bi->bi_tool_entry_close = bdb_tool_entry_close;
372         bi->bi_tool_entry_first = bdb_tool_entry_next;
373         bi->bi_tool_entry_next = bdb_tool_entry_next;
374         bi->bi_tool_entry_get = bdb_tool_entry_get;
375         bi->bi_tool_entry_put = bdb_tool_entry_put;
376 #if BDB_REINDEX
377         bi->bi_tool_entry_reindex = bdb_tool_entry_reindex;
378 #else
379         bi->bi_tool_entry_reindex = 0;
380 #endif
381         bi->bi_tool_sync = 0;
382
383         bi->bi_connection_init = 0;
384         bi->bi_connection_destroy = 0;
385
386         return 0;
387 }