]> git.sur5r.net Git - openldap/blobdiff - libraries/libldbm/ldbm.c
Provide a little information about SDF, how to use it, and where to get it.h
[openldap] / libraries / libldbm / ldbm.c
index 23e6f842f9e55eba8e2b38c2237011f4a60c22eb..0ce41481c8213a876c0c8826c69fa0edce2b1e47 100644 (file)
@@ -2,8 +2,9 @@
 
 /* Patched for Berkeley DB version 2.0; /KSp; 98/02/23
  *
- *   - basic implementation; 1998/02/23, /KSp
+ *   - DB version 2.6.4b   ; 1998/12/28, /KSp
  *   - DB_DBT_MALLOC       ; 1998/03/22, /KSp
+ *   - basic implementation; 1998/02/23, /KSp
  */
 
 #include "portable.h"
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <ac/string.h>
 #include <ac/errno.h>
 
 #include "ldbm.h"
+#include "ldap_pvt_thread.h"
 
-#if defined( LDBM_USE_DBHASH ) || defined( LDBM_USE_DBBTREE )
 
-/*****************************************************************
- *                                                               *
- * use berkeley db hash or btree package                         *
- *                                                               *
- *****************************************************************/
+void
+ldbm_datum_free( LDBM ldbm, Datum data )
+{
+       if ( data.dptr ) {
+               free( data.dptr );
+               memset( &data, 0, sizeof( Datum ));
+               data.dptr = NULL;
+       }
+}
 
-#ifdef HAVE_BERKELEY_DB2
-/*************************************************
- *                                               *
- *  A malloc routine for use with DB_DBT_MALLOC  *
- *                                               *
- *************************************************/
+
+Datum
+ldbm_datum_dup( LDBM ldbm, Datum data )
+{
+       Datum   dup;
+
+       ldbm_datum_init( dup );
+
+       if ( data.dsize == 0 ) {
+               dup.dsize = 0;
+               dup.dptr = NULL;
+
+               return( dup );
+       }
+       dup.dsize = data.dsize;
+       if ( (dup.dptr = (char *) malloc( data.dsize )) != NULL )
+               memcpy( dup.dptr, data.dptr, data.dsize );
+
+       return( dup );
+}
+
+static int ldbm_initialized = 0;
+
+#ifndef HAVE_BERKELEY_DB2
+/* Everything but DB2 is non-reentrant */
+
+static ldap_pvt_thread_mutex_t ldbm_big_mutex;
+#define LDBM_LOCK      (ldap_pvt_thread_mutex_lock(&ldbm_big_mutex))
+#define LDBM_UNLOCK    (ldap_pvt_thread_mutex_unlock(&ldbm_big_mutex))
+
+int ldbm_initialize( void )
+{
+       if(ldbm_initialized++) return 1;
+
+       ldap_pvt_thread_mutex_init( &ldbm_big_mutex );
+
+       return 0;
+}
+
+int ldbm_shutdown( void )
+{
+       if( !ldbm_initialized ) return 1;
+
+       ldap_pvt_thread_mutex_destroy( &ldbm_big_mutex );
+
+       return 0;
+}
+
+#else
+
+#ifndef WIN32
+#ifdef HAVE_SYSLOG
+#include "syslog.h"
+#else
+/* quick hack */
+#define LOG_INFO 1
+extern int syslog(int, char*, ...);
+#endif
+#endif /* WIN32 */
 
 void *
 ldbm_malloc( size_t size )
@@ -37,8 +96,75 @@ ldbm_malloc( size_t size )
        return( calloc( 1, size ));
 }
 
+static void
+ldbm_db_errcall( const char *prefix, char *message )
+{
+#ifndef WIN32
+       syslog( LOG_INFO, "ldbm_db_errcall(): %s %s", prefix, message );
 #endif
+}
+
+/*  a dbEnv for BERKELEYv2  */
+static DB_ENV    ldbm_Env_internal;
+DB_ENV           *ldbm_Env = NULL;
+
+/* Berkeley DB 2.x is reentrant */
+#define LDBM_LOCK      ((void)0)
+#define LDBM_UNLOCK    ((void)0)
+
+int ldbm_initialize( void )
+{
+       int     err;
+       int     envFlags;
+
+       if(ldbm_initialized++) return 1;
+
+       memset( &ldbm_Env_internal, 0, sizeof( DB_ENV ));
+       ldbm_Env = &ldbm_Env_internal;
+
+       ldbm_Env->db_errcall   = ldbm_db_errcall;
+       ldbm_Env->db_errpfx    = "==>";
+
+       envFlags = DB_CREATE | DB_THREAD;
+
+       if ( ( err = db_appinit( NULL, NULL, ldbm_Env, envFlags )) ) {
+               char  error[BUFSIZ];
 
+               if ( err < 0 ) {
+                       sprintf( error, "%ld\n", (long) err );
+               } else {
+                       sprintf( error, "%s\n", strerror( err ));
+               }
+
+#ifndef WIN32
+               syslog( LOG_INFO,
+                       "ldbm_initialize(): FATAL error in db_appinit() : %s\n",
+                       error );
+#endif
+               return( 1 );
+       }
+
+       return 0;
+}
+
+int ldbm_shutdown( void )
+{
+       if( !ldbm_initialized ) return 1;
+
+       db_appexit( ldbm_Env );
+
+       return 0;
+}
+
+#endif
+
+#if defined( LDBM_USE_DBHASH ) || defined( LDBM_USE_DBBTREE )
+
+/*****************************************************************
+ *                                                               *
+ * use berkeley db hash or btree package                         *
+ *                                                               *
+ *****************************************************************/
 
 LDBM
 ldbm_open( char *name, int rw, int mode, int dbcachesize )
@@ -46,14 +172,17 @@ ldbm_open( char *name, int rw, int mode, int dbcachesize )
        LDBM            ret = NULL;
 
 #ifdef HAVE_BERKELEY_DB2
-       DB_INFO         dbinfo;
+       DB_INFO dbinfo;
 
        memset( &dbinfo, 0, sizeof( dbinfo ));
-       dbinfo.db_cachesize = dbcachesize;
+       if (( ldbm_Env == NULL ) || ( ldbm_Env->mp_info == NULL ))
+               dbinfo.db_cachesize = dbcachesize;
        dbinfo.db_pagesize  = DEFAULT_DB_PAGE_SIZE;
        dbinfo.db_malloc    = ldbm_malloc;
 
-       db_open( name, DB_TYPE, rw, mode, NULL, &dbinfo, &ret );
+       LDBM_LOCK;
+    (void) db_open( name, DB_TYPE, rw, mode, ldbm_Env, &dbinfo, &ret );
+       LDBM_UNLOCK;
 
 #else
        void            *info;
@@ -72,7 +201,9 @@ ldbm_open( char *name, int rw, int mode, int dbcachesize )
                info = NULL;
        }
 
+       LDBM_LOCK;
        ret = dbopen( name, rw, mode, DB_TYPE, info );
+       LDBM_UNLOCK;
 
 #endif
 
@@ -82,45 +213,21 @@ ldbm_open( char *name, int rw, int mode, int dbcachesize )
 void
 ldbm_close( LDBM ldbm )
 {
+       LDBM_LOCK;
 #ifdef HAVE_BERKELEY_DB2
        (*ldbm->close)( ldbm, 0 );
 #else
        (*ldbm->close)( ldbm );
 #endif
+       LDBM_UNLOCK;
 }
 
 void
 ldbm_sync( LDBM ldbm )
 {
+       LDBM_LOCK;
        (*ldbm->sync)( ldbm, 0 );
-}
-
-void
-ldbm_datum_free( LDBM ldbm, Datum data )
-{
-       free( data.dptr );
-}
-
-Datum
-ldbm_datum_dup( LDBM ldbm, Datum data )
-{
-       Datum   dup;
-
-#ifdef HAVE_BERKELEY_DB2
-       memset( &dup, 0, sizeof( dup ));
-#endif
-
-       if ( data.dsize == 0 ) {
-               dup.dsize = 0;
-               dup.dptr = NULL;
-
-               return( dup );
-       }
-       dup.dsize = data.dsize;
-       if ( dup.dptr = (char *) malloc( data.dsize ) )
-               memcpy( dup.dptr, data.dptr, data.dsize );
-
-       return( dup );
+       LDBM_UNLOCK;
 }
 
 Datum
@@ -129,15 +236,19 @@ ldbm_fetch( LDBM ldbm, Datum key )
        Datum   data;
        int     rc;
 
+       LDBM_LOCK;
+
 #ifdef HAVE_BERKELEY_DB2
-       memset( &data, 0, sizeof( data ));
+       ldbm_datum_init( data );
 
        data.flags = DB_DBT_MALLOC;
 
        if ( (rc = (*ldbm->get)( ldbm, NULL, &key, &data, 0 )) != 0 ) {
-               if ( data.dptr ) free( data.dptr );
+               ldbm_datum_free( ldbm, data );
 #else
        if ( (rc = (*ldbm->get)( ldbm, &key, &data, 0 )) == 0 ) {
+               /* Berkeley DB 1.85 don't malloc the data for us */
+               /* duplicate it for to ensure reentrancy */
                data = ldbm_datum_dup( ldbm, data );
        } else {
 #endif
@@ -145,6 +256,8 @@ ldbm_fetch( LDBM ldbm, Datum key )
                data.dsize = 0;
        }
 
+       LDBM_UNLOCK;
+
        return( data );
 }
 
@@ -153,14 +266,20 @@ ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
 {
        int     rc;
 
+       LDBM_LOCK;
+
 #ifdef HAVE_BERKELEY_DB2
        rc = (*ldbm->put)( ldbm, NULL, &key, &data, flags & ~LDBM_SYNC );
        rc = (-1 ) * rc;
 #else
        rc = (*ldbm->put)( ldbm, &key, &data, flags & ~LDBM_SYNC );
 #endif
+
        if ( flags & LDBM_SYNC )
                (*ldbm->sync)( ldbm, 0 );
+
+       LDBM_UNLOCK;
+
        return( rc );
 }
 
@@ -169,6 +288,8 @@ ldbm_delete( LDBM ldbm, Datum key )
 {
        int     rc;
 
+       LDBM_LOCK;
+
 #ifdef HAVE_BERKELEY_DB2
        rc = (*ldbm->del)( ldbm, NULL, &key, 0 );
        rc = (-1 ) * rc;
@@ -176,6 +297,9 @@ ldbm_delete( LDBM ldbm, Datum key )
        rc = (*ldbm->del)( ldbm, &key, 0 );
 #endif
        (*ldbm->sync)( ldbm, 0 );
+
+       LDBM_UNLOCK;
+
        return( rc );
 }
 
@@ -187,28 +311,46 @@ ldbm_firstkey( LDBM ldbm )
 #endif
 {
        Datum   key, data;
-       int     rc;
 
 #ifdef HAVE_BERKELEY_DB2
        DBC  *dbci;
 
-       memset( &key, 0, sizeof( key ));
-       memset( &data, 0, sizeof( data ));
+       ldbm_datum_init( key );
+       ldbm_datum_init( data );
 
        key.flags = data.flags = DB_DBT_MALLOC;
 
+       LDBM_LOCK;
+
        /* acquire a cursor for the DB */
-       if ( (*ldbm->cursor)( ldbm, NULL, &dbci )) {
+
+#  if defined( DB_VERSION_MAJOR ) && defined( DB_VERSION_MINOR ) && \
+    DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
+
+       if ( (*ldbm->cursor)( ldbm, NULL, &dbci )) 
+
+#  else
+       if ( (*ldbm->cursor)( ldbm, NULL, &dbci, 0 ))
+#  endif
+       {
+               key.dptr = NULL;
                return( key );
        } else {
                *dbch = dbci;
                if ( (*dbci->c_get)( dbci, &key, &data, DB_NEXT ) == 0 ) {
-                       if ( data.dptr ) free( data.dptr );
+                       ldbm_datum_free( ldbm, data );
+               }
+       else {
 #else
+       int     rc;
+
+       LDBM_LOCK;
+
        if ( (rc = (*ldbm->seq)( ldbm, &key, &data, R_FIRST )) == 0 ) {
                key = ldbm_datum_dup( ldbm, key );
+       }
+       else {
 #endif
-       } else {
                key.dptr = NULL;
                key.dsize = 0;
        }
@@ -217,6 +359,8 @@ ldbm_firstkey( LDBM ldbm )
        }
 #endif
 
+       LDBM_UNLOCK;
+
        return( key );
 }
 
@@ -228,28 +372,34 @@ ldbm_nextkey( LDBM ldbm, Datum key )
 #endif
 {
        Datum   data;
-       int     rc;
 
 #ifdef HAVE_BERKELEY_DB2
-       void *oldKey = key.dptr;
+       ldbm_datum_init( data );
 
-       memset( &data, 0, sizeof( data ));
+       ldbm_datum_free( ldbm, key );
+       key.flags = data.flags = DB_DBT_MALLOC;
 
-       data.flags = DB_DBT_MALLOC;
+       LDBM_LOCK;
 
        if ( (*dbcp->c_get)( dbcp, &key, &data, DB_NEXT ) == 0 ) {
-               if ( data.dptr ) free( data.dptr );
+               ldbm_datum_free( ldbm, data );
+       }
+       else {
 #else
+       int     rc;
+
+       LDBM_LOCK;
+
        if ( (rc = (*ldbm->seq)( ldbm, &key, &data, R_NEXT )) == 0 ) {
                key = ldbm_datum_dup( ldbm, key );
+       }
+       else {
 #endif
-       } else {
                key.dptr = NULL;
                key.dsize = 0;
        }
-#ifdef HAVE_BERKELEY_DB2
-       if ( oldKey ) free( oldKey );
-#endif
+
+       LDBM_UNLOCK;
 
        return( key );
 }
@@ -262,11 +412,13 @@ ldbm_errno( LDBM ldbm )
 
 #elif defined( HAVE_GDBM )
 
+#ifdef HAVE_ST_BLKSIZE
 #include <sys/stat.h>
+#endif
 
 /*****************************************************************
  *                                                               *
- * use gdbm                                                     *
+ * use gdbm                                                      *
  *                                                               *
  *****************************************************************/
 
@@ -274,15 +426,28 @@ LDBM
 ldbm_open( char *name, int rw, int mode, int dbcachesize )
 {
        LDBM            db;
-       struct stat     st;
+#ifdef HAVE_ST_BLKSIZE
+               struct stat     st;
+#endif
+
+       LDBM_LOCK;
 
        if ( (db =  gdbm_open( name, 0, rw | GDBM_FAST, mode, 0 )) == NULL ) {
+               LDBM_UNLOCK;
                return( NULL );
        }
+
+#ifdef HAVE_ST_BLKSIZE
        if ( dbcachesize > 0 && stat( name, &st ) == 0 ) {
                dbcachesize = (dbcachesize / st.st_blksize);
                gdbm_setopt( db, GDBM_CACHESIZE, &dbcachesize, sizeof(int) );
        }
+#else
+       dbcachesize = (dbcachesize / 4096);
+       gdbm_setopt( db, GDBM_CACHESIZE, &dbcachesize, sizeof(int) );
+#endif
+
+       LDBM_UNLOCK;
 
        return( db );
 }
@@ -290,43 +455,29 @@ ldbm_open( char *name, int rw, int mode, int dbcachesize )
 void
 ldbm_close( LDBM ldbm )
 {
+       LDBM_LOCK;
        gdbm_close( ldbm );
+       LDBM_UNLOCK;
 }
 
 void
 ldbm_sync( LDBM ldbm )
 {
+       LDBM_LOCK;
        gdbm_sync( ldbm );
-}
-
-void
-ldbm_datum_free( LDBM ldbm, Datum data )
-{
-       free( data.dptr );
+       LDBM_UNLOCK;
 }
 
 Datum
-ldbm_datum_dup( LDBM ldbm, Datum data )
+ldbm_fetch( LDBM ldbm, Datum key )
 {
-       Datum   dup;
+       Datum d;
 
-       if ( data.dsize == 0 ) {
-               dup.dsize = 0;
-               dup.dptr = NULL;
+       LDBM_LOCK;
+       d = gdbm_fetch( ldbm, key );
+       LDBM_UNLOCK;
 
-               return( dup );
-       }
-       dup.dsize = data.dsize;
-       if ( dup.dptr = (char *) malloc( data.dsize ) )
-               memcpy( dup.dptr, data.dptr, data.dsize );
-
-       return( dup );
-}
-
-Datum
-ldbm_fetch( LDBM ldbm, Datum key )
-{
-       return( gdbm_fetch( ldbm, key ) );
+       return d;
 }
 
 int
@@ -334,9 +485,12 @@ ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
 {
        int     rc;
 
+       LDBM_LOCK;
        rc = gdbm_store( ldbm, key, data, flags & ~LDBM_SYNC );
        if ( flags & LDBM_SYNC )
                gdbm_sync( ldbm );
+       LDBM_UNLOCK;
+
        return( rc );
 }
 
@@ -345,116 +499,503 @@ ldbm_delete( LDBM ldbm, Datum key )
 {
        int     rc;
 
+       LDBM_LOCK;
        rc = gdbm_delete( ldbm, key );
        gdbm_sync( ldbm );
+       LDBM_UNLOCK;
+
        return( rc );
 }
 
 Datum
 ldbm_firstkey( LDBM ldbm )
 {
-       return( gdbm_firstkey( ldbm ) );
+       Datum d;
+
+       LDBM_LOCK;
+       d = gdbm_firstkey( ldbm );
+       LDBM_UNLOCK;
+
+       return d;
 }
 
 Datum
 ldbm_nextkey( LDBM ldbm, Datum key )
 {
-       return( gdbm_nextkey( ldbm, key ) );
+       Datum d;
+
+       LDBM_LOCK;
+       d = gdbm_nextkey( ldbm, key );
+       LDBM_UNLOCK;
+
+       return d;
 }
 
 int
 ldbm_errno( LDBM ldbm )
 {
-       return( (int) gdbm_errno );
+       int err;
+
+       LDBM_LOCK;
+       err = gdbm_errno;
+       LDBM_UNLOCK;
+
+       return( err );
 }
 
-#elif defined( HAVE_NDBM )
+#elif HAVE_MDBM
+
+/* MMAPED DBM HASHING DATABASE */
+
+#include <alloca.h>
+#include <string.h>
+
+/* #define MDBM_DEBUG */
+
+#ifdef MDBM_DEBUG
+#include <stdio.h>
+#endif
+
+#define NO_NULL_KEY
+/* #define MDBM_CHAIN */
+
+#ifdef MDBM_CHAIN
+
+/* Use chaining */
+
+
+#define mdbm_store     mdbm_chain_store
+#define mdbm_fetch     mdbm_chain_fetch
+#define mdbm_delete    mdbm_chain_delete
+#define mdbm_first     mdbm_chain_first
+#define mdbm_next      mdbm_chain_next
+
+#endif
+
+#define MDBM_PG_SZ     (4*1024)
 
 /*****************************************************************
  *                                                               *
- * if no gdbm, fall back to using ndbm, the standard unix thing  *
+ * use mdbm                                                      *
  *                                                               *
  *****************************************************************/
 
-/* ARGSUSED */
 LDBM
 ldbm_open( char *name, int rw, int mode, int dbcachesize )
 {
-       return( dbm_open( name, rw, mode ) );
-}
+       LDBM            db;
+
+#ifdef MDBM_DEBUG
+       fprintf( stdout,
+                "==>(mdbm)ldbm_open(name=%s,rw=%x,mode=%x,cachesize=%d)\n",
+                name ? name : "NULL", rw, mode, dbcachesize );
+       fflush( stdout );
+#endif
+
+       LDBM_LOCK;      /* We need locking here, this is the only non-thread
+                        * safe function we have.
+                        */
+
+       if ( (db =  mdbm_open( name, rw, mode, MDBM_PG_SZ )) == NULL ) {
+
+               LDBM_UNLOCK;
+#ifdef MDBM_DEBUG
+               fprintf( stdout, "<==(mdbm)ldbm_open(db=NULL)\n" );
+               fflush( stdout );
+#endif
+               return( NULL );
+
+       }
+
+#ifdef MDBM_CHAIN
+       (void)mdbm_set_chain(db);
+#endif
+
+       LDBM_UNLOCK;
+
+#ifdef MDBM_DEBUG
+       fprintf( stdout, "<==(mdbm)ldbm_open(db=%p)\n", db );
+       fflush( stdout );
+#endif
+
+       return( db );
+
+}/* LDBM ldbm_open() */
+
+
+
 
 void
 ldbm_close( LDBM ldbm )
 {
-       dbm_close( ldbm );
-}
 
-/* ARGSUSED */
+       /* Open and close are not reentrant so we need to use locks here */
+
+#ifdef MDBM_DEBUG
+       fprintf( stdout,
+                "==>(mdbm)ldbm_close(db=%p)\n", ldbm );
+       fflush( stdout );
+#endif
+
+       LDBM_LOCK;
+       mdbm_close( ldbm );
+       LDBM_UNLOCK;
+
+#ifdef MDBM_DEBUG
+       fprintf( stdout, "<==(mdbm)ldbm_close()\n" );
+       fflush( stdout );
+#endif
+
+}/* void ldbm_close() */
+
+
+
+
 void
 ldbm_sync( LDBM ldbm )
 {
-       return;
-}
 
-void
-ldbm_datum_free( LDBM ldbm, Datum data )
-{
-       return;
-}
+       /* XXX: Not sure if this is re-entrant need to check code, if so
+        * you can leave LOCKS out.
+        */
+
+       LDBM_LOCK;
+       mdbm_sync( ldbm );
+        LDBM_UNLOCK;
+
+}/* void ldbm_sync() */
+
+
+#define MAX_MDBM_RETRY 5
 
 Datum
-ldbm_datum_dup( LDBM ldbm, Datum data )
+ldbm_fetch( LDBM ldbm, Datum key )
 {
-       Datum   dup;
+       Datum   d;
+       kvpair  k;
+       int     retry = 0;
 
-       if ( data.dsize == 0 ) {
-               dup.dsize = 0;
-               dup.dptr = NULL;
+       /* This hack is needed because MDBM does not take keys
+        * which begin with NULL when working in the chaining
+        * mode.
+        */
 
-               return( dup );
+       /* LDBM_LOCK; */
+
+#ifdef NO_NULL_KEY
+       k.key.dsize = key.dsize + 1;                    
+       k.key.dptr = alloca(k.key.dsize);
+       *(k.key.dptr) = 'l';
+       memcpy( (void *)(k.key.dptr + 1), key.dptr, key.dsize );        
+#else
+       k.key = key;
+#endif 
+
+       k.val.dptr = NULL;
+       k.val.dsize = 0;
+
+       do {
+
+               d = mdbm_fetch( ldbm, k );
+
+               if ( d.dsize > 0 ) {
+
+                       if ( k.val.dptr != NULL ) {
+                           
+                           free( k.val.dptr );
+
+                       }
+
+                       if ( (k.val.dptr = malloc( d.dsize )) != NULL ) {
+               
+                               k.val.dsize = d.dsize;
+                               d = mdbm_fetch( ldbm, k );
+
+                       } else { 
+
+                               d.dsize = 0;
+                               break;
+                       
+                       }
+
+               }/* if ( d.dsize > 0 ) */
+
+       } while ((d.dsize > k.val.dsize) && (++retry < MAX_MDBM_RETRY));
+
+       /* LDBM_UNLOCK; */
+
+       return d;
+
+}/* Datum ldbm_fetch() */
+
+
+
+
+int
+ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
+{
+       int     rc;
+       Datum   int_key;        /* Internal key */
+
+#ifdef MDBM_DEBUG
+       fprintf( stdout,
+                "==>(mdbm)ldbm_store(db=%p, key(dptr=%p,sz=%d), data(dptr=%p,sz=%d), flags=%x)\n",
+                ldbm, key.dptr, key.dsize, data.dptr, data.dsize, flags );
+       fflush( stdout );
+#endif
+
+       /* LDBM_LOCK; */
+
+#ifdef NO_NULL_KEY
+       int_key.dsize = key.dsize + 1;
+       int_key.dptr = alloca( int_key.dsize );
+       *(int_key.dptr) = 'l';  /* Must not be NULL !*/
+       memcpy( (void *)(int_key.dptr + 1), key.dptr, key.dsize );
+#else
+       int_key = key;
+#endif
+
+       rc = mdbm_store( ldbm, int_key, data, flags );
+       if ( flags & LDBM_SYNC ) {
+               mdbm_sync( ldbm );
        }
-       dup.dsize = data.dsize;
-       dup.dptr = (char *) malloc( data.dsize );
-       if ( dup.dptr )
-               memcpy( dup.dptr, data.dptr, data.dsize );
 
-       return( dup );
+       /* LDBM_UNLOCK; */
+
+#ifdef MDBM_DEBUG
+       fprintf( stdout, "<==(mdbm)ldbm_store(rc=%d)\n", rc );
+       fflush( stdout );
+#endif
+
+       return( rc );
+
+}/* int ldbm_store() */
+
+
+
+
+int
+ldbm_delete( LDBM ldbm, Datum key )
+{
+       int     rc;
+       Datum   int_key;
+
+       /* LDBM_LOCK; */
+
+#ifdef NO_NULL_KEY
+       int_key.dsize = key.dsize + 1;
+       int_key.dptr = alloca(int_key.dsize);
+       *(int_key.dptr) = 'l';
+       memcpy( (void *)(int_key.dptr + 1), key.dptr, key.dsize );      
+#else
+       int_key = key;
+#endif
+       
+       rc = mdbm_delete( ldbm, int_key );
+
+       /* LDBM_UNLOCK; */
+
+       return( rc );
+
+}/* int ldbm_delete() */
+
+
+
+
+static Datum
+ldbm_get_next( LDBM ldbm, kvpair (*fptr)(MDBM *, kvpair) ) 
+{
+
+       kvpair  out;
+       kvpair  in;
+       Datum   ret;
+       size_t  sz = MDBM_PAGE_SIZE(ldbm);
+#ifdef NO_NULL_KEY
+       int     delta = 1;
+#else
+       int     delta = 0;
+#endif
+
+       /* LDBM_LOCK; */
+
+       in.key.dsize = sz;      /* Assume first key in one pg */
+       in.key.dptr = alloca(sz);
+       
+       in.val.dptr = NULL;     /* Don't need data just key */ 
+       in.val.dsize = 0;
+
+       ret.dptr = NULL;
+       ret.dsize = NULL;
+
+       out = fptr( ldbm, in );
+
+       if (out.key.dsize > 0) {
+
+           ret.dsize = out.key.dsize - delta;
+           if ((ret.dptr = (char *)malloc(ret.dsize)) == NULL) { 
+
+               ret.dsize = 0;
+               ret.dptr = NULL;
+
+           } else {
+
+               memcpy(ret.dptr, (void *)(out.key.dptr + delta),
+                      ret.dsize );
+
+           }
+
+       }
+
+       /* LDBM_UNLOCK; */
+
+       return ret;
+
+}/* static Datum ldbm_get_next() */
+
+
+
+
+Datum
+ldbm_firstkey( LDBM ldbm )
+{
+
+       return ldbm_get_next( ldbm, mdbm_first );
+
+}/* Datum ldbm_firstkey() */
+
+
+
+
+Datum
+ldbm_nextkey( LDBM ldbm, Datum key )
+{
+
+       /* XXX:
+        * don't know if this will affect the LDAP server opertaion 
+        * but mdbm cannot take and input key.
+        */
+
+       return ldbm_get_next( ldbm, mdbm_next );
+
+}/* Datum ldbm_nextkey() */
+
+int
+ldbm_errno( LDBM ldbm )
+{
+       /* XXX: best we can do with current  mdbm interface */
+       return( errno );
+
+}/* int ldbm_errno() */
+
+
+
+
+#elif defined( HAVE_NDBM )
+
+/*****************************************************************
+ *                                                               *
+ * if no gdbm or mdbm, fall back to using ndbm, the standard unix thing  *
+ *                                                               *
+ *****************************************************************/
+
+/* ARGSUSED */
+LDBM
+ldbm_open( char *name, int rw, int mode, int dbcachesize )
+{
+       LDBM ldbm;
+
+       LDBM_LOCK;
+       ldbm = dbm_open( name, rw, mode );
+       LDBM_UNLOCK;
+
+       return( ldbm );
+}
+
+void
+ldbm_close( LDBM ldbm )
+{
+       LDBM_LOCK;
+       dbm_close( ldbm );
+       LDBM_UNLOCK;
+}
+
+/* ARGSUSED */
+void
+ldbm_sync( LDBM ldbm )
+{
+       return;
 }
 
 Datum
 ldbm_fetch( LDBM ldbm, Datum key )
 {
-       return( ldbm_datum_dup( ldbm, dbm_fetch( ldbm, key ) ) );
+       Datum d;
+
+       LDBM_LOCK;
+       d = ldbm_datum_dup( ldbm, dbm_fetch( ldbm, key ) );
+       LDBM_UNLOCK;
+
+       return d;
 }
 
 int
 ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
 {
-       return( dbm_store( ldbm, key, data, flags ) );
+       int rc;
+
+       LDBM_LOCK;
+       rc = dbm_store( ldbm, key, data, flags );
+       LDBM_UNLOCK;
+
+       return rc;
 }
 
 int
 ldbm_delete( LDBM ldbm, Datum key )
 {
-       return( dbm_delete( ldbm, key ) );
+       int rc;
+
+       LDBM_LOCK;
+       rc = dbm_delete( ldbm, key );
+       LDBM_UNLOCK;
+
+       return rc;
 }
 
 Datum
 ldbm_firstkey( LDBM ldbm )
 {
-       return( dbm_firstkey( ldbm ) );
+       Datum d;
+
+       LDBM_LOCK;
+       d = dbm_firstkey( ldbm );
+       LDBM_UNLOCK;
+
+       return d;
 }
 
 Datum
 ldbm_nextkey( LDBM ldbm, Datum key )
 {
-       return( dbm_nextkey( ldbm ) );
+       Datum d;
+
+       LDBM_LOCK;
+       d = dbm_nextkey( ldbm );
+       LDBM_UNLOCK;
+
+       return d;
 }
 
 int
 ldbm_errno( LDBM ldbm )
 {
-       return( dbm_error( ldbm ) );
+       int err;
+
+       LDBM_LOCK;
+       err = dbm_error( ldbm );
+       LDBM_UNLOCK;
+
+       return err;
 }
 
 #endif /* ndbm */