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