Esempio n. 1
0
/*
 * meta_back_select_unique_candidate
 *
 * returns the index of the candidate in case it is unique, otherwise
 * META_TARGET_NONE if none matches, or
 * META_TARGET_MULTIPLE if more than one matches
 * Note: ndn MUST be normalized.
 */
int
meta_back_select_unique_candidate(
	metainfo_t	*mi,
	struct berval	*ndn )
{
	int	i, candidate = META_TARGET_NONE;

	for ( i = 0; i < mi->mi_ntargets; i++ ) {
		metatarget_t	*mt = mi->mi_targets[ i ];

		if ( meta_back_is_candidate( mt, ndn, LDAP_SCOPE_BASE ) ) {
			if ( candidate == META_TARGET_NONE ) {
				candidate = i;

			} else {
				return META_TARGET_MULTIPLE;
			}
		}
	}

	return candidate;
}
Esempio n. 2
0
/*
 * meta_back_getconn
 * 
 * Prepares the connection structure
 * 
 * FIXME: This function needs to receive some info on the type of operation
 * it is invoked by, so that only the correct pool of candidate targets
 * is initialized in case no connection was available yet.
 * 
 * At present a flag that says whether the candidate target must be unique
 * is passed; eventually an operation agent will be used.
 */
struct metaconn *
meta_back_getconn(
		struct metainfo *li,
	       	Connection 	*conn,
	       	Operation 	*op,
		int 		op_type,
		struct berval	*ndn,
		int 		*candidate )
{
	struct metaconn *lc, lc_curr;
	int cached = -1, i = -1, err = LDAP_SUCCESS;
	int new_conn = 0;

	/* Searches for a metaconn in the avl tree */
	lc_curr.conn = conn;
	ldap_pvt_thread_mutex_lock( &li->conn_mutex );
	lc = (struct metaconn *)avl_find( li->conntree, 
		(caddr_t)&lc_curr, meta_back_conn_cmp );
	ldap_pvt_thread_mutex_unlock( &li->conn_mutex );

	/* Looks like we didn't get a bind. Open a new session... */
	if ( !lc ) {
		lc = metaconn_alloc( li->ntargets );
		lc->conn = conn;
		new_conn = 1;
	}

	/*
	 * looks in cache, if any
	 */
	if ( li->cache.ttl != META_DNCACHE_DISABLED ) {
		cached = i = meta_dncache_get_target( &li->cache, ndn );
	}

	if ( op_type == META_OP_REQUIRE_SINGLE ) {

		/*
		 * tries to get a unique candidate
		 * (takes care of default target 
		 */
		if ( i < 0 ) {
			i = meta_back_select_unique_candidate( li, ndn );
		}

		/*
		 * if any is found, inits the connection
		 */
		if ( i < 0 ) {
			if ( new_conn ) {
				metaconn_free( lc );
			}

			send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
				NULL, "", NULL, NULL );

			return NULL;
		}
				
#ifdef NEW_LOGGING
		LDAP_LOG( BACK_META, INFO,
			"meta_back_getconn: got target %d for ndn=\"%s\" from cache\n", 
			i, ndn->bv_val, 0 );
#else /* !NEW_LOGGING */
		Debug( LDAP_DEBUG_CACHE,
	"==>meta_back_getconn: got target %d for ndn=\"%s\" from cache\n%s",
				i, ndn->bv_val, "" );
#endif /* !NEW_LOGGING */

		/*
		 * Clear all other candidates
		 */
		( void )meta_clear_unused_candidates( li, lc, i, 0 );

		/*
		 * The target is activated; if needed, it is
		 * also init'd. In case of error, init_one_conn
		 * sends the appropriate result.
		 */
		err = init_one_conn( conn, op, li->targets[ i ],
				&lc->conns[ i ] );
		if ( err != LDAP_SUCCESS ) {
		
			/*
			 * FIXME: in case one target cannot
			 * be init'd, should the other ones
			 * be tried?
			 */
			( void )meta_clear_one_candidate( &lc->conns[ i ], 1 );
			if ( new_conn ) {
				metaconn_free( lc );
			}
			return NULL;
		}

		if ( candidate ) {
			*candidate = i;
		}

	/*
	 * require all connections ...
	 */
	} else if (op_type == META_OP_REQUIRE_ALL) {
		for ( i = 0; i < li->ntargets; i++ ) {

			/*
			 * The target is activated; if needed, it is
			 * also init'd
			 */
			int lerr = init_one_conn( conn, op, li->targets[ i ],
					&lc->conns[ i ] );
			if ( lerr != LDAP_SUCCESS ) {
				
				/*
				 * FIXME: in case one target cannot
				 * be init'd, should the other ones
				 * be tried?
				 */
				( void )meta_clear_one_candidate( &lc->conns[ i ], 1 );
				err = lerr;
				continue;
			}
		}

	/*
	 * if no unique candidate ...
	 */
	} else {
		for ( i = 0; i < li->ntargets; i++ ) {
			if ( i == cached 
		|| meta_back_is_candidate( &li->targets[ i ]->suffix, ndn ) ) {

				/*
				 * The target is activated; if needed, it is
				 * also init'd
				 */
				int lerr = init_one_conn( conn, op,
						li->targets[ i ],
						&lc->conns[ i ] );
				if ( lerr != LDAP_SUCCESS ) {
				
					/*
					 * FIXME: in case one target cannot
					 * be init'd, should the other ones
					 * be tried?
					 */
					( void )meta_clear_one_candidate( &lc->conns[ i ], 1 );
					err = lerr;
					continue;
				}
			}
		}
	}

	if ( new_conn ) {
		
		/*
		 * Inserts the newly created metaconn in the avl tree
		 */
		ldap_pvt_thread_mutex_lock( &li->conn_mutex );
		err = avl_insert( &li->conntree, ( caddr_t )lc,
			       	meta_back_conn_cmp, meta_back_conn_dup );

#if PRINT_CONNTREE > 0
		myprint( li->conntree );
#endif /* PRINT_CONNTREE */
		
		ldap_pvt_thread_mutex_unlock( &li->conn_mutex );

#ifdef NEW_LOGGING
		LDAP_LOG( BACK_META, INFO,
			"meta_back_getconn: conn %ld inserted\n", lc->conn->c_connid, 0, 0);
#else /* !NEW_LOGGING */
		Debug( LDAP_DEBUG_TRACE,
			"=>meta_back_getconn: conn %ld inserted\n%s%s",
			lc->conn->c_connid, "", "" );
#endif /* !NEW_LOGGING */
		
		/*
		 * Err could be -1 in case a duplicate metaconn is inserted
		 */
		if ( err != 0 ) {
			send_ldap_result( conn, op, LDAP_OTHER,
			NULL, "Internal server error", NULL, NULL );
			metaconn_free( lc );
			return NULL;
		}
	} else {
#ifdef NEW_LOGGING
		LDAP_LOG( BACK_META, INFO,
			"meta_back_getconn: conn %ld fetched\n", lc->conn->c_connid, 0, 0 );
#else /* !NEW_LOGGING */
		Debug( LDAP_DEBUG_TRACE,
			"=>meta_back_getconn: conn %ld fetched\n%s%s",
			lc->conn->c_connid, "", "" );
#endif /* !NEW_LOGGING */
	}
	
	return lc;
}