diff options
author | Jon Bratseth <bratseth@oath.com> | 2018-04-23 21:07:39 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-23 21:07:39 +0200 |
commit | bbc315437e29723c60d17b7f715a3f11c97d2536 (patch) | |
tree | 518dee932199dcc396ef395cb64317068fb3975c /container-search/src/main/java/com/yahoo/search | |
parent | 60b66c70d7fd7c7f17bb88d6e1fef06d63ea0910 (diff) | |
parent | d43d1012473e54da068d68e7f95719c94ebdb1a4 (diff) |
Merge pull request #5677 from vespa-engine/bratseth/dispatch-summaries-take-5
Bratseth/dispatch summaries take 5
Diffstat (limited to 'container-search/src/main/java/com/yahoo/search')
7 files changed, 43 insertions, 60 deletions
diff --git a/container-search/src/main/java/com/yahoo/search/Searcher.java b/container-search/src/main/java/com/yahoo/search/Searcher.java index 2de9f5e05ee..5fefe9d2468 100644 --- a/container-search/src/main/java/com/yahoo/search/Searcher.java +++ b/container-search/src/main/java/com/yahoo/search/Searcher.java @@ -73,7 +73,6 @@ public abstract class Searcher extends Processor { // Note to developers: If you think you should add something here you are probably wrong // Create a subclass containing the new method instead. - private final Logger logger = Logger.getLogger(getClass().getName()); public Searcher() {} @@ -131,7 +130,7 @@ public abstract class Searcher extends Processor { /** Use the search method in Searcher processors. This forwards to it. */ @Override public final Response process(com.yahoo.processing.Request request, com.yahoo.processing.execution.Execution execution) { - return search((Query)request,(Execution)execution); + return search((Query)request, (Execution)execution); } /** @@ -147,7 +146,7 @@ public abstract class Searcher extends Processor { * @param summaryClass the name of the collection of fields to fetch the values of, or null to use the default */ public void fill(Result result, String summaryClass, Execution execution) { - execution.fill(result,summaryClass); + execution.fill(result, summaryClass); } /** diff --git a/container-search/src/main/java/com/yahoo/search/dispatch/Dispatcher.java b/container-search/src/main/java/com/yahoo/search/dispatch/Dispatcher.java index 1b775d2c46f..c8d8aa961de 100644 --- a/container-search/src/main/java/com/yahoo/search/dispatch/Dispatcher.java +++ b/container-search/src/main/java/com/yahoo/search/dispatch/Dispatcher.java @@ -1,7 +1,6 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.search.dispatch; -import com.google.common.annotations.Beta; import com.google.common.collect.ImmutableMap; import com.yahoo.collections.ListMap; import com.yahoo.component.AbstractComponent; @@ -9,6 +8,7 @@ import com.yahoo.compress.CompressionType; import com.yahoo.compress.Compressor; import com.yahoo.container.handler.VipStatus; import com.yahoo.container.protect.Error; +import com.yahoo.prelude.fastsearch.DocumentDatabase; import com.yahoo.slime.ArrayTraverser; import com.yahoo.data.access.slime.SlimeAdapter; import com.yahoo.prelude.fastsearch.FS4ResourcePool; @@ -22,12 +22,9 @@ import com.yahoo.search.result.Hit; import com.yahoo.data.access.Inspector; import com.yahoo.slime.BinaryFormat; import com.yahoo.slime.Cursor; -import com.yahoo.slime.JsonFormat; import com.yahoo.slime.Slime; import com.yahoo.vespa.config.search.DispatchConfig; -import java.io.ByteArrayOutputStream; -import java.io.IOException; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -38,12 +35,15 @@ import java.util.logging.Level; import java.util.logging.Logger; /** - * A dispatcher communicates with search nodes to (in the future) perform queries and (now) fill hits. + * A dispatcher communicates with search nodes to perform queries and fill hits. + * + * This is currently not functionally complete: Queries can only be dispatched to a single node, + * and summaries can only be requested when they do not need the query. + * * This class is multithread safe. * * @author bratseth */ -@Beta public class Dispatcher extends AbstractComponent { private final static Logger log = Logger.getLogger(Dispatcher.class.getName()); @@ -82,15 +82,20 @@ public class Dispatcher extends AbstractComponent { public SearchCluster searchCluster() { return searchCluster; } /** Fills the given summary class by sending RPC requests to the right search nodes */ - public void fill(Result result, String summaryClass, CompressionType compression) { + public void fill(Result result, String summaryClass, DocumentDatabase documentDb, CompressionType compression) { try { ListMap<Integer, FastHit> hitsByNode = hitsByNode(result); + if (result.getQuery().getTraceLevel() >=3) + result.getQuery().trace("Sending " + hitsByNode.size() + " summary fetch RPC requests", 3); + GetDocsumsResponseReceiver responseReceiver = new GetDocsumsResponseReceiver(hitsByNode.size(), compressor, result); for (Map.Entry<Integer, List<FastHit>> nodeHits : hitsByNode.entrySet()) { sendGetDocsumsRequest(nodeHits.getKey(), nodeHits.getValue(), summaryClass, compression, result, responseReceiver); } - responseReceiver.processResponses(result.getQuery(), summaryClass); + responseReceiver.processResponses(result.getQuery(), summaryClass, documentDb); + result.hits().setSorted(false); + result.analyzeHits(); } catch (TimeoutException e) { result.hits().addError(ErrorMessage.createTimeout("Summary data is incomplete: " + e.getMessage())); @@ -192,7 +197,7 @@ public class Dispatcher extends AbstractComponent { * Call this from the dispatcher thread to initiate and complete processing of responses. * This will block until all responses are available and processed, or to timeout. */ - public void processResponses(Query query, String summaryClass) throws TimeoutException { + public void processResponses(Query query, String summaryClass, DocumentDatabase documentDb) throws TimeoutException { try { int skippedHits = 0; while (outstandingResponses > 0) { @@ -203,11 +208,12 @@ public class Dispatcher extends AbstractComponent { Client.GetDocsumsResponseOrError response = responses.poll(timeLeftMs, TimeUnit.MILLISECONDS); if (response == null) throwTimeout(); - skippedHits += processResponse(response); + skippedHits += processResponse(response, summaryClass, documentDb); outstandingResponses--; } if (skippedHits != 0) { - result.hits().addError(com.yahoo.search.result.ErrorMessage.createEmptyDocsums("Missing hit summary data for summary " + summaryClass + " for " + skippedHits + " hits")); + result.hits().addError(com.yahoo.search.result.ErrorMessage.createEmptyDocsums("Missing hit summary data for summary " + + summaryClass + " for " + skippedHits + " hits")); } } catch (InterruptedException e) { @@ -215,7 +221,9 @@ public class Dispatcher extends AbstractComponent { } } - private int processResponse(Client.GetDocsumsResponseOrError responseOrError) { + private int processResponse(Client.GetDocsumsResponseOrError responseOrError, + String summaryClass, + DocumentDatabase documentDb) { if (responseOrError.error().isPresent()) { if (hasReportedError) return 0; String error = responseOrError.error().get(); @@ -226,7 +234,7 @@ public class Dispatcher extends AbstractComponent { Client.GetDocsumsResponse response = responseOrError.response().get(); CompressionType compression = CompressionType.valueOf(response.compression()); byte[] slimeBytes = compressor.decompress(response.compressedSlimeBytes(), compression, response.uncompressedSize()); - return fill(response.hitsContext(), slimeBytes); + return fill(response.hitsContext(), summaryClass, documentDb, slimeBytes); } return 0; } @@ -241,7 +249,7 @@ public class Dispatcher extends AbstractComponent { }); } - private int fill(List<FastHit> hits, byte[] slimeBytes) { + private int fill(List<FastHit> hits, String summaryClass, DocumentDatabase documentDb, byte[] slimeBytes) { com.yahoo.slime.Inspector root = BinaryFormat.decode(slimeBytes).get(); com.yahoo.slime.Inspector errors = root.field("errors"); boolean hasErrors = errors.valid() && (errors.entries() > 0); @@ -250,13 +258,14 @@ public class Dispatcher extends AbstractComponent { } Inspector summaries = new SlimeAdapter(root.field("docsums")); - if ( ! summaries.valid() && ! hasErrors) - throw new IllegalArgumentException("Expected a Slime root object containing a 'docsums' field"); + if ( ! summaries.valid()) + return 0; // No summaries; Perhaps we requested a non-existing summary class int skippedHits = 0; for (int i = 0; i < hits.size(); i++) { Inspector summary = summaries.entry(i).field("docsum"); if (summary.fieldCount() != 0) { - fill(hits.get(i), summary); + hits.get(i).addSummary(documentDb.getDocsumDefinitionSet().getDocsum(summaryClass), summary); + hits.get(i).setFilled(summaryClass); } else { skippedHits++; } @@ -264,27 +273,6 @@ public class Dispatcher extends AbstractComponent { return skippedHits; } - private void fill(FastHit hit, Inspector summary) { - hit.reserve(summary.fieldCount()); - summary.traverse((String name, Inspector value) -> { - hit.setField(name, nativeTypeOf(value)); - }); - } - - private Object nativeTypeOf(Inspector inspector) { - switch (inspector.type()) { - case ARRAY: return inspector; - case OBJECT: return inspector; - case BOOL: return inspector.asBool(); - case DATA: return inspector.asData(); - case DOUBLE: return inspector.asDouble(); - case LONG: return inspector.asLong(); - case STRING: return inspector.asString(); // TODO: Keep as utf8 - case EMPTY : return null; - default: throw new IllegalArgumentException("Unexpected Slime type " + inspector.type()); - } - } - } } diff --git a/container-search/src/main/java/com/yahoo/search/dispatch/SearchCluster.java b/container-search/src/main/java/com/yahoo/search/dispatch/SearchCluster.java index 60f2691aa69..9b2a24cd01f 100644 --- a/container-search/src/main/java/com/yahoo/search/dispatch/SearchCluster.java +++ b/container-search/src/main/java/com/yahoo/search/dispatch/SearchCluster.java @@ -41,7 +41,6 @@ import java.util.stream.Collectors; * * @author bratseth */ -@Beta public class SearchCluster implements NodeManager<SearchCluster.Node> { private static final Logger log = Logger.getLogger(SearchCluster.class.getName()); diff --git a/container-search/src/main/java/com/yahoo/search/grouping/request/LongValue.java b/container-search/src/main/java/com/yahoo/search/grouping/request/LongValue.java index aa2de1a1298..2f5d833a5be 100644 --- a/container-search/src/main/java/com/yahoo/search/grouping/request/LongValue.java +++ b/container-search/src/main/java/com/yahoo/search/grouping/request/LongValue.java @@ -4,16 +4,17 @@ package com.yahoo.search.grouping.request; /** * This class represents a constant {@link Long} value in a {@link GroupingExpression}. * - * @author <a href="mailto:simon@yahoo-inc.com">Simon Thoresen</a> + * @author Simon Thoresen */ public class LongValue extends ConstantValue<Long> { /** * Constructs a new instance of this class. * - * @param value The immutable value to assign to this. + * @param value the immutable value to assign to this. */ public LongValue(long value) { super(value); } + } diff --git a/container-search/src/main/java/com/yahoo/search/result/Hit.java b/container-search/src/main/java/com/yahoo/search/result/Hit.java index 6adbac56dbe..076e6659d2b 100644 --- a/container-search/src/main/java/com/yahoo/search/result/Hit.java +++ b/container-search/src/main/java/com/yahoo/search/result/Hit.java @@ -89,10 +89,10 @@ public class Hit extends ListenableFreezableClass implements Data, Comparable<Hi * Set to true for hits which does not contain content, * but which contains meta information about the query or result */ - private boolean meta=false; + private boolean meta = false; /** If this is true, then this hit will not be counted as a concrete hit */ - private boolean auxiliary=false; + private boolean auxiliary = false; /** * The hit field used to store rank features. TODO: Remove on Vespa 7 @@ -403,16 +403,13 @@ public class Hit extends ListenableFreezableClass implements Data, Comparable<Hi //TODO Should it be deprecated ? public final Map<String,Object> fields() { return getUnmodifiableFieldMap(); } - /** - * Will preallocate in order to avoid resizing. - * @param minSize The minimum size to reserve - */ + /** Aallocate room for the given number of fields to avoid resizing. */ public void reserve(int minSize) { getFieldMap(minSize); } /** - * Fields + * Returns an iterator over the fields of this * * @return an iterator for traversing the fields of this hit */ @@ -663,9 +660,7 @@ public class Hit extends ListenableFreezableClass implements Data, Comparable<Hi if (p == null) { return null; } else if (p instanceof HitField) { - HitField hf = (HitField) p; - - return hf.quotedContent(false); + return ((HitField)p).quotedContent(false); } else if (p instanceof StructuredData) { return p.toString(); } else if (p instanceof XMLString || p instanceof JSONString) { @@ -743,9 +738,10 @@ public class Hit extends ListenableFreezableClass implements Data, Comparable<Hi } /** - * For vespa internal use only. + * For internal use only. * Gives access to the modifiable backing set of filled summaries. * This set might be unmodifiable if the size is less than or equal to 1 + * * @return the set of filled summaries. */ protected final Set<String> getFilledInternal() { @@ -755,6 +751,7 @@ public class Hit extends ListenableFreezableClass implements Data, Comparable<Hi private Map<String,Object> getFieldMap() { return getFieldMap(16); } + private Map<String,Object> getFieldMap(int minSize) { if (fields == null) { // Compensate for loadfactor and then some, rounded up.... diff --git a/container-search/src/main/java/com/yahoo/search/result/HitGroup.java b/container-search/src/main/java/com/yahoo/search/result/HitGroup.java index 4f4dff6f395..cb3a9abffc4 100644 --- a/container-search/src/main/java/com/yahoo/search/result/HitGroup.java +++ b/container-search/src/main/java/com/yahoo/search/result/HitGroup.java @@ -583,8 +583,7 @@ public class HitGroup extends Hit implements DataList<Hit>, Cloneable, Iterable< Collections.sort(hits); hitsSorted = true; } else { - // This may or may not lead to a sorted result set, but - // it's a best effort + // This may or may not lead to a sorted result set, but it's a best effort hitOrderer.order(hits); if (likelyHitsHaveCorrectValueForSortFields()) { hitsSorted = true; diff --git a/container-search/src/main/java/com/yahoo/search/result/NanNumber.java b/container-search/src/main/java/com/yahoo/search/result/NanNumber.java index 2103583dfa0..078ac04f85e 100644 --- a/container-search/src/main/java/com/yahoo/search/result/NanNumber.java +++ b/container-search/src/main/java/com/yahoo/search/result/NanNumber.java @@ -4,14 +4,14 @@ package com.yahoo.search.result; /** * A class representing unset or undefined numeric values. * - * @author <a href="mailto:steinar@yahoo-inc.com">Steinar Knutsen</a> + * @author Steinar Knutsen */ @SuppressWarnings("serial") public final class NanNumber extends Number { + public static final NanNumber NaN = new NanNumber(); - private NanNumber() { - } + private NanNumber() { } @Override public double doubleValue() { |