From 1abb8cb3397c543201a421c5a229304b9d3aded3 Mon Sep 17 00:00:00 2001
From: Pierangelo Masarati <ando@openldap.org>
Date: Fri, 9 Aug 2002 17:15:10 +0000
Subject: [PATCH] rework connection pool handling (reduce amount of malloc)

---
 servers/slapd/back-meta/add.c        |  2 +-
 servers/slapd/back-meta/back-meta.h  |  5 ++-
 servers/slapd/back-meta/bind.c       | 55 ++++++++++++++--------------
 servers/slapd/back-meta/candidates.c |  2 +-
 servers/slapd/back-meta/compare.c    | 31 ++++++++--------
 servers/slapd/back-meta/conn.c       | 34 +++++------------
 servers/slapd/back-meta/delete.c     |  2 +-
 servers/slapd/back-meta/init.c       | 14 +++----
 servers/slapd/back-meta/modify.c     |  2 +-
 servers/slapd/back-meta/modrdn.c     |  4 +-
 servers/slapd/back-meta/search.c     | 38 +++++++++----------
 servers/slapd/back-meta/unbind.c     |  6 +--
 12 files changed, 89 insertions(+), 106 deletions(-)

diff --git a/servers/slapd/back-meta/add.c b/servers/slapd/back-meta/add.c
index 1c87903f45..58555bbdfe 100644
--- a/servers/slapd/back-meta/add.c
+++ b/servers/slapd/back-meta/add.c
@@ -200,7 +200,7 @@ meta_back_add(
 	}
 	attrs[ i ] = NULL;
 
-	ldap_add_s( lc->conns[ candidate ]->ld, mdn.bv_val, attrs );
+	ldap_add_s( lc->conns[ candidate ].ld, mdn.bv_val, attrs );
 	for ( --i; i >= 0; --i ) {
 		free( attrs[ i ]->mod_vals.modv_bvals );
 		free( attrs[ i ] );
diff --git a/servers/slapd/back-meta/back-meta.h b/servers/slapd/back-meta/back-meta.h
index 2862d1c2f8..3bf9285cf0 100644
--- a/servers/slapd/back-meta/back-meta.h
+++ b/servers/slapd/back-meta/back-meta.h
@@ -87,6 +87,7 @@ struct metasingleconn {
 	int			candidate;
 #define	META_NOT_CANDIDATE	0
 #define	META_CANDIDATE		1
+#define	META_LAST_CONN		-1
 	
 	LDAP            	*ld;
 	struct berval          	bound_dn;
@@ -96,6 +97,8 @@ struct metasingleconn {
 #define META_ANONYMOUS		2
 };
 
+#define META_LAST(lsc)		((lsc)->candidate == META_LAST_CONN)
+
 struct metaconn {
 	struct slap_conn	*conn;
 	struct rewrite_info	*rwinfo;
@@ -108,7 +111,7 @@ struct metaconn {
 #define META_BOUND_NONE		-1
 #define META_BOUND_ALL		-2
 	/* supersedes the connection stuff */
-	struct metasingleconn **conns;
+	struct metasingleconn *conns;
 };
 
 struct metatarget {
diff --git a/servers/slapd/back-meta/bind.c b/servers/slapd/back-meta/bind.c
index 1eb07531c3..8735d3e094 100644
--- a/servers/slapd/back-meta/bind.c
+++ b/servers/slapd/back-meta/bind.c
@@ -140,7 +140,7 @@ meta_back_bind(
 		/*
 		 * Skip non-candidates
 		 */
-		if ( lc->conns[ i ]->candidate != META_CANDIDATE ) {
+		if ( lc->conns[ i ].candidate != META_CANDIDATE ) {
 			continue;
 		}
 
@@ -181,7 +181,7 @@ meta_back_bind(
 				realdn, realndn, realcred, realmethod, i );
 		if ( lerr != LDAP_SUCCESS ) {
 			err = lerr;
-			( void )meta_clear_one_candidate( lc->conns[ i ], 1 );
+			( void )meta_clear_one_candidate( &lc->conns[ i ], 1 );
 		} else {
 			rc = LDAP_SUCCESS;
 		}
@@ -263,12 +263,12 @@ meta_back_do_single_bind(
 		return LDAP_OTHER;
 	}
 
-	rc = ldap_bind_s( lc->conns[ candidate ]->ld, mdn.bv_val, cred->bv_val, method );
+	rc = ldap_bind_s( lc->conns[ candidate ].ld, mdn.bv_val, cred->bv_val, method );
 	if ( rc != LDAP_SUCCESS ) {
 		rc = ldap_back_map_result( rc );
 	} else {
-		ber_dupbv( &lc->conns[ candidate ]->bound_dn, dn );
-		lc->conns[ candidate ]->bound = META_BOUND;
+		ber_dupbv( &lc->conns[ candidate ].bound_dn, dn );
+		lc->conns[ candidate ].bound = META_BOUND;
 		lc->bound_target = candidate;
 
 		if ( li->cache.ttl != META_DNCACHE_DISABLED
@@ -291,7 +291,7 @@ meta_back_do_single_bind(
 int
 meta_back_dobind( struct metaconn *lc, Operation *op )
 {
-	struct metasingleconn **lsc;
+	struct metasingleconn *lsc;
 	int bound = 0, i;
 
 	/*
@@ -301,20 +301,20 @@ meta_back_dobind( struct metaconn *lc, Operation *op )
 		return 1;
 	}
 
-	for ( i = 0, lsc = lc->conns; lsc[ 0 ] != NULL; ++i, ++lsc ) {
+	for ( i = 0, lsc = lc->conns; !META_LAST(lsc); ++i, ++lsc ) {
 		int rc;
 
 		/*
 		 * Not a candidate or something wrong with this target ...
 		 */
-		if ( lsc[ 0 ]->ld == NULL ) {
+		if ( lsc->ld == NULL ) {
 			continue;
 		}
 
 		/*
 		 * If the target is already bound it is skipped
 		 */
-		if ( lsc[ 0 ]->bound == META_BOUND && lc->bound_target == i ) {
+		if ( lsc->bound == META_BOUND && lc->bound_target == i ) {
 			++bound;
 			continue;
 		}
@@ -324,12 +324,12 @@ meta_back_dobind( struct metaconn *lc, Operation *op )
 		 * (note: if the target was already bound, the anonymous
 		 * bind clears the previous bind).
 		 */
-		if ( lsc[ 0 ]->bound_dn.bv_val ) {
-			ch_free( lsc[ 0 ]->bound_dn.bv_val );
-			lsc[ 0 ]->bound_dn.bv_val = NULL;
-			lsc[ 0 ]->bound_dn.bv_len = 0;
+		if ( lsc->bound_dn.bv_val ) {
+			ch_free( lsc->bound_dn.bv_val );
+			lsc->bound_dn.bv_val = NULL;
+			lsc->bound_dn.bv_len = 0;
 		}
-		rc = ldap_bind_s( lsc[ 0 ]->ld, 0, NULL, LDAP_AUTH_SIMPLE );
+		rc = ldap_bind_s( lsc->ld, 0, NULL, LDAP_AUTH_SIMPLE );
 		if ( rc != LDAP_SUCCESS ) {
 			
 #ifdef NEW_LOGGING
@@ -337,14 +337,14 @@ meta_back_dobind( struct metaconn *lc, Operation *op )
 					"meta_back_dobind: (anonymous)"
 					" bind as \"%s\" failed"
 					" with error \"%s\"\n",
-					lsc[ 0 ]->bound_dn.bv_val,
+					lsc->bound_dn.bv_val,
 					ldap_err2string( rc ), 0 );
 #else /* !NEW_LOGGING */
 			Debug( LDAP_DEBUG_ANY,
 					"==>meta_back_dobind: (anonymous)"
 					" bind as \"%s\" failed"
 					" with error \"%s\"\n%s",
-					lsc[ 0 ]->bound_dn.bv_val,
+					lsc->bound_dn.bv_val,
 					ldap_err2string( rc ), "" );
 #endif /* !NEW_LOGGING */
 
@@ -355,11 +355,11 @@ meta_back_dobind( struct metaconn *lc, Operation *op )
 			 * due to technical reasons (remote host down?)
 			 * so better clear the handle
 			 */
-			( void )meta_clear_one_candidate( lsc[ 0 ], 1 );
+			( void )meta_clear_one_candidate( lsc, 1 );
 			continue;
 		} /* else */
 		
-		lsc[ 0 ]->bound = META_ANONYMOUS;
+		lsc->bound = META_ANONYMOUS;
 		++bound;
 	}
 
@@ -372,7 +372,7 @@ meta_back_dobind( struct metaconn *lc, Operation *op )
 int
 meta_back_is_valid( struct metaconn *lc, int candidate )
 {
-	struct metasingleconn 	**lsc;
+	struct metasingleconn 	*lsc;
 	int			i;
 
 	assert( lc );
@@ -381,12 +381,11 @@ meta_back_is_valid( struct metaconn *lc, int candidate )
 		return 0;
 	}
 
-	for ( i = 0, lsc = lc->conns; 
-			lsc[ 0 ] != NULL && i < candidate; 
+	for ( i = 0, lsc = lc->conns; !META_LAST(lsc) && i < candidate; 
 			++i, ++lsc );
 	
-	if ( lsc[ 0 ] ) {
-		return( lsc[ 0 ]->ld != NULL );
+	if ( !META_LAST(lsc) ) {
+		return( lsc->ld != NULL );
 	}
 
 	return 0;
@@ -399,16 +398,16 @@ int
 meta_back_op_result( struct metaconn *lc, Operation *op )
 {
 	int i, rerr = LDAP_SUCCESS;
-	struct metasingleconn **lsc;
+	struct metasingleconn *lsc;
 	char *rmsg = NULL;
 	char *rmatch = NULL;
 
-	for ( i = 0, lsc = lc->conns; lsc[ 0 ] != NULL; ++i, ++lsc ) {
+	for ( i = 0, lsc = lc->conns; !META_LAST(lsc); ++i, ++lsc ) {
 		int err = LDAP_SUCCESS;
 		char *msg = NULL;
 		char *match = NULL;
 
-		ldap_get_option( lsc[ 0 ]->ld, LDAP_OPT_ERROR_NUMBER, &err );
+		ldap_get_option( lsc->ld, LDAP_OPT_ERROR_NUMBER, &err );
 		if ( err != LDAP_SUCCESS ) {
 			/*
 			 * better check the type of error. In some cases
@@ -416,9 +415,9 @@ meta_back_op_result( struct metaconn *lc, Operation *op )
 			 * success if at least one of the targets gave
 			 * positive result ...
 			 */
-			ldap_get_option( lsc[ 0 ]->ld,
+			ldap_get_option( lsc->ld,
 					LDAP_OPT_ERROR_STRING, &msg );
-			ldap_get_option( lsc[ 0 ]->ld,
+			ldap_get_option( lsc->ld,
 					LDAP_OPT_MATCHED_DN, &match );
 			err = ldap_back_map_result( err );
 
diff --git a/servers/slapd/back-meta/candidates.c b/servers/slapd/back-meta/candidates.c
index 4fb312dc08..643f78b17c 100644
--- a/servers/slapd/back-meta/candidates.c
+++ b/servers/slapd/back-meta/candidates.c
@@ -214,7 +214,7 @@ meta_clear_unused_candidates(
 		if ( i == candidate ) {
 			continue;
 		}
-		meta_clear_one_candidate( lc->conns[ i ], reallyclean );
+		meta_clear_one_candidate( &lc->conns[ i ], reallyclean );
 	}
 
 	return 0;
diff --git a/servers/slapd/back-meta/compare.c b/servers/slapd/back-meta/compare.c
index fea4dcf9d2..71475fdc39 100644
--- a/servers/slapd/back-meta/compare.c
+++ b/servers/slapd/back-meta/compare.c
@@ -87,7 +87,7 @@ meta_back_compare(
 {
 	struct metainfo	*li = ( struct metainfo * )be->be_private;
 	struct metaconn *lc;
-	struct metasingleconn **lsc;
+	struct metasingleconn *lsc;
 	char *match = NULL, *err = NULL, *mmatch = NULL;
 	int candidates = 0, last = 0, i, count, rc;
        	int cres = LDAP_SUCCESS, rres = LDAP_SUCCESS;
@@ -107,12 +107,12 @@ meta_back_compare(
 	/*
 	 * start an asynchronous compare for each candidate target
 	 */
-	for ( i = 0, lsc = lc->conns; lsc[ 0 ] != NULL; ++i, ++lsc ) {
+	for ( i = 0, lsc = lc->conns; !META_LAST(lsc); ++i, ++lsc ) {
 		char *mdn = NULL;
 		struct berval mapped_attr = ava->aa_desc->ad_cname;
 		struct berval mapped_value = ava->aa_value;
 
-		if ( lsc[ 0 ]->candidate != META_CANDIDATE ) {
+		if ( lsc->candidate != META_CANDIDATE ) {
 			continue;
 		}
 
@@ -158,7 +158,7 @@ meta_back_compare(
 					&ava->aa_value, &mapped_value, 0 );
 
 			if ( mapped_value.bv_val == NULL ) {
-				lsc[ 0 ]->candidate = META_NOT_CANDIDATE;
+				lsc->candidate = META_NOT_CANDIDATE;
 				continue;
 			}
 		/*
@@ -168,7 +168,7 @@ meta_back_compare(
 			ldap_back_map( &li->targets[ i ]->at_map,
 				&ava->aa_desc->ad_cname, &mapped_attr, 0 );
 			if ( mapped_attr.bv_val == NULL ) {
-				lsc[ 0 ]->candidate = META_NOT_CANDIDATE;
+				lsc->candidate = META_NOT_CANDIDATE;
 				continue;
 			}
 		}
@@ -178,10 +178,10 @@ meta_back_compare(
 		 * that returns determines the result; a constraint on unicity
 		 * of the result ought to be enforced
 		 */
-		msgid[ i ] = ldap_compare( lc->conns[ i ]->ld, mdn,
+		msgid[ i ] = ldap_compare( lc->conns[ i ].ld, mdn,
 				mapped_attr.bv_val, mapped_value.bv_val );
 		if ( msgid[ i ] == -1 ) {
-			lsc[ 0 ]->candidate = META_NOT_CANDIDATE;
+			lsc->candidate = META_NOT_CANDIDATE;
 			continue;
 		}
 
@@ -206,15 +206,15 @@ meta_back_compare(
 		/*
 		 * FIXME: should we check for abandon?
 		 */
-		for ( i = 0, lsc = lc->conns; lsc[ 0 ] != NULL; lsc++, i++ ) {
+		for ( i = 0, lsc = lc->conns; !META_LAST(lsc); lsc++, i++ ) {
 			int lrc;
 			LDAPMessage *res = NULL;
 
-			if ( lsc[ 0 ]->candidate != META_CANDIDATE ) {
+			if ( lsc->candidate != META_CANDIDATE ) {
 				continue;
 			}
 
-			lrc = ldap_result( lsc[ 0 ]->ld, msgid[ i ],
+			lrc = ldap_result( lsc->ld, msgid[ i ],
 					0, NULL, &res );
 
 			if ( lrc == 0 ) {
@@ -232,8 +232,7 @@ meta_back_compare(
 					goto finish;
 				}
 				
-				cres = ldap_result2error( lsc[ 0 ]->ld,
-						res, 1 );
+				cres = ldap_result2error( lsc->ld, res, 1 );
 				switch ( cres ) {
 				case LDAP_COMPARE_TRUE:
 				case LDAP_COMPARE_FALSE:
@@ -256,22 +255,22 @@ meta_back_compare(
 					if ( err != NULL ) {
 						free( err );
 					}
-					ldap_get_option( lsc[ 0 ]->ld,
+					ldap_get_option( lsc->ld,
 						LDAP_OPT_ERROR_STRING, &err );
 
 					if ( match != NULL ) {
 						free( match );
 					}
-					ldap_get_option( lsc[ 0 ]->ld,
+					ldap_get_option( lsc->ld,
 						LDAP_OPT_MATCHED_DN, &match );
 					
 					last = i;
 					break;
 				}
-				lsc[ 0 ]->candidate = META_NOT_CANDIDATE;
+				lsc->candidate = META_NOT_CANDIDATE;
 				--candidates;
 			} else {
-				lsc[ 0 ]->candidate = META_NOT_CANDIDATE;
+				lsc->candidate = META_NOT_CANDIDATE;
 				--candidates;
 				if ( res ) {
 					ldap_msgfree( res );
diff --git a/servers/slapd/back-meta/conn.c b/servers/slapd/back-meta/conn.c
index 7eeba85972..249555836e 100644
--- a/servers/slapd/back-meta/conn.c
+++ b/servers/slapd/back-meta/conn.c
@@ -170,7 +170,6 @@ static struct metaconn *
 metaconn_alloc( int ntargets )
 {
 	struct metaconn *lc;
-	int i;
 
 	assert( ntargets > 0 );
 
@@ -182,22 +181,12 @@ metaconn_alloc( int ntargets )
 	/*
 	 * make it a null-terminated array ...
 	 */
-	lc->conns = ch_calloc( sizeof( struct metasingleconn * ), ntargets+1 );
+	lc->conns = ch_calloc( sizeof( struct metasingleconn ), ntargets+1 );
 	if ( lc->conns == NULL ) {
 		free( lc );
 		return NULL;
 	}
-
-	for ( i = 0; i < ntargets; i++ ) {
-		lc->conns[ i ] =
-			ch_calloc( sizeof( struct metasingleconn ), 1 );
-		if ( lc->conns[ i ] == NULL ) {
-			charray_free( ( char ** )lc->conns );
-			free( lc->conns );
-			free( lc );
-			return NULL;
-		}
-	}
+	lc->conns[ ntargets ].candidate = META_LAST_CONN;
 
 	lc->bound_target = META_BOUND_NONE;
 
@@ -219,12 +208,7 @@ metaconn_free(
 	}
 	
 	if ( lc->conns ) {
-		int i;
-
-		for ( i = 0; lc->conns[ i ] != NULL; ++i ) {
-			free( lc->conns[ i ] );
-		}
-		charray_free( ( char ** )lc->conns );
+		ch_free( lc->conns );
 	}
 
 	free( lc );
@@ -422,7 +406,7 @@ meta_back_getconn(
 		 * sends the appropriate result.
 		 */
 		err = init_one_conn( conn, op, li->targets[ i ],
-				vers, lc->conns[ i ] );
+				vers, &lc->conns[ i ] );
 		if ( err != LDAP_SUCCESS ) {
 		
 			/*
@@ -430,7 +414,7 @@ meta_back_getconn(
 			 * be init'd, should the other ones
 			 * be tried?
 			 */
-			( void )meta_clear_one_candidate( lc->conns[ i ], 1 );
+			( void )meta_clear_one_candidate( &lc->conns[ i ], 1 );
 			if ( new_conn ) {
 				metaconn_free( lc );
 			}
@@ -452,7 +436,7 @@ meta_back_getconn(
 			 * also init'd
 			 */
 			int lerr = init_one_conn( conn, op, li->targets[ i ],
-					vers, lc->conns[ i ] );
+					vers, &lc->conns[ i ] );
 			if ( lerr != LDAP_SUCCESS ) {
 				
 				/*
@@ -460,7 +444,7 @@ meta_back_getconn(
 				 * be init'd, should the other ones
 				 * be tried?
 				 */
-				( void )meta_clear_one_candidate( lc->conns[ i ], 1 );
+				( void )meta_clear_one_candidate( &lc->conns[ i ], 1 );
 				err = lerr;
 				continue;
 			}
@@ -480,7 +464,7 @@ meta_back_getconn(
 				 */
 				int lerr = init_one_conn( conn, op,
 						li->targets[ i ],
-						vers, lc->conns[ i ] );
+						vers, &lc->conns[ i ] );
 				if ( lerr != LDAP_SUCCESS ) {
 				
 					/*
@@ -488,7 +472,7 @@ meta_back_getconn(
 					 * be init'd, should the other ones
 					 * be tried?
 					 */
-					( void )meta_clear_one_candidate( lc->conns[ i ], 1 );
+					( void )meta_clear_one_candidate( &lc->conns[ i ], 1 );
 					err = lerr;
 					continue;
 				}
diff --git a/servers/slapd/back-meta/delete.c b/servers/slapd/back-meta/delete.c
index ce268732ed..daeada0ad3 100644
--- a/servers/slapd/back-meta/delete.c
+++ b/servers/slapd/back-meta/delete.c
@@ -127,7 +127,7 @@ meta_back_delete(
 		return -1;
 	}
 	
-	ldap_delete_s( lc->conns[ candidate ]->ld, mdn );
+	ldap_delete_s( lc->conns[ candidate ].ld, mdn );
 
 	if ( mdn != dn->bv_val ) {
 		free( mdn );
diff --git a/servers/slapd/back-meta/init.c b/servers/slapd/back-meta/init.c
index 3f9a9f8964..3ca62e4d52 100644
--- a/servers/slapd/back-meta/init.c
+++ b/servers/slapd/back-meta/init.c
@@ -158,16 +158,16 @@ conn_free(
 	struct metaconn *lc
 )
 {
-	struct metasingleconn **lsc;
+	struct metasingleconn *lsc;
 
-	for ( lsc = lc->conns; lsc[ 0 ] != NULL; lsc++ ) {
-		if ( lsc[ 0 ]->ld != NULL ) {
-			ldap_unbind( lsc[ 0 ]->ld );
+	for ( lsc = lc->conns; !META_LAST(lsc); lsc++ ) {
+		if ( lsc->ld != NULL ) {
+			ldap_unbind( lsc->ld );
 		}
-		if ( lsc[ 0 ]->bound_dn.bv_val ) {
-			ber_memfree( lsc[ 0 ]->bound_dn.bv_val );
+		if ( lsc->bound_dn.bv_val ) {
+			ber_memfree( lsc->bound_dn.bv_val );
 		}
-		free( lsc[ 0 ] );
+		free( lsc );
 	}
 	free( lc->conns );
 	free( lc );
diff --git a/servers/slapd/back-meta/modify.c b/servers/slapd/back-meta/modify.c
index 24013e8a8f..45429332c4 100644
--- a/servers/slapd/back-meta/modify.c
+++ b/servers/slapd/back-meta/modify.c
@@ -200,7 +200,7 @@ meta_back_modify(
 	}
 	modv[ i ] = 0;
 
-	ldap_modify_s( lc->conns[ candidate ]->ld, mdn, modv );
+	ldap_modify_s( lc->conns[ candidate ].ld, mdn, modv );
 
 	if ( mdn != dn->bv_val ) {
 		free( mdn );
diff --git a/servers/slapd/back-meta/modrdn.c b/servers/slapd/back-meta/modrdn.c
index 0f05e4f713..c0f6d1437f 100644
--- a/servers/slapd/back-meta/modrdn.c
+++ b/servers/slapd/back-meta/modrdn.c
@@ -127,7 +127,7 @@ meta_back_modrdn(
 			return -1;
 		}
 
-		ldap_set_option( lc->conns[ nsCandidate ]->ld,
+		ldap_set_option( lc->conns[ nsCandidate ].ld,
 				LDAP_OPT_PROTOCOL_VERSION, &version );
 		
 		/*
@@ -194,7 +194,7 @@ meta_back_modrdn(
 		return -1;
 	}
 
-	ldap_rename2_s( lc->conns[ candidate ]->ld, mdn, newrdn->bv_val,
+	ldap_rename2_s( lc->conns[ candidate ].ld, mdn, newrdn->bv_val,
 			mnewSuperior, deleteoldrdn );
 
 	if ( mdn != dn->bv_val ) {
diff --git a/servers/slapd/back-meta/search.c b/servers/slapd/back-meta/search.c
index 811a51ee42..7d8fc6b7f8 100644
--- a/servers/slapd/back-meta/search.c
+++ b/servers/slapd/back-meta/search.c
@@ -116,7 +116,7 @@ meta_back_search(
 {
 	struct metainfo	*li = ( struct metainfo * )be->be_private;
 	struct metaconn *lc;
-	struct metasingleconn **lsc;
+	struct metasingleconn *lsc;
 	struct timeval	tv;
 	LDAPMessage	*res, *e;
 	int	count, rc = 0, *msgid, sres = LDAP_NO_SUCH_OBJECT;
@@ -195,26 +195,26 @@ meta_back_search(
 	/*
 	 * Inits searches
 	 */
-	for ( i = 0, lsc = lc->conns; lsc[ 0 ] != NULL; ++i, ++lsc ) {
+	for ( i = 0, lsc = lc->conns; !META_LAST(lsc); ++i, ++lsc ) {
 		char 	*realbase = ( char * )base->bv_val;
 		int 	realscope = scope;
 		ber_len_t suffixlen;
 		char	*mapped_filter, **mapped_attrs;
 		
-		if ( lsc[ 0 ]->candidate != META_CANDIDATE ) {
+		if ( lsc->candidate != META_CANDIDATE ) {
 			continue;
 		}
 
 		if ( deref != -1 ) {
-			ldap_set_option( lsc[ 0 ]->ld, LDAP_OPT_DEREF,
+			ldap_set_option( lsc->ld, LDAP_OPT_DEREF,
 					( void * )&deref);
 		}
 		if ( tlimit != -1 ) {
-			ldap_set_option( lsc[ 0 ]->ld, LDAP_OPT_TIMELIMIT,
+			ldap_set_option( lsc->ld, LDAP_OPT_TIMELIMIT,
 					( void * )&tlimit);
 		}
 		if ( slimit != -1 ) {
-			ldap_set_option( lsc[ 0 ]->ld, LDAP_OPT_SIZELIMIT,
+			ldap_set_option( lsc->ld, LDAP_OPT_SIZELIMIT,
 					( void * )&slimit);
 		}
 
@@ -238,7 +238,7 @@ meta_back_search(
 					/*
 					 * this target is no longer candidate
 					 */
-					lsc[ 0 ]->candidate = META_NOT_CANDIDATE;
+					lsc->candidate = META_NOT_CANDIDATE;
 					continue;
 				}
 				break;
@@ -261,7 +261,7 @@ meta_back_search(
 				/*
 				 * this target is no longer candidate
 				 */
-				lsc[ 0 ]->candidate = META_NOT_CANDIDATE;
+				lsc->candidate = META_NOT_CANDIDATE;
 				continue;
 			}
 
@@ -372,10 +372,10 @@ meta_back_search(
 		/*
 		 * Starts the search
 		 */
-		msgid[ i ] = ldap_search( lsc[ 0 ]->ld, mbase, realscope,
+		msgid[ i ] = ldap_search( lsc->ld, mbase, realscope,
 				mapped_filter, mapped_attrs, attrsonly ); 
 		if ( msgid[ i ] == -1 ) {
-			lsc[ 0 ]->candidate = META_NOT_CANDIDATE;
+			lsc->candidate = META_NOT_CANDIDATE;
 			continue;
 		}
 
@@ -410,13 +410,13 @@ meta_back_search(
 		/* check for abandon */
 		ab = op->o_abandon;
 
-		for ( i = 0, lsc = lc->conns; lsc[ 0 ] != NULL; lsc++, i++ ) {
-			if ( lsc[ 0 ]->candidate != META_CANDIDATE ) {
+		for ( i = 0, lsc = lc->conns; !META_LAST(lsc); lsc++, i++ ) {
+			if ( lsc->candidate != META_CANDIDATE ) {
 				continue;
 			}
 			
 			if ( ab ) {
-				ldap_abandon( lsc[ 0 ]->ld, msgid[ i ] );
+				ldap_abandon( lsc->ld, msgid[ i ] );
 				rc = 0;
 				break;
 			}
@@ -428,7 +428,7 @@ meta_back_search(
 				goto finish;
 			}
 
-			rc = ldap_result( lsc[ 0 ]->ld, msgid[ i ],
+			rc = ldap_result( lsc->ld, msgid[ i ],
 					0, &tv, &res );
 
 			if ( rc == 0 ) {
@@ -444,25 +444,25 @@ meta_back_search(
 				/* anything else needs be done? */
 				goto finish;
 			} else if ( rc == LDAP_RES_SEARCH_ENTRY ) {
-				e = ldap_first_entry( lsc[ 0 ]->ld, res );
+				e = ldap_first_entry( lsc->ld, res );
 				meta_send_entry(be, op, lc, i, e, attrs,
 						attrsonly);
 				count++;
 				ldap_msgfree( res );
 				gotit = 1;
 			} else {
-				sres = ldap_result2error( lsc[ 0 ]->ld,
+				sres = ldap_result2error( lsc->ld,
 						res, 1 );
 				sres = ldap_back_map_result( sres );
 				if ( err != NULL ) {
 					free( err );
 				}
-				ldap_get_option( lsc[ 0 ]->ld,
+				ldap_get_option( lsc->ld,
 						LDAP_OPT_ERROR_STRING, &err );
 				if ( match != NULL ) {
 					free( match );
 				}
-				ldap_get_option( lsc[ 0 ]->ld,
+				ldap_get_option( lsc->ld,
 						LDAP_OPT_MATCHED_DN, &match );
 
 #ifdef NEW_LOGGING
@@ -482,7 +482,7 @@ meta_back_search(
 				 * When no candidates are left,
 				 * the outer cycle finishes
 				 */
-				lsc[ 0 ]->candidate = META_NOT_CANDIDATE;
+				lsc->candidate = META_NOT_CANDIDATE;
 				--candidates;
 			}
 		}
diff --git a/servers/slapd/back-meta/unbind.c b/servers/slapd/back-meta/unbind.c
index 84b36adb21..e4f381e988 100644
--- a/servers/slapd/back-meta/unbind.c
+++ b/servers/slapd/back-meta/unbind.c
@@ -117,14 +117,12 @@ meta_back_conn_destroy(
 		 * Cleanup rewrite session
 		 */
 		for ( i = 0; i < li->ntargets; ++i ) {
-			if ( lc->conns[ i ]->ld == NULL ) {
-				free( lc->conns[ i ] );
+			if ( lc->conns[ i ].ld == NULL ) {
 				continue;
 			}
 
 			rewrite_session_delete( li->targets[ i ]->rwinfo, conn );
-			meta_clear_one_candidate( lc->conns[ i ], 1 );
-			free( lc->conns[ i ] );
+			meta_clear_one_candidate( &lc->conns[ i ], 1 );
 		}
 
 		free( lc->conns );
-- 
GitLab