summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/FleetController.java4
-rw-r--r--clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/RemoteClusterControllerTask.java7
-rw-r--r--clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/VersionDependentTaskCompletion.java10
-rw-r--r--clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/SetNodeStateRequest.java10
-rw-r--r--clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/SetNodeStatesForClusterRequest.java10
-rw-r--r--clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/SetNodeStateTest.java9
-rw-r--r--clustercontroller-utils/pom.xml5
-rw-r--r--clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/requests/SetUnitStateRequest.java2
-rw-r--r--clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/JsonReader.java7
-rw-r--r--clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/RestApiHandler.java54
-rw-r--r--clustercontroller-utils/src/test/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/RestApiHandlerTest.java20
-rw-r--r--config-model-api/src/main/java/com/yahoo/config/model/api/HostProvisioner.java2
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/documentmodel/SummaryTransform.java2
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/ReloadHandler.java3
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClient.java4
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java2
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandler.java2
-rw-r--r--container-dependencies-enforcer/pom.xml2
-rw-r--r--container-dependency-versions/pom.xml9
-rw-r--r--container-search/src/main/java/com/yahoo/search/federation/vespa/ResultBuilder.java3
-rw-r--r--container-search/src/main/java/com/yahoo/search/query/profile/config/QueryProfileConfigurer.java72
-rw-r--r--container-search/src/main/java/com/yahoo/search/result/Relevance.java4
-rw-r--r--container-search/src/test/java/com/yahoo/search/pagetemplates/engine/test/MapSectionsToSectionsResult.xml6
-rw-r--r--container-search/src/test/java/com/yahoo/search/pagetemplates/engine/test/MapSourcesToSectionsResult.xml2
-rw-r--r--container-search/src/test/java/com/yahoo/search/pagetemplates/engine/test/TwoSectionsFourSourcesResult.xml2
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment.json6
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/dev-us-west-1.json6
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/prod-corp-us-east-1.json6
-rw-r--r--fat-model-dependencies/pom.xml7
-rw-r--r--jdisc_core/pom.xml13
-rw-r--r--jdisc_core/src/main/java/com/yahoo/jdisc/core/ExportPackages.java11
-rw-r--r--jdisc_core_test/integration_test/pom.xml28
-rw-r--r--jdisc_core_test/test_bundles/cert-k-pkgs/pom.xml7
-rw-r--r--jdisc_core_test/test_bundles/cert-k-pkgs/src/main/java/com/yahoo/jdisc/bundle/k/CertificateK.java23
-rw-r--r--orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorContext.java15
-rw-r--r--orchestrator/src/main/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerClientImpl.java21
-rw-r--r--orchestrator/src/test/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerClientTest.java5
-rw-r--r--orchestrator/src/test/java/com/yahoo/vespa/orchestrator/controller/SingleInstanceClusterControllerClientFactoryTest.java6
-rw-r--r--searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/integration/ml/VariableConverterTestCase.java2
-rw-r--r--vespajlib/src/main/java/com/yahoo/data/access/simple/JsonRender.java7
-rw-r--r--vespajlib/src/main/java/com/yahoo/geo/BoundingBoxParser.java5
-rw-r--r--vespajlib/src/main/java/com/yahoo/slime/JsonFormat.java7
-rw-r--r--vespajlib/src/main/java/com/yahoo/text/DoubleFormatter.java517
-rw-r--r--vespajlib/src/main/java/com/yahoo/text/DoubleParser.java182
-rw-r--r--vespajlib/src/main/java/com/yahoo/time/TimeBudget.java43
-rw-r--r--vespajlib/src/test/java/com/yahoo/text/DoubleFormatterTestCase.java15
-rw-r--r--vespajlib/src/test/java/com/yahoo/text/DoubleParserTestCase.java1
-rw-r--r--vespajlib/src/test/java/com/yahoo/text/DoubleToStringBenchmark.java1
-rw-r--r--vespajlib/src/test/java/com/yahoo/time/TimeBudgetTest.java17
49 files changed, 365 insertions, 839 deletions
diff --git a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/FleetController.java b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/FleetController.java
index 6b40577b1b0..56fe679fc6a 100644
--- a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/FleetController.java
+++ b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/FleetController.java
@@ -882,11 +882,11 @@ public class FleetController implements NodeStateOrHostInfoChangeHandler, NodeAd
*/
private void scheduleVersionDependentTasksForFutureCompletion(int completeAtVersion) {
// TODO expose and use monotonic clock instead of system clock
- final long deadlineTimePointMs = timer.getCurrentTimeInMillis() + options.getMaxDeferredTaskVersionWaitTime().toMillis();
+ final long maxDeadlineTimePointMs = timer.getCurrentTimeInMillis() + options.getMaxDeferredTaskVersionWaitTime().toMillis();
for (RemoteClusterControllerTask task : tasksPendingStateRecompute) {
log.finest(() -> String.format("Adding task of type '%s' to be completed at version %d",
task.getClass().getName(), completeAtVersion));
- taskCompletionQueue.add(new VersionDependentTaskCompletion(completeAtVersion, task, deadlineTimePointMs));
+ taskCompletionQueue.add(new VersionDependentTaskCompletion(completeAtVersion, task, maxDeadlineTimePointMs));
}
tasksPendingStateRecompute.clear();
}
diff --git a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/RemoteClusterControllerTask.java b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/RemoteClusterControllerTask.java
index e96209c083a..8382e127e13 100644
--- a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/RemoteClusterControllerTask.java
+++ b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/RemoteClusterControllerTask.java
@@ -5,6 +5,9 @@ import com.yahoo.vdslib.state.ClusterState;
import com.yahoo.vespa.clustercontroller.core.listeners.NodeAddedOrRemovedListener;
import com.yahoo.vespa.clustercontroller.core.listeners.NodeStateOrHostInfoChangeHandler;
+import java.time.Instant;
+import java.util.Optional;
+
public abstract class RemoteClusterControllerTask {
public static class Context {
@@ -65,6 +68,10 @@ public abstract class RemoteClusterControllerTask {
*/
public void handleFailure(FailureCondition condition) {}
+ public Optional<Instant> getDeadline() {
+ return Optional.empty();
+ }
+
public boolean isCompleted() {
synchronized (monitor) {
return completed;
diff --git a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/VersionDependentTaskCompletion.java b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/VersionDependentTaskCompletion.java
index 5d6a4f66467..28df5a8e35a 100644
--- a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/VersionDependentTaskCompletion.java
+++ b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/VersionDependentTaskCompletion.java
@@ -16,10 +16,12 @@ class VersionDependentTaskCompletion {
private final RemoteClusterControllerTask task;
private final long deadlineTimePointMs;
- VersionDependentTaskCompletion(long minimumVersion, RemoteClusterControllerTask task, long deadlineTimePointMs) {
+ VersionDependentTaskCompletion(long minimumVersion, RemoteClusterControllerTask task, long maxDeadlineTimePointMs) {
this.minimumVersion = minimumVersion;
this.task = task;
- this.deadlineTimePointMs = deadlineTimePointMs;
+ this.deadlineTimePointMs = task.getDeadline().map(deadline ->
+ Math.max(0, Math.min(deadline.toEpochMilli(), maxDeadlineTimePointMs)))
+ .orElse(maxDeadlineTimePointMs);
}
long getMinimumVersion() {
@@ -30,7 +32,9 @@ class VersionDependentTaskCompletion {
return task;
}
- long getDeadlineTimePointMs() { return deadlineTimePointMs; }
+ long getDeadlineTimePointMs() {
+ return deadlineTimePointMs;
+ }
@Override
public boolean equals(Object o) {
diff --git a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/SetNodeStateRequest.java b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/SetNodeStateRequest.java
index 849d8cc6e7b..4d6738940a8 100644
--- a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/SetNodeStateRequest.java
+++ b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/SetNodeStateRequest.java
@@ -2,6 +2,7 @@
package com.yahoo.vespa.clustercontroller.core.restapiv2.requests;
import com.yahoo.log.LogLevel;
+import com.yahoo.time.TimeBudget;
import com.yahoo.vdslib.state.ClusterState;
import com.yahoo.vdslib.state.Node;
import com.yahoo.vdslib.state.NodeState;
@@ -21,8 +22,10 @@ import com.yahoo.vespa.clustercontroller.utils.staterestapi.requests.SetUnitStat
import com.yahoo.vespa.clustercontroller.utils.staterestapi.response.SetResponse;
import com.yahoo.vespa.clustercontroller.utils.staterestapi.response.UnitState;
+import java.time.Instant;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
import java.util.logging.Logger;
public class SetNodeStateRequest extends Request<SetResponse> {
@@ -33,6 +36,7 @@ public class SetNodeStateRequest extends Request<SetResponse> {
private final SetUnitStateRequest.Condition condition;
private final SetUnitStateRequest.ResponseWait responseWait;
private final WantedStateSetter wantedState;
+ private final TimeBudget timeBudget;
public SetNodeStateRequest(Id.Node id, SetUnitStateRequest setUnitStateRequest) {
this(id, setUnitStateRequest, SetNodeStateRequest::setWantedState);
@@ -46,6 +50,7 @@ public class SetNodeStateRequest extends Request<SetResponse> {
this.condition = setUnitStateRequest.getCondition();
this.responseWait = setUnitStateRequest.getResponseWait();
this.wantedState = wantedState;
+ this.timeBudget = setUnitStateRequest.timeBudget();
}
@Override
@@ -79,6 +84,11 @@ public class SetNodeStateRequest extends Request<SetResponse> {
}
@Override
+ public Optional<Instant> getDeadline() {
+ return timeBudget.deadline();
+ }
+
+ @Override
public boolean isFailed() {
// Failure to set a node state is propagated as a 200 with wasModified false.
return super.isFailed() || (resultSet && !result.getWasModified());
diff --git a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/SetNodeStatesForClusterRequest.java b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/SetNodeStatesForClusterRequest.java
index 1246ba62313..b4d189bcd55 100644
--- a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/SetNodeStatesForClusterRequest.java
+++ b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/SetNodeStatesForClusterRequest.java
@@ -1,6 +1,7 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.clustercontroller.core.restapiv2.requests;
+import com.yahoo.time.TimeBudget;
import com.yahoo.vdslib.distribution.ConfiguredNode;
import com.yahoo.vdslib.state.Node;
import com.yahoo.vdslib.state.NodeType;
@@ -14,7 +15,9 @@ import com.yahoo.vespa.clustercontroller.utils.staterestapi.requests.SetUnitStat
import com.yahoo.vespa.clustercontroller.utils.staterestapi.response.SetResponse;
import com.yahoo.vespa.clustercontroller.utils.staterestapi.response.UnitState;
+import java.time.Instant;
import java.util.Map;
+import java.util.Optional;
import java.util.logging.Logger;
public class SetNodeStatesForClusterRequest extends Request<SetResponse> {
@@ -23,6 +26,7 @@ public class SetNodeStatesForClusterRequest extends Request<SetResponse> {
private final Id.Cluster cluster;
private final Map<String, UnitState> newStates;
private final SetUnitStateRequest.Condition condition;
+ private final TimeBudget timeBudget;
public SetNodeStatesForClusterRequest(Id.Cluster cluster, SetUnitStateRequest request) {
@@ -30,6 +34,7 @@ public class SetNodeStatesForClusterRequest extends Request<SetResponse> {
this.cluster = cluster;
this.newStates = request.getNewState();
this.condition = request.getCondition();
+ this.timeBudget = request.timeBudget();
}
@Override
@@ -80,6 +85,11 @@ public class SetNodeStatesForClusterRequest extends Request<SetResponse> {
}
@Override
+ public Optional<Instant> getDeadline() {
+ return timeBudget.deadline();
+ }
+
+ @Override
public boolean isFailed() {
// Failure to set a node state is propagated as a 200 with wasModified false.
return super.isFailed() || (resultSet && !result.getWasModified());
diff --git a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/SetNodeStateTest.java b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/SetNodeStateTest.java
index 3f977273054..f3a4be5ac2f 100644
--- a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/SetNodeStateTest.java
+++ b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/SetNodeStateTest.java
@@ -1,6 +1,7 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.clustercontroller.core.restapiv2;
+import com.yahoo.time.TimeBudget;
import com.yahoo.vdslib.state.NodeType;
import com.yahoo.vespa.clustercontroller.core.MasterInterface;
import com.yahoo.vespa.clustercontroller.core.RemoteClusterControllerTask;
@@ -20,6 +21,8 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import java.time.Clock;
+import java.time.Duration;
import java.util.LinkedHashMap;
import java.util.Map;
@@ -42,6 +45,7 @@ public class SetNodeStateTest extends StateRestApiTest {
private Map<String, UnitState> newStates = new LinkedHashMap<>();
private Condition condition = Condition.FORCE;
private ResponseWait responseWait = ResponseWait.WAIT_UNTIL_CLUSTER_ACKED;
+ private TimeBudget timeBudget = TimeBudget.fromNow(Clock.systemUTC(), Duration.ofSeconds(10));
public SetUnitStateRequestImpl(String req) {
super(req, 0);
@@ -89,6 +93,11 @@ public class SetNodeStateTest extends StateRestApiTest {
public ResponseWait getResponseWait() {
return responseWait;
}
+
+ @Override
+ public TimeBudget timeBudget() {
+ return timeBudget;
+ }
}
private void verifyStateSet(String state, String reason) throws Exception {
diff --git a/clustercontroller-utils/pom.xml b/clustercontroller-utils/pom.xml
index ecfc6df3bd0..e176ce9d1e5 100644
--- a/clustercontroller-utils/pom.xml
+++ b/clustercontroller-utils/pom.xml
@@ -40,6 +40,11 @@
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <scope>provided</scope>
+ </dependency>
</dependencies>
<build>
<plugins>
diff --git a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/requests/SetUnitStateRequest.java b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/requests/SetUnitStateRequest.java
index d583e4ecc27..a28ddb3539b 100644
--- a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/requests/SetUnitStateRequest.java
+++ b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/requests/SetUnitStateRequest.java
@@ -1,6 +1,7 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.clustercontroller.utils.staterestapi.requests;
+import com.yahoo.time.TimeBudget;
import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.InvalidContentException;
import com.yahoo.vespa.clustercontroller.utils.staterestapi.response.UnitState;
@@ -62,4 +63,5 @@ public interface SetUnitStateRequest extends UnitRequest {
}
ResponseWait getResponseWait();
+ TimeBudget timeBudget();
}
diff --git a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/JsonReader.java b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/JsonReader.java
index 3d0856669f1..d871a8ed6bc 100644
--- a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/JsonReader.java
+++ b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/JsonReader.java
@@ -12,7 +12,6 @@ import java.util.HashMap;
import java.util.Map;
public class JsonReader {
-
private static class UnitStateImpl implements UnitState {
private final String id;
private final String reason;
@@ -37,7 +36,9 @@ public class JsonReader {
final Map<String, UnitState> stateMap;
final SetUnitStateRequest.Condition condition;
final SetUnitStateRequest.ResponseWait responseWait;
- public SetRequestData(Map<String, UnitState> stateMap, SetUnitStateRequest.Condition condition,
+
+ public SetRequestData(Map<String, UnitState> stateMap,
+ SetUnitStateRequest.Condition condition,
SetUnitStateRequest.ResponseWait responseWait) {
this.stateMap = stateMap;
this.condition = condition;
@@ -98,7 +99,7 @@ public class JsonReader {
}
stateMap.put(type, new UnitStateImpl(code, reason));
}
+
return new SetRequestData(stateMap, condition, responseWait);
}
-
}
diff --git a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/RestApiHandler.java b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/RestApiHandler.java
index 71e6bc36de1..d3cab74c66f 100644
--- a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/RestApiHandler.java
+++ b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/RestApiHandler.java
@@ -1,33 +1,52 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.clustercontroller.utils.staterestapi.server;
+import com.google.common.util.concurrent.UncheckedTimeoutException;
import com.yahoo.log.LogLevel;
-import com.yahoo.yolean.Exceptions;
+import com.yahoo.time.TimeBudget;
import com.yahoo.vespa.clustercontroller.utils.communication.http.HttpRequest;
import com.yahoo.vespa.clustercontroller.utils.communication.http.HttpRequestHandler;
import com.yahoo.vespa.clustercontroller.utils.communication.http.HttpResult;
import com.yahoo.vespa.clustercontroller.utils.communication.http.JsonHttpResult;
import com.yahoo.vespa.clustercontroller.utils.staterestapi.StateRestAPI;
-import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.*;
+import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.DeadlineExceededException;
+import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.InvalidContentException;
+import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.InvalidOptionValueException;
+import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.OtherMasterException;
+import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.StateRestApiException;
+import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.UnknownMasterException;
import com.yahoo.vespa.clustercontroller.utils.staterestapi.requests.SetUnitStateRequest;
import com.yahoo.vespa.clustercontroller.utils.staterestapi.requests.UnitStateRequest;
-import com.yahoo.vespa.clustercontroller.utils.staterestapi.response.*;
+import com.yahoo.vespa.clustercontroller.utils.staterestapi.response.SetResponse;
+import com.yahoo.vespa.clustercontroller.utils.staterestapi.response.UnitResponse;
+import com.yahoo.vespa.clustercontroller.utils.staterestapi.response.UnitState;
+import com.yahoo.yolean.Exceptions;
-import java.util.*;
+import java.time.Clock;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;
public class RestApiHandler implements HttpRequestHandler {
+ public static final Duration MAX_TIMEOUT = Duration.ofHours(1);
private final static Logger log = Logger.getLogger(RestApiHandler.class.getName());
private final StateRestAPI restApi;
private final JsonWriter jsonWriter;
private final JsonReader jsonReader = new JsonReader();
+ private final Clock clock;
public RestApiHandler(StateRestAPI restApi) {
this.restApi = restApi;
this.jsonWriter = new JsonWriter();
+ this.clock = Clock.systemUTC();
}
public RestApiHandler setDefaultPathPrefix(String defaultPathPrefix) {
@@ -43,6 +62,8 @@ public class RestApiHandler implements HttpRequestHandler {
@Override
public HttpResult handleRequest(HttpRequest request) {
+ Instant start = clock.instant();
+
try{
final String[] unitPath = createUnitPath(request);
if (request.getHttpOperation().equals(HttpRequest.HttpOp.GET)) {
@@ -60,6 +81,7 @@ public class RestApiHandler implements HttpRequestHandler {
return new JsonHttpResult().setJson(jsonWriter.createJson(data));
} else {
final JsonReader.SetRequestData setRequestData = jsonReader.getStateRequestData(request);
+ final Optional<Duration> timeout = parseTimeout(request.getOption("timeout", null));
SetResponse setResponse = restApi.setUnitState(new SetUnitStateRequest() {
@Override
public Map<String, UnitState> getNewState() {
@@ -73,6 +95,8 @@ public class RestApiHandler implements HttpRequestHandler {
public Condition getCondition() { return setRequestData.condition; }
@Override
public ResponseWait getResponseWait() { return setRequestData.responseWait; }
+ @Override
+ public TimeBudget timeBudget() { return TimeBudget.from(clock, start, timeout); }
});
return new JsonHttpResult().setJson(jsonWriter.createJson(setResponse));
}
@@ -89,7 +113,7 @@ public class RestApiHandler implements HttpRequestHandler {
result.setHttpCode(503, "Service Unavailable");
result.setJson(jsonWriter.createErrorJson(exception.getMessage()));
return result;
- } catch (DeadlineExceededException exception) {
+ } catch (DeadlineExceededException | UncheckedTimeoutException exception) {
logRequestException(request, exception, Level.WARNING);
JsonHttpResult result = new JsonHttpResult();
result.setHttpCode(504, "Gateway Timeout");
@@ -172,4 +196,24 @@ public class RestApiHandler implements HttpRequestHandler {
return value;
}
+ static Optional<Duration> parseTimeout(String timeoutOption) throws InvalidContentException {
+ if (timeoutOption == null) {
+ return Optional.empty();
+ }
+
+ float timeoutSeconds;
+ try {
+ timeoutSeconds = Float.parseFloat(timeoutOption);
+ } catch (NumberFormatException e) {
+ throw new InvalidContentException("value of timeout->" + timeoutOption + " is not a float");
+ }
+
+ if (timeoutSeconds <= 0.0) {
+ return Optional.of(Duration.ZERO);
+ } else if (timeoutSeconds <= MAX_TIMEOUT.getSeconds()) {
+ return Optional.of(Duration.ofMillis(Math.round(timeoutSeconds * 1000)));
+ } else {
+ throw new InvalidContentException("value of timeout->" + timeoutOption + " exceeds max timeout " + MAX_TIMEOUT);
+ }
+ }
}
diff --git a/clustercontroller-utils/src/test/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/RestApiHandlerTest.java b/clustercontroller-utils/src/test/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/RestApiHandlerTest.java
new file mode 100644
index 00000000000..f7f109fffc8
--- /dev/null
+++ b/clustercontroller-utils/src/test/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/RestApiHandlerTest.java
@@ -0,0 +1,20 @@
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.clustercontroller.utils.staterestapi.server;
+
+import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.InvalidContentException;
+import org.junit.Test;
+
+import java.time.Duration;
+import java.util.Optional;
+
+import static org.junit.Assert.assertEquals;
+
+public class RestApiHandlerTest {
+ @Test
+ public void testParsingOfTimeout() throws InvalidContentException {
+ assertEquals(Optional.empty(), RestApiHandler.parseTimeout(null));
+ assertEquals(Optional.of(Duration.ofMillis(12500)), RestApiHandler.parseTimeout("12.5"));
+ assertEquals(Optional.of(Duration.ofMillis(0)), RestApiHandler.parseTimeout("-1"));
+ assertEquals(Optional.of(Duration.ofMillis(0)), RestApiHandler.parseTimeout("0.0001"));
+ }
+} \ No newline at end of file
diff --git a/config-model-api/src/main/java/com/yahoo/config/model/api/HostProvisioner.java b/config-model-api/src/main/java/com/yahoo/config/model/api/HostProvisioner.java
index e182b11522b..4738249b420 100644
--- a/config-model-api/src/main/java/com/yahoo/config/model/api/HostProvisioner.java
+++ b/config-model-api/src/main/java/com/yahoo/config/model/api/HostProvisioner.java
@@ -11,7 +11,7 @@ import java.util.logging.Level;
* and {@link com.yahoo.config.provision.Provisioner}, is that this interface only exposes methods needed
* to build the model.
*
- * @author lulf
+ * @author Ulf Lilleengen
*/
public interface HostProvisioner {
diff --git a/config-model/src/main/java/com/yahoo/vespa/documentmodel/SummaryTransform.java b/config-model/src/main/java/com/yahoo/vespa/documentmodel/SummaryTransform.java
index 082265c7694..4f85dd0c84e 100644
--- a/config-model/src/main/java/com/yahoo/vespa/documentmodel/SummaryTransform.java
+++ b/config-model/src/main/java/com/yahoo/vespa/documentmodel/SummaryTransform.java
@@ -24,7 +24,7 @@ public enum SummaryTransform {
private String name;
- private SummaryTransform(String name) {
+ SummaryTransform(String name) {
this.name=name;
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ReloadHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/ReloadHandler.java
index b493e2c7bc6..93af4b1d593 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/ReloadHandler.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/ReloadHandler.java
@@ -9,8 +9,7 @@ import java.util.Set;
/**
* Interface representing a reload handler.
*
- * @author lulf
- * @since 5.1.24
+ * @author Ulf Lilleengen
*/
public interface ReloadHandler {
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClient.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClient.java
index 68704eeb66a..f9f84de1cfb 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClient.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClient.java
@@ -360,8 +360,8 @@ public class ZooKeeperClient {
}
}
- public void write(AllocatedHosts info) throws IOException {
- configCurator.putData(rootPath.append(ZKApplicationPackage.allocatedHostsNode).getAbsolute(), info.toJson());
+ public void write(AllocatedHosts hosts) throws IOException {
+ configCurator.putData(rootPath.append(ZKApplicationPackage.allocatedHostsNode).getAbsolute(), hosts.toJson());
}
public void write(Map<Version, FileRegistry> fileRegistryMap) {
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java
index 9374d68a6ac..bc7c428833b 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java
@@ -62,7 +62,7 @@ public class RemoteSession extends Session {
return ApplicationSet.fromList(applicationLoader.buildModels(zooKeeperClient.readApplicationId(),
zooKeeperClient.readVespaVersion(),
- zooKeeperClient.loadApplicationPackage(),
+ applicationPackage,
new SettableOptional<>(allocatedHosts),
clock.instant()));
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandler.java
index 8d7023fef5b..f30a58cffea 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandler.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandler.java
@@ -123,7 +123,7 @@ public class TenantRequestHandler implements RequestHandler, ReloadHandler, Host
private void setLiveApp(ApplicationSet applicationSet) {
ApplicationId id = applicationSet.getId();
- final Collection<String> hostsForApp = applicationSet.getAllHosts();
+ Collection<String> hostsForApp = applicationSet.getAllHosts();
hostRegistry.update(id, hostsForApp);
applicationSet.updateHostMetrics();
tenantMetricUpdater.setApplications(applicationMapper.numApplications());
diff --git a/container-dependencies-enforcer/pom.xml b/container-dependencies-enforcer/pom.xml
index fa55908befe..f693517c844 100644
--- a/container-dependencies-enforcer/pom.xml
+++ b/container-dependencies-enforcer/pom.xml
@@ -88,6 +88,7 @@
<include>com.google.inject.extensions:guice-assistedinject:[${guice.version}]:jar:provided</include>
<include>com.google.inject.extensions:guice-multibindings:[${guice.version}]:jar:provided</include>
<include>com.google.inject:guice:[${guice.version}]:jar:provided:no_aop</include>
+ <include>com.sun.activation:javax.activation:jar[1.2.0]:jar:provided</include>
<include>commons-codec:commons-codec:[1.4]:jar:provided</include>
<include>commons-daemon:commons-daemon:[1.0.3]:jar:provided</include>
<include>commons-logging:commons-logging:[1.1.1]:jar:provided</include>
@@ -96,6 +97,7 @@
<include>javax.servlet:javax.servlet-api:[3.1.0]:jar:provided</include>
<include>javax.validation:validation-api:[${javax.validation-api.version}]:jar:provided</include>
<include>javax.ws.rs:javax.ws.rs-api:[${javax.ws.rs-api.version}]:jar:provided</include>
+ <include>javax.xml.bind:jaxb-api:[${jaxb.version}]:jar:provided</include>
<include>net.jcip:jcip-annotations:[1.0]:jar:provided</include>
<include>net.jpountz.lz4:lz4:[1.3.0]:jar:provided</include>
<include>org.apache.felix:org.apache.felix.framework:[${felix.version}]:jar:provided</include>
diff --git a/container-dependency-versions/pom.xml b/container-dependency-versions/pom.xml
index 4d9c1e94ed9..195e66902db 100644
--- a/container-dependency-versions/pom.xml
+++ b/container-dependency-versions/pom.xml
@@ -186,7 +186,7 @@
<version>${javax.ws.rs-api.version}</version>
</dependency>
- <!-- TODO: upgrade jaxb-api artifacts to >=2.3.0. Note that from 2.3, these are OSGi bundles.
+ <!-- TODO: upgrade jaxb-api artifacts to >=2.3.0.
See https://stackoverflow.com/questions/50237516/proper-fix-for-java-10-complaining-about-illegal-reflection-access-by-jaxb-impl -->
<dependency>
<groupId>javax.xml.bind</groupId>
@@ -204,10 +204,11 @@
<version>${jaxb.version}</version>
</dependency>
<dependency>
- <groupId>javax.activation</groupId>
- <artifactId>javax.activation-api</artifactId>
+ <groupId>com.sun.activation</groupId>
+ <artifactId>javax.activation</artifactId>
<version>1.2.0</version>
</dependency>
+ <!-- jaxb end -->
<dependency>
<groupId>net.jcip</groupId>
@@ -456,7 +457,7 @@
<findbugs.version>1.3.9</findbugs.version>
<guava.version>18.0</guava.version>
<guice.version>3.0</guice.version>
- <jaxb.version>2.2.7</jaxb.version>
+ <jaxb.version>2.3.0</jaxb.version>
<jetty.version>9.4.10.v20180503</jetty.version>
<slf4j.version>1.7.5</slf4j.version>
diff --git a/container-search/src/main/java/com/yahoo/search/federation/vespa/ResultBuilder.java b/container-search/src/main/java/com/yahoo/search/federation/vespa/ResultBuilder.java
index 71971b56ef1..dd20472474d 100644
--- a/container-search/src/main/java/com/yahoo/search/federation/vespa/ResultBuilder.java
+++ b/container-search/src/main/java/com/yahoo/search/federation/vespa/ResultBuilder.java
@@ -10,7 +10,6 @@ import com.yahoo.search.result.Hit;
import com.yahoo.search.result.HitGroup;
import com.yahoo.search.result.Relevance;
import com.yahoo.text.XML;
-import com.yahoo.text.DoubleParser;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
@@ -472,7 +471,7 @@ public class ResultBuilder extends DefaultHandler {
//We try to get either uri or documentID and use that as id
Object docId = extractDocumentID();
Hit newHit = new Hit(docId.toString());
- if (hitRelevance != null) newHit.setRelevance(new Relevance(DoubleParser.parse(hitRelevance)));
+ if (hitRelevance != null) newHit.setRelevance(new Relevance(Double.parseDouble(hitRelevance)));
if(hitSource != null) newHit.setSource(hitSource);
if(hitType != null) {
for(String type: hitType.split(" ")) {
diff --git a/container-search/src/main/java/com/yahoo/search/query/profile/config/QueryProfileConfigurer.java b/container-search/src/main/java/com/yahoo/search/query/profile/config/QueryProfileConfigurer.java
index 410f10edda8..1af78982b9c 100644
--- a/container-search/src/main/java/com/yahoo/search/query/profile/config/QueryProfileConfigurer.java
+++ b/container-search/src/main/java/com/yahoo/search/query/profile/config/QueryProfileConfigurer.java
@@ -42,23 +42,23 @@ public class QueryProfileConfigurer implements ConfigSubscriber.SingleSubscriber
}
public static QueryProfileRegistry createFromConfig(QueryProfilesConfig config) {
- QueryProfileRegistry registry=new QueryProfileRegistry();
+ QueryProfileRegistry registry = new QueryProfileRegistry();
// Pass 1: Create all profiles and profile types
for (QueryProfilesConfig.Queryprofiletype profileTypeConfig : config.queryprofiletype()) {
- createProfileType(profileTypeConfig,registry.getTypeRegistry());
+ createProfileType(profileTypeConfig, registry.getTypeRegistry());
}
for (QueryProfilesConfig.Queryprofile profileConfig : config.queryprofile()) {
- createProfile(profileConfig,registry);
+ createProfile(profileConfig, registry);
}
// Pass 2: Resolve references and add content
for (QueryProfilesConfig.Queryprofiletype profileTypeConfig : config.queryprofiletype()) {
- fillProfileType(profileTypeConfig,registry.getTypeRegistry());
+ fillProfileType(profileTypeConfig, registry.getTypeRegistry());
}
- // To ensure topological sorting, using DPS. This will _NOT_ detect cycles (but it will not fail if they
- // exist either)
+ // To ensure topological sorting, using DPS. This will _NOT_ detect cycles
+ // (but it will not fail if they exist)
Set<ComponentId> filled = new HashSet<>();
for (QueryProfilesConfig.Queryprofile profileConfig : config.queryprofile()) {
fillProfile(profileConfig, config, registry, filled);
@@ -73,29 +73,29 @@ public class QueryProfileConfigurer implements ConfigSubscriber.SingleSubscriber
subscriber.close();
}
- private static void createProfile(QueryProfilesConfig.Queryprofile config,QueryProfileRegistry registry) {
- QueryProfile profile=new QueryProfile(config.id());
+ private static void createProfile(QueryProfilesConfig.Queryprofile config, QueryProfileRegistry registry) {
+ QueryProfile profile = new QueryProfile(config.id());
try {
- String typeId=config.type();
- if (typeId!=null && !typeId.isEmpty())
+ String typeId = config.type();
+ if (typeId != null && ! typeId.isEmpty())
profile.setType(registry.getType(typeId));
if (config.dimensions().size()>0) {
- String[] dimensions=new String[config.dimensions().size()];
- for (int i=0; i<config.dimensions().size(); i++)
- dimensions[i]=config.dimensions().get(i);
+ String[] dimensions = new String[config.dimensions().size()];
+ for (int i = 0; i < config.dimensions().size(); i++)
+ dimensions[i] = config.dimensions().get(i);
profile.setDimensions(dimensions);
}
registry.register(profile);
}
catch (IllegalArgumentException e) {
- throw new IllegalArgumentException("Invalid " + profile,e);
+ throw new IllegalArgumentException("Invalid " + profile, e);
}
}
private static void createProfileType(QueryProfilesConfig.Queryprofiletype config, QueryProfileTypeRegistry registry) {
- QueryProfileType type=new QueryProfileType(config.id());
+ QueryProfileType type = new QueryProfileType(config.id());
type.setStrict(config.strict());
type.setMatchAsPath(config.matchaspath());
registry.register(type);
@@ -105,46 +105,46 @@ public class QueryProfileConfigurer implements ConfigSubscriber.SingleSubscriber
QueryProfilesConfig queryProfilesConfig,
QueryProfileRegistry registry,
Set<ComponentId> filled) {
- QueryProfile profile=registry.getComponent(new ComponentSpecification(config.id()).toId());
+ QueryProfile profile = registry.getComponent(new ComponentSpecification(config.id()).toId());
if (filled.contains(profile.getId())) return;
filled.add(profile.getId());
try {
for (String inheritedId : config.inherit()) {
- QueryProfile inherited=registry.getComponent(inheritedId);
- if (inherited==null)
+ QueryProfile inherited = registry.getComponent(inheritedId);
+ if (inherited == null)
throw new IllegalArgumentException("Inherited query profile '" + inheritedId + "' in " + profile + " was not found");
fillProfile(inherited, queryProfilesConfig, registry, filled);
profile.addInherited(inherited);
}
for (QueryProfilesConfig.Queryprofile.Reference referenceConfig : config.reference()) {
- QueryProfile referenced=registry.getComponent(referenceConfig.value());
- if (referenced==null)
+ QueryProfile referenced = registry.getComponent(referenceConfig.value());
+ if (referenced == null)
throw new IllegalArgumentException("Query profile '" + referenceConfig.value() + "' referenced as '" +
referenceConfig.name() + "' in " + profile + " was not found");
- profile.set(referenceConfig.name(),referenced, registry);
- if (referenceConfig.overridable()!=null && !referenceConfig.overridable().isEmpty())
- profile.setOverridable(referenceConfig.name(),BooleanParser.parseBoolean(referenceConfig.overridable()),null);
+ profile.set(referenceConfig.name(), referenced, registry);
+ if (referenceConfig.overridable() != null && !referenceConfig.overridable().isEmpty())
+ profile.setOverridable(referenceConfig.name(), BooleanParser.parseBoolean(referenceConfig.overridable()), null);
}
for (QueryProfilesConfig.Queryprofile.Property propertyConfig : config.property()) {
- profile.set(propertyConfig.name(),propertyConfig.value(), registry);
- if (propertyConfig.overridable()!=null && !propertyConfig.overridable().isEmpty())
- profile.setOverridable(propertyConfig.name(),BooleanParser.parseBoolean(propertyConfig.overridable()),null);
+ profile.set(propertyConfig.name(), propertyConfig.value(), registry);
+ if (propertyConfig.overridable() != null && ! propertyConfig.overridable().isEmpty())
+ profile.setOverridable(propertyConfig.name(), BooleanParser.parseBoolean(propertyConfig.overridable()), null);
}
for (QueryProfilesConfig.Queryprofile.Queryprofilevariant variantConfig : config.queryprofilevariant()) {
- String[] forDimensionValueArray=new String[variantConfig.fordimensionvalues().size()];
- for (int i=0; i<variantConfig.fordimensionvalues().size(); i++) {
- forDimensionValueArray[i]=variantConfig.fordimensionvalues().get(i).trim();
+ String[] forDimensionValueArray = new String[variantConfig.fordimensionvalues().size()];
+ for (int i = 0; i<variantConfig.fordimensionvalues().size(); i++) {
+ forDimensionValueArray[i] = variantConfig.fordimensionvalues().get(i).trim();
if ("*".equals(forDimensionValueArray[i]))
- forDimensionValueArray[i]=null;
+ forDimensionValueArray[i] = null;
}
- DimensionValues forDimensionValues=DimensionValues.createFrom(forDimensionValueArray);
+ DimensionValues forDimensionValues = DimensionValues.createFrom(forDimensionValueArray);
for (String inheritedId : variantConfig.inherit()) {
- QueryProfile inherited=registry.getComponent(inheritedId);
- if (inherited==null)
+ QueryProfile inherited = registry.getComponent(inheritedId);
+ if (inherited == null)
throw new IllegalArgumentException("Inherited query profile '" + inheritedId + "' in " + profile +
" for '" + forDimensionValues + "' was not found");
fillProfile(inherited, queryProfilesConfig, registry, filled);
@@ -153,7 +153,7 @@ public class QueryProfileConfigurer implements ConfigSubscriber.SingleSubscriber
for (QueryProfilesConfig.Queryprofile.Queryprofilevariant.Reference referenceConfig : variantConfig.reference()) {
QueryProfile referenced=registry.getComponent(referenceConfig.value());
- if (referenced==null)
+ if (referenced == null)
throw new IllegalArgumentException("Query profile '" + referenceConfig.value() + "' referenced as '" +
referenceConfig.name() + "' in " + profile + " for '" + forDimensionValues + "' was not found");
profile.set(referenceConfig.name(), referenced, forDimensionValues, registry);
@@ -167,7 +167,7 @@ public class QueryProfileConfigurer implements ConfigSubscriber.SingleSubscriber
}
catch (IllegalArgumentException e) {
- throw new IllegalArgumentException("Invalid " + profile,e);
+ throw new IllegalArgumentException("Invalid " + profile, e);
}
}
@@ -218,7 +218,7 @@ public class QueryProfileConfigurer implements ConfigSubscriber.SingleSubscriber
type.addField(field, registry);
}
catch (IllegalArgumentException e) {
- throw new IllegalArgumentException("Invalid field '" + fieldConfig.name() + "' in " + type,e);
+ throw new IllegalArgumentException("Invalid field '" + fieldConfig.name() + "' in " + type, e);
}
}
diff --git a/container-search/src/main/java/com/yahoo/search/result/Relevance.java b/container-search/src/main/java/com/yahoo/search/result/Relevance.java
index 7737b01cc14..69d49dc33ed 100644
--- a/container-search/src/main/java/com/yahoo/search/result/Relevance.java
+++ b/container-search/src/main/java/com/yahoo/search/result/Relevance.java
@@ -1,8 +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.result;
-import com.yahoo.text.DoubleFormatter;
-
/**
* A relevance double value. These values should always be normalized between 0 and 1 (where 1 means perfect),
* however, this is not enforced.
@@ -47,7 +45,7 @@ public class Relevance implements Comparable<Relevance> {
*/
@Override
public String toString() {
- return DoubleFormatter.stringValue(score);
+ return String.valueOf(score);
}
/** Compares relevancy values with */
diff --git a/container-search/src/test/java/com/yahoo/search/pagetemplates/engine/test/MapSectionsToSectionsResult.xml b/container-search/src/test/java/com/yahoo/search/pagetemplates/engine/test/MapSectionsToSectionsResult.xml
index cb63af526a0..4272e54aeec 100644
--- a/container-search/src/test/java/com/yahoo/search/pagetemplates/engine/test/MapSectionsToSectionsResult.xml
+++ b/container-search/src/test/java/com/yahoo/search/pagetemplates/engine/test/MapSectionsToSectionsResult.xml
@@ -64,10 +64,10 @@
<hit relevance="0.2" source="source5">
<id>source5-5</id>
</hit>
- <hit relevance="0.1666666666666667" source="source5">
+ <hit relevance="0.16666666666666666" source="source5">
<id>source5-6</id>
</hit>
- <hit relevance="0.1428571428571428" source="source5">
+ <hit relevance="0.14285714285714285" source="source5">
<id>source5-7</id>
</hit>
</section>
@@ -87,7 +87,7 @@
<hit relevance="0.2" source="source4">
<id>source4-5</id>
</hit>
- <hit relevance="0.1666666666666667" source="source4">
+ <hit relevance="0.16666666666666666" source="source4">
<id>source4-6</id>
</hit>
</section>
diff --git a/container-search/src/test/java/com/yahoo/search/pagetemplates/engine/test/MapSourcesToSectionsResult.xml b/container-search/src/test/java/com/yahoo/search/pagetemplates/engine/test/MapSourcesToSectionsResult.xml
index 1b8b5a71e35..623918c8739 100644
--- a/container-search/src/test/java/com/yahoo/search/pagetemplates/engine/test/MapSourcesToSectionsResult.xml
+++ b/container-search/src/test/java/com/yahoo/search/pagetemplates/engine/test/MapSourcesToSectionsResult.xml
@@ -64,7 +64,7 @@
<hit relevance="0.2" source="source4">
<id>source4-5</id>
</hit>
- <hit relevance="0.1666666666666667" source="source4">
+ <hit relevance="0.16666666666666666" source="source4">
<id>source4-6</id>
</hit>
</section>
diff --git a/container-search/src/test/java/com/yahoo/search/pagetemplates/engine/test/TwoSectionsFourSourcesResult.xml b/container-search/src/test/java/com/yahoo/search/pagetemplates/engine/test/TwoSectionsFourSourcesResult.xml
index eb2e458ac6d..73b62afd6c1 100644
--- a/container-search/src/test/java/com/yahoo/search/pagetemplates/engine/test/TwoSectionsFourSourcesResult.xml
+++ b/container-search/src/test/java/com/yahoo/search/pagetemplates/engine/test/TwoSectionsFourSourcesResult.xml
@@ -57,7 +57,7 @@
<hit relevance="0.2" source="source4">
<id>source4-5</id>
</hit>
- <hit relevance="0.1666666666666667" source="source4">
+ <hit relevance="0.16666666666666666" source="source4">
<id>source4-6</id>
</hit>
</section>
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment.json
index 2ce9d69472a..b790cec3912 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment.json
@@ -25,12 +25,12 @@
"cost": {
"tco": 74,
"waste": 0,
- "utilization": 2.999999999999999,
+ "utilization": 2.9999999999999996,
"cluster": {
"cluster1": {
"count": 2,
"resource": "cpu",
- "utilization": 2.999999999999999,
+ "utilization": 2.9999999999999996,
"tco": 74,
"waste": 0,
"flavor": "flavor1",
@@ -40,7 +40,7 @@
"flavorDisk":50.0,
"type": "content",
"util": {
- "cpu": 2.999999999999999,
+ "cpu": 2.9999999999999996,
"mem": 0.4285714285714286,
"disk": 0.5714285714285715,
"diskBusy": 1.0
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/dev-us-west-1.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/dev-us-west-1.json
index ab86b891fae..f6eae19337a 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/dev-us-west-1.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/dev-us-west-1.json
@@ -24,12 +24,12 @@
"cost": {
"tco": 74,
"waste": 0,
- "utilization": 2.999999999999999,
+ "utilization": 2.9999999999999996,
"cluster": {
"cluster1": {
"count": 2,
"resource": "cpu",
- "utilization": 2.999999999999999,
+ "utilization": 2.9999999999999996,
"tco": 74,
"waste": 0,
"flavor": "flavor1",
@@ -39,7 +39,7 @@
"flavorDisk": 50.0,
"type": "content",
"util": {
- "cpu": 2.999999999999999,
+ "cpu": 2.9999999999999996,
"mem": 0.4285714285714286,
"disk": 0.5714285714285715,
"diskBusy": 1.0
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/prod-corp-us-east-1.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/prod-corp-us-east-1.json
index 902bda472cf..b35a53eb1a4 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/prod-corp-us-east-1.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/prod-corp-us-east-1.json
@@ -31,12 +31,12 @@
"cost": {
"tco": 74,
"waste": 0,
- "utilization": 2.999999999999999,
+ "utilization": 2.9999999999999996,
"cluster": {
"cluster1": {
"count": 2,
"resource": "cpu",
- "utilization": 2.999999999999999,
+ "utilization": 2.9999999999999996,
"tco": 74,
"waste": 0,
"flavor": "flavor1",
@@ -46,7 +46,7 @@
"flavorDisk": 50.0,
"type": "content",
"util": {
- "cpu": 2.999999999999999,
+ "cpu": 2.9999999999999996,
"mem": 0.4285714285714286,
"disk": 0.5714285714285715,
"diskBusy": 1.0
diff --git a/fat-model-dependencies/pom.xml b/fat-model-dependencies/pom.xml
index 68abc36c678..0421f0bbd01 100644
--- a/fat-model-dependencies/pom.xml
+++ b/fat-model-dependencies/pom.xml
@@ -26,6 +26,13 @@
<groupId>com.yahoo.vespa</groupId>
<artifactId>provided-dependencies</artifactId>
<version>${project.version}</version>
+ <exclusions>
+ <exclusion>
+ <!-- Not needed runtime, and a multi-release jar which is currently not supported by maven-bundle-plugin (really bndtools) -->
+ <groupId>javax.xml.bind</groupId>
+ <artifactId>jaxb-api</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
<groupId>commons-io</groupId>
diff --git a/jdisc_core/pom.xml b/jdisc_core/pom.xml
index 246265203cb..6b22aa4a985 100644
--- a/jdisc_core/pom.xml
+++ b/jdisc_core/pom.xml
@@ -16,6 +16,17 @@
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<dependencies>
+ <!-- Necessary for jaxb support from java 9. (Could be deployed as bundles since 2.2.11.) -->
+ <dependency>
+ <groupId>javax.xml.bind</groupId>
+ <artifactId>jaxb-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.activation</groupId>
+ <artifactId>javax.activation</artifactId>
+ </dependency>
+ <!-- jaxb end -->
+
<dependency>
<!-- Newer version than the one in rt.jar, including the ElementTraversal class needed by Xerces (Aug 2015, still valid Sep 2017) -->
<groupId>xml-apis</groupId>
@@ -228,6 +239,8 @@
<argument>${project.build.directory}/dependency/log4j-over-slf4j.jar</argument>
<argument>${project.build.directory}/dependency/config-lib.jar</argument>
<argument>${project.build.directory}/dependency/yolean.jar</argument>
+ <argument>${project.build.directory}/dependency/jaxb-api.jar</argument>
+ <argument>${project.build.directory}/dependency/javax.activation.jar</argument>
</arguments>
</configuration>
</execution>
diff --git a/jdisc_core/src/main/java/com/yahoo/jdisc/core/ExportPackages.java b/jdisc_core/src/main/java/com/yahoo/jdisc/core/ExportPackages.java
index 8da1a4fad99..86ab016bded 100644
--- a/jdisc_core/src/main/java/com/yahoo/jdisc/core/ExportPackages.java
+++ b/jdisc_core/src/main/java/com/yahoo/jdisc/core/ExportPackages.java
@@ -38,9 +38,11 @@ public class ExportPackages {
.append("javax.inject;version=1.0.0,") // Included in guice, but not exported. Needed by container-jersey.
.append("org.aopalliance.intercept,")
.append("org.aopalliance.aop,")
+ .append("sun.misc,")
+ .append("sun.net.util,")
+ .append("sun.security.krb5,")
- // xml-apis:xml-apis:1.4.01 is not a bundle
- .append("org.w3c.dom,")
+ // TODO: remove for Vespa 7 (xml-apis:xml-apis:1.4.01 is not a bundle, but exposed from system classpath on Java 9)
.append("org.w3c.dom.bootstrap,")
.append("org.w3c.dom.css,")
.append("org.w3c.dom.events,")
@@ -49,11 +51,8 @@ public class ExportPackages {
.append("org.w3c.dom.ranges,")
.append("org.w3c.dom.stylesheets,")
.append("org.w3c.dom.traversal,")
- .append("org.w3c.dom.views,")
+ .append("org.w3c.dom.views");
- .append("sun.misc,")
- .append("sun.net.util,")
- .append("sun.security.krb5");
for (int i = 1; i < args.length; ++i) {
out.append(",").append(getExportedPackages(args[i]));
}
diff --git a/jdisc_core_test/integration_test/pom.xml b/jdisc_core_test/integration_test/pom.xml
index d68d6e2966b..e31fa122232 100644
--- a/jdisc_core_test/integration_test/pom.xml
+++ b/jdisc_core_test/integration_test/pom.xml
@@ -230,14 +230,34 @@
<scope>test</scope>
</dependency>
</dependencies>
+ <profiles>
+ <profile>
+ <id>java9-surefire</id>
+ <activation>
+ <jdk>[9, )</jdk>
+ </activation>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <!-- Allow installing fragment bundles, see felix.framework:ExtensionManager.addExtensionBundle -->
+ <argLine>
+ --add-opens=java.base/jdk.internal.loader=ALL-UNNAMED
+ </argLine>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+ </profile>
+ </profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
diff --git a/jdisc_core_test/test_bundles/cert-k-pkgs/pom.xml b/jdisc_core_test/test_bundles/cert-k-pkgs/pom.xml
index f0e16644a41..37e8469afdc 100644
--- a/jdisc_core_test/test_bundles/cert-k-pkgs/pom.xml
+++ b/jdisc_core_test/test_bundles/cert-k-pkgs/pom.xml
@@ -14,13 +14,6 @@
<version>6-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>${project.artifactId}</name>
- <dependencies>
- <dependency>
- <groupId>javax.xml.bind</groupId>
- <artifactId>jaxb-api</artifactId>
- <scope>provided</scope>
- </dependency>
- </dependencies>
<build>
<plugins>
<plugin>
diff --git a/jdisc_core_test/test_bundles/cert-k-pkgs/src/main/java/com/yahoo/jdisc/bundle/k/CertificateK.java b/jdisc_core_test/test_bundles/cert-k-pkgs/src/main/java/com/yahoo/jdisc/bundle/k/CertificateK.java
index 44ec6a2ff6c..ea371eb632b 100644
--- a/jdisc_core_test/test_bundles/cert-k-pkgs/src/main/java/com/yahoo/jdisc/bundle/k/CertificateK.java
+++ b/jdisc_core_test/test_bundles/cert-k-pkgs/src/main/java/com/yahoo/jdisc/bundle/k/CertificateK.java
@@ -112,12 +112,6 @@ public class CertificateK {
private final javax.tools.FileObject fileObject = null;
private final javax.transaction.xa.XAException xaException = null;
private final javax.xml.XMLConstants xmlConstants = null;
- private final javax.xml.bind.DataBindingException dataBindingException = null;
- private final javax.xml.bind.annotation.DomHandler<?,?> domHandler = null;
- private final javax.xml.bind.annotation.adapters.CollapsedStringAdapter collapsedStringAdapter = null;
- private final javax.xml.bind.attachment.AttachmentMarshaller attachmentMarshaller = null;
- private final javax.xml.bind.helpers.AbstractMarshallerImpl abstractMarshaller = null;
- private final javax.xml.bind.util.JAXBResult jaxbResult = null;
private final javax.xml.crypto.AlgorithmMethod algorithmMethod = null;
private final javax.xml.crypto.dom.DOMCryptoContext domCryptoContext = null;
private final javax.xml.crypto.dsig.CanonicalizationMethod canonicalizationMethod = null;
@@ -174,8 +168,23 @@ public class CertificateK {
private final org.xml.sax.ext.Attributes2Impl attributes2 = null;
private final org.xml.sax.helpers.AttributesImpl attributes = null;
+
// Packages made invisible from Java 9
-// private final javax.activation.CommandInfo commandInfo = null;
+
+ // Added as dep in jdisc_core: com.sun.activation:javax.activation (OSGi bundle)
+ private final javax.activation.CommandInfo commandInfo = null;
+
+ // Added as dep in jdisc_core: javax.xml.bind:jaxb-api (OSGi bundle)
+ private final javax.xml.bind.DataBindingException dataBindingException = null;
+ private final javax.xml.bind.annotation.DomHandler<?,?> domHandler = null;
+ private final javax.xml.bind.annotation.adapters.CollapsedStringAdapter collapsedStringAdapter = null;
+ private final javax.xml.bind.attachment.AttachmentMarshaller attachmentMarshaller = null;
+ private final javax.xml.bind.helpers.AbstractMarshallerImpl abstractMarshaller = null;
+ private final javax.xml.bind.util.JAXBResult jaxbResult = null;
+
+
+ // Packages that most likely won't be provided from JDisc from Vespa 7
+
// private final javax.activity.ActivityCompletedException activityCompletedException = null;
// private final javax.jws.HandlerChain handlerChain = null;
// private final javax.jws.soap.SOAPBinding soapBinding = null;
diff --git a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorContext.java b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorContext.java
index 880eab0c755..6577b4b96cc 100644
--- a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorContext.java
+++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorContext.java
@@ -6,7 +6,6 @@ import com.yahoo.time.TimeBudget;
import java.time.Clock;
import java.time.Duration;
-import java.util.Optional;
/**
* Context for the Orchestrator, e.g. timeout management.
@@ -24,14 +23,18 @@ public class OrchestratorContext {
/** Get the original timeout in seconds. */
public long getOriginalTimeoutInSeconds() {
- return timeBudget.originalTimeout().getSeconds();
+ return timeBudget.originalTimeout().get().getSeconds();
}
/**
- * Get number of seconds until the deadline, or empty if there's no deadline, or throw
- * an {@link UncheckedTimeoutException} if timed out.
+ * Get timeout for a suboperation that should take up {@code shareOfRemaining} of the
+ * remaining time, or throw an {@link UncheckedTimeoutException} if timed out.
*/
- public Optional<Float> getSuboperationTimeoutInSeconds() {
- return Optional.of((float) (timeBudget.timeLeftOrThrow().toMillis() / 1000.0));
+ public float getSuboperationTimeoutInSeconds(float shareOfRemaining) {
+ if (!(0f <= shareOfRemaining && shareOfRemaining <= 1.0f)) {
+ throw new IllegalArgumentException("Share of remaining time must be between 0 and 1: " + shareOfRemaining);
+ }
+
+ return shareOfRemaining * timeBudget.timeLeftOrThrow().get().toMillis() / 1000.0f;
}
}
diff --git a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerClientImpl.java b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerClientImpl.java
index 7d7a9b36ff9..467b534f809 100644
--- a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerClientImpl.java
+++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerClientImpl.java
@@ -15,6 +15,23 @@ public class ClusterControllerClientImpl implements ClusterControllerClient{
public static final String REQUEST_REASON = "Orchestrator";
+ // On setNodeState calls against the CC ensemble.
+ //
+ // We'd like to set a timeout for the request to the first CC such that if the first
+ // CC is faulty, there's sufficient time to send the request to the second and third CC.
+ // The timeouts would be:
+ // timeout(1. request) = SHARE_REMAINING_TIME * T
+ // timeout(2. request) = SHARE_REMAINING_TIME * T * (1 - SHARE_REMAINING_TIME)
+ // timeout(3. request) = SHARE_REMAINING_TIME * T * (1 - SHARE_REMAINING_TIME)^2
+ //
+ // Using a share of 50% gives approximately:
+ // timeout(1. request) = T * 0.5
+ // timeout(2. request) = T * 0.25
+ // timeout(3. request) = T * 0.125
+ //
+ // which seems fine
+ public static final float SHARE_REMAINING_TIME = 0.5f;
+
private final JaxRsStrategy<ClusterControllerJaxRsApi> clusterControllerApi;
private final String clusterName;
@@ -40,7 +57,7 @@ public class ClusterControllerClientImpl implements ClusterControllerClient{
return clusterControllerApi.apply(api -> api.setNodeState(
clusterName,
storageNodeIndex,
- context.getSuboperationTimeoutInSeconds().orElse(null),
+ context.getSuboperationTimeoutInSeconds(SHARE_REMAINING_TIME),
stateRequest)
);
} catch (IOException e) {
@@ -69,7 +86,7 @@ public class ClusterControllerClientImpl implements ClusterControllerClient{
try {
return clusterControllerApi.apply(api -> api.setClusterState(
clusterName,
- context.getSuboperationTimeoutInSeconds().orElse(null),
+ context.getSuboperationTimeoutInSeconds(SHARE_REMAINING_TIME),
stateRequest));
} catch (IOException e) {
final String message = String.format(
diff --git a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerClientTest.java b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerClientTest.java
index b3f80b5129f..228174a9b3d 100644
--- a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerClientTest.java
+++ b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerClientTest.java
@@ -6,8 +6,7 @@ import com.yahoo.vespa.jaxrs.client.LocalPassThroughJaxRsStrategy;
import com.yahoo.vespa.orchestrator.OrchestratorContext;
import org.junit.Test;
-import java.util.Optional;
-
+import static org.mockito.Matchers.anyFloat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
@@ -29,7 +28,7 @@ public class ClusterControllerClientTest {
final ClusterControllerNodeState wantedState = ClusterControllerNodeState.MAINTENANCE;
OrchestratorContext context = mock(OrchestratorContext.class);
- when(context.getSuboperationTimeoutInSeconds()).thenReturn(Optional.of(1.0f));
+ when(context.getSuboperationTimeoutInSeconds(anyFloat())).thenReturn(1.0f);
clusterControllerClient.setNodeState(context, STORAGE_NODE_INDEX, wantedState);
final ClusterControllerStateRequest expectedNodeStateRequest = new ClusterControllerStateRequest(
diff --git a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/controller/SingleInstanceClusterControllerClientFactoryTest.java b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/controller/SingleInstanceClusterControllerClientFactoryTest.java
index c3dbe5c8a92..4dabae14add 100644
--- a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/controller/SingleInstanceClusterControllerClientFactoryTest.java
+++ b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/controller/SingleInstanceClusterControllerClientFactoryTest.java
@@ -10,13 +10,13 @@ import org.junit.Test;
import java.util.Arrays;
import java.util.List;
-import java.util.Optional;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyFloat;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.argThat;
@@ -67,7 +67,7 @@ public class SingleInstanceClusterControllerClientFactoryTest {
public void testCreateClientWithSingleClusterControllerInstance() throws Exception {
final List<HostName> clusterControllers = Arrays.asList(HOST_NAME_1);
- when(context.getSuboperationTimeoutInSeconds()).thenReturn(Optional.of(1.0f));
+ when(context.getSuboperationTimeoutInSeconds(anyFloat())).thenReturn(1.0f);
clientFactory.createClient(clusterControllers, "clusterName")
.setNodeState(context, 0, ClusterControllerNodeState.MAINTENANCE);
@@ -95,7 +95,7 @@ public class SingleInstanceClusterControllerClientFactoryTest {
public void testCreateClientWithThreeClusterControllerInstances() throws Exception {
final List<HostName> clusterControllers = Arrays.asList(HOST_NAME_1, HOST_NAME_2, HOST_NAME_3);
- when(context.getSuboperationTimeoutInSeconds()).thenReturn(Optional.of(1.0f));
+ when(context.getSuboperationTimeoutInSeconds(anyFloat())).thenReturn(1.0f);
clientFactory.createClient(clusterControllers, "clusterName")
.setNodeState(context, 0, ClusterControllerNodeState.MAINTENANCE);
diff --git a/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/integration/ml/VariableConverterTestCase.java b/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/integration/ml/VariableConverterTestCase.java
index f94098e6255..4e3f722fabd 100644
--- a/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/integration/ml/VariableConverterTestCase.java
+++ b/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/integration/ml/VariableConverterTestCase.java
@@ -13,7 +13,7 @@ public class VariableConverterTestCase {
byte[] converted = VariableConverter.importVariable("src/test/files/integration/tensorflow/mnist_softmax/saved",
"Variable_1",
"tensor(d0[10],d1[1])");
- assertEquals("{\"cells\":[{\"address\":{\"d0\":\"0\",\"d1\":\"0\"},\"value\":-0.3546536862850189},{\"address\":{\"d0\":\"1\",\"d1\":\"0\"},\"value\":0.3759574592113495},{\"address\":{\"d0\":\"2\",\"d1\":\"0\"},\"value\":0.06054411828517914},{\"address\":{\"d0\":\"3\",\"d1\":\"0\"},\"value\":-0.251544713973999},{\"address\":{\"d0\":\"4\",\"d1\":\"0\"},\"value\":0.01795101352035999},{\"address\":{\"d0\":\"5\",\"d1\":\"0\"},\"value\":1.289906740188599},{\"address\":{\"d0\":\"6\",\"d1\":\"0\"},\"value\":-0.1038961559534073},{\"address\":{\"d0\":\"7\",\"d1\":\"0\"},\"value\":0.6367976665496826},{\"address\":{\"d0\":\"8\",\"d1\":\"0\"},\"value\":-1.413674473762512},{\"address\":{\"d0\":\"9\",\"d1\":\"0\"},\"value\":-0.2573896050453186}]}",
+ assertEquals("{\"cells\":[{\"address\":{\"d0\":\"0\",\"d1\":\"0\"},\"value\":-0.3546536862850189},{\"address\":{\"d0\":\"1\",\"d1\":\"0\"},\"value\":0.3759574592113495},{\"address\":{\"d0\":\"2\",\"d1\":\"0\"},\"value\":0.06054411828517914},{\"address\":{\"d0\":\"3\",\"d1\":\"0\"},\"value\":-0.251544713973999},{\"address\":{\"d0\":\"4\",\"d1\":\"0\"},\"value\":0.017951013520359993},{\"address\":{\"d0\":\"5\",\"d1\":\"0\"},\"value\":1.2899067401885986},{\"address\":{\"d0\":\"6\",\"d1\":\"0\"},\"value\":-0.10389615595340729},{\"address\":{\"d0\":\"7\",\"d1\":\"0\"},\"value\":0.6367976665496826},{\"address\":{\"d0\":\"8\",\"d1\":\"0\"},\"value\":-1.4136744737625122},{\"address\":{\"d0\":\"9\",\"d1\":\"0\"},\"value\":-0.2573896050453186}]}",
new String(converted, StandardCharsets.UTF_8));
}
diff --git a/vespajlib/src/main/java/com/yahoo/data/access/simple/JsonRender.java b/vespajlib/src/main/java/com/yahoo/data/access/simple/JsonRender.java
index bc4543011b3..53be6a82dd2 100644
--- a/vespajlib/src/main/java/com/yahoo/data/access/simple/JsonRender.java
+++ b/vespajlib/src/main/java/com/yahoo/data/access/simple/JsonRender.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.data.access.simple;
-import com.yahoo.text.DoubleFormatter;
import com.yahoo.data.access.*;
/**
@@ -52,10 +51,10 @@ public final class JsonRender
}
private void encodeDOUBLE(double value) {
- if (Double.isNaN(value) || Double.isInfinite(value)) {
- out.append("null");
+ if (Double.isFinite(value)) {
+ out.append(String.valueOf(value));
} else {
- out.append(DoubleFormatter.stringValue(value));
+ out.append("null");
}
}
diff --git a/vespajlib/src/main/java/com/yahoo/geo/BoundingBoxParser.java b/vespajlib/src/main/java/com/yahoo/geo/BoundingBoxParser.java
index 5cb8c1db2de..69baa119fde 100644
--- a/vespajlib/src/main/java/com/yahoo/geo/BoundingBoxParser.java
+++ b/vespajlib/src/main/java/com/yahoo/geo/BoundingBoxParser.java
@@ -1,9 +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.geo;
-import com.yahoo.text.DoubleParser;
-
-
/**
* Class for parsing a bounding box in text format:
* "n=37.44899,s=37.3323,e=-121.98241,w=-122.06566"
@@ -102,7 +99,7 @@ public class BoundingBoxParser {
if (nsew != 0 && lastNumStartPos > 0) {
String sub = parseString.substring(lastNumStartPos, pos-1);
try {
- double v = DoubleParser.parse(sub);
+ double v = Double.parseDouble(sub);
if (nsew == 'n') {
if (doneN) {
throw new IllegalArgumentException("multiple limits for 'n' boundary");
diff --git a/vespajlib/src/main/java/com/yahoo/slime/JsonFormat.java b/vespajlib/src/main/java/com/yahoo/slime/JsonFormat.java
index d908359df19..c4c82609df7 100644
--- a/vespajlib/src/main/java/com/yahoo/slime/JsonFormat.java
+++ b/vespajlib/src/main/java/com/yahoo/slime/JsonFormat.java
@@ -6,7 +6,6 @@ import com.yahoo.io.ByteWriter;
import com.yahoo.text.AbstractUtf8Array;
import com.yahoo.text.Utf8;
import com.yahoo.text.Utf8String;
-import com.yahoo.text.DoubleFormatter;
import java.io.*;
@@ -107,10 +106,10 @@ public final class JsonFormat implements SlimeFormat
}
private void encodeDOUBLE(double value) throws IOException {
- if (Double.isNaN(value) || Double.isInfinite(value)) {
- out.write(NULL);
+ if (Double.isFinite(value)) {
+ out.write(String.valueOf(value));
} else {
- out.write(DoubleFormatter.stringValue(value));
+ out.write(NULL);
}
}
diff --git a/vespajlib/src/main/java/com/yahoo/text/DoubleFormatter.java b/vespajlib/src/main/java/com/yahoo/text/DoubleFormatter.java
index 29f038a4cd3..7281f3cd9d6 100644
--- a/vespajlib/src/main/java/com/yahoo/text/DoubleFormatter.java
+++ b/vespajlib/src/main/java/com/yahoo/text/DoubleFormatter.java
@@ -1,532 +1,35 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.text;
-import com.google.common.annotations.Beta;
-
/**
* Utility class to format a double into a String.
* <p>
- * This is intended as a lower-cost replacement for the standard
- * String.valueOf(double) since that method will cause lock
- * contention if it's used too often.
- * <p>
- * Note that this implementation won't always produce the same results
- * as java.lang.* formatting.
+ * This was intended as a lower-cost replacement for the standard
+ * String.valueOf(double) since that method used to cause contention.
* <p>
- * Also, this implementation is very poorly tested at the moment, so
- * it should be used carefully, only in cases where you know the input
- * will be well-defined and you don't need full precision.
+ * The contention issue is fixed in Java 8u96 so this class is now obsolete.
*
* @author arnej27959
*/
-@Beta
+@Deprecated
public final class DoubleFormatter {
- private static void tooSmall(StringBuilder target, long mantissa, int exponent) {
- double carry = 0;
- int prExp = 0;
- while (exponent < 0) {
- while (mantissa < (1L << 53)) {
- carry *= 10.0;
- mantissa *= 10;
- ++prExp;
- }
- carry *= 0.5;
- carry += 0.5*(mantissa & 1);
- mantissa >>= 1;
- ++exponent;
- }
- while (mantissa < (1L << 53)) {
- carry *= 10.0;
- mantissa *= 10;
- ++prExp;
- }
- mantissa += (long)(carry+0.5);
-
- int[] befor = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- int b = 0;
- for (int i = 0; mantissa > 0; i++) {
- befor[i] = (int)(mantissa % 10);
- mantissa /= 10;
- ++b;
- }
- --b;
- target.append((char)('0'+befor[b]));
- target.append('.');
- if (b == 0) {
- target.append('0');
- } else {
- for (int i = b; i-- > 0; ) {
- target.append((char)('0'+befor[i]));
- }
- }
- prExp -= b;
- target.append("E-");
- target.append(String.valueOf(prExp));
- }
-
public static StringBuilder fmt(StringBuilder target, double v) {
- append(target, v);
+ target.append(v);
return target;
}
public static String stringValue(double v) {
- return fmt(new StringBuilder(), v).toString();
+ return String.valueOf(v);
}
-
- //Hardcode some byte arrays to make them quickly available
- public static final char[] INFINITY = {'I','n','f','i','n','i','t','y'};
- public static final char[] NaN = {'N','a','N'};
- public static final char[][] ZEROS = {
- {},
- {'0'},
- {'0','0'},
- {'0','0','0'},
- {'0','0','0','0'},
- {'0','0','0','0','0'},
- {'0','0','0','0','0','0'},
- {'0','0','0','0','0','0','0'},
- {'0','0','0','0','0','0','0','0'},
- {'0','0','0','0','0','0','0','0','0'},
- {'0','0','0','0','0','0','0','0','0','0'},
- {'0','0','0','0','0','0','0','0','0','0','0'},
- {'0','0','0','0','0','0','0','0','0','0','0','0'},
- {'0','0','0','0','0','0','0','0','0','0','0','0','0'},
- {'0','0','0','0','0','0','0','0','0','0','0','0','0','0'},
- {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'},
- {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'},
- {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'},
- {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'},
- {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'},
- {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'},
- };
-
- private static final char[] charForDigit = {
- '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h',
- 'i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'
- };
-
- //And required double related constants.
- private static final long DoubleSignMask = 0x8000000000000000L;
- private static final long DoubleExpMask = 0x7ff0000000000000L;
- private static final long DoubleFractMask= ~(DoubleSignMask|DoubleExpMask);
- private static final int DoubleExpShift = 52;
- private static final int DoubleExpBias = 1023;
-
- private static final double[] d_tenthPowers = {
- 1e-323D, 1e-322D, 1e-321D, 1e-320D, 1e-319D, 1e-318D, 1e-317D, 1e-316D, 1e-315D, 1e-314D,
- 1e-313D, 1e-312D, 1e-311D, 1e-310D, 1e-309D, 1e-308D, 1e-307D, 1e-306D, 1e-305D, 1e-304D,
- 1e-303D, 1e-302D, 1e-301D, 1e-300D, 1e-299D, 1e-298D, 1e-297D, 1e-296D, 1e-295D, 1e-294D,
- 1e-293D, 1e-292D, 1e-291D, 1e-290D, 1e-289D, 1e-288D, 1e-287D, 1e-286D, 1e-285D, 1e-284D,
- 1e-283D, 1e-282D, 1e-281D, 1e-280D, 1e-279D, 1e-278D, 1e-277D, 1e-276D, 1e-275D, 1e-274D,
- 1e-273D, 1e-272D, 1e-271D, 1e-270D, 1e-269D, 1e-268D, 1e-267D, 1e-266D, 1e-265D, 1e-264D,
- 1e-263D, 1e-262D, 1e-261D, 1e-260D, 1e-259D, 1e-258D, 1e-257D, 1e-256D, 1e-255D, 1e-254D,
- 1e-253D, 1e-252D, 1e-251D, 1e-250D, 1e-249D, 1e-248D, 1e-247D, 1e-246D, 1e-245D, 1e-244D,
- 1e-243D, 1e-242D, 1e-241D, 1e-240D, 1e-239D, 1e-238D, 1e-237D, 1e-236D, 1e-235D, 1e-234D,
- 1e-233D, 1e-232D, 1e-231D, 1e-230D, 1e-229D, 1e-228D, 1e-227D, 1e-226D, 1e-225D, 1e-224D,
- 1e-223D, 1e-222D, 1e-221D, 1e-220D, 1e-219D, 1e-218D, 1e-217D, 1e-216D, 1e-215D, 1e-214D,
- 1e-213D, 1e-212D, 1e-211D, 1e-210D, 1e-209D, 1e-208D, 1e-207D, 1e-206D, 1e-205D, 1e-204D,
- 1e-203D, 1e-202D, 1e-201D, 1e-200D, 1e-199D, 1e-198D, 1e-197D, 1e-196D, 1e-195D, 1e-194D,
- 1e-193D, 1e-192D, 1e-191D, 1e-190D, 1e-189D, 1e-188D, 1e-187D, 1e-186D, 1e-185D, 1e-184D,
- 1e-183D, 1e-182D, 1e-181D, 1e-180D, 1e-179D, 1e-178D, 1e-177D, 1e-176D, 1e-175D, 1e-174D,
- 1e-173D, 1e-172D, 1e-171D, 1e-170D, 1e-169D, 1e-168D, 1e-167D, 1e-166D, 1e-165D, 1e-164D,
- 1e-163D, 1e-162D, 1e-161D, 1e-160D, 1e-159D, 1e-158D, 1e-157D, 1e-156D, 1e-155D, 1e-154D,
- 1e-153D, 1e-152D, 1e-151D, 1e-150D, 1e-149D, 1e-148D, 1e-147D, 1e-146D, 1e-145D, 1e-144D,
- 1e-143D, 1e-142D, 1e-141D, 1e-140D, 1e-139D, 1e-138D, 1e-137D, 1e-136D, 1e-135D, 1e-134D,
- 1e-133D, 1e-132D, 1e-131D, 1e-130D, 1e-129D, 1e-128D, 1e-127D, 1e-126D, 1e-125D, 1e-124D,
- 1e-123D, 1e-122D, 1e-121D, 1e-120D, 1e-119D, 1e-118D, 1e-117D, 1e-116D, 1e-115D, 1e-114D,
- 1e-113D, 1e-112D, 1e-111D, 1e-110D, 1e-109D, 1e-108D, 1e-107D, 1e-106D, 1e-105D, 1e-104D,
- 1e-103D, 1e-102D, 1e-101D, 1e-100D, 1e-99D, 1e-98D, 1e-97D, 1e-96D, 1e-95D, 1e-94D,
- 1e-93D, 1e-92D, 1e-91D, 1e-90D, 1e-89D, 1e-88D, 1e-87D, 1e-86D, 1e-85D, 1e-84D,
- 1e-83D, 1e-82D, 1e-81D, 1e-80D, 1e-79D, 1e-78D, 1e-77D, 1e-76D, 1e-75D, 1e-74D,
- 1e-73D, 1e-72D, 1e-71D, 1e-70D, 1e-69D, 1e-68D, 1e-67D, 1e-66D, 1e-65D, 1e-64D,
- 1e-63D, 1e-62D, 1e-61D, 1e-60D, 1e-59D, 1e-58D, 1e-57D, 1e-56D, 1e-55D, 1e-54D,
- 1e-53D, 1e-52D, 1e-51D, 1e-50D, 1e-49D, 1e-48D, 1e-47D, 1e-46D, 1e-45D, 1e-44D,
- 1e-43D, 1e-42D, 1e-41D, 1e-40D, 1e-39D, 1e-38D, 1e-37D, 1e-36D, 1e-35D, 1e-34D,
- 1e-33D, 1e-32D, 1e-31D, 1e-30D, 1e-29D, 1e-28D, 1e-27D, 1e-26D, 1e-25D, 1e-24D,
- 1e-23D, 1e-22D, 1e-21D, 1e-20D, 1e-19D, 1e-18D, 1e-17D, 1e-16D, 1e-15D, 1e-14D,
- 1e-13D, 1e-12D, 1e-11D, 1e-10D, 1e-9D, 1e-8D, 1e-7D, 1e-6D, 1e-5D, 1e-4D,
- 1e-3D, 1e-2D, 1e-1D, 1e0D, 1e1D, 1e2D, 1e3D, 1e4D,
- 1e5D, 1e6D, 1e7D, 1e8D, 1e9D, 1e10D, 1e11D, 1e12D, 1e13D, 1e14D,
- 1e15D, 1e16D, 1e17D, 1e18D, 1e19D, 1e20D, 1e21D, 1e22D, 1e23D, 1e24D,
- 1e25D, 1e26D, 1e27D, 1e28D, 1e29D, 1e30D, 1e31D, 1e32D, 1e33D, 1e34D,
- 1e35D, 1e36D, 1e37D, 1e38D, 1e39D, 1e40D, 1e41D, 1e42D, 1e43D, 1e44D,
- 1e45D, 1e46D, 1e47D, 1e48D, 1e49D, 1e50D, 1e51D, 1e52D, 1e53D, 1e54D,
- 1e55D, 1e56D, 1e57D, 1e58D, 1e59D, 1e60D, 1e61D, 1e62D, 1e63D, 1e64D,
- 1e65D, 1e66D, 1e67D, 1e68D, 1e69D, 1e70D, 1e71D, 1e72D, 1e73D, 1e74D,
- 1e75D, 1e76D, 1e77D, 1e78D, 1e79D, 1e80D, 1e81D, 1e82D, 1e83D, 1e84D,
- 1e85D, 1e86D, 1e87D, 1e88D, 1e89D, 1e90D, 1e91D, 1e92D, 1e93D, 1e94D,
- 1e95D, 1e96D, 1e97D, 1e98D, 1e99D, 1e100D, 1e101D, 1e102D, 1e103D, 1e104D,
- 1e105D, 1e106D, 1e107D, 1e108D, 1e109D, 1e110D, 1e111D, 1e112D, 1e113D, 1e114D,
- 1e115D, 1e116D, 1e117D, 1e118D, 1e119D, 1e120D, 1e121D, 1e122D, 1e123D, 1e124D,
- 1e125D, 1e126D, 1e127D, 1e128D, 1e129D, 1e130D, 1e131D, 1e132D, 1e133D, 1e134D,
- 1e135D, 1e136D, 1e137D, 1e138D, 1e139D, 1e140D, 1e141D, 1e142D, 1e143D, 1e144D,
- 1e145D, 1e146D, 1e147D, 1e148D, 1e149D, 1e150D, 1e151D, 1e152D, 1e153D, 1e154D,
- 1e155D, 1e156D, 1e157D, 1e158D, 1e159D, 1e160D, 1e161D, 1e162D, 1e163D, 1e164D,
- 1e165D, 1e166D, 1e167D, 1e168D, 1e169D, 1e170D, 1e171D, 1e172D, 1e173D, 1e174D,
- 1e175D, 1e176D, 1e177D, 1e178D, 1e179D, 1e180D, 1e181D, 1e182D, 1e183D, 1e184D,
- 1e185D, 1e186D, 1e187D, 1e188D, 1e189D, 1e190D, 1e191D, 1e192D, 1e193D, 1e194D,
- 1e195D, 1e196D, 1e197D, 1e198D, 1e199D, 1e200D, 1e201D, 1e202D, 1e203D, 1e204D,
- 1e205D, 1e206D, 1e207D, 1e208D, 1e209D, 1e210D, 1e211D, 1e212D, 1e213D, 1e214D,
- 1e215D, 1e216D, 1e217D, 1e218D, 1e219D, 1e220D, 1e221D, 1e222D, 1e223D, 1e224D,
- 1e225D, 1e226D, 1e227D, 1e228D, 1e229D, 1e230D, 1e231D, 1e232D, 1e233D, 1e234D,
- 1e235D, 1e236D, 1e237D, 1e238D, 1e239D, 1e240D, 1e241D, 1e242D, 1e243D, 1e244D,
- 1e245D, 1e246D, 1e247D, 1e248D, 1e249D, 1e250D, 1e251D, 1e252D, 1e253D, 1e254D,
- 1e255D, 1e256D, 1e257D, 1e258D, 1e259D, 1e260D, 1e261D, 1e262D, 1e263D, 1e264D,
- 1e265D, 1e266D, 1e267D, 1e268D, 1e269D, 1e270D, 1e271D, 1e272D, 1e273D, 1e274D,
- 1e275D, 1e276D, 1e277D, 1e278D, 1e279D, 1e280D, 1e281D, 1e282D, 1e283D, 1e284D,
- 1e285D, 1e286D, 1e287D, 1e288D, 1e289D, 1e290D, 1e291D, 1e292D, 1e293D, 1e294D,
- 1e295D, 1e296D, 1e297D, 1e298D, 1e299D, 1e300D, 1e301D, 1e302D, 1e303D, 1e304D,
- 1e305D, 1e306D, 1e307D, 1e308D
- };
-
-
- /**
- * Assumes i is positive. Returns the magnitude of i in base 10.
- */
- private static long tenthPower(long i)
- {
- if (i < 10L) return 1;
- else if (i < 100L) return 10L;
- else if (i < 1000L) return 100L;
- else if (i < 10000L) return 1000L;
- else if (i < 100000L) return 10000L;
- else if (i < 1000000L) return 100000L;
- else if (i < 10000000L) return 1000000L;
- else if (i < 100000000L) return 10000000L;
- else if (i < 1000000000L) return 100000000L;
- else if (i < 10000000000L) return 1000000000L;
- else if (i < 100000000000L) return 10000000000L;
- else if (i < 1000000000000L) return 100000000000L;
- else if (i < 10000000000000L) return 1000000000000L;
- else if (i < 100000000000000L) return 10000000000000L;
- else if (i < 1000000000000000L) return 100000000000000L;
- else if (i < 10000000000000000L) return 1000000000000000L;
- else if (i < 100000000000000000L) return 10000000000000000L;
- else if (i < 1000000000000000000L) return 100000000000000000L;
- else return 1000000000000000000L;
+ public static void append(StringBuilder s, double d) {
+ s.append(d);
}
-
- private static int magnitude(double d)
- {
- //It works. What else can I say.
- long doubleToLongBits = Double.doubleToLongBits(d);
- int magnitude =
- (int) ((((doubleToLongBits & DoubleExpMask) >> DoubleExpShift) - DoubleExpBias) * 0.301029995663981);
-
- if (magnitude < -323)
- magnitude = -323;
- else if (magnitude > 308)
- magnitude = 308;
-
- if (d >= d_tenthPowers[magnitude+323])
- {
- while(magnitude < 309 && d >= d_tenthPowers[magnitude+323])
- magnitude++;
- magnitude--;
- return magnitude;
- }
- else
- {
- while(magnitude > -324 && d < d_tenthPowers[magnitude+323])
- magnitude--;
- return magnitude;
- }
+ public static void append(StringBuilder s, int i) {
+ s.append(i);
}
- static long[] l_tenthPowers = {
- 1,
- 10L,
- 100L,
- 1000L,
- 10000L,
- 100000L,
- 1000000L,
- 10000000L,
- 100000000L,
- 1000000000L,
- 10000000000L,
- 100000000000L,
- 1000000000000L,
- 10000000000000L,
- 100000000000000L,
- 1000000000000000L,
- 10000000000000000L,
- 100000000000000000L,
- 1000000000000000000L,
- };
-
- public static long getNthDigit(long l, int n)
- {
- return (l/(tenthPower(l)/l_tenthPowers[n-1]))%10;
- }
-
-
-
-
- public static void append(StringBuilder s, double d)
- {
- if (d == Double.NEGATIVE_INFINITY)
- s.append(NEGATIVE_INFINITY);
- else if (d == Double.POSITIVE_INFINITY)
- s.append(POSITIVE_INFINITY);
- else if (d != d)
- s.append(NaN);
- else if (d == 0.0)
- {
- if ( (Double.doubleToLongBits(d) & DoubleSignMask) != 0)
- s.append('-');
- s.append(DOUBLE_ZERO);
- }
- else
- {
- if (d < 0)
- {
- s.append('-');
- d = -d;
- }
-
- if (d >= 0.001 && d < 0.01)
- {
- long i = (long) (d * 1E20);
- i = i%100 >= 50 ? (i/100) + 1 : i/100;
- s.append(DOUBLE_ZERO2);
- appendFractDigits(s, i,-1);
- }
- else if (d >= 0.01 && d < 0.1)
- {
- long i = (long) (d * 1E19);
- i = i%100 >= 50 ? (i/100) + 1 : i/100;
- s.append(DOUBLE_ZERO);
- appendFractDigits(s, i,-1);
- }
- else if (d >= 0.1 && d < 1)
- {
- long i = (long) (d * 1E18);
- i = i%100 >= 50 ? (i/100) + 1 : i/100;
- s.append(DOUBLE_ZERO0);
- appendFractDigits(s, i,-1);
- }
- else if (d >= 1 && d < 10)
- {
- long i = (long) (d * 1E17);
- i = i%100 >= 50 ? (i/100) + 1 : i/100;
- appendFractDigits(s, i,1);
- }
- else if (d >= 10 && d < 100)
- {
- long i = (long) (d * 1E16);
- i = i%100 >= 50 ? (i/100) + 1 : i/100;
- appendFractDigits(s, i,2);
- }
- else if (d >= 100 && d < 1000)
- {
- long i = (long) (d * 1E15);
- i = i%100 >= 50 ? (i/100) + 1 : i/100;
- appendFractDigits(s, i,3);
- }
- else if (d >= 1000 && d < 10000)
- {
- long i = (long) (d * 1E14);
- i = i%100 >= 50 ? (i/100) + 1 : i/100;
- appendFractDigits(s, i,4);
- }
- else if (d >= 10000 && d < 100000)
- {
- long i = (long) (d * 1E13);
- i = i%100 >= 50 ? (i/100) + 1 : i/100;
- appendFractDigits(s, i,5);
- }
- else if (d >= 100000 && d < 1000000)
- {
- long i = (long) (d * 1E12);
- i = i%100 >= 50 ? (i/100) + 1 : i/100;
- appendFractDigits(s, i,6);
- }
- else if (d >= 1000000 && d < 10000000)
- {
- long i = (long) (d * 1E11);
- i = i%100 >= 50 ? (i/100) + 1 : i/100;
- appendFractDigits(s, i,7);
- }
- else
- {
- int magnitude = magnitude(d);
- long i;
- if (magnitude < -280) {
- long valueBits = Double.doubleToRawLongBits(d);
- long mantissa = valueBits & 0x000fffffffffffffL;
- int exponent = (int)((valueBits >> 52) & 0x7ff);
- if (exponent == 0) {
- tooSmall(s, mantissa, -1074);
- } else {
- mantissa |= 0x0010000000000000L;
- exponent -= 1075;
- tooSmall(s, mantissa, exponent);
- }
- } else {
- i = (long) (d / d_tenthPowers[magnitude + 323 - 17]);
- i = i%100 >= 50 ? (i/100) + 1 : i/100;
- appendFractDigits(s, i, 1);
- s.append('E');
- append(s, magnitude);
- }
- }
- }
- }
- public static void append(StringBuilder s, int i)
- {
- if (i < 0)
- {
- if (i == Integer.MIN_VALUE)
- {
- //cannot make this positive due to integer overflow
- s.append("-2147483648");
- }
- s.append('-');
- i = -i;
- }
- int mag;
- int c;
- if (i < 10)
- {
- //one digit
- s.append(charForDigit[i]);
- }
- else if (i < 100)
- {
- //two digits
- s.append(charForDigit[i/10]);
- s.append(charForDigit[i%10]);
- }
- else if (i < 1000)
- {
- //three digits
- s.append(charForDigit[i/100]);
- s.append(charForDigit[(c=i%100)/10]);
- s.append(charForDigit[c%10]);
- }
- else if (i < 10000)
- {
- //four digits
- s.append(charForDigit[i/1000]);
- s.append(charForDigit[(c=i%1000)/100]);
- s.append(charForDigit[(c%=100)/10]);
- s.append(charForDigit[c%10]);
- }
- else if (i < 100000)
- {
- //five digits
- s.append(charForDigit[i/10000]);
- s.append(charForDigit[(c=i%10000)/1000]);
- s.append(charForDigit[(c%=1000)/100]);
- s.append(charForDigit[(c%=100)/10]);
- s.append(charForDigit[c%10]);
- }
- else if (i < 1000000)
- {
- //six digits
- s.append(charForDigit[i/100000]);
- s.append(charForDigit[(c=i%100000)/10000]);
- s.append(charForDigit[(c%=10000)/1000]);
- s.append(charForDigit[(c%=1000)/100]);
- s.append(charForDigit[(c%=100)/10]);
- s.append(charForDigit[c%10]);
- }
- else if (i < 10000000)
- {
- //seven digits
- s.append(charForDigit[i/1000000]);
- s.append(charForDigit[(c=i%1000000)/100000]);
- s.append(charForDigit[(c%=100000)/10000]);
- s.append(charForDigit[(c%=10000)/1000]);
- s.append(charForDigit[(c%=1000)/100]);
- s.append(charForDigit[(c%=100)/10]);
- s.append(charForDigit[c%10]);
- }
- else if (i < 100000000)
- {
- //eight digits
- s.append(charForDigit[i/10000000]);
- s.append(charForDigit[(c=i%10000000)/1000000]);
- s.append(charForDigit[(c%=1000000)/100000]);
- s.append(charForDigit[(c%=100000)/10000]);
- s.append(charForDigit[(c%=10000)/1000]);
- s.append(charForDigit[(c%=1000)/100]);
- s.append(charForDigit[(c%=100)/10]);
- s.append(charForDigit[c%10]);
- }
- else if (i < 1000000000)
- {
- //nine digits
- s.append(charForDigit[i/100000000]);
- s.append(charForDigit[(c=i%100000000)/10000000]);
- s.append(charForDigit[(c%=10000000)/1000000]);
- s.append(charForDigit[(c%=1000000)/100000]);
- s.append(charForDigit[(c%=100000)/10000]);
- s.append(charForDigit[(c%=10000)/1000]);
- s.append(charForDigit[(c%=1000)/100]);
- s.append(charForDigit[(c%=100)/10]);
- s.append(charForDigit[c%10]);
- }
- else
- {
- //ten digits
- s.append(charForDigit[i/1000000000]);
- s.append(charForDigit[(c=i%1000000000)/100000000]);
- s.append(charForDigit[(c%=100000000)/10000000]);
- s.append(charForDigit[(c%=10000000)/1000000]);
- s.append(charForDigit[(c%=1000000)/100000]);
- s.append(charForDigit[(c%=100000)/10000]);
- s.append(charForDigit[(c%=10000)/1000]);
- s.append(charForDigit[(c%=1000)/100]);
- s.append(charForDigit[(c%=100)/10]);
- s.append(charForDigit[c%10]);
- }
- }
- private static void appendFractDigits(StringBuilder s, long i, int decimalOffset)
- {
- long mag = tenthPower(i);
- long c;
- while ( i > 0 )
- {
- c = i/mag;
- s.append(charForDigit[(int) c]);
- decimalOffset--;
- if (decimalOffset == 0)
- s.append('.');
- c *= mag;
- if ( c <= i)
- i -= c;
- mag = mag/10;
- }
- if (i != 0)
- s.append(charForDigit[(int) i]);
- else if (decimalOffset > 0)
- {
- s.append(ZEROS[decimalOffset]);
- decimalOffset = 1;
- }
-
- decimalOffset--;
- if (decimalOffset == 0)
- s.append(DOT_ZERO);
- else if (decimalOffset == -1)
- s.append('0');
- }
-
- public static final char[] NEGATIVE_INFINITY = {'-','I','n','f','i','n','i','t','y'};
- public static final char[] POSITIVE_INFINITY = {'I','n','f','i','n','i','t','y'};
- public static final char[] DOUBLE_ZERO = {'0','.','0'};
- public static final char[] DOUBLE_ZERO2 = {'0','.','0','0'};
- public static final char[] DOUBLE_ZERO0 = {'0','.'};
- public static final char[] DOT_ZERO = {'.','0'};
-
}
diff --git a/vespajlib/src/main/java/com/yahoo/text/DoubleParser.java b/vespajlib/src/main/java/com/yahoo/text/DoubleParser.java
index 6a1fd8e170c..0a777f3000f 100644
--- a/vespajlib/src/main/java/com/yahoo/text/DoubleParser.java
+++ b/vespajlib/src/main/java/com/yahoo/text/DoubleParser.java
@@ -4,20 +4,15 @@ package com.yahoo.text;
/**
* Utility class to parse a String into a double.
* <p>
- * This is intended as a lower-cost replacement for the standard
- * Double.parseDouble(String) since that method will cause lock
- * contention if it's used too often.
+ * This was intended as a lower-cost replacement for the standard
+ * Double.parseDouble(String) since that method used to cause lock
+ * contention.
* <p>
- * Note that this implementation won't always produce the same results
- * as java.lang.Double (low-order bits may differ), and it doesn't
- * properly support denormalized numbers.
- * <p>
- * Also, this implementation is very poorly tested at the moment, so
- * it should be used carefully, only in cases where you know the input
- * will be well-defined and you don't need full precision.
+ * The contention issue is fixed in Java 8u96 so this class is now obsolete.
*
* @author arnej27959
*/
+@Deprecated
public final class DoubleParser {
/**
@@ -29,171 +24,6 @@ public final class DoubleParser {
* @throws NullPointerException if the string is a null pointer
*/
public static double parse(String data) {
- final int len = data.length();
- double result = 0;
- boolean negative = false;
- int beforePoint = 0;
- int exponent = 0;
- byte[] digits = new byte[25];
- int numDigits = 0;
-
- int i = 0;
- while (i < len && Character.isWhitespace(data.charAt(i))) {
- i++;
- }
- if (data.charAt(i) == '+') {
- i++;
- } else if (data.charAt(i) == '-') {
- negative = true;
- i++;
- }
- if (i + 3 <= len && data.substring(i, i+3).equals("NaN")) {
- i += 3;
- result = Double.NaN;
- } else if (i + 8 <= len && data.substring(i, i+8).equals("Infinity")) {
- i += 8;
- if (negative) {
- result = Double.NEGATIVE_INFINITY;
- } else {
- result = Double.POSITIVE_INFINITY;
- }
- } else {
- while (i < len && Character.isDigit(data.charAt(i))) {
- int dval = Character.digit(data.charAt(i), 10);
- assert dval >= 0;
- assert dval < 10;
- if (numDigits < 25) {
- digits[numDigits++] = (byte)dval;
- }
- ++beforePoint;
- i++;
- }
- if (i < len && data.charAt(i) == '.') {
- i++;
- while (i < len && Character.isDigit(data.charAt(i))) {
- int dval = Character.digit(data.charAt(i), 10);
- assert dval >= 0;
- assert dval < 10;
- if (numDigits < 25) {
- digits[numDigits++] = (byte)dval;
- }
- i++;
- }
- }
- if (numDigits == 0) {
- throw new NumberFormatException("No digits in number: '"+data+"'");
- }
- if (i < len && (data.charAt(i) == 'e' || data.charAt(i) == 'E')) {
- i++;
- boolean expNeg = false;
- int expDigits = 0;
- if (data.charAt(i) == '+') {
- i++;
- } else if (data.charAt(i) == '-') {
- expNeg = true;
- i++;
- }
- while (i < len && Character.isDigit(data.charAt(i))) {
- int dval = Character.digit(data.charAt(i), 10);
- assert dval >= 0;
- assert dval < 10;
- exponent *= 10;
- exponent += dval;
- ++expDigits;
- i++;
- }
- if (expDigits == 0) {
- throw new NumberFormatException("Missing digits in exponent part: "+data);
- }
- if (expNeg) {
- exponent = -exponent;
- }
- }
- // System.out.println("parsed exp: "+exponent);
- // System.out.println("before pt: "+beforePoint);
- exponent += beforePoint;
- exponent -= numDigits;
- // System.out.println("adjusted exp: "+exponent);
- for (int d = numDigits; d > 0; d--) {
- double dv = digits[d-1];
- dv *= powTen(numDigits - d);
- result += dv;
- }
- // System.out.println("digits sum: "+result);
- while (exponent < -99) {
- result *= powTen(-99);
- exponent += 99;
- }
- while (exponent > 99) {
- result *= powTen(99);
- exponent -= 99;
- }
- // System.out.println("digits sum: "+result);
- // System.out.println("exponent multiplier: "+powTen(exponent));
- result *= powTen(exponent);
-
- if (negative) {
- result = -result;
- }
- }
- while (i < len && Character.isWhitespace(data.charAt(i))) {
- i++;
- }
- if (i < len) {
- throw new NumberFormatException("Extra characters after number: "+data.substring(i));
- }
- return result;
- }
-
- private static double[] tens = {
- 1.0e00, 1.0e01, 1.0e02, 1.0e03, 1.0e04, 1.0e05, 1.0e06,
- 1.0e07, 1.0e08, 1.0e09, 1.0e10, 1.0e11, 1.0e12, 1.0e13,
- 1.0e14, 1.0e15, 1.0e16, 1.0e17, 1.0e18, 1.0e19, 1.0e20,
- 1.0e21, 1.0e22, 1.0e23, 1.0e24, 1.0e25, 1.0e26, 1.0e27,
- 1.0e28, 1.0e29, 1.0e30, 1.0e31, 1.0e32, 1.0e33, 1.0e34,
- 1.0e35, 1.0e36, 1.0e37, 1.0e38, 1.0e39, 1.0e40, 1.0e41,
- 1.0e42, 1.0e43, 1.0e44, 1.0e45, 1.0e46, 1.0e47, 1.0e48,
- 1.0e49, 1.0e50, 1.0e51, 1.0e52, 1.0e53, 1.0e54, 1.0e55,
- 1.0e56, 1.0e57, 1.0e58, 1.0e59, 1.0e60, 1.0e61, 1.0e62,
- 1.0e63, 1.0e64, 1.0e65, 1.0e66, 1.0e67, 1.0e68, 1.0e69,
- 1.0e70, 1.0e71, 1.0e72, 1.0e73, 1.0e74, 1.0e75, 1.0e76,
- 1.0e77, 1.0e78, 1.0e79, 1.0e80, 1.0e81, 1.0e82, 1.0e83,
- 1.0e84, 1.0e85, 1.0e86, 1.0e87, 1.0e88, 1.0e89, 1.0e90,
- 1.0e91, 1.0e92, 1.0e93, 1.0e94, 1.0e95, 1.0e96, 1.0e97,
- 1.0e98, 1.0e99
- };
-
- private static double[] tenths = {
- 1.0e-00, 1.0e-01, 1.0e-02, 1.0e-03, 1.0e-04, 1.0e-05,
- 1.0e-06, 1.0e-07, 1.0e-08, 1.0e-09, 1.0e-10, 1.0e-11,
- 1.0e-12, 1.0e-13, 1.0e-14, 1.0e-15, 1.0e-16, 1.0e-17,
- 1.0e-18, 1.0e-19, 1.0e-20, 1.0e-21, 1.0e-22, 1.0e-23,
- 1.0e-24, 1.0e-25, 1.0e-26, 1.0e-27, 1.0e-28, 1.0e-29,
- 1.0e-30, 1.0e-31, 1.0e-32, 1.0e-33, 1.0e-34, 1.0e-35,
- 1.0e-36, 1.0e-37, 1.0e-38, 1.0e-39, 1.0e-40, 1.0e-41,
- 1.0e-42, 1.0e-43, 1.0e-44, 1.0e-45, 1.0e-46, 1.0e-47,
- 1.0e-48, 1.0e-49, 1.0e-50, 1.0e-51, 1.0e-52, 1.0e-53,
- 1.0e-54, 1.0e-55, 1.0e-56, 1.0e-57, 1.0e-58, 1.0e-59,
- 1.0e-60, 1.0e-61, 1.0e-62, 1.0e-63, 1.0e-64, 1.0e-65,
- 1.0e-66, 1.0e-67, 1.0e-68, 1.0e-69, 1.0e-70, 1.0e-71,
- 1.0e-72, 1.0e-73, 1.0e-74, 1.0e-75, 1.0e-76, 1.0e-77,
- 1.0e-78, 1.0e-79, 1.0e-80, 1.0e-81, 1.0e-82, 1.0e-83,
- 1.0e-84, 1.0e-85, 1.0e-86, 1.0e-87, 1.0e-88, 1.0e-89,
- 1.0e-90, 1.0e-91, 1.0e-92, 1.0e-93, 1.0e-94, 1.0e-95,
- 1.0e-96, 1.0e-97, 1.0e-98, 1.0e-99
- };
-
- private static double powTen(int exponent) {
- if (exponent > 0) {
- assert exponent < 100;
- return tens[exponent];
- }
- if (exponent < 0) {
- exponent = -exponent;
- assert exponent < 100;
- return tenths[exponent];
- }
- return 1.0;
+ return Double.parseDouble(data);
}
-
}
diff --git a/vespajlib/src/main/java/com/yahoo/time/TimeBudget.java b/vespajlib/src/main/java/com/yahoo/time/TimeBudget.java
index fa18cb5e467..a7963df0208 100644
--- a/vespajlib/src/main/java/com/yahoo/time/TimeBudget.java
+++ b/vespajlib/src/main/java/com/yahoo/time/TimeBudget.java
@@ -6,26 +6,31 @@ import com.google.common.util.concurrent.UncheckedTimeoutException;
import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
+import java.util.Optional;
/**
- * A TimeBudget can be used to track the time of an ongoing operation with a timeout.
+ * A TimeBudget can be used to track the time of an ongoing operation, possibly with a timeout.
*
* @author hakon
*/
public class TimeBudget {
private final Clock clock;
private final Instant start;
- private final Duration timeout;
+ private final Optional<Duration> timeout;
/** Returns a TimeBudget with a start time of now, and with the given timeout. */
public static TimeBudget fromNow(Clock clock, Duration timeout) {
- return new TimeBudget(clock, clock.instant(), timeout);
+ return new TimeBudget(clock, clock.instant(), Optional.of(timeout));
}
- private TimeBudget(Clock clock, Instant start, Duration timeout) {
+ public static TimeBudget from(Clock clock, Instant start, Optional<Duration> timeout) {
+ return new TimeBudget(clock, start, timeout);
+ }
+
+ private TimeBudget(Clock clock, Instant start, Optional<Duration> timeout) {
this.clock = clock;
this.start = start;
- this.timeout = makeNonNegative(timeout);
+ this.timeout = timeout.map(TimeBudget::makeNonNegative);
}
/** Returns time since start. */
@@ -33,26 +38,32 @@ public class TimeBudget {
return nonNegativeBetween(start, clock.instant());
}
- /** Returns the original timeout. */
- public Duration originalTimeout() {
+ /** Returns the original timeout, if any. */
+ public Optional<Duration> originalTimeout() {
return timeout;
}
+ /** Returns the deadline, if present. */
+ public Optional<Instant> deadline() {
+ return timeout.map(start::plus);
+ }
+
/**
- * Returns the time until deadline.
+ * Returns the time until deadline, if there is one.
*
* @return time until deadline. It's toMillis() is guaranteed to be positive.
* @throws UncheckedTimeoutException if the deadline has been reached or passed.
*/
- public Duration timeLeftOrThrow() {
- Instant now = clock.instant();
- Duration left = Duration.between(now, start.plus(timeout));
- if (left.toMillis() <= 0) {
- throw new UncheckedTimeoutException("Time since start " + nonNegativeBetween(start, now) +
- " exceeds timeout " + timeout);
- }
+ public Optional<Duration> timeLeftOrThrow() {
+ return timeout.map(timeout -> {
+ Duration passed = timePassed();
+ Duration left = timeout.minus(passed);
+ if (left.toMillis() <= 0) {
+ throw new UncheckedTimeoutException("Time since start " + passed + " exceeds timeout " + this.timeout);
+ }
- return left;
+ return left;
+ });
}
private static Duration nonNegativeBetween(Instant start, Instant end) {
diff --git a/vespajlib/src/test/java/com/yahoo/text/DoubleFormatterTestCase.java b/vespajlib/src/test/java/com/yahoo/text/DoubleFormatterTestCase.java
index 9299c96d902..3d0c623bbf4 100644
--- a/vespajlib/src/test/java/com/yahoo/text/DoubleFormatterTestCase.java
+++ b/vespajlib/src/test/java/com/yahoo/text/DoubleFormatterTestCase.java
@@ -4,6 +4,7 @@ package com.yahoo.text;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
+@SuppressWarnings("deprecation")
/**
* @author arnej27959
*/
@@ -73,19 +74,19 @@ public class DoubleFormatterTestCase {
assertEquals("1.0737418255E9", s);
s = DoubleFormatter.stringValue(1.23456789012345669);
- assertEquals("1.234567890123457", s);
+ assertEquals("1.2345678901234567", s);
s = DoubleFormatter.stringValue(12.3456789012345673);
- assertEquals("12.34567890123457", s);
+ assertEquals("12.345678901234567", s);
s = DoubleFormatter.stringValue(123.456789012345666);
- assertEquals("123.4567890123457", s);
+ assertEquals("123.45678901234567", s);
s = DoubleFormatter.stringValue(1234.56789012345666);
- assertEquals("1234.567890123457", s);
+ assertEquals("1234.5678901234567", s);
s = DoubleFormatter.stringValue(12345.6789012345670);
- assertEquals("12345.67890123457", s);
+ assertEquals("12345.678901234567", s);
s = DoubleFormatter.stringValue(123456.789012345674);
- assertEquals("123456.7890123457", s);
+ assertEquals("123456.78901234567", s);
s = DoubleFormatter.stringValue(1234567.89012345671);
- assertEquals("1234567.890123457", s);
+ assertEquals("1234567.8901234567", s);
s = DoubleFormatter.stringValue(0.99);
// assertEquals("0.99", s);
diff --git a/vespajlib/src/test/java/com/yahoo/text/DoubleParserTestCase.java b/vespajlib/src/test/java/com/yahoo/text/DoubleParserTestCase.java
index 7f20b9b89ec..a48a1b6a943 100644
--- a/vespajlib/src/test/java/com/yahoo/text/DoubleParserTestCase.java
+++ b/vespajlib/src/test/java/com/yahoo/text/DoubleParserTestCase.java
@@ -4,6 +4,7 @@ package com.yahoo.text;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
+@SuppressWarnings("deprecation")
/**
* @author arnej27959
*/
diff --git a/vespajlib/src/test/java/com/yahoo/text/DoubleToStringBenchmark.java b/vespajlib/src/test/java/com/yahoo/text/DoubleToStringBenchmark.java
index ec3eae50aa7..a5925df2caf 100644
--- a/vespajlib/src/test/java/com/yahoo/text/DoubleToStringBenchmark.java
+++ b/vespajlib/src/test/java/com/yahoo/text/DoubleToStringBenchmark.java
@@ -12,6 +12,7 @@ import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertEquals;
+@SuppressWarnings("deprecation")
/**
* @author arnej27959
*/
diff --git a/vespajlib/src/test/java/com/yahoo/time/TimeBudgetTest.java b/vespajlib/src/test/java/com/yahoo/time/TimeBudgetTest.java
index a51081067b7..f197cc34b32 100644
--- a/vespajlib/src/test/java/com/yahoo/time/TimeBudgetTest.java
+++ b/vespajlib/src/test/java/com/yahoo/time/TimeBudgetTest.java
@@ -8,8 +8,10 @@ import org.junit.Test;
import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
+import java.util.Optional;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
@@ -23,12 +25,12 @@ public class TimeBudgetTest {
TimeBudget timeBudget = TimeBudget.fromNow(clock, Duration.ofSeconds(10));
clock.advance(Duration.ofSeconds(7));
- assertEquals(Duration.ofSeconds(3), timeBudget.timeLeftOrThrow());
+ assertEquals(Duration.ofSeconds(3), timeBudget.timeLeftOrThrow().get());
// Verify that toMillis() of >=1 is fine, but 0 is not.
clock.setInstant(Instant.ofEpochSecond(9, 999000000));
- assertEquals(1, timeBudget.timeLeftOrThrow().toMillis());
+ assertEquals(1, timeBudget.timeLeftOrThrow().get().toMillis());
clock.setInstant(Instant.ofEpochSecond(9, 999000001));
try {
timeBudget.timeLeftOrThrow();
@@ -37,4 +39,15 @@ public class TimeBudgetTest {
// OK
}
}
+
+ @Test
+ public void noDeadline() {
+ ManualClock clock = new ManualClock();
+ clock.setInstant(Instant.ofEpochSecond(0));
+ TimeBudget timeBudget = TimeBudget.from(clock, clock.instant(), Optional.empty());
+
+ assertFalse(timeBudget.originalTimeout().isPresent());
+ assertFalse(timeBudget.timeLeftOrThrow().isPresent());
+ assertFalse(timeBudget.deadline().isPresent());
+ }
} \ No newline at end of file