Commit 314f3f6e authored by Kurt Spanier's avatar Kurt Spanier
Browse files

Introduction of a backend startup/shutdown function to make backend-specific

initialization after reading slapd.conf, and before starting the daemon
parent 9f96ab2f
......@@ -202,8 +202,7 @@ LDAP_END_DECL
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 );
......@@ -213,6 +212,16 @@ Datum ldbm_fetch( LDBM ldbm, Datum key );
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 );
......
......@@ -31,95 +31,56 @@
#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;
......@@ -374,17 +335,9 @@ ldbm_errno( LDBM ldbm )
/* 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 );
}
/*****************************************************************
* *
......@@ -401,7 +354,6 @@ ldbm_open( char *name, int rw, int mode, int dbcachesize )
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 ) {
......@@ -410,6 +362,7 @@ ldbm_open( char *name, int rw, int mode, int dbcachesize )
}
LDBM_UNLOCK;
return( db );
}
......@@ -473,6 +426,7 @@ ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
if ( flags & LDBM_SYNC )
gdbm_sync( ldbm );
LDBM_UNLOCK;
return( rc );
}
......@@ -485,6 +439,7 @@ ldbm_delete( LDBM ldbm, Datum key )
rc = gdbm_delete( ldbm, key );
gdbm_sync( ldbm );
LDBM_UNLOCK;
return( rc );
}
......@@ -503,7 +458,7 @@ ldbm_nextkey( LDBM ldbm, Datum key )
{
Datum d;
LDBM_LOCK;
d = gdbm_nextkey( ldbm, key );
d = gdbm_nextkey( ldbm );
LDBM_UNLOCK;
return d;
}
......@@ -513,33 +468,25 @@ ldbm_errno( LDBM ldbm )
{
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 )
......@@ -597,9 +544,11 @@ Datum
ldbm_fetch( LDBM ldbm, Datum key )
{
Datum d;
LDBM_LOCK;
d = ldbm_datum_dup( ldbm, dbm_fetch( ldbm, key ) );
LDBM_UNLOCK;
return d;
}
......@@ -607,9 +556,11 @@ int
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;
}
......@@ -617,9 +568,11 @@ int
ldbm_delete( LDBM ldbm, Datum key )
{
int rc;
LDBM_LOCK;
rc = dbm_delete( ldbm, key );
LDBM_UNLOCK;
return rc;
}
......@@ -627,9 +580,11 @@ Datum
ldbm_firstkey( LDBM ldbm )
{
Datum d;
LDBM_LOCK;
d = dbm_firstkey( ldbm );
LDBM_UNLOCK;
return d;
}
......@@ -637,9 +592,11 @@ Datum
ldbm_nextkey( LDBM ldbm, Datum key )
{
Datum d;
LDBM_LOCK;
d = dbm_nextkey( ldbm );
LDBM_UNLOCK;
return d;
}
......@@ -647,9 +604,11 @@ int
ldbm_errno( LDBM ldbm )
{
int err;
LDBM_LOCK;
err = dbm_error( ldbm );
LDBM_UNLOCK;
return err;
}
......
......@@ -2,11 +2,11 @@ XSRCS = version.c
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
......
......@@ -4,6 +4,7 @@
#define _BACK_LDBM_H_
#include "ldbm.h"
#include "db.h"
LDAP_BEGIN_DECL
......@@ -47,26 +48,16 @@ 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 {
......@@ -76,7 +67,7 @@ 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 */
......@@ -84,10 +75,14 @@ struct dbcache {
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.) */
......@@ -111,20 +106,11 @@ struct attrinfo {
#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;
......@@ -132,8 +118,15 @@ struct ldbminfo {
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"
......
......@@ -34,7 +34,7 @@ ldbm_cache_open(
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 );
......@@ -91,8 +91,13 @@ ldbm_cache_open(
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"
......
......@@ -19,18 +19,11 @@ ldbm_back_init(
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;
......
......@@ -121,6 +121,14 @@ int index_add_values LDAP_P(( Backend *be, char *type, struct berval **vals, ID
/* 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
*/
......
......@@ -54,6 +54,8 @@ new_backend(
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
......@@ -270,6 +272,32 @@ be_isroot_pw( Backend *be, char *ndn, struct berval *cred )
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 )
{
......
......@@ -33,8 +33,16 @@ static void fp_parse_line(char *line, int *argcp, char **argv);
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;
......@@ -471,6 +479,8 @@ read_config( char *fname, Backend **bep, FILE *pfp )
}
}
fclose( fp );
if ( startup ) be_startup();
}
static void
......
......@@ -44,6 +44,8 @@ static void do_nothing (int sig);
extern char *slapd_pid_file;
extern char *slapd_args_file;
int listener_running = 1;
void *
slapd_daemon(
void *port
......@@ -391,7 +393,11 @@ slapd_daemon(
"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;
}
......
......@@ -49,6 +49,8 @@ static int cnvt_str2int();
#endif /* LOG_LOCAL4 */
extern int listener_running;
static void
usage( char *name )
......@@ -187,23 +189,35 @@ main( int argc, char **argv )
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 );