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