search.c

来自「ldap服务器源码」· C语言 代码 · 共 1,963 行 · 第 1/4 页

C
1,963
字号
				ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );				snprintf( buf, sizeof( buf ),					"%s meta_back_search[%ld] mc=%p msgid=%d%s%s%s\n",					op->o_log_prefix, (long)i, (void *)mc,					candidates[ i ].sr_msgid,					META_IS_BINDING( &candidates[ i ] ) ? " binding" : "",					LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] ) ? " connbinding" : "",					META_BACK_CONN_CREATING( &mc->mc_conns[ i ] ) ? " conncreating" : "" );				ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );									Debug( LDAP_DEBUG_ANY, "!!! %s\n", buf, 0, 0 );			}#endif /* DEBUG_205 */						/*			 * FIXME: handle time limit as well?			 * Note that target servers are likely 			 * to handle it, so at some time we'll			 * get a LDAP_TIMELIMIT_EXCEEDED from			 * one of them ...			 */			tv = save_tv;			rc = ldap_result( msc->msc_ld, candidates[ i ].sr_msgid,					LDAP_MSG_RECEIVED, &tv, &res );			switch ( rc ) {			case 0:				/* FIXME: res should not need to be freed */				assert( res == NULL );				continue;			case -1:really_bad:;				/* something REALLY bad happened! */				if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {					candidates[ i ].sr_type = REP_RESULT;					if ( meta_back_retry( op, rs, &mc, i, LDAP_BACK_DONTSEND ) ) {						candidates[ i ].sr_msgid = META_MSGID_IGNORE;						switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates ) )						{							/* means that failed but onerr == continue */						case META_SEARCH_NOT_CANDIDATE:							candidates[ i ].sr_msgid = META_MSGID_IGNORE;							assert( ncandidates > 0 );							--ncandidates;							candidates[ i ].sr_err = rs->sr_err;							if ( META_BACK_ONERR_STOP( mi ) ) {								savepriv = op->o_private;								op->o_private = (void *)i;								send_ldap_result( op, rs );								op->o_private = savepriv;								goto finish;							}							/* fall thru */						case META_SEARCH_CANDIDATE:							/* get back into business... */							continue;						case META_SEARCH_BINDING:						case META_SEARCH_NEED_BIND:						case META_SEARCH_UNDEFINED:							assert( 0 );						default:							/* unrecoverable error */							candidates[ i ].sr_msgid = META_MSGID_IGNORE;							rc = rs->sr_err = LDAP_OTHER;							goto finish;						}					}					candidates[ i ].sr_err = rs->sr_err;					if ( META_BACK_ONERR_STOP( mi ) ) {						savepriv = op->o_private;						op->o_private = (void *)i;						send_ldap_result( op, rs );						op->o_private = savepriv;						goto finish;					}				}				/*				 * When no candidates are left,				 * the outer cycle finishes				 */				candidates[ i ].sr_msgid = META_MSGID_IGNORE;				assert( ncandidates > 0 );				--ncandidates;				rs->sr_err = candidates[ i ].sr_err;				continue;			default:				lastres_time = slap_get_time();				/* only touch when activity actually took place... */				if ( mi->mi_idle_timeout != 0 && msc->msc_time < lastres_time ) {					msc->msc_time = lastres_time;				}				break;			}			for ( msg = ldap_first_message( msc->msc_ld, res );				msg != NULL;				msg = ldap_next_message( msc->msc_ld, msg ) )			{				rc = ldap_msgtype( msg );				if ( rc == LDAP_RES_SEARCH_ENTRY ) {					LDAPMessage	*e;					if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {						/* don't retry any more... */						candidates[ i ].sr_type = REP_RESULT;					}					is_ok++;					e = ldap_first_entry( msc->msc_ld, msg );					savepriv = op->o_private;					op->o_private = (void *)i;					rs->sr_err = meta_send_entry( op, rs, mc, i, e );					switch ( rs->sr_err ) {					case LDAP_SIZELIMIT_EXCEEDED:						savepriv = op->o_private;						op->o_private = (void *)i;						send_ldap_result( op, rs );						op->o_private = savepriv;						rs->sr_err = LDAP_SUCCESS;						ldap_msgfree( res );						res = NULL;						goto finish;					case LDAP_UNAVAILABLE:						rs->sr_err = LDAP_OTHER;						ldap_msgfree( res );						res = NULL;						goto finish;					}					op->o_private = savepriv;					/* don't wait any longer... */					gotit = 1;					save_tv.tv_sec = 0;					save_tv.tv_usec = 0;				} else if ( rc == LDAP_RES_SEARCH_REFERENCE ) {					char		**references = NULL;					int		cnt;					if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {						/* don't retry any more... */						candidates[ i ].sr_type = REP_RESULT;					}						is_ok++;						rc = ldap_parse_reference( msc->msc_ld, msg,							&references, &rs->sr_ctrls, 0 );						if ( rc != LDAP_SUCCESS ) {						continue;					}						if ( references == NULL ) {						continue;					}#ifdef ENABLE_REWRITE					dc.ctx = "referralDN";#else /* ! ENABLE_REWRITE */					dc.tofrom = 0;					dc.normalized = 0;#endif /* ! ENABLE_REWRITE */					/* FIXME: merge all and return at the end */						for ( cnt = 0; references[ cnt ]; cnt++ )						;						rs->sr_ref = ch_calloc( sizeof( struct berval ), cnt + 1 );						for ( cnt = 0; references[ cnt ]; cnt++ ) {						ber_str2bv( references[ cnt ], 0, 1, &rs->sr_ref[ cnt ] );					}					BER_BVZERO( &rs->sr_ref[ cnt ] );						( void )ldap_back_referral_result_rewrite( &dc, rs->sr_ref );					if ( rs->sr_ref != NULL && !BER_BVISNULL( &rs->sr_ref[ 0 ] ) ) {						/* ignore return value by now */						savepriv = op->o_private;						op->o_private = (void *)i;						( void )send_search_reference( op, rs );						op->o_private = savepriv;							ber_bvarray_free( rs->sr_ref );						rs->sr_ref = NULL;					}					/* cleanup */					if ( references ) {						ber_memvfree( (void **)references );					}					if ( rs->sr_ctrls ) {						ldap_controls_free( rs->sr_ctrls );						rs->sr_ctrls = NULL;					}				} else if ( rc == LDAP_RES_SEARCH_RESULT ) {					char		buf[ SLAP_TEXT_BUFLEN ];					char		**references = NULL;					if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {						/* don't retry any more... */						candidates[ i ].sr_type = REP_RESULT;					}						/* NOTE: ignores response controls					 * (and intermediate response controls					 * as well, except for those with search					 * references); this may not be correct,					 * but if they're not ignored then					 * back-meta would need to merge them					 * consistently (think of pagedResults...)					 */					/* FIXME: response controls? */					rs->sr_err = ldap_parse_result( msc->msc_ld,						msg,						&candidates[ i ].sr_err,						(char **)&candidates[ i ].sr_matched,						NULL /* (char **)&candidates[ i ].sr_text */ ,						&references,						NULL /* &candidates[ i ].sr_ctrls (unused) */ ,						0 );					if ( rs->sr_err != LDAP_SUCCESS ) {						ldap_get_option( msc->msc_ld,							LDAP_OPT_ERROR_NUMBER,							&rs->sr_err );						sres = slap_map_api2result( rs );						candidates[ i ].sr_type = REP_RESULT;						ldap_msgfree( res );						res = NULL;						goto really_bad;					}					/* massage matchedDN if need be */					if ( candidates[ i ].sr_matched != NULL ) {						struct berval	match, mmatch;						ber_str2bv( candidates[ i ].sr_matched,							0, 0, &match );						candidates[ i ].sr_matched = NULL;						dc.ctx = "matchedDN";						dc.target = mi->mi_targets[ i ];						if ( !ldap_back_dn_massage( &dc, &match, &mmatch ) ) {							if ( mmatch.bv_val == match.bv_val ) {								candidates[ i ].sr_matched									= ch_strdup( mmatch.bv_val );							} else {								candidates[ i ].sr_matched = mmatch.bv_val;							}							candidate_match++;						} 						ldap_memfree( match.bv_val );					}					/* add references to array */					if ( references ) {						BerVarray	sr_ref;						int		cnt;							for ( cnt = 0; references[ cnt ]; cnt++ )							;							sr_ref = ch_calloc( sizeof( struct berval ), cnt + 1 );							for ( cnt = 0; references[ cnt ]; cnt++ ) {							ber_str2bv( references[ cnt ], 0, 1, &sr_ref[ cnt ] );						}						BER_BVZERO( &sr_ref[ cnt ] );							( void )ldap_back_referral_result_rewrite( &dc, sr_ref );											/* cleanup */						ber_memvfree( (void **)references );							if ( rs->sr_v2ref == NULL ) {							rs->sr_v2ref = sr_ref;						} else {							for ( cnt = 0; !BER_BVISNULL( &sr_ref[ cnt ] ); cnt++ ) {								ber_bvarray_add( &rs->sr_v2ref, &sr_ref[ cnt ] );							}							ber_memfree( sr_ref );						}					}						rs->sr_err = candidates[ i ].sr_err;					sres = slap_map_api2result( rs );						if ( StatslogTest( LDAP_DEBUG_TRACE | LDAP_DEBUG_ANY ) ) {						snprintf( buf, sizeof( buf ),							"%s meta_back_search[%ld] "							"match=\"%s\" err=%ld",							op->o_log_prefix, i,							candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "",							(long) candidates[ i ].sr_err );						if ( candidates[ i ].sr_err == LDAP_SUCCESS ) {							Debug( LDAP_DEBUG_TRACE, "%s.\n", buf, 0, 0 );							} else {							Debug( LDAP_DEBUG_ANY, "%s (%s).\n",								buf, ldap_err2string( candidates[ i ].sr_err ), 0 );						}					}						switch ( sres ) {					case LDAP_NO_SUCH_OBJECT:						/* is_ok is touched any time a valid						 * (even intermediate) result is						 * returned; as a consequence, if						 * a candidate returns noSuchObject						 * it is ignored and the candidate						 * is simply demoted. */						if ( is_ok ) {							sres = LDAP_SUCCESS;						}						break;						case LDAP_SUCCESS:					case LDAP_REFERRAL:						is_ok++;						break;						case LDAP_SIZELIMIT_EXCEEDED:						/* if a target returned sizelimitExceeded						 * and the entry count is equal to the						 * proxy's limit, the target would have						 * returned more, and the error must be						 * propagated to the client; otherwise,						 * the target enforced a limit lower						 * than what requested by the proxy;						 * ignore it */						candidates[ i ].sr_err = rs->sr_err;						if ( rs->sr_nentries == op->ors_slimit							|| META_BACK_ONERR_STOP( mi ) )						{							savepriv = op->o_private;							op->o_private = (void *)i;							send_ldap_result( op, rs );							op->o_private = savepriv;							ldap_msgfree( res );							res = NULL;							goto finish;						}						break;						default:						candidates[ i ].sr_err = rs->sr_err;						if ( META_BACK_ONERR_STOP( mi ) ) {							savepriv = op->o_private;							op->o_private = (void *)i;							send_ldap_result( op, rs );							op->o_private = savepriv;							ldap_msgfree( res );							res = NULL;							goto finish;						}						break;					}						last = i;					rc = 0;						/*					 * When no candidates are left,					 * the outer cycle finishes					 */					candidates[ i ].sr_msgid = META_MSGID_IGNORE;					assert( ncandidates > 0 );					--ncandidates;					} else if ( rc == LDAP_RES_BIND ) {					meta_search_candidate_t	retcode;						retcode = meta_search_dobind_result( op, rs, &mc, i, candidates, msg );					if ( retcode == META_SEARCH_CANDIDATE ) {						candidates[ i ].sr_msgid = META_MSGID_IGNORE;						retcode = meta_back_search_start( op, rs, &dc, &mc, i, candidates );					}						switch ( retcode ) {					case META_SEARCH_CANDIDATE:						break;							/* means that failed but onerr == continue */					case META_SEARCH_NOT_CANDIDATE:					case META_SEARCH_ERR:						candidates[ i ].sr_msgid = META_MSGID_IGNORE;						assert( ncandidates > 0 );						--ncandidates;							candidates[ i ].sr_err = rs->sr_err;						if ( META_BACK_ONERR_STOP( mi ) ) {							savepriv = op->o_private;							op->o_private = (void *)i;							send_ldap_result( op, rs );							op->o_private = savepriv;							ldap_msgfree( res );							res = NULL;							goto finish;						}						goto free_message;						default:						assert( 0 );						break;					}					} else {					assert( 0 );					ldap_msgfree( res );					res = NULL;					goto really_bad;				}			}free_message:;			ldap_msgfree( res );			res = NULL;		}		/* check for abandon */		if ( op->o_abandon || LDAP_BACK_CONN_ABANDON( mc ) ) {			for ( i = 0; i < mi->mi_ntargets; i++ ) {				if ( candidates[ i ].sr_msgid >= 0 ) {					if ( META_IS_BINDING( &candidates[ i ] ) ) {						ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );						if ( LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] ) ) {							/* if still binding, destroy */#ifdef DEBUG_205							char buf[ SLAP_TEXT_BUFLEN ];							snprintf( buf, sizeof( buf), "%s meta_back_search(abandon) "								"ldap_unbind_ext[%ld] mc=%p ld=%p",								op->o_log_prefix, i, (void *)mc,								(void *)mc->mc_conns[i].msc_ld );							Debug( LDAP_DEBUG_ANY, "### %s\n", buf, 0, 0 );#endif /* DEBUG_205 */							meta_clear_one_candidate( op, mc, i );						}						ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );						META_BINDING_CLEAR( &candidates[ i ] );											} else {						(void)meta_back_cancel( mc, op, rs,							candidates[ i ].sr_msgid, i,							LDAP_BACK_DONTSEND );					}					candidates[ i ].sr_msgid = META_MSGID_IGNORE;					assert( ncandidates > 0 );					--ncandidates;				}			}			if ( op->o_abandon ) {				rc = SLAPD_ABANDON;			}			/* let send_ldap_result play cleanup handlers (ITS#4645) */			break;		}		/* if no entry was found during this loop,		 * set a minimal timeout */		if ( ncandidates > 0 && gotit == 0 ) {			if ( save_tv.tv_sec == 0 && save_tv.tv_usec == 0 ) {				save_tv.tv_usec = LDAP_BACK_RESULT_UTIMEOUT/initial_candidates;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?