diff --git a/include/ldap_int_thread.h b/include/ldap_int_thread.h
index d6a6d779575564762c1c324635562ea9acfcb270..db345df06dedd639b25526d04991cc92ae120d59 100644
--- a/include/ldap_int_thread.h
+++ b/include/ldap_int_thread.h
@@ -44,6 +44,7 @@ LDAP_BEGIN_DECL
 typedef pthread_t		ldap_int_thread_t;
 typedef pthread_mutex_t		ldap_int_thread_mutex_t;
 typedef pthread_cond_t		ldap_int_thread_cond_t;
+typedef pthread_key_t		ldap_int_thread_key_t;
 
 #define ldap_int_thread_equal(a, b)	pthread_equal((a), (b))
 
@@ -88,6 +89,7 @@ LDAP_BEGIN_DECL
 typedef cthread_t		ldap_int_thread_t;
 typedef struct mutex		ldap_int_thread_mutex_t;
 typedef struct condition	ldap_int_thread_cond_t;
+typedef cthread_key_t		ldap_int_thread_key_t;
 
 LDAP_END_DECL
 
@@ -106,6 +108,7 @@ LDAP_BEGIN_DECL
 typedef pth_t		ldap_int_thread_t;
 typedef pth_mutex_t	ldap_int_thread_mutex_t;
 typedef pth_cond_t	ldap_int_thread_cond_t;
+typedef pth_key_t	ldap_int_thread_key_t;
 
 #if 0
 #define LDAP_THREAD_HAVE_RDWR 1
@@ -129,6 +132,7 @@ LDAP_BEGIN_DECL
 typedef thread_t		ldap_int_thread_t;
 typedef mutex_t			ldap_int_thread_mutex_t;
 typedef cond_t			ldap_int_thread_cond_t;
+typedef thread_key_t	ldap_int_thread_key_t;
 
 #define HAVE_REENTRANT_FUNCTIONS 1
 
@@ -181,6 +185,7 @@ LDAP_BEGIN_DECL
 typedef unsigned long	ldap_int_thread_t;
 typedef HANDLE	ldap_int_thread_mutex_t;
 typedef HANDLE	ldap_int_thread_cond_t;
+typedef DWORD	ldap_int_thread_key_t;
 
 LDAP_END_DECL
 
@@ -201,6 +206,7 @@ LDAP_BEGIN_DECL
 typedef int			ldap_int_thread_t;
 typedef int			ldap_int_thread_mutex_t;
 typedef int			ldap_int_thread_cond_t;
+typedef int			ldap_int_thread_key_t;
 
 #define LDAP_THREAD_HAVE_TPOOL 1
 typedef int			ldap_int_thread_pool_t;
diff --git a/include/ldap_pvt_thread.h b/include/ldap_pvt_thread.h
index 151756d692a03690537699f3e3f3ec709e6f1af6..21b2dc69cdf3affcca2b2db47d5ed4404b06c3bc 100644
--- a/include/ldap_pvt_thread.h
+++ b/include/ldap_pvt_thread.h
@@ -34,6 +34,7 @@ typedef ldap_int_thread_cond_t		ldap_pvt_thread_cond_t;
 typedef ldap_int_thread_rdwr_t		ldap_pvt_thread_rdwr_t;
 #endif
 typedef ldap_int_thread_rmutex_t	ldap_pvt_thread_rmutex_t;
+typedef ldap_int_thread_key_t	ldap_pvt_thread_key_t;
 #endif /* !LDAP_PVT_THREAD_H_DONE */
 
 #define ldap_pvt_thread_equal		ldap_int_thread_equal
@@ -169,6 +170,18 @@ ldap_pvt_thread_rdwr_wtrylock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp));
 LDAP_F( int )
 ldap_pvt_thread_rdwr_wunlock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp));
 
+LDAP_F( int )
+ldap_pvt_thread_key_create LDAP_P((ldap_pvt_thread_key_t *keyp));
+
+LDAP_F( int )
+ldap_pvt_thread_key_destroy LDAP_P((ldap_pvt_thread_key_t key));
+
+LDAP_F( int )
+ldap_pvt_thread_key_setdata LDAP_P((ldap_pvt_thread_key_t key, void *data));
+
+LDAP_F( int )
+ldap_pvt_thread_key_getdata LDAP_P((ldap_pvt_thread_key_t key, void **data));
+
 #ifdef LDAP_DEBUG
 LDAP_F( int )
 ldap_pvt_thread_rdwr_readers LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp));
diff --git a/libraries/libldap_r/thr_cthreads.c b/libraries/libldap_r/thr_cthreads.c
index b98a47afa2caa28f736207e6a19a7faa6c73e84f..ab19880bb77d3f18c90b5df31336bf01f6519be4 100644
--- a/libraries/libldap_r/thr_cthreads.c
+++ b/libraries/libldap_r/thr_cthreads.c
@@ -153,4 +153,28 @@ ldap_pvt_thread_self( void )
 	return cthread_self();
 }
 
+int
+ldap_pvt_thread_key_create( ldap_pvt_thread_key_t *key )
+{
+	return cthread_keycreate( key );
+}
+
+int
+ldap_pvt_thread_key_destroy( ldap_pvt_thread_key_t key )
+{
+	return( 0 );
+}
+
+int
+ldap_pvt_thread_key_setdata( ldap_pvt_thread_key_t key, void *data )
+{
+	return cthread_setspecific( key, data );
+}
+
+int
+ldap_pvt_thread_key_getdata( ldap_pvt_thread_key_t key, void **data )
+{
+	return cthread_getspecific( key, data );
+}
+
 #endif /* HAVE_MACH_CTHREADS */
diff --git a/libraries/libldap_r/thr_nt.c b/libraries/libldap_r/thr_nt.c
index f3d0755de99941f3a78f237b3c40a6d4349c9330..29416fa85e0071b2f6915987bd27d0608d1dcc97 100644
--- a/libraries/libldap_r/thr_nt.c
+++ b/libraries/libldap_r/thr_nt.c
@@ -198,4 +198,37 @@ ldap_pvt_thread_self( void )
 	return GetCurrentThreadId();
 }
 
+int
+ldap_pvt_thread_key_create( ldap_pvt_thread_key_t *keyp )
+{
+	DWORD key = TlsAlloc();
+	if ( key != TLS_OUT_OF_INDEXES ) {
+		*keyp = key;
+		return 0;
+	} else {
+		return -1;
+	}
+}
+
+int
+ldap_pvt_thread_key_destroy( ldap_pvt_thread_key_t key )
+{
+	/* TlsFree returns 0 on failure */
+	return( TlsFree( key ) == 0 );
+}
+
+int
+ldap_pvt_thread_key_setdata( ldap_pvt_thread_key_t key, void *data )
+{
+	return ( TlsSetValue( key, data ) == 0 );
+}
+
+int
+ldap_pvt_thread_key_getdata( ldap_pvt_thread_key_t key, void **data )
+{
+	void *ptr = TlsGetValue( key );
+	*data = ptr;
+	return( ptr ? GetLastError() : 0 );
+}
+
 #endif
diff --git a/libraries/libldap_r/thr_posix.c b/libraries/libldap_r/thr_posix.c
index 4e0a45b4321b44872a5b8f20915ce6fd1341288f..34914b626f959e7454821ecd111e991b8f4f7383 100644
--- a/libraries/libldap_r/thr_posix.c
+++ b/libraries/libldap_r/thr_posix.c
@@ -312,6 +312,31 @@ ldap_pvt_thread_t ldap_pvt_thread_self( void )
 	return pthread_self();
 }
 
+int
+ldap_pvt_thread_key_create( ldap_pvt_thread_key_t *key )
+{
+	return pthread_key_create( key, NULL );
+}
+
+int
+ldap_pvt_thread_key_destroy( ldap_pvt_thread_key_t key )
+{
+	return pthread_key_delete( key );
+}
+
+int
+ldap_pvt_thread_key_setdata( ldap_pvt_thread_key_t key, void *data )
+{
+	return pthread_setspecific( key, data );
+}
+
+int
+ldap_pvt_thread_key_getdata( ldap_pvt_thread_key_t key, void **data )
+{
+	*data = pthread_getspecific( key );
+	return 0;
+}
+
 #ifdef LDAP_THREAD_HAVE_RDWR
 #ifdef HAVE_PTHREAD_RWLOCK_DESTROY
 int 
diff --git a/libraries/libldap_r/thr_pth.c b/libraries/libldap_r/thr_pth.c
index c5844533c12da13974e8ecb9ed13b651c0240ab2..f06efe0d130730637c29e3a188e3b6209abecca6 100644
--- a/libraries/libldap_r/thr_pth.c
+++ b/libraries/libldap_r/thr_pth.c
@@ -159,6 +159,31 @@ ldap_pvt_thread_self( void )
 	return pth_self();
 }
 
+int
+ldap_pvt_thread_key_create( ldap_pvt_thread_key_t *key )
+{
+	return pth_key_create( key, NULL );
+}
+
+int
+ldap_pvt_thread_key_destroy( ldap_pvt_thread_key_t key )
+{
+	return pth_key_delete( key );
+}
+
+int
+ldap_pvt_thread_key_setdata( ldap_pvt_thread_key_t key, void *data )
+{
+	return pth_key_setdata( key, data );
+}
+
+int
+ldap_pvt_thread_key_getdata( ldap_pvt_thread_key_t key, void **data )
+{
+	*data = pth_key_getdata( key );
+	return 0;
+}
+
 #ifdef LDAP_THREAD_HAVE_RDWR
 int 
 ldap_pvt_thread_rdwr_init( ldap_pvt_thread_rdwr_t *rw )
diff --git a/libraries/libldap_r/thr_stub.c b/libraries/libldap_r/thr_stub.c
index 1dce9d160be0f08a4796bd01e2537fd73b2c8bb5..65a18bd0ac1bb919b21b01a78ec3db1fbbd3f4c4 100644
--- a/libraries/libldap_r/thr_stub.c
+++ b/libraries/libldap_r/thr_stub.c
@@ -237,6 +237,30 @@ ldap_pvt_thread_self( void )
 	return(0);
 }
 
+int
+ldap_pvt_thread_key_create( ldap_pvt_thread_key_t *key )
+{
+	return(0);
+}
+
+int
+ldap_pvt_thread_key_destroy( ldap_pvt_thread_key_t key )
+{
+	return(0);
+}
+
+int
+ldap_pvt_thread_key_setdata( ldap_pvt_thread_key_t key, void *data )
+{
+	return(0);
+}
+
+int
+ldap_pvt_thread_key_getdata( ldap_pvt_thread_key_t key, void **data )
+{
+	return(0);
+}
+
 ldap_pvt_thread_t
 ldap_pvt_thread_pool_tid( void *vctx )
 {
diff --git a/libraries/libldap_r/thr_thr.c b/libraries/libldap_r/thr_thr.c
index 2acbe083a64978566581134e46a507defc2dbe5e..2a9abae5454f160180ad822b0a03698df0dadb44 100644
--- a/libraries/libldap_r/thr_thr.c
+++ b/libraries/libldap_r/thr_thr.c
@@ -159,4 +159,28 @@ ldap_pvt_thread_self( void )
 	return thr_self();
 }
 
+int
+ldap_pvt_thread_key_create( ldap_pvt_thread_key_t *key )
+{
+	return thr_keycreate( key, NULL );
+}
+
+int
+ldap_pvt_thread_key_destroy( ldap_pvt_thread_key_t key )
+{
+	return( 0 );
+}
+
+int
+ldap_pvt_thread_key_setdata( ldap_pvt_thread_key_t key, void *data )
+{
+	return thr_setspecific( key, data );
+}
+
+int
+ldap_pvt_thread_key_getdata( ldap_pvt_thread_key_t key, void **data )
+{
+	return thr_getspecific( key, data );
+}
+
 #endif /* HAVE_THR */
diff --git a/libraries/libldap_r/tpool.c b/libraries/libldap_r/tpool.c
index 6e3d81b3b2d18b99d0f5ae903277870e0827f747..81ebd92ed63b5d59a0a393a429298d1ce980cd7f 100644
--- a/libraries/libldap_r/tpool.c
+++ b/libraries/libldap_r/tpool.c
@@ -38,11 +38,11 @@ typedef enum ldap_int_thread_pool_state_e {
 } ldap_int_thread_pool_state_t;
 
 /* Thread-specific key with data and optional free function */
-typedef struct ldap_int_thread_key_s {
+typedef struct ldap_int_tpool_key_s {
 	void *ltk_key;
 	void *ltk_data;
 	ldap_pvt_thread_pool_keyfree_t *ltk_free;
-} ldap_int_thread_key_t;
+} ldap_int_tpool_key_t;
 
 /* Max number of thread-specific keys we store per thread.
  * We don't expect to use many...
@@ -55,7 +55,7 @@ typedef struct ldap_int_thread_key_s {
 /* Context: thread ID and thread-specific key/data pairs */
 typedef struct ldap_int_thread_userctx_s {
 	ldap_pvt_thread_t ltu_id;
-	ldap_int_thread_key_t ltu_key[MAXKEYS];
+	ldap_int_tpool_key_t ltu_key[MAXKEYS];
 } ldap_int_thread_userctx_t;
 
 
@@ -126,6 +126,8 @@ static ldap_pvt_thread_mutex_t ldap_pvt_thread_pool_mutex;
 
 static void *ldap_int_thread_pool_wrapper( void *pool );
 
+static ldap_pvt_thread_key_t	ldap_tpool_key;
+
 /* Context of the main thread */
 static ldap_int_thread_userctx_t ldap_int_main_thrctx;
 
@@ -133,6 +135,7 @@ int
 ldap_int_thread_pool_startup ( void )
 {
 	ldap_int_main_thrctx.ltu_id = ldap_pvt_thread_self();
+	ldap_pvt_thread_key_create( &ldap_tpool_key );
 	return ldap_pvt_thread_mutex_init(&ldap_pvt_thread_pool_mutex);
 }
 
@@ -145,6 +148,7 @@ ldap_int_thread_pool_shutdown ( void )
 		(ldap_pvt_thread_pool_destroy)(&pool, 0); /* ignore thr_debug macro */
 	}
 	ldap_pvt_thread_mutex_destroy(&ldap_pvt_thread_pool_mutex);
+	ldap_pvt_thread_key_destroy( ldap_tpool_key );
 	return(0);
 }
 
@@ -552,6 +556,8 @@ ldap_int_thread_pool_wrapper (
 	ctx.ltu_id = ldap_pvt_thread_self();
 	TID_HASH(ctx.ltu_id, hash);
 
+	ldap_pvt_thread_key_setdata( ldap_tpool_key, &ctx );
+
 	ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
 
 	/* thread_keys[] is read-only when paused */
@@ -819,29 +825,10 @@ void ldap_pvt_thread_pool_purgekey( void *key )
  */
 void *ldap_pvt_thread_pool_context( )
 {
-	ldap_pvt_thread_t tid;
-	unsigned i, hash;
-	ldap_int_thread_userctx_t *ctx;
-
-	tid = ldap_pvt_thread_self();
-	if ( ldap_pvt_thread_equal( tid, ldap_int_main_thrctx.ltu_id ))
-		return &ldap_int_main_thrctx;
-
-	TID_HASH( tid, hash );
-	i = hash &= (LDAP_MAXTHR-1);
-	ldap_pvt_thread_mutex_lock(&ldap_pvt_thread_pool_mutex);
-	do {
-		ctx = thread_keys[i].ctx;
-		if ( ctx == DELETED_THREAD_CTX )
-			continue;
-		if ( !ctx || ldap_pvt_thread_equal(thread_keys[i].ctx->ltu_id, tid) )
-			goto done;
-	} while ( (i = (i+1) & (LDAP_MAXTHR-1)) != hash );
-	ctx = NULL;
- done:
-	ldap_pvt_thread_mutex_unlock(&ldap_pvt_thread_pool_mutex);
+	void *ctx = NULL;
 
-	return ctx;
+	ldap_pvt_thread_key_getdata( ldap_tpool_key, &ctx );
+	return ctx ? ctx : &ldap_int_main_thrctx;
 }
 
 /*
diff --git a/servers/slapd/abandon.c b/servers/slapd/abandon.c
index c77dc1e25e34756e0783c7c0305fe8170146a648..3f8b608c45741ae54e8e8af4be161be56ccc0910 100644
--- a/servers/slapd/abandon.c
+++ b/servers/slapd/abandon.c
@@ -98,7 +98,7 @@ do_abandon( Operation *op, SlapReply *rs )
 					o, Operation, o_next );
 				LDAP_STAILQ_NEXT(o, o_next) = NULL;
 				op->o_conn->c_n_ops_pending--;
-				slap_op_free( o );
+				slap_op_free( o, NULL );
 				break;
 			}
 		}
diff --git a/servers/slapd/back-monitor/operation.c b/servers/slapd/back-monitor/operation.c
index 74bd27402c2805d361cacb098eec6c8bb4ff937c..10086079187bbbf407b1bff772b495ec2bad9464 100644
--- a/servers/slapd/back-monitor/operation.c
+++ b/servers/slapd/back-monitor/operation.c
@@ -177,6 +177,7 @@ monitor_subsys_ops_update(
 	struct berval		rdn;
 	int 			i;
 	Attribute		*a;
+	slap_counters_t *sc;
 	static struct berval	bv_ops = BER_BVC( "cn=operations" );
 
 	assert( mi != NULL );
@@ -188,21 +189,35 @@ monitor_subsys_ops_update(
 		ldap_pvt_mp_init( nInitiated );
 		ldap_pvt_mp_init( nCompleted );
 
-		ldap_pvt_thread_mutex_lock( &slap_counters.sc_ops_mutex );
+		ldap_pvt_thread_mutex_lock( &slap_counters.sc_mutex );
 		for ( i = 0; i < SLAP_OP_LAST; i++ ) {
 			ldap_pvt_mp_add( nInitiated, slap_counters.sc_ops_initiated_[ i ] );
 			ldap_pvt_mp_add( nCompleted, slap_counters.sc_ops_completed_[ i ] );
 		}
-		ldap_pvt_thread_mutex_unlock( &slap_counters.sc_ops_mutex );
+		for ( sc = slap_counters.sc_next; sc; sc = sc->sc_next ) {
+			ldap_pvt_thread_mutex_lock( &sc->sc_mutex );
+			for ( i = 0; i < SLAP_OP_LAST; i++ ) {
+				ldap_pvt_mp_add( nInitiated, sc->sc_ops_initiated_[ i ] );
+				ldap_pvt_mp_add( nCompleted, sc->sc_ops_completed_[ i ] );
+			}
+			ldap_pvt_thread_mutex_unlock( &sc->sc_mutex );
+		}
+		ldap_pvt_thread_mutex_unlock( &slap_counters.sc_mutex );
 		
 	} else {
 		for ( i = 0; i < SLAP_OP_LAST; i++ ) {
 			if ( dn_match( &rdn, &monitor_op[ i ].nrdn ) )
 			{
-				ldap_pvt_thread_mutex_lock( &slap_counters.sc_ops_mutex );
+				ldap_pvt_thread_mutex_lock( &slap_counters.sc_mutex );
 				ldap_pvt_mp_init_set( nInitiated, slap_counters.sc_ops_initiated_[ i ] );
 				ldap_pvt_mp_init_set( nCompleted, slap_counters.sc_ops_completed_[ i ] );
-				ldap_pvt_thread_mutex_unlock( &slap_counters.sc_ops_mutex );
+				for ( sc = slap_counters.sc_next; sc; sc = sc->sc_next ) {
+					ldap_pvt_thread_mutex_lock( &sc->sc_mutex );
+					ldap_pvt_mp_add( nInitiated, sc->sc_ops_initiated_[ i ] );
+					ldap_pvt_mp_add( nCompleted, sc->sc_ops_completed_[ i ] );
+					ldap_pvt_thread_mutex_unlock( &sc->sc_mutex );
+				}
+				ldap_pvt_thread_mutex_unlock( &slap_counters.sc_mutex );
 				break;
 			}
 		}
diff --git a/servers/slapd/back-monitor/sent.c b/servers/slapd/back-monitor/sent.c
index 1be74711d9a0c38f68c9b0fc7b30f7bc94f9962c..d4d11fd30cd868749826dc5b4c0cc6ee8a13b161 100644
--- a/servers/slapd/back-monitor/sent.c
+++ b/servers/slapd/back-monitor/sent.c
@@ -166,6 +166,7 @@ monitor_subsys_sent_update(
 	struct berval		nrdn;
 	ldap_pvt_mp_t		n;
 	Attribute		*a;
+	slap_counters_t *sc;
 	int			i;
 
 	assert( mi != NULL );
@@ -183,28 +184,48 @@ monitor_subsys_sent_update(
 		return SLAP_CB_CONTINUE;
 	}
 
-	ldap_pvt_thread_mutex_lock(&slap_counters.sc_sent_mutex);
+	ldap_pvt_thread_mutex_lock(&slap_counters.sc_mutex);
 	switch ( i ) {
 	case MONITOR_SENT_ENTRIES:
 		ldap_pvt_mp_init_set( n, slap_counters.sc_entries );
+		for ( sc = slap_counters.sc_next; sc; sc = sc->sc_next ) {
+			ldap_pvt_thread_mutex_lock( &sc->sc_mutex );
+			ldap_pvt_mp_add( n, sc->sc_entries );
+			ldap_pvt_thread_mutex_unlock( &sc->sc_mutex );
+		}
 		break;
 
 	case MONITOR_SENT_REFERRALS:
 		ldap_pvt_mp_init_set( n, slap_counters.sc_refs );
+		for ( sc = slap_counters.sc_next; sc; sc = sc->sc_next ) {
+			ldap_pvt_thread_mutex_lock( &sc->sc_mutex );
+			ldap_pvt_mp_add( n, sc->sc_refs );
+			ldap_pvt_thread_mutex_unlock( &sc->sc_mutex );
+		}
 		break;
 
 	case MONITOR_SENT_PDU:
 		ldap_pvt_mp_init_set( n, slap_counters.sc_pdu );
+		for ( sc = slap_counters.sc_next; sc; sc = sc->sc_next ) {
+			ldap_pvt_thread_mutex_lock( &sc->sc_mutex );
+			ldap_pvt_mp_add( n, sc->sc_pdu );
+			ldap_pvt_thread_mutex_unlock( &sc->sc_mutex );
+		}
 		break;
 
 	case MONITOR_SENT_BYTES:
 		ldap_pvt_mp_init_set( n, slap_counters.sc_bytes );
+		for ( sc = slap_counters.sc_next; sc; sc = sc->sc_next ) {
+			ldap_pvt_thread_mutex_lock( &sc->sc_mutex );
+			ldap_pvt_mp_add( n, sc->sc_bytes );
+			ldap_pvt_thread_mutex_unlock( &sc->sc_mutex );
+		}
 		break;
 
 	default:
 		assert(0);
 	}
-	ldap_pvt_thread_mutex_unlock(&slap_counters.sc_sent_mutex);
+	ldap_pvt_thread_mutex_unlock(&slap_counters.sc_mutex);
 	
 	a = attr_find( e->e_attrs, mi->mi_ad_monitorCounter );
 	assert( a != NULL );
diff --git a/servers/slapd/cancel.c b/servers/slapd/cancel.c
index dd4c79730cd86f505eb0cbaf9694686dff4c5cef..d11ad6a001d7e859282b0372ea67646652c8d175 100644
--- a/servers/slapd/cancel.c
+++ b/servers/slapd/cancel.c
@@ -70,7 +70,7 @@ int cancel_extop( Operation *op, SlapReply *rs )
 			LDAP_STAILQ_REMOVE( &op->o_conn->c_pending_ops, o, Operation, o_next );
 			LDAP_STAILQ_NEXT(o, o_next) = NULL;
 			op->o_conn->c_n_ops_pending--;
-			slap_op_free( o );
+			slap_op_free( o, NULL );
 			ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
 			return LDAP_SUCCESS;
 		}
diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c
index 9ec67f503a6d049ee48eec22e6e75089100234c6..c2e5a74318186f7f14de9048f4415d7129e69b6f 100644
--- a/servers/slapd/connection.c
+++ b/servers/slapd/connection.c
@@ -83,25 +83,19 @@ connection_state2str( int state )
 
 static Connection* connection_get( ber_socket_t s );
 
-#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
-
 typedef struct conn_readinfo {
 	Operation *op;
 	ldap_pvt_thread_start_t *func;
 	void *arg;
+	void *ctx;
 	int nullop;
 } conn_readinfo;
 
 static int connection_input( Connection *c, conn_readinfo *cri );
-#else
-static int connection_input( Connection *c );
-#endif
 static void connection_close( Connection *c );
 
 static int connection_op_activate( Operation *op );
-#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
 static void connection_op_queue( Operation *op );
-#endif
 static int connection_resched( Connection *conn );
 static void connection_abandon( Connection *conn );
 static void connection_destroy( Connection *c );
@@ -267,8 +261,6 @@ static Connection* connection_get( ber_socket_t s )
 #else
 	c = NULL;
 	{
-		ber_socket_t i, sd;
-
 		ldap_pvt_thread_mutex_lock( &connections_mutex );
 		for(i=0; i<dtblsize; i++) {
 			if( connections[i].c_struct_state == SLAP_C_PENDING )
@@ -280,12 +272,9 @@ static Connection* connection_get( ber_socket_t s )
 				break;
 			}
 
-			ber_sockbuf_ctrl( connections[i].c_sb,
-				LBER_SB_OPT_GET_FD, &sd );
-
 			if( connections[i].c_struct_state == SLAP_C_UNUSED ) {
 				assert( connections[i].c_conn_state == SLAP_C_INVALID );
-				assert( sd == AC_SOCKET_INVALID );
+				assert( connections[i].c_sd == AC_SOCKET_INVALID );
 				continue;
 			}
 
@@ -293,7 +282,7 @@ static Connection* connection_get( ber_socket_t s )
 			 * so don't assert details here.
 			 */
 
-			if( sd == s ) {
+			if( connections[i].c_sd == s ) {
 				c = &connections[i];
 				break;
 			}
@@ -303,18 +292,15 @@ static Connection* connection_get( ber_socket_t s )
 #endif
 
 	if( c != NULL ) {
-		ber_socket_t	sd;
-
 		ldap_pvt_thread_mutex_lock( &c->c_mutex );
 
 		assert( c->c_struct_state != SLAP_C_UNINITIALIZED );
 
-		ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_GET_FD, &sd );
 #ifdef HAVE_WINSOCK
 		/* Avoid race condition after releasing
 		 * connections_mutex
 		 */
-		if ( sd != s ) {
+		if ( c->c_sd != s ) {
 			ldap_pvt_thread_mutex_unlock( &c->c_mutex );
 			return NULL;
 		}
@@ -323,7 +309,7 @@ static Connection* connection_get( ber_socket_t s )
 			/* connection must have been closed due to resched */
 
 			assert( c->c_conn_state == SLAP_C_INVALID );
-			assert( sd == AC_SOCKET_INVALID );
+			assert( c->c_sd == AC_SOCKET_INVALID );
 
 			Debug( LDAP_DEBUG_TRACE,
 				"connection_get(%d): connection not used\n",
@@ -341,7 +327,7 @@ static Connection* connection_get( ber_socket_t s )
 
 		assert( c->c_struct_state == SLAP_C_USED );
 		assert( c->c_conn_state != SLAP_C_INVALID );
-		assert( sd != AC_SOCKET_INVALID );
+		assert( c->c_sd != AC_SOCKET_INVALID );
 
 #ifndef SLAPD_MONITOR
 		if ( global_idletimeout > 0 )
@@ -405,8 +391,6 @@ Connection * connection_init(
 
 		ldap_pvt_thread_mutex_lock( &connections_mutex );
 		for( i=0; i < dtblsize; i++) {
-			ber_socket_t	sd;
-
 			if ( connections[i].c_struct_state == SLAP_C_PENDING )
 				continue;
 
@@ -418,14 +402,7 @@ Connection * connection_init(
 				break;
 			}
 
-			sd = AC_SOCKET_INVALID;
-			if (connections[i].c_sb != NULL) {
-				ber_sockbuf_ctrl( connections[i].c_sb,
-					LBER_SB_OPT_GET_FD, &sd );
-			}
-
 			if( connections[i].c_struct_state == SLAP_C_UNUSED ) {
-				assert( sd == AC_SOCKET_INVALID );
 				c = &connections[i];
 				c->c_struct_state = SLAP_C_PENDING;
 				break;
@@ -435,7 +412,6 @@ Connection * connection_init(
 
 			assert( connections[i].c_struct_state == SLAP_C_USED );
 			assert( connections[i].c_conn_state != SLAP_C_INVALID );
-			assert( sd != AC_SOCKET_INVALID );
 		}
 		ldap_pvt_thread_mutex_unlock( &connections_mutex );
 
@@ -525,6 +501,7 @@ Connection * connection_init(
 	assert( c->c_writewaiter == 0);
 
 	c->c_listener = listener;
+	c->c_sd = s;
 
 	if ( flags & CONN_IS_CLIENT ) {
 		c->c_connid = 0;
@@ -677,7 +654,6 @@ void connection2anonymous( Connection *c )
 static void
 connection_destroy( Connection *c )
 {
-	ber_socket_t	sd;
 	unsigned long	connid;
 	const char		*close_reason;
 	Sockbuf			*sb;
@@ -754,21 +730,20 @@ connection_destroy( Connection *c )
 		ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max );
 	}
 
-	ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
-
 	/* c must be fully reset by this point; when we call slapd_remove
 	 * it may get immediately reused by a new connection.
 	 */
-	if ( sd != AC_SOCKET_INVALID ) {
-		slapd_remove( sd, sb, 1, 0, 0 );
+	if ( c->c_sd != AC_SOCKET_INVALID ) {
+		slapd_remove( c->c_sd, sb, 1, 0, 0 );
 
 		if ( close_reason == NULL ) {
 			Statslog( LDAP_DEBUG_STATS, "conn=%lu fd=%ld closed\n",
-				connid, (long) sd, 0, 0, 0 );
+				connid, (long) c->c_sd, 0, 0, 0 );
 		} else {
 			Statslog( LDAP_DEBUG_STATS, "conn=%lu fd=%ld closed (%s)\n",
-				connid, (long) sd, close_reason, 0, 0 );
+				connid, (long) c->c_sd, close_reason, 0, 0 );
 		}
+		c->c_sd = AC_SOCKET_INVALID;
 	}
 }
 
@@ -813,7 +788,7 @@ static void connection_abandon( Connection *c )
 	while ( (o = LDAP_STAILQ_FIRST( &c->c_txn_ops )) != NULL) {
 		LDAP_STAILQ_REMOVE_HEAD( &c->c_txn_ops, o_next );
 		LDAP_STAILQ_NEXT(o, o_next) = NULL;
-		slap_op_free( o );
+		slap_op_free( o, NULL );
 	}
 
 	/* clear transaction */
@@ -825,7 +800,7 @@ static void connection_abandon( Connection *c )
 	while ( (o = LDAP_STAILQ_FIRST( &c->c_pending_ops )) != NULL) {
 		LDAP_STAILQ_REMOVE_HEAD( &c->c_pending_ops, o_next );
 		LDAP_STAILQ_NEXT(o, o_next) = NULL;
-		slap_op_free( o );
+		slap_op_free( o, NULL );
 	}
 }
 
@@ -839,18 +814,15 @@ void connection_closing( Connection *c, const char *why )
 	/* c_mutex must be locked by caller */
 
 	if( c->c_conn_state != SLAP_C_CLOSING ) {
-		ber_socket_t	sd;
-
-		ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_GET_FD, &sd );
 		Debug( LDAP_DEBUG_TRACE,
 			"connection_closing: readying conn=%lu sd=%d for close\n",
-			c->c_connid, sd, 0 );
+			c->c_connid, c->c_sd, 0 );
 		/* update state to closing */
 		c->c_conn_state = SLAP_C_CLOSING;
 		c->c_close_reason = why;
 
 		/* don't listen on this port anymore */
-		slapd_clr_read( sd, 0 );
+		slapd_clr_read( c->c_sd, 0 );
 
 		/* abandon active operations */
 		connection_abandon( c );
@@ -862,13 +834,13 @@ void connection_closing( Connection *c, const char *why )
 			 * connection_resched / connection_close before we
 			 * finish, but that's OK.
 			 */
-			slapd_clr_write( sd, 1 );
+			slapd_clr_write( c->c_sd, 1 );
 			ldap_pvt_thread_mutex_unlock( &c->c_mutex );
 			ldap_pvt_thread_mutex_lock( &c->c_write_mutex );
 			ldap_pvt_thread_mutex_lock( &c->c_mutex );
 			ldap_pvt_thread_mutex_unlock( &c->c_write_mutex );
 		} else {
-			slapd_clr_write( sd, 1 );
+			slapd_clr_write( c->c_sd, 1 );
 		}
 
 	} else if( why == NULL && c->c_close_reason == conn_lost_str ) {
@@ -880,8 +852,6 @@ void connection_closing( Connection *c, const char *why )
 static void
 connection_close( Connection *c )
 {
-	ber_socket_t	sd = AC_SOCKET_INVALID;
-
 	assert( connections != NULL );
 	assert( c != NULL );
 
@@ -894,22 +864,17 @@ connection_close( Connection *c )
 
 	/* NOTE: c_mutex should be locked by caller */
 
-	/* NOTE: don't get the file descriptor if not needed */
-	if ( LogTest( LDAP_DEBUG_TRACE ) ) {
-		ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_GET_FD, &sd );
-	}
-
 	if ( !LDAP_STAILQ_EMPTY(&c->c_ops) ||
 		!LDAP_STAILQ_EMPTY(&c->c_pending_ops) )
 	{
 		Debug( LDAP_DEBUG_TRACE,
 			"connection_close: deferring conn=%lu sd=%d\n",
-			c->c_connid, sd, 0 );
+			c->c_connid, c->c_sd, 0 );
 		return;
 	}
 
 	Debug( LDAP_DEBUG_TRACE, "connection_close: conn=%lu sd=%d\n",
-		c->c_connid, sd, 0 );
+		c->c_connid, c->c_sd, 0 );
 
 	connection_destroy( c );
 }
@@ -1011,24 +976,24 @@ void connection_done( Connection *c )
 /* FIXME: returns 0 in case of failure */
 #define INCR_OP_INITIATED(index) \
 	do { \
-		ldap_pvt_thread_mutex_lock( &slap_counters.sc_ops_mutex ); \
-		ldap_pvt_mp_add_ulong(slap_counters.sc_ops_initiated_[(index)], 1); \
-		ldap_pvt_thread_mutex_unlock( &slap_counters.sc_ops_mutex ); \
+		ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex ); \
+		ldap_pvt_mp_add_ulong(op->o_counters->sc_ops_initiated_[(index)], 1); \
+		ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex ); \
 	} while (0)
 #define INCR_OP_COMPLETED(index) \
 	do { \
-		ldap_pvt_thread_mutex_lock( &slap_counters.sc_ops_mutex ); \
-		ldap_pvt_mp_add_ulong(slap_counters.sc_ops_completed, 1); \
-		ldap_pvt_mp_add_ulong(slap_counters.sc_ops_completed_[(index)], 1); \
-		ldap_pvt_thread_mutex_unlock( &slap_counters.sc_ops_mutex ); \
+		ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex ); \
+		ldap_pvt_mp_add_ulong(op->o_counters->sc_ops_completed, 1); \
+		ldap_pvt_mp_add_ulong(op->o_counters->sc_ops_completed_[(index)], 1); \
+		ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex ); \
 	} while (0)
 #else /* !SLAPD_MONITOR */
 #define INCR_OP_INITIATED(index) do { } while (0)
 #define INCR_OP_COMPLETED(index) \
 	do { \
-		ldap_pvt_thread_mutex_lock( &slap_counters.sc_ops_mutex ); \
-		ldap_pvt_mp_add_ulong(slap_counters.sc_ops_completed, 1); \
-		ldap_pvt_thread_mutex_unlock( &slap_counters.sc_ops_mutex ); \
+		ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex ); \
+		ldap_pvt_mp_add_ulong(op->o_counters->sc_ops_completed, 1); \
+		ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex ); \
 	} while (0)
 #endif /* !SLAPD_MONITOR */
 
@@ -1049,6 +1014,62 @@ static BI_op_func *opfun[] = {
 	NULL
 };
 
+/* Counters are per-thread, not per-connection.
+ */
+static void
+conn_counter_destroy( void *key, void *data )
+{
+	slap_counters_t **prev, *sc;
+
+	ldap_pvt_thread_mutex_lock( &slap_counters.sc_mutex );
+	for ( prev = &slap_counters.sc_next, sc = slap_counters.sc_next; sc;
+		prev = &sc->sc_next, sc = sc->sc_next ) {
+		if ( sc == data ) {
+			int i;
+
+			*prev = sc->sc_next;
+			/* Copy data to main counter */
+			ldap_pvt_mp_add( slap_counters.sc_bytes, sc->sc_bytes );
+			ldap_pvt_mp_add( slap_counters.sc_pdu, sc->sc_pdu );
+			ldap_pvt_mp_add( slap_counters.sc_entries, sc->sc_entries );
+			ldap_pvt_mp_add( slap_counters.sc_refs, sc->sc_refs );
+			ldap_pvt_mp_add( slap_counters.sc_ops_initiated, sc->sc_ops_initiated );
+			ldap_pvt_mp_add( slap_counters.sc_ops_completed, sc->sc_ops_completed );
+#ifdef SLAPD_MONITOR
+			for ( i = 0; i < SLAP_OP_LAST; i++ ) {
+				ldap_pvt_mp_add( slap_counters.sc_ops_initiated_[ i ], sc->sc_ops_initiated_[ i ] );
+				ldap_pvt_mp_add( slap_counters.sc_ops_initiated_[ i ], sc->sc_ops_completed_[ i ] );
+			}
+#endif /* SLAPD_MONITOR */
+			slap_counters_destroy( sc );
+			ber_memfree_x( data, NULL );
+			break;
+		}
+	}
+	ldap_pvt_thread_mutex_unlock( &slap_counters.sc_mutex );
+}
+
+static void
+conn_counter_init( Operation *op, void *ctx )
+{
+	slap_counters_t *sc;
+	void *vsc = NULL;
+
+	if ( ldap_pvt_thread_pool_getkey( ctx, conn_counter_init, &vsc, NULL ) || !vsc ) {
+		vsc = ch_malloc( sizeof( slap_counters_t ));
+		sc = vsc;
+		slap_counters_init( sc );
+		ldap_pvt_thread_pool_setkey( ctx, conn_counter_init, vsc,
+			conn_counter_destroy );
+
+		ldap_pvt_thread_mutex_lock( &slap_counters.sc_mutex );
+		sc->sc_next = slap_counters.sc_next;
+		slap_counters.sc_next = sc;
+		ldap_pvt_thread_mutex_unlock( &slap_counters.sc_mutex );
+	}
+	op->o_counters = vsc;
+}
+
 static void *
 connection_operation( void *ctx, void *arg_v )
 {
@@ -1062,10 +1083,11 @@ connection_operation( void *ctx, void *arg_v )
 	void *memctx_null = NULL;
 	ber_len_t memsiz;
 
-	ldap_pvt_thread_mutex_lock( &slap_counters.sc_ops_mutex );
+	conn_counter_init( op, ctx );
+	ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex );
 	/* FIXME: returns 0 in case of failure */
-	ldap_pvt_mp_add_ulong(slap_counters.sc_ops_initiated, 1);
-	ldap_pvt_thread_mutex_unlock( &slap_counters.sc_ops_mutex );
+	ldap_pvt_mp_add_ulong(op->o_counters->sc_ops_initiated, 1);
+	ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex );
 
 	op->o_threadctx = ctx;
 	op->o_tid = ldap_pvt_thread_pool_tid( ctx );
@@ -1175,7 +1197,6 @@ operations_error:
 
 	LDAP_STAILQ_REMOVE( &conn->c_ops, op, Operation, o_next);
 	LDAP_STAILQ_NEXT(op, o_next) = NULL;
-	slap_op_free( op );
 	conn->c_n_ops_executing--;
 	conn->c_n_ops_completed++;
 
@@ -1190,6 +1211,7 @@ operations_error:
 
 	connection_resched( conn );
 	ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+	slap_op_free( op, ctx );
 	return NULL;
 }
 
@@ -1247,8 +1269,6 @@ void connection_client_stop(
 	connection_return( c );
 }
 
-#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
-
 static int connection_read( ber_socket_t s, conn_readinfo *cri );
 
 static void* connection_read_thread( void* ctx, void* argv )
@@ -1261,6 +1281,7 @@ static void* connection_read_thread( void* ctx, void* argv )
 	 * read incoming LDAP requests. If there is more than one,
 	 * the first one is returned with new_op
 	 */
+	cri.ctx = ctx;
 	if( ( rc = connection_read( s, &cri ) ) < 0 ) {
 		Debug( LDAP_DEBUG_CONNS, "connection_read(%d) error\n", s, 0, 0 );
 		return (void*)(long)rc;
@@ -1300,14 +1321,9 @@ int connection_read_activate( ber_socket_t s )
 
 	return rc;
 }
-#endif
 
-#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
 static int
 connection_read( ber_socket_t s, conn_readinfo *cri )
-#else
-int connection_read(ber_socket_t s)
-#endif
 {
 	int rc = 0;
 	Connection *c;
@@ -1336,15 +1352,9 @@ int connection_read(ber_socket_t s)
 	}
 
 	if ( c->c_conn_state == SLAP_C_CLIENT ) {
-#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
 		cri->func = c->c_clientfunc;
 		cri->arg = c->c_clientarg;
 		/* read should already be cleared */
-#else
-		slapd_clr_read( s, 0 );
-		ldap_pvt_thread_pool_submit( &connection_pool,
-			c->c_clientfunc, c->c_clientarg );
-#endif
 		connection_return( c );
 		return 0;
 	}
@@ -1399,10 +1409,7 @@ int connection_read(ber_socket_t s)
 		/* if success and data is ready, fall thru to data input loop */
 		if( !ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DATA_READY, NULL ) )
 		{
-#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
 			slapd_set_read( s, 1 );
-#endif
-
 			connection_return( c );
 			return 0;
 		}
@@ -1413,10 +1420,7 @@ int connection_read(ber_socket_t s)
 	if ( c->c_sasl_layers ) {
 		/* If previous layer is not removed yet, give up for now */
 		if ( !c->c_sasl_sockctx ) {
-#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
 			slapd_set_read( s, 1 );
-#endif
-
 			connection_return( c );
 			return 0;
 		}
@@ -1444,11 +1448,7 @@ int connection_read(ber_socket_t s)
 
 	do {
 		/* How do we do this without getting into a busy loop ? */
-#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
 		rc = connection_input( c, cri );
-#else
-		rc = connection_input( c );
-#endif
 	}
 #ifdef DATA_READY_LOOP
 	while( !rc && ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DATA_READY, NULL ));
@@ -1470,33 +1470,18 @@ int connection_read(ber_socket_t s)
 		return 0;
 	}
 
-#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
 	if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_WRITE, NULL ) ) {
 		slapd_set_write( s, 0 );
 	}
 
 	slapd_set_read( s, 1 );
-#else
-	if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_READ, NULL ) ) {
-		slapd_set_read( s, 1 );
-	}
-
-	if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_WRITE, NULL ) ) {
-		slapd_set_write( s, 1 );
-	}
-#endif
-
 	connection_return( c );
 
 	return 0;
 }
 
 static int
-#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
 connection_input( Connection *conn , conn_readinfo *cri )
-#else
-connection_input( Connection *conn )
-#endif
 {
 	Operation *op;
 	ber_tag_t	tag;
@@ -1509,6 +1494,7 @@ connection_input( Connection *conn )
 	char 		*cdn = NULL;
 #endif
 	char *defer = NULL;
+	void *ctx;
 
 	if ( conn->c_currentber == NULL &&
 		( conn->c_currentber = ber_alloc()) == NULL )
@@ -1538,15 +1524,12 @@ connection_input( Connection *conn )
 	tag = ber_get_next( conn->c_sb, &len, conn->c_currentber );
 	if ( tag != LDAP_TAG_MESSAGE ) {
 		int err = sock_errno();
-		ber_socket_t	sd;
-
-		ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_GET_FD, &sd );
 
 		if ( err != EWOULDBLOCK && err != EAGAIN ) {
 			/* log, close and send error */
 			Debug( LDAP_DEBUG_TRACE,
 				"ber_get_next on fd %d failed errno=%d (%s)\n",
-			sd, err, sock_errstr(err) );
+			conn->c_sd, err, sock_errstr(err) );
 			ber_free( conn->c_currentber, 1 );
 			conn->c_currentber = NULL;
 
@@ -1592,7 +1575,8 @@ connection_input( Connection *conn )
 		connection_abandon( conn );
 	}
 
-	op = slap_op_alloc( ber, msgid, tag, conn->c_n_ops_received++ );
+	ctx = cri->ctx;
+	op = slap_op_alloc( ber, msgid, tag, conn->c_n_ops_received++, ctx );
 
 	op->o_conn = conn;
 	/* clear state if the connection is being reused from inactive */
@@ -1682,7 +1666,6 @@ connection_input( Connection *conn )
 	} else {
 		conn->c_n_ops_executing++;
 
-#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
 		/*
 		 * The first op will be processed in the same thread context,
 		 * as long as there is only one op total.
@@ -1701,9 +1684,6 @@ connection_input( Connection *conn )
 			}
 			connection_op_activate( op );
 		}
-#else
-		connection_op_activate( op );
-#endif
 	}
 
 #ifdef NO_THREADS
@@ -1723,12 +1703,9 @@ connection_resched( Connection *conn )
 	Operation *op;
 
 	if( conn->c_conn_state == SLAP_C_CLOSING ) {
-		ber_socket_t	sd;
-		ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_GET_FD, &sd );
-
 		Debug( LDAP_DEBUG_TRACE, "connection_resched: "
 			"attempting closing conn=%lu sd=%d\n",
-			conn->c_connid, sd, 0 );
+			conn->c_connid, conn->c_sd, 0 );
 		connection_close( conn );
 		return 0;
 	}
@@ -2010,6 +1987,7 @@ connection_fake_init2(
 	Operation *op = (Operation *) opbuf;
 
 	conn->c_connid = -1;
+	conn->c_conn_idx = -1;
 	conn->c_send_ldap_result = slap_send_ldap_result;
 	conn->c_send_search_entry = slap_send_search_entry;
 	conn->c_send_search_reference = slap_send_search_reference;
@@ -2028,6 +2006,7 @@ connection_fake_init2(
 	op->o_threadctx = ctx;
 	op->o_tid = ldap_pvt_thread_pool_tid( ctx );
 
+	op->o_counters = &slap_counters;
 	op->o_conn = conn;
 	op->o_connid = op->o_conn->c_connid;
 	connection_init_log_prefix( op );
diff --git a/servers/slapd/daemon.c b/servers/slapd/daemon.c
index 5949e543d732d4b177689720dcaf5778d0fdcae5..641e4380424fefb7711fe0965df42458b8d4c547 100644
--- a/servers/slapd/daemon.c
+++ b/servers/slapd/daemon.c
@@ -182,14 +182,12 @@ static struct slap_daemon {
 # define SLAP_SOCK_CLR_READ(s)		SLAP_EPOLL_SOCK_CLR((s), EPOLLIN)
 # define SLAP_SOCK_CLR_WRITE(s)		SLAP_EPOLL_SOCK_CLR((s), EPOLLOUT)
 
-# ifdef SLAP_LIGHTWEIGHT_DISPATCHER
 #  define SLAP_SOCK_SET_SUSPEND(s) \
 	( slap_daemon.sd_suspend[SLAP_EPOLL_SOCK_IX(s)] = 1 )
 #  define SLAP_SOCK_CLR_SUSPEND(s) \
 	( slap_daemon.sd_suspend[SLAP_EPOLL_SOCK_IX(s)] = 0 )
 #  define SLAP_SOCK_IS_SUSPEND(s) \
 	( slap_daemon.sd_suspend[SLAP_EPOLL_SOCK_IX(s)] == 1 )
-# endif /* SLAP_LIGHTWEIGHT_DISPATCHER */
 
 # define SLAP_EPOLL_EVENT_CLR(i, mode)	(revents[(i)].events &= ~(mode))
 
@@ -356,14 +354,12 @@ static struct slap_daemon {
 # define SLAP_SOCK_CLR_READ(s)		SLAP_DEVPOLL_SOCK_CLR((s), POLLIN)
 # define SLAP_SOCK_CLR_WRITE(s)		SLAP_DEVPOLL_SOCK_CLR((s), POLLOUT)
 
-# ifdef SLAP_LIGHTWEIGHT_DISPATCHER
 #  define SLAP_SOCK_SET_SUSPEND(s) \
 	( slap_daemon.sd_suspend[SLAP_DEVPOLL_SOCK_IX((s))] = 1 )
 #  define SLAP_SOCK_CLR_SUSPEND(s) \
 	( slap_daemon.sd_suspend[SLAP_DEVPOLL_SOCK_IX((s))] = 0 )
 #  define SLAP_SOCK_IS_SUSPEND(s) \
 	( slap_daemon.sd_suspend[SLAP_DEVPOLL_SOCK_IX((s))] == 1 )
-# endif /* SLAP_LIGHTWEIGHT_DISPATCHER */
 
 # define SLAP_DEVPOLL_EVENT_CLR(i, mode)	(revents[(i)].events &= ~(mode))
 
@@ -704,9 +700,7 @@ slapd_add( ber_socket_t s, int isactive, Listener *sl )
 
 	ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
 
-#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
 	WAKE_LISTENER(1);
-#endif /* SLAP_LIGHTWEIGHT_DISPATCHER */
 }
 
 /*
@@ -1128,9 +1122,7 @@ slap_open_listener(
 
 	l.sl_url.bv_val = NULL;
 	l.sl_mute = 0;
-#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
 	l.sl_busy = 0;
-#endif /* SLAP_LIGHTWEIGHT_DISPATCHER */
 
 #ifndef HAVE_TLS
 	if( ldap_pvt_url_scheme2tls( lud->lud_scheme ) ) {
@@ -1608,13 +1600,11 @@ slap_listener(
 
 	s = accept( sl->sl_sd, (struct sockaddr *) &from, &len );
 
-#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
 	/* Resume the listener FD to allow concurrent-processing of
 	 * additional incoming connections.
 	 */
 	sl->sl_busy = 0;
 	WAKE_LISTENER(1);
-#endif /* SLAP_LIGHTWEIGHT_DISPATCHER */
 
 	if ( s == AC_SOCKET_INVALID ) {
 		int err = sock_errno();
@@ -1844,7 +1834,6 @@ slap_listener(
 	return 0;
 }
 
-#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
 static void*
 slap_listener_thread(
 	void* ctx,
@@ -1885,7 +1874,6 @@ slap_listener_activate(
 	}
 	return rc;
 }
-#endif /* SLAP_LIGHTWEIGHT_DISPATCHER */
 
 static void *
 slapd_daemon_task(
@@ -1972,7 +1960,6 @@ slapd_daemon_task(
 			return (void*)-1;
 		}
 
-#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
 		/* make the listening socket non-blocking */
 		if ( ber_pvt_socket_set_nonblock( slap_listeners[l]->sl_sd, 1 ) < 0 ) {
 			Debug( LDAP_DEBUG_ANY, "slapd_daemon_task: "
@@ -1981,7 +1968,6 @@ slapd_daemon_task(
 			slapd_shutdown = 2;
 			return (void*)-1;
 		}
-#endif /* SLAP_LIGHTWEIGHT_DISPATCHER */
 
 		slapd_add( slap_listeners[l]->sl_sd, 0, slap_listeners[l] );
 	}
@@ -2061,11 +2047,7 @@ slapd_daemon_task(
 
 			if ( lr->sl_sd == AC_SOCKET_INVALID ) continue;
 
-#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
 			if ( lr->sl_mute || lr->sl_busy )
-#else /* ! SLAP_LIGHTWEIGHT_DISPATCHER */
-			if ( lr->sl_mute )
-#endif /* ! SLAP_LIGHTWEIGHT_DISPATCHER */
 			{
 				SLAP_SOCK_CLR_READ( lr->sl_sd );
 			} else {
@@ -2140,7 +2122,6 @@ slapd_daemon_task(
 				continue;
 			}
 
-#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
 			if ( lr->sl_busy ) {
 				Debug( LDAP_DEBUG_CONNS,
 					"daemon: " SLAP_EVENT_FNAME ": "
@@ -2148,7 +2129,6 @@ slapd_daemon_task(
 					lr->sl_sd, 0, 0 );
 				continue;
 			}
-#endif /* SLAP_LIGHTWEIGHT_DISPATCHER */
 
 			Debug( LDAP_DEBUG_CONNS,
 				"daemon: " SLAP_EVENT_FNAME ": "
@@ -2231,11 +2211,7 @@ slapd_daemon_task(
 			SLAP_EVENT_CLR_WRITE( slap_listeners[l]->sl_sd );
 			ns--;
 
-#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
 			rc = slap_listener_activate( slap_listeners[l] );
-#else /* ! SLAP_LIGHTWEIGHT_DISPATCHER */
-			rc = slap_listener( slap_listeners[l] );
-#endif /* ! SLAP_LIGHTWEIGHT_DISPATCHER */
 		}
 
 		/* bypass the following tests if no descriptors left */
@@ -2339,11 +2315,7 @@ slapd_daemon_task(
 			 * active.
 			 */
 
-#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
 			connection_read_activate( rd );
-#else /* ! SLAP_LIGHTWEIGHT_DISPATCHER */
-			connection_read( rd );
-#endif /* ! SLAP_LIGHTWEIGHT_DISPATCHER */
 		}
 #else	/* !SLAP_EVENTS_ARE_INDEXED */
 	/* FIXME */
@@ -2395,11 +2367,7 @@ slapd_daemon_task(
 			int rc = 1, fd;
 
 			if ( SLAP_EVENT_IS_LISTENER( i ) ) {
-#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
 				rc = slap_listener_activate( SLAP_EVENT_LISTENER( i ) );
-#else /* ! SLAP_LIGHTWEIGHT_DISPATCHER */
-				rc = slap_listener( SLAP_EVENT_LISTENER( i ) );
-#endif /* ! SLAP_LIGHTWEIGHT_DISPATCHER */
 			}
 
 			/* If we found a regular listener, rc is now zero, and we
@@ -2441,17 +2409,7 @@ slapd_daemon_task(
 						fd, 0, 0 );
 
 					SLAP_EVENT_CLR_READ( i );
-#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
 					connection_read_activate( fd );
-#else /* ! SLAP_LIGHTWEIGHT_DISPATCHER */
-					/*
-					 * NOTE: it is possible that the connection was closed
-					 * and that the stream is now inactive.
-					 * connection_read() must valid the stream is still
-					 * active.
-					 */
-					connection_read( fd );
-#endif /* ! SLAP_LIGHTWEIGHT_DISPATCHER */
 				} else {
 					Debug( LDAP_DEBUG_CONNS,
 						"daemon: hangup on %d\n", fd, 0, 0 );
diff --git a/servers/slapd/init.c b/servers/slapd/init.c
index 28f30521c6913a6eec4709a5538f39a5f9461421..d1cb5ecc6eabebe18adb2918a263b0f359ff7415 100644
--- a/servers/slapd/init.c
+++ b/servers/slapd/init.c
@@ -67,7 +67,7 @@ int			connection_pool_max = SLAP_MAX_WORKER_THREADS;
 int		slap_tool_thread_max = 1;
 ldap_pvt_thread_mutex_t	gmtime_mutex;
 
-slap_counters_t			slap_counters;
+slap_counters_t			slap_counters, *slap_counters_list;
 
 static const char* slap_name = NULL;
 int slapMode = SLAP_UNDEFINED_MODE;
@@ -76,7 +76,6 @@ int
 slap_init( int mode, const char *name )
 {
 	int rc;
-	int i;
 
 	assert( mode );
 
@@ -144,27 +143,12 @@ slap_init( int mode, const char *name )
 		ldap_pvt_thread_pool_init( &connection_pool,
 				connection_pool_max, 0);
 
-		ldap_pvt_thread_mutex_init( &slap_counters.sc_sent_mutex );
-		ldap_pvt_thread_mutex_init( &slap_counters.sc_ops_mutex );
-		ldap_pvt_mp_init( slap_counters.sc_bytes );
-		ldap_pvt_mp_init( slap_counters.sc_pdu );
-		ldap_pvt_mp_init( slap_counters.sc_entries );
-		ldap_pvt_mp_init( slap_counters.sc_refs );
-
-		ldap_pvt_mp_init( slap_counters.sc_ops_initiated );
-		ldap_pvt_mp_init( slap_counters.sc_ops_completed );
+		slap_counters_init( &slap_counters );
 
 		ldap_pvt_thread_mutex_init( &slapd_rq.rq_mutex );
 		LDAP_STAILQ_INIT( &slapd_rq.task_list );
 		LDAP_STAILQ_INIT( &slapd_rq.run_list );
 
-#ifdef SLAPD_MONITOR
-		for ( i = 0; i < SLAP_OP_LAST; i++ ) {
-			ldap_pvt_mp_init( slap_counters.sc_ops_initiated_[ i ] );
-			ldap_pvt_mp_init( slap_counters.sc_ops_completed_[ i ] );
-		}
-#endif /* SLAPD_MONITOR */
-
 		ldap_pvt_thread_mutex_init( &gmtime_mutex );
 		slap_passwd_init();
 
@@ -264,7 +248,6 @@ int slap_shutdown( Backend *be )
 int slap_destroy(void)
 {
 	int rc;
-	int i;
 
 	Debug( LDAP_DEBUG_TRACE,
 		"%s destroy: freeing system resources.\n",
@@ -288,24 +271,8 @@ int slap_destroy(void)
 
 	switch ( slapMode & SLAP_MODE ) {
 	case SLAP_SERVER_MODE:
-
 	case SLAP_TOOL_MODE:
-
-		ldap_pvt_thread_mutex_destroy( &slap_counters.sc_sent_mutex );
-		ldap_pvt_thread_mutex_destroy( &slap_counters.sc_ops_mutex );
-		ldap_pvt_mp_clear( slap_counters.sc_bytes );
-		ldap_pvt_mp_clear( slap_counters.sc_pdu );
-		ldap_pvt_mp_clear( slap_counters.sc_entries );
-		ldap_pvt_mp_clear( slap_counters.sc_refs );
-		ldap_pvt_mp_clear( slap_counters.sc_ops_initiated );
-		ldap_pvt_mp_clear( slap_counters.sc_ops_completed );
-
-#ifdef SLAPD_MONITOR
-		for ( i = 0; i < SLAP_OP_LAST; i++ ) {
-			ldap_pvt_mp_clear( slap_counters.sc_ops_initiated_[ i ] );
-			ldap_pvt_mp_clear( slap_counters.sc_ops_completed_[ i ] );
-		}
-#endif /* SLAPD_MONITOR */
+		slap_counters_destroy( &slap_counters );
 		break;
 
 	default:
@@ -324,3 +291,46 @@ int slap_destroy(void)
 	/* should destroy the above mutex */
 	return rc;
 }
+
+void slap_counters_init( slap_counters_t *sc )
+{
+	int i;
+
+	ldap_pvt_thread_mutex_init( &sc->sc_mutex );
+	ldap_pvt_mp_init( sc->sc_bytes );
+	ldap_pvt_mp_init( sc->sc_pdu );
+	ldap_pvt_mp_init( sc->sc_entries );
+	ldap_pvt_mp_init( sc->sc_refs );
+
+	ldap_pvt_mp_init( sc->sc_ops_initiated );
+	ldap_pvt_mp_init( sc->sc_ops_completed );
+
+#ifdef SLAPD_MONITOR
+	for ( i = 0; i < SLAP_OP_LAST; i++ ) {
+		ldap_pvt_mp_init( sc->sc_ops_initiated_[ i ] );
+		ldap_pvt_mp_init( sc->sc_ops_completed_[ i ] );
+	}
+#endif /* SLAPD_MONITOR */
+}
+
+void slap_counters_destroy( slap_counters_t *sc )
+{
+	int i;
+
+	ldap_pvt_thread_mutex_destroy( &sc->sc_mutex );
+	ldap_pvt_mp_clear( sc->sc_bytes );
+	ldap_pvt_mp_clear( sc->sc_pdu );
+	ldap_pvt_mp_clear( sc->sc_entries );
+	ldap_pvt_mp_clear( sc->sc_refs );
+
+	ldap_pvt_mp_clear( sc->sc_ops_initiated );
+	ldap_pvt_mp_clear( sc->sc_ops_completed );
+
+#ifdef SLAPD_MONITOR
+	for ( i = 0; i < SLAP_OP_LAST; i++ ) {
+		ldap_pvt_mp_clear( sc->sc_ops_initiated_[ i ] );
+		ldap_pvt_mp_clear( sc->sc_ops_completed_[ i ] );
+	}
+#endif /* SLAPD_MONITOR */
+}
+
diff --git a/servers/slapd/operation.c b/servers/slapd/operation.c
index b5b2f3d1e661b180962917607614e7a74be17893..124a3b85b90b8d2060f9c593fee4216f8b987172 100644
--- a/servers/slapd/operation.c
+++ b/servers/slapd/operation.c
@@ -38,26 +38,27 @@
 #endif
 
 static ldap_pvt_thread_mutex_t	slap_op_mutex;
-static LDAP_STAILQ_HEAD(s_o, Operation)	slap_free_ops;
 static time_t last_time;
 static int last_incr;
 
 void slap_op_init(void)
 {
 	ldap_pvt_thread_mutex_init( &slap_op_mutex );
-	LDAP_STAILQ_INIT(&slap_free_ops);
 }
 
 void slap_op_destroy(void)
 {
-	Operation *o;
+	ldap_pvt_thread_mutex_destroy( &slap_op_mutex );
+}
 
-	while ( (o = LDAP_STAILQ_FIRST( &slap_free_ops )) != NULL) {
-		LDAP_STAILQ_REMOVE_HEAD( &slap_free_ops, o_next );
-		LDAP_STAILQ_NEXT(o, o_next) = NULL;
-		ch_free( o );
+static void
+slap_op_q_destroy( void *key, void *data )
+{
+	Operation *op, *op2;
+	for ( op = data; op; op = op2 ) {
+		op2 = LDAP_STAILQ_NEXT( op, o_next );
+		ber_memfree_x( op, NULL );
 	}
-	ldap_pvt_thread_mutex_destroy( &slap_op_mutex );
 }
 
 void
@@ -72,7 +73,7 @@ slap_op_groups_free( Operation *op )
 }
 
 void
-slap_op_free( Operation *op )
+slap_op_free( Operation *op, void *ctx )
 {
 	OperationBuffer *opbuf;
 
@@ -110,15 +111,22 @@ slap_op_free( Operation *op )
 	}
 #endif /* defined( LDAP_SLAPI ) */
 
-
 	opbuf = (OperationBuffer *) op;
 	memset( opbuf, 0, sizeof(*opbuf) );
 	op->o_hdr = &opbuf->ob_hdr;
 	op->o_controls = opbuf->ob_controls;
 
-	ldap_pvt_thread_mutex_lock( &slap_op_mutex );
-	LDAP_STAILQ_INSERT_HEAD( &slap_free_ops, op, o_next );
-	ldap_pvt_thread_mutex_unlock( &slap_op_mutex );
+	if ( ctx ) {
+		Operation *op2;
+		void *otmp = NULL;
+		ldap_pvt_thread_pool_getkey( ctx, (void *)slap_op_free, &otmp, NULL );
+		op2 = otmp;
+		LDAP_STAILQ_NEXT( op, o_next ) = op2;
+		ldap_pvt_thread_pool_setkey( ctx, (void *)slap_op_free, (void *)op,
+			slap_op_q_destroy );
+	} else {
+		ber_memfree_x( op, NULL );
+	}
 }
 
 void
@@ -141,16 +149,21 @@ slap_op_alloc(
     BerElement		*ber,
     ber_int_t	msgid,
     ber_tag_t	tag,
-    ber_int_t	id )
+    ber_int_t	id,
+	void *ctx )
 {
-	Operation	*op;
-
-	ldap_pvt_thread_mutex_lock( &slap_op_mutex );
-	if ((op = LDAP_STAILQ_FIRST( &slap_free_ops ))) {
-		LDAP_STAILQ_REMOVE_HEAD( &slap_free_ops, o_next );
+	Operation	*op = NULL;
+
+	if ( ctx ) {
+		void *otmp = NULL;
+		ldap_pvt_thread_pool_getkey( ctx, (void *)slap_op_free, &otmp, NULL );
+		if ( otmp ) {
+			op = otmp;
+			otmp = LDAP_STAILQ_NEXT( op, o_next );
+			ldap_pvt_thread_pool_setkey( ctx, (void *)slap_op_free, otmp,
+				slap_op_q_destroy );
+		}
 	}
-	ldap_pvt_thread_mutex_unlock( &slap_op_mutex );
-
 	if (!op) {
 		op = (Operation *) ch_calloc( 1, sizeof(OperationBuffer) );
 		op->o_hdr = &((OperationBuffer *) op)->ob_hdr;
diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h
index fbbc9ae67535995552860bb2163c3f83d278082b..11f05fec56d1c6bdf559a3f0b549bfab003d8ac6 100644
--- a/servers/slapd/proto-slap.h
+++ b/servers/slapd/proto-slap.h
@@ -736,11 +736,7 @@ LDAP_SLAPD_F (int) connection_state_closing LDAP_P(( Connection *c ));
 LDAP_SLAPD_F (const char *) connection_state2str LDAP_P(( int state ))
 	LDAP_GCCATTR((const));
 
-#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
 LDAP_SLAPD_F (int) connection_read_activate LDAP_P((ber_socket_t s));
-#else
-LDAP_SLAPD_F (int) connection_read LDAP_P((ber_socket_t s));
-#endif
 LDAP_SLAPD_F (int) connection_write LDAP_P((ber_socket_t s));
 
 LDAP_SLAPD_F (unsigned long) connections_nextid(void);
@@ -1067,6 +1063,8 @@ LDAP_SLAPD_F (int)	slap_init LDAP_P((int mode, const char* name));
 LDAP_SLAPD_F (int)	slap_startup LDAP_P(( Backend *be ));
 LDAP_SLAPD_F (int)	slap_shutdown LDAP_P(( Backend *be ));
 LDAP_SLAPD_F (int)	slap_destroy LDAP_P((void));
+LDAP_SLAPD_F (void) slap_counters_init LDAP_P((slap_counters_t *sc));
+LDAP_SLAPD_F (void) slap_counters_destroy LDAP_P((slap_counters_t *sc));
 
 LDAP_SLAPD_V (char *)	slap_known_controls[];
 
@@ -1372,11 +1370,11 @@ LDAP_SLAPD_F (int) parse_oidm LDAP_P((
 LDAP_SLAPD_F (void) slap_op_init LDAP_P(( void ));
 LDAP_SLAPD_F (void) slap_op_destroy LDAP_P(( void ));
 LDAP_SLAPD_F (void) slap_op_groups_free LDAP_P(( Operation *op ));
-LDAP_SLAPD_F (void) slap_op_free LDAP_P(( Operation *op ));
+LDAP_SLAPD_F (void) slap_op_free LDAP_P(( Operation *op, void *ctx ));
 LDAP_SLAPD_F (void) slap_op_time LDAP_P(( time_t *t, int *n ));
 LDAP_SLAPD_F (Operation *) slap_op_alloc LDAP_P((
 	BerElement *ber, ber_int_t msgid,
-	ber_tag_t tag, ber_int_t id ));
+	ber_tag_t tag, ber_int_t id, void *ctx ));
 
 LDAP_SLAPD_F (int) slap_op_add LDAP_P(( Operation **olist, Operation *op ));
 LDAP_SLAPD_F (int) slap_op_remove LDAP_P(( Operation **olist, Operation *op ));
diff --git a/servers/slapd/result.c b/servers/slapd/result.c
index c3e3861590b8ac4e02d05487795e89fe5939d0dd..7be8d952494c4f50a856de25e982e7e63e31f708 100644
--- a/servers/slapd/result.c
+++ b/servers/slapd/result.c
@@ -149,7 +149,6 @@ static long send_ldap_ber(
 	/* write the pdu */
 	while( 1 ) {
 		int err;
-		ber_socket_t	sd;
 
 		if ( connection_state_closing( conn ) ) {
 			ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
@@ -184,8 +183,7 @@ static long send_ldap_ber(
 
 		/* wait for socket to be write-ready */
 		conn->c_writewaiter = 1;
-		ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_GET_FD, &sd );
-		slapd_set_write( sd, 1 );
+		slapd_set_write( conn->c_sd, 1 );
 
 		ldap_pvt_thread_cond_wait( &conn->c_write_cv, &conn->c_mutex );
 		conn->c_writewaiter = 0;
@@ -508,10 +506,10 @@ send_ldap_response(
 		goto cleanup;
 	}
 
-	ldap_pvt_thread_mutex_lock( &slap_counters.sc_sent_mutex );
-	ldap_pvt_mp_add_ulong( slap_counters.sc_pdu, 1 );
-	ldap_pvt_mp_add_ulong( slap_counters.sc_bytes, (unsigned long)bytes );
-	ldap_pvt_thread_mutex_unlock( &slap_counters.sc_sent_mutex );
+	ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex );
+	ldap_pvt_mp_add_ulong( op->o_counters->sc_pdu, 1 );
+	ldap_pvt_mp_add_ulong( op->o_counters->sc_bytes, (unsigned long)bytes );
+	ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex );
 
 cleanup:;
 	/* Tell caller that we did this for real, as opposed to being
@@ -1194,11 +1192,11 @@ slap_send_search_entry( Operation *op, SlapReply *rs )
 		}
 		rs->sr_nentries++;
 
-		ldap_pvt_thread_mutex_lock( &slap_counters.sc_sent_mutex );
-		ldap_pvt_mp_add_ulong( slap_counters.sc_bytes, (unsigned long)bytes );
-		ldap_pvt_mp_add_ulong( slap_counters.sc_entries, 1 );
-		ldap_pvt_mp_add_ulong( slap_counters.sc_pdu, 1 );
-		ldap_pvt_thread_mutex_unlock( &slap_counters.sc_sent_mutex );
+		ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex );
+		ldap_pvt_mp_add_ulong( op->o_counters->sc_bytes, (unsigned long)bytes );
+		ldap_pvt_mp_add_ulong( op->o_counters->sc_entries, 1 );
+		ldap_pvt_mp_add_ulong( op->o_counters->sc_pdu, 1 );
+		ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex );
 	}
 
 	Statslog( LDAP_DEBUG_STATS2, "%s ENTRY dn=\"%s\"\n",
@@ -1361,11 +1359,11 @@ slap_send_search_reference( Operation *op, SlapReply *rs )
 	if ( bytes < 0 ) {
 		rc = LDAP_UNAVAILABLE;
 	} else {
-		ldap_pvt_thread_mutex_lock( &slap_counters.sc_sent_mutex );
-		ldap_pvt_mp_add_ulong( slap_counters.sc_bytes, (unsigned long)bytes );
-		ldap_pvt_mp_add_ulong( slap_counters.sc_refs, 1 );
-		ldap_pvt_mp_add_ulong( slap_counters.sc_pdu, 1 );
-		ldap_pvt_thread_mutex_unlock( &slap_counters.sc_sent_mutex );
+		ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex );
+		ldap_pvt_mp_add_ulong( op->o_counters->sc_bytes, (unsigned long)bytes );
+		ldap_pvt_mp_add_ulong( op->o_counters->sc_refs, 1 );
+		ldap_pvt_mp_add_ulong( op->o_counters->sc_pdu, 1 );
+		ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex );
 	}
 #ifdef LDAP_CONNECTIONLESS
 	}
diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h
index eae710d0ce47fe862f5e7591eb49fc83cfccfe93..8e12ed64c6f2224a8c0e9ee9588b631006771800 100644
--- a/servers/slapd/slap.h
+++ b/servers/slapd/slap.h
@@ -58,8 +58,6 @@
 
 LDAP_BEGIN_DECL
 
-#define SLAP_LIGHTWEIGHT_DISPATCHER /* experimental slapd architecture */
-
 #ifdef LDAP_DEVEL
 #define LDAP_COLLECTIVE_ATTRIBUTES
 #define LDAP_COMP_MATCH
@@ -2390,6 +2388,39 @@ struct slap_control_ids {
 	int sc_valuesReturnFilter;
 };
 
+/*
+ * Operation indices
+ */
+typedef enum {
+	SLAP_OP_BIND = 0,
+	SLAP_OP_UNBIND,
+	SLAP_OP_SEARCH,
+	SLAP_OP_COMPARE,
+	SLAP_OP_MODIFY,
+	SLAP_OP_MODRDN,
+	SLAP_OP_ADD,
+	SLAP_OP_DELETE,
+	SLAP_OP_ABANDON,
+	SLAP_OP_EXTENDED,
+	SLAP_OP_LAST
+} slap_op_t;
+
+typedef struct slap_counters_t {
+	struct slap_counters_t	*sc_next;
+	ldap_pvt_thread_mutex_t	sc_mutex;
+	ldap_pvt_mp_t		sc_bytes;
+	ldap_pvt_mp_t		sc_pdu;
+	ldap_pvt_mp_t		sc_entries;
+	ldap_pvt_mp_t		sc_refs;
+
+	ldap_pvt_mp_t		sc_ops_completed;
+	ldap_pvt_mp_t		sc_ops_initiated;
+#ifdef SLAPD_MONITOR
+	ldap_pvt_mp_t		sc_ops_completed_[SLAP_OP_LAST];
+	ldap_pvt_mp_t		sc_ops_initiated_[SLAP_OP_LAST];
+#endif /* SLAPD_MONITOR */
+} slap_counters_t;
+
 /*
  * represents an operation pending from an ldap client
  */
@@ -2407,6 +2438,8 @@ typedef struct Opheader {
 	void	*oh_tmpmemctx;		/* slab malloc context */
 	BerMemoryFunctions *oh_tmpmfuncs;
 
+	slap_counters_t	*oh_counters;
+
 	char		oh_log_prefix[ /* sizeof("conn=18446744073709551615 op=18446744073709551615") */ SLAP_TEXT_BUFLEN ];
 
 #ifdef LDAP_SLAPI
@@ -2439,6 +2472,7 @@ struct Operation {
 #define o_threadctx o_hdr->oh_threadctx
 #define o_tmpmemctx o_hdr->oh_tmpmemctx
 #define o_tmpmfuncs o_hdr->oh_tmpmfuncs
+#define o_counters o_hdr->oh_counters
 
 #define	o_tmpalloc	o_tmpmfuncs->bmf_malloc
 #define o_tmpcalloc	o_tmpmfuncs->bmf_calloc
@@ -2668,6 +2702,7 @@ struct Connection {
 	int			c_struct_state; /* structure management state */
 	int			c_conn_state;	/* connection state */
 	int			c_conn_idx;		/* slot in connections array */
+	ber_socket_t	c_sd;
 	const char	*c_close_reason; /* why connection is closing */
 
 	ldap_pvt_thread_mutex_t	c_mutex; /* protect the connection */
@@ -2685,7 +2720,6 @@ struct Connection {
 #define c_sock_name c_listener->sl_name	/* sock name (trans=addr:port) */
 
 	/* only can be changed by binding thread */
-	int		c_sasl_bind_in_progress;	/* multi-op bind in progress */
 	struct berval	c_sasl_bind_mech;			/* mech in progress */
 	struct berval	c_sasl_dn;	/* temporary storage */
 	struct berval	c_sasl_authz_dn;	/* SASL proxy authz */
@@ -2712,7 +2746,10 @@ struct Connection {
 	ldap_pvt_thread_cond_t	c_write_cv;		/* used to wait for sd write-ready*/
 
 	BerElement	*c_currentber;	/* ber we're attempting to read */
-	int		c_writewaiter;	/* true if writer is waiting */
+
+	char		c_sasl_bind_in_progress;	/* multi-op bind in progress */
+
+	char		c_writewaiter;	/* true if writer is waiting */
 
 #define	CONN_IS_TLS	1
 #define	CONN_IS_UDP	2
@@ -2720,14 +2757,14 @@ struct Connection {
 #define	CONN_IS_IPC	8
 
 #ifdef LDAP_CONNECTIONLESS
-	int	c_is_udp;		/* true if this is (C)LDAP over UDP */
+	char	c_is_udp;		/* true if this is (C)LDAP over UDP */
 #endif
 #ifdef HAVE_TLS
-	int	c_is_tls;		/* true if this LDAP over raw TLS */
-	int	c_needs_tls_accept;	/* true if SSL_accept should be called */
+	char	c_is_tls;		/* true if this LDAP over raw TLS */
+	char	c_needs_tls_accept;	/* true if SSL_accept should be called */
 #endif
-	int		c_sasl_layers;	 /* true if we need to install SASL i/o handlers */
-	int	c_sasl_done;		/* SASL completed once */
+	char	c_sasl_layers;	 /* true if we need to install SASL i/o handlers */
+	char	c_sasl_done;		/* SASL completed once */
 	void	*c_sasl_authctx;	/* SASL authentication context */
 	void	*c_sasl_sockctx;	/* SASL security layer context */
 	void	*c_sasl_extra;		/* SASL session extra stuff */
@@ -2810,47 +2847,12 @@ struct slap_listener {
 	int	sl_is_udp;		/* UDP listener is also data port */
 #endif
 	int	sl_mute;	/* Listener is temporarily disabled due to emfile */
-#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
 	int	sl_busy;	/* Listener is busy (accept thread activated) */
-#endif
 	ber_socket_t sl_sd;
 	Sockaddr sl_sa;
 #define sl_addr	sl_sa.sa_in_addr
 };
 
-/*
- * Operation indices
- */
-typedef enum {
-	SLAP_OP_BIND = 0,
-	SLAP_OP_UNBIND,
-	SLAP_OP_SEARCH,
-	SLAP_OP_COMPARE,
-	SLAP_OP_MODIFY,
-	SLAP_OP_MODRDN,
-	SLAP_OP_ADD,
-	SLAP_OP_DELETE,
-	SLAP_OP_ABANDON,
-	SLAP_OP_EXTENDED,
-	SLAP_OP_LAST
-} slap_op_t;
-
-typedef struct slap_counters_t {
-	ldap_pvt_thread_mutex_t	sc_sent_mutex;
-	ldap_pvt_mp_t		sc_bytes;
-	ldap_pvt_mp_t		sc_pdu;
-	ldap_pvt_mp_t		sc_entries;
-	ldap_pvt_mp_t		sc_refs;
-
-	ldap_pvt_thread_mutex_t	sc_ops_mutex;
-	ldap_pvt_mp_t		sc_ops_completed;
-	ldap_pvt_mp_t		sc_ops_initiated;
-#ifdef SLAPD_MONITOR
-	ldap_pvt_mp_t		sc_ops_completed_[SLAP_OP_LAST];
-	ldap_pvt_mp_t		sc_ops_initiated_[SLAP_OP_LAST];
-#endif /* SLAPD_MONITOR */
-} slap_counters_t;
-
 /*
  * Better know these all around slapd
  */