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.
* 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 );
}
}
}
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 ?
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",
Attribute **a, **next;
Attribute *tmp;
struct tm *ltm;
+ time_t currenttime;
Debug( LDAP_DEBUG_TRACE, "add_created_attrs\n", 0, 0, 0 );
}
attr_merge( e, "creatorsname", bvals );
- ldap_pvt_thread_mutex_lock( ¤ttime_mutex );
+ currenttime = slap_get_time();
+ ldap_pvt_thread_mutex_lock( &gmtime_mutex );
#ifndef LDAP_LOCALTIME
ltm = gmtime( ¤ttime );
strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
ltm = localtime( ¤ttime );
strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
#endif
- ldap_pvt_thread_mutex_unlock( ¤ttime_mutex );
+ ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
bv.bv_val = buf;
bv.bv_len = strlen( bv.bv_val );
flags, li->li_mode );
lru = 0;
- ldap_pvt_thread_mutex_lock( ¤ttime_mutex );
- curtime = currenttime;
- ldap_pvt_thread_mutex_unlock( ¤ttime_mutex );
+ curtime = slap_get_time();
oldtime = curtime;
ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex );
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 ) {
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
/* check time limit */
- ldap_pvt_thread_mutex_lock( ¤ttime_mutex );
- time( ¤ttime );
- if ( tlimit != -1 && currenttime > stoptime ) {
- ldap_pvt_thread_mutex_unlock( ¤ttime_mutex );
+ if ( tlimit != -1 && slap_get_time() > stoptime ) {
send_ldap_search_result( conn, op,
LDAP_TIMELIMIT_EXCEEDED, NULL, nrefs > 0 ? rbuf :
NULL, nentries );
}
return( 0 );
}
- ldap_pvt_thread_mutex_unlock( ¤ttime_mutex );
/* get the entry with reader lock */
if ( (e = id2entry_r( be, id )) == NULL ) {
free( cred.bv_val );
}
- ldap_pvt_thread_mutex_lock( &conn->c_dnmutex );
+ ldap_pvt_thread_mutex_lock( &conn->c_mutex );
conn->c_protocol = version;
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;
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;
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 );
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;
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 );
#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 );
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
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:
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_mutex );
- ldap_pvt_thread_mutex_lock( &conn->c_opsmutex );
+#ifdef LDAP_COUNTERS
conn->c_ops_completed++;
+#endif
slap_op_remove( &conn->c_ops, arg->co_op );
slap_op_free( arg->co_op );
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--;
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
)
{
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;
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 ) {
0 );
ber_free( ber, 1 );
- close_connection( conn, conn->c_connid, -1 );
- return;
+ return -1;
}
#ifdef LDAP_COMPAT30
}
#endif
- op = slap_op_alloc( ber, msgid, tag,
- conn->c_ops_received, conn->c_connid );
-
- if ( conn->c_state == SLAP_C_BINDING ) {
- /* connection is binding to a dn, make 'em wait */
- ldap_pvt_thread_mutex_lock( &conn->c_opsmutex );
- slap_op_add( &conn->c_pending_ops, op );
+ op = slap_op_alloc( ber, msgid, tag, conn->c_n_ops_received++ );
+ 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 );
- ldap_pvt_thread_mutex_unlock( &conn->c_opsmutex );
+ } else {
+ connection_op_activate( conn, op );
+ }
- return;
+#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 );
- connection_op_activate( conn, op );
+ return 0;
}
static int
{
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 )
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;
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 );
}
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;
+}
-
-/* Revision history
- *
- * 5-Jun-96 hodges
- * Added locking of new_conn_mutex when traversing the c[] array.
- */
-
#include "portable.h"
#include <stdio.h>
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;
+
+ 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 );
-void *
-slapd_daemon(
+ 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 );
}
#endif /* !FD_SETSIZE */
- c = (Connection *) ch_calloc( (size_t) dtblsize, sizeof(Connection) );
-
- 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 );
- }
+ connections_init();
- 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 );
- }
+ ldap_pvt_thread_mutex_init( &slap_daemon.sd_mutex );
+ FD_ZERO( &slap_daemon.sd_readers );
+ FD_ZERO( &slap_daemon.sd_writers );
- 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( addr != NULL ) {
+ int tmp;
- 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 ( (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 );
+ }
- 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 );
- }
+#ifndef HAVE_WINSOCK
+ if ( tcps >= dtblsize ) {
+ Debug( LDAP_DEBUG_ANY,
+ "daemon: listener descriptor %d is too great",
+ tcps, dtblsize, 0 );
+ exit( 1 );
+ }
+#endif
- Debug( LDAP_DEBUG_ANY, "slapd starting\n", 0, 0, 0 );
+ 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 (( slapd_pid_file != NULL ) &&
- (( fp = fopen( slapd_pid_file, "w" )) != NULL )) {
- fprintf( fp, "%d\n", (int) getpid() );
- fclose( fp );
- }
+ 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 );
- 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] );
+ } else {
+ if( connection_init( 0, NULL, NULL ) ) {
+ Debug( LDAP_DEBUG_ANY,
+ "connection_init(%d) failed.\n",
+ 0, 0, 0 );
+
+ exit( 1 );
}
- fprintf( fp, "\n" );
- fclose( fp );
+
+ 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 );
}
}
+#else
+ memcpy( &readfds, &slap_daemon.sd_readers, sizeof(fd_set) );
+ memcpy( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) );
+#endif
- Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
- ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
+ 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 );
- Debug( LDAP_DEBUG_CONNS, "before select active_threads %d\n",
- active_threads, 0, 0 );
+ ldap_pvt_thread_mutex_lock( &active_threads_mutex );
#if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS )
- tvp = (data_ready) ? &zero : NULL;
+ tvp = NULL;
#else
- tvp = (active_threads || data_ready) ? &zero : NULL;
+ 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( ¤ttime_mutex );
- time( ¤ttime );
- ldap_pvt_thread_mutex_unlock( ¤ttime_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)
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 {
/* 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 );
-
- Statslog( LDAP_DEBUG_STATS,
- "conn=%d fd=%d connection from %s (%s) accepted.\n",
- c[ns].c_connid, ns,
+ 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,
- 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;
+ client_addr == NULL ? "unknown" : client_addr);
+ close(s);
+ continue;
}
- 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 );
- }
+ Statslog( LDAP_DEBUG_STATS,
+ "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 );
- 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 );
r ? "r" : "", w ? "w" : "" );
}
}
+
Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
+#endif
- for ( i = 0; i < dtblsize; i++ ) {
- if ( i == tcps || (! FD_ISSET( i, &readfds ) &&
- ! FD_ISSET( i, &writefds )) ) {
+ /* 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 );
+
+ assert( FD_ISSET( 0, &slap_daemon.sd_actives) );
- 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 );
+ /* 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 );
+
+ assert( FD_ISSET( i, &slap_daemon.sd_actives) );
- connection_activity( &c[i] );
+ 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 );
+
+ } 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 );
+ }
- close( tcps );
+ if( tcps >= 0 ) {
+ close( tcps );
+ }
ldap_pvt_thread_mutex_lock( &active_threads_mutex );
Debug( LDAP_DEBUG_ANY,
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 );
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 );
}
#include <ac/string.h>
#include <ac/time.h>
-#include "portable.h"
#include "slap.h"
/*
int ldap_syslog_level = LOG_DEBUG;
char *default_referral;
-time_t starttime;
-ldap_pvt_thread_t listener_tid;
int g_argc;
char **g_argv;
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
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 )
{
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( ¤ttime_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
return rc;
}
+/* should create a utils.c for these */
+
+void slap_set_time(void)
+{
+ ldap_pvt_thread_mutex_lock( ¤ttime_mutex );
+ time( ¤ttime );
+ ldap_pvt_thread_mutex_unlock( ¤ttime_mutex );
+}
+
+time_t slap_get_time(void)
+{
+ time_t t;
+ ldap_pvt_thread_mutex_lock( ¤ttime_mutex );
+ t = currenttime;
+ ldap_pvt_thread_mutex_unlock( ¤ttime_mutex );
+ return t;
+}
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;
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 )
- {
- Debug( LDAP_DEBUG_ANY,
- "listener ldap_pvt_thread_create failed (%d)\n", status, 0, 0 );
+ if(!inetd) {
+ FILE *fp;
- rc = 1;
+ slapd_addr = &bind_addr;
- } else {
- /* wait for the listener thread to complete */
- ldap_pvt_thread_join( listener_tid, (void *) NULL );
- }
+ Debug( LDAP_DEBUG_ANY, "slapd starting\n", 0, 0, 0 );
- } 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 );
+ if (( slapd_pid_file != NULL ) &&
+ (( fp = fopen( slapd_pid_file, "w" )) != NULL ))
+ {
+ fprintf( fp, "%d\n", (int) getpid() );
+ fclose( fp );
}
- 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( ¤ttime_mutex );
- time( ¤ttime );
- ldap_pvt_thread_mutex_unlock( ¤ttime_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 (( 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 );
+ }
- 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;
- }
+ } else {
+ slapd_addr = NULL;
+ }
- connection_activity( &c );
+ time( &starttime );
- ber_free( &ber, 1 );
- }
- }
+ rc = slapd_daemon( slapd_addr );
shutdown:
/* remember an error during shutdown */
LDAPModList **m;
LDAPModList *tmp;
struct tm *ltm;
+ time_t currenttime;
Debug( LDAP_DEBUG_TRACE, "add_lastmods\n", 0, 0, 0 );
tmp->ml_next = *modlist;
*modlist = tmp;
- ldap_pvt_thread_mutex_lock( ¤ttime_mutex );
+ currenttime = slap_get_time();
+ ldap_pvt_thread_mutex_lock( &gmtime_mutex );
#ifndef LDAP_LOCALTIME
ltm = gmtime( ¤ttime );
strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
ltm = localtime( ¤ttime );
strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
#endif
- ldap_pvt_thread_mutex_unlock( ¤ttime_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) );
* 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>
int i, nconns, nwritewaiters, nreadwaiters;
struct tm *ltm;
char *p;
+ Connection *c;
+ time_t currenttime;
vals[0] = &val;
vals[1] = NULL;
}
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 );
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( ¤ttime_mutex );
+#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[i].c_starttime );
- strftime( buf2, sizeof(buf2), "%Y%m%d%H%M%SZ", ltm );
+ ltm = gmtime( &c->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 );
+ ltm = localtime( &c->.c_starttime );
+ strftime( buf2, sizeof(buf2), "%y%m%d%H%M%SZ", ltm );
#endif
- ldap_pvt_thread_mutex_unlock( ¤ttime_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 );
- }
+ 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 );
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 );
val.bv_val = buf;
val.bv_len = strlen( buf );
attr_merge( e, "bytessent", vals );
+#endif
- ldap_pvt_thread_mutex_lock( ¤ttime_mutex );
+ slap_set_time();
+ currenttime = slap_get_time();
+
+ ldap_pvt_thread_mutex_lock( &gmtime_mutex );
#ifndef LDAP_LOCALTIME
ltm = gmtime( ¤ttime );
strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
ltm = localtime( ¤ttime );
strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
#endif
- ldap_pvt_thread_mutex_unlock( ¤ttime_mutex );
val.bv_val = buf;
val.bv_len = strlen( buf );
attr_merge( e, "currenttime", vals );
- ldap_pvt_thread_mutex_lock( ¤ttime_mutex );
#ifndef LDAP_LOCALTIME
ltm = gmtime( &starttime );
strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
ltm = localtime( &starttime );
strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
#endif
- ldap_pvt_thread_mutex_unlock( ¤ttime_mutex );
+ ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
+
val.bv_val = buf;
val.bv_len = strlen( buf );
attr_merge( e, "starttime", vals );
{
assert( op->o_next == NULL );
- ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
-
if ( op->o_ber != NULL ) {
ber_free( op->o_ber, 1 );
}
free( op->o_ndn );
}
- ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
ldap_pvt_thread_mutex_destroy( &op->o_abandonmutex );
+
free( (char *) op );
}
BerElement *ber,
unsigned long msgid,
unsigned long tag,
- int id,
- int connid
+ long id
)
{
Operation *op;
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( ¤ttime_mutex );
- op->o_time = currenttime;
- ldap_pvt_thread_mutex_unlock( ¤ttime_mutex );
+ op->o_time = slap_get_time();
op->o_opid = id;
- op->o_connid = connid;
op->o_next = NULL;
return( op );
/*
* 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
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 ));
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
* Other...
*/
-extern char **g_argv;
extern char *default_referral;
extern char *replogfile;
extern char Versionstr[];
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));
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 */
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 ) {
#include "slap.h"
-
static void
send_ldap_result2(
Connection *conn,
)
{
BerElement *ber;
- int rc;
+ int rc, tmp;
unsigned long tag, bytes;
if ( err == LDAP_PARTIAL_RESULTS && (text == NULL || *text == '\0') )
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;
}
}
/* 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
: "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,
{
BerElement *ber;
Attribute *a;
- int i, rc, bytes;
+ int i, rc=-1, bytes;
struct acl *acl;
char *edn;
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,
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 );
}
}
- 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,
return( 1 );
}
+ bytes = ber->ber_ptr - ber->ber_buf;
+
/* 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 );
- 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 );
+ /* 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
: "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 );
-
- if( active_threads < 1 ) {
- ldap_pvt_thread_cond_signal(&active_threads_cond);
- }
- ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
+ slapd_set_write( conn->c_sb.sb_sd, 1 );
- 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
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 );
-}
*/
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;
* 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)
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
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
--- /dev/null
+/*
+ * 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;
+}
/* 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 );
}