]> git.sur5r.net Git - openldap/blob - libraries/libldbm/ldbm.c
update CDB support
[openldap] / libraries / libldbm / ldbm.c
1 /* ldbm.c - ldap dbm compatibility routines */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 /* Patched for Berkeley DB version 2.0; /KSp; 98/02/23
9  *
10  *   - DB version 2.6.4b   ; 1998/12/28, /KSp
11  *   - DB_DBT_MALLOC       ; 1998/03/22, /KSp
12  *   - basic implementation; 1998/02/23, /KSp
13  */
14
15 #include "portable.h"
16
17 #ifdef SLAPD_LDBM
18
19 #include <stdio.h>
20
21 #include <ac/stdlib.h>
22 #include <ac/string.h>
23 #include <ac/errno.h>
24
25 #include "ldbm.h"
26 #include "ldap_pvt_thread.h"
27
28 void
29 ldbm_datum_free( LDBM ldbm, Datum data )
30 {
31         if ( data.dptr ) {
32                 free( data.dptr );
33                 memset( &data, '\0', sizeof( Datum ));
34                 data.dptr = NULL;
35         }
36 }
37
38
39 Datum
40 ldbm_datum_dup( LDBM ldbm, Datum data )
41 {
42         Datum   dup;
43
44         ldbm_datum_init( dup );
45
46         if ( data.dsize == 0 ) {
47                 dup.dsize = 0;
48                 dup.dptr = NULL;
49
50                 return( dup );
51         }
52         dup.dsize = data.dsize;
53
54         if ( (dup.dptr = (char *) malloc( data.dsize )) != NULL ) {
55                 AC_MEMCPY( dup.dptr, data.dptr, data.dsize );
56         }
57
58         return( dup );
59 }
60
61 static int ldbm_initialized = 0;
62
63 #ifdef HAVE_BERKELEY_DB_THREAD
64 #define LDBM_LOCK       ((void) 0)
65 #define LDBM_UNLOCK     ((void) 0)
66 #else
67 static ldap_pvt_thread_mutex_t ldbm_big_mutex;
68 #define LDBM_LOCK       (ldap_pvt_thread_mutex_lock(&ldbm_big_mutex))
69 #define LDBM_UNLOCK     (ldap_pvt_thread_mutex_unlock(&ldbm_big_mutex))
70 #endif
71
72
73 /*******************************************************************
74  *                                                                 *
75  *  Create some special functions to initialize Berkeley DB for    *
76  *  versions greater than 2.                                       *
77  *                                                                 *
78  *******************************************************************/
79 #if defined( HAVE_BERKELEY_DB ) && (DB_VERSION_MAJOR >= 2)
80
81 void *
82 ldbm_malloc( size_t size )
83 {
84         return( calloc( 1, size ));
85 }
86
87 #ifdef LDAP_SYSLOG
88 #include <ac/syslog.h>
89 #endif
90
91 static void
92 ldbm_db_errcall( const char *prefix, char *message )
93 {
94 #ifdef LDAP_SYSLOG
95         syslog( LOG_INFO, "ldbm: %s %s", prefix, message );
96 #endif
97 }
98
99 /*  a dbEnv for BERKELEYv2  */
100 DB_ENV  *ldbm_Env = NULL;
101
102 int ldbm_initialize( const char* home )
103 {
104         int     err;
105         u_int32_t       envFlags;
106
107         if(ldbm_initialized++) return 1;
108
109         {
110                 char *version;
111                 int major, minor, patch;
112                 version = db_version( &major, &minor, &patch );
113
114                 if( major != DB_VERSION_MAJOR ||
115                         minor < DB_VERSION_MINOR )
116                 {
117 #ifdef LDAP_SYSLOG
118                         char error[BUFSIZ];
119
120                         sprintf( error, "%s (%d)\n", STRERROR( err ), err );
121
122                         syslog( LOG_INFO,
123                                 "ldbm_initialize(): version mismatch\nexpected: %s\ngot: %s\n",
124                                 DB_VERSION_STRING,
125                                 version );
126 #endif
127
128                         return 1;
129                 }
130         }
131
132 #ifndef HAVE_BERKELEY_DB_THREAD
133         ldap_pvt_thread_mutex_init( &ldbm_big_mutex );
134 #endif
135
136 #if DB_VERSION_MAJOR < 3
137         ldbm_Env = calloc( 1, sizeof( DB_ENV ));
138
139         if( ldbm_Env == NULL ) return 1;
140
141         ldbm_Env->db_errcall    = ldbm_db_errcall;
142         ldbm_Env->db_errpfx             = "==>";
143 #else
144         ldbm_Env = NULL;
145 #endif
146
147         envFlags = DB_CREATE;
148
149         /* add optional flags */
150 #ifdef DB_PRIVATE
151         envFlags |= DB_PRIVATE;
152 #endif
153
154 #ifdef HAVE_BERKELEY_DB_THREAD
155         envFlags |= DB_THREAD | DB_INIT_CDB | DB_INIT_MPOOL;
156 #ifdef DB_MPOOL_PRIVATE
157         envFlags |= DB_MPOOL_PRIVATE;
158 #endif
159 #endif
160
161 #if DB_VERSION_MAJOR >= 3
162         err = db_env_create( &ldbm_Env, 0 );
163 #else
164         envFlags |= DB_USE_ENVIRON;
165         err = db_appinit( home, NULL, ldbm_Env, envFlags );
166 #endif
167
168         if ( err ) {
169 #ifdef LDAP_SYSLOG
170                 char error[BUFSIZ];
171
172                 sprintf( error, "%s (%d)\n", STRERROR( err ), err );
173
174                 syslog( LOG_INFO,
175 #if DB_VERSION_MAJOR >= 3
176                         "ldbm_initialize(): FATAL error in db_env_create() : %s\n",
177 #else
178                         "ldbm_initialize(): FATAL error in db_appinit() : %s\n",
179 #endif
180                         error );
181 #endif
182                 return( 1 );
183         }
184
185 #if DB_VERSION_MAJOR > 2
186         ldbm_Env->set_errcall( ldbm_Env, ldbm_db_errcall );
187         ldbm_Env->set_errpfx( ldbm_Env, "==>" );
188
189 #ifdef HAVE_BERKELEY_DB_THREAD
190         envFlags |= DB_INIT_CDB | DB_INIT_MPOOL;
191 #endif
192         envFlags |= DB_USE_ENVIRON;
193
194 #if (DB_VERSION_MAJOR > 3) || (DB_VERSION_MINOR >= 1)
195         err = ldbm_Env->open( ldbm_Env, home, envFlags, 0 );
196 #else
197         err = ldbm_Env->open( ldbm_Env, home, NULL, envFlags, 0 );
198 #endif
199
200         if ( err != 0 ) {
201 #ifdef LDAP_SYSLOG
202                 char error[BUFSIZ];
203
204                 sprintf( error, "%s (%d)\n", STRERROR( err ), err );
205                 syslog( LOG_INFO,
206                         "ldbm_initialize(): FATAL error in dbEnv->open() : %s\n",
207                         error );
208 #endif
209                 ldbm_Env->close( ldbm_Env, 0 );
210                 return( 1 );
211         }
212 #endif
213
214         return 0;
215 }
216
217 int ldbm_shutdown( void )
218 {
219         if( !ldbm_initialized ) return 1;
220
221 #if DB_VERSION_MAJOR >= 3
222         ldbm_Env->close( ldbm_Env, 0 );
223 #else
224         db_appexit( ldbm_Env );
225 #endif
226
227 #ifndef HAVE_BERKELEY_DB_THREAD
228         ldap_pvt_thread_mutex_destroy( &ldbm_big_mutex );
229 #endif
230
231         return 0;
232 }
233
234 #else  /* some DB other than Berkeley V2 or greater */
235
236 int ldbm_initialize( const char * home )
237 {
238         if(ldbm_initialized++) return 1;
239
240         ldap_pvt_thread_mutex_init( &ldbm_big_mutex );
241
242         return 0;
243 }
244
245 int ldbm_shutdown( void )
246 {
247         if( !ldbm_initialized ) return 1;
248
249         ldap_pvt_thread_mutex_destroy( &ldbm_big_mutex );
250
251         return 0;
252 }
253
254 #endif /* HAVE_BERKELEY_DB */
255
256
257 #if defined( LDBM_USE_DBHASH ) || defined( LDBM_USE_DBBTREE )
258
259 /*****************************************************************
260  *                                                               *
261  * use berkeley db hash or btree package                         *
262  *                                                               *
263  *****************************************************************/
264
265 LDBM
266 ldbm_open( char *name, int rw, int mode, int dbcachesize )
267 {
268         LDBM            ret = NULL;
269
270 #if DB_VERSION_MAJOR >= 3
271         int err;
272
273         LDBM_LOCK;
274
275         err = db_create( &ret, ldbm_Env, 0 );
276         if ( err != 0 ) {
277                 (void)ret->close(ret, 0);
278                 LDBM_UNLOCK;
279
280                 return NULL;
281         }
282
283         ret->set_pagesize( ret, DEFAULT_DB_PAGE_SIZE );
284         ret->set_malloc( ret, ldbm_malloc );
285
286         err = ret->open( ret, name, NULL, DB_TYPE, rw, mode);
287
288         if ( err != 0 ) {
289                 int tmp = errno;
290                 (void)ret->close(ret, 0);
291                 errno = tmp;
292
293                 LDBM_UNLOCK;
294                 return NULL;
295         }
296
297         LDBM_UNLOCK;
298  
299 #elif DB_VERSION_MAJOR >= 2
300         DB_INFO dbinfo;
301
302         memset( &dbinfo, '\0', sizeof( dbinfo ));
303
304 #if     DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 4
305         /*
306          * BerkeleyDB 2.4 do not allow db_cachesize
307          * to be specified if an DB_ENV is.
308          */
309 #else
310         /* set db_cachesize of MPOOL is NOT being used. */
311         if (( ldbm_Env == NULL ) || ( ldbm_Env->mp_info == NULL )) {
312                 dbinfo.db_cachesize = dbcachesize;
313         }
314 #endif
315
316         dbinfo.db_pagesize      = DEFAULT_DB_PAGE_SIZE;
317         dbinfo.db_malloc        = ldbm_malloc;
318
319         LDBM_LOCK;
320         (void) db_open( name, DB_TYPE, rw, mode, ldbm_Env, &dbinfo, &ret );
321         LDBM_UNLOCK;
322
323 #else
324         void            *info;
325         BTREEINFO       binfo;
326         HASHINFO        hinfo;
327
328         if ( DB_TYPE == DB_HASH ) {
329                 memset( (char *) &hinfo, '\0', sizeof(hinfo) );
330                 hinfo.cachesize = dbcachesize;
331                 info = &hinfo;
332         } else if ( DB_TYPE == DB_BTREE ) {
333                 memset( (char *) &binfo, '\0', sizeof(binfo) );
334                 binfo.cachesize = dbcachesize;
335                 info = &binfo;
336         } else {
337                 info = NULL;
338         }
339
340         LDBM_LOCK;
341         ret = dbopen( name, rw, mode, DB_TYPE, info );
342         LDBM_UNLOCK;
343 #endif
344
345         return ret;
346 }
347
348 void
349 ldbm_close( LDBM ldbm )
350 {
351         LDBM_LOCK;
352 #if DB_VERSION_MAJOR >= 3
353         ldbm->close( ldbm, 0 );
354 #elif DB_VERSION_MAJOR >= 2
355         (*ldbm->close)( ldbm, 0 );
356 #else
357         (*ldbm->close)( ldbm );
358 #endif
359         LDBM_UNLOCK;
360 }
361
362 void
363 ldbm_sync( LDBM ldbm )
364 {
365         LDBM_LOCK;
366         (*ldbm->sync)( ldbm, 0 );
367         LDBM_UNLOCK;
368 }
369
370 Datum
371 ldbm_fetch( LDBM ldbm, Datum key )
372 {
373         Datum   data;
374         int     rc;
375
376         LDBM_LOCK;
377
378 #if DB_VERSION_MAJOR >= 3
379         ldbm_datum_init( data );
380
381         data.flags = DB_DBT_MALLOC;
382
383         if ( (rc = ldbm->get( ldbm, NULL, &key, &data, 0 )) != 0 ) {
384                 ldbm_datum_free( ldbm, data );
385                 data.dptr = NULL;
386                 data.dsize = 0;
387         }
388
389 #elif DB_VERSION_MAJOR >= 2
390         ldbm_datum_init( data );
391
392         data.flags = DB_DBT_MALLOC;
393
394         if ( (rc = (*ldbm->get)( ldbm, NULL, &key, &data, 0 )) != 0 ) {
395                 ldbm_datum_free( ldbm, data );
396                 data.dptr = NULL;
397                 data.dsize = 0;
398         }
399 #else
400
401         if ( (rc = (*ldbm->get)( ldbm, &key, &data, 0 )) == 0 ) {
402                 /* Berkeley DB 1.85 don't malloc the data for us */
403                 /* duplicate it for to ensure reentrancy */
404                 data = ldbm_datum_dup( ldbm, data );
405         } else {
406                 data.dptr = NULL;
407                 data.dsize = 0;
408         }
409 #endif
410
411         LDBM_UNLOCK;
412
413         return( data );
414 }
415
416 int
417 ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
418 {
419         int     rc;
420
421         LDBM_LOCK;
422
423 #if DB_VERSION_MAJOR >= 3
424         rc = ldbm->put( ldbm, NULL, &key, &data, flags & ~LDBM_SYNC );
425         rc = (-1) * rc;
426
427 #elif DB_VERSION_MAJOR >= 2
428         rc = (*ldbm->put)( ldbm, NULL, &key, &data, flags & ~LDBM_SYNC );
429         rc = (-1) * rc;
430 #else
431         rc = (*ldbm->put)( ldbm, &key, &data, flags & ~LDBM_SYNC );
432 #endif
433
434         if ( flags & LDBM_SYNC )
435                 (*ldbm->sync)( ldbm, 0 );
436
437         LDBM_UNLOCK;
438
439         return( rc );
440 }
441
442 int
443 ldbm_delete( LDBM ldbm, Datum key )
444 {
445         int     rc;
446
447         LDBM_LOCK;
448
449 #if DB_VERSION_MAJOR >= 3
450         rc = ldbm->del( ldbm, NULL, &key, 0 );
451         rc = (-1) * rc;
452 #elif DB_VERSION_MAJOR >= 2
453         rc = (*ldbm->del)( ldbm, NULL, &key, 0 );
454         rc = (-1) * rc;
455 #else
456         rc = (*ldbm->del)( ldbm, &key, 0 );
457 #endif
458         (*ldbm->sync)( ldbm, 0 );
459
460         LDBM_UNLOCK;
461
462         return( rc );
463 }
464
465 Datum
466 ldbm_firstkey( LDBM ldbm, LDBMCursor **dbch )
467 {
468         Datum   key, data;
469
470 #if DB_VERSION_MAJOR >= 2
471         LDBMCursor  *dbci;
472
473         ldbm_datum_init( key );
474         ldbm_datum_init( data );
475
476         key.flags = data.flags = DB_DBT_MALLOC;
477
478         LDBM_LOCK;
479
480         /* acquire a cursor for the DB */
481 # if DB_VERSION_MAJOR >= 3
482         if ( ldbm->cursor( ldbm, NULL, &dbci, 0 ) )
483 # elif defined( DB_VERSION_MAJOR ) && defined( DB_VERSION_MINOR ) && \
484         (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6)
485
486         if ( (*ldbm->cursor)( ldbm, NULL, &dbci ))
487
488 #  else
489         if ( (*ldbm->cursor)( ldbm, NULL, &dbci, 0 ))
490 #  endif
491         {
492                 key.dptr = NULL;
493                 return( key );
494         } else {
495                 *dbch = dbci;
496                 if ( (*dbci->c_get)( dbci, &key, &data, DB_NEXT ) == 0 ) {
497                         ldbm_datum_free( ldbm, data );
498                 }
499         else {
500 #else
501         int     rc;
502
503         LDBM_LOCK;
504
505         if ( (rc = (*ldbm->seq)( ldbm, &key, &data, R_FIRST )) == 0 ) {
506                 key = ldbm_datum_dup( ldbm, key );
507         }
508         else {
509 #endif
510                 key.dptr = NULL;
511                 key.dsize = 0;
512         }
513
514 #if DB_VERSION_MAJOR >= 2
515         }
516 #endif
517
518         LDBM_UNLOCK;
519
520         return( key );
521 }
522
523 Datum
524 ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp )
525 {
526         Datum   data;
527
528 #if DB_VERSION_MAJOR >= 2
529         ldbm_datum_init( data );
530
531         ldbm_datum_free( ldbm, key );
532         key.flags = data.flags = DB_DBT_MALLOC;
533
534         LDBM_LOCK;
535
536         if ( (*dbcp->c_get)( dbcp, &key, &data, DB_NEXT ) == 0 ) {
537                 ldbm_datum_free( ldbm, data );
538         }
539         else {
540 #else
541         int     rc;
542
543         LDBM_LOCK;
544
545         if ( (rc = (*ldbm->seq)( ldbm, &key, &data, R_NEXT )) == 0 ) {
546                 key = ldbm_datum_dup( ldbm, key );
547         }
548         else {
549 #endif
550                 key.dptr = NULL;
551                 key.dsize = 0;
552         }
553
554         LDBM_UNLOCK;
555
556         return( key );
557 }
558
559 int
560 ldbm_errno( LDBM ldbm )
561 {
562         return( errno );
563 }
564
565 /******************************************************************
566  *                                                                *
567  *         END Berkeley section                                   *
568  *                                                                *
569  ******************************************************************/
570
571 #elif defined( HAVE_GDBM )
572
573 #ifdef HAVE_ST_BLKSIZE
574 #include <sys/stat.h>
575 #endif
576
577 /*****************************************************************
578  *                                                               *
579  * use gdbm                                                      *
580  *                                                               *
581  *****************************************************************/
582
583 LDBM
584 ldbm_open( char *name, int rw, int mode, int dbcachesize )
585 {
586         LDBM            db;
587 #ifdef HAVE_ST_BLKSIZE
588                 struct stat     st;
589 #endif
590
591         LDBM_LOCK;
592
593         if ( (db =  gdbm_open( name, 0, rw | GDBM_FAST, mode, 0 )) == NULL ) {
594                 LDBM_UNLOCK;
595                 return( NULL );
596         }
597
598 #ifdef HAVE_ST_BLKSIZE
599         if ( dbcachesize > 0 && stat( name, &st ) == 0 ) {
600                 dbcachesize /= st.st_blksize;
601                 if( dbcachesize == 0 ) dbcachesize = 1;
602                 gdbm_setopt( db, GDBM_CACHESIZE, &dbcachesize, sizeof(int) );
603         }
604 #else
605         if ( dbcachesize > 0 ) {
606                 dbcachesize /= 4096;
607                 if( dbcachesize == 0 ) dbcachesize = 1;
608                 gdbm_setopt( db, GDBM_CACHESIZE, &dbcachesize, sizeof(int) );
609         }
610 #endif
611
612         LDBM_UNLOCK;
613
614         return( db );
615 }
616
617 void
618 ldbm_close( LDBM ldbm )
619 {
620         LDBM_LOCK;
621         gdbm_close( ldbm );
622         LDBM_UNLOCK;
623 }
624
625 void
626 ldbm_sync( LDBM ldbm )
627 {
628         LDBM_LOCK;
629         gdbm_sync( ldbm );
630         LDBM_UNLOCK;
631 }
632
633 Datum
634 ldbm_fetch( LDBM ldbm, Datum key )
635 {
636         Datum d;
637
638         LDBM_LOCK;
639         d = gdbm_fetch( ldbm, key );
640         LDBM_UNLOCK;
641
642         return d;
643 }
644
645 int
646 ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
647 {
648         int     rc;
649
650         LDBM_LOCK;
651         rc = gdbm_store( ldbm, key, data, flags & ~LDBM_SYNC );
652         if ( flags & LDBM_SYNC )
653                 gdbm_sync( ldbm );
654         LDBM_UNLOCK;
655
656         return( rc );
657 }
658
659 int
660 ldbm_delete( LDBM ldbm, Datum key )
661 {
662         int     rc;
663
664         LDBM_LOCK;
665         rc = gdbm_delete( ldbm, key );
666         gdbm_sync( ldbm );
667         LDBM_UNLOCK;
668
669         return( rc );
670 }
671
672 Datum
673 ldbm_firstkey( LDBM ldbm, LDBMCursor **dbcp )
674 {
675         Datum d;
676
677         LDBM_LOCK;
678         d = gdbm_firstkey( ldbm );
679         LDBM_UNLOCK;
680
681         if ( d.dptr != NULL ) {
682                 *dbcp = (Datum *) malloc( sizeof( Datum ) );
683                 **dbcp = ldbm_datum_dup( ldbm, d );
684         }
685
686         return d;
687 }
688
689 Datum
690 ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp )
691 {
692         Datum d;
693
694         LDBM_LOCK;
695         d = gdbm_nextkey( ldbm, *dbcp );
696         LDBM_UNLOCK;
697
698         ldbm_datum_free( ldbm, *dbcp );
699
700         if ( d.dptr != NULL ) {
701                 *dbcp = ldbm_datum_dup( ldbm, d );
702         } else {
703                 free( dbcp );
704         }
705
706         return d;
707 }
708
709 int
710 ldbm_errno( LDBM ldbm )
711 {
712         int err;
713
714         LDBM_LOCK;
715         err = gdbm_errno;
716         LDBM_UNLOCK;
717
718         return( err );
719 }
720
721 #elif HAVE_MDBM
722
723 /* MMAPED DBM HASHING DATABASE */
724
725 #include <ac/string.h>
726
727 /* #define MDBM_DEBUG */
728
729 #ifdef MDBM_DEBUG
730 #include <stdio.h>
731 #endif
732
733 #define NO_NULL_KEY
734 /* #define MDBM_CHAIN */
735
736 #ifdef MDBM_CHAIN
737
738 /* Use chaining */
739
740
741 #define mdbm_store      mdbm_chain_store
742 #define mdbm_fetch      mdbm_chain_fetch
743 #define mdbm_delete     mdbm_chain_delete
744 #define mdbm_first      mdbm_chain_first
745 #define mdbm_next       mdbm_chain_next
746
747 #endif
748
749 #define MDBM_PG_SZ      (4*1024)
750
751 /*****************************************************************
752  *                                                               *
753  * use mdbm                                                      *
754  *                                                               *
755  *****************************************************************/
756
757 LDBM
758 ldbm_open( char *name, int rw, int mode, int dbcachesize )
759 {
760         LDBM            db;
761
762 #ifdef MDBM_DEBUG
763         fprintf( stdout,
764                  "==>(mdbm)ldbm_open(name=%s,rw=%x,mode=%x,cachesize=%d)\n",
765                  name ? name : "NULL", rw, mode, dbcachesize );
766         fflush( stdout );
767 #endif
768
769         LDBM_LOCK;      /* We need locking here, this is the only non-thread
770                          * safe function we have.
771                          */
772
773         if ( (db =  mdbm_open( name, rw, mode, MDBM_PG_SZ )) == NULL ) {
774
775                 LDBM_UNLOCK;
776 #ifdef MDBM_DEBUG
777                 fprintf( stdout, "<==(mdbm)ldbm_open(db=NULL)\n" );
778                 fflush( stdout );
779 #endif
780                 return( NULL );
781
782         }
783
784 #ifdef MDBM_CHAIN
785         (void)mdbm_set_chain(db);
786 #endif
787
788         LDBM_UNLOCK;
789
790 #ifdef MDBM_DEBUG
791         fprintf( stdout, "<==(mdbm)ldbm_open(db=%p)\n", db );
792         fflush( stdout );
793 #endif
794
795         return( db );
796
797 }
798
799
800
801
802 void
803 ldbm_close( LDBM ldbm )
804 {
805
806         /* Open and close are not reentrant so we need to use locks here */
807
808 #ifdef MDBM_DEBUG
809         fprintf( stdout,
810                  "==>(mdbm)ldbm_close(db=%p)\n", ldbm );
811         fflush( stdout );
812 #endif
813
814         LDBM_LOCK;
815         mdbm_close( ldbm );
816         LDBM_UNLOCK;
817
818 #ifdef MDBM_DEBUG
819         fprintf( stdout, "<==(mdbm)ldbm_close()\n" );
820         fflush( stdout );
821 #endif
822
823 }
824
825
826
827
828 void
829 ldbm_sync( LDBM ldbm )
830 {
831         /* XXX: Not sure if this is re-entrant need to check code, if so
832          * you can leave LOCKS out.
833          */
834
835         LDBM_LOCK;
836         mdbm_sync( ldbm );
837         LDBM_UNLOCK;
838 }
839
840
841 #define MAX_MDBM_RETRY  5
842
843 Datum
844 ldbm_fetch( LDBM ldbm, Datum key )
845 {
846         Datum   d;
847         kvpair  k;
848         int     retry = 0;
849
850         /* This hack is needed because MDBM does not take keys
851          * which begin with NULL when working in the chaining
852          * mode.
853          */
854
855         /* LDBM_LOCK; */
856
857 #ifdef NO_NULL_KEY
858         k.key.dsize = key.dsize + 1;                    
859         k.key.dptr = malloc(k.key.dsize);
860         *(k.key.dptr) = 'l';
861         AC_MEMCPY( (void *)(k.key.dptr + 1), key.dptr, key.dsize );     
862 #else
863         k.key = key;
864 #endif  
865
866         k.val.dptr = NULL;
867         k.val.dsize = 0;
868
869         do {
870
871                 d = mdbm_fetch( ldbm, k );
872
873                 if ( d.dsize > 0 ) {
874
875                         if ( k.val.dptr != NULL ) {
876                                 free( k.val.dptr );
877                         }
878
879                         if ( (k.val.dptr = malloc( d.dsize )) != NULL ) {
880                 
881                                 k.val.dsize = d.dsize;
882                                 d = mdbm_fetch( ldbm, k );
883
884                         } else { 
885
886                                 d.dsize = 0;
887                                 break;
888                         
889                         }
890
891                 }/* if ( d.dsize > 0 ) */
892
893         } while ((d.dsize > k.val.dsize) && (++retry < MAX_MDBM_RETRY));
894
895         /* LDBM_UNLOCK; */
896
897 #ifdef NO_NULL_KEY
898         free(k.key.dptr);
899 #endif
900
901         return d;
902
903 }
904
905
906
907
908 int
909 ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
910 {
911         int     rc;
912         Datum   int_key;        /* Internal key */
913
914 #ifdef MDBM_DEBUG
915         fprintf( stdout,
916                  "==>(mdbm)ldbm_store(db=%p, key(dptr=%p,sz=%d), data(dptr=%p,sz=%d), flags=%x)\n",
917                  ldbm, key.dptr, key.dsize, data.dptr, data.dsize, flags );
918         fflush( stdout );
919 #endif
920
921         /* LDBM_LOCK; */
922
923 #ifdef NO_NULL_KEY
924         int_key.dsize = key.dsize + 1;
925         int_key.dptr = malloc( int_key.dsize );
926         *(int_key.dptr) = 'l';  /* Must not be NULL !*/
927         AC_MEMCPY( (void *)(int_key.dptr + 1), key.dptr, key.dsize );
928 #else
929         int_key = key;
930 #endif
931
932         rc = mdbm_store( ldbm, int_key, data, flags );
933         if ( flags & LDBM_SYNC ) {
934                 mdbm_sync( ldbm );
935         }
936
937         /* LDBM_UNLOCK; */
938
939 #ifdef MDBM_DEBUG
940         fprintf( stdout, "<==(mdbm)ldbm_store(rc=%d)\n", rc );
941         fflush( stdout );
942 #endif
943
944 #ifdef NO_NULL_KEY
945         free(int_key.dptr);
946 #endif
947
948         return( rc );
949
950 }
951
952
953
954 int
955 ldbm_delete( LDBM ldbm, Datum key )
956 {
957         int     rc;
958         Datum   int_key;
959
960         /* LDBM_LOCK; */
961
962 #ifdef NO_NULL_KEY
963         int_key.dsize = key.dsize + 1;
964         int_key.dptr = malloc(int_key.dsize);
965         *(int_key.dptr) = 'l';
966         AC_MEMCPY( (void *)(int_key.dptr + 1), key.dptr, key.dsize );   
967 #else
968         int_key = key;
969 #endif
970         
971         rc = mdbm_delete( ldbm, int_key );
972
973         /* LDBM_UNLOCK; */
974 #ifdef NO_NULL_KEY
975         free(int_key.dptr);
976 #endif
977
978         return( rc );
979 }
980
981
982
983
984 static Datum
985 ldbm_get_next( LDBM ldbm, kvpair (*fptr)(MDBM *, kvpair) ) 
986 {
987         kvpair  out;
988         kvpair  in;
989         Datum   ret;
990         size_t  sz = MDBM_PAGE_SIZE(ldbm);
991 #ifdef NO_NULL_KEY
992         int     delta = 1;
993 #else
994         int     delta = 0;
995 #endif
996
997         /* LDBM_LOCK; */
998
999         in.key.dsize = sz;      /* Assume first key in one pg */
1000         in.key.dptr = malloc(sz);
1001         
1002         in.val.dptr = NULL;     /* Don't need data just key */ 
1003         in.val.dsize = 0;
1004
1005         ret.dptr = NULL;
1006         ret.dsize = NULL;
1007
1008         out = fptr( ldbm, in );
1009
1010         if (out.key.dsize > 0) {
1011                 ret.dsize = out.key.dsize - delta;
1012
1013                 if ((ret.dptr = (char *)malloc(ret.dsize)) == NULL) { 
1014                         ret.dsize = 0;
1015                         ret.dptr = NULL;
1016
1017                 } else {
1018                         AC_MEMCPY(ret.dptr, (void *)(out.key.dptr + delta),
1019                                 ret.dsize );
1020             }
1021         }
1022
1023         /* LDBM_UNLOCK; */
1024         
1025         free(in.key.dptr);
1026         return ret;
1027 }
1028
1029 Datum
1030 ldbm_firstkey( LDBM ldbm, LDBMCursor **dbcp )
1031 {
1032         return ldbm_get_next( ldbm, mdbm_first );
1033 }
1034
1035 Datum
1036 ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp )
1037 {
1038         /* XXX:
1039          * don't know if this will affect the LDAP server operation 
1040          * but mdbm cannot take and input key.
1041          */
1042
1043         return ldbm_get_next( ldbm, mdbm_next );
1044 }
1045
1046 int
1047 ldbm_errno( LDBM ldbm )
1048 {
1049         /* XXX: best we can do with current  mdbm interface */
1050         return( errno );
1051 }
1052
1053
1054
1055
1056 #elif defined( HAVE_NDBM )
1057
1058 /*****************************************************************
1059  *                                                               *
1060  * if no gdbm or mdbm, fall back to using ndbm, the standard unix thing  *
1061  *                                                               *
1062  *****************************************************************/
1063
1064 /* ARGSUSED */
1065 LDBM
1066 ldbm_open( char *name, int rw, int mode, int dbcachesize )
1067 {
1068         LDBM ldbm;
1069
1070         LDBM_LOCK;
1071         ldbm = dbm_open( name, rw, mode );
1072         LDBM_UNLOCK;
1073
1074         return( ldbm );
1075 }
1076
1077 void
1078 ldbm_close( LDBM ldbm )
1079 {
1080         LDBM_LOCK;
1081         dbm_close( ldbm );
1082         LDBM_UNLOCK;
1083 }
1084
1085 /* ARGSUSED */
1086 void
1087 ldbm_sync( LDBM ldbm )
1088 {
1089         return;
1090 }
1091
1092 Datum
1093 ldbm_fetch( LDBM ldbm, Datum key )
1094 {
1095         Datum d;
1096
1097         LDBM_LOCK;
1098         d = ldbm_datum_dup( ldbm, dbm_fetch( ldbm, key ) );
1099         LDBM_UNLOCK;
1100
1101         return d;
1102 }
1103
1104 int
1105 ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
1106 {
1107         int rc;
1108
1109         LDBM_LOCK;
1110         rc = dbm_store( ldbm, key, data, flags );
1111         LDBM_UNLOCK;
1112
1113         return rc;
1114 }
1115
1116 int
1117 ldbm_delete( LDBM ldbm, Datum key )
1118 {
1119         int rc;
1120
1121         LDBM_LOCK;
1122         rc = dbm_delete( ldbm, key );
1123         LDBM_UNLOCK;
1124
1125         return rc;
1126 }
1127
1128 Datum
1129 ldbm_firstkey( LDBM ldbm, LDBMCursor **dbcp )
1130 {
1131         Datum d;
1132
1133         LDBM_LOCK;
1134         d = dbm_firstkey( ldbm );
1135         LDBM_UNLOCK;
1136
1137         return d;
1138 }
1139
1140 Datum
1141 ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp )
1142 {
1143         Datum d;
1144
1145         LDBM_LOCK;
1146         d = dbm_nextkey( ldbm );
1147         LDBM_UNLOCK;
1148
1149         return d;
1150 }
1151
1152 int
1153 ldbm_errno( LDBM ldbm )
1154 {
1155         int err;
1156
1157         LDBM_LOCK;
1158         err = dbm_error( ldbm );
1159         LDBM_UNLOCK;
1160
1161         return err;
1162 }
1163
1164 #endif /* ndbm */
1165 #endif /* ldbm */