summaryrefslogtreecommitdiffstats
path: root/container-search/src/main/java/com
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@yahoo-inc.com>2016-08-15 11:43:59 +0200
committerJon Bratseth <bratseth@yahoo-inc.com>2016-08-15 11:43:59 +0200
commitbf6ffad296a00eb5e0d130d798d799de28c69b1e (patch)
tree9c05fc7421309f75dd58255d0619ee75b4909f8d /container-search/src/main/java/com
parentf2dfe73196795211900f0d2053af6d6cc7411360 (diff)
Dedupe absolutely identical federation targets
Diffstat (limited to 'container-search/src/main/java/com')
-rw-r--r--container-search/src/main/java/com/yahoo/search/federation/FederationSearcher.java63
-rw-r--r--container-search/src/main/java/com/yahoo/search/federation/selection/FederationTarget.java2
-rw-r--r--container-search/src/main/java/com/yahoo/search/federation/selection/TargetSelector.java2
-rw-r--r--container-search/src/main/java/com/yahoo/search/federation/sourceref/SearchChainInvocationSpec.java34
-rw-r--r--container-search/src/main/java/com/yahoo/search/federation/sourceref/SearchChainResolver.java1
-rw-r--r--container-search/src/main/java/com/yahoo/search/searchchain/model/federation/FederationOptions.java13
6 files changed, 88 insertions, 27 deletions
diff --git a/container-search/src/main/java/com/yahoo/search/federation/FederationSearcher.java b/container-search/src/main/java/com/yahoo/search/federation/FederationSearcher.java
index 2c2264deec9..4f7c4749467 100644
--- a/container-search/src/main/java/com/yahoo/search/federation/FederationSearcher.java
+++ b/container-search/src/main/java/com/yahoo/search/federation/FederationSearcher.java
@@ -63,7 +63,9 @@ public class FederationSearcher extends ForkingSearcher {
public static final String FEDERATION = "Federation";
+ /** A target for federation, containing a chain to which a federation query can be forwarded. */
private static abstract class TargetHandler {
+
abstract Chain<Searcher> getChain();
abstract void modifyTargetQuery(Query query);
abstract void modifyTargetResult(Result result);
@@ -75,13 +77,16 @@ public class FederationSearcher extends ForkingSearcher {
public abstract FederationOptions federationOptions();
@Override
- public String toString() {
- return getChain().getId().stringValue();
- }
+ public String toString() { return getChain().getId().stringValue(); }
}
+ /**
+ * A handler representing a target created by the federation logic.
+ * This is a value object, to ensure that identical target invocations are not invoked multiple times.
+ */
private static class StandardTargetHandler extends TargetHandler {
+
private final SearchChainInvocationSpec target;
private final Chain<Searcher> chain;
@@ -91,9 +96,7 @@ public class FederationSearcher extends ForkingSearcher {
}
@Override
- Chain<Searcher> getChain() {
- return chain;
- }
+ Chain<Searcher> getChain() { return chain; }
@Override
void modifyTargetQuery(Query query) {}
@@ -101,13 +104,27 @@ public class FederationSearcher extends ForkingSearcher {
void modifyTargetResult(Result result) {}
@Override
- public FederationOptions federationOptions() {
- return target.federationOptions;
+ public FederationOptions federationOptions() { return target.federationOptions; }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) return true;
+ if ( ! ( o instanceof StandardTargetHandler)) return false;
+
+ StandardTargetHandler other = (StandardTargetHandler)o;
+ if ( ! other.chain.getId().equals(this.chain.getId())) return false;
+ if ( ! other.target.equals(this.target)) return false;
+ return true;
}
- }
+
+ @Override
+ public int hashCode() { return chain.getId().hashCode() + 11 * target.hashCode(); }
+ }
+ /** A target handler where the target generation logic is delegated to the application provided target selector */
private static class CustomTargetHandler<T> extends TargetHandler {
+
private final TargetSelector<T> selector;
private final FederationTarget<T> target;
@@ -135,18 +152,21 @@ public class FederationSearcher extends ForkingSearcher {
public FederationOptions federationOptions() {
return target.getFederationOptions();
}
+
}
private static class ExecutionInfo {
- final TargetHandler targetHandler;
- final FederationOptions federationOptions;
- final FutureResult futureResult;
+
+ private final TargetHandler targetHandler;
+ private final FederationOptions federationOptions;
+ private final FutureResult futureResult;
public ExecutionInfo(TargetHandler targetHandler, FederationOptions federationOptions, FutureResult futureResult) {
this.targetHandler = targetHandler;
this.federationOptions = federationOptions;
this.futureResult = futureResult;
}
+
}
private static class CompoundKey {
@@ -304,7 +324,7 @@ public class FederationSearcher extends ForkingSearcher {
throw new RuntimeException("Invalid federation config, " + target.id() + " != " + searchChain.searchChainId());
builder.addSearchChain(ComponentId.fromString(searchChain.searchChainId()),
- federationOptions(searchChain), searchChain.documentTypes());
+ federationOptions(searchChain), searchChain.documentTypes());
}
private static void addSourceForProvider(SearchChainResolver.Builder builder, FederationConfig.Target target,
@@ -325,13 +345,13 @@ public class FederationSearcher extends ForkingSearcher {
setRequestTimeoutInMilliseconds(searchChain.requestTimeoutMillis());
}
- private static long calculateTimeout(Query query, List<TargetHandler> targets) {
+ private static long calculateTimeout(Query query, Collection<TargetHandler> targets) {
class PartitionByOptional {
final List<TargetHandler> mandatoryTargets;
final List<TargetHandler> optionalTargets;
- PartitionByOptional(List<TargetHandler> targets) {
+ PartitionByOptional(Collection<TargetHandler> targets) {
List<TargetHandler> mandatoryTargets = new ArrayList<>();
List<TargetHandler> optionalTargets = new ArrayList<>();
@@ -864,10 +884,10 @@ public class FederationSearcher extends ForkingSearcher {
Results<TargetHandler, ErrorMessage> regularTargetHandlers = resolveSearchChains(prunedTargets, execution.searchChainRegistry());
query.errors().addAll(regularTargetHandlers.errors());
- List<TargetHandler> targetHandlers = new ArrayList<>(regularTargetHandlers.data());
+ Set<TargetHandler> targetHandlers = new LinkedHashSet<>(regularTargetHandlers.data());
targetHandlers.addAll(getAdditionalTargets(query, execution, targetSelector));
- final long targetsTimeout = calculateTimeout(query, targetHandlers);
+ long targetsTimeout = calculateTimeout(query, targetHandlers);
if (targetsTimeout < 0)
return new Result(query, ErrorMessage.createTimeout("Timed out when about to federate"));
@@ -875,7 +895,8 @@ public class FederationSearcher extends ForkingSearcher {
if (targetHandlers.size() == 0) {
return mergedResults;
- } else if (targetHandlers.size() == 1 && ! shouldExecuteTargetLongerThanThread(query, targetHandlers.get(0))) {
+ } else if (targetHandlers.size() == 1 &&
+ ! shouldExecuteTargetLongerThanThread(query, targetHandlers.iterator().next())) {
TargetHandler chain = first(targetHandlers);
searchSingleTarget(query, mergedResults, chain, targetsTimeout, execution);
} else {
@@ -885,8 +906,8 @@ public class FederationSearcher extends ForkingSearcher {
return mergedResults;
}
- private void traceTargets(Query query, List<TargetHandler> targetHandlers) {
- final int traceFederationLevel = 2;
+ private void traceTargets(Query query, Collection<TargetHandler> targetHandlers) {
+ int traceFederationLevel = 2;
if ( ! query.isTraceable(traceFederationLevel)) return;
query.trace("Federating to " + targetHandlers, traceFederationLevel);
}
@@ -909,7 +930,7 @@ public class FederationSearcher extends ForkingSearcher {
Chain<Searcher> chain = registry.getChain(target.searchChainId);
if (chain == null) {
targetHandlers.addError(ErrorMessage.createIllegalQuery(
- "Could not find search chain '" + target.searchChainId + "'"));
+ "Could not find search chain '" + target.searchChainId + "'"));
} else {
targetHandlers.addData(new StandardTargetHandler(target, chain));
}
diff --git a/container-search/src/main/java/com/yahoo/search/federation/selection/FederationTarget.java b/container-search/src/main/java/com/yahoo/search/federation/selection/FederationTarget.java
index 676292d6a3a..bcc82e51bb8 100644
--- a/container-search/src/main/java/com/yahoo/search/federation/selection/FederationTarget.java
+++ b/container-search/src/main/java/com/yahoo/search/federation/selection/FederationTarget.java
@@ -16,6 +16,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
* @author tonytv
*/
public final class FederationTarget<T> {
+
private final Chain<Searcher> chain;
private final FederationOptions federationOptions;
private final T customData;
@@ -65,4 +66,5 @@ public final class FederationTarget<T> {
result = 31 * result + federationOptions.hashCode();
return result;
}
+
}
diff --git a/container-search/src/main/java/com/yahoo/search/federation/selection/TargetSelector.java b/container-search/src/main/java/com/yahoo/search/federation/selection/TargetSelector.java
index 0f6bf2d5b71..72de1516e74 100644
--- a/container-search/src/main/java/com/yahoo/search/federation/selection/TargetSelector.java
+++ b/container-search/src/main/java/com/yahoo/search/federation/selection/TargetSelector.java
@@ -21,6 +21,7 @@ import java.util.Collection;
* @author tonytv
*/
public interface TargetSelector<T> {
+
Collection<FederationTarget<T>> getTargets(Query query, ChainRegistry<Searcher> searcherChainRegistry);
/**
@@ -32,4 +33,5 @@ public interface TargetSelector<T> {
* For modifying the result produced by the target.
*/
void modifyTargetResult(FederationTarget<T> target, Result result);
+
}
diff --git a/container-search/src/main/java/com/yahoo/search/federation/sourceref/SearchChainInvocationSpec.java b/container-search/src/main/java/com/yahoo/search/federation/sourceref/SearchChainInvocationSpec.java
index 7e82801d85f..c4d168af085 100644
--- a/container-search/src/main/java/com/yahoo/search/federation/sourceref/SearchChainInvocationSpec.java
+++ b/container-search/src/main/java/com/yahoo/search/federation/sourceref/SearchChainInvocationSpec.java
@@ -1,24 +1,30 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.search.federation.sourceref;
+import com.google.common.collect.ImmutableList;
import com.yahoo.component.ComponentId;
import com.yahoo.search.searchchain.model.federation.FederationOptions;
import java.util.List;
+import java.util.Objects;
/**
* Specifices which search chain should be run and how it should be run.
+ * This is a value object.
*
* @author tonytv
*/
public class SearchChainInvocationSpec implements Cloneable {
+
public final ComponentId searchChainId;
+ /** The source to invoke, or null if none */
public final ComponentId source;
+ /** The provider to invoke, or null if none */
public final ComponentId provider;
public final FederationOptions federationOptions;
- public final List<String> documentTypes;
+ public final ImmutableList<String> documentTypes;
SearchChainInvocationSpec(ComponentId searchChainId,
ComponentId source, ComponentId provider, FederationOptions federationOptions,
@@ -27,11 +33,35 @@ public class SearchChainInvocationSpec implements Cloneable {
this.source = source;
this.provider = provider;
this.federationOptions = federationOptions;
- this.documentTypes = documentTypes;
+ this.documentTypes = ImmutableList.copyOf(documentTypes);
}
@Override
public SearchChainInvocationSpec clone() throws CloneNotSupportedException {
return (SearchChainInvocationSpec)super.clone();
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) return true;
+ if ( ! ( o instanceof SearchChainInvocationSpec)) return false;
+
+ SearchChainInvocationSpec other = (SearchChainInvocationSpec)o;
+ if ( ! Objects.equals(this.searchChainId, other.searchChainId)) return false;
+ if ( ! Objects.equals(this.source, other.source)) return false;
+ if ( ! Objects.equals(this.provider, other.provider)) return false;
+ if ( ! Objects.equals(this.federationOptions, other.federationOptions)) return false;
+ if ( ! Objects.equals(this.documentTypes, other.documentTypes)) return false;
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return searchChainId.hashCode() +
+ (source != null ? 3 * source.hashCode() : 0) +
+ (provider != null ? 5 * provider.hashCode(): 0) +
+ federationOptions.hashCode() +
+ documentTypes.hashCode();
+ }
+
}
diff --git a/container-search/src/main/java/com/yahoo/search/federation/sourceref/SearchChainResolver.java b/container-search/src/main/java/com/yahoo/search/federation/sourceref/SearchChainResolver.java
index fc70fb5e5e7..bdd40ca83f4 100644
--- a/container-search/src/main/java/com/yahoo/search/federation/sourceref/SearchChainResolver.java
+++ b/container-search/src/main/java/com/yahoo/search/federation/sourceref/SearchChainResolver.java
@@ -40,6 +40,7 @@ import java.util.TreeSet;
* @author tonytv
*/
public class SearchChainResolver {
+
private final ComponentRegistry<Target> targets;
private final SortedSet<Target> defaultTargets;
diff --git a/container-search/src/main/java/com/yahoo/search/searchchain/model/federation/FederationOptions.java b/container-search/src/main/java/com/yahoo/search/searchchain/model/federation/FederationOptions.java
index ec6bf9661c6..bf22a309058 100644
--- a/container-search/src/main/java/com/yahoo/search/searchchain/model/federation/FederationOptions.java
+++ b/container-search/src/main/java/com/yahoo/search/searchchain/model/federation/FederationOptions.java
@@ -5,6 +5,7 @@ import net.jcip.annotations.Immutable;
/**
* Options for controlling federation to a single source.
+ * This is a value object.
*
* @author tonytv
*/
@@ -103,13 +104,17 @@ public class FederationOptions implements Cloneable {
@Override
public boolean equals(Object other) {
- return (other instanceof FederationOptions) &&
- equals((FederationOptions) other);
+ return (other instanceof FederationOptions) && equals((FederationOptions) other);
}
-
+
public boolean equals(FederationOptions other) {
return getOptional() == other.getOptional() &&
- getTimeoutInMilliseconds() == other.getTimeoutInMilliseconds();
+ getTimeoutInMilliseconds() == other.getTimeoutInMilliseconds();
+ }
+
+ @Override
+ public int hashCode() {
+ return ( getOptional() ? 1 : 0 ) + 13 * getTimeoutInMilliseconds();
}
@Override