aboutsummaryrefslogtreecommitdiffstats
path: root/vespaclient-container-plugin/src/main/java/com/yahoo
diff options
context:
space:
mode:
Diffstat (limited to 'vespaclient-container-plugin/src/main/java/com/yahoo')
-rw-r--r--vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/OperationHandler.java12
-rwxr-xr-xvespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/StatusResponse.java65
-rwxr-xr-xvespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerCompatibility.java41
-rwxr-xr-xvespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerGet.java34
-rwxr-xr-xvespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerRemove.java91
-rw-r--r--vespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerRemoveLocation.java91
-rwxr-xr-xvespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerStatus.java89
-rw-r--r--vespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerVisit.java36
-rw-r--r--vespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/package-info.java3
-rwxr-xr-xvespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/ContinuationHit.java31
-rwxr-xr-xvespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/DocumentFieldTemplate.java98
-rwxr-xr-xvespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/DocumentHit.java45
-rw-r--r--vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/DocumentRemoveHit.java23
-rwxr-xr-xvespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/DocumentXMLTemplate.java120
-rwxr-xr-xvespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/GetSearcher.java508
-rwxr-xr-xvespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/MessageBusErrorMessage.java39
-rw-r--r--vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/VisitSearcher.java210
-rw-r--r--vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/package-info.java6
-rw-r--r--vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/FeedHandler.java193
-rw-r--r--vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/Feeder.java537
20 files changed, 2 insertions, 2270 deletions
diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/OperationHandler.java b/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/OperationHandler.java
index f32b3594f28..cfa77455f41 100644
--- a/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/OperationHandler.java
+++ b/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/OperationHandler.java
@@ -31,18 +31,6 @@ public interface OperationHandler {
public final Optional<Integer> concurrency;
public final Optional<String> bucketSpace;
- /** @deprecated Use a VisitOptions.Builder instead */
- // TODO: Remove on Vespa 7
- @Deprecated // OK
- public VisitOptions(Optional<String> cluster, Optional<String> continuation, Optional<Integer> wantedDocumentCount) {
- this.cluster = cluster;
- this.continuation = continuation;
- this.wantedDocumentCount = wantedDocumentCount;
- this.fieldSet = Optional.empty();
- this.concurrency = Optional.empty();
- this.bucketSpace = Optional.empty();
- }
-
private VisitOptions(Builder builder) {
this.cluster = Optional.ofNullable(builder.cluster);
this.continuation = Optional.ofNullable(builder.continuation);
diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/StatusResponse.java b/vespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/StatusResponse.java
deleted file mode 100755
index 365f605688c..00000000000
--- a/vespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/StatusResponse.java
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.feedhandler;
-
-import com.yahoo.container.jdisc.HttpResponse;
-import com.yahoo.metrics.MetricManager;
-import com.yahoo.metrics.MetricSnapshot;
-import com.yahoo.text.Utf8String;
-import com.yahoo.text.XMLWriter;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-
-/**
- * @deprecated Legacy API. Will be removed in Vespa 7
- */
-// TODO: Remove on Vespa 7
-@Deprecated // OK
-public class StatusResponse extends HttpResponse {
-
- MetricManager manager;
- int verbosity;
- int snapshotTime;
-
- StatusResponse(MetricManager manager, int verbosity, int snapshotTime) {
- super(com.yahoo.jdisc.http.HttpResponse.Status.OK);
- this.manager = manager;
- this.snapshotTime = snapshotTime;
- this.verbosity = verbosity;
- }
-
- @Override
- public void render(OutputStream stream) throws IOException {
- XMLWriter writer = new XMLWriter(new OutputStreamWriter(stream));
- writer.openTag("status");
- if (verbosity >= 2) {
- writer.attribute(new Utf8String("description"), "Metrics since start");
- }
-
- if (snapshotTime == 0) {
- MetricSnapshot snapshot = (new MetricSnapshot(
- "Total metrics from start until current time", 0,
- manager.getActiveMetrics().getMetrics(), false));
- manager.getTotalMetricSnapshot().addToSnapshot(snapshot, (int)(System.currentTimeMillis() / 1000), false);
- snapshot.printXml(manager, "", verbosity, writer);
- } else {
- try {
- manager.getMetricSnapshotSet(snapshotTime).getSnapshot().printXml(manager, "", verbosity, writer);
- } catch (Exception e) {
- writer.openTag("error");
- writer.attribute(new Utf8String("details"), "No metric snapshot with period " + snapshotTime +
- " was found. Legal snapshot periods are: " + manager.getSnapshotPeriods());
- writer.closeTag();
- }
- }
- writer.closeTag();
- writer.flush();
- }
-
- @Override
- public java.lang.String getContentType() {
- return "application/xml";
- }
-
-}
diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerCompatibility.java b/vespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerCompatibility.java
deleted file mode 100755
index 8fe721899f9..00000000000
--- a/vespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerCompatibility.java
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.feedhandler;
-
-import java.util.concurrent.Executor;
-import javax.inject.Inject;
-
-import com.yahoo.jdisc.Metric;
-import com.yahoo.container.jdisc.HttpRequest;
-import com.yahoo.container.jdisc.HttpResponse;
-import com.yahoo.container.jdisc.ThreadedHttpRequestHandler;
-
-/**
- * @deprecated Legacy API. Will be removed in Vespa 7
- */
-// TODO: Remove on Vespa 7
-@Deprecated // OK
-public class VespaFeedHandlerCompatibility extends ThreadedHttpRequestHandler {
-
- private final VespaFeedHandlerGet getHandler;
- private final VespaFeedHandler feedHandler;
-
- @Inject
- public VespaFeedHandlerCompatibility(Executor executor, Metric metric, VespaFeedHandlerGet getHandler,
- VespaFeedHandler feedHandler) {
- super(executor, metric);
- this.getHandler = getHandler;
- this.feedHandler = feedHandler;
- }
-
- @Override
- public HttpResponse handle(HttpRequest request) {
- boolean hasType = request.hasProperty("type");
- // If we have an ID and no document type, redirect to Get
- if (request.hasProperty("id") && !hasType) {
- return getHandler.handle(request);
- } else {
- return feedHandler.handle(request);
- }
- }
-
-}
diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerGet.java b/vespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerGet.java
deleted file mode 100755
index ab8728e017b..00000000000
--- a/vespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerGet.java
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.feedhandler;
-
-import java.util.Collections;
-import java.util.concurrent.Executor;
-import javax.inject.Inject;
-
-import com.yahoo.jdisc.Metric;
-import com.yahoo.container.jdisc.HttpRequest;
-import com.yahoo.container.jdisc.HttpResponse;
-import com.yahoo.container.jdisc.ThreadedHttpRequestHandler;
-import com.yahoo.search.handler.SearchHandler;
-
-/**
- * @deprecated Legacy API. Will be removed in Vespa 7
- */
-// TODO: Remove on Vespa 7
-@Deprecated // OK
-public class VespaFeedHandlerGet extends ThreadedHttpRequestHandler {
-
- private final SearchHandler searchHandler;
-
- @Inject
- public VespaFeedHandlerGet(SearchHandler searchHandler, Executor executor, Metric metric) {
- super(executor, metric, true);
- this.searchHandler = searchHandler;
- }
-
- @Override
- public HttpResponse handle(HttpRequest request) {
- return searchHandler.handle(new HttpRequest(request.getJDiscRequest(), request.getData(), Collections.singletonMap("searchChain", "vespaget")));
- }
-
-}
diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerRemove.java b/vespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerRemove.java
deleted file mode 100755
index 9baad1a605d..00000000000
--- a/vespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerRemove.java
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.feedhandler;
-
-import com.google.inject.Inject;
-import com.yahoo.clientmetrics.RouteMetricSet;
-import com.yahoo.cloud.config.ClusterListConfig;
-import com.yahoo.cloud.config.SlobroksConfig;
-import com.yahoo.container.jdisc.HttpRequest;
-import com.yahoo.container.jdisc.HttpResponse;
-import com.yahoo.container.protect.Error;
-import com.yahoo.document.DocumentId;
-import com.yahoo.document.config.DocumentmanagerConfig;
-import com.yahoo.feedapi.FeedContext;
-import com.yahoo.feedapi.MessagePropertyProcessor;
-import com.yahoo.feedapi.SingleSender;
-import com.yahoo.jdisc.Metric;
-import com.yahoo.vespa.config.content.LoadTypeConfig;
-import com.yahoo.vespaclient.config.FeederConfig;
-
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.util.concurrent.Executor;
-
-/**
- * @deprecated Legacy API. Will be removed in Vespa 7
- */
-// TODO: Remove on Vespa 7
-@Deprecated // OK
-public class VespaFeedHandlerRemove extends VespaFeedHandlerBase {
-
- @Inject
- public VespaFeedHandlerRemove(FeederConfig feederConfig,
- LoadTypeConfig loadTypeConfig,
- DocumentmanagerConfig documentmanagerConfig,
- SlobroksConfig slobroksConfig,
- ClusterListConfig clusterListConfig,
- Executor executor,
- Metric metric) throws Exception {
- super(feederConfig, loadTypeConfig, documentmanagerConfig, slobroksConfig, clusterListConfig, executor, metric);
- }
-
- VespaFeedHandlerRemove(FeedContext context, Executor executor) throws Exception {
- super(context, executor);
- }
-
- @Override
- public HttpResponse handle(HttpRequest request) {
- if (request.getProperty("status") != null) {
- return new MetricResponse(context.getMetrics().getMetricSet());
- }
-
- MessagePropertyProcessor.PropertySetter properties = getPropertyProcessor().buildPropertySetter(request);
- String route = properties.getRoute().toString();
- FeedResponse response = new FeedResponse(new RouteMetricSet(route, null));
- SingleSender sender = new SingleSender(response, getSharedSender(route));
- sender.addMessageProcessor(properties);
-
- response.setAbortOnFeedError(properties.getAbortOnFeedError());
-
- if (request.hasProperty("id")) {
- sender.remove(new DocumentId(request.getProperty("id")));
- } else if (request.hasProperty("id[0]")) {
- int index = 0;
- while (request.hasProperty("id[" + index + "]")) {
- sender.remove(new DocumentId(request.getProperty("id[" + index + "]")));
- ++index;
- }
- }
-
- if (request.getData() != null) {
- try {
- String line;
- BufferedReader reader = new BufferedReader(
- new InputStreamReader(getRequestInputStream(request), "UTF-8"));
- while ((line = reader.readLine()) != null) {
- sender.remove(new DocumentId(line));
- }
- } catch (Exception e) {
- response.addError(e.getClass() + ": " + e.getCause());
- }
- }
-
- sender.done();
- long millis = getTimeoutMillis(request);
- boolean completed = sender.waitForPending(millis);
- if ( ! completed)
- response.addError(Error.TIMEOUT, "Timed out after "+millis+" ms waiting for responses");
- return response;
- }
-
-}
diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerRemoveLocation.java b/vespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerRemoveLocation.java
deleted file mode 100644
index 0ca77decf22..00000000000
--- a/vespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerRemoveLocation.java
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.feedhandler;
-
-import com.google.inject.Inject;
-import com.yahoo.clientmetrics.RouteMetricSet;
-import com.yahoo.cloud.config.ClusterListConfig;
-import com.yahoo.cloud.config.SlobroksConfig;
-import com.yahoo.container.jdisc.HttpRequest;
-import com.yahoo.container.jdisc.HttpResponse;
-import com.yahoo.container.protect.Error;
-import com.yahoo.document.config.DocumentmanagerConfig;
-import com.yahoo.documentapi.messagebus.protocol.RemoveLocationMessage;
-import com.yahoo.feedapi.FeedContext;
-import com.yahoo.feedapi.MessagePropertyProcessor;
-import com.yahoo.feedapi.SingleSender;
-import com.yahoo.jdisc.Metric;
-import com.yahoo.messagebus.routing.Route;
-import com.yahoo.vespa.config.content.LoadTypeConfig;
-import com.yahoo.vespaclient.config.FeederConfig;
-
-import java.util.concurrent.Executor;
-
-/**
- * @deprecated Legacy API. Will be removed in Vespa 7
- */
-// TODO: Remove on Vespa 7
-@Deprecated // OK
-public class VespaFeedHandlerRemoveLocation extends VespaFeedHandlerBase {
-
- @Inject
- public VespaFeedHandlerRemoveLocation(FeederConfig feederConfig,
- LoadTypeConfig loadTypeConfig,
- DocumentmanagerConfig documentmanagerConfig,
- SlobroksConfig slobroksConfig,
- ClusterListConfig clusterListConfig,
- Executor executor, Metric metric) throws Exception {
- super(feederConfig, loadTypeConfig, documentmanagerConfig, slobroksConfig, clusterListConfig, executor, metric);
- }
-
- VespaFeedHandlerRemoveLocation(FeedContext context, Executor executor) throws Exception {
- super(context, executor);
- }
-
- @Override
- public HttpResponse handle(HttpRequest request) {
- MessagePropertyProcessor.PropertySetter properties = getPropertyProcessor().buildPropertySetter(request);
- FeedResponse response;
-
- if (request.getProperty("route") == null) {
- if (context.getClusterList().getStorageClusters().size() == 0) {
- return new FeedResponse(null).addError("No storage clusters configured and no alternate route specified.");
- } else if (context.getClusterList().getStorageClusters().size() > 1) {
- return new FeedResponse(null).addError("More than one storage cluster configured and no route specified.");
- } else {
- properties.setRoute(Route.parse(context.getClusterList().getStorageClusters().get(0).getName()));
- }
- }
-
- response = new FeedResponse(new RouteMetricSet(properties.getRoute().toString(), null));
-
- SingleSender sender = new SingleSender(response, getSharedSender(properties.getRoute().toString()));
- sender.addMessageProcessor(properties);
-
- String user = request.getProperty("user");
- String group = request.getProperty("group");
- String selection = request.getProperty("selection");
-
- boolean oneFound = (user != null) ^ (group != null) ^ (selection != null);
-
- if (!oneFound) {
- response.addError("Exactly one of \"user\", \"group\" or \"selection\" must be specified for removelocation");
- return response;
- }
-
- if (user != null) {
- selection = "id.user=" + user;
- }
- if (group != null) {
- selection = "id.group=\"" + group + "\"";
- }
-
- sender.send(new RemoveLocationMessage(selection));
- sender.done();
- long millis = getTimeoutMillis(request);
- boolean completed = sender.waitForPending(millis);
- if ( ! completed)
- response.addError(Error.TIMEOUT, "Timed out after "+millis+" ms waiting for responses");
- return response;
- }
-
-}
diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerStatus.java b/vespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerStatus.java
deleted file mode 100755
index ac16159a9bb..00000000000
--- a/vespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerStatus.java
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.feedhandler;
-
-import java.util.concurrent.Executor;
-
-import com.yahoo.cloud.config.ClusterListConfig;
-import com.yahoo.cloud.config.SlobroksConfig;
-import com.yahoo.container.jdisc.HttpRequest;
-import com.yahoo.container.jdisc.HttpResponse;
-import com.yahoo.container.jdisc.ThreadedHttpRequestHandler;
-import com.yahoo.document.config.DocumentmanagerConfig;
-import com.yahoo.jdisc.Metric;
-import com.yahoo.vespa.config.content.LoadTypeConfig;
-import com.yahoo.feedapi.FeedContext;
-import com.yahoo.metrics.MetricManager;
-import com.yahoo.metrics.MetricSet;
-import com.yahoo.vespaclient.config.FeederConfig;
-
-/**
- * @deprecated Legacy API. Will be removed in Vespa 7
- */
-// TODO: Remove on Vespa 7
-@Deprecated // OK
-public class VespaFeedHandlerStatus extends ThreadedHttpRequestHandler {
-
- private MetricManager manager;
-
- public VespaFeedHandlerStatus(FeederConfig feederConfig,
- LoadTypeConfig loadTypeConfig,
- DocumentmanagerConfig documentmanagerConfig,
- SlobroksConfig slobroksConfig,
- ClusterListConfig clusterListConfig,
- Executor executor,
- Metric metric) {
- this(FeedContext.getInstance(feederConfig, loadTypeConfig,
- documentmanagerConfig, slobroksConfig,
- clusterListConfig, metric),
- true, true, executor);
- }
-
- VespaFeedHandlerStatus(FeedContext context, boolean doLog, boolean makeSnapshots, Executor executor) {
- super(executor);
- manager = new MetricManager();
- final MetricSet metricSet = context.getMetrics().getMetricSet();
- metricSet.unregister();
- manager.registerMetric(metricSet);
- if (doLog) {
- manager.addMetricToConsumer("log", "routes.total.putdocument.count");
- manager.addMetricToConsumer("log", "routes.total.removedocument.count");
- manager.addMetricToConsumer("log", "routes.total.updatedocument.count");
- manager.addMetricToConsumer("log", "routes.total.getdocument.count");
-
- manager.addMetricToConsumer("log", "routes.total.putdocument.errors.total");
- manager.addMetricToConsumer("log", "routes.total.removedocument.errors.total");
- manager.addMetricToConsumer("log", "routes.total.updatedocument.errors.total");
- manager.addMetricToConsumer("log", "routes.total.getdocument.errors.total");
-
- manager.addMetricToConsumer("log", "routes.total.putdocument.latency");
- manager.addMetricToConsumer("log", "routes.total.removedocument.latency");
- manager.addMetricToConsumer("log", "routes.total.updatedocument.latency");
- manager.addMetricToConsumer("log", "routes.total.getdocument.latency");
- }
-
- if (doLog || makeSnapshots) {
- new Thread(manager).start();
- }
- }
-
- @Override
- public HttpResponse handle(HttpRequest request) {
- try {
- return new StatusResponse(manager, asInt(request.getProperty("verbosity"), 0), asInt(request.getProperty("snapshotperiod"), 0));
- } catch (Exception e) {
- e.printStackTrace();
- return null;
- }
- }
-
- private int asInt(String value, int defaultValue) {
- if (value == null) return defaultValue;
- return Integer.parseInt(value);
- }
-
- @Override
- public void destroy() {
- manager.stop();
- }
-
-}
diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerVisit.java b/vespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerVisit.java
deleted file mode 100644
index b73ea455c32..00000000000
--- a/vespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerVisit.java
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.feedhandler;
-
-import java.util.Collections;
-import java.util.concurrent.Executor;
-import javax.inject.Inject;
-
-import com.yahoo.jdisc.Metric;
-import com.yahoo.container.jdisc.HttpRequest;
-import com.yahoo.container.jdisc.HttpResponse;
-import com.yahoo.container.jdisc.ThreadedHttpRequestHandler;
-import com.yahoo.search.handler.SearchHandler;
-
-/**
- * @author thomasg
- *
- * @deprecated Legacy API. Will be removed in Vespa 7
- */
-// TODO: Remove on Vespa 7
-@Deprecated // OK
-public class VespaFeedHandlerVisit extends ThreadedHttpRequestHandler {
-
- private final SearchHandler searchHandler;
-
- @Inject
- public VespaFeedHandlerVisit(SearchHandler searchHandler, Executor executor, Metric metric) {
- super(executor, metric, true);
- this.searchHandler = searchHandler;
- }
-
- @Override
- public HttpResponse handle(HttpRequest request) {
- return searchHandler.handle(new HttpRequest(request.getJDiscRequest(), request.getData(), Collections.singletonMap("searchChain", "vespavisit")));
- }
-
-}
diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/package-info.java b/vespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/package-info.java
deleted file mode 100644
index 857e7127b6f..00000000000
--- a/vespaclient-container-plugin/src/main/java/com/yahoo/feedhandler/package-info.java
+++ /dev/null
@@ -1,3 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-// TODO: This implements the old, deprecated document http API. Remove this package on Vespa 7.
-package com.yahoo.feedhandler;
diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/ContinuationHit.java b/vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/ContinuationHit.java
deleted file mode 100755
index c66af4f02ba..00000000000
--- a/vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/ContinuationHit.java
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.storage.searcher;
-
-import com.yahoo.documentapi.ProgressToken;
-import com.yahoo.search.result.Hit;
-import java.io.IOException;
-import java.util.Base64;
-
-/**
- * @deprecated
- */
-@Deprecated // OK
-// TODO: Remove on Vespa 7
-public class ContinuationHit extends Hit {
-
- private final String value;
-
- public ContinuationHit(ProgressToken token) {
- super("continuation");
- value = token.serializeToString();
- }
-
- public static ProgressToken getToken(String continuation) {
- return ProgressToken.fromSerializedString(continuation);
- }
-
- public String getValue() {
- return value;
- }
-
-}
diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/DocumentFieldTemplate.java b/vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/DocumentFieldTemplate.java
deleted file mode 100755
index cf35c789f65..00000000000
--- a/vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/DocumentFieldTemplate.java
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.storage.searcher;
-
-import com.yahoo.document.DataType;
-import com.yahoo.document.Document;
-import com.yahoo.document.Field;
-import com.yahoo.document.datatypes.FieldValue;
-import com.yahoo.document.datatypes.Raw;
-import com.yahoo.io.ByteWriter;
-import com.yahoo.text.XML;
-
-import java.io.IOException;
-import java.io.Writer;
-
-/**
- * Template used to render a single field for a single Document. Fields
- * that are either of type CONTENT or RAW are written directly, while
- * all other fields are wrapped in Vespa XML and escaped.
- *
- * @deprecated use a renderer instead
- */
-@Deprecated // OK
-// TODO: Remove on Vespa 7
-@SuppressWarnings("deprecation")
-public class DocumentFieldTemplate extends com.yahoo.prelude.templates.UserTemplate<Writer> {
-
- Field field;
- String contentType;
- String encoding;
- boolean wrapXml;
-
- public DocumentFieldTemplate(Field field, String contentType, String encoding, boolean wrapXml) {
- super("documentfield", contentType, encoding);
- this.field = field;
- this.contentType = contentType;
- this.encoding = encoding;
- this.wrapXml = wrapXml;
- }
-
- @Override
- public void error(com.yahoo.prelude.templates.Context context, Writer writer) throws IOException {
- // Error shouldn't be handled by this template, but rather
- // delegated to the searcher
- }
-
- @Override
- public Writer wrapWriter(Writer writer) {
- /* TODO: uncomment
- if (!(writer instanceof ByteWriter)) {
- throw new IllegalArgumentException("ByteWriter required, but got " + writer.getClass().getName());
- }
- */
-
- return writer;
- }
-
- @Override
- public void header(com.yahoo.prelude.templates.Context context, Writer writer) throws IOException {
- if (wrapXml) {
- // XML wrapping should only be used for default field rendering
- writer.write("<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>\n");
- writer.write("<result>");
- }
- }
-
- @Override
- public void footer(com.yahoo.prelude.templates.Context context, Writer writer) throws IOException {
- if (wrapXml) {
- writer.write("</result>\n");
- }
- }
-
- @Override
- public void hit(com.yahoo.prelude.templates.Context context, Writer writer) throws IOException {
- DocumentHit hit = (DocumentHit)context.get("hit");
- Document doc = hit.getDocument();
- // Assume field existence has been checked before we ever get here.
- // Also assume that relevant encoding/content type is set
- // appropriately according to the request and the field's content
- // type, as this is immutable in the template set.
- FieldValue value = doc.getFieldValue(field);
- if (field.getDataType() == DataType.RAW) {
- ByteWriter bw = (ByteWriter)writer;
- bw.append(((Raw) value).getByteBuffer().array());
- } else {
- writer.write(XML.xmlEscape(value.toString(), false));
- }
- }
-
- @Override
- public void hitFooter(com.yahoo.prelude.templates.Context context, Writer writer) throws IOException {
- }
-
- @Override
- public void noHits(com.yahoo.prelude.templates.Context context, Writer writer) throws IOException {
- }
-
-}
diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/DocumentHit.java b/vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/DocumentHit.java
deleted file mode 100755
index 514cf055e84..00000000000
--- a/vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/DocumentHit.java
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.storage.searcher;
-
-import com.yahoo.document.Document;
-import com.yahoo.document.Field;
-import com.yahoo.document.datatypes.FieldValue;
-import com.yahoo.search.result.Hit;
-
-import java.util.Iterator;
-import java.util.Map;
-
-@Deprecated // OK
-// TODO: Remove on Vespa 7
-public class DocumentHit extends Hit {
-
- private Document document;
- private int index;
-
- public DocumentHit(Document document, int index) {
- super(document.getId().toString());
- this.document = document;
- this.index = index;
- }
-
- public void populateHitFields() {
- // Create hit fields for all document fields
- Iterator<Map.Entry<Field, FieldValue>> fieldIter = document.iterator();
- while (fieldIter.hasNext()) {
- Map.Entry<Field, FieldValue> field = fieldIter.next();
- setField(field.getKey().getName(), field.getValue());
- }
-
- // Assign an explicit document id field
- setField("documentid", document.getId().toString());
- }
-
- public Document getDocument() {
- return document;
- }
-
- public int getIndex() {
- return index;
- }
-
-}
diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/DocumentRemoveHit.java b/vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/DocumentRemoveHit.java
deleted file mode 100644
index 73363e68e2b..00000000000
--- a/vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/DocumentRemoveHit.java
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.storage.searcher;
-
-import com.yahoo.document.DocumentId;
-import com.yahoo.search.result.Hit;
-
-@Deprecated // OK
-// TODO: Remove on Vespa 7
-public class DocumentRemoveHit extends Hit {
-
- private final DocumentId idOfRemovedDoc;
-
- public DocumentRemoveHit(DocumentId idOfRemovedDoc) {
- super(idOfRemovedDoc.toString());
- this.idOfRemovedDoc = idOfRemovedDoc;
- setField("documentid", idOfRemovedDoc.toString());
- }
-
- public DocumentId getIdOfRemovedDoc() {
- return idOfRemovedDoc;
- }
-
-}
diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/DocumentXMLTemplate.java b/vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/DocumentXMLTemplate.java
deleted file mode 100755
index 2366e7059bd..00000000000
--- a/vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/DocumentXMLTemplate.java
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.storage.searcher;
-
-import com.yahoo.log.LogLevel;
-import com.yahoo.search.Result;
-import com.yahoo.search.result.ErrorHit;
-import com.yahoo.search.result.ErrorMessage;
-import com.yahoo.search.result.HitGroup;
-import com.yahoo.search.result.Hit;
-import com.yahoo.text.XML;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.util.logging.Logger;
-
-/**
- * @deprecated use a renderer instead
- */
-@Deprecated // OK
-// TODO: Remove on Vespa 7
-@SuppressWarnings("deprecation")
-public class DocumentXMLTemplate extends com.yahoo.prelude.templates.UserTemplate<Writer> {
-
- private static final Logger log = Logger.getLogger(DocumentXMLTemplate.class.getName());
-
- public DocumentXMLTemplate() {
- super("vespa_xml");
- }
-
- public DocumentXMLTemplate(String mimeType, String encoding) {
- super("vespa_xml", mimeType, encoding);
- }
-
- private void writeErrorMessage(Writer writer, String type, int code,
- String message, String detailedMessage) throws IOException {
- writer.write("<error type=\"" + type + "\" code=\"" + code + "\" message=\"");
- writer.write(XML.xmlEscape(message, true));
- if (detailedMessage != null) {
- writer.write(": ");
- writer.write(XML.xmlEscape(detailedMessage, true));
- }
- writer.write("\"/>\n");
- }
-
- private void writeGenericErrorMessage(Writer writer, ErrorMessage message) throws IOException {
- // A bit dirty, but we don't have to support many different types
- if (message instanceof MessageBusErrorMessage) {
- writeErrorMessage(writer, "messagebus",
- ((MessageBusErrorMessage)message).getMessageBusCode(),
- message.getMessage(), message.getDetailedMessage());
- } else {
- writeErrorMessage(writer, "searcher", message.getCode(),
- message.getMessage(), message.getDetailedMessage());
- }
- }
-
- @Override
- public void error(com.yahoo.prelude.templates.Context context, Writer writer) throws IOException {
- writer.write("<errors>\n");
- // If the error contains no error hits, use a single error with the main
- // code and description. Otherwise, use the error hits explicitly
- ErrorHit errorHit = ((Result)context.get("result")).hits().getErrorHit();
- if (errorHit == null || errorHit.errors().isEmpty()) {
- ErrorMessage message = ((Result)context.get("result")).hits().getError();
- writeGenericErrorMessage(writer, message);
- } else {
- for (ErrorMessage message : errorHit.errors()) {
- writeGenericErrorMessage(writer, message);
- }
- }
- writer.write("</errors>\n");
- }
-
- @Override
- public void header(com.yahoo.prelude.templates.Context context, Writer writer) throws IOException {
- writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
- writer.write("<result>\n");
- HitGroup rootGroup = ((Result) context.get("result")).hits();
- if (rootGroup.getField(VisitSearcher.VISITOR_CONTINUATION_TOKEN_FIELDNAME) != null) {
- writer.write("<continuation>" + rootGroup.getField(VisitSearcher.VISITOR_CONTINUATION_TOKEN_FIELDNAME) + "</continuation>");
- }
- }
-
- @Override
- public void footer(com.yahoo.prelude.templates.Context context, Writer writer) throws IOException {
- writer.write("</result>\n");
- }
-
- @Override
- public void hit(com.yahoo.prelude.templates.Context context, Writer writer) throws IOException {
- Hit hit = (Hit)context.get("hit");
- if (hit instanceof DocumentHit) {
- DocumentHit docHit = (DocumentHit) hit;
- if (docHit.getDocument() != null) {
- writer.write(docHit.getDocument().toXML(" "));
- }
- } else if (hit instanceof DocumentRemoveHit) {
- writeDocumentRemoveHit(writer, (DocumentRemoveHit) hit);
- } else {
- log.log(LogLevel.WARNING, "Cannot render document XML; expected hit of type " +
- "com.yahoo.storage.searcher.Document[Remove]Hit, got " + hit.getClass().getName() +
- ". Is there another backend searcher present?");
- }
- }
-
- private void writeDocumentRemoveHit(Writer writer, DocumentRemoveHit remove) throws IOException {
- writer.write("<remove documentid=\"");
- writer.write(XML.xmlEscape(remove.getIdOfRemovedDoc().toString()));
- writer.write("\"/>\n");
- }
-
- @Override
- public void hitFooter(com.yahoo.prelude.templates.Context context, Writer writer) throws IOException {
- }
-
- @Override
- public void noHits(com.yahoo.prelude.templates.Context context, Writer writer) throws IOException {
- }
-
-}
diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/GetSearcher.java b/vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/GetSearcher.java
deleted file mode 100755
index 869a2f9317a..00000000000
--- a/vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/GetSearcher.java
+++ /dev/null
@@ -1,508 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.storage.searcher;
-
-import com.google.inject.Inject;
-import com.yahoo.cloud.config.ClusterListConfig;
-import com.yahoo.cloud.config.SlobroksConfig;
-import com.yahoo.container.jdisc.HttpRequest;
-import com.yahoo.document.config.DocumentmanagerConfig;
-import com.yahoo.jdisc.Metric;
-import com.yahoo.processing.request.CompoundName;
-import com.yahoo.vespa.config.content.LoadTypeConfig;
-import com.yahoo.document.DataType;
-import com.yahoo.document.Document;
-import com.yahoo.document.DocumentId;
-import com.yahoo.document.Field;
-import com.yahoo.document.datatypes.FieldValue;
-import com.yahoo.documentapi.messagebus.protocol.GetDocumentMessage;
-import com.yahoo.documentapi.messagebus.protocol.GetDocumentReply;
-import com.yahoo.feedapi.*;
-import com.yahoo.log.LogLevel;
-import com.yahoo.messagebus.Reply;
-import com.yahoo.search.Query;
-import com.yahoo.search.query.Properties;
-import com.yahoo.search.Result;
-import com.yahoo.search.Searcher;
-import com.yahoo.search.result.DefaultErrorHit;
-import com.yahoo.search.result.ErrorMessage;
-import com.yahoo.search.searchchain.Execution;
-import com.yahoo.vespaclient.config.FeederConfig;
-
-import java.io.*;
-import java.util.*;
-import java.util.logging.Logger;
-import java.util.zip.GZIPInputStream;
-
-/**
- * Searcher component to make GET requests to a content cluster.
- * <p>
- * Document ID must be given either as 1 "id=docid" query parameter
- * for single-document GETs and 1-n "id[0]=docid_1&amp;id[1]=...&amp;id[n-1]=docid_n"
- * parameters for multi-document GETs.
- *
- * <p>
- * Standard gateway query parameters are implicitly supported:
- * priority, timeout, route
- *
- * <p>
- * The searcher also accepts the following (optional) query parameters:
- * headersonly=true|false (default: false)
- * For specifying whether or not to return only header fields.
- *
- * <p>
- * field=string (default: no parameter specified)
- * For getting a single document field.
- *
- * <p>
- * contenttype=string (default: no content type specified)
- * For specifiying the returned HTTP header content type for a returned
- * document field's content. field must also be specified.
- * @deprecated do not use
- */
-@SuppressWarnings("deprecation")
-// TODO: Remove on Vespa 7
-@Deprecated // OK
-public class GetSearcher extends Searcher {
-
- private static final Logger log = Logger.getLogger(GetSearcher.class.getName());
-
- private static final CompoundName ID = new CompoundName("id");
- private static final CompoundName HEADERS_ONLY = new CompoundName("headersonly");
- private static final CompoundName POPULATE_HIT_FIELDS = new CompoundName("populatehitfields");
- private static final CompoundName FIELDSET = new CompoundName("fieldset");
- private static final CompoundName FIELD = new CompoundName("field");
- private static final CompoundName CONTENT_TYPE = new CompoundName("contenttype");
- private static final CompoundName TIEMOUT = new CompoundName("timeout");
-
- FeedContext context;
-
- private final long defaultTimeoutMillis;
-
- private class GetResponse implements SharedSender.ResultCallback {
-
- /**
- * We have to maintain the same ordering of results as that
- * given in the request. Do this by remembering the index of
- * each requested document ID.
- */
- private Map<String, Integer> ordering;
- private List<DocumentHit> documentHits = new ArrayList<>();
- private List<DefaultErrorHit> errorHits = new ArrayList<>();
- private List<Reply> replies = new ArrayList<>();
- private final SharedSender.Pending pendingNumber = new SharedSender.Pending();
-
- public GetResponse(List<String> documentIds) {
- ordering = new HashMap<>(documentIds.size());
- for (int i = 0; i < documentIds.size(); ++i) {
- ordering.put(documentIds.get(i), i);
- }
- }
-
- public boolean isAborted() {
- return false;
- }
-
- private String stackTraceFromException(Exception e) {
- StringWriter sw = new StringWriter();
- PrintWriter ps = new PrintWriter(sw);
- e.printStackTrace(ps);
- ps.flush();
- return sw.toString();
- }
-
- public boolean handleReply(Reply reply) {
- if ((reply.getTrace().getLevel() > 0) && log.isLoggable(LogLevel.DEBUG)) {
- String str = reply.getTrace().toString();
- log.log(LogLevel.DEBUG, str);
- }
- replies.add(reply);
- return true;
- }
- public SharedSender.Pending getPending() { return pendingNumber; }
-
- private void processReplies() {
- for (Reply reply : replies) {
- processReply(reply);
- }
- }
- private void processReply(Reply reply) {
- if (!reply.hasErrors()) {
- try {
- addDocumentHit(reply);
- } catch (Exception e) {
- String msg = "Got exception of type " + e.getClass().getName()
- + " during document deserialization: " + e.getMessage();
- errorHits.add(new DefaultErrorHit("GetSearcher", ErrorMessage.createInternalServerError(msg)));
- log.log(LogLevel.DEBUG, "Got exception during document deserialization: " + stackTraceFromException(e));
- }
- } else {
- errorHits.add(new DefaultErrorHit("GetSearcher", new MessageBusErrorMessage(
- reply.getError(0).getCode(), 0, reply.getError(0).getMessage())));
- if (log.isLoggable(LogLevel.DEBUG)) {
- log.log(LogLevel.DEBUG, "Received error reply with message " + reply.getError(0).getMessage());
- }
- }
- }
-
- private void addDocumentHit(Reply reply) {
- Document doc = ((GetDocumentReply)reply).getDocument();
- GetDocumentMessage msg = (GetDocumentMessage)reply.getMessage();
- Integer index = ordering.get(msg.getDocumentId().toString());
- if (index == null) { // Shouldn't happen
- throw new IllegalStateException("Received GetDocumentReply for unknown document: "
- + doc.getId().toString());
- }
- if (doc != null) {
- documentHits.add(new DocumentHit(doc, index));
- if (log.isLoggable(LogLevel.DEBUG)) {
- log.log(LogLevel.DEBUG, "Received GetDocumentReply for "
- + doc.getId().toString());
- }
- } else {
- // Don't add a hit for documents that can't be found
- if (log.isLoggable(LogLevel.DEBUG)) {
- log.log(LogLevel.DEBUG, "Received empty (not found) GetDocumentReply for "
- + msg.getDocumentId().toString());
- }
- }
- }
-
- private class IndexComparator implements Comparator<DocumentHit> {
- public int compare(DocumentHit o1, DocumentHit o2) {
- return o1.getIndex() - o2.getIndex();
- }
- }
-
- public void addHitsToResult(Result result, boolean populateHitFields) {
- for (DefaultErrorHit hit : errorHits) {
- result.hits().add(hit);
- }
- // Sort document hits according to their request index
- Collections.sort(documentHits, new IndexComparator());
- for (DocumentHit hit : documentHits) {
- if (populateHitFields) {
- hit.populateHitFields();
- }
- result.hits().add(hit);
- }
- result.setTotalHitCount(documentHits.size());
- }
-
- public List<DocumentHit> getDocumentHits() {
- return documentHits;
- }
-
- public List<DefaultErrorHit> getErrorHits() {
- return errorHits;
- }
- }
-
- @Inject
- public GetSearcher(FeederConfig feederConfig,
- LoadTypeConfig loadTypeConfig,
- DocumentmanagerConfig documentmanagerConfig,
- SlobroksConfig slobroksConfig,
- ClusterListConfig clusterListConfig,
- Metric metric)
- throws Exception
- {
- this(FeedContext.getInstance(feederConfig, loadTypeConfig,
- documentmanagerConfig, slobroksConfig,
- clusterListConfig, metric),
- (long)(feederConfig.timeout() * 1000));
- }
-
- GetSearcher(FeedContext context) throws Exception {
- this.context = context;
- this.defaultTimeoutMillis = context.getPropertyProcessor().getDefaultTimeoutMillis();
- }
-
- GetSearcher(FeedContext context, long defaultTimeoutMillis) throws Exception {
- this.context = context;
- this.defaultTimeoutMillis = defaultTimeoutMillis;
- }
-
- private static void postValidateDocumentIdParameters(Properties properties, int arrayIdsFound) throws Exception {
- for (Map.Entry<String, Object> kv : properties.listProperties().entrySet()) {
- if (!kv.getKey().startsWith("id[")) {
- continue;
- }
- if (!kv.getKey().endsWith("]")) {
- throw new IllegalArgumentException("Malformed document ID array parameter");
- }
- String indexStr = kv.getKey().substring(3, kv.getKey().length() - 1);
- int idx = Integer.parseInt(indexStr);
- if (idx >= arrayIdsFound) {
- throw new IllegalArgumentException("query contains document ID array " +
- "that is not zero-based and/or linearly increasing");
- }
- }
- }
-
- private List<String> getDocumentIds(Query query) throws Exception {
- Properties properties = query.properties();
- List<String> docIds = new ArrayList<>();
-
- // First check for regular "id=XX" syntax. If found, return vector with that
- // document id only
- String singleId = properties.getString(ID);
-
- int index = 0;
- if (singleId != null) {
- docIds.add(singleId);
- } else {
- // Check for id[0]=XX&id[1]=YY...id[n]=ZZ syntax. Indices always start
- // at 0 and are always increased by 1.
- while (true) {
- String docId = properties.getString("id[" + index + "]");
- if (docId == null) {
- break;
- }
- docIds.add(docId);
- ++index;
- }
- postValidateDocumentIdParameters(properties, index);
- }
-
- handleData(query.getHttpRequest(), docIds);
- return docIds;
- }
-
- private void handleData(HttpRequest request, List<String> docIds) throws IOException {
- if (request.getData() != null) {
- InputStream input;
- if ("gzip".equals(request.getHeader("Content-Encoding"))) {
- input = new GZIPInputStream(request.getData());
- } else {
- input = request.getData();
- }
- InputStreamReader reader = new InputStreamReader(input, "UTF-8");
- BufferedReader lineReader = new BufferedReader(reader);
- String line;
- while ((line = lineReader.readLine()) != null) {
- docIds.add(line);
- }
- }
- }
-
- private void handleFieldFiltering(GetResponse response, Result result,
- String fieldName, String contentType,
- boolean headersOnly) {
-
- if (response.getDocumentHits().isEmpty()) {
- result.hits().addError(ErrorMessage.createNotFound(
- "Document not found, could not return field '" + fieldName + "'"));
- return;
- }
-
- if (result.hits().getErrorHit() == null) {
- Document doc = response.getDocumentHits().get(0).getDocument();
- Field field = doc.getDataType().getField(fieldName);
- boolean wrapXml = false;
-
- if (field == null) {
- result.hits().addError(ErrorMessage.createIllegalQuery(
- "Field '" + fieldName + "' not found in document type"));
- return;
- }
- FieldValue value = doc.getFieldValue(field);
- // If the field exists but hasn't been set in this document, the
- // content will be null. We treat this as an error.
- if (value == null) {
- if (!field.isHeader() && headersOnly) {
- // TODO(vekterli): make this work with field sets as well.
- result.hits().addError(ErrorMessage.createInvalidQueryParameter(
- "Field '" + fieldName + "' is located in document body, but headersonly "
- + "prevents it from being retrieved in " + doc.getId().toString()));
- } else {
- result.hits().addError(ErrorMessage.createNotFound(
- "Field '" + fieldName + "' found in document type, but had "
- + "no content in " + doc.getId().toString()));
- }
- return;
- }
- String encoding = null;
- if (field.getDataType() == DataType.RAW) {
- if (contentType == null) {
- contentType = "application/octet-stream";
- }
- encoding = "ISO-8859-1";
- } else {
- // By default, return field wrapped in a blanket of vespa XML
- contentType = "text/xml";
- wrapXml = true;
- }
- if (encoding == null) {
- // Encoding doesn't matter for binary content, since we're always
- // writing directly to the byte buffer and not through a charset
- // encoder. Presumably, the client is intelligent enough to not
- // attempt to UTF-8 decode binary data.
- encoding = "UTF-8";
- }
- // Add hit now that we know there aren't any field errors. Otherwise,
- // there would be both an error hit and a document hit in the result
- response.addHitsToResult(result, false);
- // Override Vespa XML template
- result.getTemplating().setTemplates(new DocumentFieldTemplate(field, contentType, encoding, wrapXml));
- }
- // else: return with error hit, invoking regular Vespa XML error template
- }
-
- private void validateParameters(String fieldName, String contentType,
- List<String> documentIds) {
- // Content-type only makes sense for single document queries with a field
- // set
- if (contentType != null) {
- if (documentIds.size() > 1) {
- throw new IllegalArgumentException(
- "contenttype parameter only valid for single document id query");
- }
- if (fieldName == null) {
- throw new IllegalArgumentException(
- "contenttype set without document field being specified");
- }
- }
- if (fieldName != null && documentIds.size() > 1) {
- throw new IllegalArgumentException(
- "Field only valid for single document id query");
- }
- }
-
- // For unit testing
- protected MessagePropertyProcessor getMessagePropertyProcessor() {
- return context.getPropertyProcessor();
- }
-
- private void doGetDocuments(Query query, Result result, List<String> documentIds) {
- GetResponse response = new GetResponse(documentIds);
- Properties properties = query.properties();
-
- boolean headersOnly = properties.getBoolean(HEADERS_ONLY, false);
- boolean populateHitFields = properties.getBoolean(POPULATE_HIT_FIELDS, false);
- String fieldSet = properties.getString(FIELDSET);
- String fieldName = properties.getString(FIELD);
- String contentType = properties.getString(CONTENT_TYPE);
- long timeoutMillis = properties.getString(TIEMOUT) != null ? query.getTimeout() : defaultTimeoutMillis;
-
- if (fieldSet == null) {
- fieldSet = headersOnly ? "[header]" : "[all]";
- }
-
- validateParameters(fieldName, contentType, documentIds);
-
- MessagePropertyProcessor.PropertySetter propertySetter;
- propertySetter = context.getPropertyProcessor().buildPropertySetter(query.getHttpRequest());
-
- SingleSender sender = new SingleSender(response, context.getSharedSender(propertySetter.getRoute().toString()));
- sender.addMessageProcessor(propertySetter);
-
- sendDocumentGetMessages(documentIds, fieldSet, sender);
- // Twiddle thumbs until we've received a reply for all documents
- sender.done();
- boolean completed = sender.waitForPending(timeoutMillis);
- if ( ! completed) {
- result.hits().addError(ErrorMessage.createTimeout(
- "Timed out after waiting "+timeoutMillis+" ms for responses"));
- }
- response.processReplies();
- if (fieldName != null) {
- handleFieldFiltering(response, result, fieldName, contentType, headersOnly);
- } else {
- response.addHitsToResult(result, populateHitFields);
- }
- }
-
- private void sendDocumentGetMessages(List<String> documentIds, String fieldSet, SingleSender sender) {
- for (String docIdStr : documentIds) {
- DocumentId docId = new DocumentId(docIdStr);
- GetDocumentMessage getMsg = new GetDocumentMessage(docId, fieldSet);
-
- sender.send(getMsg);
- if (log.isLoggable(LogLevel.DEBUG)) {
- log.log(LogLevel.DEBUG, "Sent GetDocumentMessage for "
- + docId.toString());
- }
- }
- }
-
- boolean verifyBackendDocumentHitsOnly(Result result) {
- if (result.hits().size() != 0) {
- log.log(LogLevel.DEBUG, "Result had hits after being sent down");
- for (int i = 0; i < result.hits().size(); ++i) {
- if (!(result.hits().get(i) instanceof DocumentHit)) {
- log.log(LogLevel.WARNING, "Got hit from backend searcher which was "
- + "not a com.yahoo.storage.searcher.DocumentHit instance: "
- + result.hits().get(i).getClass().getName());
- return false;
- }
- }
- }
- return true;
- }
-
- @Override
- public Result search(Query query, Execution execution) {
- // Pass through to next searcher
- Result result = execution.search(query);
-
- List<String> documentIds;
- try {
- documentIds = getDocumentIds(query);
- } catch (Exception e) {
- setOutputFormat(query, result);
- result.hits().addError(ErrorMessage.createIllegalQuery(e.getClass().getName() + ": " + e.getMessage()));
- return result;
- }
- // Early-out for pass-through queries
- if (documentIds.isEmpty()) {
- return result;
- }
- // Make sure we don't try to combine non-document hits and document hits
- // in the same result set.
- if (!verifyBackendDocumentHitsOnly(result)) {
- result = new Result(query); // Don't include unknown hits
- setOutputFormat(query, result);
- result.hits().addError(ErrorMessage.createInternalServerError(
- "A backend searcher to com.yahoo.storage.searcher.GetSearcher " +
- "returned a hit that was not an instance of com.yahoo.storage.searcher.DocumentHit. " +
- "Only DocumentHit instances are supported in the backend hit result set when doing " +
- "queries that contain document identifier sets recognised by the Get Searcher."));
- return result;
- }
- setOutputFormat(query, result);
- // Do not propagate exceptions back up, as we want to have all errors
- // be reported using the proper template
- try {
- doGetDocuments(query, result, documentIds);
- query.setHits(result.hits().size());
- } catch (IllegalArgumentException e) {
- result.hits().addError(ErrorMessage.createIllegalQuery(e.getClass().getName() + ": " + e.getMessage()));
- } catch (Exception e) {
- result.hits().addError(ErrorMessage.createUnspecifiedError(e.getClass().getName() + ": " + e.getMessage()));
- }
-
- return result;
- }
-
- private static final CompoundName formatShortcut = new CompoundName("format");
- private static final CompoundName format = new CompoundName("presentation.format");
-
- /**
- * Use custom XML output format unless the default JSON renderer is specified in the request.
- */
- @SuppressWarnings("deprecation")
- static void setOutputFormat(Query query, Result result) {
- if (getRequestProperty(formatShortcut, "", query).equals("JsonRenderer")) return;
- if (getRequestProperty(format, "", query).equals("JsonRenderer")) return;
- if (getRequestProperty(formatShortcut, "", query).equals("json")) return;
- if (getRequestProperty(format, "", query).equals("json")) return;
- result.getTemplating().setTemplates(new DocumentXMLTemplate());
- }
-
- private static String getRequestProperty(CompoundName propertyName, String defaultValue, Query query) {
- String propertyValue = query.getHttpRequest().getProperty(propertyName.toString());
- if (propertyValue == null) return defaultValue;
- return propertyValue;
- }
-
-}
diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/MessageBusErrorMessage.java b/vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/MessageBusErrorMessage.java
deleted file mode 100755
index ad93645e55e..00000000000
--- a/vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/MessageBusErrorMessage.java
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.storage.searcher;
-
-import com.yahoo.search.result.ErrorMessage;
-
-/**
- * Simple ErrorMessage extension that includes a message bus error code, not
- * just the searcher error code (which isn't very useful for a Vespa XML consumer)
- */
-@Deprecated // OK
-// TODO: Remove on Vespa 7
-public class MessageBusErrorMessage extends ErrorMessage {
-
- private int mbusCode;
-
- public MessageBusErrorMessage(int mbusCode, int qrsCode, String message) {
- super(qrsCode, message);
- this.mbusCode = mbusCode;
- }
-
- public MessageBusErrorMessage(int mbusCode, int qrsCode, String message, String detailedMessage) {
- super(qrsCode, message, detailedMessage);
- this.mbusCode = mbusCode;
- }
-
- public MessageBusErrorMessage(int mbusCode, int qrsCode, String message, String detailedMessage, Throwable cause) {
- super(qrsCode, message, detailedMessage, cause);
- this.mbusCode = mbusCode;
- }
-
- public int getMessageBusCode() {
- return mbusCode;
- }
-
- public void setMessageBusCode(int code) {
- this.mbusCode = code;
- }
-
-}
diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/VisitSearcher.java b/vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/VisitSearcher.java
deleted file mode 100644
index e330b76fa4b..00000000000
--- a/vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/VisitSearcher.java
+++ /dev/null
@@ -1,210 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.storage.searcher;
-
-import com.yahoo.cloud.config.ClusterListConfig;
-import com.yahoo.cloud.config.SlobroksConfig;
-import com.yahoo.document.config.DocumentmanagerConfig;
-import com.yahoo.vespa.config.content.LoadTypeConfig;
-import com.yahoo.component.ComponentId;
-import com.yahoo.component.ComponentSpecification;
-import com.yahoo.document.Document;
-import com.yahoo.document.DocumentId;
-import com.yahoo.documentapi.*;
-import com.yahoo.documentapi.messagebus.protocol.DocumentProtocol;
-import com.yahoo.feedapi.FeedContext;
-import com.yahoo.feedapi.MessagePropertyProcessor;
-import com.yahoo.jdisc.Metric;
-import com.yahoo.messagebus.StaticThrottlePolicy;
-import com.yahoo.search.Query;
-import com.yahoo.search.Result;
-import com.yahoo.search.Searcher;
-import com.yahoo.search.rendering.RendererRegistry;
-import com.yahoo.search.result.ErrorMessage;
-import com.yahoo.search.searchchain.Execution;
-import com.yahoo.vdslib.VisitorOrdering;
-import com.yahoo.vespaclient.ClusterDef;
-import com.yahoo.vespaclient.config.FeederConfig;
-
-/**
- * A searcher that allows you to iterate through a storage cluster using visiting.
- *
- * @deprecated do not use
- */
-// TODO: Remove on Vespa 7
-@Deprecated // OK
-public class VisitSearcher extends Searcher {
-
- public static final String VISITOR_CONTINUATION_TOKEN_FIELDNAME = "visitorContinuationToken";
- FeedContext context;
-
- public VisitSearcher(FeederConfig feederConfig,
- LoadTypeConfig loadTypeConfig,
- DocumentmanagerConfig documentmanagerConfig,
- SlobroksConfig slobroksConfig,
- ClusterListConfig clusterListConfig,
- Metric metric)
- throws Exception
- {
- this(FeedContext.getInstance(feederConfig, loadTypeConfig,
- documentmanagerConfig, slobroksConfig,
- clusterListConfig, metric));
- }
-
- VisitSearcher(FeedContext context) throws Exception {
- this.context = context;
- }
-
- class HitDataHandler extends DumpVisitorDataHandler {
- private final Result result;
- private final boolean populateHits;
- private final Object monitor = new Object();
-
- HitDataHandler(Result result, boolean populateHits) {
- this.result = result;
- this.populateHits = populateHits;
- }
-
- @Override
- public void onDocument(Document document, long l) {
- final DocumentHit hit = new DocumentHit(document, 0);
- if (populateHits) {
- hit.populateHitFields();
- }
- synchronized (monitor) {
- result.hits().add(hit);
- }
- }
-
- @Override
- public void onRemove(DocumentId documentId) {
- final DocumentRemoveHit hit = new DocumentRemoveHit(documentId);
- synchronized (monitor) {
- result.hits().add(hit);
- }
- }
- }
-
- public VisitorParameters getVisitorParameters(Query query, Result result) throws Exception {
- String documentSelection = query.properties().getString("visit.selection");
- if (documentSelection == null) {
- documentSelection = "";
- }
-
- VisitorParameters params = new VisitorParameters(documentSelection);
- params.setMaxBucketsPerVisitor(query.properties().getInteger("visit.maxBucketsPerVisitor", 1));
- params.setMaxPending(query.properties().getInteger("visit.maxPendingMessagesPerVisitor", 32));
- params.setMaxFirstPassHits(query.properties().getInteger("visit.approxMaxDocs", 1));
- params.setMaxTotalHits(query.properties().getInteger("visit.approxMaxDocs", 1));
- params.setThrottlePolicy(new StaticThrottlePolicy().setMaxPendingCount(
- query.properties().getInteger("visit.maxPendingVisitors", 1)));
- params.setToTimestamp(query.properties().getLong("visit.toTimestamp", 0L));
- params.setFromTimestamp(query.properties().getLong("visit.fromTimestamp", 0L));
-
- String pri = query.properties().getString("visit.priority");
- if (pri != null) {
- params.setPriority(DocumentProtocol.Priority.valueOf(pri));
- }
-
- if (query.properties().getBoolean("visit.visitInconsistentBuckets")) {
- params.visitInconsistentBuckets(true);
- }
-
- String ordering = query.properties().getString("visit.order");
- if (!"ascending".equalsIgnoreCase(ordering)) {
- params.setVisitorOrdering(VisitorOrdering.ASCENDING);
- } else {
- params.setVisitorOrdering(VisitorOrdering.DESCENDING);
- }
-
- String remoteCluster = query.properties().getString("visit.dataHandler");
- if (remoteCluster != null) {
- params.setRemoteDataHandler(remoteCluster);
- } else {
- params.setLocalDataHandler(new HitDataHandler(
- result, query.properties().getBoolean("populatehitfields", false)));
- }
-
- String fieldSet = query.properties().getString("visit.fieldSet");
- if (fieldSet != null) {
- params.fieldSet(fieldSet);
- }
-
- String continuation = query.properties().getString("visit.continuation");
- if (continuation != null) {
- params.setResumeToken(ContinuationHit.getToken(continuation));
- }
-
- params.setVisitRemoves(query.properties().getBoolean("visit.visitRemoves"));
-
- MessagePropertyProcessor.PropertySetter propertySetter;
- propertySetter = context.getPropertyProcessor().buildPropertySetter(query.getHttpRequest());
-
- propertySetter.process(params);
-
- if (context.getClusterList().getStorageClusters().size() == 0) {
- throw new IllegalArgumentException("No content clusters have been defined");
- }
-
- String route = query.properties().getString("visit.cluster");
- ClusterDef found = null;
- if (route != null) {
- String names = "";
- for (ClusterDef c : context.getClusterList().getStorageClusters()) {
- if (c.getName().equals(route)) {
- found = c;
- }
- if (!names.isEmpty()) {
- names += ", ";
- }
- names += c.getName();
- }
- if (found == null) {
- throw new IllegalArgumentException("Your vespa cluster contains the storage clusters " + names + ", not " + route + ". Please select a valid vespa cluster.");
- }
- } else if (context.getClusterList().getStorageClusters().size() == 1) {
- found = context.getClusterList().getStorageClusters().get(0);
- } else {
- throw new IllegalArgumentException("Multiple content clusters are defined, select one using the \"visit.cluster\" option");
- }
-
- params.setRoute("[Storage:cluster=" + found.getName() + ";clusterconfigid=" + found.getConfigId() + "]");
- return params;
- }
-
- @Override
- public Result search(Query query, Execution execution) {
- Result result = execution.search(query);
-
- VisitorParameters parameters;
-
- try {
- parameters = getVisitorParameters(query, result);
- } catch (Exception e) {
- return new Result(query, ErrorMessage.createBadRequest("Illegal parameters: " + e.toString()));
- }
-
- if (parameters != null) {
- VisitorSession session = context.getSessionFactory().createVisitorSession(parameters);
-
- try {
- if (!session.waitUntilDone(query.getTimeout())) {
- return new Result(query, ErrorMessage.createTimeout("Visitor timed out"));
- }
-
- ProgressToken token = session.getProgress();
- if (!token.isFinished()) {
- final ContinuationHit continuation = new ContinuationHit(token);
- result.hits().setField(VISITOR_CONTINUATION_TOKEN_FIELDNAME, continuation.getValue());
- }
- } catch (InterruptedException e) {
- } finally {
- session.destroy();
- }
- }
-
- GetSearcher.setOutputFormat(query, result);
- query.setHits(result.hits().size());
- return result;
- }
-
-}
diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/package-info.java b/vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/package-info.java
deleted file mode 100644
index 581afb0b1c8..00000000000
--- a/vespaclient-container-plugin/src/main/java/com/yahoo/storage/searcher/package-info.java
+++ /dev/null
@@ -1,6 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-// TODO: This implements the old, deprecated document http API. Remove this package on Vespa 7.
-@ExportPackage
-package com.yahoo.storage.searcher;
-
-import com.yahoo.osgi.annotation.ExportPackage;
diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/FeedHandler.java b/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/FeedHandler.java
index 5294545ad50..bd7d195b48b 100644
--- a/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/FeedHandler.java
+++ b/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/FeedHandler.java
@@ -51,16 +51,8 @@ import java.util.zip.GZIPInputStream;
*/
public class FeedHandler extends LoggingRequestHandler {
- private final ExecutorService workers = Executors.newCachedThreadPool(ThreadFactoryFactory.getThreadFactory("feedhandler"));
- private final DocumentTypeManager docTypeManager;
- private final Map<String, ClientState> clients;
- private final ScheduledThreadPoolExecutor cron;
- private final SessionCache sessionCache;
protected final ReplyHandler feedReplyHandler;
- private final AtomicLong sessionId;
- private final Metric metric;
- private static final List<Integer> serverSupportedVersions = Collections.unmodifiableList(Arrays.asList(2, 3));
- private final String localHostname;
+ private static final List<Integer> serverSupportedVersions = Collections.unmodifiableList(Arrays.asList(3));
private final FeedHandlerV3 feedHandlerV3;
@Inject
@@ -73,46 +65,7 @@ public class FeedHandler extends LoggingRequestHandler {
super(parentCtx);
DocumentApiMetrics metricsHelper = new DocumentApiMetrics(metricReceiver, "vespa.http.server");
feedHandlerV3 = new FeedHandlerV3(parentCtx, documentManagerConfig, sessionCache, threadpoolConfig, metricsHelper);
- docTypeManager = createDocumentManager(documentManagerConfig);
- clients = new HashMap<>();
- this.sessionCache = sessionCache;
- sessionId = new AtomicLong(ThreadLocalRandom.current().nextLong());
feedReplyHandler = new FeedReplyReader(parentCtx.getMetric(), metricsHelper);
- cron = new ScheduledThreadPoolExecutor(1, ThreadFactoryFactory.getThreadFactory("feedhandler.cron"));
- cron.scheduleWithFixedDelay(new CleanClients(), 16, 11, TimeUnit.MINUTES);
- this.metric = parentCtx.getMetric();
- this.localHostname = resolveLocalHostname();
- }
-
- /**
- * Exposed for creating mocks.
- */
- protected DocumentTypeManager createDocumentManager(DocumentmanagerConfig documentManagerConfig) {
- return new DocumentTypeManager(documentManagerConfig);
- }
-
- private class CleanClients implements Runnable {
-
- @Override
- public void run() {
- List<ClientState> clientsToShutdown = new ArrayList<>();
- long now = System.currentTimeMillis();
-
- synchronized (clients) {
- for (Iterator<Map.Entry<String, ClientState>> i = clients
- .entrySet().iterator(); i.hasNext();) {
- ClientState client = i.next().getValue();
-
- if (now - client.creationTime > 10 * 60 * 1000) {
- clientsToShutdown.add(client);
- i.remove();
- }
- }
- }
- for (ClientState client : clientsToShutdown) {
- client.sourceSession.getReference().close();
- }
- }
}
private Tuple2<HttpResponse, Integer> checkProtocolVersion(HttpRequest request) {
@@ -135,8 +88,6 @@ public class FeedHandler extends LoggingRequestHandler {
int version;
if (washedClientVersions.contains("3")) {
version = 3;
- } else if (washedClientVersions.contains("2")) { // TODO: Vespa 7: Remove support for Version 2
- version = 2;
} else {
return new Tuple2<>(new ErrorHttpResponse(
Headers.HTTP_NOT_ACCEPTABLE,
@@ -175,43 +126,7 @@ public class FeedHandler extends LoggingRequestHandler {
if (protocolVersion.first != null) {
return protocolVersion.first;
}
- if (3 == protocolVersion.second) {
- return feedHandlerV3.handle(request);
- }
- final BlockingQueue<OperationStatus> operations = new LinkedBlockingQueue<>();
- Tuple2<String, Boolean> clientId;
- clientId = sessionId(request);
-
- if (clientId.second != null && clientId.second) {
- if (log.isLoggable(LogLevel.DEBUG)) {
- log.log(LogLevel.DEBUG, "Received initial request from client with session ID " +
- clientId.first + ", protocol version " + protocolVersion.second);
- }
- }
-
- Feeder feeder;
- try {
- feeder = createFeeder(request, request.getData(), operations, clientId.first,
- clientId.second, protocolVersion.second);
- // the synchronous FeedResponse blocks draining the InputStream, letting the Feeder read it
- workers.submit(feeder);
- } catch (UnknownClientException uce) {
- String msg = Exceptions.toMessageString(uce);
- log.log(LogLevel.WARNING, msg);
- return new ErrorHttpResponse(Status.BAD_REQUEST, msg);
- } catch (Exception e) {
- String msg = "Could not initialize document parsing";
- log.log(LogLevel.WARNING, "Could not initialize document parsing", e);
- return new ErrorHttpResponse(Status.INTERNAL_SERVER_ERROR, msg + ": " + Exceptions.toMessageString(e));
- }
-
- try {
- feeder.waitForRequestReceived();
- } catch (InterruptedException e) {
- return new ErrorHttpResponse(Status.INTERNAL_SERVER_ERROR, e.getMessage());
- }
-
- return new FeedResponse(200, operations, protocolVersion.second, clientId.first);
+ return feedHandlerV3.handle(request);
}
// Protected for testing
@@ -225,82 +140,6 @@ public class FeedHandler extends LoggingRequestHandler {
}
}
- /**
- * Exposed for creating mocks.
- */
- protected Feeder createFeeder(
- HttpRequest request,
- InputStream requestInputStream,
- BlockingQueue<OperationStatus> operations,
- String clientId,
- boolean sessionIdWasGeneratedJustNow,
- int protocolVersion) throws Exception {
- if (protocolVersion != 2)
- throw new IllegalStateException("Protocol version " + protocolVersion + " not supported.");
-
- return new Feeder(
- unzipStreamIfNeeded(requestInputStream, request),
- new FeedReaderFactory(),
- docTypeManager,
- operations,
- popClient(clientId),
- new FeederSettings(request),
- clientId,
- sessionIdWasGeneratedJustNow,
- sourceSessionParams(request),
- sessionCache,
- this,
- metric,
- feedReplyHandler,
- localHostname);
- }
-
- private Tuple2<String, Boolean> sessionId(HttpRequest request) {
- boolean sessionIdWasGeneratedJustNow = false;
- String sessionId = request.getHeader(Headers.SESSION_ID);
- if (sessionId == null) {
- sessionId = Long.toString(this.sessionId.incrementAndGet()) + "-" +
- remoteHostAddressAndPort(request.getJDiscRequest()) + "#" +
- localHostname;
- sessionIdWasGeneratedJustNow = true;
- }
- return new Tuple2<>(sessionId, sessionIdWasGeneratedJustNow);
- }
-
- private static String remoteHostAddressAndPort(com.yahoo.jdisc.http.HttpRequest httpRequest) {
- SocketAddress remoteAddress = httpRequest.getRemoteAddress();
- if (remoteAddress instanceof InetSocketAddress) {
- InetSocketAddress isa = (InetSocketAddress) remoteAddress;
- return isa.getAddress().getHostAddress() + "-" + isa.getPort();
- }
- return "";
- }
-
- private static String resolveLocalHostname() {
- String hostname = HostName.getLocalhost();
- if (hostname.equals("localhost")) {
- return "";
- }
- return hostname;
- }
-
- /**
- * Exposed for use when creating mocks.
- */
- protected SourceSessionParams sourceSessionParams(HttpRequest request) {
- SourceSessionParams params = new SourceSessionParams();
- String timeout = request.getHeader(Headers.TIMEOUT);
-
- if (timeout != null) {
- try {
- params.setTimeout(Double.parseDouble(timeout));
- } catch (NumberFormatException e) {
- // NOP
- }
- }
- return params;
- }
-
@Override
protected void destroy() {
feedHandlerV3.destroy();
@@ -316,33 +155,5 @@ public class FeedHandler extends LoggingRequestHandler {
private void internalDestroy() {
super.destroy();
- workers.shutdown();
- cron.shutdown();
- synchronized (clients) {
- for (ClientState client : clients.values()) {
- client.sourceSession.getReference().close();
- }
- clients.clear();
- }
- }
-
- void putClient(final String sessionId, final ClientState value) {
- synchronized (clients) {
- clients.put(sessionId, value);
- }
}
-
- ClientState popClient(String sessionId) {
- synchronized (clients) {
- return clients.remove(sessionId);
- }
- }
-
- /**
- * Guess what, testing only.
- */
- void forceRunCleanClients() {
- new CleanClients().run();
- }
-
}
diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/Feeder.java b/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/Feeder.java
deleted file mode 100644
index f7890db3b35..00000000000
--- a/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/Feeder.java
+++ /dev/null
@@ -1,537 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.http.server;
-
-import com.yahoo.collections.Tuple2;
-import com.yahoo.container.jdisc.messagebus.SessionCache;
-import com.yahoo.document.DocumentId;
-import com.yahoo.document.DocumentUpdate;
-import com.yahoo.document.DocumentRemove;
-import com.yahoo.document.DocumentPut;
-import com.yahoo.document.DocumentTypeManager;
-import com.yahoo.documentapi.messagebus.protocol.DocumentMessage;
-import com.yahoo.documentapi.messagebus.protocol.DocumentProtocol;
-import com.yahoo.documentapi.messagebus.protocol.PutDocumentMessage;
-import com.yahoo.documentapi.messagebus.protocol.RemoveDocumentMessage;
-import com.yahoo.documentapi.messagebus.protocol.UpdateDocumentMessage;
-import com.yahoo.documentapi.metrics.DocumentOperationType;
-import com.yahoo.jdisc.Metric;
-import com.yahoo.jdisc.ReferencedResource;
-import com.yahoo.log.LogLevel;
-import com.yahoo.messagebus.Message;
-import com.yahoo.messagebus.ReplyHandler;
-import com.yahoo.messagebus.Result;
-import com.yahoo.messagebus.SourceSessionParams;
-import com.yahoo.messagebus.routing.ErrorDirective;
-import com.yahoo.messagebus.routing.Hop;
-import com.yahoo.messagebus.routing.Route;
-import com.yahoo.messagebus.shared.SharedSourceSession;
-import com.yahoo.yolean.Exceptions;
-import com.yahoo.text.Utf8String;
-import com.yahoo.vespa.http.client.core.Encoder;
-import com.yahoo.vespa.http.client.core.ErrorCode;
-import com.yahoo.vespa.http.client.core.OperationStatus;
-import com.yahoo.vespa.http.server.util.ByteLimitedInputStream;
-import com.yahoo.vespaxmlparser.FeedReader;
-import com.yahoo.vespaxmlparser.VespaXMLFeedReader;
-import com.yahoo.vespaxmlparser.VespaXMLFeedReader.Operation;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Arrays;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.TimeUnit;
-import java.util.logging.Logger;
-
-import static com.yahoo.messagebus.ErrorCode.SEND_QUEUE_FULL;
-
-/**
- * Read documents from client, and send them through message bus.
- *
- * @author <a href="mailto:steinar@yahoo-inc.com">Steinar Knutsen</a>
- */
-public class Feeder implements Runnable {
-
- protected static final Logger log = Logger.getLogger(Feeder.class.getName());
-
- final InputStream requestInputStream;
- final DocumentTypeManager docTypeManager;
- final BlockingQueue<OperationStatus> operations;
- final BlockingQueue<OperationStatus> feedReplies;
- int numPending;
- final FeederSettings settings;
- final String clientId;
- final ReferencedResource<SharedSourceSession> sourceSession;
- final FeedHandler handler;
- final Metric metric;
- final Metric.Context metricContext;
- private long prevOpsPerSecTime; // previous measurement time of OPS
- private double operationsForOpsPerSec;
- private final ReplyHandler feedReplyHandler;
- protected final static String EOF = "End of stream";
- protected final boolean sessionIdWasGeneratedJustNow;
- private final CountDownLatch requestReceived = new CountDownLatch(1);
- private final FeedReaderFactory feedReaderFactory;
-
- public Feeder(InputStream requestInputStream,
- FeedReaderFactory feedReaderFactory,
- DocumentTypeManager docTypeManager,
- BlockingQueue<OperationStatus> operations,
- ClientState storedState,
- FeederSettings settings,
- String clientId, boolean sessionIdWasGeneratedJustNow, SourceSessionParams sessionParams,
- SessionCache sessionCache,
- FeedHandler handler, Metric metric, ReplyHandler feedReplyHandler,
- String localHostname) throws Exception {
- super();
- this.feedReaderFactory = feedReaderFactory;
- if (storedState == null) {
- if (!sessionIdWasGeneratedJustNow) {
- // We do not have a stored state, BUT the session ID came in with the request.
- // Possible session timeout, server restart, server reconfig, or VIP usage. Examine.
- examineClientId(clientId, localHostname);
- }
- numPending = 0;
- feedReplies = new LinkedBlockingQueue<>();
- sourceSession = retainSession(sessionParams, sessionCache);
- metricContext = createClientMetricContext(metric, clientId);
- prevOpsPerSecTime = System.currentTimeMillis();
- operationsForOpsPerSec = 0.0;
- } else {
- //we have a stored state, and the session ID was obviously not generated now. All OK.
- numPending = storedState.pending;
- feedReplies = storedState.feedReplies;
- sourceSession = storedState.sourceSession;
- metricContext = storedState.metricContext;
- prevOpsPerSecTime = storedState.prevOpsPerSecTime;
- operationsForOpsPerSec = storedState.operationsForOpsPerSec;
- }
- this.clientId = clientId;
- this.sessionIdWasGeneratedJustNow = sessionIdWasGeneratedJustNow;
- this.requestInputStream = requestInputStream;
- this.docTypeManager = docTypeManager;
- this.operations = operations;
- this.settings = settings;
- this.handler = handler;
- this.metric = metric;
- this.feedReplyHandler = feedReplyHandler;
- }
- protected void examineClientId(String clientId, String localHostname) {
- if (!clientId.contains("#")) {
- throw new UnknownClientException("Got request from client with id '" + clientId +
- "', but found no session for this client. " +
- "This is expected during upgrades of gateways and infrastructure nodes.");
- }
- int hashPos = clientId.indexOf("#");
- String supposedHostname = clientId.substring(hashPos + 1, clientId.length());
- if (supposedHostname.isEmpty()) {
- throw new UnknownClientException("Got request from client with id '" + clientId +
- "', but found no session for this client. Possible session " +
- "timeout due to inactivity, server restart or reconfig, " +
- "or bad VIP usage. " +
- "This is expected during upgrades of gateways and infrastructure nodes.");
- }
-
- if (!supposedHostname.equals(localHostname)) {
- throw new UnknownClientException("Got request from client with id '" + clientId +
- "', but found no session for this client. " +
- "Session was originally established towards host " +
- supposedHostname + ", but our hostname is " +
- localHostname + ". " +
- "If using VIP rotation, this could be due to a session was rotated from one server to another. " +
- "Configure VIP with persistence=enabled. " +
- "This is expected during upgrades of gateways and infrastructure nodes.");
- }
- log.log(LogLevel.DEBUG, "Client '" + clientId + "' reconnected after session inactivity, or server restart " +
- "or reconfig. Re-establishing session.");
- }
-
-
-
- private static Metric.Context createClientMetricContext(Metric metric, String clientId) {
- // No real value in separate metric dimensions per client.
- return null;
- }
-
- /**
- * Exposed for creating mocks.
- */
- protected ReferencedResource<SharedSourceSession> retainSession(
- SourceSessionParams sessionParams, SessionCache sessionCache) {
- return sessionCache.retainSource(sessionParams);
- }
-
- @Override
- public void run() {
- try {
- if (handshake()) {
- return; //will putClient in finally block below
- }
- flushResponseQueue();
- feed();
- requestReceived.countDown();
- drain();
- } catch (InterruptedException e) {
- // NOP, just terminate
- } catch (Exception e) {
- log.log(LogLevel.WARNING, "Unhandled exception while feeding: "
- + Exceptions.toMessageString(e), e);
- } catch (Throwable e) {
- log.log(LogLevel.WARNING, "Unhandled error while feeding: "
- + Exceptions.toMessageString(e), e);
- throw e;
- } finally {
- requestReceived.countDown();
- putClient();
- try {
- enqueue("-", "-", ErrorCode.END_OF_FEED, false, null);
- } catch (InterruptedException e) {
- // NOP, we are already exiting the thread
- }
- }
- }
-
- protected boolean handshake() throws IOException {
- if (sessionIdWasGeneratedJustNow) {
- if (log.isLoggable(LogLevel.DEBUG)) {
- log.log(LogLevel.DEBUG, "Handshake completed for client " + clientId + ".");
- }
- requestInputStream.close();
- return true;
- }
- return false;
- }
-
- void feed() throws InterruptedException {
- while (true) {
- Result result;
- String operationId;
- try {
- operationId = getNextOperationId();
- } catch (IOException ioe) {
- if (log.isLoggable(LogLevel.DEBUG)) {
- log.log(LogLevel.DEBUG, Exceptions.toMessageString(ioe), ioe);
- }
- break;
- }
-
- //noinspection StringEquality
- if (operationId == EOF) {
- break;
- }
-
- Tuple2<String, Message> msg;
- try {
- msg = getNextMessage(operationId);
- setRoute(msg);
- } catch (Exception e) {
- if (log.isLoggable(LogLevel.DEBUG)) {
- log.log(LogLevel.DEBUG, Exceptions.toMessageString(e), e);
- }
- //noinspection StringEquality
- if (operationId != null) { //v1 always returns null, all others return something useful, or throw an exception above
- msg = newErrorMessage(operationId, e);
- } else {
- break;
- }
- }
-
- if (msg == null) {
- break;
- }
-
- setMessageParameters(msg);
-
- while (true) {
- try {
- msg.second.pushHandler(feedReplyHandler);
- if (settings.denyIfBusy) {
- result = sourceSession.getResource().sendMessage(msg.second);
- } else {
- result = sourceSession.getResource().sendMessageBlocking(msg.second);
- }
- } catch (RuntimeException e) {
- enqueue(msg.first, Exceptions.toMessageString(e),
- ErrorCode.ERROR, false, msg.second);
- return;
- }
- if (result.isAccepted() || result.getError().getCode() != SEND_QUEUE_FULL) {
- break;
- }
- if (settings.denyIfBusy) {
- break;
- } else {
- //This will never happen
- Thread.sleep(100);
- }
- }
-
- if (result.isAccepted()) {
- ++numPending;
- updateMetrics(msg.second);
- updateOpsPerSec();
- log(LogLevel.DEBUG, "Sent message successfully, document id: ", msg.first);
- } else if (!result.getError().isFatal()) {
- enqueue(msg.first, result.getError().getMessage(), ErrorCode.TRANSIENT_ERROR, false, msg.second);
- break;
- } else {
- // should probably not happen, but everybody knows stuff that
- // shouldn't happen, happens all the time
- boolean isConditionNotMet = result.getError().getCode() == DocumentProtocol.ERROR_TEST_AND_SET_CONDITION_FAILED;
- enqueue(msg.first, result.getError().getMessage(), ErrorCode.ERROR, isConditionNotMet, msg.second);
- break;
- }
- }
- }
-
- private Tuple2<String, Message> newErrorMessage(String operationId, Exception e) {
- Message m = new FeedErrorMessage(operationId);
- Tuple2<String, Message> msg = new Tuple2<>(operationId, m);
- Hop hop = new Hop();
- hop.addDirective(new ErrorDirective(Exceptions.toMessageString(e)));
- Route route = new Route();
- route.addHop(hop);
- m.setRoute(route);
- return msg;
- }
-
- private void updateMetrics(Message m) {
- metric.set(
- MetricNames.PENDING,
- Double.valueOf(sourceSession.getResource().session().getPendingCount()),
- null);
-
- metric.add(MetricNames.NUM_OPERATIONS, 1, metricContext);
-
- if (m instanceof PutDocumentMessage) {
- metric.add(MetricNames.NUM_PUTS, 1, metricContext);
- } else if (m instanceof RemoveDocumentMessage) {
- metric.add(MetricNames.NUM_REMOVES, 1, metricContext);
- } else if (m instanceof UpdateDocumentMessage) {
- metric.add(MetricNames.NUM_UPDATES, 1, metricContext);
- }
- }
-
- private void updateOpsPerSec() {
- long now = System.currentTimeMillis();
- if ((now - prevOpsPerSecTime) >= 1000) { //every second
- double ms = (double) (now - prevOpsPerSecTime);
- final double opsPerSec = operationsForOpsPerSec / (ms / 1000);
- metric.set(MetricNames.OPERATIONS_PER_SEC, opsPerSec, metricContext);
- operationsForOpsPerSec = 1.0d;
- prevOpsPerSecTime = now;
- } else {
- operationsForOpsPerSec += 1.0d;
- }
- }
-
- private Tuple2<String, Message> getNextMessage(String operationId) throws Exception {
- VespaXMLFeedReader.Operation op = new VespaXMLFeedReader.Operation();
- Tuple2<String, Message> msg;
-
- getNextOperation(op);
-
- switch (op.getType()) {
- case DOCUMENT:
- msg = newPutMessage(op, operationId);
- break;
- case REMOVE:
- msg = newRemoveMessage(op, operationId);
- break;
- case UPDATE:
- msg = newUpdateMessage(op, operationId);
- break;
- default:
- // typical end of feed
- return null;
- }
- log(LogLevel.DEBUG, "Successfully deserialized document id: ", msg.first);
- return msg;
- }
-
- private void setMessageParameters(Tuple2<String, Message> msg) {
- msg.second.setContext(new ReplyContext(msg.first, feedReplies, DocumentOperationType.fromMessage(msg.second)));
- if (settings.traceLevel != null) {
- msg.second.getTrace().setLevel(settings.traceLevel);
- }
- if (settings.priority != null) {
- try {
- DocumentProtocol.Priority priority = DocumentProtocol.Priority.valueOf(settings.priority);
- if (msg.second instanceof DocumentMessage) {
- ((DocumentMessage) msg.second).setPriority(priority);
- }
- }
- catch (IllegalArgumentException i) {
- log.severe(i.getMessage());
- }
- }
- }
-
- private void setRoute(Tuple2<String, Message> msg) {
- if (settings.route != null) {
- msg.second.setRoute(settings.route);
- }
- }
-
- protected void getNextOperation(VespaXMLFeedReader.Operation op) throws Exception {
- int length = readByteLength();
-
- try (InputStream limitedInputStream = new ByteLimitedInputStream(requestInputStream, length)){
- FeedReader reader = feedReaderFactory.createReader(limitedInputStream, docTypeManager, settings.dataFormat);
- reader.read(op);
- }
- }
-
- protected String getNextOperationId() throws IOException {
- return readOperationId();
- }
-
- private String readOperationId() throws IOException {
- StringBuilder idBuf = new StringBuilder(100);
- int c;
- while ((c = requestInputStream.read()) != -1) {
- if (c == 32) {
- break;
- }
- idBuf.append((char) c); //it's ASCII
- }
- if (idBuf.length() == 0) {
- return EOF;
- }
- return Encoder.decode(idBuf.toString(), new StringBuilder(idBuf.length())).toString();
- }
-
- private int readByteLength() throws IOException {
- StringBuilder lenBuf = new StringBuilder(8);
- int c;
- while ((c = requestInputStream.read()) != -1) {
- if (c == 10) {
- break;
- }
- lenBuf.append((char) c); //it's ASCII
- }
- if (lenBuf.length() == 0) {
- throw new IllegalStateException("Operation length missing.");
- }
- return Integer.valueOf(lenBuf.toString(), 16);
- }
-
- protected final void log(LogLevel level, Object... msgParts) {
- StringBuilder s;
-
- if (!log.isLoggable(level)) {
- return;
- }
-
- s = new StringBuilder();
- for (Object part : msgParts) {
- s.append(part.toString());
- }
-
- log.log(level, s.toString());
- }
-
- private Tuple2<String, Message> newUpdateMessage(Operation op, String operationId) {
- DocumentUpdate update = op.getDocumentUpdate();
- update.setCondition(op.getCondition());
- Message msg = new UpdateDocumentMessage(update);
-
- String id = (operationId == null) ? update.getId().toString() : operationId;
- return new Tuple2<>(id, msg);
- }
-
- private Tuple2<String, Message> newRemoveMessage(Operation op, String operationId) {
- DocumentRemove remove = new DocumentRemove(op.getRemove());
- remove.setCondition(op.getCondition());
- Message msg = new RemoveDocumentMessage(remove);
-
- String id = (operationId == null) ? remove.getId().toString() : operationId;
- return new Tuple2<>(id, msg);
- }
-
- private Tuple2<String, Message> newPutMessage(Operation op, String operationId) {
- DocumentPut put = new DocumentPut(op.getDocument());
- put.setCondition(op.getCondition());
- Message msg = new PutDocumentMessage(put);
-
- String id = (operationId == null) ? put.getId().toString() : operationId;
- return new Tuple2<>(id, msg);
- }
-
-
- void flushResponseQueue() throws InterruptedException {
- OperationStatus status = feedReplies.poll();
- while (status != null) {
- decreasePending(status);
- status = feedReplies.poll();
- }
- }
-
- void putClient() {
- handler.putClient(clientId,
- new ClientState(numPending,
- feedReplies, sourceSession, metricContext,
- prevOpsPerSecTime, operationsForOpsPerSec));
- }
-
- void drain() throws InterruptedException {
- if (settings.drain) {
- while (numPending > 0) {
- OperationStatus o = feedReplies.take();
- decreasePending(o);
- }
- }
- }
-
- private void decreasePending(OperationStatus o) throws InterruptedException {
- operations.put(o);
- --numPending;
- }
-
- private void enqueue(String id, String message, ErrorCode code, boolean isConditionalNotMet, Message msg)
- throws InterruptedException {
- String traceMessage = msg != null && msg.getTrace() != null && msg.getTrace().getLevel() > 0
- ? msg.getTrace().toString()
- : "";
- operations.put(new OperationStatus(message, id, code, isConditionalNotMet, traceMessage));
- }
-
- public void waitForRequestReceived() throws InterruptedException {
- requestReceived.await(1, TimeUnit.HOURS);
- }
-
- public class FeedErrorMessage extends Message {
- private long sequenceId;
-
- private FeedErrorMessage(String operationId) {
- try {
- DocumentId id = new DocumentId(operationId);
- sequenceId = Arrays.hashCode(id.getGlobalId());
- } catch (Exception e) {
- sequenceId = 0;
- }
- }
-
- @Override
- public Utf8String getProtocol() {
- return new Utf8String("vespa-feed-handler-internal-bogus-protocol");
- }
-
- @Override
- public int getType() {
- return 1234;
- }
-
- @Override
- public boolean hasSequenceId() {
- return true;
- }
-
- @Override
- public long getSequenceId() {
- return sequenceId;
- }
- }
-
-}