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