]> git.sur5r.net Git - openldap/blob - libraries/libldbm/ldbm.c
Integration of the BDB2 backend into the new init/startup/shutdown schema.
[openldap] / libraries / libldbm / ldbm.c
1 /* ldbm.c - ldap dbm compatibility routines */
2
3 /* Patched for Berkeley DB version 2.0; /KSp; 98/02/23
4  *
5  *   - DB version 2.6.4b   ; 1998/12/28, /KSp
6  *   - DB_DBT_MALLOC       ; 1998/03/22, /KSp
7  *   - basic implementation; 1998/02/23, /KSp
8  */
9
10 #include "portable.h"
11
12 #include "syslog.h"
13
14 #ifdef SLAPD_LDBM
15
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <ac/string.h>
19 #include <ac/errno.h>
20
21 #include "ldbm.h"
22 #include "ldap_pvt_thread.h"
23
24
25 void
26 ldbm_datum_free( LDBM ldbm, Datum data )
27 {
28         free( data.dptr );
29         data.dptr = NULL;
30 }
31
32
33 Datum
34 ldbm_datum_dup( LDBM ldbm, Datum data )
35 {
36         Datum   dup;
37
38         if ( data.dsize == 0 ) {
39                 dup.dsize = 0;
40                 dup.dptr = NULL;
41
42                 return( dup );
43         }
44         dup.dsize = data.dsize;
45         if ( (dup.dptr = (char *) malloc( data.dsize )) != NULL )
46                 memcpy( dup.dptr, data.dptr, data.dsize );
47
48         return( dup );
49 }
50
51 static int ldbm_initialized = 0;
52
53 #ifndef HAVE_BERKELEY_DB2
54 /* Everything but DB2 is non-reentrant */
55
56 static ldap_pvt_thread_mutex_t ldbm_big_mutex;
57 #define LDBM_LOCK       (ldap_pvt_thread_mutex_lock(&ldbm_big_mutex))
58 #define LDBM_UNLOCK     (ldap_pvt_thread_mutex_unlock(&ldbm_big_mutex))
59
60 int ldbm_initialize( void )
61 {
62         if(ldbm_initialized++) return 1;
63
64         ldap_pvt_thread_mutex_init( &ldbm_big_mutex );
65
66         return 0;
67 }
68
69 int ldbm_shutdown( void )
70 {
71         if( !ldbm_initialized ) return 1;
72
73         ldap_pvt_thread_mutex_destroy( &ldbm_big_mutex );
74
75         return 0;
76 }
77
78 #else
79
80 void *
81 ldbm_malloc( size_t size )
82 {
83         return( calloc( 1, size ));
84 }
85
86 static void
87 ldbm_db_errcall( const char *prefix, char *message )
88 {
89
90         syslog( LOG_INFO, "ldbm_db_errcall(): %s %s", prefix, message );
91
92 }
93
94 /*  a dbEnv for BERKELEYv2  */
95 DB_ENV           ldbm_Env;
96
97 /* Berkeley DB 2.x is reentrant */
98 #define LDBM_LOCK       ((void)0)
99 #define LDBM_UNLOCK     ((void)0)
100
101 int ldbm_initialize( void )
102 {
103         int     err;
104         int     envFlags;
105
106         if(ldbm_initialized++) return 1;
107
108         memset( &ldbm_Env, 0, sizeof( ldbm_Env ));
109
110         ldbm_Env.db_errcall   = ldbm_db_errcall;
111         ldbm_Env.db_errpfx    = "==>";
112
113         envFlags = DB_CREATE | DB_THREAD;
114
115         if ( ( err = db_appinit( NULL, NULL, &ldbm_Env, envFlags )) ) {
116                 char  error[BUFSIZ];
117
118                 if ( err < 0 ) {
119                         sprintf( error, "%ld\n", (long) err );
120                 } else {
121                         sprintf( error, "%s\n", strerror( err ));
122                 }
123
124                 syslog( LOG_INFO,
125                         "ldbm_initialize(): FATAL error in db_appinit() : %s\n",
126                         error );
127                 return( 1 );
128         }
129
130         return 0;
131 }
132
133 int ldbm_shutdown( void )
134 {
135         if( !ldbm_initialized ) return 1;
136
137         db_appexit( &ldbm_Env );
138
139         return 0;
140 }
141
142 #endif
143
144 #if defined( LDBM_USE_DBHASH ) || defined( LDBM_USE_DBBTREE )
145
146 /*****************************************************************
147  *                                                               *
148  * use berkeley db hash or btree package                         *
149  *                                                               *
150  *****************************************************************/
151
152 LDBM
153 ldbm_open( char *name, int rw, int mode, int dbcachesize )
154 {
155         LDBM            ret = NULL;
156
157 #ifdef HAVE_BERKELEY_DB2
158         DB_INFO dbinfo;
159
160         memset( &dbinfo, 0, sizeof( dbinfo ));
161         if ( ldbm_Env.mp_info == NULL )
162                 dbinfo.db_cachesize = dbcachesize;
163         dbinfo.db_pagesize  = DEFAULT_DB_PAGE_SIZE;
164         dbinfo.db_malloc    = ldbm_malloc;
165
166         LDBM_LOCK;
167     (void) db_open( name, DB_TYPE, rw, mode, &ldbm_Env, &dbinfo, &ret );
168         LDBM_UNLOCK;
169
170 #else
171         void            *info;
172         BTREEINFO       binfo;
173         HASHINFO        hinfo;
174
175         if ( DB_TYPE == DB_HASH ) {
176                 memset( (char *) &hinfo, '\0', sizeof(hinfo) );
177                 hinfo.cachesize = dbcachesize;
178                 info = &hinfo;
179         } else if ( DB_TYPE == DB_BTREE ) {
180                 memset( (char *) &binfo, '\0', sizeof(binfo) );
181                 binfo.cachesize = dbcachesize;
182                 info = &binfo;
183         } else {
184                 info = NULL;
185         }
186
187         LDBM_LOCK;
188         ret = dbopen( name, rw, mode, DB_TYPE, info );
189         LDBM_UNLOCK;
190
191 #endif
192
193         return( ret );
194 }
195
196 void
197 ldbm_close( LDBM ldbm )
198 {
199         LDBM_LOCK;
200 #ifdef HAVE_BERKELEY_DB2
201         (*ldbm->close)( ldbm, 0 );
202 #else
203         (*ldbm->close)( ldbm );
204 #endif
205         LDBM_UNLOCK;
206 }
207
208 void
209 ldbm_sync( LDBM ldbm )
210 {
211         LDBM_LOCK;
212         (*ldbm->sync)( ldbm, 0 );
213         LDBM_UNLOCK;
214 }
215
216 Datum
217 ldbm_fetch( LDBM ldbm, Datum key )
218 {
219         Datum   data;
220         int     rc;
221
222         LDBM_LOCK;
223
224 #ifdef HAVE_BERKELEY_DB2
225         ldbm_datum_init( data );
226
227         data.flags = DB_DBT_MALLOC;
228
229         if ( (rc = (*ldbm->get)( ldbm, NULL, &key, &data, 0 )) != 0 ) {
230                 if ( data.dptr ) free( data.dptr );
231 #else
232         if ( (rc = (*ldbm->get)( ldbm, &key, &data, 0 )) == 0 ) {
233                 /* Berkeley DB 1.85 don't malloc the data for us */
234                 /* duplicate it for to ensure reentrancy */
235                 data = ldbm_datum_dup( ldbm, data );
236         } else {
237 #endif
238                 data.dptr = NULL;
239                 data.dsize = 0;
240         }
241
242         LDBM_UNLOCK;
243
244         return( data );
245 }
246
247 int
248 ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
249 {
250         int     rc;
251
252         LDBM_LOCK;
253
254 #ifdef HAVE_BERKELEY_DB2
255         rc = (*ldbm->put)( ldbm, NULL, &key, &data, flags & ~LDBM_SYNC );
256         rc = (-1 ) * rc;
257 #else
258         rc = (*ldbm->put)( ldbm, &key, &data, flags & ~LDBM_SYNC );
259 #endif
260
261         if ( flags & LDBM_SYNC )
262                 (*ldbm->sync)( ldbm, 0 );
263
264         LDBM_UNLOCK;
265
266         return( rc );
267 }
268
269 int
270 ldbm_delete( LDBM ldbm, Datum key )
271 {
272         int     rc;
273
274         LDBM_LOCK;
275
276 #ifdef HAVE_BERKELEY_DB2
277         rc = (*ldbm->del)( ldbm, NULL, &key, 0 );
278         rc = (-1 ) * rc;
279 #else
280         rc = (*ldbm->del)( ldbm, &key, 0 );
281 #endif
282         (*ldbm->sync)( ldbm, 0 );
283
284         LDBM_UNLOCK;
285
286         return( rc );
287 }
288
289 Datum
290 #ifdef HAVE_BERKELEY_DB2
291 ldbm_firstkey( LDBM ldbm, DBC **dbch )
292 #else
293 ldbm_firstkey( LDBM ldbm )
294 #endif
295 {
296         Datum   key, data;
297         int     rc;
298
299 #ifdef HAVE_BERKELEY_DB2
300         DBC  *dbci;
301
302         ldbm_datum_init( key );
303         ldbm_datum_init( data );
304
305         key.flags = data.flags = DB_DBT_MALLOC;
306
307         LDBM_LOCK;
308
309         /* acquire a cursor for the DB */
310
311 #  if defined( DB_VERSION_MAJOR ) && defined( DB_VERSION_MINOR ) && \
312     DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
313
314         if ( (*ldbm->cursor)( ldbm, NULL, &dbci )) 
315
316 #  else
317         if ( (*ldbm->cursor)( ldbm, NULL, &dbci, 0 ))
318 #  endif
319         {
320                 return( key );
321         } else {
322                 *dbch = dbci;
323                 if ( (*dbci->c_get)( dbci, &key, &data, DB_NEXT ) == 0 ) {
324                         if ( data.dptr ) {
325                                 free( data.dptr );
326                         }       
327                 }
328 #else
329
330         LDBM_LOCK;
331
332         if ( (rc = (*ldbm->seq)( ldbm, &key, &data, R_FIRST )) == 0 ) {
333                 key = ldbm_datum_dup( ldbm, key );
334         }
335 #endif
336         else {
337                 key.dptr = NULL;
338                 key.dsize = 0;
339         }
340
341 #ifdef HAVE_BERKELEY_DB2
342         }
343 #endif
344
345         LDBM_UNLOCK;
346
347         return( key );
348 }
349
350 Datum
351 #ifdef HAVE_BERKELEY_DB2
352 ldbm_nextkey( LDBM ldbm, Datum key, DBC *dbcp )
353 #else
354 ldbm_nextkey( LDBM ldbm, Datum key )
355 #endif
356 {
357         Datum   data;
358         int     rc;
359
360 #ifdef HAVE_BERKELEY_DB2
361         void *oldKey = key.dptr;
362
363         ldbm_datum_init( data );
364
365         data.flags = DB_DBT_MALLOC;
366
367         LDBM_LOCK;
368
369         if ( (*dbcp->c_get)( dbcp, &key, &data, DB_NEXT ) == 0 ) {
370                 if ( data.dptr ) free( data.dptr );
371         }
372 #else
373
374         LDBM_LOCK;
375
376         if ( (rc = (*ldbm->seq)( ldbm, &key, &data, R_NEXT )) == 0 ) {
377                 key = ldbm_datum_dup( ldbm, key );
378         }
379 #endif
380         else {
381                 key.dptr = NULL;
382                 key.dsize = 0;
383         }
384
385         LDBM_UNLOCK;
386
387 #ifdef HAVE_BERKELEY_DB2
388         if ( oldKey ) free( oldKey );
389 #endif
390
391         return( key );
392 }
393
394 int
395 ldbm_errno( LDBM ldbm )
396 {
397         return( errno );
398 }
399
400 #elif defined( HAVE_GDBM )
401
402 #include <sys/stat.h>
403
404 /*****************************************************************
405  *                                                               *
406  * use gdbm                                                      *
407  *                                                               *
408  *****************************************************************/
409
410 LDBM
411 ldbm_open( char *name, int rw, int mode, int dbcachesize )
412 {
413         LDBM            db;
414         struct stat     st;
415
416         LDBM_LOCK;
417
418         if ( (db =  gdbm_open( name, 0, rw | GDBM_FAST, mode, 0 )) == NULL ) {
419                 LDBM_UNLOCK;
420                 return( NULL );
421         }
422         if ( dbcachesize > 0 && stat( name, &st ) == 0 ) {
423                 dbcachesize = (dbcachesize / st.st_blksize);
424                 gdbm_setopt( db, GDBM_CACHESIZE, &dbcachesize, sizeof(int) );
425         }
426
427         LDBM_UNLOCK;
428
429         return( db );
430 }
431
432 void
433 ldbm_close( LDBM ldbm )
434 {
435         LDBM_LOCK;
436         gdbm_close( ldbm );
437         LDBM_UNLOCK;
438 }
439
440 void
441 ldbm_sync( LDBM ldbm )
442 {
443         LDBM_LOCK;
444         gdbm_sync( ldbm );
445         LDBM_UNLOCK;
446 }
447
448 Datum
449 ldbm_fetch( LDBM ldbm, Datum key )
450 {
451         Datum d;
452
453         LDBM_LOCK;
454         d = gdbm_fetch( ldbm, key );
455         LDBM_UNLOCK;
456
457         return d;
458 }
459
460 int
461 ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
462 {
463         int     rc;
464
465         LDBM_LOCK;
466         rc = gdbm_store( ldbm, key, data, flags & ~LDBM_SYNC );
467         if ( flags & LDBM_SYNC )
468                 gdbm_sync( ldbm );
469         LDBM_UNLOCK;
470
471         return( rc );
472 }
473
474 int
475 ldbm_delete( LDBM ldbm, Datum key )
476 {
477         int     rc;
478
479         LDBM_LOCK;
480         rc = gdbm_delete( ldbm, key );
481         gdbm_sync( ldbm );
482         LDBM_UNLOCK;
483
484         return( rc );
485 }
486
487 Datum
488 ldbm_firstkey( LDBM ldbm )
489 {
490         Datum d;
491
492         LDBM_LOCK;
493         d = gdbm_firstkey( ldbm );
494         LDBM_UNLOCK;
495
496         return d;
497 }
498
499 Datum
500 ldbm_nextkey( LDBM ldbm, Datum key )
501 {
502         Datum d;
503
504         LDBM_LOCK;
505         d = gdbm_nextkey( ldbm, key );
506         LDBM_UNLOCK;
507
508         return d;
509 }
510
511 int
512 ldbm_errno( LDBM ldbm )
513 {
514         int err;
515
516         LDBM_LOCK;
517         err = gdbm_errno;
518         LDBM_UNLOCK;
519
520         return( err );
521 }
522
523 #elif defined( HAVE_NDBM )
524
525 /*****************************************************************
526  *                                                               *
527  * if no gdbm, fall back to using ndbm, the standard unix thing  *
528  *                                                               *
529  *****************************************************************/
530
531 /* ARGSUSED */
532 LDBM
533 ldbm_open( char *name, int rw, int mode, int dbcachesize )
534 {
535         LDBM ldbm;
536
537         LDBM_LOCK;
538         ldbm = dbm_open( name, rw, mode );
539         LDBM_UNLOCK;
540
541         return( ldbm );
542 }
543
544 void
545 ldbm_close( LDBM ldbm )
546 {
547         LDBM_LOCK;
548         dbm_close( ldbm );
549         LDBM_UNLOCK;
550 }
551
552 /* ARGSUSED */
553 void
554 ldbm_sync( LDBM ldbm )
555 {
556         return;
557 }
558
559 Datum
560 ldbm_fetch( LDBM ldbm, Datum key )
561 {
562         Datum d;
563
564         LDBM_LOCK;
565         d = ldbm_datum_dup( ldbm, dbm_fetch( ldbm, key ) );
566         LDBM_UNLOCK;
567
568         return d;
569 }
570
571 int
572 ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
573 {
574         int rc;
575
576         LDBM_LOCK;
577         rc = dbm_store( ldbm, key, data, flags );
578         LDBM_UNLOCK;
579
580         return rc;
581 }
582
583 int
584 ldbm_delete( LDBM ldbm, Datum key )
585 {
586         int rc;
587
588         LDBM_LOCK;
589         rc = dbm_delete( ldbm, key );
590         LDBM_UNLOCK;
591
592         return rc;
593 }
594
595 Datum
596 ldbm_firstkey( LDBM ldbm )
597 {
598         Datum d;
599
600         LDBM_LOCK;
601         d = dbm_firstkey( ldbm );
602         LDBM_UNLOCK;
603
604         return d;
605 }
606
607 Datum
608 ldbm_nextkey( LDBM ldbm, Datum key )
609 {
610         Datum d;
611
612         LDBM_LOCK;
613         d = dbm_nextkey( ldbm );
614         LDBM_UNLOCK;
615
616         return d;
617 }
618
619 int
620 ldbm_errno( LDBM ldbm )
621 {
622         int err;
623
624         LDBM_LOCK;
625         err = dbm_error( ldbm );
626         LDBM_UNLOCK;
627
628         return err;
629 }
630
631 #endif /* ndbm */
632 #endif /* ldbm */