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