LDBM/back-ldbm locking reworked!

back-ldbm was using a cache specific lock to protect non-reentrant
	database routines from being reenterred.  This is inadequate.
	Also, reentrant database systems calls were serialized unnecessarily.

	Non-reentrant database calls must have a big_mutex.  Implemented
	this within -lldbm itself.  library requires ldbm_initialize()
	be called before any other ldbm call to initialize the big_mutex
	and to do any other db specific initialization (ie: such as
	required for DB2).

The dbc_mutex, dbc_cv, & dbc_readers fileds of dbcache are history.
The "reentrant_database" (REENTRANT_DATABASE) define is also axed.
This commit is contained in:
Kurt Zeilenga 1999-01-26 20:55:54 +00:00
parent f3fb0c74a6
commit bd6dfe333d
8 changed files with 218 additions and 155 deletions

View File

@ -109,7 +109,7 @@ AC_DEFUN([OL_BERKELEY_DB2],
[AC_REQUIRE([OL_LIB_BERKELEY_DB2])
AC_REQUIRE([OL_HEADER_BERKELEY_DB2])
AC_CACHE_CHECK([for Berkeley DB2], [ol_cv_berkeley_db2], [
if test $ol_cv_lib_db2 = no -o $ol_cv_header_db2 = no ; then
if test "$ol_cv_lib_db2" = no -o "$ol_cv_header_db2" = no ; then
ol_cv_berkeley_db2=no
else
ol_cv_berkeley_db2=yes
@ -132,7 +132,7 @@ dnl
AC_DEFUN([OL_HEADER_BERKELEY_DB],
[AC_REQUIRE([OL_HEADER_BERKELEY_DB2])
AC_CHECK_HEADERS(db_185.h)
if test $ol_cv_header_db2 = yes ; then
if test "$ol_cv_header_db2" = yes ; then
dnl db.h is db2!
ol_cv_header_db=$ac_cv_header_db_185_h
@ -175,7 +175,7 @@ AC_DEFUN([OL_BERKELEY_DB],
[AC_REQUIRE([OL_LIB_BERKELEY_DB])
AC_REQUIRE([OL_HEADER_BERKELEY_DB])
AC_CACHE_CHECK([for Berkeley DB], [ol_cv_berkeley_db], [
if test $ol_cv_lib_db = no -o $ol_cv_header_db = no ; then
if test "$ol_cv_lib_db" = no -o "$ol_cv_header_db" = no ; then
ol_cv_berkeley_db=no
else
ol_cv_berkeley_db=yes

6
configure vendored
View File

@ -5514,7 +5514,7 @@ if eval "test \"`echo '$''{'ol_cv_berkeley_db2'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
if test $ol_cv_lib_db2 = no -o $ol_cv_header_db2 = no ; then
if test "$ol_cv_lib_db2" = no -o "$ol_cv_header_db2" = no ; then
ol_cv_berkeley_db2=no
else
ol_cv_berkeley_db2=yes
@ -5698,7 +5698,7 @@ else
fi
done
if test $ol_cv_header_db2 = yes ; then
if test "$ol_cv_header_db2" = yes ; then
ol_cv_header_db=$ac_cv_header_db_185_h
else
@ -5713,7 +5713,7 @@ if eval "test \"`echo '$''{'ol_cv_berkeley_db'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
if test $ol_cv_lib_db = no -o $ol_cv_header_db = no ; then
if test "$ol_cv_lib_db" = no -o "$ol_cv_header_db" = no ; then
ol_cv_berkeley_db=no
else
ol_cv_berkeley_db=yes

View File

@ -12,6 +12,8 @@
#ifndef _LDBM_H_
#define _LDBM_H_
#include <ldap_cdefs.h>
#ifdef LDBM_USE_DBBTREE
/*****************************************************************
@ -24,7 +26,7 @@
#include <limits.h>
#include <fcntl.h>
#ifdef HAVE_DB185_H
#ifdef HAVE_DB_185_H
# include <db_185.h>
#else
# include <db.h>
@ -78,7 +80,7 @@ typedef DB *LDBM;
#include <limits.h>
#include <fcntl.h>
#ifdef HAVE_DB185_H
#ifdef HAVE_DB_185_H
# include <db_185.h>
#else
# include <db.h>
@ -182,6 +184,9 @@ typedef DBM *LDBM;
#endif
LDAP_BEGIN_DECL
void ldbm_initialize( void );
int ldbm_errno( LDBM ldbm );
LDBM ldbm_open( char *name, int rw, int mode, int dbcachesize );
void ldbm_close( LDBM ldbm );
@ -204,13 +209,11 @@ int ldbm_delete( LDBM ldbm, Datum key );
/* initialization of Datum structures */
#ifdef HAVE_BERKELEY_DB2
# define ldbm_datum_init(d) ((void)memset(&(d), 0, sizeof(Datum)))
#else
# define ldbm_datum_init(d) ((void)0)
#endif /* HAVE_BERKELEY_DB2 */
LDAP_END_DECL
#endif /* _ldbm_h_ */

View File

@ -75,13 +75,3 @@ va_dcl
(*lber_pvt_log_print)( buf );
return 1;
}
static int lber_log_puts(int errlvl, int loglvl, char *buf)
{
if ( !ldap_log_check( errlvl, loglvl )) {
return 0;
}
(*lber_pvt_log_print)( buf );
return 1;
}

View File

@ -19,6 +19,7 @@
#include <ac/errno.h>
#include "ldbm.h"
#include "lthread.h"
#if defined( LDBM_USE_DBHASH ) || defined( LDBM_USE_DBBTREE )
@ -29,11 +30,6 @@
*****************************************************************/
#ifdef HAVE_BERKELEY_DB2
/*************************************************
* *
* A malloc routine for use with DB_DBT_MALLOC *
* *
*************************************************/
void *
ldbm_malloc( size_t size )
@ -41,83 +37,89 @@ 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 );
}
/* 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)
void ldbm_initialize( void )
{
static int initialized = 0;
int err;
int envFlags;
if(initialized++) return;
memset( &ldbm_Env, 0, sizeof( ldbm_Env ));
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 ));
}
syslog( LOG_INFO,
"ldbm_initialize(): FATAL error in db_appinit() : %s\n",
error );
exit( 1 );
}
}
#else
/* 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))
void ldbm_initialize( void )
{
static int initialized = 0;
if(initialized++) return;
pthread_mutex_init( &ldbm_big_mutex, pthread_mutexattr_default );
}
#endif
LDBM
ldbm_open( char *name, int rw, int mode, int dbcachesize )
{
LDBM ret = NULL;
#ifdef HAVE_BERKELEY_DB2
DB_INFO dbinfo;
/* initialize an environment for the DB application */
pthread_mutex_lock( &dbEnvInit_mutex );
if ( !dbEnvInit ) {
char *dir;
char tmp[BUFSIZ];
int err = 0;
int envFlags = DB_CREATE | DB_THREAD;
strcpy( tmp, name );
if ( ( dir = strrchr( tmp, '/' )) ) {
*dir ='\0';
dir = tmp;
} else {
dir = "/";
}
memset( &dbEnv, 0, sizeof( dbEnv ));
dbEnv.db_errcall = ldbm_db_errcall;
dbEnv.db_errpfx = "==>";
if ( ( err = db_appinit( NULL, NULL, &dbEnv, envFlags )) ) {
char error[BUFSIZ];
if ( err < 0 ) sprintf( error, "%ld\n", (long) err );
else sprintf( error, "%s\n", strerror( err ));
syslog( LOG_INFO,
"ldbm_open(): FATAL error in db_appinit(%s) : %s\n",
dir, error );
exit( 1 );
}
dbEnvInit = 1;
}
pthread_mutex_unlock( &dbEnvInit_mutex );
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;
@ -136,7 +138,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
@ -146,17 +150,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 );
LDBM_UNLOCK;
}
void
@ -188,6 +196,8 @@ ldbm_fetch( LDBM ldbm, Datum key )
Datum data;
int rc;
LDBM_LOCK;
#ifdef HAVE_BERKELEY_DB2
ldbm_datum_init( data );
@ -204,6 +214,8 @@ ldbm_fetch( LDBM ldbm, Datum key )
data.dsize = 0;
}
LDBM_UNLOCK;
return( data );
}
@ -212,6 +224,8 @@ 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;
@ -221,6 +235,9 @@ ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
if ( flags & LDBM_SYNC )
(*ldbm->sync)( ldbm, 0 );
LDBM_UNLOCK;
return( rc );
}
@ -229,6 +246,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;
@ -236,6 +255,9 @@ ldbm_delete( LDBM ldbm, Datum key )
rc = (*ldbm->del)( ldbm, &key, 0 );
#endif
(*ldbm->sync)( ldbm, 0 );
LDBM_UNLOCK;
return( rc );
}
@ -257,6 +279,8 @@ ldbm_firstkey( LDBM ldbm )
key.flags = data.flags = DB_DBT_MALLOC;
LDBM_LOCK;
/* acquire a cursor for the DB */
# if defined( DB_VERSION_MAJOR ) && defined( DB_VERSION_MINOR ) && \
@ -276,6 +300,9 @@ ldbm_firstkey( LDBM ldbm )
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
@ -288,6 +315,8 @@ ldbm_firstkey( LDBM ldbm )
}
#endif
LDBM_UNLOCK;
return( key );
}
@ -308,9 +337,14 @@ ldbm_nextkey( LDBM ldbm, Datum 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
@ -318,6 +352,9 @@ ldbm_nextkey( LDBM ldbm, Datum key )
key.dptr = NULL;
key.dsize = 0;
}
LDBM_UNLOCK;
#ifdef HAVE_BERKELEY_DB2
if ( oldKey ) free( oldKey );
#endif
@ -335,6 +372,20 @@ ldbm_errno( LDBM ldbm )
#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 *
@ -347,7 +398,10 @@ ldbm_open( char *name, int rw, int mode, int dbcachesize )
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 ) {
@ -355,19 +409,24 @@ ldbm_open( char *name, int rw, int mode, int dbcachesize )
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
@ -397,7 +456,11 @@ ldbm_datum_dup( LDBM ldbm, Datum data )
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
@ -405,9 +468,11 @@ 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 );
}
@ -416,31 +481,59 @@ 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 )
/* 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 *
@ -451,13 +544,21 @@ ldbm_errno( LDBM ldbm )
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 */
@ -495,37 +596,61 @@ ldbm_datum_dup( LDBM ldbm, Datum data )
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 */

View File

@ -71,18 +71,13 @@ struct cache {
/* for the cache of open index files */
struct dbcache {
char *dbc_name;
int dbc_refcnt;
time_t dbc_lastref;
pthread_mutex_t dbc_mutex;
#ifdef REENTRANT_DATBASE
pthread_cond_t dbc_cv;
int dbc_readers;
#endif
long dbc_blksize;
int dbc_maxids;
int dbc_maxindirect;
LDBM dbc_db;
time_t dbc_lastref;
long dbc_blksize;
char *dbc_name;
LDBM dbc_db;
};
/* for the cache of attribute information (which are indexed, etc.) */

View File

@ -160,9 +160,7 @@ ldbm_cache_flush_all( Backend *be )
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 );
@ -178,24 +176,8 @@ ldbm_cache_fetch(
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 );
}
@ -209,14 +191,6 @@ ldbm_cache_store(
{
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",
@ -237,8 +211,6 @@ ldbm_cache_store(
rc = ldbm_store( db->dbc_db, key, data, flags );
pthread_mutex_unlock( &db->dbc_mutex );
return( rc );
}
@ -250,17 +222,7 @@ ldbm_cache_delete(
{
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 );
}

View File

@ -19,9 +19,8 @@ ldbm_back_init(
char *argv[ 4 ];
int i;
#ifdef HAVE_BERKELEY_DB2
extern pthread_mutex_t dbEnvInit_mutex;
#endif
/* initialize the underlying database system */
ldbm_initialize();
/* allocate backend-specific stuff */
li = (struct ldbminfo *) ch_calloc( 1, sizeof(struct ldbminfo) );
@ -77,17 +76,6 @@ ldbm_back_init(
pthread_mutex_init( &li->li_nextid_mutex, pthread_mutexattr_default );
pthread_mutex_init( &li->li_dbcache_mutex, pthread_mutexattr_default );
pthread_cond_init( &li->li_dbcache_cv, pthread_condattr_default );
for ( i = 0; i < MAXDBCACHE; i++ ) {
pthread_mutex_init( &li->li_dbcache[i].dbc_mutex,
pthread_mutexattr_default );
#ifdef reentrant_database
pthread_cond_init( &li->li_dbcache[i].dbc_cv,
pthread_condattr_default );
#endif
}
#ifdef HAVE_BERKELEY_DB2
pthread_mutex_init( &dbEnvInit_mutex, pthread_mutexattr_default );
#endif
be->be_private = li;
}