PROTOTYPE: New connection management infrastructure designed to

remove race conditions on connection close.
BROKEN: various counters for dn=monitor.
Initial testing on FreeBSD (with and without pthreads) was successfull.
Have not yet tested preemptive threading environments.
Have not built against backends other than LDBM.
This commit is contained in:
Kurt Zeilenga 1999-03-22 07:14:54 +00:00
parent 61f6d5d8ca
commit 8f02beada9
20 changed files with 1185 additions and 611 deletions

View file

@ -49,19 +49,28 @@ do_abandon(
* flag and abort the operation at a convenient time.
*/
ldap_pvt_thread_mutex_lock( &conn->c_opsmutex );
ldap_pvt_thread_mutex_lock( &conn->c_mutex );
for ( o = conn->c_ops; o != NULL; o = o->o_next ) {
if ( o->o_msgid == id )
goto found_op;
}
for ( o = conn->c_pending_ops; o != NULL; o = o->o_next ) {
if ( o->o_msgid == id )
break;
}
found_op:
if ( o != NULL ) {
ldap_pvt_thread_mutex_lock( &o->o_abandonmutex );
o->o_abandon = 1;
ldap_pvt_thread_mutex_unlock( &o->o_abandonmutex );
} else {
Debug( LDAP_DEBUG_TRACE, "do_abandon: op not found\n", 0, 0,
0 );
}
ldap_pvt_thread_mutex_unlock( &conn->c_opsmutex );
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
}

View file

@ -287,7 +287,9 @@ acl_access_allowed(
}
}
if ( b->a_addrpat != NULL ) {
if ( regex_matches( b->a_addrpat, conn->c_addr, edn, matches ) ) {
if ( regex_matches( b->a_addrpat, conn->c_client_addr,
edn, matches ) )
{
Debug( LDAP_DEBUG_ACL,
"<= acl_access_allowed: matched by clause #%d access %s\n",
i, (b->a_access & ~ACL_SELF) >= access ?
@ -299,7 +301,8 @@ acl_access_allowed(
if ( b->a_domainpat != NULL ) {
Debug( LDAP_DEBUG_ARGS, "<= check a_domainpath: %s\n",
b->a_domainpat, 0, 0 );
if ( regex_matches( b->a_domainpat, conn->c_domain, edn, matches ) )
if ( regex_matches( b->a_domainpat, conn->c_client_name,
edn, matches ) )
{
Debug( LDAP_DEBUG_ACL,
"<= acl_access_allowed: matched by clause #%d access %s\n",

View file

@ -151,6 +151,7 @@ add_created_attrs( Operation *op, Entry *e )
Attribute **a, **next;
Attribute *tmp;
struct tm *ltm;
time_t currenttime;
Debug( LDAP_DEBUG_TRACE, "add_created_attrs\n", 0, 0, 0 );
@ -181,7 +182,8 @@ add_created_attrs( Operation *op, Entry *e )
}
attr_merge( e, "creatorsname", bvals );
ldap_pvt_thread_mutex_lock( &currenttime_mutex );
currenttime = slap_get_time();
ldap_pvt_thread_mutex_lock( &gmtime_mutex );
#ifndef LDAP_LOCALTIME
ltm = gmtime( &currenttime );
strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
@ -189,7 +191,7 @@ add_created_attrs( Operation *op, Entry *e )
ltm = localtime( &currenttime );
strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
#endif
ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
bv.bv_val = buf;
bv.bv_len = strlen( bv.bv_val );

View file

@ -41,9 +41,7 @@ ldbm_cache_open(
flags, li->li_mode );
lru = 0;
ldap_pvt_thread_mutex_lock( &currenttime_mutex );
curtime = currenttime;
ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
curtime = slap_get_time();
oldtime = curtime;
ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex );

View file

@ -139,6 +139,7 @@ ldbm_back_search(
rcur = strchr( rbuf, '\0' );
for ( id = idl_firstid( candidates ); id != NOID;
id = idl_nextid( candidates, id ) ) {
/* check for abandon */
ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
if ( op->o_abandon ) {
@ -153,10 +154,7 @@ ldbm_back_search(
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
/* check time limit */
ldap_pvt_thread_mutex_lock( &currenttime_mutex );
time( &currenttime );
if ( tlimit != -1 && currenttime > stoptime ) {
ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
if ( tlimit != -1 && slap_get_time() > stoptime ) {
send_ldap_search_result( conn, op,
LDAP_TIMELIMIT_EXCEEDED, NULL, nrefs > 0 ? rbuf :
NULL, nentries );
@ -167,7 +165,6 @@ ldbm_back_search(
}
return( 0 );
}
ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
/* get the entry with reader lock */
if ( (e = id2entry_r( be, id )) == NULL ) {

View file

@ -135,7 +135,7 @@ do_bind(
free( cred.bv_val );
}
ldap_pvt_thread_mutex_lock( &conn->c_dnmutex );
ldap_pvt_thread_mutex_lock( &conn->c_mutex );
conn->c_protocol = version;
@ -149,7 +149,7 @@ do_bind(
conn->c_dn = NULL;
}
ldap_pvt_thread_mutex_unlock( &conn->c_dnmutex );
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
return;
@ -168,7 +168,7 @@ do_bind(
free( cred.bv_val );
}
if ( cred.bv_len == 0 ) {
ldap_pvt_thread_mutex_lock( &conn->c_dnmutex );
ldap_pvt_thread_mutex_lock( &conn->c_mutex );
conn->c_protocol = version;
@ -182,7 +182,7 @@ do_bind(
conn->c_dn = NULL;
}
ldap_pvt_thread_mutex_unlock( &conn->c_dnmutex );
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
send_ldap_result( conn, op, LDAP_SUCCESS,
NULL, NULL );
@ -203,7 +203,7 @@ do_bind(
ndn = suffixAlias( ndn, op, be );
if ( (*be->be_bind)( be, conn, op, ndn, method, &cred, &edn ) == 0 ) {
ldap_pvt_thread_mutex_lock( &conn->c_dnmutex );
ldap_pvt_thread_mutex_lock( &conn->c_mutex );
conn->c_protocol = version;
@ -228,7 +228,7 @@ do_bind(
Debug( LDAP_DEBUG_TRACE, "do_bind: bound \"%s\" to \"%s\"\n",
conn->c_cdn, conn->c_dn, method );
ldap_pvt_thread_mutex_unlock( &conn->c_dnmutex );
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
/* send this here to avoid a race condition */
send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );

View file

@ -10,6 +10,16 @@
#include "slap.h"
/* protected by connections_mutex */
static ldap_pvt_thread_mutex_t connections_mutex;
static Connection *connections = NULL;
static int conn_index = -1;
static long conn_nextid = 0;
static Connection* connection_get( int s );
static int connection_input( Connection *c );
static int connection_op_activate( Connection *conn, Operation *op );
static int connection_resched( Connection *conn );
@ -18,6 +28,360 @@ struct co_arg {
Operation *co_op;
};
/*
* Initialize connection management infrastructure.
*/
int connections_init(void)
{
int i;
assert( connections == NULL );
if( connections != NULL) { /* probably should assert this */
Debug( LDAP_DEBUG_ANY, "connections_init: already initialized.\n",
0, 0, 0 );
return -1;
}
/* should check return of every call */
ldap_pvt_thread_mutex_init( &connections_mutex );
connections = (Connection *) calloc( dtblsize, sizeof(Connection) );
if( connections == NULL ) {
Debug( LDAP_DEBUG_ANY,
"connections_init: allocation (%d*%ld) of connection array failed.\n",
dtblsize, (long) sizeof(Connection), 0 );
return -1;
}
/*
* per entry initialization of the Connection array initialization
* will be done by connection_init()
*/
return 0;
}
static Connection* connection_get( int s )
{
Connection *c = NULL;
assert( connections != NULL );
if(s < 0) {
return NULL;
}
#ifndef HAVE_WINSOCK
assert( connections[s].c_struct_state == SLAP_C_USED );
assert( connections[s].c_conn_state != SLAP_C_INVALID );
assert( connections[s].c_sb.sb_sd != -1 );
c = &connections[s];
#else
{
int i;
for(i=0; i<dtblsize; i++) {
if( connections[i].c_struct_state == SLAP_C_STRUCT_UNINITIALIZED ) {
assert( connections[i].c_conn_state == SLAP_C_INVALID );
assert( connections[s].c_sb.sb_sd == 0 );
break;
}
if( connections[i].c_struct_state == SLAP_C_STRUCT_UNUSED ) {
assert( connections[i].c_conn_state == SLAP_C_INVALID );
assert( connections[s].c_sb.sb_sd == -1 );
continue;
}
assert( connections[i].c_struct_state == SLAP_C_STRUCT_USED );
assert( connections[i].c_conn_state != SLAP_C_INVALID );
assert( connections[s].c_sb.sb_sd != -1 );
if( connections[i].c_sb.sb_sd == s ) {
c = &connections[s];
break;
}
}
}
#endif
if( c != NULL ) {
ldap_pvt_thread_mutex_lock( &c->c_mutex );
}
return c;
}
static void connection_return( Connection *c )
{
ldap_pvt_thread_mutex_unlock( &c->c_mutex );
}
long connection_init(
int s,
const char* name,
const char* addr)
{
long id;
Connection *c;
assert( connections != NULL );
if( s < 0 ) {
return -1;
}
assert( s >= 0 );
#ifndef HAVE_WINSOCK
assert( s < dtblsize );
#endif
ldap_pvt_thread_mutex_lock( &connections_mutex );
#ifndef HAVE_WINSOCK
c = &connections[s];
#else
{
int i;
for( i=0; i < dtblsize; i++ {
if( connections[i].c_struct_state == SLAP_C_UNINITIALIZED ) {
assert( connections[i].c_sb.sb_sd == 0 );
c = &connections[i];
break;
}
if( connections[i].c_struct_state == SLAP_C_UNUSED ) {
assert( connections[i].c_sb.sb_sd == -1 );
c = &connections[i];
break;
}
assert( connections[i].c_struct_state == SLAP_C_USED );
assert( connections[i].c_conn_state != SLAP_C_INVALID );
assert( connections[i].c_sb.sb_sd != -1 );
}
if( c == NULL ) {
ldap_pvt_thread_mutex_unlock( &connections_mutex );
return -1;
}
}
#endif
assert( c != NULL );
assert( c->c_struct_state != SLAP_C_USED );
assert( c->c_conn_state == SLAP_C_INVALID );
if( c->c_struct_state == SLAP_C_UNINITIALIZED ) {
c->c_dn = NULL;
c->c_cdn = NULL;
c->c_client_name = NULL;
c->c_client_addr = NULL;
c->c_ops = NULL;
c->c_pending_ops = NULL;
lber_pvt_sb_init( &c->c_sb );
/* should check status of thread calls */
ldap_pvt_thread_mutex_init( &c->c_mutex );
ldap_pvt_thread_mutex_init( &c->c_write_mutex );
ldap_pvt_thread_cond_init( &c->c_write_cv );
c->c_struct_state = SLAP_C_UNUSED;
}
ldap_pvt_thread_mutex_lock( &c->c_mutex );
assert( c->c_struct_state == SLAP_C_UNUSED );
assert( c->c_dn == NULL );
assert( c->c_cdn == NULL );
assert( c->c_client_name == NULL );
assert( c->c_client_addr == NULL );
assert( c->c_ops == NULL );
assert( c->c_pending_ops == NULL );
c->c_client_name = ch_strdup( name == NULL ? "" : name );
c->c_client_addr = ch_strdup( addr );
c->c_n_ops_received = 0;
#ifdef LDAP_COUNTERS
c->c_n_ops_executing = 0;
c->c_n_ops_pending = 0;
c->c_n_ops_completed = 0;
#endif
c->c_starttime = slap_get_time();
lber_pvt_sb_set_desc( &c->c_sb, s );
lber_pvt_sb_set_io( &c->c_sb, &lber_pvt_sb_io_tcp, NULL );
if( lber_pvt_sb_set_nonblock( &c->c_sb, 1 ) < 0 ) {
Debug( LDAP_DEBUG_ANY,
"connection_init(%d, %s, %s): set nonblocking failed\n",
s, c->c_client_name, c->c_client_addr);
}
id = c->c_connid = conn_nextid++;
c->c_conn_state = SLAP_C_INACTIVE;
c->c_struct_state = SLAP_C_USED;
ldap_pvt_thread_mutex_unlock( &c->c_mutex );
ldap_pvt_thread_mutex_unlock( &connections_mutex );
return id;
}
static void
connection_destroy( Connection *c )
{
assert( connections != NULL );
assert( c != NULL );
assert( c->c_struct_state != SLAP_C_UNUSED );
assert( c->c_conn_state != SLAP_C_INVALID );
assert( c->c_ops == NULL );
c->c_struct_state = SLAP_C_UNUSED;
c->c_conn_state = SLAP_C_INVALID;
c->c_version = 0;
c->c_protocol = 0;
c->c_starttime = 0;
if(c->c_dn != NULL) {
free(c->c_dn);
c->c_dn = NULL;
}
if(c->c_cdn != NULL) {
free(c->c_cdn);
c->c_cdn = NULL;
}
if(c->c_client_name != NULL) {
free(c->c_client_name);
c->c_client_name = NULL;
}
if(c->c_client_addr != NULL) {
free(c->c_client_addr);
c->c_client_addr = NULL;
}
if ( lber_pvt_sb_in_use(&c->c_sb) ) {
int sd = lber_pvt_sb_get_desc(&c->c_sb);
slapd_remove( sd );
lber_pvt_sb_close( &c->c_sb );
Statslog( LDAP_DEBUG_STATS,
"conn=%d fd=%d closed.\n",
c->c_connid, sd, 0, 0, 0 );
}
lber_pvt_sb_destroy( &c->c_sb );
}
static void connection_close( Connection *c )
{
assert( connections != NULL );
assert( c != NULL );
assert( c->c_struct_state == SLAP_C_USED );
assert( c->c_conn_state == SLAP_C_CLOSING );
if( c->c_ops != NULL ) {
Debug( LDAP_DEBUG_TRACE,
"connection_close: deferring conn=%ld sd=%d.\n",
c->c_connid, c->c_sb.sb_sd, 0 );
return;
}
Debug( LDAP_DEBUG_TRACE, "connection_close: conn=%ld sd=%d.\n",
c->c_connid, c->c_sb.sb_sd, 0 );
connection_destroy( c );
}
long connections_nextid(void)
{
long id;
assert( connections != NULL );
ldap_pvt_thread_mutex_lock( &connections_mutex );
id = conn_nextid;
ldap_pvt_thread_mutex_unlock( &connections_mutex );
return id;
}
Connection* connection_first(void)
{
assert( connections != NULL );
ldap_pvt_thread_mutex_lock( &connections_mutex );
assert( conn_index == -1 );
conn_index = 0;
return connection_next(NULL);
}
Connection* connection_next(Connection *c)
{
assert( connections != NULL );
assert( conn_index != -1 );
assert( conn_index <= dtblsize );
if( c != NULL ) {
ldap_pvt_thread_mutex_unlock( &c->c_mutex );
}
c = NULL;
for(; conn_index < dtblsize; conn_index++) {
if( connections[conn_index].c_struct_state == SLAP_C_UNINITIALIZED ) {
assert( connections[conn_index].c_conn_state == SLAP_C_INVALID );
#ifndef HAVE_WINSOCK
continue;
#else
break;
#endif
}
if( connections[conn_index].c_struct_state == SLAP_C_USED ) {
assert( connections[conn_index].c_conn_state != SLAP_C_INVALID );
c = &connections[conn_index++];
break;
}
assert( connections[conn_index].c_struct_state == SLAP_C_UNUSED );
assert( connections[conn_index].c_conn_state == SLAP_C_INVALID );
}
if( c != NULL ) {
ldap_pvt_thread_mutex_lock( &c->c_mutex );
}
return c;
}
void connection_done(Connection *c)
{
assert( connections != NULL );
assert( conn_index != -1 );
assert( conn_index <= dtblsize );
if( c != NULL ) {
ldap_pvt_thread_mutex_unlock( &c->c_mutex );
}
conn_index = -1;
ldap_pvt_thread_mutex_unlock( &connections_mutex );
}
/*
* connection_activity - handle the request operation op on connection
* conn. This routine figures out what kind of operation it is and
@ -31,13 +395,11 @@ connection_operation( void *arg_v )
int tag = arg->co_op->o_tag;
Connection *conn = arg->co_conn;
ldap_pvt_thread_mutex_lock( &conn->c_opsmutex );
conn->c_ops_received++;
ldap_pvt_thread_mutex_unlock( &conn->c_opsmutex );
#ifdef LDAP_COUNTERS
ldap_pvt_thread_mutex_lock( &ops_mutex );
ops_initiated++;
ldap_pvt_thread_mutex_unlock( &ops_mutex );
#endif
switch ( tag ) {
case LDAP_REQ_BIND:
@ -91,12 +453,17 @@ connection_operation( void *arg_v )
break;
}
#ifdef LDAP_COUNTERS
ldap_pvt_thread_mutex_lock( &ops_mutex );
ops_completed++;
ldap_pvt_thread_mutex_unlock( &ops_mutex );
#endif
ldap_pvt_thread_mutex_lock( &conn->c_opsmutex );
ldap_pvt_thread_mutex_lock( &conn->c_mutex );
#ifdef LDAP_COUNTERS
conn->c_ops_completed++;
#endif
slap_op_remove( &conn->c_ops, arg->co_op );
slap_op_free( arg->co_op );
@ -105,11 +472,27 @@ connection_operation( void *arg_v )
free( (char *) arg );
arg = NULL;
if((tag == LDAP_REQ_BIND) && (conn->c_state == SLAP_C_BINDING)) {
conn->c_state = SLAP_C_ACTIVE;
switch( tag ) {
#ifdef LDAP_COMPAT30
case LDAP_REQ_UNBIND_30:
#endif
case LDAP_REQ_UNBIND:
conn->c_conn_state = SLAP_C_CLOSING;
break;
case LDAP_REQ_BIND:
if( conn->c_conn_state == SLAP_C_BINDING) {
conn->c_conn_state = SLAP_C_ACTIVE;
}
}
ldap_pvt_thread_mutex_unlock( &conn->c_opsmutex );
if( conn->c_conn_state == SLAP_C_CLOSING ) {
Debug( LDAP_DEBUG_TRACE,
"connection_operation: attempting closing conn=%ld sd=%d.\n",
conn->c_connid, conn->c_sb.sb_sd, 0 );
connection_close( conn );
}
ldap_pvt_thread_mutex_lock( &active_threads_mutex );
active_threads--;
@ -120,11 +503,58 @@ connection_operation( void *arg_v )
connection_resched( conn );
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
return NULL;
}
void
connection_activity(
int connection_read(int s)
{
int rc = 0;
Connection *c;
assert( connections != NULL );
ldap_pvt_thread_mutex_lock( &connections_mutex );
c = connection_get( s );
if( c == NULL ) {
Debug( LDAP_DEBUG_ANY,
"connection_read(%d): no connection!\n",
s, 0, 0 );
return -1;
}
Debug( LDAP_DEBUG_TRACE,
"connection_read(%d): checking for input on id=%ld\n",
s, c->c_connid, 0 );
#define CONNECTION_INPUT_LOOP 1
#ifdef DATA_READY_LOOP
while(!rc && lber_pvt_sb_data_ready(&c->c_sb))
#elif CONNECTION_INPUT_LOOP
while(!rc)
#endif
{
rc = connection_input( c );
}
if( rc < 0 ) {
Debug( LDAP_DEBUG_TRACE,
"connection_read(%d): input error id=%ld, closing.\n",
s, c->c_connid, 0 );
c->c_conn_state = SLAP_C_CLOSING;
connection_close( c );
}
connection_return( c );
ldap_pvt_thread_mutex_unlock( &connections_mutex );
return 0;
}
static int
connection_input(
Connection *conn
)
{
@ -136,30 +566,32 @@ connection_activity(
if ( conn->c_currentber == NULL && (conn->c_currentber = ber_alloc())
== NULL ) {
Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
return;
return -1;
}
errno = 0;
if ( (tag = ber_get_next( &conn->c_sb, &len, conn->c_currentber ))
!= LDAP_TAG_MESSAGE ) {
!= LDAP_TAG_MESSAGE )
{
Debug( LDAP_DEBUG_TRACE,
"ber_get_next on fd %d failed errno %d (%s)\n",
lber_pvt_sb_get_desc(&conn->c_sb), errno, errno > -1 && errno < sys_nerr ?
sys_errlist[errno] : "unknown" );
Debug( LDAP_DEBUG_TRACE, "*** got %ld of %lu so far\n",
(long)(conn->c_currentber->ber_rwptr - conn->c_currentber->ber_buf),
conn->c_currentber->ber_len, 0 );
"ber_get_next on fd %d failed errno %d (%s)\n",
lber_pvt_sb_get_desc(&conn->c_sb), errno,
errno > -1 && errno < sys_nerr ? sys_errlist[errno] : "unknown" );
Debug( LDAP_DEBUG_TRACE, "\t*** got %ld of %lu so far\n",
(long)(conn->c_currentber->ber_rwptr - conn->c_currentber->ber_buf),
conn->c_currentber->ber_len, 0 );
if ( errno != EWOULDBLOCK && errno != EAGAIN ) {
/* log, close and send error */
ber_free( conn->c_currentber, 1 );
conn->c_currentber = NULL;
close_connection( conn, conn->c_connid, -1 );
return -1;
}
return;
return 1;
}
ber = conn->c_currentber;
conn->c_currentber = NULL;
@ -168,9 +600,7 @@ connection_activity(
Debug( LDAP_DEBUG_ANY, "ber_get_int returns 0x%lx\n", tag, 0,
0 );
ber_free( ber, 1 );
close_connection( conn, conn->c_connid, -1 );
return;
return -1;
}
if ( (tag = ber_peek_tag( ber, &len )) == LBER_ERROR ) {
@ -179,8 +609,7 @@ connection_activity(
0 );
ber_free( ber, 1 );
close_connection( conn, conn->c_connid, -1 );
return;
return -1;
}
#ifdef LDAP_COMPAT30
@ -189,22 +618,27 @@ connection_activity(
}
#endif
op = slap_op_alloc( ber, msgid, tag,
conn->c_ops_received, conn->c_connid );
op = slap_op_alloc( ber, msgid, tag, conn->c_n_ops_received++ );
if ( conn->c_state == SLAP_C_BINDING ) {
/* connection is binding to a dn, make 'em wait */
ldap_pvt_thread_mutex_lock( &conn->c_opsmutex );
if ( conn->c_conn_state == SLAP_C_BINDING
|| conn->c_conn_state == SLAP_C_CLOSING )
{
Debug( LDAP_DEBUG_ANY, "deferring operation\n", 0, 0, 0 );
slap_op_add( &conn->c_pending_ops, op );
Debug( LDAP_DEBUG_ANY, "deferring operation\n", 0, 0, 0 );
ldap_pvt_thread_mutex_unlock( &conn->c_opsmutex );
return;
} else {
connection_op_activate( conn, op );
}
connection_op_activate( conn, op );
#ifdef NO_THREADS
if ( conn->c_struct_state != SLAP_C_USED ) {
/* connection must have got closed underneath us */
return 1;
}
#endif
assert( conn->c_struct_state == SLAP_C_USED );
return 0;
}
static int
@ -212,29 +646,21 @@ connection_resched( Connection *conn )
{
Operation *op;
if( conn->c_state != SLAP_C_ACTIVE ) {
if( conn->c_conn_state != SLAP_C_ACTIVE ) {
/* other states need different handling */
return;
}
ldap_pvt_thread_mutex_lock( &conn->c_opsmutex );
for( op = slap_op_pop( &conn->c_pending_ops );
op != NULL;
op = slap_op_pop( &conn->c_pending_ops ) )
{
ldap_pvt_thread_mutex_unlock( &conn->c_opsmutex );
connection_op_activate( conn, op );
ldap_pvt_thread_mutex_lock( &conn->c_opsmutex );
if ( conn->c_state == SLAP_C_BINDING ) {
if ( conn->c_conn_state == SLAP_C_BINDING ) {
break;
}
}
ldap_pvt_thread_mutex_unlock( &conn->c_opsmutex );
}
static int connection_op_activate( Connection *conn, Operation *op )
@ -244,13 +670,11 @@ static int connection_op_activate( Connection *conn, Operation *op )
int status;
unsigned long tag = op->o_tag;
ldap_pvt_thread_mutex_lock( &conn->c_dnmutex );
if ( conn->c_dn != NULL ) {
tmpdn = ch_strdup( conn->c_dn );
} else {
tmpdn = NULL;
}
ldap_pvt_thread_mutex_unlock( &conn->c_dnmutex );
arg = (struct co_arg *) ch_malloc( sizeof(struct co_arg) );
arg->co_conn = conn;
@ -259,16 +683,12 @@ static int connection_op_activate( Connection *conn, Operation *op )
arg->co_op->o_dn = ch_strdup( tmpdn != NULL ? tmpdn : "" );
arg->co_op->o_ndn = dn_normalize_case( ch_strdup( arg->co_op->o_dn ) );
ldap_pvt_thread_mutex_lock( &conn->c_opsmutex );
slap_op_add( &conn->c_ops, arg->co_op );
if(tag == LDAP_REQ_BIND) {
conn->c_state = SLAP_C_BINDING;
conn->c_conn_state = SLAP_C_BINDING;
}
ldap_pvt_thread_mutex_unlock( &conn->c_opsmutex );
if ( tmpdn != NULL ) {
free( tmpdn );
}
@ -281,8 +701,37 @@ static int connection_op_activate( Connection *conn, Operation *op )
connection_operation, (void *) arg );
if ( status != 0 ) {
Debug( LDAP_DEBUG_ANY, "ldap_pvt_thread_create failed (%d)\n", status, 0, 0 );
Debug( LDAP_DEBUG_ANY,
"ldap_pvt_thread_create failed (%d)\n", status, 0, 0 );
/* should move op to pending list */
}
return status;
}
int connection_write(int s)
{
Connection *c;
assert( connections != NULL );
ldap_pvt_thread_mutex_lock( &connections_mutex );
c = connection_get( s );
if( c == NULL ) {
Debug( LDAP_DEBUG_ANY,
"connection_write(%d): no connection!\n",
s, 0, 0 );
return -1;
}
Debug( LDAP_DEBUG_TRACE,
"connection_write(%d): waking output for id=%ld\n",
s, c->c_connid, 0 );
ldap_pvt_thread_cond_signal( &c->c_write_cv );
connection_return( c );
ldap_pvt_thread_mutex_unlock( &connections_mutex );
return 0;
}

View file

@ -1,10 +1,3 @@
/* Revision history
*
* 5-Jun-96 hodges
* Added locking of new_conn_mutex when traversing the c[] array.
*/
#include "portable.h"
#include <stdio.h>
@ -33,26 +26,113 @@ int allow_severity = LOG_INFO;
int deny_severity = LOG_NOTICE;
#endif /* TCP Wrappers */
int dtblsize;
Connection *c;
/* globals */
int dtblsize;
static ldap_pvt_thread_t listener_tid;
static volatile sig_atomic_t slapd_shutdown = 0;
/* a link to the slapd.conf configuration parameters */
extern char *slapd_pid_file;
extern char *slapd_args_file;
struct slap_daemon {
ldap_pvt_thread_mutex_t sd_mutex;
void *
slapd_daemon(
int sd_nactives;
#ifndef HAVE_WINSOCK
/* In winsock, accept() returns values higher than dtblsize
so don't bother with this optimization */
int sd_nfds;
#endif
fd_set sd_actives;
fd_set sd_readers;
fd_set sd_writers;
} slap_daemon;
/*
* Add a descriptor to daemon control
*/
static void slapd_add(int s) {
ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
assert( !FD_ISSET( s, &slap_daemon.sd_actives ));
assert( !FD_ISSET( s, &slap_daemon.sd_readers ));
assert( !FD_ISSET( s, &slap_daemon.sd_writers ));
if (s >= slap_daemon.sd_nfds) {
slap_daemon.sd_nfds = s + 1;
}
FD_SET( s, &slap_daemon.sd_actives );
FD_SET( s, &slap_daemon.sd_readers );
Debug( LDAP_DEBUG_CONNS, "daemon: added %d%s%s\n", s,
FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
}
/*
* Remove the descriptor from daemon control
*/
void slapd_remove(int s) {
ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
assert( s < slap_daemon.sd_nfds );
assert( FD_ISSET( s, &slap_daemon.sd_actives ));
Debug( LDAP_DEBUG_CONNS, "daemon: removing %d%s%s\n", s,
FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
FD_CLR( s, &slap_daemon.sd_actives );
FD_CLR( s, &slap_daemon.sd_readers );
FD_CLR( s, &slap_daemon.sd_writers );
ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
}
void slapd_clr_write(int s, int wake) {
ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
assert( s < slap_daemon.sd_nfds );
assert( FD_ISSET( s, &slap_daemon.sd_actives) );
assert( FD_ISSET( s, &slap_daemon.sd_writers) );
FD_SET( s, &slap_daemon.sd_writers );
ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
if( wake ) {
ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
}
}
void slapd_set_write(int s, int wake) {
ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
FD_SET( s, &slap_daemon.sd_writers );
ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
if( wake ) {
ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
}
}
static void slapd_close(int s) {
slapd_remove(s);
Debug( LDAP_DEBUG_CONNS, "daemon: closing %d\n", s, 0, 0 );
close(s);
}
static void *
slapd_daemon_task(
void *ptr
)
{
struct sockaddr_in *addr = ptr;
int i;
int tcps, ns;
fd_set readfds;
fd_set writefds;
FILE *fp;
int tcps = -1;
#ifdef HAVE_SYSCONF
dtblsize = sysconf( _SC_OPEN_MAX );
@ -68,179 +148,201 @@ slapd_daemon(
}
#endif /* !FD_SETSIZE */
c = (Connection *) ch_calloc( (size_t) dtblsize, sizeof(Connection) );
connections_init();
for ( i = 0; i < dtblsize; i++ ) {
c[i].c_dn = NULL;
c[i].c_cdn = NULL;
c[i].c_addr = NULL;
c[i].c_domain = NULL;
c[i].c_ops = NULL;
lber_pvt_sb_init( &c[i].c_sb );
ldap_pvt_thread_mutex_init( &c[i].c_dnmutex );
ldap_pvt_thread_mutex_init( &c[i].c_opsmutex );
ldap_pvt_thread_mutex_init( &c[i].c_pdumutex );
ldap_pvt_thread_cond_init( &c[i].c_wcv );
}
ldap_pvt_thread_mutex_init( &slap_daemon.sd_mutex );
FD_ZERO( &slap_daemon.sd_readers );
FD_ZERO( &slap_daemon.sd_writers );
if ( (tcps = socket( AF_INET, SOCK_STREAM, 0 )) == -1 ) {
Debug( LDAP_DEBUG_ANY, "socket() failed errno %d (%s)", errno,
errno > -1 && errno < sys_nerr ? sys_errlist[errno] :
"unknown", 0 );
exit( 1 );
}
if( addr != NULL ) {
int tmp;
i = 1;
if ( setsockopt( tcps, SOL_SOCKET, SO_REUSEADDR, (char *) &i,
sizeof(i) ) == -1 ) {
Debug( LDAP_DEBUG_ANY, "setsockopt() failed errno %d (%s)",
errno, errno > -1 && errno < sys_nerr ? sys_errlist[errno] :
"unknown", 0 );
}
if ( bind( tcps, (struct sockaddr *) addr, sizeof(*addr) ) == -1 ) {
Debug( LDAP_DEBUG_ANY, "bind() failed errno %d (%s)\n",
errno, errno > -1 && errno < sys_nerr ? sys_errlist[errno] :
"unknown", 0 );
exit( 1 );
}
if ( listen( tcps, 5 ) == -1 ) {
Debug( LDAP_DEBUG_ANY, "listen() failed errno %d (%s)",
errno, errno > -1 && errno < sys_nerr ? sys_errlist[errno] :
"unknown", 0 );
exit( 1 );
}
Debug( LDAP_DEBUG_ANY, "slapd starting\n", 0, 0, 0 );
if (( slapd_pid_file != NULL ) &&
(( fp = fopen( slapd_pid_file, "w" )) != NULL )) {
fprintf( fp, "%d\n", (int) getpid() );
fclose( fp );
}
if (( slapd_args_file != NULL ) &&
(( fp = fopen( slapd_args_file, "w" )) != NULL )) {
for ( i = 0; i < g_argc; i++ ) {
fprintf( fp, "%s ", g_argv[i] );
if ( (tcps = socket( AF_INET, SOCK_STREAM, 0 )) == -1 ) {
Debug( LDAP_DEBUG_ANY,
"daemon: socket() failed errno %d (%s)", errno,
errno > -1 && errno < sys_nerr ? sys_errlist[errno] :
"unknown", 0 );
exit( 1 );
}
fprintf( fp, "\n" );
fclose( fp );
#ifndef HAVE_WINSOCK
if ( tcps >= dtblsize ) {
Debug( LDAP_DEBUG_ANY,
"daemon: listener descriptor %d is too great",
tcps, dtblsize, 0 );
exit( 1 );
}
#endif
tmp = 1;
if ( setsockopt( tcps, SOL_SOCKET, SO_REUSEADDR,
(char *) &tmp, sizeof(tmp) ) == -1 )
{
Debug( LDAP_DEBUG_ANY,
"slapd(%d): setsockopt() failed errno %d (%s)",
tcps, errno,
errno > -1 && errno < sys_nerr
? sys_errlist[errno] : "unknown" );
errno = 0;
}
if ( bind( tcps, (struct sockaddr *) addr, sizeof(*addr) ) == -1 ) {
Debug( LDAP_DEBUG_ANY, "daemon: bind(%d) failed errno %d (%s)\n",
tcps, errno,
errno > -1 && errno < sys_nerr
? sys_errlist[errno] : "unknown" );
exit( 1 );
}
if ( listen( tcps, 5 ) == -1 ) {
Debug( LDAP_DEBUG_ANY,
"daemon: listen(%d, 5) failed errno %d (%s)\n",
tcps, errno,
errno > -1 && errno < sys_nerr
? sys_errlist[errno] : "unknown" );
exit( 1 );
}
slapd_add( tcps );
} else {
if( connection_init( 0, NULL, NULL ) ) {
Debug( LDAP_DEBUG_ANY,
"connection_init(%d) failed.\n",
0, 0, 0 );
exit( 1 );
}
slapd_add( 0 );
}
while ( !slapd_shutdown ) {
int i, ns, nfds;
fd_set readfds;
fd_set writefds;
struct sockaddr_in from;
struct hostent *hp;
struct timeval zero;
struct timeval *tvp;
int len;
int data_ready;
char *client_name;
char *client_addr;
FD_ZERO( &writefds );
FD_ZERO( &readfds );
FD_SET( tcps, &readfds );
zero.tv_sec = 0;
zero.tv_usec = 0;
ldap_pvt_thread_mutex_lock( &active_threads_mutex );
Debug( LDAP_DEBUG_CONNS,
"listening for connections on %d, activity on:",
tcps, 0, 0 );
data_ready = 0;
ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
ldap_pvt_thread_mutex_lock( &new_conn_mutex );
for ( i = 0; i < dtblsize; i++ ) {
if ( (c[i].c_state != SLAP_C_INACTIVE)
&& (c[i].c_state != SLAP_C_CLOSING) )
{
assert(lber_pvt_sb_in_use( &c[i].c_sb ));
FD_SET( lber_pvt_sb_get_desc(&c[i].c_sb),
&readfds );
if (lber_pvt_sb_data_ready(&c[i].c_sb))
data_ready = 1;
if ( c[i].c_writewaiter ) {
FD_SET( lber_pvt_sb_get_desc(&c[i].c_sb),
&writefds );
}
Debug( LDAP_DEBUG_CONNS, " %dr%s", i,
c[i].c_writewaiter ? "w" : "", 0 );
#ifdef FD_SET_MANUAL_COPY
for( s = 0; s < nfds; s++ ) {
if(FD_ISSET( &slap_sd_writers, s )) {
FD_SET( &writefds, s );
}
if(FD_ISSET( &slap_sd_writers, s )) {
FD_SET( &writefds, s );
}
}
Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
Debug( LDAP_DEBUG_CONNS, "before select active_threads %d\n",
active_threads, 0, 0 );
#if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS )
tvp = (data_ready) ? &zero : NULL;
#else
tvp = (active_threads || data_ready) ? &zero : NULL;
memcpy( &readfds, &slap_daemon.sd_readers, sizeof(fd_set) );
memcpy( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) );
#endif
FD_SET( tcps, &readfds );
#ifndef HAVE_WINSOCK
nfds = slap_daemon.sd_nfds;
#else
nfds = dtblsize;
#endif
ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
ldap_pvt_thread_mutex_lock( &active_threads_mutex );
#if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS )
tvp = NULL;
#else
tvp = active_threads ? &zero : NULL;
#endif
Debug( LDAP_DEBUG_CONNS,
"daemon: select: tcps=%d active_threads=%d tvp=%s\n",
tcps, active_threads,
tvp == NULL ? "NULL" : "zero" );
ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
switch ( i = select( dtblsize, &readfds, &writefds, 0, tvp ) ) {
switch(ns = select( nfds, &readfds, &writefds, 0, tvp )) {
case -1: /* failure - try again */
Debug( LDAP_DEBUG_CONNS,
"select failed errno %d (%s)\n",
errno, errno > -1 && errno < sys_nerr ?
sys_errlist[errno] : "unknown", 0 );
if( errno != EINTR ) {
Debug( LDAP_DEBUG_CONNS,
"daemon: select failed (%d): %s\n",
errno,
errno >= 0 && errno < sys_nerr
? sys_errlist[errno] : "unknown",
0 );
slapd_shutdown = -1;
}
errno = 0;
continue;
case 0: /* timeout - let threads run */
Debug( LDAP_DEBUG_CONNS, "select timeout - yielding\n",
Debug( LDAP_DEBUG_CONNS, "daemon: select timeout - yielding\n",
0, 0, 0 );
if (!data_ready)
ldap_pvt_thread_yield();
ldap_pvt_thread_yield();
continue;
default: /* something happened - deal with it */
Debug( LDAP_DEBUG_CONNS, "select activity on %d descriptors\n", i, 0, 0 );
; /* FALL */
Debug( LDAP_DEBUG_CONNS, "daemon: activity on %d descriptors\n",
ns, 0, 0 );
/* FALL THRU */
}
ldap_pvt_thread_mutex_lock( &currenttime_mutex );
time( &currenttime );
ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
/* new connection */
ldap_pvt_thread_mutex_lock( &new_conn_mutex );
slap_set_time();
if ( FD_ISSET( tcps, &readfds ) ) {
len = sizeof(from);
if ( (ns = accept( tcps, (struct sockaddr *) &from,
&len )) == -1 ) {
int s;
int len = sizeof(from);
long id;
if ( (s = accept( tcps,
(struct sockaddr *) &from, &len )) == -1 )
{
Debug( LDAP_DEBUG_ANY,
"accept() failed errno %d (%s)", errno,
errno > -1 && errno < sys_nerr ?
sys_errlist[errno] : "unknown", 0 );
ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
"daemon: accept(%d) failed errno %d (%s)", errno,
tcps, errno >= 0 && errno < sys_nerr ?
sys_errlist[errno] : "unknown");
continue;
}
assert( !FD_ISSET( 0, &slap_daemon.sd_actives) );
assert( !FD_ISSET( 0, &slap_daemon.sd_readers) );
assert( !FD_ISSET( 0, &slap_daemon.sd_writers) );
#ifndef HAVE_WINSOCK
/* make sure descriptor number isn't too great */
if ( ns >= dtblsize ) {
if ( s >= dtblsize ) {
Debug( LDAP_DEBUG_ANY,
"new connection on %d beyond descriptor table size %d\n",
ns, dtblsize, 0 );
close(ns);
ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
"daemon: %d beyond descriptor table size %d\n",
s, dtblsize, 0 );
close(s);
continue;
}
#endif
Debug( LDAP_DEBUG_CONNS, "new connection on %d\n", ns,
0, 0 );
Debug( LDAP_DEBUG_CONNS, "daemon: new connection on %d\n",
s, 0, 0 );
len = sizeof(from);
if ( getpeername( ns, (struct sockaddr *) &from, &len )
== 0 ) {
char *s;
if ( getpeername( s, (struct sockaddr *) &from, &len ) == 0 ) {
client_addr = inet_ntoa( from.sin_addr );
#if defined(SLAPD_RLOOKUPS) || defined(HAVE_TCPD)
@ -249,11 +351,12 @@ slapd_daemon(
sizeof(from.sin_addr.s_addr), AF_INET );
if(hp) {
char *p;
client_name = hp->h_name;
/* normalize the domain */
for ( s = client_name; *s; s++ ) {
*s = TOLOWER( (unsigned char) *s );
for ( p = client_name; *p; p++ ) {
*p = TOLOWER( (unsigned char) *p );
}
} else {
@ -277,72 +380,42 @@ slapd_daemon(
/* DENY ACCESS */
Statslog( LDAP_DEBUG_ANY,
"fd=%d connection from %s (%s) denied.\n",
ns,
client_name == NULL ? "unknown" : client_name,
client_addr == NULL ? "unknown" : client_addr,
s,
client_name == NULL ? "unknown" : client_name,
client_addr == NULL ? "unknown" : client_addr,
0, 0 );
ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
close(s);
continue;
}
#endif /* HAVE_TCPD */
ldap_pvt_thread_mutex_lock( &ops_mutex );
c[ns].c_connid = num_conns++;
ldap_pvt_thread_mutex_unlock( &ops_mutex );
if( (id = connection_init(s, client_name, client_addr)) < 0 ) {
Debug( LDAP_DEBUG_ANY,
"daemon: connection_init(%d, %s, %s) failed.\n",
s,
client_name == NULL ? "unknown" : client_name,
client_addr == NULL ? "unknown" : client_addr);
close(s);
continue;
}
Statslog( LDAP_DEBUG_STATS,
"conn=%d fd=%d connection from %s (%s) accepted.\n",
c[ns].c_connid, ns,
client_name == NULL ? "unknown" : client_name,
client_addr == NULL ? "unknown" : client_addr,
0 );
"daemon: conn=%d fd=%d connection from %s (%s) accepted.\n",
id, s,
client_name == NULL ? "unknown" : client_name,
client_addr == NULL ? "unknown" : client_addr,
0 );
if ( c[ns].c_addr != NULL ) {
free( c[ns].c_addr );
}
c[ns].c_addr = ch_strdup( client_addr );
if ( c[ns].c_domain != NULL ) {
free( c[ns].c_domain );
}
c[ns].c_domain = ch_strdup( client_name == NULL
? "" : client_name );
ldap_pvt_thread_mutex_lock( &c[ns].c_dnmutex );
if ( c[ns].c_dn != NULL ) {
free( c[ns].c_dn );
c[ns].c_dn = NULL;
}
if ( c[ns].c_cdn != NULL ) {
free( c[ns].c_cdn );
c[ns].c_cdn = NULL;
}
ldap_pvt_thread_mutex_unlock( &c[ns].c_dnmutex );
c[ns].c_starttime = currenttime;
c[ns].c_ops_received = 0;
c[ns].c_ops_executing = 0;
c[ns].c_ops_pending = 0;
c[ns].c_ops_completed = 0;
lber_pvt_sb_set_desc( &c[ns].c_sb, ns );
lber_pvt_sb_set_io( &c[ns].c_sb, &lber_pvt_sb_io_tcp, NULL );
if (lber_pvt_sb_set_nonblock( &c[ns].c_sb, 1)<0) {
Debug( LDAP_DEBUG_ANY,
"FIONBIO ioctl on %d failed\n", ns, 0, 0 );
}
c[ns].c_state = SLAP_C_ACTIVE;
slapd_add( s );
continue;
}
ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
Debug( LDAP_DEBUG_CONNS, "activity on:", 0, 0, 0 );
for ( i = 0; i < dtblsize; i++ ) {
int r, w;
#ifdef LDAP_DEBUG
Debug( LDAP_DEBUG_CONNS, "daemon: activity on:", 0, 0, 0 );
for ( i = 0; i < nfds; i++ ) {
int a, r, w;
r = FD_ISSET( i, &readfds );
w = FD_ISSET( i, &writefds );
@ -351,42 +424,70 @@ slapd_daemon(
r ? "r" : "", w ? "w" : "" );
}
}
Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
for ( i = 0; i < dtblsize; i++ ) {
if ( i == tcps || (! FD_ISSET( i, &readfds ) &&
! FD_ISSET( i, &writefds )) ) {
Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
#endif
/* loop through the writers */
for ( i = 0; i < nfds; i++ ) {
if ( i == tcps ) {
continue;
}
if ( FD_ISSET( i, &writefds ) ) {
Debug( LDAP_DEBUG_CONNS,
"signaling write waiter on %d\n", i, 0, 0 );
"daemon: signaling write waiter on %d\n", i, 0, 0 );
ldap_pvt_thread_mutex_lock( &active_threads_mutex );
active_threads++;
c[i].c_writewaiter = 0;
ldap_pvt_thread_cond_signal( &c[i].c_wcv );
ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
assert( FD_ISSET( 0, &slap_daemon.sd_actives) );
/* clear the write flag */
slapd_clr_write( i, 0 );
if( connection_write( i ) < 0 ) {
FD_CLR( i, &readfds );
slapd_close( i );
}
}
}
for ( i = 0; i < nfds; i++ ) {
if ( i == tcps ) {
continue;
}
if ( FD_ISSET( i, &readfds ) ||
lber_pvt_sb_data_ready( &c[i].c_sb ) ) {
if ( FD_ISSET( i, &readfds ) ) {
Debug( LDAP_DEBUG_CONNS,
"read activity on %d\n", i, 0, 0 );
"daemon: read activity on %d\n", i, 0, 0 );
connection_activity( &c[i] );
assert( FD_ISSET( i, &slap_daemon.sd_actives) );
if( connection_read( i ) < 0) {
slapd_close( i );
}
}
}
ldap_pvt_thread_yield();
}
Debug( LDAP_DEBUG_TRACE,
"slapd shutdown: shutdown initiated.\n",
0, 0, 0 );
if( slapd_shutdown > 0 ) {
Debug( LDAP_DEBUG_TRACE,
"daemon: shutdown requested and initiated.\n",
0, 0, 0 );
close( tcps );
} else if ( slapd_shutdown < 0 ) {
Debug( LDAP_DEBUG_TRACE,
"daemon: abnormal condition, shutdown initiated.\n",
0, 0, 0 );
} else {
Debug( LDAP_DEBUG_TRACE,
"daemon: no active streams, shutdown initiated.\n",
0, 0, 0 );
}
if( tcps >= 0 ) {
close( tcps );
}
ldap_pvt_thread_mutex_lock( &active_threads_mutex );
Debug( LDAP_DEBUG_ANY,
@ -400,10 +501,28 @@ slapd_daemon(
return NULL;
}
int slapd_daemon( struct sockaddr_in *addr )
{
int status;
status = ldap_pvt_thread_create( &listener_tid, 0,
slapd_daemon_task, addr );
if ( status != 0 ) {
Debug( LDAP_DEBUG_ANY,
"listener ldap_pvt_thread_create failed (%d)\n", status, 0, 0 );
return -1;
} else {
/* wait for the listener thread to complete */
ldap_pvt_thread_join( listener_tid, (void *) NULL );
}
return 0;
}
void
slap_set_shutdown( int sig )
{
Debug( LDAP_DEBUG_ANY, "slapd got shutdown signal %d\n", sig, 0, 0 );
slapd_shutdown = 1;
ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
@ -414,8 +533,6 @@ slap_set_shutdown( int sig )
void
slap_do_nothing( int sig )
{
Debug( LDAP_DEBUG_TRACE, "slapd got do_nothing signal %d\n", sig, 0, 0 );
/* reinstall self */
(void) SIGNAL( sig, slap_do_nothing );
}

View file

@ -8,7 +8,6 @@
#include <ac/string.h>
#include <ac/time.h>
#include "portable.h"
#include "slap.h"
/*
@ -25,8 +24,6 @@ int ldap_syslog;
int ldap_syslog_level = LOG_DEBUG;
char *default_referral;
time_t starttime;
ldap_pvt_thread_t listener_tid;
int g_argc;
char **g_argv;
@ -37,11 +34,7 @@ int active_threads;
ldap_pvt_thread_mutex_t active_threads_mutex;
ldap_pvt_thread_cond_t active_threads_cond;
time_t currenttime;
ldap_pvt_thread_mutex_t currenttime_mutex;
ldap_pvt_thread_mutex_t new_conn_mutex;
ldap_pvt_thread_mutex_t gmtime_mutex;
#ifdef SLAPD_CRYPT
ldap_pvt_thread_mutex_t crypt_mutex;
#endif
@ -64,6 +57,9 @@ ldap_pvt_thread_mutex_t replog_mutex;
static char* slap_name;
int slapMode = SLAP_UNDEFINED_MODE;
static time_t currenttime;
static ldap_pvt_thread_mutex_t currenttime_mutex;
int
slap_init( int mode, char *name )
{
@ -98,12 +94,13 @@ slap_init( int mode, char *name )
ldap_pvt_thread_mutex_init( &active_threads_mutex );
ldap_pvt_thread_cond_init( &active_threads_cond );
ldap_pvt_thread_mutex_init( &new_conn_mutex );
ldap_pvt_thread_mutex_init( &currenttime_mutex );
ldap_pvt_thread_mutex_init( &entry2str_mutex );
ldap_pvt_thread_mutex_init( &replog_mutex );
ldap_pvt_thread_mutex_init( &ops_mutex );
ldap_pvt_thread_mutex_init( &num_sent_mutex );
ldap_pvt_thread_mutex_init( &gmtime_mutex );
#ifdef SLAPD_CRYPT
ldap_pvt_thread_mutex_init( &crypt_mutex );
#endif
@ -162,3 +159,20 @@ int slap_destroy(void)
return rc;
}
/* should create a utils.c for these */
void slap_set_time(void)
{
ldap_pvt_thread_mutex_lock( &currenttime_mutex );
time( &currenttime );
ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
}
time_t slap_get_time(void)
{
time_t t;
ldap_pvt_thread_mutex_lock( &currenttime_mutex );
t = currenttime;
ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
return t;
}

View file

@ -56,13 +56,15 @@ usage( char *name )
fprintf( stderr, "\n" );
}
time_t starttime;
int
main( int argc, char **argv )
{
int i;
int inetd = 0;
int rc = 0;
struct sockaddr_in bind_addr;
int status, rc;
struct sockaddr_in bind_addr, *slapd_addr;
int udp;
#ifdef LOG_LOCAL4
int syslogUser = DEFAULT_SYSLOG_USER;
@ -207,131 +209,62 @@ main( int argc, char **argv )
goto destroy;
}
if ( slap_startup(-1) != 0 ) {
rc = 1;
goto shutdown;
}
if ( ! inetd ) {
int status;
(void) SIGNAL( LDAP_SIGUSR1, slap_do_nothing );
(void) SIGNAL( LDAP_SIGUSR2, slap_set_shutdown );
(void) SIGNAL( LDAP_SIGUSR1, slap_do_nothing );
(void) SIGNAL( LDAP_SIGUSR2, slap_set_shutdown );
#ifdef SIGPIPE
(void) SIGNAL( SIGPIPE, SIG_IGN );
(void) SIGNAL( SIGPIPE, SIG_IGN );
#endif
#ifdef SIGHUP
(void) SIGNAL( SIGHUP, slap_set_shutdown );
(void) SIGNAL( SIGHUP, slap_set_shutdown );
#endif
(void) SIGNAL( SIGINT, slap_set_shutdown );
(void) SIGNAL( SIGTERM, slap_set_shutdown );
(void) SIGNAL( SIGINT, slap_set_shutdown );
(void) SIGNAL( SIGTERM, slap_set_shutdown );
if(!inetd) {
#ifdef LDAP_DEBUG
lutil_detach( ldap_debug, 0 );
#else
lutil_detach( 0, 0 );
#endif
}
time( &starttime );
if ( slap_startup(-1) != 0 ) {
rc = 1;
goto shutdown;
}
status = ldap_pvt_thread_create( &listener_tid, 0,
slapd_daemon, &bind_addr );
if ( status != 0 )
if(!inetd) {
FILE *fp;
slapd_addr = &bind_addr;
Debug( LDAP_DEBUG_ANY, "slapd starting\n", 0, 0, 0 );
if (( slapd_pid_file != NULL ) &&
(( fp = fopen( slapd_pid_file, "w" )) != NULL ))
{
Debug( LDAP_DEBUG_ANY,
"listener ldap_pvt_thread_create failed (%d)\n", status, 0, 0 );
fprintf( fp, "%d\n", (int) getpid() );
fclose( fp );
}
rc = 1;
} else {
/* wait for the listener thread to complete */
ldap_pvt_thread_join( listener_tid, (void *) NULL );
if (( slapd_args_file != NULL ) &&
(( fp = fopen( slapd_args_file, "w" )) != NULL ))
{
for ( i = 0; i < g_argc; i++ ) {
fprintf( fp, "%s ", g_argv[i] );
}
fprintf( fp, "\n" );
fclose( fp );
}
} else {
Connection c;
BerElement ber;
unsigned long len, tag;
long msgid;
int flen;
struct sockaddr_in from;
struct hostent *hp;
c.c_dn = NULL;
c.c_cdn = NULL;
c.c_ops = NULL;
lber_pvt_sb_init( &c.c_sb );
lber_pvt_sb_set_desc( &c.c_sb, 0 );
lber_pvt_sb_set_io( &c.c_sb,
(udp) ? &lber_pvt_sb_io_udp : &lber_pvt_sb_io_tcp,
NULL );
/* FIXME: handle udp here */
ldap_pvt_thread_mutex_init( &c.c_dnmutex );
ldap_pvt_thread_mutex_init( &c.c_opsmutex );
ldap_pvt_thread_mutex_init( &c.c_pdumutex );
#ifdef notdefcldap
c.c_sb.sb_addrs = (void **) saddrlist;
c.c_sb.sb_fromaddr = &faddr;
c.c_sb.sb_useaddr = saddrlist[ 0 ] = &saddr;
#endif
flen = sizeof(from);
if ( getpeername( 0, (struct sockaddr *) &from, &flen ) == 0 ) {
#ifdef SLAPD_RLOOKUPS
hp = gethostbyaddr( (char *) &(from.sin_addr.s_addr),
sizeof(from.sin_addr.s_addr), AF_INET );
#else
hp = NULL;
#endif
Debug( LDAP_DEBUG_ARGS, "connection from %s (%s)\n",
hp == NULL ? "unknown" : hp->h_name,
inet_ntoa( from.sin_addr ), 0 );
c.c_addr = inet_ntoa( from.sin_addr );
c.c_domain = ch_strdup( hp == NULL ? "" : hp->h_name );
} else {
Debug( LDAP_DEBUG_ARGS, "connection from unknown\n",
0, 0, 0 );
}
c.c_state = SLAP_C_ACTIVE;
ber_init_w_nullc( &ber, 0 );
while ( (tag = ber_get_next( &c.c_sb, &len, &ber ))
== LDAP_TAG_MESSAGE ) {
ldap_pvt_thread_mutex_lock( &currenttime_mutex );
time( &currenttime );
ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
if ( (tag = ber_get_int( &ber, &msgid ))
!= LDAP_TAG_MSGID ) {
/* log and send error */
Debug( LDAP_DEBUG_ANY,
"ber_get_int returns 0x%lx\n", tag, 0, 0 );
ber_free( &ber, 1 );
return 1;
}
if ( (tag = ber_peek_tag( &ber, &len ))
== LBER_ERROR ) {
/* log, close and send error */
Debug( LDAP_DEBUG_ANY,
"ber_peek_tag returns 0x%lx\n", tag, 0, 0 );
ber_free( &ber, 1 );
lber_pvt_sb_close( &c.c_sb );
lber_pvt_sb_destroy( &c.c_sb );
return 1;
}
connection_activity( &c );
ber_free( &ber, 1 );
}
slapd_addr = NULL;
}
time( &starttime );
rc = slapd_daemon( slapd_addr );
shutdown:
/* remember an error during shutdown */
rc |= slap_shutdown(-1);

View file

@ -206,6 +206,7 @@ add_lastmods( Operation *op, LDAPModList **modlist )
LDAPModList **m;
LDAPModList *tmp;
struct tm *ltm;
time_t currenttime;
Debug( LDAP_DEBUG_TRACE, "add_lastmods\n", 0, 0, 0 );
@ -249,7 +250,8 @@ add_lastmods( Operation *op, LDAPModList **modlist )
tmp->ml_next = *modlist;
*modlist = tmp;
ldap_pvt_thread_mutex_lock( &currenttime_mutex );
currenttime = slap_get_time();
ldap_pvt_thread_mutex_lock( &gmtime_mutex );
#ifndef LDAP_LOCALTIME
ltm = gmtime( &currenttime );
strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
@ -257,7 +259,8 @@ add_lastmods( Operation *op, LDAPModList **modlist )
ltm = localtime( &currenttime );
strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
#endif
ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
bv.bv_val = buf;
bv.bv_len = strlen( bv.bv_val );
tmp = (LDAPModList *) ch_calloc( 1, sizeof(LDAPModList) );

View file

@ -10,13 +10,6 @@
* is provided ``as is'' without express or implied warranty.
*/
/* Revision history
*
* 5-Jun-96 jeff.hodges@stanford.edu
* Added locking of new_conn_mutex when traversing the c[] array.
* Added locking of currenttime_mutex to protect call(s) to localtime().
*/
#include "portable.h"
#include <stdio.h>
@ -40,6 +33,8 @@ monitor_info( Connection *conn, Operation *op )
int i, nconns, nwritewaiters, nreadwaiters;
struct tm *ltm;
char *p;
Connection *c;
time_t currenttime;
vals[0] = &val;
vals[1] = NULL;
@ -59,7 +54,9 @@ monitor_info( Connection *conn, Operation *op )
}
attr_merge( e, "version", vals );
ldap_pvt_thread_mutex_lock( &active_threads_mutex );
sprintf( buf, "%d", active_threads );
ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
val.bv_val = buf;
val.bv_len = strlen( buf );
attr_merge( e, "threads", vals );
@ -68,49 +65,49 @@ monitor_info( Connection *conn, Operation *op )
nwritewaiters = 0;
nreadwaiters = 0;
ldap_pvt_thread_mutex_lock( &new_conn_mutex );
for ( i = 0; i < dtblsize; i++ ) {
if ( lber_pvt_sb_in_use(&(c[i].c_sb)) ) {
nconns++;
if ( c[i].c_writewaiter ) {
nwritewaiters++;
}
if ( c[i].c_gettingber ) {
nreadwaiters++;
}
ldap_pvt_thread_mutex_lock( &currenttime_mutex );
#ifndef LDAP_LOCALTIME
ltm = gmtime( &c[i].c_starttime );
strftime( buf2, sizeof(buf2), "%Y%m%d%H%M%SZ", ltm );
#else
ltm = localtime( &c[i].c_starttime );
strftime( buf2, sizeof(buf2), "%y%m%d%H%M%SZ", ltm );
#endif
ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
ldap_pvt_thread_mutex_lock( &c[i].c_dnmutex );
sprintf( buf, "%d : %s : %d : %d : %s : %s%s%s%s", i,
buf2, c[i].c_ops_received, c[i].c_ops_completed,
c[i].c_cdn ? c[i].c_cdn : "NULLDN",
c[i].c_gettingber ? "r" : "",
c[i].c_writewaiter ? "w" : "",
c[i].c_ops_executing ? "x" : "",
c[i].c_ops_pending ? "p" : ""
);
ldap_pvt_thread_mutex_unlock( &c[i].c_dnmutex );
val.bv_val = buf;
val.bv_len = strlen( buf );
attr_merge( e, "connection", vals );
#ifdef LDAP_COUNTERS
/* loop through the connections */
for ( c = connection_first() ; c != NULL; c = connection_next(c) ) {
nconns++;
if ( c->c_writewaiter ) {
nwritewaiters++;
}
if ( c->c_currentber != NULL ) {
nreadwaiters++;
}
ldap_pvt_thread_mutex_lock( &gmtime_mutex );
#ifndef LDAP_LOCALTIME
ltm = gmtime( &c->c_starttime );
strftime( buf2, sizeof(buf2), "%Y%m%d%H%M%SZ", ltm );
#else
ltm = localtime( &c->.c_starttime );
strftime( buf2, sizeof(buf2), "%y%m%d%H%M%SZ", ltm );
#endif
ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
sprintf( buf, "%d : %s : %d : %d : %s : %s%s%s%s", i,
buf2, c[i].c_ops_received, c[i].c_ops_completed,
c[i].c_cdn ? c[i].c_cdn : "NULLDN",
c[i].c_gettingber ? "r" : "",
c[i].c_writewaiter ? "w" : "",
c[i].c_ops_executing ? "x" : "",
c[i].c_ops_pending ? "p" : ""
);
val.bv_val = buf;
val.bv_len = strlen( buf );
attr_merge( e, "connection", vals );
}
ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
connection_done(c);
#endif
sprintf( buf, "%d", nconns );
val.bv_val = buf;
val.bv_len = strlen( buf );
attr_merge( e, "currentconnections", vals );
sprintf( buf, "%d", num_conns );
sprintf( buf, "%ld", connections_nextid() );
val.bv_val = buf;
val.bv_len = strlen( buf );
attr_merge( e, "totalconnections", vals );
@ -130,6 +127,7 @@ monitor_info( Connection *conn, Operation *op )
val.bv_len = strlen( buf );
attr_merge( e, "readwaiters", vals );
#ifdef LDAP_COUNTERS
sprintf( buf, "%ld", ops_initiated );
val.bv_val = buf;
val.bv_len = strlen( buf );
@ -149,8 +147,12 @@ monitor_info( Connection *conn, Operation *op )
val.bv_val = buf;
val.bv_len = strlen( buf );
attr_merge( e, "bytessent", vals );
#endif
ldap_pvt_thread_mutex_lock( &currenttime_mutex );
slap_set_time();
currenttime = slap_get_time();
ldap_pvt_thread_mutex_lock( &gmtime_mutex );
#ifndef LDAP_LOCALTIME
ltm = gmtime( &currenttime );
strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
@ -158,12 +160,10 @@ monitor_info( Connection *conn, Operation *op )
ltm = localtime( &currenttime );
strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
#endif
ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
val.bv_val = buf;
val.bv_len = strlen( buf );
attr_merge( e, "currenttime", vals );
ldap_pvt_thread_mutex_lock( &currenttime_mutex );
#ifndef LDAP_LOCALTIME
ltm = gmtime( &starttime );
strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
@ -171,7 +171,8 @@ monitor_info( Connection *conn, Operation *op )
ltm = localtime( &starttime );
strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
#endif
ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
val.bv_val = buf;
val.bv_len = strlen( buf );
attr_merge( e, "starttime", vals );

View file

@ -15,8 +15,6 @@ slap_op_free( Operation *op )
{
assert( op->o_next == NULL );
ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
if ( op->o_ber != NULL ) {
ber_free( op->o_ber, 1 );
}
@ -27,8 +25,8 @@ slap_op_free( Operation *op )
free( op->o_ndn );
}
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
ldap_pvt_thread_mutex_destroy( &op->o_abandonmutex );
free( (char *) op );
}
@ -37,8 +35,7 @@ slap_op_alloc(
BerElement *ber,
unsigned long msgid,
unsigned long tag,
int id,
int connid
long id
)
{
Operation *op;
@ -46,19 +43,17 @@ slap_op_alloc(
op = (Operation *) ch_calloc( 1, sizeof(Operation) );
ldap_pvt_thread_mutex_init( &op->o_abandonmutex );
op->o_abandon = 0;
op->o_ber = ber;
op->o_msgid = msgid;
op->o_tag = tag;
op->o_abandon = 0;
op->o_dn = NULL;
op->o_ndn = NULL;
ldap_pvt_thread_mutex_lock( &currenttime_mutex );
op->o_time = currenttime;
ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
op->o_time = slap_get_time();
op->o_opid = id;
op->o_connid = connid;
op->o_next = NULL;
return( op );

View file

@ -109,8 +109,20 @@ int read_config LDAP_P(( char *fname ));
/*
* connection.c
*/
int connections_init LDAP_P((void));
void connection_activity LDAP_P(( Connection *conn ));
long connection_init LDAP_P((
int s,
const char* name, const char* addr));
int connection_write LDAP_P((int s));
int connection_read LDAP_P((int s));
long connections_nextid(void);
Connection* connection_first LDAP_P((void));
Connection* connection_next LDAP_P((Connection *));
void connection_done LDAP_P((Connection *));
/*
* dn.c
@ -173,7 +185,7 @@ void monitor_info LDAP_P(( Connection *conn, Operation *op ));
void slap_op_free LDAP_P(( Operation *op ));
Operation * slap_op_alloc LDAP_P((
BerElement *ber, unsigned long msgid,
unsigned long tag, int id, int connid ));
unsigned long tag, long id ));
int slap_op_add LDAP_P(( Operation **olist, Operation *op ));
int slap_op_remove LDAP_P(( Operation **olist, Operation *op ));
@ -202,7 +214,8 @@ void send_ldap_result LDAP_P(( Connection *conn, Operation *op, int err, char *m
char *text ));
void send_ldap_search_result LDAP_P(( Connection *conn, Operation *op, int err,
char *matched, char *text, int nentries ));
void close_connection LDAP_P(( Connection *conn, int opconnid, int opid ));
void do_close( Connection *conn, long opid );
/*
* schema.c
@ -244,7 +257,6 @@ char *suffixAlias LDAP_P(( char *dn, Operation *op, Backend *be ));
* Other...
*/
extern char **g_argv;
extern char *default_referral;
extern char *replogfile;
extern char Versionstr[];
@ -257,35 +269,48 @@ extern int global_lastmod;
extern int global_schemacheck;
extern int lber_debug;
extern int ldap_syslog;
extern int num_conns;
#ifdef LDAP_COUNTERS
extern ldap_pvt_thread_mutex_t num_sent_mutex;
extern long num_bytes_sent;
extern long num_entries_sent;
extern ldap_pvt_thread_mutex_t ops_mutex;
extern long ops_completed;
extern long ops_initiated;
#endif
extern char *slapd_pid_file;
extern char *slapd_args_file;
extern char **g_argv;
extern time_t starttime;
time_t slap_get_time LDAP_P((void));
void slap_set_time LDAP_P((void));
extern ldap_pvt_thread_mutex_t active_threads_mutex;
extern ldap_pvt_thread_cond_t active_threads_cond;
extern ldap_pvt_thread_mutex_t currenttime_mutex;
extern ldap_pvt_thread_mutex_t entry2str_mutex;
extern ldap_pvt_thread_mutex_t new_conn_mutex;
extern ldap_pvt_thread_mutex_t num_sent_mutex;
extern ldap_pvt_thread_mutex_t ops_mutex;
extern ldap_pvt_thread_mutex_t replog_mutex;
#ifdef SLAPD_CRYPT
extern ldap_pvt_thread_mutex_t crypt_mutex;
#endif
extern ldap_pvt_thread_t listener_tid;
extern ldap_pvt_thread_mutex_t gmtime_mutex;
extern struct acl *global_acl;
extern struct objclass *global_oc;
extern time_t currenttime;
extern int slap_init LDAP_P((int mode, char* name));
extern int slap_startup LDAP_P((int dbnum));
extern int slap_shutdown LDAP_P((int dbnum));
extern int slap_destroy LDAP_P((void));
extern void * slapd_daemon LDAP_P((void *port));
struct sockaddr_in;
extern int slapd_daemon LDAP_P((struct sockaddr_in *addr));
extern void slap_set_shutdown LDAP_P((int sig));
extern void slap_do_nothing LDAP_P((int sig));
@ -303,11 +328,7 @@ extern void do_unbind LDAP_P((Connection *conn, Operation *op));
extern int send_search_entry LDAP_P((Backend *be, Connection *conn, Operation *op, Entry *e, char **attrs, int attrsonly));
extern int str2result LDAP_P(( char *s, int *code, char **matched, char **info ));
#if defined( SLAPD_MONITOR_DN )
extern Connection *c;
extern int dtblsize;
extern time_t starttime;
#endif
extern int dtblsize;
#endif /* _proto_slap */

View file

@ -46,7 +46,7 @@ replog(
i++ ) {
fprintf( fp, "replica: %s\n", be->be_replica[i] );
}
fprintf( fp, "time: %ld\n", (long) currenttime );
fprintf( fp, "time: %ld\n", (long) slap_get_time() );
fprintf( fp, "dn: %s\n", dn );
switch ( optype ) {

View file

@ -13,7 +13,6 @@
#include "slap.h"
static void
send_ldap_result2(
Connection *conn,
@ -25,7 +24,7 @@ send_ldap_result2(
)
{
BerElement *ber;
int rc;
int rc, tmp;
unsigned long tag, bytes;
if ( err == LDAP_PARTIAL_RESULTS && (text == NULL || *text == '\0') )
@ -52,12 +51,14 @@ send_ldap_result2(
break;
}
#ifdef LDAP_COMPAT30
if ( (ber = ber_alloc_t( conn->c_version == 30 ? 0 : LBER_USE_DER ))
== NULLBER ) {
== NULLBER )
#else
if ( (ber = der_alloc()) == NULLBER ) {
if ( (ber = der_alloc()) == NULLBER )
#endif
{
Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
return;
}
@ -83,14 +84,15 @@ send_ldap_result2(
}
/* write only one pdu at a time - wait til it's our turn */
ldap_pvt_thread_mutex_lock( &conn->c_pdumutex );
ldap_pvt_thread_mutex_lock( &conn->c_write_mutex );
/* lock the connection */
ldap_pvt_thread_mutex_lock( &conn->c_mutex );
/* write the pdu */
bytes = ber->ber_ptr - ber->ber_buf;
ldap_pvt_thread_mutex_lock( &new_conn_mutex );
while ( conn->c_connid == op->o_connid && ber_flush( &conn->c_sb, ber,
1 ) != 0 ) {
ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
while ( ber_flush( &conn->c_sb, ber, 1 ) != 0 ) {
/*
* we got an error. if it's ewouldblock, we need to
* wait on the socket being writable. otherwise, figure
@ -102,35 +104,29 @@ send_ldap_result2(
: "unknown", 0 );
if ( errno != EWOULDBLOCK && errno != EAGAIN ) {
close_connection( conn, op->o_connid, op->o_opid );
conn->c_conn_state = SLAP_C_CLOSING;
ldap_pvt_thread_mutex_unlock( &conn->c_pdumutex );
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
return;
}
/* wait for socket to be write-ready */
ldap_pvt_thread_mutex_lock( &active_threads_mutex );
active_threads--;
conn->c_writewaiter = 1;
slapd_set_write( conn->c_sb.sb_sd, 1 );
ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
ldap_pvt_thread_cond_wait( &conn->c_wcv, &active_threads_mutex );
if( active_threads < 1 ) {
ldap_pvt_thread_cond_signal(&active_threads_cond);
}
ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
ldap_pvt_thread_yield();
ldap_pvt_thread_mutex_lock( &new_conn_mutex );
ldap_pvt_thread_cond_wait( &conn->c_write_cv, &conn->c_mutex );
conn->c_writewaiter = 0;
}
ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
ldap_pvt_thread_mutex_unlock( &conn->c_pdumutex );
ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
#ifdef LDAP_COUNTERS
ldap_pvt_thread_mutex_lock( &num_sent_mutex );
num_bytes_sent += bytes;
ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
#endif
Statslog( LDAP_DEBUG_STATS,
"conn=%d op=%d RESULT err=%d tag=%lu nentries=%d\n", conn->c_connid,
@ -186,7 +182,7 @@ send_search_entry(
{
BerElement *ber;
Attribute *a;
int i, rc, bytes;
int i, rc=-1, bytes;
struct acl *acl;
char *edn;
@ -261,7 +257,7 @@ send_search_entry(
continue;
}
if ( ber_printf( ber, "{s[", a->a_type ) == -1 ) {
if (( rc = ber_printf( ber, "{s[", a->a_type )) == -1 ) {
Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
ber_free( ber, 1 );
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
@ -278,9 +274,9 @@ send_search_entry(
continue;
}
if ( ber_printf( ber, "o",
if (( rc = ber_printf( ber, "o",
a->a_vals[i]->bv_val,
a->a_vals[i]->bv_len ) == -1 )
a->a_vals[i]->bv_len )) == -1 )
{
Debug( LDAP_DEBUG_ANY,
"ber_printf failed\n", 0, 0, 0 );
@ -293,7 +289,7 @@ send_search_entry(
}
}
if ( ber_printf( ber, "]}" ) == -1 ) {
if (( rc = ber_printf( ber, "]}" )) == -1 ) {
Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
ber_free( ber, 1 );
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
@ -317,14 +313,16 @@ send_search_entry(
return( 1 );
}
/* write only one pdu at a time - wait til it's our turn */
ldap_pvt_thread_mutex_lock( &conn->c_pdumutex );
bytes = ber->ber_ptr - ber->ber_buf;
ldap_pvt_thread_mutex_lock( &new_conn_mutex );
while ( conn->c_connid == op->o_connid && ber_flush( &conn->c_sb, ber,
1 ) != 0 ) {
ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
/* write only one pdu at a time - wait til it's our turn */
ldap_pvt_thread_mutex_lock( &conn->c_write_mutex );
/* lock the connection */
ldap_pvt_thread_mutex_lock( &conn->c_mutex );
/* write the pdu */
while ( ber_flush( &conn->c_sb, ber, 1 ) != 0 ) {
/*
* we got an error. if it's ewouldblock, we need to
* wait on the socket being writable. otherwise, figure
@ -336,51 +334,40 @@ send_search_entry(
: "unknown", 0 );
if ( errno != EWOULDBLOCK && errno != EAGAIN ) {
close_connection( conn, op->o_connid, op->o_opid );
conn->c_conn_state = SLAP_C_CLOSING;
ldap_pvt_thread_mutex_unlock( &conn->c_pdumutex );
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
return( -1 );
}
/* wait for socket to be write-ready */
ldap_pvt_thread_mutex_lock( &active_threads_mutex );
active_threads--;
conn->c_writewaiter = 1;
ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
ldap_pvt_thread_cond_wait( &conn->c_wcv, &active_threads_mutex );
slapd_set_write( conn->c_sb.sb_sd, 1 );
if( active_threads < 1 ) {
ldap_pvt_thread_cond_signal(&active_threads_cond);
}
ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
ldap_pvt_thread_yield();
ldap_pvt_thread_mutex_lock( &new_conn_mutex );
ldap_pvt_thread_cond_wait( &conn->c_write_cv, &conn->c_mutex );
conn->c_writewaiter = 0;
}
ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
ldap_pvt_thread_mutex_unlock( &conn->c_pdumutex );
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
#ifdef LDAP_COUNTERS
ldap_pvt_thread_mutex_lock( &num_sent_mutex );
num_bytes_sent += bytes;
num_entries_sent++;
ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
#endif
ldap_pvt_thread_mutex_lock( &new_conn_mutex );
if ( conn->c_connid == op->o_connid ) {
rc = 0;
Statslog( LDAP_DEBUG_STATS2, "conn=%d op=%d ENTRY dn=\"%s\"\n",
conn->c_connid, op->o_opid, e->e_dn, 0, 0 );
} else {
rc = -1;
}
ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
Statslog( LDAP_DEBUG_STATS2, "conn=%d op=%d ENTRY dn=\"%s\"\n",
conn->c_connid, op->o_opid, e->e_dn, 0, 0 );
Debug( LDAP_DEBUG_TRACE, "<= send_search_entry\n", 0, 0, 0 );
return( rc );
rc = 0;
error_return:;
return( 1 );
return( rc );
}
int
@ -436,26 +423,3 @@ str2result(
return( rc );
}
/*
* close_connection - close a connection. takes the connection to close,
* the connid associated with the operation generating the close (so we
* don't accidentally close a connection that's not ours), and the opid
* of the operation generating the close (for logging purposes).
*/
void
close_connection( Connection *conn, int opconnid, int opid )
{
ldap_pvt_thread_mutex_lock( &new_conn_mutex );
if ( lber_pvt_sb_in_use(&conn->c_sb) && conn->c_connid == opconnid ) {
Statslog( LDAP_DEBUG_STATS,
"conn=%d op=%d fd=%d closed errno=%d\n", conn->c_connid,
opid, lber_pvt_sb_get_desc(&conn->c_sb), errno, 0 );
lber_pvt_sb_close( &conn->c_sb );
lber_pvt_sb_destroy( &conn->c_sb );
conn->c_version = 0;
conn->c_protocol = 0;
conn->c_state = SLAP_C_INACTIVE;
}
ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
}

View file

@ -380,27 +380,33 @@ struct backend_info {
*/
typedef struct slap_op {
long o_opid; /* id of this operation */
long o_msgid; /* msgid of the request */
ldap_pvt_thread_t o_tid; /* thread handling this op */
BerElement *o_ber; /* ber of the request */
long o_msgid; /* msgid of the request */
unsigned long o_tag; /* tag of the request */
time_t o_time; /* time op was initiated */
char *o_dn; /* dn bound when op was initiated */
char *o_ndn; /* normalized dn bound when op was initiated */
int o_authtype; /* auth method used to bind dn */
int o_authtype; /* auth method used to bind dn */
/* values taken from ldap.h */
/* LDAP_AUTH_* */
int o_opid; /* id of this operation */
int o_connid; /* id of conn initiating this op */
/* long o_connid; *//* id of conn initiating this op */
#ifdef LDAP_CONNECTIONLESS
int o_cldap; /* != 0 if this came in via CLDAP */
struct sockaddr o_clientaddr; /* client address if via CLDAP */
char o_searchbase; /* search base if via CLDAP */
#endif
struct slap_op *o_next; /* next operation in list */
ldap_pvt_thread_t o_tid; /* thread handling this op */
int o_abandon; /* signals op has been abandoned */
ldap_pvt_thread_mutex_t o_abandonmutex; /* signals op has been abandoned */
ldap_pvt_thread_mutex_t o_abandonmutex; /* protects o_abandon */
int o_abandon; /* abandon flag */
struct slap_op *o_next; /* next operation in list */
void *o_private; /* anything the backend needs */
} Operation;
@ -408,41 +414,56 @@ typedef struct slap_op {
* represents a connection from an ldap client
*/
#define SLAP_C_INACTIVE 0x0
#define SLAP_C_ACTIVE 0x1
#define SLAP_C_BINDING 0x2
#define SLAP_C_CLOSING 0x3
/* structure state (protected by connections_mutex) */
#define SLAP_C_UNINITIALIZED 0x0 /* MUST BE ZERO (0) */
#define SLAP_C_UNUSED 0x1
#define SLAP_C_USED 0x2
/* connection state (protected by c_mutex ) */
#define SLAP_C_INVALID 0x0 /* MUST BE ZERO (0) */
#define SLAP_C_INACTIVE 0x1 /* zero threads */
#define SLAP_C_ACTIVE 0x2 /* one or more threads */
#define SLAP_C_BINDING 0x3 /* binding */
#define SLAP_C_CLOSING 0x4 /* closing */
typedef struct slap_conn {
int c_state; /* connection state */
int c_struct_state; /* structure management state */
int c_conn_state; /* connection state */
ldap_pvt_thread_mutex_t c_mutex; /* protect the connection */
Sockbuf c_sb; /* ber connection stuff */
char *c_cdn; /* DN provided by the client */
char *c_dn; /* DN bound to this conn */
ldap_pvt_thread_mutex_t c_dnmutex; /* mutex for c_dn field */
/* only can be changed by connect_init */
time_t c_starttime; /* when the connection was opened */
long c_connid; /* id of this connection for stats*/
char *c_client_addr; /* address of client */
char *c_client_name; /* name of client */
/* only can be changed by binding thread */
char *c_cdn; /* DN provided by the client */
char *c_dn; /* DN bound to this conn */
int c_protocol; /* version of the LDAP protocol used by client */
int c_authtype; /* auth method used to bind c_dn */
#ifdef LDAP_COMPAT
int c_version; /* for compatibility w/2.0, 3.0 */
#endif
char *c_addr; /* address of client on this conn */
char *c_domain; /* domain of client on this conn */
Operation *c_ops; /* list of operations being processed */
Operation *c_pending_ops; /* list of pending operations */
ldap_pvt_thread_mutex_t c_opsmutex; /* mutex for c_ops list & stats */
ldap_pvt_thread_mutex_t c_pdumutex; /* only one pdu written at a time */
ldap_pvt_thread_cond_t c_wcv; /* used to wait for sd write-ready*/
int c_gettingber; /* in the middle of ber_get_next */
BerElement *c_currentber; /* ber we're getting */
int c_writewaiter; /* signals write-ready sd waiter */
int c_pduwaiters; /* signals threads waiting 4 pdu */
time_t c_starttime; /* when the connection was opened */
long c_connid; /* id of this connection for stats*/
ldap_pvt_thread_mutex_t c_write_mutex; /* only one pdu written at a time */
ldap_pvt_thread_cond_t c_write_cv; /* used to wait for sd write-ready*/
long c_ops_received; /* num of ops received (next op_id) */
long c_ops_executing; /* num of ops currently executing */
long c_ops_pending; /* num of ops pending execution */
long c_ops_completed; /* num of ops completed */
BerElement *c_currentber; /* ber we're attempting to read */
int c_writewaiter; /* true if writer is waiting */
long c_n_ops_received; /* num of ops received (next op_id) */
#ifdef LDAP_COUNTERS
long c_n_ops_executing; /* num of ops currently executing */
long c_n_ops_pending; /* num of ops pending execution */
long c_n_ops_completed; /* num of ops completed */
#endif
} Connection;
#if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG)

View file

@ -31,7 +31,8 @@ PROGRAMS2=ldif2index-bdb2 ldif2ldbm-bdb2 \
ldif2id2entry-bdb2 ldif2id2children-bdb2
SRCS = centipede.c ldbmcat.c ldbmtest.c sizecount.c \
ldif.c ldif2id2children.c ldif2id2entry.c ldif2index.c ldif2ldbm.c
ldif.c ldif2id2children.c ldif2id2entry.c ldif2index.c ldif2ldbm.c \
mimic.c
SRCS2 = ldif2id2children-bdb2.c ldif2id2entry-bdb2.c \
ldif2index-bdb2.c ldif2ldbm-bdb2.c
@ -41,8 +42,9 @@ XSRCS = edb2-vers.c
EDB2LDIFSRCS = edb2ldif.c ldapsyntax.c
EDB2LDIFOBJS = edb2ldif.o ldapsyntax.o
OBJS2 = ../config.o ../ch_malloc.o ../backend.o ../charray.o \
../aclparse.o ../schema.o ../result.o ../filterentry.o \
OBJS2 = mimic.o \
../config.o ../ch_malloc.o ../backend.o ../charray.o \
../aclparse.o ../schema.o ../filterentry.o \
../acl.o ../phonetic.o ../attr.o ../value.o ../entry.o \
../dn.o ../filter.o ../str2filter.o ../ava.o ../init.o \
../schemaparse.o

View file

@ -0,0 +1,48 @@
/*
* Mimic unused interfaces of slapd...
* needed for linking.
*/
#include "portable.h"
#include <stdio.h>
#include "../slap.h"
void
send_ldap_result(
Connection *conn,
Operation *op,
int err,
char *matched,
char *text
)
{
assert(0);
}
void
send_ldap_search_result(
Connection *conn,
Operation *op,
int err,
char *matched,
char *text,
int nentries
)
{
assert(0);
}
int
send_search_entry(
Backend *be,
Connection *conn,
Operation *op,
Entry *e,
char **attrs,
int attrsonly
)
{
assert(0);
return -1;
}

View file

@ -41,7 +41,4 @@ do_unbind(
/* pass the unbind to all backends */
backend_unbind( conn, op );
/* close the connection to the client */
close_connection( conn, op->o_connid, op->o_opid );
}