LDAP_BEGIN_DECL
-void ldbm_initialize( void );
-int ldbm_errno( LDBM ldbm );
+int ldbm_errno( LDBM ldbm );
LDBM ldbm_open( char *name, int rw, int mode, int dbcachesize );
void ldbm_close( LDBM ldbm );
void ldbm_sync( LDBM ldbm );
int ldbm_store( LDBM ldbm, Datum key, Datum data, int flags );
int ldbm_delete( LDBM ldbm, Datum key );
+#ifdef LDBM_USE_DBBTREE
+# if HAVE_BERKELEY_DB2
+ LDBM ldbm_open_env( char *name, int rw, int mode,
+ int dbcachesize, DB_ENV *env );
+# else
+ LDBM ldbm_open_env( char *name, int rw, int mode,
+ int dbcachesize, void *env );
+# endif
+#endif
+
#if HAVE_BERKELEY_DB2
void *ldbm_malloc( size_t size );
Datum ldbm_firstkey( LDBM ldbm, DBC **dbch );
#ifdef HAVE_BERKELEY_DB2
+/* A malloc routine for use with DB_DBT_MALLOC */
void *
ldbm_malloc( size_t size )
{
return( calloc( 1, size ));
}
-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 );
- }
-}
+#define LDBM_LOCK ((void)0)
+#define LDBM_UNLOCK ((void)0)
#else
/* DB 1.85 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))
-
-void ldbm_initialize( void )
-{
- static int initialized = 0;
+#define LDBM_LOCK (ldap_pvt_thread_mutex_lock(&ldbm_big_mutex))
+#define LDBM_UNLOCK (ldap_pvt_thread_mutex_unlock(&ldbm_big_mutex))
- if(initialized++) return;
- ldap_pvt_thread_mutex_init( &ldbm_big_mutex );
-}
+/* we need a dummy definition for pre-2.0 DB */
+typedef void DB_ENV
#endif
-
+/* the old interface for tools and pre-2.0 DB */
LDBM
ldbm_open( char *name, int rw, int mode, int dbcachesize )
+{
+ return( ldbm_open_env( name, rw, mode, dbcachesize, NULL ));
+}
+
+
+/* an enhanced interface for DB 2.0-slapd */
+LDBM
+ldbm_open_env( char *name, int rw, int mode, int dbcachesize, DB_ENV *dbEnv )
{
LDBM ret = NULL;
#ifdef HAVE_BERKELEY_DB2
- DB_INFO dbinfo;
+ DB_INFO dbinfo;
memset( &dbinfo, 0, sizeof( dbinfo ));
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 );
- LDBM_UNLOCK;
+ /* use the environment, but only if initialized */
+ (void) db_open( name, DB_TYPE, rw, mode,
+ dbEnv->db_errcall ? dbEnv : NULL, &dbinfo, &ret );
#else
void *info;
/* GDBM 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))
+#define LDBM_LOCK (ldap_pvt_thread_mutex_lock(&ldbm_big_mutex))
+#define LDBM_UNLOCK (ldap_pvt_thread_mutex_unlock(&ldbm_big_mutex))
-void ldbm_initialize( void )
-{
- static int initialized = 0;
-
- if(initialized++) return;
-
- ldap_pvt_thread_mutex_init( &ldbm_big_mutex );
-}
/*****************************************************************
* *
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 ) {
}
LDBM_UNLOCK;
+
return( db );
}
if ( flags & LDBM_SYNC )
gdbm_sync( ldbm );
LDBM_UNLOCK;
+
return( rc );
}
rc = gdbm_delete( ldbm, key );
gdbm_sync( ldbm );
LDBM_UNLOCK;
+
return( rc );
}
{
Datum d;
LDBM_LOCK;
- d = gdbm_nextkey( ldbm, key );
+ d = gdbm_nextkey( ldbm );
LDBM_UNLOCK;
return d;
}
{
int err;
LDBM_LOCK;
- err = gdbm_errno;
+ err = (int) gdbm_errno;
LDBM_UNLOCK;
return( err );
}
#elif defined( HAVE_NDBM )
-/* GDBM 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))
-
-void ldbm_initialize( void )
-{
- static int initialized = 0;
-
- if(initialized++) return;
-
- ldap_pvt_thread_mutex_init( &ldbm_big_mutex );
-}
-
/*****************************************************************
* *
* if no gdbm, fall back to using ndbm, the standard unix thing *
* *
*****************************************************************/
+/* NDBM 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))
+
+
/* ARGSUSED */
LDBM
ldbm_open( char *name, int rw, int mode, int dbcachesize )
ldbm_fetch( LDBM ldbm, Datum key )
{
Datum d;
+
LDBM_LOCK;
d = ldbm_datum_dup( ldbm, dbm_fetch( ldbm, key ) );
LDBM_UNLOCK;
+
return d;
}
ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
{
int rc;
+
LDBM_LOCK;
rc = dbm_store( ldbm, key, data, flags );
LDBM_UNLOCK;
+
return rc;
}
ldbm_delete( LDBM ldbm, Datum key )
{
int rc;
+
LDBM_LOCK;
rc = dbm_delete( ldbm, key );
LDBM_UNLOCK;
+
return rc;
}
ldbm_firstkey( LDBM ldbm )
{
Datum d;
+
LDBM_LOCK;
d = dbm_firstkey( ldbm );
LDBM_UNLOCK;
+
return d;
}
ldbm_nextkey( LDBM ldbm, Datum key )
{
Datum d;
+
LDBM_LOCK;
d = dbm_nextkey( ldbm );
LDBM_UNLOCK;
+
return d;
}
ldbm_errno( LDBM ldbm )
{
int err;
+
LDBM_LOCK;
err = dbm_error( ldbm );
LDBM_UNLOCK;
+
return err;
}
SRCS = idl.c add.c search.c cache.c dbcache.c dn2id.c id2entry.c \
index.c id2children.c nextid.c abandon.c compare.c group.c \
modify.c modrdn.c delete.c init.c config.c bind.c attr.c \
- filterindex.c unbind.c kerberos.c close.c alias.c
+ filterindex.c unbind.c kerberos.c close.c alias.c startup.c
OBJS = idl.o add.o search.o cache.o dbcache.o dn2id.o id2entry.o \
index.o id2children.o nextid.o abandon.o compare.o group.o \
modify.o modrdn.o delete.o init.o config.o bind.o attr.o \
- filterindex.o unbind.o kerberos.o close.o alias.o
+ filterindex.o unbind.o kerberos.o close.o alias.o startup.o
LDAP_INCDIR= ../../../include
LDAP_LIBDIR= ../../../libraries
#define _BACK_LDBM_H_
#include "ldbm.h"
+#include "db.h"
LDAP_BEGIN_DECL
* the list is terminated by an id of NOID.
* b_ids a list of the actual ids themselves
*/
+typedef struct block {
+ ID b_nmax; /* max number of ids in this list */
+#define ALLIDSBLOCK 0 /* == 0 => this is an allid block */
+ ID b_nids; /* current number of ids used */
+#define INDBLOCK 0 /* == 0 => this is an indirect blk */
+ ID b_ids[1]; /* the ids - actually bigger */
+} Block, IDList;
-typedef ID ID_BLOCK;
-
-#define ID_BLOCK_NMAX_OFFSET 0
-#define ID_BLOCK_NIDS_OFFSET 1
-#define ID_BLOCK_IDS_OFFSET 2
-
-/* all ID_BLOCK macros operate on a pointer to a ID_BLOCK */
-
-#define ID_BLOCK_NMAX(b) ((b)[ID_BLOCK_NMAX_OFFSET])
-#define ID_BLOCK_NIDS(b) ((b)[ID_BLOCK_NIDS_OFFSET])
-#define ID_BLOCK_ID(b, n) ((b)[ID_BLOCK_IDS_OFFSET+(n)])
-
-#define ID_BLOCK_NOID(b, n) (ID_BLOCK_ID((b),(n)) == NOID)
-
-#define ID_BLOCK_ALLIDS_VALUE 0
-#define ID_BLOCK_ALLIDS(b) (ID_BLOCK_NMAX(b) == ID_BLOCK_ALLIDS_VALUE)
-
-#define ID_BLOCK_INDIRECT_VALUE 0
-#define ID_BLOCK_INDIRECT(b) (ID_BLOCK_NIDS(b) == ID_BLOCK_INDIRECT_VALUE)
+#define ALLIDS( idl ) ((idl)->b_nmax == ALLIDSBLOCK)
+#define INDIRECT_BLOCK( idl ) ((idl)->b_nids == INDBLOCK)
/* for the in-core cache of entries */
struct cache {
Avlnode *c_idtree;
Entry *c_lruhead; /* lru - add accessed entries here */
Entry *c_lrutail; /* lru - rem lru entries from here */
- ldap_pvt_thread_mutex_t c_mutex;
+ pthread_mutex_t c_mutex;
};
/* for the cache of open index files */
int dbc_refcnt;
int dbc_maxids;
int dbc_maxindirect;
- time_t dbc_lastref;
- long dbc_blksize;
- char *dbc_name;
- LDBM dbc_db;
+ time_t dbc_lastref;
+ long dbc_blksize;
+ char *dbc_name;
+ LDBM dbc_db;
+
+#ifdef HAVE_BERKELEY_DB2
+ struct dbcache *next;
+#endif
};
/* for the cache of attribute information (which are indexed, etc.) */
#define MAXDBCACHE 10
-/* this could be made an option */
-#ifndef SLAPD_NEXTID_CHUNK
-#define SLAPD_NEXTID_CHUNK 32
-#endif
-
struct ldbminfo {
ID li_nextid;
-#if SLAPD_NEXTID_CHUNK > 1
- ID li_nextid_wrote;
-#endif
- char *li_nextid_file;
- ldap_pvt_thread_mutex_t li_root_mutex;
- ldap_pvt_thread_mutex_t li_add_mutex;
- ldap_pvt_thread_mutex_t li_nextid_mutex;
+ pthread_mutex_t li_root_mutex;
+ pthread_mutex_t li_add_mutex;
+ pthread_mutex_t li_nextid_mutex;
int li_mode;
char *li_directory;
struct cache li_cache;
int li_dbcachesize;
int li_dbcachewsync;
struct dbcache li_dbcache[MAXDBCACHE];
- ldap_pvt_thread_mutex_t li_dbcache_mutex;
- ldap_pvt_thread_cond_t li_dbcache_cv;
+ ldap_pvt_thread_mutex_t li_dbcache_mutex;
+ ldap_pvt_thread_cond_t li_dbcache_cv;
+
+#ifdef HAVE_BERKELEY_DB2
+
+ /* Berkeley DB2 Environment */
+ DB_ENV li_db_env;
+
+#endif
};
#include "proto-back-ldbm.h"
LDBM db;
struct stat st;
- sprintf( buf, "%s/%s%s", li->li_directory, name, suffix );
+ sprintf( buf, "%s%s%s%s", li->li_directory, DEFAULT_DIRSEP, name, suffix );
Debug( LDAP_DEBUG_TRACE, "=> ldbm_cache_open( \"%s\", %d, %o )\n", buf,
flags, li->li_mode );
li->li_dbcache[i].dbc_name = NULL;
}
+#ifdef HAVE_BERKELEY_DB2
+ if ( (li->li_dbcache[i].dbc_db = ldbm_open_env( buf, flags, li->li_mode,
+ li->li_dbcachesize, &li->li_db_env )) == NULL ) {
+#else
if ( (li->li_dbcache[i].dbc_db = ldbm_open( buf, flags, li->li_mode,
li->li_dbcachesize )) == NULL ) {
+#endif
Debug( LDAP_DEBUG_TRACE,
"<= ldbm_cache_open NULL \"%s\" errno %d reason \"%s\")\n",
buf, errno, errno > -1 && errno < sys_nerr ?
-/* compare.c - ldbm backend compare routine */
+/* group.c - ldbm backend acl group routine */
#include "portable.h"
char *argv[ 4 ];
int i;
- /* initialize the underlying database system */
- ldbm_initialize();
-
/* allocate backend-specific stuff */
li = (struct ldbminfo *) ch_calloc( 1, sizeof(struct ldbminfo) );
/* arrange to read nextid later (on first request for it) */
- li->li_nextid = NOID;
-
-#if SLAPD_NEXTID_CHUNK > 1
- li->li_nextid_wrote = NOID;
-#endif
+ li->li_nextid = -1;
/* default cache size */
li->li_cache.c_maxsize = DEFAULT_CACHE_SIZE;
/* krbv4_ldap_auth LDAP_P(( Backend *be, struct berval *cred, AUTH_DAT *ad )); */
#endif
+/*
+ * startup.c
+ */
+
+void ldbm_back_startup LDAP_P(( Backend *be ));
+void ldbm_back_shutdown LDAP_P(( Backend *be ));
+void ldbm_db_errcall LDAP_P(( char *prefix, char *message ));
+
/*
* nextid.c
*/
be->be_config = ldbm_back_config;
be->be_init = ldbm_back_init;
be->be_close = ldbm_back_close;
+ be->be_startup = ldbm_back_startup;
+ be->be_shutdown = ldbm_back_shutdown;
#ifdef SLAPD_ACLGROUPS
be->be_group = ldbm_back_group;
#endif
return result == 0;
}
+void
+be_startup( void )
+{
+ int i;
+
+ for ( i = 0; i < nbackends; i++ ) {
+ if ( backends[i].be_startup != NULL ) {
+ (*backends[i].be_startup)( &backends[i] );
+ }
+ }
+}
+
+
+void
+be_shutdown( void )
+{
+ int i;
+
+ for ( i = 0; i < nbackends; i++ ) {
+ if ( backends[i].be_shutdown != NULL ) {
+ (*backends[i].be_shutdown)( &backends[i] );
+ }
+ }
+}
+
+
void
be_close( void )
{
static char *strtok_quote(char *line, char *sep);
+/* the old interface for tools */
void
read_config( char *fname, Backend **bep, FILE *pfp )
+{
+ read_config_env( fname, bep, pfp, 0 );
+}
+
+/* the new interface for slapd */
+void
+read_config_env( char *fname, Backend **bep, FILE *pfp, int startup )
{
FILE *fp;
char *line, *savefname;
}
}
fclose( fp );
+
+ if ( startup ) be_startup();
}
static void
extern char *slapd_pid_file;
extern char *slapd_args_file;
+int listener_running = 1;
+
void *
slapd_daemon(
void *port
"slapd shutting down - waiting for backends to close down\n", 0, 0,
0 );
be_close();
- Debug( LDAP_DEBUG_ANY, "slapd stopping\n", 0, 0, 0 );
+ be_shutdown();
+ Debug( LDAP_DEBUG_ANY, "slapd stopped\n", 0, 0, 0 );
+
+ listener_running = 0;
+
return NULL;
}
#endif /* LOG_LOCAL4 */
+extern int listener_running;
+
static void
usage( char *name )
openlog( serverName, OPENLOG_OPTIONS );
#endif
+#ifdef SLAPD_BDB2
+ bdb2i_do_timing = 1;
+#endif
+
init();
- read_config( configfile, &be, fp );
+ read_config_env( configfile, &be, fp, 1 );
if ( ! inetd ) {
int status;
time( &starttime );
- if ( status = ldap_pvt_thread_create( &listener_tid, 0,
+ if ( status = pthread_create( &listener_tid, NULL,
slapd_daemon, (void *) port ) != 0 )
{
Debug( LDAP_DEBUG_ANY,
- "listener ldap_pvt_thread_create failed (%d)\n", status, 0, 0 );
+ "listener pthread_create failed (%d)\n", status, 0, 0 );
exit( 1 );
}
- ldap_pvt_thread_join( listener_tid, (void *) NULL );
+ /* We must prevent the Father of All Threads to terminate
+ before the listener thread has done it's clean-up work
+ (that's not always garuanteed when using LINUX kernel
+ threads :-( ) So we have to withhold the Father, until
+ the listener says OK
+ */
+ while ( listener_running ) {
+ ldap_pvt_thread_join( listener_tid, (void *) NULL );
+ }
return 0;
c.c_sb.sb_ber.ber_buf = NULL;
c.c_sb.sb_ber.ber_ptr = NULL;
c.c_sb.sb_ber.ber_end = NULL;
- ldap_pvt_thread_mutex_init( &c.c_dnmutex );
- ldap_pvt_thread_mutex_init( &c.c_opsmutex );
- ldap_pvt_thread_mutex_init( &c.c_pdumutex );
+ pthread_mutex_init( &c.c_dnmutex, pthread_mutexattr_default );
+ pthread_mutex_init( &c.c_opsmutex, pthread_mutexattr_default );
+ pthread_mutex_init( &c.c_pdumutex, pthread_mutexattr_default );
#ifdef notdefcldap
c.c_sb.sb_addrs = (void **) saddrlist;
c.c_sb.sb_fromaddr = &faddr;
while ( (tag = ber_get_next( &c.c_sb, &len, &ber ))
== LDAP_TAG_MESSAGE ) {
- ldap_pvt_thread_mutex_lock( ¤ttime_mutex );
+ pthread_mutex_lock( ¤ttime_mutex );
time( ¤ttime );
- ldap_pvt_thread_mutex_unlock( ¤ttime_mutex );
+ pthread_mutex_unlock( ¤ttime_mutex );
if ( (tag = ber_get_int( &ber, &msgid ))
!= LDAP_TAG_MSGID ) {
int be_isroot_pw LDAP_P(( Backend *be, char *ndn, struct berval *cred ));
char* be_root_dn LDAP_P(( Backend *be ));
void be_close LDAP_P(( void ));
+void be_startup LDAP_P(( void ));
+void be_shutdown LDAP_P(( void ));
/*
* ch_malloc.c
*/
void read_config LDAP_P(( char *fname, Backend **bep, FILE *pfp ));
+void read_config_env LDAP_P(( char *fname, Backend **bep, FILE *pfp, int up ));
/*
* connection.c
extern int ldbm_back_group LDAP_P((Backend *be, Entry *target,
char *gr_ndn, char *op_ndn,
char *objectclassValue, char *groupattrName ));
+extern void ldbm_back_startup LDAP_P((Backend *be));
+extern void ldbm_back_shutdown LDAP_P((Backend *be));
#endif
#ifdef SLAPD_PASSWD
extern int slap_debug;
+#ifdef SLAPD_BDB2
+extern int bdb2i_do_timing;
+#endif
+
struct slap_op;
struct slap_conn;
void (*be_config) LDAP_P((Backend *be,
char *fname, int lineno, int argc, char **argv ));
void (*be_init) LDAP_P((Backend *be));
+ void (*be_startup) LDAP_P((Backend *be));
+ void (*be_shutdown) LDAP_P((Backend *be));
void (*be_close) LDAP_P((Backend *be));
#ifdef SLAPD_ACLGROUPS
rootpw secret
index cn,sn,uid pres,eq,approx
index default none
+# index default pres,eq,approx
lastmod on
replogfile ./test-db/slapd.replog
updatedn "cn=Manager, o=University of Michigan, c=US"
index cn,sn,uid pres,eq,approx
index default none
+# index default pres,eq,approx
lastmod on
dbcachenowsync