#include <ac/errno.h>
#include "ldbm.h"
+#include "lthread.h"
#if defined( LDBM_USE_DBHASH ) || defined( LDBM_USE_DBBTREE )
*****************************************************************/
#ifdef HAVE_BERKELEY_DB2
-/*************************************************
- * *
- * A malloc routine for use with DB_DBT_MALLOC *
- * *
- *************************************************/
void *
ldbm_malloc( size_t size )
return( calloc( 1, size ));
}
-/* a dbEnv for BERKELEYv2 */
-#include "lthread.h"
-
-DB_ENV dbEnv;
-int dbEnvInit = 0;
-pthread_mutex_t dbEnvInit_mutex;
-
-void
-ldbm_db_errcall( char *prefix, char *message )
+static void
+ldbm_db_errcall( const char *prefix, char *message )
{
syslog( LOG_INFO, "ldbm_db_errcall(): %s %s", prefix, message );
}
-#endif
+/* a dbEnv for BERKELEYv2 */
+static DB_ENV ldbm_Env;
+/* Berkeley DB 2.x is reentrant */
+#define LDBM_LOCK ((void)0)
+#define LDBM_UNLOCK ((void)0)
-LDBM
-ldbm_open( char *name, int rw, int mode, int dbcachesize )
+void ldbm_initialize( void )
{
- LDBM ret = NULL;
+ static int initialized = 0;
-#ifdef HAVE_BERKELEY_DB2
- DB_INFO dbinfo;
+ int err;
+ int envFlags;
- /* initialize an environment for the DB application */
- pthread_mutex_lock( &dbEnvInit_mutex );
+ if(initialized++) return;
- if ( !dbEnvInit ) {
- char *dir;
- char tmp[BUFSIZ];
- int err = 0;
- int envFlags = DB_CREATE | DB_THREAD;
+ memset( &ldbm_Env, 0, sizeof( ldbm_Env ));
- strcpy( tmp, name );
- if ( ( dir = strrchr( tmp, '/' )) ) {
+ ldbm_Env.db_errcall = ldbm_db_errcall;
+ ldbm_Env.db_errpfx = "==>";
- *dir ='\0';
- dir = tmp;
+ 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 ));
+ }
- dir = "/";
+ syslog( LOG_INFO,
+ "ldbm_initialize(): FATAL error in db_appinit() : %s\n",
+ error );
+ exit( 1 );
+ }
+}
- }
+#else
- memset( &dbEnv, 0, sizeof( dbEnv ));
+/* DB 1.85 is non-reentrant */
+static pthread_mutex_t ldbm_big_mutex;
+#define LDBM_LOCK (pthread_mutex_lock(&ldbm_big_mutex))
+#define LDBM_UNLOCK (pthread_mutex_unlock(&ldbm_big_mutex))
- dbEnv.db_errcall = ldbm_db_errcall;
- dbEnv.db_errpfx = "==>";
+void ldbm_initialize( void )
+{
+ static int initialized = 0;
- if ( ( err = db_appinit( NULL, NULL, &dbEnv, envFlags )) ) {
- char error[BUFSIZ];
+ if(initialized++) return;
- if ( err < 0 ) sprintf( error, "%ld\n", (long) err );
- else sprintf( error, "%s\n", strerror( err ));
+ pthread_mutex_init( &ldbm_big_mutex, pthread_mutexattr_default );
+}
- syslog( LOG_INFO,
- "ldbm_open(): FATAL error in db_appinit(%s) : %s\n",
- dir, error );
+#endif
- exit( 1 );
- }
- dbEnvInit = 1;
+LDBM
+ldbm_open( char *name, int rw, int mode, int dbcachesize )
+{
+ LDBM ret = NULL;
- }
- pthread_mutex_unlock( &dbEnvInit_mutex );
+#ifdef HAVE_BERKELEY_DB2
+ DB_INFO dbinfo;
memset( &dbinfo, 0, sizeof( dbinfo ));
dbinfo.db_cachesize = dbcachesize;
dbinfo.db_pagesize = DEFAULT_DB_PAGE_SIZE;
dbinfo.db_malloc = ldbm_malloc;
- (void) db_open( name, DB_TYPE, rw, mode, &dbEnv, &dbinfo, &ret );
+ LDBM_LOCK;
+ (void) db_open( name, DB_TYPE, rw, mode, &ldbm_Env, &dbinfo, &ret );
+ LDBM_UNLOCK;
#else
void *info;
info = NULL;
}
+ LDBM_LOCK;
ret = dbopen( name, rw, mode, DB_TYPE, info );
+ LDBM_UNLOCK;
#endif
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 );
+ LDBM_UNLOCK;
}
void
Datum data;
int rc;
+ LDBM_LOCK;
+
#ifdef HAVE_BERKELEY_DB2
ldbm_datum_init( data );
data.dsize = 0;
}
+ LDBM_UNLOCK;
+
return( data );
}
{
int rc;
+ LDBM_LOCK;
+
#ifdef HAVE_BERKELEY_DB2
rc = (*ldbm->put)( ldbm, NULL, &key, &data, flags & ~LDBM_SYNC );
rc = (-1 ) * rc;
if ( flags & LDBM_SYNC )
(*ldbm->sync)( ldbm, 0 );
+
+ LDBM_UNLOCK;
+
return( rc );
}
{
int rc;
+ LDBM_LOCK;
+
#ifdef HAVE_BERKELEY_DB2
rc = (*ldbm->del)( ldbm, NULL, &key, 0 );
rc = (-1 ) * rc;
rc = (*ldbm->del)( ldbm, &key, 0 );
#endif
(*ldbm->sync)( ldbm, 0 );
+
+ LDBM_UNLOCK;
+
return( rc );
}
key.flags = data.flags = DB_DBT_MALLOC;
+ LDBM_LOCK;
+
/* acquire a cursor for the DB */
# if defined( DB_VERSION_MAJOR ) && defined( DB_VERSION_MINOR ) && \
if ( (*dbci->c_get)( dbci, &key, &data, DB_NEXT ) == 0 ) {
if ( data.dptr ) free( data.dptr );
#else
+
+ LDBM_LOCK;
+
if ( (rc = (*ldbm->seq)( ldbm, &key, &data, R_FIRST )) == 0 ) {
key = ldbm_datum_dup( ldbm, key );
#endif
}
#endif
+ LDBM_UNLOCK;
+
return( key );
}
data.flags = DB_DBT_MALLOC;
+ LDBM_LOCK;
+
if ( (*dbcp->c_get)( dbcp, &key, &data, DB_NEXT ) == 0 ) {
if ( data.dptr ) free( data.dptr );
#else
+
+ LDBM_LOCK;
+
if ( (rc = (*ldbm->seq)( ldbm, &key, &data, R_NEXT )) == 0 ) {
key = ldbm_datum_dup( ldbm, key );
#endif
key.dptr = NULL;
key.dsize = 0;
}
+
+ LDBM_UNLOCK;
+
#ifdef HAVE_BERKELEY_DB2
if ( oldKey ) free( oldKey );
#endif
#include <sys/stat.h>
+/* GDBM is non-reentrant */
+static pthread_mutex_t ldbm_big_mutex;
+#define LDBM_LOCK (pthread_mutex_lock(&ldbm_big_mutex))
+#define LDBM_UNLOCK (pthread_mutex_unlock(&ldbm_big_mutex))
+
+void ldbm_initialize( void )
+{
+ static int initialized = 0;
+
+ if(initialized++) return;
+
+ pthread_mutex_init( &ldbm_big_mutex, pthread_mutexattr_default );
+}
+
/*****************************************************************
* *
* use gdbm *
LDBM db;
struct stat st;
+ LDBM_LOCK;
+
if ( (db = gdbm_open( name, 0, rw | GDBM_FAST, mode, 0 )) == NULL ) {
+ LDBM_UNLOCK;
return( NULL );
}
if ( dbcachesize > 0 && stat( name, &st ) == 0 ) {
gdbm_setopt( db, GDBM_CACHESIZE, &dbcachesize, sizeof(int) );
}
+ LDBM_UNLOCK;
return( db );
}
void
ldbm_close( LDBM ldbm )
{
+ LDBM_LOCK;
gdbm_close( ldbm );
+ LDBM_UNLOCK;
}
void
ldbm_sync( LDBM ldbm )
{
+ LDBM_LOCK;
gdbm_sync( ldbm );
+ LDBM_UNLOCK;
}
void
Datum
ldbm_fetch( LDBM ldbm, Datum key )
{
- return( gdbm_fetch( ldbm, key ) );
+ Datum d;
+ LDBM_LOCK;
+ d = gdbm_fetch( ldbm, key );
+ LDBM_UNLOCK;
+ return d;
}
int
{
int rc;
+ LDBM_LOCK;
rc = gdbm_store( ldbm, key, data, flags & ~LDBM_SYNC );
if ( flags & LDBM_SYNC )
gdbm_sync( ldbm );
+ LDBM_UNLOCK;
return( rc );
}
{
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 )
+/* GDBM is non-reentrant */
+static pthread_mutex_t ldbm_big_mutex;
+#define LDBM_LOCK (pthread_mutex_lock(&ldbm_big_mutex))
+#define LDBM_UNLOCK (pthread_mutex_unlock(&ldbm_big_mutex))
+
+void ldbm_initialize( void )
+{
+ static int initialized = 0;
+
+ if(initialized++) return;
+
+ pthread_mutex_init( &ldbm_big_mutex, pthread_mutexattr_default );
+}
+
/*****************************************************************
* *
* if no gdbm, fall back to using ndbm, the standard unix thing *
LDBM
ldbm_open( char *name, int rw, int mode, int dbcachesize )
{
- return( dbm_open( name, rw, mode ) );
+ 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 */
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 */
if ( li->li_dbcache[i].dbc_name != NULL ) {
Debug( LDAP_DEBUG_TRACE, "ldbm flushing db (%s)\n",
li->li_dbcache[i].dbc_name, 0, 0 );
- pthread_mutex_lock( &li->li_dbcache[i].dbc_mutex );
ldbm_sync( li->li_dbcache[i].dbc_db );
- pthread_mutex_unlock( &li->li_dbcache[i].dbc_mutex );
}
}
pthread_mutex_unlock( &li->li_dbcache_mutex );
ldbm_datum_init( data );
- pthread_mutex_lock( &db->dbc_mutex );
-#ifdef REENTRANT_DATABASE
- /* increment reader count */
- db->dbc_readers++
- pthread_mutex_unlock( &db->dbc_mutex );
-#endif
-
data = ldbm_fetch( db->dbc_db, key );
-#ifdef REENTRANT_DATABASE
- pthread_mutex_lock( &db->dbc_mutex );
- /* decrement reader count & signal any waiting writers */
- if ( --db->dbc_readers == 0 ) {
- pthread_cond_signal( &db->dbc_cv );
- }
-#endif
- pthread_mutex_unlock( &db->dbc_mutex );
-
return( data );
}
{
int rc;
- pthread_mutex_lock( &db->dbc_mutex );
-#ifdef REENTRANT_DATABASE
- /* wait for reader count to drop to zero */
- while ( db->dbc_readers > 0 ) {
- pthread_cond_wait( &db->dbc_cv, &db->dbc_mutex );
- }
-#endif
-
#ifdef LDBM_DEBUG
Statslog( LDAP_DEBUG_STATS,
"=> ldbm_cache_store(): key.dptr=%s, key.dsize=%d\n",
rc = ldbm_store( db->dbc_db, key, data, flags );
- pthread_mutex_unlock( &db->dbc_mutex );
-
return( rc );
}
{
int rc;
- pthread_mutex_lock( &db->dbc_mutex );
-#ifdef REENTRANT_DATABASE
- /* wait for reader count to drop to zero - then write */
- while ( db->dbc_readers > 0 ) {
- pthread_cond_wait( &db->dbc_cv, &db->dbc_mutex );
- }
-#endif
-
rc = ldbm_delete( db->dbc_db, key );
- pthread_mutex_unlock( &db->dbc_mutex );
-
return( rc );
}