]> 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 db5749267dfb3132c1a600aa0f2444d7ed92d2fc..0ce41481c8213a876c0c8826c69fa0edce2b1e47 100644 (file)
@@ -9,8 +9,6 @@
 
 #include "portable.h"
 
-#include "syslog.h"
-
 #ifdef SLAPD_LDBM
 
 #include <stdio.h>
 void
 ldbm_datum_free( LDBM ldbm, Datum data )
 {
-       free( data.dptr );
-       data.dptr = NULL;
+       if ( data.dptr ) {
+               free( data.dptr );
+               memset( &data, 0, sizeof( Datum ));
+               data.dptr = NULL;
+       }
 }
 
 
@@ -35,6 +36,8 @@ ldbm_datum_dup( LDBM ldbm, Datum data )
 {
        Datum   dup;
 
+       ldbm_datum_init( dup );
+
        if ( data.dsize == 0 ) {
                dup.dsize = 0;
                dup.dptr = NULL;
@@ -77,6 +80,16 @@ int ldbm_shutdown( void )
 
 #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 )
 {
@@ -86,13 +99,14 @@ ldbm_malloc( size_t 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  */
-DB_ENV           ldbm_Env;
+static DB_ENV    ldbm_Env_internal;
+DB_ENV           *ldbm_Env = NULL;
 
 /* Berkeley DB 2.x is reentrant */
 #define LDBM_LOCK      ((void)0)
@@ -105,14 +119,15 @@ int ldbm_initialize( void )
 
        if(ldbm_initialized++) return 1;
 
-       memset( &ldbm_Env, 0, sizeof( ldbm_Env ));
+       memset( &ldbm_Env_internal, 0, sizeof( DB_ENV ));
+       ldbm_Env = &ldbm_Env_internal;
 
-       ldbm_Env.db_errcall   = ldbm_db_errcall;
-       ldbm_Env.db_errpfx    = "==>";
+       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 )) ) {
+       if ( ( err = db_appinit( NULL, NULL, ldbm_Env, envFlags )) ) {
                char  error[BUFSIZ];
 
                if ( err < 0 ) {
@@ -121,9 +136,11 @@ int ldbm_initialize( void )
                        sprintf( error, "%s\n", strerror( err ));
                }
 
+#ifndef WIN32
                syslog( LOG_INFO,
                        "ldbm_initialize(): FATAL error in db_appinit() : %s\n",
                        error );
+#endif
                return( 1 );
        }
 
@@ -134,7 +151,7 @@ int ldbm_shutdown( void )
 {
        if( !ldbm_initialized ) return 1;
 
-       db_appexit( &ldbm_Env );
+       db_appexit( ldbm_Env );
 
        return 0;
 }
@@ -158,13 +175,13 @@ ldbm_open( char *name, int rw, int mode, int dbcachesize )
        DB_INFO dbinfo;
 
        memset( &dbinfo, 0, sizeof( dbinfo ));
-       if ( ldbm_Env.mp_info == NULL )
+       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;
 
        LDBM_LOCK;
-    (void) db_open( name, DB_TYPE, rw, mode, &ldbm_Env, &dbinfo, &ret );
+    (void) db_open( name, DB_TYPE, rw, mode, ldbm_Env, &dbinfo, &ret );
        LDBM_UNLOCK;
 
 #else
@@ -227,7 +244,7 @@ ldbm_fetch( LDBM ldbm, Datum key )
        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 */
@@ -294,7 +311,6 @@ ldbm_firstkey( LDBM ldbm )
 #endif
 {
        Datum   key, data;
-       int     rc;
 
 #ifdef HAVE_BERKELEY_DB2
        DBC  *dbci;
@@ -317,23 +333,24 @@ ldbm_firstkey( LDBM ldbm )
        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 );
        }
-#endif
        else {
+#endif
                key.dptr = NULL;
                key.dsize = 0;
        }
@@ -355,39 +372,35 @@ ldbm_nextkey( LDBM ldbm, Datum key )
 #endif
 {
        Datum   data;
-       int     rc;
 
 #ifdef HAVE_BERKELEY_DB2
-       void *oldKey = key.dptr;
-
        ldbm_datum_init( data );
 
-       data.flags = DB_DBT_MALLOC;
+       ldbm_datum_free( ldbm, key );
+       key.flags = 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 );
        }
-#endif
        else {
+#endif
                key.dptr = NULL;
                key.dsize = 0;
        }
 
        LDBM_UNLOCK;
 
-#ifdef HAVE_BERKELEY_DB2
-       if ( oldKey ) free( oldKey );
-#endif
-
        return( key );
 }
 
@@ -399,7 +412,9 @@ ldbm_errno( LDBM ldbm )
 
 #elif defined( HAVE_GDBM )
 
+#ifdef HAVE_ST_BLKSIZE
 #include <sys/stat.h>
+#endif
 
 /*****************************************************************
  *                                                               *
@@ -411,7 +426,9 @@ 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;
 
@@ -419,10 +436,16 @@ ldbm_open( char *name, int rw, int mode, int dbcachesize )
                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;
 
@@ -520,11 +543,358 @@ ldbm_errno( LDBM ldbm )
        return( err );
 }
 
+#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)
+
+/*****************************************************************
+ *                                                               *
+ * use mdbm                                                      *
+ *                                                               *
+ *****************************************************************/
+
+LDBM
+ldbm_open( char *name, int rw, int mode, int dbcachesize )
+{
+       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 )
+{
+
+       /* 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 )
+{
+
+       /* 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_fetch( LDBM ldbm, Datum key )
+{
+       Datum   d;
+       kvpair  k;
+       int     retry = 0;
+
+       /* This hack is needed because MDBM does not take keys
+        * which begin with NULL when working in the chaining
+        * mode.
+        */
+
+       /* 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 );
+       }
+
+       /* 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, fall back to using ndbm, the standard unix thing  *
+ * if no gdbm or mdbm, fall back to using ndbm, the standard unix thing  *
  *                                                               *
  *****************************************************************/