summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnstein Ressem <aressem@yahoo-inc.com>2017-06-14 14:48:48 +0200
committerArnstein Ressem <aressem@yahoo-inc.com>2017-06-14 14:48:48 +0200
commitc5348f715b0e156eeaebc1a56bdd3600761e0fa2 (patch)
tree2b3ecf57439ca31817f7d70d2c6d6b61561c32b1
parent65303e439b87b202739a9bbb2561d996df404312 (diff)
parentb7f9e7ceaef72489d76683537973b639f8895b84 (diff)
Merged master.
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/AbstractService.java7
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/HostResource.java23
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/InstanceResolver.java44
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/PortsMeta.java5
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/admin/Configserver.java20
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/admin/Slobrok.java8
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/Container.java31
-rwxr-xr-xconfig-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java26
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java32
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/search/Tuning.java1
-rw-r--r--config-model/src/main/resources/schema/content.rnc2
-rwxr-xr-xconfig-model/src/test/java/com/yahoo/vespa/model/container/ContainerClusterTest.java2
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/content/ClusterTest.java106
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/content/utils/ContentClusterUtils.java23
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/ClusterSpec.java4
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/DockerImage.java10
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provisioning/package-info.java5
-rw-r--r--config-provisioning/src/main/resources/configdefinitions/node-repository.def5
-rw-r--r--config-provisioning/src/test/java/com/yahoo/config/provision/ProvisionInfoTest.java1
-rwxr-xr-xconfig-proxy/src/main/sh/vespa-config-ctl (renamed from config-proxy/src/main/sh/config-ctl)2
-rw-r--r--config-proxy/src/main/sh/vespa-config-loadtester (renamed from config-proxy/src/main/sh/cloudconfig_loadtester)0
-rw-r--r--config-proxy/src/main/sh/vespa-config-verification (renamed from config-proxy/src/main/sh/cloudconfig_verification)0
-rw-r--r--config/src/tests/configparser/configparser.cpp8
-rw-r--r--configd/src/apps/sentinel/.gitignore2
-rw-r--r--configd/src/apps/sentinel/CMakeLists.txt2
-rw-r--r--configd/src/apps/su/.gitignore2
-rw-r--r--configd/src/apps/su/CMakeLists.txt4
-rw-r--r--configd/src/apps/su/main.cpp2
-rwxr-xr-xconfigd/src/tests/configd/run-sentinel.sh2
-rw-r--r--configserver/CMakeLists.txt2
-rw-r--r--configserver/pom.xml1
-rwxr-xr-xconfigserver/src/main/sh/start-configserver6
-rwxr-xr-xconfigserver/src/main/sh/start-filedistribution2
-rw-r--r--configserver/src/main/sh/start-logd2
-rwxr-xr-xconfigserver/src/main/sh/stop-configserver8
-rwxr-xr-xconfigserver/src/main/sh/vespa-configserver-remove-state (renamed from configserver/src/main/sh/cloudconfig_server-remove-state)0
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java3
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/query/parser/test/specialtokens.cfg2
-rwxr-xr-xdist/post_install.sh23
-rwxr-xr-xdist/release-vespa-rpm.sh34
-rw-r--r--dist/vespa.spec18
-rw-r--r--docker-api/src/test/java/com/yahoo/vespa/hosted/dockerapi/RunSystemTests.java2
-rw-r--r--docker/.gitignore1
-rw-r--r--docker/Dockerfile.build6
-rw-r--r--docker/Dockerfile.ci11
-rw-r--r--docker/Dockerfile.run2
-rw-r--r--docker/README.md4
-rwxr-xr-xdocker/vespa-ci-internal.sh34
-rwxr-xr-xdocker/vespa-ci.sh20
-rw-r--r--docprocs/pom.xml1
-rw-r--r--document/CMakeLists.txt1
-rw-r--r--document/src/main/java/com/yahoo/document/serialization/VespaDocumentSerializer42.java2
-rw-r--r--document/src/test/java/com/yahoo/document/serialization/VespaDocumentSerializerTestCase.java89
-rw-r--r--document/src/tests/data/serializejava-compressed.datbin8337 -> 377 bytes
-rw-r--r--document/src/tests/serialization/compression_test.cpp23
-rw-r--r--document/src/vespa/document/fieldvalue/serializablearray.cpp11
-rw-r--r--document/src/vespa/document/serialization/vespadocumentserializer.cpp1
-rw-r--r--document/src/vespa/document/util/CMakeLists.txt6
-rw-r--r--document/src/vespa/document/util/compressionconfig.h17
-rw-r--r--document/src/vespa/document/util/compressor.cpp72
-rw-r--r--document/src/vespa/document/util/compressor.h22
-rw-r--r--document/src/vespa/document/util/lz4compressor.cpp46
-rw-r--r--document/src/vespa/document/util/lz4compressor.h17
-rw-r--r--document/src/vespa/document/util/zstdcompressor.cpp34
-rw-r--r--document/src/vespa/document/util/zstdcompressor.h17
-rw-r--r--documentgen-test/pom.xml1
-rw-r--r--fastlib/src/vespa/fastlib/testsuite/cpptest.el2
-rw-r--r--fastlib/src/vespa/fastlib/testsuite/testproject.el2
-rw-r--r--fastlib/src/vespa/fastlib/text/tests/wordfolderstest.h6
-rw-r--r--fastlib/src/vespa/fastlib/util/testproject.el2
-rw-r--r--filedistribution/src/apps/filedistributor/.gitignore2
-rw-r--r--filedistribution/src/apps/filedistributor/CMakeLists.txt2
-rw-r--r--filedistribution/src/apps/status/.gitignore2
-rw-r--r--filedistribution/src/apps/status/CMakeLists.txt2
-rw-r--r--filedistribution/src/apps/status/vespa-status-filedistribution.sh2
-rw-r--r--filedistributionmanager/src/main/java/com/yahoo/vespa/filedistribution/FileDistributionManager.java7
-rw-r--r--install_java.cmake24
-rw-r--r--jdisc_core/pom.xml4
-rw-r--r--jdisc_core/src/main/java/com/yahoo/jdisc/core/ActiveContainer.java37
-rw-r--r--jdisc_core/src/main/java/com/yahoo/jdisc/core/ActiveContainerDeactivationWatchdog.java75
-rwxr-xr-xjdisc_core/src/main/perl/vespa-jdisc-logfmt (renamed from jdisc_core/src/main/perl/jdisc_logfmt)0
-rw-r--r--jdisc_core/src/main/perl/vespa-jdisc-logfmt.1 (renamed from jdisc_core/src/main/perl/jdisc_logfmt.1)10
-rw-r--r--jdisc_core/src/test/java/com/yahoo/jdisc/core/ActiveContainerDeactivationWatchdogTest.java55
-rw-r--r--jdisc_core/src/test/perl/help.Levent.expected2
-rw-r--r--jdisc_core/src/test/perl/help.expected2
-rwxr-xr-xjdisc_core/src/test/perl/vespa-jdisc-logfmt-test.sh (renamed from jdisc_core/src/test/perl/jdisc_logfmt_test.sh)4
-rw-r--r--jdisc_http_service/docs/class-diagram.graffle1856
-rw-r--r--jdisc_http_service/docs/class-diagram.pngbin87451 -> 0 bytes
-rw-r--r--jdisc_http_service/docs/httpserver.html96
-rw-r--r--jrt/pom.xml1
-rw-r--r--jrt_test/src/jrt-test/simpleserver/CMakeLists.txt1
-rw-r--r--juniper/src/testproject.el2
-rw-r--r--libmlr/pom.xml1
-rw-r--r--logd/src/apps/logd/.gitignore2
-rw-r--r--logd/src/apps/logd/CMakeLists.txt2
-rwxr-xr-xlogd/src/tests/rotate/rotate_test.sh2
-rw-r--r--messagebus/src/apps/printversion/CMakeLists.txt1
-rwxr-xr-xmessagebus/src/main/java/com/yahoo/messagebus/routing/RoutingNode.java2
-rw-r--r--node-admin/README.md2
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImpl.java15
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImplTest.java7
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/noderepository/NodeRepositoryImplTest.java4
-rw-r--r--node-repository/src/main/config/node-repository.xml1
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java14
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirer.java33
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Status.java58
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java8
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java6
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodePatcher.java12
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodesResponse.java18
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockDeployer.java32
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java14
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/ServiceMonitorStub.java2
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/NodeRepositoryTester.java10
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/FailedExpirerTest.java8
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/InactiveAndFailedExpirerTest.java12
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MaintenanceTester.java4
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailTester.java6
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirerTest.java49
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirerTester.java37
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/OperatorChangeApplicationMaintainerTest.java6
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainerTest.java6
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ReservationExpirerTest.java8
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RetiredExpirerTest.java20
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/monitoring/MetricsReporterTest.java7
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/SerializationTest.java39
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java14
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java4
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node1.json2
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node10.json8
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node2.json2
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node3.json2
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node4-after-changes.json8
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node4.json6
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node5.json4
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node6.json2
-rw-r--r--orchestrator/src/main/java/com/yahoo/vespa/orchestrator/resources/HostResource.java3
-rw-r--r--persistence/src/tests/proxy/.gitignore2
-rw-r--r--persistence/src/tests/proxy/CMakeLists.txt2
-rw-r--r--pom.xml2
-rw-r--r--sample-apps/http-api-using-request-handlers-and-processors/README.md4
-rw-r--r--sample-apps/http-api-using-request-handlers-and-processors/pom.xml85
-rw-r--r--sample-apps/http-api-using-request-handlers-and-processors/src/main/application/services.xml25
-rw-r--r--sample-apps/http-api-using-request-handlers-and-processors/src/main/java/com/yahoo/demo/AnnotatingProcessor.java97
-rw-r--r--sample-apps/http-api-using-request-handlers-and-processors/src/main/java/com/yahoo/demo/DataProcessor.java87
-rw-r--r--sample-apps/http-api-using-request-handlers-and-processors/src/main/java/com/yahoo/demo/DemoComponent.java47
-rw-r--r--sample-apps/http-api-using-request-handlers-and-processors/src/main/java/com/yahoo/demo/DemoHandler.java76
-rw-r--r--sample-apps/http-api-using-request-handlers-and-processors/src/main/java/com/yahoo/demo/DemoRenderer.java119
-rw-r--r--sample-apps/http-api-using-request-handlers-and-processors/src/main/resources/configdefinitions/demo.def5
-rw-r--r--sample-apps/http-api-using-request-handlers-and-processors/src/test/java/com/yahoo/example/ApplicationMain.java27
-rw-r--r--sample-apps/http-api-using-searcher/README.md4
-rw-r--r--sample-apps/http-api-using-searcher/feed.json14
-rw-r--r--sample-apps/http-api-using-searcher/pom.xml85
-rw-r--r--sample-apps/http-api-using-searcher/src/main/application/searchdefinitions/basic.sd16
-rw-r--r--sample-apps/http-api-using-searcher/src/main/application/services.xml55
-rw-r--r--sample-apps/http-api-using-searcher/src/main/java/com/yahoo/demo/DemoComponent.java45
-rw-r--r--sample-apps/http-api-using-searcher/src/main/java/com/yahoo/demo/DemoHandler.java50
-rw-r--r--sample-apps/http-api-using-searcher/src/main/java/com/yahoo/demo/DemoRenderer.java74
-rw-r--r--sample-apps/http-api-using-searcher/src/main/java/com/yahoo/demo/DemoSearcher.java76
-rw-r--r--sample-apps/http-api-using-searcher/src/main/resources/configdefinitions/demo.def5
-rw-r--r--sample-apps/http-api-using-searcher/src/test/java/com/yahoo/example/ApplicationMain.java27
-rw-r--r--sample-apps/pom.xml2
-rw-r--r--searchcommon/src/vespa/searchcommon/attribute/search_context_params.h6
-rw-r--r--searchcommon/src/vespa/searchcommon/common/range.h6
-rw-r--r--searchcore/src/apps/vespa-dump-feed/CMakeLists.txt1
-rw-r--r--searchcore/src/apps/vespa-dump-feed/vespa-dump-feed.cpp4
-rw-r--r--searchcore/src/tests/proton/summaryengine/summaryengine.cpp4
-rw-r--r--searchcore/src/vespa/searchcore/config/proton.def6
-rw-r--r--searchcore/src/vespa/searchcore/proton/docsummary/summarymanager.cpp4
-rw-r--r--searchcore/src/vespa/searchcore/proton/docsummary/summarymanager.h1
-rw-r--r--searchcore/src/vespa/searchcore/proton/summaryengine/docsum_by_slime.cpp8
-rw-r--r--searchlib/src/tests/docstore/chunk/chunk_test.cpp30
-rw-r--r--searchlib/src/vespa/searchlib/attribute/attributevector.cpp6
-rw-r--r--searchlib/src/vespa/searchlib/attribute/enumstorebase.h2
-rw-r--r--searchlib/src/vespa/searchlib/attribute/postingchange.cpp1
-rw-r--r--searchlib/src/vespa/searchlib/attribute/postinglistsearchcontext.h122
-rw-r--r--searchlib/src/vespa/searchlib/attribute/postinglistsearchcontext.hpp107
-rw-r--r--searchlib/src/vespa/searchlib/attribute/postinglisttraits.h6
-rw-r--r--searchlib/src/vespa/searchlib/attribute/postingstore.cpp9
-rw-r--r--searchlib/src/vespa/searchlib/attribute/postingstore.h99
-rw-r--r--searchlib/src/vespa/searchlib/attribute/postingstore.hpp90
-rw-r--r--searchlib/src/vespa/searchlib/btree/btreestore.h10
-rw-r--r--searchlib/src/vespa/searchlib/common/packets.cpp7
-rw-r--r--searchlib/src/vespa/searchlib/docstore/chunkformat.cpp26
-rw-r--r--searchlib/src/vespa/searchlib/docstore/documentstore.cpp80
-rw-r--r--searchlib/src/vespa/searchlib/docstore/visitcache.cpp6
-rw-r--r--searchlib/src/vespa/searchlib/grouping/sketch.h4
-rw-r--r--staging_vespalib/src/vespa/vespalib/data/databuffer.h6
-rw-r--r--storage/src/vespa/storage/tools/.gitignore1
-rw-r--r--storageapi/src/vespa/storageapi/app/CMakeLists.txt1
-rw-r--r--vbench/src/apps/dumpurl/CMakeLists.txt1
-rw-r--r--vbench/src/apps/vbench/CMakeLists.txt1
-rw-r--r--vdslib/pom.xml1
-rw-r--r--vespabase/CMakeLists.txt7
-rwxr-xr-xvespabase/src/start-vespa-base.sh2
-rwxr-xr-xvespabase/src/stop-vespa-base.sh2
-rw-r--r--vespaclient-java/src/main/java/com/yahoo/vespafeeder/Arguments.java2
-rwxr-xr-xvespaclient-java/src/main/java/com/yahoo/vespafeeder/VespaFeeder.java4
-rw-r--r--vespaclient-java/src/main/java/com/yahoo/vespaget/CommandLineOptions.java2
-rw-r--r--vespaclient-java/src/main/java/com/yahoo/vespaget/Main.java2
-rw-r--r--vespaclient-java/src/main/java/com/yahoo/vespastat/CommandLineOptions.java2
-rw-r--r--vespaclient-java/src/main/java/com/yahoo/vespavisit/VdsVisit.java6
-rw-r--r--vespaclient-java/src/main/java/com/yahoo/vespavisit/VdsVisitTarget.java6
-rwxr-xr-xvespaclient-java/src/main/sh/vespa-destination.sh (renamed from vespaclient-java/src/main/sh/vespadestination.sh)0
-rwxr-xr-xvespaclient-java/src/main/sh/vespa-document-statistics.sh (renamed from vespaclient-java/src/main/sh/vds-document-statistics.sh)4
-rwxr-xr-xvespaclient-java/src/main/sh/vespa-feeder.sh (renamed from vespaclient-java/src/main/sh/vespafeeder.sh)0
-rw-r--r--vespaclient-java/src/main/sh/vespa-get.sh (renamed from vespaclient-java/src/main/sh/vespaget.sh)0
-rw-r--r--vespaclient-java/src/main/sh/vespa-stat.sh (renamed from vespaclient-java/src/main/sh/vdsstat.sh)0
-rw-r--r--vespaclient-java/src/main/sh/vespa-visit-target.1 (renamed from vespaclient-java/src/main/sh/vespavisittarget.1)6
-rwxr-xr-xvespaclient-java/src/main/sh/vespa-visit-target.sh (renamed from vespaclient-java/src/main/sh/vespavisittarget.sh)0
-rw-r--r--vespaclient-java/src/main/sh/vespa-visit.1 (renamed from vespaclient-java/src/main/sh/vespavisit.1)18
-rwxr-xr-xvespaclient-java/src/main/sh/vespa-visit.sh (renamed from vespaclient-java/src/main/sh/vespavisit.sh)0
-rw-r--r--vespaclient-java/src/test/java/com/yahoo/vespaget/CommandLineOptionsTest.java2
-rw-r--r--vespaclient-java/src/test/java/com/yahoo/vespastat/CommandLineOptionsTest.java2
-rw-r--r--vespajlib/src/main/java/com/yahoo/compress/Compressor.java2
-rw-r--r--vespajlib/src/test/java/com/yahoo/compress/LZ4CompressorTest.java25
-rw-r--r--vespalib/src/apps/make_fixture_macros/CMakeLists.txt1
-rw-r--r--vespalib/src/vespa/vespalib/util/optimized.h2
-rw-r--r--vespalog/src/vespa/log/bufferedlogger.cpp3
-rw-r--r--vespamalloc/CMakeLists.txt2
220 files changed, 2455 insertions, 2955 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/AbstractService.java b/config-model/src/main/java/com/yahoo/vespa/model/AbstractService.java
index bda79ee2356..dd6556f81d2 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/AbstractService.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/AbstractService.java
@@ -102,7 +102,7 @@ public abstract class AbstractService extends AbstractConfigProducer<AbstractCon
Map<HostResource, List<SERVICE>> affinityMap = new HashMap<>();
for (SERVICE service : services) {
if (!affinityMap.containsKey(service.getHostResource())) {
- affinityMap.put(service.getHostResource(), new ArrayList<SERVICE>());
+ affinityMap.put(service.getHostResource(), new ArrayList<>());
}
int cpuSocket = affinityMap.get(service.getHostResource()).size();
affinityMap.get(service.getHostResource()).add(service);
@@ -548,4 +548,9 @@ public abstract class AbstractService extends AbstractConfigProducer<AbstractCon
public void setAffinity(Affinity affinity) {
this.affinity = Optional.ofNullable(affinity);
}
+
+ @Override
+ public String toString() {
+ return getServiceName() + " on " + getHost().toString();
+ }
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/HostResource.java b/config-model/src/main/java/com/yahoo/vespa/model/HostResource.java
index d54dc912da6..46dc287bb10 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/HostResource.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/HostResource.java
@@ -3,13 +3,11 @@ package com.yahoo.vespa.model;
import com.yahoo.config.model.api.HostInfo;
import com.yahoo.config.provision.ClusterMembership;
-import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.Flavor;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
@@ -30,7 +28,7 @@ import java.util.stream.Collectors;
public class HostResource implements Comparable<HostResource> {
public final static int BASE_PORT = 19100;
- public final static int MAX_PORTS = 799;
+ final static int MAX_PORTS = 799;
private final Host host;
// Map from "sentinel name" to service
@@ -81,18 +79,6 @@ public class HostResource implements Comparable<HostResource> {
0;
}
- boolean isPortRangeAvailable(int start, int numPorts) {
- int range = 0;
- int port = start;
- for (; port < BASE_PORT + MAX_PORTS && (range < numPorts); port++) {
- if (portDB.containsKey(port)) {
- return false;
- }
- range++;
- }
- return range == numPorts;
- }
-
/**
* Adds service and allocates resources for it.
*
@@ -179,7 +165,8 @@ public class HostResource implements Comparable<HostResource> {
return port >= BASE_PORT &&
port < BASE_PORT + MAX_PORTS;
}
- private void portAlreadyReserved(AbstractService service, int port) {
+
+ private void portAlreadyReserved(AbstractService service, int port) {
AbstractService otherService = (AbstractService)portDB.get(port);
int nextAvailablePort = nextAvailableBaseport(service.getPortCount());
if (nextAvailablePort == 0) {
@@ -190,10 +177,9 @@ public class HostResource implements Comparable<HostResource> {
: "";
throw new RuntimeException(service.getServiceName() + " cannot reserve port " + port +
" on " + this + ": Already reserved for " + otherService.getServiceName() +
- ". " + msg + "Next available port is: " + nextAvailablePort);
+ ". " + msg + "Next available port is: " + nextAvailablePort + " ports used: " + portDB);
}
-
private void noMoreAvailablePorts() {
throw new RuntimeException
("Too many ports are reserved in Vespa's port range (" +
@@ -201,7 +187,6 @@ public class HostResource implements Comparable<HostResource> {
". Move one or more services to another host, or outside this port range.");
}
-
/**
* Returns the service with the given "sentinel name" on this Host,
* or null if the name does not match any service.
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/InstanceResolver.java b/config-model/src/main/java/com/yahoo/vespa/model/InstanceResolver.java
index ab095ec8d42..051f0e9e52e 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/InstanceResolver.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/InstanceResolver.java
@@ -59,9 +59,8 @@ class InstanceResolver {
ConfigDefinitionKey defKey = new ConfigDefinitionKey(key);
try {
if (targetDef != null) applyDef(builder, targetDef);
- ConfigInstance instance = getInstance(defKey, builder.getClass().getClassLoader());
- Class<? extends ConfigInstance> clazz = instance.getClass();
- return clazz.getConstructor(new Class<?>[]{builder.getClass()}).newInstance(builder);
+ Class<? extends ConfigInstance> clazz = getConfigClass(defKey, builder.getClass().getClassLoader());
+ return clazz.getConstructor(builder.getClass()).newInstance(builder);
} catch (Exception e) {
throw new ConfigurationRuntimeException(e);
}
@@ -153,50 +152,25 @@ class InstanceResolver {
}
/**
- * Create a ConfigBuilder given a definition key and a payload
- * @param key The key to use to create the correct builder.
- * @param payload The payload to populate the builder with.
- * @return A ConfigBuilder initialized with payload.
- */
- static ConfigBuilder createBuilderFromPayload(ConfigDefinitionKey key, VespaModel model, ConfigPayload payload, ConfigDefinition targetDef) {
- ConfigBuilder builderInstance = model.createBuilder(key, targetDef);
- if (builderInstance == null || builderInstance instanceof GenericConfig.GenericConfigBuilder) {
- if (log.isLoggable(LogLevel.SPAM)) {
- log.log(LogLevel.SPAM, "Creating generic builder for key=" + key);
- }
- return new GenericConfig.GenericConfigBuilder(key, new ConfigPayloadBuilder(payload));
- }
- ConfigTransformer transformer = new ConfigTransformer(builderInstance.getClass().getDeclaringClass());
- return transformer.toConfigBuilder(payload);
- }
-
- /**
* Returns a {@link ConfigInstance} of right type for given key using reflection
*
* @param cKey a ConfigKey
* @return a {@link ConfigInstance} or null if not available in classpath
*/
- private static ConfigInstance getInstance(ConfigDefinitionKey cKey, ClassLoader instanceLoader) {
+ @SuppressWarnings("unchecked")
+ private static Class<? extends ConfigInstance> getConfigClass(ConfigDefinitionKey cKey, ClassLoader instanceLoader) {
String className = ConfigGenerator.createClassName(cKey.getName());
- Class<?> clazz;
String fullClassName = packageName(cKey) + "." + className;
+ Class<?> clazz;
try {
clazz = instanceLoader != null ? instanceLoader.loadClass(fullClassName) : Class.forName(fullClassName);
} catch (ClassNotFoundException e) {
- return null;
- }
- Object i;
- try {
- Constructor<?> configConstructor = clazz.getDeclaredConstructor();
- configConstructor.setAccessible(true);
- i = configConstructor.newInstance();
- } catch (InvocationTargetException | InstantiationException | IllegalAccessException | NoSuchMethodException e) {
- throw new ConfigurationRuntimeException(e);
+ throw new ConfigurationRuntimeException("Could not find config class for key " + cKey, e);
}
- if (!(i instanceof ConfigInstance)) {
- throw new ConfigurationRuntimeException(fullClassName + " is not a ConfigInstance, can not produce config for the name '" + cKey.getName() + "'.");
+ if (! ConfigInstance.class.isAssignableFrom(clazz)) {
+ throw new ConfigurationRuntimeException(fullClassName + " is not a ConfigInstance subclass, can not produce config for " + cKey);
}
- return (ConfigInstance) i;
+ return (Class<? extends ConfigInstance>) clazz;
}
static String packageName(ConfigDefinitionKey cKey) {
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/PortsMeta.java b/config-model/src/main/java/com/yahoo/vespa/model/PortsMeta.java
index a0b3cc7294b..e8f2bf42807 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/PortsMeta.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/PortsMeta.java
@@ -20,7 +20,7 @@ public class PortsMeta implements Serializable {
private Integer rpcAdminOffset = null;
/** Remember the rpc status port offset. */
private Integer rpcStatusOffset = null;
- /** Remember the https admin port offset. */
+ /** Remember the http admin port offset. */
private Integer httpAdminOffset = null;
/** Remember the http status port offset. */
private Integer httpStatusOffset = null;
@@ -64,7 +64,7 @@ public class PortsMeta implements Serializable {
private PortsMeta register(int offset, String meta) {
// Allocate new LinkedLists on each element up-to-and-including offset
for (int i = ports.size(); i <= offset; i++) {
- ports.add(i, new LinkedList<String>());
+ ports.add(i, new LinkedList<>());
}
ports.get(offset).addFirst(meta);
@@ -88,6 +88,7 @@ public class PortsMeta implements Serializable {
public int getNumPorts() {
return ports.size();
}
+
/**
* Get an iterator of the Strings registered at the specific point.
* @param offset The relative offset to inquire about tags.
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/admin/Configserver.java b/config-model/src/main/java/com/yahoo/vespa/model/admin/Configserver.java
index b2c2510ce22..cd06ae67776 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/admin/Configserver.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/admin/Configserver.java
@@ -42,16 +42,16 @@ public class Configserver extends AbstractService {
* Returns the desired base port for this service.
*/
public int getWantedPort() {
- try {
- // TODO: Provide configserver port as argument when creating this service instead
- Process process = new ProcessBuilder(getDefaults().underVespaHome("bin/vespa-print-default"), "configserver_rpc_port").start();
- InputStream in = process.getInputStream();
- BufferedReader reader = new BufferedReader(new InputStreamReader(in));
- return Integer.parseInt(reader.readLine().trim());
- } catch (Exception exception) {
- log.log(LogLevel.DEBUG, "Error reading port from script, using " + defaultPort);
- return defaultPort;
- }
+ try {
+ // TODO: Provide configserver port as argument when creating this service instead
+ Process process = new ProcessBuilder(getDefaults().underVespaHome("bin/vespa-print-default"), "configserver_rpc_port").start();
+ InputStream in = process.getInputStream();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+ return Integer.parseInt(reader.readLine().trim());
+ } catch (Exception exception) {
+ log.log(LogLevel.DEBUG, "Error reading port from script, using " + defaultPort);
+ return defaultPort;
+ }
}
/**
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/admin/Slobrok.java b/config-model/src/main/java/com/yahoo/vespa/model/admin/Slobrok.java
index a2b7c7a5532..912809178ee 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/admin/Slobrok.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/admin/Slobrok.java
@@ -13,8 +13,8 @@ public class Slobrok extends AbstractService {
private static final long serialVersionUID = 1L;
/**
- * @param parent The parent ConfigProducer.
- * @param index unique index for all slobroks
+ * @param parent The parent ConfigProducer.
+ * @param index unique index for all slobroks
*/
public Slobrok(AbstractConfigProducer parent, int index) {
super(parent, "slobrok." + index);
@@ -42,8 +42,8 @@ public class Slobrok extends AbstractService {
public String getStartupCommand() {
return "exec $ROOT/bin/slobrok -p " + getPort() +
- " -s " + getStatePort() +
- " -c " + getConfigId();
+ " -s " + getStatePort() +
+ " -c " + getConfigId();
}
/**
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/Container.java b/config-model/src/main/java/com/yahoo/vespa/model/container/Container.java
index 56fa3d01abc..baf4b8d41e4 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/container/Container.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/container/Container.java
@@ -48,18 +48,7 @@ public class Container extends AbstractService implements
ComponentsConfig.Producer,
JdiscBindingsConfig.Producer,
ContainerHttpConfig.Producer,
- ContainerMbusConfig.Producer
-{
- public static final class PortOverride {
- public final ComponentSpecification serverId;
- public final int port;
-
- public PortOverride(ComponentSpecification serverId, int port) {
- this.serverId = serverId;
- this.port = port;
- }
- }
-
+ ContainerMbusConfig.Producer {
public static final int BASEPORT = Defaults.getDefaults().vespaWebServicePort();
public static final String SINGLENODE_CONTAINER_SERVICESPEC = "default_singlenode_container";
@@ -80,15 +69,15 @@ public class Container extends AbstractService implements
private final int index;
private final ComponentGroup<Handler<?>> handlers = new ComponentGroup<>(this, "handler");
- private final ComponentGroup<Component<?, ?>> components = new ComponentGroup(this, "components");
+ private final ComponentGroup<Component<?, ?>> components = new ComponentGroup<>(this, "components");
private final JettyHttpServer defaultHttpServer = new JettyHttpServer(new ComponentId("DefaultHttpServer"));
private final List<PortOverride> portOverrides;
private final int numHttpServerPorts;
- private final int numRpcServerPorts = 2;
- private static String defaultHostedJVMArgs = "-XX:+UseOSErrorReporting -XX:+SuppressFatalErrorMessage";
+ private static final int numRpcServerPorts = 2;
+ private static final String defaultHostedJVMArgs = "-XX:+UseOSErrorReporting -XX:+SuppressFatalErrorMessage";
public Container(AbstractConfigProducer parent, String name, int index) {
this(parent, name, Collections.<PortOverride>emptyList(), index);
@@ -218,7 +207,7 @@ public class Container extends AbstractService implements
return (parent instanceof ContainerCluster) && (((ContainerCluster)parent).getDocproc() != null);
}
- // TODO: hack to retain old service names, e.g. in ymon config, vespa.log etc.
+ // TODO: hack to retain old service names, e.g. in monitoring config, vespa.log etc.
@Override
public String getServiceType() {
if (parent instanceof ContainerCluster) {
@@ -404,4 +393,14 @@ public class Container extends AbstractService implements
this.httpServerEnabled = httpServerEnabled;
}
+ public static final class PortOverride {
+ public final ComponentSpecification serverId;
+ public final int port;
+
+ public PortOverride(ComponentSpecification serverId, int port) {
+ this.serverId = serverId;
+ this.port = port;
+ }
+ }
+
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java
index dbae6851977..fdb0f08f631 100755
--- a/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java
@@ -154,7 +154,7 @@ public final class ContainerCluster
public static final String ROOT_HANDLER_BINDING = "*://*/";
- private String name;
+ private final String name;
private List<Container> containers = new ArrayList<>();
@@ -243,9 +243,9 @@ public final class ContainerCluster
Handler<AbstractConfigProducer<?>> stateHandler = new Handler<>(
new ComponentModel(STATE_HANDLER_CLASS, null, null, null));
stateHandler.addServerBindings("http://*" + StateHandler.STATE_API_ROOT,
- "https://*" + StateHandler.STATE_API_ROOT,
- "http://*" + StateHandler.STATE_API_ROOT + "/*",
- "https://*" + StateHandler.STATE_API_ROOT + "/*");
+ "https://*" + StateHandler.STATE_API_ROOT,
+ "http://*" + StateHandler.STATE_API_ROOT + "/*",
+ "https://*" + StateHandler.STATE_API_ROOT + "/*");
addComponent(stateHandler);
}
@@ -308,12 +308,6 @@ public final class ContainerCluster
}
}
- public final void addComponents(Collection<Component<?, ?>> components) {
- for (Component<?, ?> component : components) {
- addComponent(component);
- }
- }
-
public final void addSimpleComponent(String idSpec, String classSpec, String bundleSpec) {
addComponent(new SimpleComponent(new ComponentModel(idSpec, classSpec, bundleSpec)));
}
@@ -847,14 +841,14 @@ public final class ContainerCluster
}
public static class MbusParams {
- //the amount of the maxpendingbytes to process concurrently, typically 0.2 (20%)
- public final Double maxConcurrentFactor;
+ // the amount of the maxpendingbytes to process concurrently, typically 0.2 (20%)
+ final Double maxConcurrentFactor;
- //the amount that documents expand temporarily when processing them
- public final Double documentExpansionFactor;
+ // the amount that documents expand temporarily when processing them
+ final Double documentExpansionFactor;
- //the space to reserve for container, docproc stuff (memory that cannot be used for processing documents), in MB
- public final Integer containerCoreMemory;
+ // the space to reserve for container, docproc stuff (memory that cannot be used for processing documents), in MB
+ final Integer containerCoreMemory;
public MbusParams(Double maxConcurrentFactor, Double documentExpansionFactor, Integer containerCoreMemory) {
this.maxConcurrentFactor = maxConcurrentFactor;
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java
index 90ad0117dfb..1ddfbbd76e1 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java
@@ -6,6 +6,7 @@ import com.google.common.collect.Sets;
import com.yahoo.config.model.ConfigModelContext;
import com.yahoo.config.model.producer.AbstractConfigProducerRoot;
import com.yahoo.config.provision.ClusterSpec;
+import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.RegionName;
import com.yahoo.config.provision.Zone;
import com.yahoo.vespa.config.content.MessagetyperouteselectorpolicyConfig;
@@ -46,6 +47,7 @@ import org.w3c.dom.Element;
import java.util.*;
import java.util.logging.Level;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
/**
* A content cluster.
@@ -100,7 +102,7 @@ public class ContentCluster extends AbstractConfigProducer implements StorDistri
ModelElement documentsElement = contentElement.getChild("documents");
Map<String, NewDocumentType> documentDefinitions =
- new SearchDefinitionBuilder().build(context.getParentProducer().getRoot().getDeployState().getDocumentModel().getDocumentManager(), documentsElement);
+ new SearchDefinitionBuilder().build(context.getDeployState().getDocumentModel().getDocumentManager(), documentsElement);
String routingSelection = new DocumentSelectionBuilder().build(documentsElement);
Redundancy redundancy = new RedundancyBuilder().build(contentElement);
@@ -108,7 +110,7 @@ public class ContentCluster extends AbstractConfigProducer implements StorDistri
ContentCluster c = new ContentCluster(context.getParentProducer(), getClusterName(contentElement), documentDefinitions,
globallyDistributedDocuments, routingSelection, redundancy,
- context.getParentProducer().getRoot().getDeployState().getProperties().zone());
+ context.getDeployState().getProperties().zone());
c.clusterControllerConfig = new ClusterControllerConfig.Builder(getClusterName(contentElement), contentElement).build(c, contentElement.getXml());
c.search = new ContentSearchCluster.Builder(documentDefinitions, globallyDistributedDocuments).build(c, contentElement.getXml());
c.persistenceFactory = new EngineFactoryBuilder().build(contentElement, c);
@@ -585,19 +587,27 @@ public class ContentCluster extends AbstractConfigProducer implements StorDistri
/**
* Returns the distribution bits this cluster should use.
- * OnHosted Vespa this is hardcoded not computed from the nodes because reducing the number of nodes is a common
- * operation while reducing the number of distribution bits can lead to consistency problems.
+ * On Hosted Vespa this is hardcoded and not computed from the nodes because reducing the number of nodes is a common
+ * operation, while reducing the number of distribution bits can lead to consistency problems.
* This hardcoded value should work fine from 1-200 nodes. Those who have more will need to set this value
* in config and not remove it again if they reduce the node count.
*/
public int distributionBits() {
- if (zone.region().equals(RegionName.from("us-west-1"))) return 16; // TODO: Enable for all hosted zones (i.e when zone isn't default)
- if (zone.region().equals(RegionName.from("us-central-1"))) return 16; // TODO: Enable for all hosted zones (i.e when zone isn't default)
- if (zone.region().equals(RegionName.from("eu-west-1"))) return 16; // TODO: Enable for all hosted zones (i.e when zone isn't default)
- if (zone.region().equals(RegionName.from("ap-northeast-1"))) return 16; // TODO: Enable for all hosted zones (i.e when zone isn't default)
- if (zone.region().equals(RegionName.from("ap-northeast-2"))) return 16; // TODO: Enable for all hosted zones (i.e when zone isn't default)
- if (zone.region().equals(RegionName.from("us-east-3"))) return 16; // TODO: Enable for all hosted zones (i.e when zone isn't default)
- return DistributionBitCalculator.getDistributionBits(getNodeCountPerGroup(), getDistributionMode());
+ // TODO: Enable for all hosted zones (i.e when zone isn't default)
+ List<Zone> zonesWith16DistributionBits = Arrays.asList(createZone(Environment.prod, "us-west-1"),
+ createZone(Environment.prod, "us-central-1"),
+ createZone(Environment.prod, "eu-west-1"),
+ createZone(Environment.prod, "ap-northeast-1"),
+ createZone(Environment.prod, "ap-northeast-2"),
+ createZone(Environment.prod, "us-east-3"));
+ if (zonesWith16DistributionBits.contains(zone))
+ return 16;
+ else
+ return DistributionBitCalculator.getDistributionBits(getNodeCountPerGroup(), getDistributionMode());
+ }
+
+ private Zone createZone(Environment environment, String region) {
+ return new Zone(environment, RegionName.from(region));
}
@Override
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/search/Tuning.java b/config-model/src/main/java/com/yahoo/vespa/model/search/Tuning.java
index 5e02a6a84d1..38c7e8524b4 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/search/Tuning.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/search/Tuning.java
@@ -210,6 +210,7 @@ public class Tuning extends AbstractConfigProducer implements PartitionsConfig.P
public static class Compression {
public enum Type {
NONE("NONE"),
+ ZSTD("ZSTD"),
LZ4("LZ4");
public final String name;
diff --git a/config-model/src/main/resources/schema/content.rnc b/config-model/src/main/resources/schema/content.rnc
index 66e97e76aa4..88527951ccc 100644
--- a/config-model/src/main/resources/schema/content.rnc
+++ b/config-model/src/main/resources/schema/content.rnc
@@ -361,6 +361,6 @@ TuningIoOptionsLight = string "normal" | string "directio"
TuningIoOptionsFull = string "normal" | string "directio" | string "mmap" | string "mlock"
TuningCompression = element compression {
- element type { string "none" | string "lz4" }? &
+ element type { string "none" | string "lz4" | string "zstd" }? &
element level { xsd:nonNegativeInteger }?
}
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/ContainerClusterTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/ContainerClusterTest.java
index 859dd15e040..9b0e02d580b 100755
--- a/config-model/src/test/java/com/yahoo/vespa/model/container/ContainerClusterTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/container/ContainerClusterTest.java
@@ -207,7 +207,7 @@ public class ContainerClusterTest {
addContainer(cluster, "c2", "host-c2");
assertTrue(false);
} catch (IllegalArgumentException e) {
- assertTrue(e.getMessage().startsWith("Cluster container1 does not accept container com.yahoo.vespa.model.container.Container"));
+ assertEquals("Cluster container1 does not accept container qrserver on host 'host-c2'", e.getMessage());
}
}
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/content/ClusterTest.java b/config-model/src/test/java/com/yahoo/vespa/model/content/ClusterTest.java
index 126fcf7a583..82cbc338a8e 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/content/ClusterTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/content/ClusterTest.java
@@ -1,8 +1,14 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.model.content;
+import com.yahoo.config.model.deploy.DeployProperties;
+import com.yahoo.config.model.deploy.DeployState;
+import com.yahoo.config.model.test.MockRoot;
import com.yahoo.config.model.test.TestDriver;
import com.yahoo.config.model.test.TestRoot;
+import com.yahoo.config.provision.Environment;
+import com.yahoo.config.provision.RegionName;
+import com.yahoo.config.provision.Zone;
import com.yahoo.vespa.config.content.core.StorDistributormanagerConfig;
import com.yahoo.vespa.config.content.StorFilestorConfig;
import com.yahoo.vespa.config.content.core.StorServerConfig;
@@ -14,15 +20,20 @@ import com.yahoo.vespa.model.VespaModel;
import com.yahoo.vespa.model.container.ContainerCluster;
import com.yahoo.vespa.model.content.cluster.ContentCluster;
import com.yahoo.vespa.model.content.engines.ProtonEngine;
+import com.yahoo.vespa.model.content.utils.ContentClusterBuilder;
+import com.yahoo.vespa.model.content.utils.ContentClusterUtils;
+import com.yahoo.vespa.model.content.utils.SearchDefinitionBuilder;
import com.yahoo.vespa.model.test.utils.ApplicationPackageUtils;
import com.yahoo.vespa.model.test.utils.VespaModelCreatorWithMockPkg;
import org.junit.Test;
import java.util.List;
+import static junit.framework.TestCase.assertEquals;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.*;
+// TODO Rename to ContentClusterTest
public class ClusterTest extends ContentBaseTest {
private final static String HOSTS = "<admin version='2.0'><adminserver hostalias='mockhost' /></admin>";
@@ -412,20 +423,8 @@ public class ClusterTest extends ContentBaseTest {
"</content>"
);
- {
- FleetcontrollerConfig.Builder builder = new FleetcontrollerConfig.Builder();
- cluster.getConfig(builder);
- cluster.getClusterControllerConfig().getConfig(builder);
- FleetcontrollerConfig config = new FleetcontrollerConfig(builder);
- assertEquals(8, config.ideal_distribution_bits());
- }
+ assertDistributionBitsInConfig(cluster, 8);
- {
- StorDistributormanagerConfig.Builder builder = new StorDistributormanagerConfig.Builder();
- cluster.getConfig(builder);
- StorDistributormanagerConfig config = new StorDistributormanagerConfig(builder);
- assertEquals(8, config.minsplitcount());
- }
cluster = parse(
"<content version=\"1.0\" id=\"storage\">\n" +
" <documents/>" +
@@ -438,20 +437,7 @@ public class ClusterTest extends ContentBaseTest {
"</content>"
);
- {
- FleetcontrollerConfig.Builder builder = new FleetcontrollerConfig.Builder();
- cluster.getConfig(builder);
- cluster.getClusterControllerConfig().getConfig(builder);
- FleetcontrollerConfig config = new FleetcontrollerConfig(builder);
- assertEquals(8, config.ideal_distribution_bits());
- }
-
- {
- StorDistributormanagerConfig.Builder builder = new StorDistributormanagerConfig.Builder();
- cluster.getConfig(builder);
- StorDistributormanagerConfig config = new StorDistributormanagerConfig(builder);
- assertEquals(8, config.minsplitcount());
- }
+ assertDistributionBitsInConfig(cluster, 8);
}
@Test
@@ -469,20 +455,8 @@ public class ClusterTest extends ContentBaseTest {
"</content>"
);
- {
- FleetcontrollerConfig.Builder builder = new FleetcontrollerConfig.Builder();
- cluster.getConfig(builder);
- cluster.getClusterControllerConfig().getConfig(builder);
- FleetcontrollerConfig config = new FleetcontrollerConfig(builder);
- assertEquals(8, config.ideal_distribution_bits());
- }
+ assertDistributionBitsInConfig(cluster, 8);
- {
- StorDistributormanagerConfig.Builder builder = new StorDistributormanagerConfig.Builder();
- cluster.getConfig(builder);
- StorDistributormanagerConfig config = new StorDistributormanagerConfig(builder);
- assertEquals(8, config.minsplitcount());
- }
cluster = parse(
"<content version=\"1.0\" id=\"storage\">\n" +
" <documents/>" +
@@ -498,23 +472,20 @@ public class ClusterTest extends ContentBaseTest {
"</content>"
);
- {
- FleetcontrollerConfig.Builder builder = new FleetcontrollerConfig.Builder();
- cluster.getConfig(builder);
- cluster.getClusterControllerConfig().getConfig(builder);
- FleetcontrollerConfig config = new FleetcontrollerConfig(builder);
- assertEquals(8, config.ideal_distribution_bits());
- }
-
- {
- StorDistributormanagerConfig.Builder builder = new StorDistributormanagerConfig.Builder();
- cluster.getConfig(builder);
- StorDistributormanagerConfig config = new StorDistributormanagerConfig(builder);
- assertEquals(8, config.minsplitcount());
- }
+ assertDistributionBitsInConfig(cluster, 8);
}
@Test
+ public void testZoneDependentDistributionBits() throws Exception {
+ String xml = new ContentClusterBuilder().docTypes("test").getXml();
+
+ ContentCluster prodWith16Bits = createWithZone(xml, new Zone(Environment.prod, RegionName.from("us-east-3")));
+ assertDistributionBitsInConfig(prodWith16Bits, 16);
+
+ ContentCluster stagingNot16Bits = createWithZone(xml, new Zone(Environment.staging, RegionName.from("us-east-3")));
+ assertDistributionBitsInConfig(stagingNot16Bits, 8);
+ }
+ @Test
public void testGenerateSearchNodes()
{
ContentCluster cluster = parse(
@@ -818,4 +789,31 @@ public class ClusterTest extends ContentBaseTest {
assertThat(cluster.getSearch().getSearchNodes().size(), is(1));
assertTrue(cluster.getSearch().getSearchNodes().get(0).getPreShutdownCommand().isPresent());
}
+
+ private ContentCluster createWithZone(String clusterXml, Zone zone) throws Exception {
+ DeployState.Builder deployStateBuilder = new DeployState.Builder().properties(new DeployProperties.Builder()
+ .hostedVespa(true)
+ .zone(zone)
+ .build());
+ List<String> searchDefinitions = SearchDefinitionBuilder.createSearchDefinitions("test");
+ MockRoot root = ContentClusterUtils.createMockRoot(searchDefinitions, deployStateBuilder);
+ ContentCluster cluster = ContentClusterUtils.createCluster(clusterXml, root);
+ root.freezeModelTopology();
+ cluster.validate();
+ return cluster;
+ }
+
+ private void assertDistributionBitsInConfig(ContentCluster cluster, int distributionBits) {
+ FleetcontrollerConfig.Builder builder = new FleetcontrollerConfig.Builder();
+ cluster.getConfig(builder);
+ cluster.getClusterControllerConfig().getConfig(builder);
+ FleetcontrollerConfig config = new FleetcontrollerConfig(builder);
+ assertEquals(distributionBits, config.ideal_distribution_bits());
+
+ StorDistributormanagerConfig.Builder sdBuilder = new StorDistributormanagerConfig.Builder();
+ cluster.getConfig(sdBuilder);
+ StorDistributormanagerConfig storDistributormanagerConfig = new StorDistributormanagerConfig(sdBuilder);
+ assertEquals(distributionBits, storDistributormanagerConfig.minsplitcount());
+ }
+
}
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/content/utils/ContentClusterUtils.java b/config-model/src/test/java/com/yahoo/vespa/model/content/utils/ContentClusterUtils.java
index 595013c506e..aebe1b76644 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/content/utils/ContentClusterUtils.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/content/utils/ContentClusterUtils.java
@@ -2,10 +2,8 @@
package com.yahoo.vespa.model.content.utils;
import com.yahoo.config.application.api.ApplicationPackage;
-import com.yahoo.config.application.api.DeployLogger;
import com.yahoo.config.model.ConfigModelContext;
import com.yahoo.config.model.api.HostProvisioner;
-import com.yahoo.config.model.application.provider.BaseDeployLogger;
import com.yahoo.config.model.deploy.DeployState;
import com.yahoo.config.model.provision.InMemoryProvisioner;
import com.yahoo.config.model.provision.SingleNodeProvisioner;
@@ -34,14 +32,17 @@ public class ContentClusterUtils {
}
private static MockRoot createMockRoot(HostProvisioner provisioner, List<String> searchDefinitions) {
- ApplicationPackage applicationPackage = new MockApplicationPackage.Builder().withSearchDefinitions(searchDefinitions).build();
- DeployState deployState = new DeployState.Builder()
- .applicationPackage(applicationPackage)
- .modelHostProvisioner(provisioner)
- .build();
- return new MockRoot("", deployState);
+ return createMockRoot(provisioner, searchDefinitions, new DeployState.Builder());
+ }
+ private static MockRoot createMockRoot(HostProvisioner provisioner, List<String> searchDefinitions, DeployState.Builder deployStateBuilder) {
+ ApplicationPackage applicationPackage = new MockApplicationPackage.Builder().withSearchDefinitions(searchDefinitions).build();
+ deployStateBuilder.applicationPackage(applicationPackage)
+ .modelHostProvisioner(provisioner)
+ .build();
+ return new MockRoot("", deployStateBuilder.build());
}
+
public static MockRoot createMockRoot(String[] hosts, List<String> searchDefinitions) throws Exception {
return createMockRoot(new InMemoryProvisioner(true, hosts), searchDefinitions);
}
@@ -50,10 +51,14 @@ public class ContentClusterUtils {
return createMockRoot(new SingleNodeProvisioner(), searchDefinitions);
}
+ public static MockRoot createMockRoot(List<String> searchDefinitions, DeployState.Builder deployStateBuilder) {
+ return createMockRoot(new SingleNodeProvisioner(), searchDefinitions, deployStateBuilder);
+ }
+
public static ContentCluster createCluster(String clusterXml, MockRoot root) throws Exception {
Document doc = XML.getDocument(clusterXml);
Admin admin = new Admin(root, new Yamas("vespa", 60), new Metrics(), Collections.emptyMap(), false);
- ConfigModelContext context = ConfigModelContext.create(null, DeployState.createTestState(), null, root, null);
+ ConfigModelContext context = ConfigModelContext.create(null, root.getDeployState(), null, root, null);
return new ContentCluster.Builder(admin).build(Collections.emptyList(), context, doc.getDocumentElement());
}
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterSpec.java b/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterSpec.java
index 19fcce4b965..b7c942168d6 100644
--- a/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterSpec.java
+++ b/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterSpec.java
@@ -37,10 +37,6 @@ public final class ClusterSpec {
public Version vespaVersion() { return vespaVersion; }
- public String dockerImage() {
- return DockerImage.defaultImage.withTag(vespaVersion).toString();
- }
-
/** Returns the group within the cluster this specifies, or empty to specify the whole cluster */
public Optional<Group> group() { return groupId; }
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/DockerImage.java b/config-provisioning/src/main/java/com/yahoo/config/provision/DockerImage.java
index 2c6c9d82419..ba60e42e7d6 100644
--- a/config-provisioning/src/main/java/com/yahoo/config/provision/DockerImage.java
+++ b/config-provisioning/src/main/java/com/yahoo/config/provision/DockerImage.java
@@ -10,8 +10,6 @@ import com.yahoo.component.Version;
*/
public class DockerImage {
- public static final DockerImage defaultImage = new DockerImage("docker-registry.ops.yahoo.com:4443/vespa/ci");
-
private final String name;
public DockerImage(String name) {
@@ -20,9 +18,9 @@ public class DockerImage {
/** Get Docker image tag as version */
public Version tagAsVersion() {
- String[] parts = toString().split(":");
+ String[] parts = asString().split(":");
if (parts.length < 2) {
- throw new IllegalArgumentException("Could not parse tag from Docker image '" + toString() + "'");
+ throw new IllegalArgumentException("Could not parse tag from Docker image '" + asString() + "'");
}
return Version.fromString(parts[parts.length - 1]);
}
@@ -32,8 +30,8 @@ public class DockerImage {
return new DockerImage(name + ":" + version.toFullString());
}
- @Override
- public String toString() {
+ public String asString() {
return name;
}
+
}
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provisioning/package-info.java b/config-provisioning/src/main/java/com/yahoo/config/provisioning/package-info.java
new file mode 100644
index 00000000000..ff01235ac6f
--- /dev/null
+++ b/config-provisioning/src/main/java/com/yahoo/config/provisioning/package-info.java
@@ -0,0 +1,5 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+@ExportPackage
+package com.yahoo.config.provisioning;
+
+import com.yahoo.osgi.annotation.ExportPackage;
diff --git a/config-provisioning/src/main/resources/configdefinitions/node-repository.def b/config-provisioning/src/main/resources/configdefinitions/node-repository.def
new file mode 100644
index 00000000000..5fa1838af66
--- /dev/null
+++ b/config-provisioning/src/main/resources/configdefinitions/node-repository.def
@@ -0,0 +1,5 @@
+namespace=config.provisioning
+
+# Docker image to use in REST API responses. This must be a fully qualified name, including registry, but excluding
+# version. Example: my-docker-registry.domain.tld:8080/dist/vespa
+dockerImage string default="dummyImage"
diff --git a/config-provisioning/src/test/java/com/yahoo/config/provision/ProvisionInfoTest.java b/config-provisioning/src/test/java/com/yahoo/config/provision/ProvisionInfoTest.java
index bd691afaf55..b4726022ebb 100644
--- a/config-provisioning/src/test/java/com/yahoo/config/provision/ProvisionInfoTest.java
+++ b/config-provisioning/src/test/java/com/yahoo/config/provision/ProvisionInfoTest.java
@@ -54,7 +54,6 @@ public class ProvisionInfoTest {
assertTrue(!getHost(h1.hostname(), serializedInfo.getHosts()).membership().isPresent());
assertEquals("container/test/0", getHost(h3.hostname(), serializedInfo.getHosts()).membership().get().stringValue());
assertEquals(h3.membership().get().cluster().vespaVersion(), getHost(h3.hostname(), serializedInfo.getHosts()).membership().get().cluster().vespaVersion());
- assertEquals("docker-registry.ops.yahoo.com:4443/vespa/ci:6.73.1", getHost(h3.hostname(), serializedInfo.getHosts()).membership().get().cluster().dockerImage());
}
private HostSpec getHost(String hostname, Set<HostSpec> hosts) {
diff --git a/config-proxy/src/main/sh/config-ctl b/config-proxy/src/main/sh/vespa-config-ctl
index 7221ff0ee27..8f015bab6c1 100755
--- a/config-proxy/src/main/sh/config-ctl
+++ b/config-proxy/src/main/sh/vespa-config-ctl
@@ -140,7 +140,7 @@ case $1 in
export VESPA_SERVICE_NAME
vespa-runserver -s config-sentinel -r 10 -p $P_SENTINEL -- \
- sbin/config-sentinel -c "$CONFIG_ID"
+ sbin/vespa-config-sentinel -c "$CONFIG_ID"
;;
stop)
diff --git a/config-proxy/src/main/sh/cloudconfig_loadtester b/config-proxy/src/main/sh/vespa-config-loadtester
index 6efe70d570a..6efe70d570a 100644
--- a/config-proxy/src/main/sh/cloudconfig_loadtester
+++ b/config-proxy/src/main/sh/vespa-config-loadtester
diff --git a/config-proxy/src/main/sh/cloudconfig_verification b/config-proxy/src/main/sh/vespa-config-verification
index 0df2723cee5..0df2723cee5 100644
--- a/config-proxy/src/main/sh/cloudconfig_verification
+++ b/config-proxy/src/main/sh/vespa-config-verification
diff --git a/config/src/tests/configparser/configparser.cpp b/config/src/tests/configparser/configparser.cpp
index f9e36a11def..521df96af3a 100644
--- a/config/src/tests/configparser/configparser.cpp
+++ b/config/src/tests/configparser/configparser.cpp
@@ -108,14 +108,6 @@ TEST("require that escaped values are properly unescaped") {
ASSERT_EQUAL("a\nb\rc\\d\"eBg", value);
}
-TEST("verify that locale affects double parsing") {
- std::vector<vespalib::string> payload;
- setlocale(LC_NUMERIC, "nb_NO.UTF-8");
- payload.push_back("foo 3.14");
- ASSERT_EXCEPTION(ConfigParser::parse<double>("foo", payload), InvalidConfigException, "Value 3.14 is not a legal double");
- setlocale(LC_NUMERIC, "C");
-}
-
TEST("require that maps can be parsed")
{
writeFile("foo.cfg", "\nfooValue \"a\"\nfooMap{\"foo\"} 1336\nfooMap{\"bar\"} 1337\n");
diff --git a/configd/src/apps/sentinel/.gitignore b/configd/src/apps/sentinel/.gitignore
index bc87d9cebdc..b299012f583 100644
--- a/configd/src/apps/sentinel/.gitignore
+++ b/configd/src/apps/sentinel/.gitignore
@@ -1,3 +1,3 @@
.depend
Makefile
-config-sentinel
+vespa-config-sentinel
diff --git a/configd/src/apps/sentinel/CMakeLists.txt b/configd/src/apps/sentinel/CMakeLists.txt
index 5f20042c021..ea25156a3c4 100644
--- a/configd/src/apps/sentinel/CMakeLists.txt
+++ b/configd/src/apps/sentinel/CMakeLists.txt
@@ -9,7 +9,7 @@ vespa_add_executable(configd_config-sentinel_app
output-connection.cpp
metrics.cpp
state-api.cpp
- OUTPUT_NAME config-sentinel
+ OUTPUT_NAME vespa-config-sentinel
INSTALL sbin
DEPENDS
configdefinitions
diff --git a/configd/src/apps/su/.gitignore b/configd/src/apps/su/.gitignore
index 343f531c8c1..cda22958555 100644
--- a/configd/src/apps/su/.gitignore
+++ b/configd/src/apps/su/.gitignore
@@ -1,3 +1,3 @@
/.depend
/Makefile
-/run-as-yahoo
+/vespa-run-as-vespa-user
diff --git a/configd/src/apps/su/CMakeLists.txt b/configd/src/apps/su/CMakeLists.txt
index 8883fe2344f..72502e9dc5e 100644
--- a/configd/src/apps/su/CMakeLists.txt
+++ b/configd/src/apps/su/CMakeLists.txt
@@ -1,8 +1,8 @@
# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-vespa_add_executable(configd_run-as-yahoo_app
+vespa_add_executable(configd_vespa-run-as-vespa-user_app
SOURCES
main.cpp
- OUTPUT_NAME run-as-yahoo
+ OUTPUT_NAME vespa-run-as-vespa-user
INSTALL bin
DEPENDS
)
diff --git a/configd/src/apps/su/main.cpp b/configd/src/apps/su/main.cpp
index e6252e483cb..ab6cd919138 100644
--- a/configd/src/apps/su/main.cpp
+++ b/configd/src/apps/su/main.cpp
@@ -13,7 +13,7 @@
int main(int argc, char** argv)
{
if (argc < 2) {
- fprintf(stderr, "missing arguments, usage: run-as-yahoo <cmd> [args ...]\n");
+ fprintf(stderr, "missing arguments, usage: vespa-run-as-vespa-user <cmd> [args ...]\n");
exit(1);
}
const char *username = getenv("VESPA_USER");
diff --git a/configd/src/tests/configd/run-sentinel.sh b/configd/src/tests/configd/run-sentinel.sh
index 0a0f8e80bf2..e257a41c829 100755
--- a/configd/src/tests/configd/run-sentinel.sh
+++ b/configd/src/tests/configd/run-sentinel.sh
@@ -2,7 +2,7 @@
# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
set -e
-if ../../apps/sentinel/config-sentinel > tmp.log 2>&1 ; then
+if ../../apps/sentinel/vespa-config-sentinel > tmp.log 2>&1 ; then
echo "Should need argument"
exit 1
fi
diff --git a/configserver/CMakeLists.txt b/configserver/CMakeLists.txt
index fcc011790b9..0e7d404288b 100644
--- a/configserver/CMakeLists.txt
+++ b/configserver/CMakeLists.txt
@@ -1,5 +1,5 @@
# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-vespa_install_script(src/main/sh/cloudconfig_server-remove-state bin)
+vespa_install_script(src/main/sh/vespa-configserver-remove-state bin)
vespa_install_script(src/main/sh/start-filedistribution libexec/vespa)
vespa_install_script(src/main/sh/ping-configserver libexec/vespa)
vespa_install_script(src/main/sh/start-configserver libexec/vespa)
diff --git a/configserver/pom.xml b/configserver/pom.xml
index 0351000b760..519da2e80f2 100644
--- a/configserver/pom.xml
+++ b/configserver/pom.xml
@@ -239,7 +239,6 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
- <version>2.3.1</version>
<configuration>
<updateReleaseInfo>true</updateReleaseInfo>
</configuration>
diff --git a/configserver/src/main/sh/start-configserver b/configserver/src/main/sh/start-configserver
index 4d85b3e65b3..3c43f230094 100755
--- a/configserver/src/main/sh/start-configserver
+++ b/configserver/src/main/sh/start-configserver
@@ -101,8 +101,8 @@ export LD_LIBRARY_PATH=${VESPA_HOME}lib64
#Does not need fast allocation
export MALLOC_ARENA_MAX=1
-run-as-yahoo ${VESPA_HOME}libexec/vespa/start-filedistribution
-run-as-yahoo ${VESPA_HOME}libexec/vespa/start-logd
+vespa-run-as-vespa-user ${VESPA_HOME}libexec/vespa/start-filedistribution
+vespa-run-as-vespa-user ${VESPA_HOME}libexec/vespa/start-logd
# stuff for the configserver process:
@@ -128,7 +128,7 @@ printenv > $cfpfile
mkdir -p $bundlecachedir
chown -R ${VESPA_USER} $bundlecachedir
-run-as-yahoo vespa-runserver -s configserver -r 30 -p $pidfile -- \
+vespa-run-as-vespa-user vespa-runserver -s configserver -r 30 -p $pidfile -- \
java \
-Xms128m -Xmx2048m \
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${VESPA_HOME}var/crash \
diff --git a/configserver/src/main/sh/start-filedistribution b/configserver/src/main/sh/start-filedistribution
index ecf04e9e035..df8dce34f13 100755
--- a/configserver/src/main/sh/start-filedistribution
+++ b/configserver/src/main/sh/start-filedistribution
@@ -78,5 +78,5 @@ if [ "$multitenant" = "true" ]; then
export VESPA_LOG_CONTROL_DIR
export VESPA_LOG_CONTROL_FILE
cd ${ROOT}
- vespa-runserver -r 30 -s filedistributor -p $PIDFILE_FILEDISTRIBUTOR -- ${ROOT}/sbin/filedistributor --configid $VESPA_CONFIG_ID
+ vespa-runserver -r 30 -s filedistributor -p $PIDFILE_FILEDISTRIBUTOR -- ${ROOT}/sbin/vespa-filedistributor --configid $VESPA_CONFIG_ID
fi
diff --git a/configserver/src/main/sh/start-logd b/configserver/src/main/sh/start-logd
index 3ad735d5183..ab5f0384678 100644
--- a/configserver/src/main/sh/start-logd
+++ b/configserver/src/main/sh/start-logd
@@ -68,5 +68,5 @@ if [ "$multitenant" = "true" ]; then
PIDFILE_LOGD=var/run/logd.pid
VESPA_SERVICE_NAME=logd
export VESPA_SERVICE_NAME
- vespa-runserver -r 30 -s logd -p $PIDFILE_LOGD -- ${ROOT}/sbin/logd
+ vespa-runserver -r 30 -s logd -p $PIDFILE_LOGD -- ${ROOT}/sbin/vespa-logd
fi
diff --git a/configserver/src/main/sh/stop-configserver b/configserver/src/main/sh/stop-configserver
index 04867dd180e..371c2e6aafd 100755
--- a/configserver/src/main/sh/stop-configserver
+++ b/configserver/src/main/sh/stop-configserver
@@ -80,15 +80,15 @@ export VESPA_LOG_TARGET
multitenant=$cloudconfig_server__multitenant
if [ "$multitenant" = "true" ]; then
- run-as-yahoo vespa-runserver -s filedistributor -p $PIDFILE_FILEDISTRIBUTOR -S
- run-as-yahoo vespa-runserver -s logd -p $PIDFILE_LOGD -S
+ vespa-run-as-vespa-user vespa-runserver -s filedistributor -p $PIDFILE_FILEDISTRIBUTOR -S
+ vespa-run-as-vespa-user vespa-runserver -s logd -p $PIDFILE_LOGD -S
fi
# Try shutting down this way in case of upgrade. Can be removed in later versions.
-run-as-yahoo vespa-runserver -s configserver -p $PIDFILE_CONFIGSERVER -S
+vespa-run-as-vespa-user vespa-runserver -s configserver -p $PIDFILE_CONFIGSERVER -S
if [ -e "$PIDFILE_CONFIGSERVER" ]; then
export UNPRIVILEGED=1
export PID_FILE=$PIDFILE_CONFIGSERVER
- exec run-as-yahoo ${ROOT}/bin/jdisc_container_stop
+ exec vespa-run-as-vespa-user ${ROOT}/bin/jdisc_container_stop
fi
diff --git a/configserver/src/main/sh/cloudconfig_server-remove-state b/configserver/src/main/sh/vespa-configserver-remove-state
index 34ba240ffae..34ba240ffae 100755
--- a/configserver/src/main/sh/cloudconfig_server-remove-state
+++ b/configserver/src/main/sh/vespa-configserver-remove-state
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java
index 83b9a30b946..12670c0e8cc 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java
@@ -109,8 +109,7 @@ public class HostedDeployTest {
private void assertProvisionInfo(String vespaVersion, DeployTester tester, ApplicationId applicationId) {
tester.getProvisionInfoFromDeployedApp(applicationId).getHosts().stream()
- .forEach(h -> assertEquals(dockerRegistry + dockerVespaBaseImage + ":" + vespaVersion,
- h.membership().get().cluster().dockerImage()));
+ .forEach(h -> assertEquals(vespaVersion, h.membership().get().cluster().vespaVersion()));
}
private static ConfigserverConfig createConfigserverConfig() {
diff --git a/container-search/src/test/java/com/yahoo/prelude/query/parser/test/specialtokens.cfg b/container-search/src/test/java/com/yahoo/prelude/query/parser/test/specialtokens.cfg
index 5f54d47353f..306e590a7ca 100644
--- a/container-search/src/test/java/com/yahoo/prelude/query/parser/test/specialtokens.cfg
+++ b/container-search/src/test/java/com/yahoo/prelude/query/parser/test/specialtokens.cfg
@@ -6,7 +6,7 @@ tokenlist[0].tokens[1].token c++
tokenlist[0].tokens[2].token b.s.d.
tokenlist[0].tokens[3].token with space
tokenlist[0].tokens[4].token c#
-tokenlist[0].tokens[5].token dvd±r
+tokenlist[0].tokens[5].token dvd\xB1r
tokenlist[1].name other
tokenlist[1].tokens[4]
tokenlist[1].tokens[0].token [huh]
diff --git a/dist/post_install.sh b/dist/post_install.sh
index 8640f377e3d..abbfd55e13f 100755
--- a/dist/post_install.sh
+++ b/dist/post_install.sh
@@ -69,6 +69,10 @@ ln -s $PREFIX/lib/jars/zkfacade-jar-with-dependencies.jar $INSTALLPATH/conf/conf
ln -s $PREFIX/conf/configserver-app/components $INSTALLPATH/lib/jars/config-models
ln -s vespa-storaged-bin $INSTALLPATH/sbin/vespa-distributord-bin
+# Temporary when renaming programs in filedistribution
+ln -s vespa-filedistributor $INSTALLPATH/sbin/filedistributor
+ln -s vespa-filedistributor-bin $INSTALLPATH/sbin/filedistributor-bin
+
# Temporary when renaming binaries in fnet
ln -s vespa-rpc-info $INSTALLPATH/bin/rpc_info
ln -s vespa-rpc-invoke $INSTALLPATH/bin/rpc_invoke
@@ -98,12 +102,24 @@ ln -s vespa-doclocator $INSTALLPATH/bin/vespadoclocator
ln -s vespa-route $INSTALLPATH/bin/vesparoute
ln -s vespa-spoolmaster $INSTALLPATH/bin/spoolmaster
+# Temporary when renaming binaries in vespaclient-java
+ln -s vespa-document-statistics $INSTALLPATH/bin/vds-document-statistics
+ln -s vespa-stat $INSTALLPATH/bin/vdsstat
+ln -s vespa-destination $INSTALLPATH/bin/vespadestination
+ln -s vespa-feeder $INSTALLPATH/bin/vespafeeder
+ln -s vespa-get $INSTALLPATH/bin/vespaget
+ln -s vespa-visit $INSTALLPATH/bin/vespavisit
+ln -s vespa-visit-target $INSTALLPATH/bin/vespavisittarget
+
# Temporary when renaming binaries in vespalog
ln -s vespa-log-conv $INSTALLPATH/bin/vlogconv
ln -s vespa-logctl $INSTALLPATH/bin/logctl
ln -s vespa-logfmt $INSTALLPATH/bin/logfmt
ln -s vespa-log-replay $INSTALLPATH/bin/vlogreplay
+# Temporary when renaming binaries in logd
+ln -s vespa-logd $INSTALLPATH/sbin/logd
+
# Temporary when renaming binaries in memfilepersistence
ln -s vespa-dump-slotfile $INSTALLPATH/bin/dumpslotfile
ln -s vespa-vds-disktool-bin $INSTALLPATH/bin/vdsdisktool-bin
@@ -131,3 +147,10 @@ ln -s vespa-fbench-split-file $INSTALLPATH/bin/splitfile
# Temporary when renaming programs in slobrok
ln -s vespa-slobrok $INSTALLPATH/bin/slobrok
ln -s vespa-slobrok-cmd $INSTALLPATH/bin/sbcmd
+
+# Temporary when renaming programs in configd
+ln -s vespa-run-as-vespa-user $INSTALLPATH/bin/run-as-yahoo
+ln -s vespa-config-sentinel $INSTALLPATH/sbin/config-sentinel
+
+# Temporary when renaming programs in logserver
+ln -s vespa-logserver-start $INSTALLPATH/bin/logserver-start
diff --git a/dist/release-vespa-rpm.sh b/dist/release-vespa-rpm.sh
new file mode 100755
index 00000000000..4059b30b857
--- /dev/null
+++ b/dist/release-vespa-rpm.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+set -e
+
+if [ $# -ne 1 ]; then
+ echo "Usage: $0 <version>"
+ exit 1
+fi
+
+readonly VERSION=$1
+readonly SPECFILE="dist/vespa.spec"
+readonly RPM_BRANCH="rpmbuild"
+readonly CURRENT_BRANCH=$(git branch | grep "^\*" | cut -d' ' -f2)
+
+# Make sure we are up to date
+git checkout master
+git pull --rebase
+
+# Delete existing branch if exists and create new one
+git push origin :$RPM_BRANCH &> /dev/null || true
+git branch -D $RPM_BRANCH &> /dev/null || true
+git checkout -b $RPM_BRANCH $VERSION
+
+# Tito expects spec file to be on root
+git mv $SPECFILE .
+
+# Run tito to update spec file and tag
+tito init
+tito tag --use-version=$VERSION --no-auto-changelog
+
+# Push changes and tag to branc
+git push -u origin --follow-tags $RPM_BRANCH
+
+git checkout $CURRENT_BRANCH
+
diff --git a/dist/vespa.spec b/dist/vespa.spec
index b97662a3df5..1b4bc307468 100644
--- a/dist/vespa.spec
+++ b/dist/vespa.spec
@@ -22,6 +22,7 @@ BuildRequires: devtoolset-6-binutils
BuildRequires: Judy-devel
BuildRequires: cmake3
BuildRequires: lz4-devel
+BuildRequires: libzstd-devel
BuildRequires: zlib-devel
BuildRequires: maven
BuildRequires: libicu-devel
@@ -30,23 +31,24 @@ BuildRequires: java-1.8.0-openjdk-devel
BuildRequires: openssl-devel
BuildRequires: rpm-build
BuildRequires: make
-BuildRequires: vespa-boost-devel >= 1.59
-BuildRequires: vespa-cppunit-devel >= 1.12.1
-BuildRequires: vespa-libtorrent-devel >= 1.0.9
-BuildRequires: vespa-zookeeper-c-client-devel >= 3.4.8
+BuildRequires: vespa-boost-devel >= 1.59.0-6
+BuildRequires: vespa-cppunit-devel >= 1.12.1-6
+BuildRequires: vespa-libtorrent-devel >= 1.0.11-6
+BuildRequires: vespa-zookeeper-c-client-devel >= 3.4.9-6
BuildRequires: systemd
Requires: epel-release
Requires: Judy
Requires: lz4
+Requires: libzstd
Requires: zlib
Requires: libicu
Requires: llvm3.9
Requires: java-1.8.0-openjdk
Requires: openssl
-Requires: vespa-boost >= 1.59
-Requires: vespa-cppunit >= 1.12.1
-Requires: vespa-libtorrent >= 1.0.9
-Requires: vespa-zookeeper-c-client >= 3.4.8
+Requires: vespa-boost >= 1.59.0-6
+Requires: vespa-cppunit >= 1.12.1-6
+Requires: vespa-libtorrent >= 1.0.11-6
+Requires: vespa-zookeeper-c-client >= 3.4.9-6
Requires(pre): shadow-utils
# Ugly workaround because vespamalloc/src/vespamalloc/malloc/mmap.cpp uses the private
diff --git a/docker-api/src/test/java/com/yahoo/vespa/hosted/dockerapi/RunSystemTests.java b/docker-api/src/test/java/com/yahoo/vespa/hosted/dockerapi/RunSystemTests.java
index 0b52d54c0dd..96e5584fb4b 100644
--- a/docker-api/src/test/java/com/yahoo/vespa/hosted/dockerapi/RunSystemTests.java
+++ b/docker-api/src/test/java/com/yahoo/vespa/hosted/dockerapi/RunSystemTests.java
@@ -30,7 +30,7 @@ import static org.junit.Assert.assertEquals;
*
*
* Example usage:
- DockerImage vespaDockerBase = new DockerImage("docker-registry.ops.yahoo.com:4443/vespa/ci:6.52.35");
+ DockerImage vespaDockerBase = new DockerImage("docker-registry.domain.tld:8080/vespa/ci:6.52.35");
Path pathToSystemtestsInHost = Paths.get("/home/valerijf/dev/systemtests");
RunSystemTests runSystemTests = new RunSystemTests(vespaDockerBase, pathToSystemtestsInHost);
diff --git a/docker/.gitignore b/docker/.gitignore
index e7a9c1347be..d8d0fbf70f1 100644
--- a/docker/.gitignore
+++ b/docker/.gitignore
@@ -1 +1,2 @@
*.rpm
+vespa-ci-*.log
diff --git a/docker/Dockerfile.build b/docker/Dockerfile.build
index a0b935093eb..9aa35f2bd99 100644
--- a/docker/Dockerfile.build
+++ b/docker/Dockerfile.build
@@ -8,11 +8,13 @@ RUN yum-config-manager --add-repo https://copr.fedorainfracloud.org/coprs/g/vesp
devtoolset-6-gcc-c++ \
devtoolset-6-libatomic-devel \
devtoolset-6-binutils \
+ git \
make \
cmake3 \
ccache \
Judy-devel \
lz4-devel \
+ libzstd-devel \
zlib-devel \
maven \
libicu-devel \
@@ -26,6 +28,10 @@ RUN yum-config-manager --add-repo https://copr.fedorainfracloud.org/coprs/g/vesp
perl-Env \
perl-JSON \
perl-IO-Socket-IP \
+ perl-Data-Dumper \
+ perl-libwww-perl \
+ perl-Net-INET6Glue \
+ perl-URI \
sudo \
vespa-boost-devel \
vespa-libtorrent-devel \
diff --git a/docker/Dockerfile.ci b/docker/Dockerfile.ci
new file mode 100644
index 00000000000..39a5317fe14
--- /dev/null
+++ b/docker/Dockerfile.ci
@@ -0,0 +1,11 @@
+FROM vespabuild
+
+COPY vespa-ci-internal.sh /vespa-ci-internal.sh
+
+# Build using non-root user 'vespabuilder'
+RUN useradd --create-home -s /bin/bash vespabuilder
+WORKDIR /home/vespabuilder
+USER vespabuilder
+
+# Java requires proper locale for unicode
+ENV LANG en_US.UTF-8
diff --git a/docker/Dockerfile.run b/docker/Dockerfile.run
index e5ddc1c7903..d62faa5075c 100644
--- a/docker/Dockerfile.run
+++ b/docker/Dockerfile.run
@@ -3,5 +3,5 @@ FROM centos:7
# Needed to run vespa
RUN yum-config-manager --add-repo https://copr.fedorainfracloud.org/coprs/g/vespa/vespa/repo/epel-7/group_vespa-vespa-epel-7.repo && \
yum -y install epel-release && \
- yum -y install centos-release-scl
+ yum -y install centos-release-scl
diff --git a/docker/README.md b/docker/README.md
index 393d726cff2..e3105b9263a 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -13,6 +13,10 @@ Execute ```./build-vespa.sh <Vespa version number>``` to build Vespa from this s
The produced rpms will be available in this folder after compiliation. The version number will be compiled into binaries, but has no other meaning than that.
+## Building and testing Vespa
+Execute ```./vespa-ci.sh <git commit>``` to build and test a specific branch/tag/commit.
+
+
## Running Vespa
Execute ```./run-vespa.sh <Vespa version number>``` to start Vespa.
diff --git a/docker/vespa-ci-internal.sh b/docker/vespa-ci-internal.sh
new file mode 100755
index 00000000000..caa64824044
--- /dev/null
+++ b/docker/vespa-ci-internal.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+set -e
+set -x
+
+if [ $# -ne 1 ]; then
+ echo "Usage: $0 <git commit>"
+ echo "This script should not be called manually."
+ exit 1
+fi
+
+GIT_COMMIT=$1
+SOURCE_DIR=/home/vespabuilder/vespa
+BUILD_DIR=/home/vespabuilder/build
+NUM_CORES=$(nproc --all)
+NUM_THREADS=$((${NUM_CORES} + ${NUM_CORES}/2))
+
+mkdir "${SOURCE_DIR}"
+mkdir "${BUILD_DIR}"
+git clone --no-checkout --local --no-hardlinks file:///vespa "${SOURCE_DIR}"
+cd "${SOURCE_DIR}"
+git checkout --detach ${GIT_COMMIT}
+source /opt/rh/devtoolset-6/enable || true
+sh ./bootstrap.sh full
+MAVEN_OPTS="-Xms512m -Xmx512m" mvn install
+cd "${BUILD_DIR}"
+cmake3 -DCMAKE_INSTALL_PREFIX=/opt/vespa \
+ -DJAVA_HOME=/usr/lib/jvm/java-openjdk \
+ -DEXTRA_LINK_DIRECTORY="/opt/vespa-boost/lib;/opt/vespa-libtorrent/lib;/opt/vespa-zookeeper-c-client/lib;/opt/vespa-cppunit/lib;/usr/lib64/llvm3.9/lib" \
+ -DEXTRA_INCLUDE_DIRECTORY="/opt/vespa-boost/include;/opt/vespa-libtorrent/include;/opt/vespa-zookeeper-c-client/include;/opt/vespa-cppunit/include;/usr/include/llvm3.9" \
+ -DCMAKE_INSTALL_RPATH="/opt/vespa/lib64;/opt/vespa-boost/lib;/opt/vespa-libtorrent/lib;/opt/vespa-zookeeper-c-client/lib;/opt/vespa-cppunit/lib;/usr/lib/jvm/java-1.8.0/jre/lib/amd64/server;/usr/include/llvm3.9" \
+ -DCMAKE_BUILD_RPATH=/opt/vespa/lib64 \
+ "${SOURCE_DIR}"
+make -j ${NUM_THREADS}
+make -j ${NUM_THREADS} test
diff --git a/docker/vespa-ci.sh b/docker/vespa-ci.sh
new file mode 100755
index 00000000000..58705eae339
--- /dev/null
+++ b/docker/vespa-ci.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+set -e
+set -x
+
+if [ $# -ne 1 ]; then
+ echo "Usage: $0 <git commit>"
+ exit 1
+fi
+
+DIR=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)
+cd $DIR
+
+GIT_COMMIT=$1
+BUILD_DOCKER_IMAGE="vespabuild"
+CI_DOCKER_IMAGE="vespaci"
+
+docker build -t "$BUILD_DOCKER_IMAGE" -f Dockerfile.build .
+docker build -t "$CI_DOCKER_IMAGE" -f Dockerfile.ci .
+docker run --rm -v $(pwd)/..:/vespa --entrypoint /vespa-ci-internal.sh "$CI_DOCKER_IMAGE" "$GIT_COMMIT" \
+ 2>&1 | tee vespa-ci-${GIT_COMMIT}-$(date +%Y-%m-%dT%H:%M:%S%z).log
diff --git a/docprocs/pom.xml b/docprocs/pom.xml
index d85a4c475dd..b5c60b1179f 100644
--- a/docprocs/pom.xml
+++ b/docprocs/pom.xml
@@ -153,7 +153,6 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
- <version>2.3.1</version>
<configuration>
<updateReleaseInfo>true</updateReleaseInfo>
</configuration>
diff --git a/document/CMakeLists.txt b/document/CMakeLists.txt
index c0089c2bed8..cc4784c1ee2 100644
--- a/document/CMakeLists.txt
+++ b/document/CMakeLists.txt
@@ -10,6 +10,7 @@ vespa_define_module(
EXTERNAL_DEPENDS
lz4
+ zstd
LIBS
src/vespa/document
diff --git a/document/src/main/java/com/yahoo/document/serialization/VespaDocumentSerializer42.java b/document/src/main/java/com/yahoo/document/serialization/VespaDocumentSerializer42.java
index 211412be684..6095d4a1545 100644
--- a/document/src/main/java/com/yahoo/document/serialization/VespaDocumentSerializer42.java
+++ b/document/src/main/java/com/yahoo/document/serialization/VespaDocumentSerializer42.java
@@ -344,7 +344,7 @@ public class VespaDocumentSerializer42 extends BufferSerializer implements Docum
}
int pos = buf.position();
- if (compression.data() != null) {
+ if (compression.data() != null && compression.type().isCompressed()) {
put(null, compression.data());
} else {
put(null, buffer.getByteBuffer());
diff --git a/document/src/test/java/com/yahoo/document/serialization/VespaDocumentSerializerTestCase.java b/document/src/test/java/com/yahoo/document/serialization/VespaDocumentSerializerTestCase.java
index a47b6356a36..3e742c9e618 100644
--- a/document/src/test/java/com/yahoo/document/serialization/VespaDocumentSerializerTestCase.java
+++ b/document/src/test/java/com/yahoo/document/serialization/VespaDocumentSerializerTestCase.java
@@ -1,27 +1,37 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.document.serialization;
+import com.yahoo.compress.CompressionType;
+import com.yahoo.compress.Compressor;
+import com.yahoo.document.CompressionConfig;
import com.yahoo.document.DataType;
import com.yahoo.document.Document;
import com.yahoo.document.DocumentType;
+import com.yahoo.document.DocumentTypeManager;
import com.yahoo.document.Field;
+import com.yahoo.document.MapDataType;
+import com.yahoo.document.StructDataType;
import com.yahoo.document.datatypes.IntegerFieldValue;
+import com.yahoo.document.datatypes.MapFieldValue;
import com.yahoo.document.datatypes.PredicateFieldValue;
import com.yahoo.document.datatypes.StringFieldValue;
+import com.yahoo.document.datatypes.Struct;
import com.yahoo.io.GrowableByteBuffer;
import org.junit.Test;
import org.mockito.Mockito;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
/**
- * @author <a href="mailto:simon@yahoo-inc.com">Simon Thoresen</a>
+ * @author Simon Thoresen
+ * @author vekterli
*/
@SuppressWarnings("deprecation")
public class VespaDocumentSerializerTestCase {
@Test
- public void requireThatGetSerializedSizeUsesLatestSerializer() {
+ public void get_serialized_size_uses_latest_serializer() {
DocumentType docType = new DocumentType("my_type");
docType.addField("my_str", DataType.STRING);
docType.addField("my_int", DataType.INT);
@@ -35,7 +45,7 @@ public class VespaDocumentSerializerTestCase {
}
@Test
- public void requireThatPredicateFieldValuesAreSerialized() {
+ public void predicate_field_values_are_serialized() {
DocumentType docType = new DocumentType("my_type");
Field field = new Field("my_predicate", DataType.PREDICATE);
docType.addField(field);
@@ -46,4 +56,77 @@ public class VespaDocumentSerializerTestCase {
DocumentSerializerFactory.create42(new GrowableByteBuffer()).write(doc);
Mockito.verify(predicate, Mockito.times(1)).serialize(Mockito.same(field), Mockito.any(FieldWriter.class));
}
+
+ static class CompressionFixture {
+
+ static final String COMPRESSABLE_STRING = "zippy zip mc zippington the 3rd zippy zip";
+
+ final DocumentTypeManager manager;
+ final DocumentType docType;
+ final StructDataType nestedType;
+ final MapDataType mapType;
+
+ CompressionFixture() {
+ docType = new DocumentType("map_of_structs");
+ docType.getHeaderType().setCompressionConfig(new CompressionConfig(CompressionType.LZ4));
+
+ nestedType = new StructDataType("nested_type");
+ nestedType.addField(new Field("str", DataType.STRING));
+
+ mapType = new MapDataType(DataType.STRING, nestedType);
+ docType.addField(new Field("map", mapType));
+
+ manager = new DocumentTypeManager();
+ manager.registerDocumentType(docType);
+ }
+
+ static GrowableByteBuffer asSerialized(Document inputDoc) {
+ GrowableByteBuffer buf = new GrowableByteBuffer();
+ inputDoc.serialize(buf);
+ buf.flip();
+ return buf;
+ }
+
+ Document roundtripSerialize(Document inputDoc) {
+ return manager.createDocument(asSerialized(inputDoc));
+ }
+ }
+
+ @Test
+ public void compressed_map_of_compressed_structs_is_supported() {
+ CompressionFixture fixture = new CompressionFixture();
+
+ Document doc = new Document(fixture.docType, "id:foo:map_of_structs::flarn");
+ Struct nested = new Struct(fixture.nestedType);
+ nested.setFieldValue("str", new StringFieldValue(CompressionFixture.COMPRESSABLE_STRING));
+
+ MapFieldValue<StringFieldValue, Struct> map = new MapFieldValue<StringFieldValue, Struct>(fixture.mapType);
+ map.put(new StringFieldValue("foo"), nested);
+ map.put(new StringFieldValue("bar"), nested);
+ doc.setFieldValue("map", map);
+
+ // Should _not_ throw any deserialization exceptions
+ Document result = fixture.roundtripSerialize(doc);
+ assertEquals(doc, result);
+ }
+
+ @Test
+ public void incompressable_structs_are_serialized_without_buffer_size_overhead_bug() {
+ CompressionFixture fixture = new CompressionFixture();
+
+ Document doc = new Document(fixture.docType, "id:foo:map_of_structs::flarn");
+ Struct nested = new Struct(fixture.nestedType);
+ nested.setFieldValue("str", new StringFieldValue(CompressionFixture.COMPRESSABLE_STRING));
+
+ MapFieldValue<StringFieldValue, Struct> map = new MapFieldValue<StringFieldValue, Struct>(fixture.mapType);
+ // Only 1 struct added. Not enough redundant information that header struct containing map itself
+ // can be compressed.
+ map.put(new StringFieldValue("foo"), nested);
+ doc.setFieldValue("map", map);
+
+ GrowableByteBuffer buf = CompressionFixture.asSerialized(doc);
+ // Explanation of arbitrary value: buffer copy bug meant that incompressable structs were all serialized
+ // rounded up to 4096 bytes.
+ assertTrue(buf.remaining() < 4096);
+ }
}
diff --git a/document/src/tests/data/serializejava-compressed.dat b/document/src/tests/data/serializejava-compressed.dat
index 5c8721c097c..453abef81f1 100644
--- a/document/src/tests/data/serializejava-compressed.dat
+++ b/document/src/tests/data/serializejava-compressed.dat
Binary files differ
diff --git a/document/src/tests/serialization/compression_test.cpp b/document/src/tests/serialization/compression_test.cpp
index b41dfad7b36..240a309d180 100644
--- a/document/src/tests/serialization/compression_test.cpp
+++ b/document/src/tests/serialization/compression_test.cpp
@@ -1,27 +1,44 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-// Unit tests for annotation serialization.
-#include <vespa/log/log.h>
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/vespalib/stllike/string.h>
#include <vespa/document/util/compressor.h>
+#include <vespa/vespalib/data/databuffer.h>
+#include <vespa/log/log.h>
LOG_SETUP("compression_test");
using namespace document;
+using namespace document::compression;
using namespace vespalib;
static vespalib::string _G_compressableText("AAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDEEEEEEEEEEEEEEE"
"AAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDEEEEEEEEEEEEEEE"
"AAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDEEEEEEEEEEEEEEE"
"AAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDEEEEEEEEEEEEEEE"
- "AAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDEEEEEEEEEEEEEEE");
+ "AAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDEEEEEEEEEEEEEEE"
+ "XYZABCDEFGHIJGJMNOPQRSTUVW"
+ "AAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDEEEEEEEEEEEEEEE"
+ "AAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDEEEEEEEEEEEEEEE"
+ "AAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDEEEEEEEEEEEEEEE"
+ "AAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDEEEEEEEEEEEEEEE"
+ "AAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDEEEEEEEEEEEEEEE"
+ "XYZABCDEFGHIJGJMNOPQRSTUVW");
TEST("requireThatLZ4CompressFine") {
CompressionConfig cfg(CompressionConfig::Type::LZ4);
ConstBufferRef ref(_G_compressableText.c_str(), _G_compressableText.size());
DataBuffer compressed;
EXPECT_EQUAL(CompressionConfig::Type::LZ4, compress(cfg, ref, compressed, false));
+ EXPECT_EQUAL(66u, compressed.getDataLen());
+}
+
+TEST("requireThatZStdCompressFine") {
+ CompressionConfig cfg(CompressionConfig::Type::ZSTD);
+ ConstBufferRef ref(_G_compressableText.c_str(), _G_compressableText.size());
+ DataBuffer compressed;
+ EXPECT_EQUAL(CompressionConfig::Type::ZSTD, compress(cfg, ref, compressed, false));
+ EXPECT_EQUAL(64u, compressed.getDataLen());
}
TEST_MAIN() {
diff --git a/document/src/vespa/document/fieldvalue/serializablearray.cpp b/document/src/vespa/document/fieldvalue/serializablearray.cpp
index c8beea5e79c..0fb85a2aaf2 100644
--- a/document/src/vespa/document/fieldvalue/serializablearray.cpp
+++ b/document/src/vespa/document/fieldvalue/serializablearray.cpp
@@ -2,14 +2,15 @@
#include "serializablearray.h"
#include <vespa/document/util/serializableexceptions.h>
#include <vespa/document/util/bytebuffer.h>
+#include <vespa/document/util/compressor.h>
#include <vespa/vespalib/stllike/hash_map.hpp>
#include <vespa/vespalib/data/databuffer.h>
-#include <vespa/document/util/compressor.h>
#include <vespa/log/log.h>
LOG_SETUP(".document.serializable-array");
using std::vector;
+using vespalib::make_string;
namespace document {
@@ -179,6 +180,7 @@ SerializableArray::clear(int id)
void
SerializableArray::deCompress() // throw (DeserializeException)
{
+ using document::compression::decompress;
// will only do this once
LOG_ASSERT(_compSerData);
@@ -201,15 +203,14 @@ SerializableArray::deCompress() // throw (DeserializeException)
false);
} catch (const std::runtime_error & e) {
throw DeserializeException(
- vespalib::make_string( "Document was compressed with code unknown code %d", _serializedCompression),
+ make_string( "Document was compressed with code unknown code %d", _serializedCompression),
VESPA_STRLOC);
}
if (unCompressed.getDataLen() != (size_t)_uncompressedLength) {
throw DeserializeException(
- vespalib::make_string(
- "Did not decompress to the expected length: had %" PRIu64 ", wanted %d, got %" PRIu64,
- _compSerData->getRemaining(), _uncompressedLength, unCompressed.getDataLen()),
+ make_string("Did not decompress to the expected length: had %zu, wanted %d, got %zu",
+ _compSerData->getRemaining(), _uncompressedLength, unCompressed.getDataLen()),
VESPA_STRLOC);
}
assert(newSerialization->getBuffer() == unCompressed.getData());
diff --git a/document/src/vespa/document/serialization/vespadocumentserializer.cpp b/document/src/vespa/document/serialization/vespadocumentserializer.cpp
index 1f6a4a4f0b0..a95dd092f20 100644
--- a/document/src/vespa/document/serialization/vespadocumentserializer.cpp
+++ b/document/src/vespa/document/serialization/vespadocumentserializer.cpp
@@ -263,6 +263,7 @@ vespalib::ConstBufferRef
compressStream(const CompressionConfig &config, nbostream &stream,
vespalib::DataBuffer & compressed_data)
{
+ using compression::compress;
vespalib::ConstBufferRef buf(stream.c_str(), stream.size());
if (config.useCompression() && bigEnough(stream.size(), config)) {
CompressionConfig::Type compressedType = compress(config, vespalib::ConstBufferRef(stream.c_str(), stream.size()), compressed_data, false);
diff --git a/document/src/vespa/document/util/CMakeLists.txt b/document/src/vespa/document/util/CMakeLists.txt
index d8fe0d833ff..ae1f7441062 100644
--- a/document/src/vespa/document/util/CMakeLists.txt
+++ b/document/src/vespa/document/util/CMakeLists.txt
@@ -1,11 +1,13 @@
# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
vespa_add_library(document_util OBJECT
SOURCES
- stringutil.cpp
bytebuffer.cpp
- serializable.cpp
compressor.cpp
+ lz4compressor.cpp
+ zstdcompressor.cpp
printable.cpp
+ serializable.cpp
+ stringutil.cpp
DEPENDS
AFTER
document_documentconfig
diff --git a/document/src/vespa/document/util/compressionconfig.h b/document/src/vespa/document/util/compressionconfig.h
index 1ed6ec882ec..ff02e35977a 100644
--- a/document/src/vespa/document/util/compressionconfig.h
+++ b/document/src/vespa/document/util/compressionconfig.h
@@ -7,16 +7,16 @@
namespace document {
-
struct CompressionConfig {
enum Type {
- NONE = 0,
- HISTORIC_1 = 1,
- HISTORIC_2 = 2,
- HISTORIC_3 = 3,
- HISTORIC_4 = 4,
- UNCOMPRESSABLE = 5,
- LZ4 = 6
+ NONE = 0,
+ HISTORIC_1 = 1,
+ HISTORIC_2 = 2,
+ HISTORIC_3 = 3,
+ HISTORIC_4 = 4,
+ UNCOMPRESSABLE = 5,
+ LZ4 = 6,
+ ZSTD = 7
};
CompressionConfig()
@@ -47,6 +47,7 @@ struct CompressionConfig {
case 4: return HISTORIC_4;
case 5: return UNCOMPRESSABLE;
case 6: return LZ4;
+ case 7: return ZSTD;
default: return NONE;
}
}
diff --git a/document/src/vespa/document/util/compressor.cpp b/document/src/vespa/document/util/compressor.cpp
index 0783bb28a60..6ada9bca3db 100644
--- a/document/src/vespa/document/util/compressor.cpp
+++ b/document/src/vespa/document/util/compressor.cpp
@@ -1,56 +1,17 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-#include "compressor.h"
+
+#include "lz4compressor.h"
+#include "zstdcompressor.h"
#include <vespa/vespalib/util/memory.h>
#include <vespa/vespalib/util/stringfmt.h>
-#include <stdexcept>
-#include <lz4.h>
-#include <lz4hc.h>
+#include <vespa/vespalib/data/databuffer.h>
using vespalib::alloc::Alloc;
using vespalib::ConstBufferRef;
using vespalib::DataBuffer;
using vespalib::make_string;
-namespace document
-{
-
-size_t LZ4Compressor::adjustProcessLen(uint16_t, size_t len) const { return LZ4_compressBound(len); }
-size_t LZ4Compressor::adjustUnProcessLen(uint16_t, size_t len) const { return len; }
-
-bool
-LZ4Compressor::process(const CompressionConfig& config, const void * inputV, size_t inputLen, void * outputV, size_t & outputLenV)
-{
- const char * input(static_cast<const char *>(inputV));
- char * output(static_cast<char *>(outputV));
- int sz(-1);
- int maxOutputLen = LZ4_compressBound(inputLen);
- if (config.compressionLevel > 6) {
- Alloc state = Alloc::alloc(LZ4_sizeofStateHC());
- sz = LZ4_compress_HC_extStateHC(state.get(), input, output, inputLen, maxOutputLen, config.compressionLevel);
- } else {
- Alloc state = Alloc::alloc(LZ4_sizeofState());
- sz = LZ4_compress_fast_extState(state.get(), input, output, inputLen, maxOutputLen, 1);
- }
- if (sz != 0) {
- outputLenV = sz;
- }
- assert(sz != 0);
- return (sz != 0);
-
-}
-
-bool
-LZ4Compressor::unprocess(const void * inputV, size_t inputLen, void * outputV, size_t & outputLenV)
-{
- const char * input(static_cast<const char *>(inputV));
- char * output(static_cast<char *>(outputV));
- int sz = LZ4_decompress_safe(input, output, inputLen, outputLenV);
- if (sz > 0) {
- outputLenV = sz;
- }
- assert(sz > 0);
- return (sz > 0);
-}
+namespace document::compression {
CompressionConfig::Type
compress(ICompressor & compressor, const CompressionConfig & compression, const ConstBufferRef & org, DataBuffer & dest)
@@ -78,6 +39,12 @@ docompress(const CompressionConfig & compression, const ConstBufferRef & org, Da
type = compress(lz4, compression, org, dest);
}
break;
+ case CompressionConfig::ZSTD:
+ {
+ ZStdCompressor zstd;
+ type = compress(zstd, compression, org, dest);
+ }
+ break;
case CompressionConfig::NONE:
default:
break;
@@ -138,6 +105,12 @@ decompress(const CompressionConfig::Type & type, size_t uncompressedLen, const C
decompress(lz4, uncompressedLen, org, dest, allowSwap);
}
break;
+ case CompressionConfig::ZSTD:
+ {
+ ZStdCompressor zstd;
+ decompress(zstd, uncompressedLen, org, dest, allowSwap);
+ }
+ break;
case CompressionConfig::NONE:
case CompressionConfig::UNCOMPRESSABLE:
if (allowSwap) {
@@ -154,4 +127,15 @@ decompress(const CompressionConfig::Type & type, size_t uncompressedLen, const C
}
}
+size_t computeMaxCompressedsize(CompressionConfig::Type type, size_t payloadSize) {
+ if (type == CompressionConfig::LZ4) {
+ document::LZ4Compressor lz4;
+ return lz4.adjustProcessLen(0, payloadSize);
+ } else if (type == CompressionConfig::ZSTD) {
+ document::ZStdCompressor zstd;
+ return zstd.adjustProcessLen(0, payloadSize);
+ }
+ return payloadSize;
+}
+
}
diff --git a/document/src/vespa/document/util/compressor.h b/document/src/vespa/document/util/compressor.h
index 599d9424889..11103beb93c 100644
--- a/document/src/vespa/document/util/compressor.h
+++ b/document/src/vespa/document/util/compressor.h
@@ -1,12 +1,12 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#pragma once
-#include <vespa/document/util/compressionconfig.h>
-#include <vespa/vespalib/data/databuffer.h>
+#include "compressionconfig.h"
#include <vespa/vespalib/util/buffer.h>
-namespace document
-{
+namespace vespalib { class DataBuffer; }
+
+namespace document {
class ICompressor
{
@@ -15,17 +15,9 @@ public:
virtual bool process(const CompressionConfig& config, const void * input, size_t inputLen, void * output, size_t & outputLen) = 0;
virtual bool unprocess(const void * input, size_t inputLen, void * output, size_t & outputLen) = 0;
virtual size_t adjustProcessLen(uint16_t options, size_t len) const = 0;
- virtual size_t adjustUnProcessLen(uint16_t options, size_t len) const = 0;
};
-class LZ4Compressor : public ICompressor
-{
-public:
- bool process(const CompressionConfig& config, const void * input, size_t inputLen, void * output, size_t & outputLen) override;
- bool unprocess(const void * input, size_t inputLen, void * output, size_t & outputLen) override;
- size_t adjustProcessLen(uint16_t options, size_t len) const override;
- size_t adjustUnProcessLen(uint16_t options, size_t len) const override;
-};
+namespace compression {
/**
* Will try to compress a buffer according to the config. If the criteria can not
@@ -51,5 +43,9 @@ CompressionConfig::Type compress(const CompressionConfig & compression, const ve
*/
void decompress(const CompressionConfig::Type & compression, size_t uncompressedLen, const vespalib::ConstBufferRef & org, vespalib::DataBuffer & dest, bool allowSwap);
+
+size_t computeMaxCompressedsize(CompressionConfig::Type type, size_t uncompressedSize);
+
}
+}
diff --git a/document/src/vespa/document/util/lz4compressor.cpp b/document/src/vespa/document/util/lz4compressor.cpp
new file mode 100644
index 00000000000..9b41df239a9
--- /dev/null
+++ b/document/src/vespa/document/util/lz4compressor.cpp
@@ -0,0 +1,46 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include "lz4compressor.h"
+#include <vespa/vespalib/util/alloc.h>
+#include <lz4.h>
+#include <lz4hc.h>
+#include <cassert>
+
+using vespalib::alloc::Alloc;
+
+namespace document {
+
+size_t LZ4Compressor::adjustProcessLen(uint16_t, size_t len) const { return LZ4_compressBound(len); }
+
+bool
+LZ4Compressor::process(const CompressionConfig& config, const void * inputV, size_t inputLen, void * outputV, size_t & outputLenV)
+{
+ const char * input(static_cast<const char *>(inputV));
+ char * output(static_cast<char *>(outputV));
+ int sz(-1);
+ int maxOutputLen = LZ4_compressBound(inputLen);
+ if (config.compressionLevel > 6) {
+ Alloc state = Alloc::alloc(LZ4_sizeofStateHC());
+ sz = LZ4_compress_HC_extStateHC(state.get(), input, output, inputLen, maxOutputLen, config.compressionLevel);
+ } else {
+ Alloc state = Alloc::alloc(LZ4_sizeofState());
+ sz = LZ4_compress_fast_extState(state.get(), input, output, inputLen, maxOutputLen, 1);
+ }
+ assert(sz != 0);
+ outputLenV = sz;
+ return (sz != 0);
+
+}
+
+bool
+LZ4Compressor::unprocess(const void * inputV, size_t inputLen, void * outputV, size_t & outputLenV)
+{
+ const char * input(static_cast<const char *>(inputV));
+ char * output(static_cast<char *>(outputV));
+ int sz = LZ4_decompress_safe(input, output, inputLen, outputLenV);
+ assert(sz > 0);
+ outputLenV = sz;
+ return (sz > 0);
+}
+
+}
diff --git a/document/src/vespa/document/util/lz4compressor.h b/document/src/vespa/document/util/lz4compressor.h
new file mode 100644
index 00000000000..aa1726cd639
--- /dev/null
+++ b/document/src/vespa/document/util/lz4compressor.h
@@ -0,0 +1,17 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#pragma once
+
+#include "compressor.h"
+
+namespace document {
+
+class LZ4Compressor : public ICompressor
+{
+public:
+ bool process(const CompressionConfig& config, const void * input, size_t inputLen, void * output, size_t & outputLen) override;
+ bool unprocess(const void * input, size_t inputLen, void * output, size_t & outputLen) override;
+ size_t adjustProcessLen(uint16_t options, size_t len) const override;
+};
+
+}
+
diff --git a/document/src/vespa/document/util/zstdcompressor.cpp b/document/src/vespa/document/util/zstdcompressor.cpp
new file mode 100644
index 00000000000..bb13d8009c1
--- /dev/null
+++ b/document/src/vespa/document/util/zstdcompressor.cpp
@@ -0,0 +1,34 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include "zstdcompressor.h"
+#include <vespa/vespalib/util/alloc.h>
+#include <zstd.h>
+#include <cassert>
+
+using vespalib::alloc::Alloc;
+
+namespace document {
+
+size_t ZStdCompressor::adjustProcessLen(uint16_t, size_t len) const { return ZSTD_compressBound(len); }
+
+bool
+ZStdCompressor::process(const CompressionConfig& config, const void * inputV, size_t inputLen, void * outputV, size_t & outputLenV)
+{
+ size_t maxOutputLen = ZSTD_compressBound(inputLen);
+ size_t sz = ZSTD_compress(outputV, maxOutputLen, inputV, inputLen, config.compressionLevel);
+ assert( ! ZSTD_isError(sz) );
+ outputLenV = sz;
+ return ! ZSTD_isError(sz);
+
+}
+
+bool
+ZStdCompressor::unprocess(const void * inputV, size_t inputLen, void * outputV, size_t & outputLenV)
+{
+ size_t sz = ZSTD_decompress(outputV, outputLenV, inputV, inputLen);
+ assert( ! ZSTD_isError(sz) );
+ outputLenV = sz;
+ return ! ZSTD_isError(sz);
+}
+
+}
diff --git a/document/src/vespa/document/util/zstdcompressor.h b/document/src/vespa/document/util/zstdcompressor.h
new file mode 100644
index 00000000000..5c52c144651
--- /dev/null
+++ b/document/src/vespa/document/util/zstdcompressor.h
@@ -0,0 +1,17 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#pragma once
+
+#include "compressor.h"
+
+namespace document {
+
+class ZStdCompressor : public ICompressor
+{
+public:
+ bool process(const CompressionConfig& config, const void * input, size_t inputLen, void * output, size_t & outputLen) override;
+ bool unprocess(const void * input, size_t inputLen, void * output, size_t & outputLen) override;
+ size_t adjustProcessLen(uint16_t options, size_t len) const override;
+};
+
+}
+
diff --git a/documentgen-test/pom.xml b/documentgen-test/pom.xml
index 972cc8633f7..793aed44a74 100644
--- a/documentgen-test/pom.xml
+++ b/documentgen-test/pom.xml
@@ -75,7 +75,6 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
- <version>2.3.1</version>
<configuration>
<updateReleaseInfo>true</updateReleaseInfo>
</configuration>
diff --git a/fastlib/src/vespa/fastlib/testsuite/cpptest.el b/fastlib/src/vespa/fastlib/testsuite/cpptest.el
index 6a1e1da09b0..d0a4f5c839a 100644
--- a/fastlib/src/vespa/fastlib/testsuite/cpptest.el
+++ b/fastlib/src/vespa/fastlib/testsuite/cpptest.el
@@ -2,7 +2,7 @@
;; $Revision: 1.179 $ $Date: 2004-02-17 17:01:15 $
-;; Author: Nils Sandøy <nils.sandoy@fast.no>
+;; Author: Nils Sandøy <nils.sandoy@fast.no>
;; Keywords: C++, tools
;;
diff --git a/fastlib/src/vespa/fastlib/testsuite/testproject.el b/fastlib/src/vespa/fastlib/testsuite/testproject.el
index 6cdfe9929ec..0a7ed652378 100644
--- a/fastlib/src/vespa/fastlib/testsuite/testproject.el
+++ b/fastlib/src/vespa/fastlib/testsuite/testproject.el
@@ -6,7 +6,7 @@
;; the class(es) you want to test.
;; $Revision: 1.6 $ $Date: 2003-09-11 09:14:01 $
-;; Author: Nils Sandøy <nils.sandoy@fast.no>
+;; Author: Nils Sandøy <nils.sandoy@fast.no>
;; Just a message to show that this file is beeing read. Look for this
;; in the *Messages* buffer.
diff --git a/fastlib/src/vespa/fastlib/text/tests/wordfolderstest.h b/fastlib/src/vespa/fastlib/text/tests/wordfolderstest.h
index eb717ad489d..08b3e60a538 100644
--- a/fastlib/src/vespa/fastlib/text/tests/wordfolderstest.h
+++ b/fastlib/src/vespa/fastlib/text/tests/wordfolderstest.h
@@ -98,10 +98,12 @@ class WordFoldersTest : public Test
}
bool AccentRemovalTest() {
+ // Note last encoded characters encoded as octets to avoid interpreting following letters after xNN as part of the encoding of the character
+ // See http://en.cppreference.com/w/cpp/language/escape
auto freefunction = [] (char * ptr) { free(ptr); };
- auto input = std::unique_ptr<char, decltype(freefunction)>(Fast_UnicodeUtil::strdupLAT1("¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþpþ!"),
+ auto input = std::unique_ptr<char, decltype(freefunction)>(Fast_UnicodeUtil::strdupLAT1("\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\x70\xFE\x21"),
freefunction);
- auto yelloutput = std::unique_ptr<char, decltype(freefunction)>(Fast_UnicodeUtil::strdupLAT1("¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿AAAAAEAAAECEEEEIIIIDNOOOOOE×OEUUUUEYTHssaaaaaeaaaeceeeeiiiidnoooooe÷oeuuuueythpth!"),
+ auto yelloutput = std::unique_ptr<char, decltype(freefunction)>(Fast_UnicodeUtil::strdupLAT1("\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\277AAAAAEAAAECEEEEIIIIDNOOOOOE\327OEUUUUEYTHssaaaaaeaaaeceeeeiiiidnoooooe\367oeuuuueythpth!"),
freefunction);
Fast_NormalizeWordFolder wordfolder;
int len = wordfolder.FoldedSizeAsUTF8(input.get());
diff --git a/fastlib/src/vespa/fastlib/util/testproject.el b/fastlib/src/vespa/fastlib/util/testproject.el
index f10d9ebc108..3221370d475 100644
--- a/fastlib/src/vespa/fastlib/util/testproject.el
+++ b/fastlib/src/vespa/fastlib/util/testproject.el
@@ -2,7 +2,7 @@
;; Local configurations for the cpptest Emacs unit-test framework
-;; Author: Nils Sandøy <nils.sandoy@fast.no>
+;; Author: Nils Sandøy <nils.sandoy@fast.no>
(message "Setting local test configuration")
diff --git a/filedistribution/src/apps/filedistributor/.gitignore b/filedistribution/src/apps/filedistributor/.gitignore
index a41b1963b70..89aaa70637e 100644
--- a/filedistribution/src/apps/filedistributor/.gitignore
+++ b/filedistribution/src/apps/filedistributor/.gitignore
@@ -1,2 +1,2 @@
/filedistributor
-filedistributor-bin
+vespa-filedistributor-bin
diff --git a/filedistribution/src/apps/filedistributor/CMakeLists.txt b/filedistribution/src/apps/filedistributor/CMakeLists.txt
index 1a7ef87bbac..42e47856208 100644
--- a/filedistribution/src/apps/filedistributor/CMakeLists.txt
+++ b/filedistribution/src/apps/filedistributor/CMakeLists.txt
@@ -2,7 +2,7 @@
vespa_add_executable(filedistribution_filedistributor_app
SOURCES
filedistributor.cpp
- OUTPUT_NAME filedistributor-bin
+ OUTPUT_NAME vespa-filedistributor-bin
INSTALL sbin
DEPENDS
filedistribution_distributor
diff --git a/filedistribution/src/apps/status/.gitignore b/filedistribution/src/apps/status/.gitignore
index 6dc1c1fff5d..2105a3c7051 100644
--- a/filedistribution/src/apps/status/.gitignore
+++ b/filedistribution/src/apps/status/.gitignore
@@ -1,2 +1,2 @@
-/status-filedistribution
+/vespa-status-filedistribution-bin
filedistribution_status-filedistribution_app
diff --git a/filedistribution/src/apps/status/CMakeLists.txt b/filedistribution/src/apps/status/CMakeLists.txt
index 63e9752496e..e46e0c58d86 100644
--- a/filedistribution/src/apps/status/CMakeLists.txt
+++ b/filedistribution/src/apps/status/CMakeLists.txt
@@ -3,7 +3,7 @@ vespa_add_executable(filedistribution_status-filedistribution_app
SOURCES
status-filedistribution.cpp
INSTALL bin
- OUTPUT_NAME status-filedistribution
+ OUTPUT_NAME vespa-status-filedistribution-bin
DEPENDS
filedistribution_filedistributionmodel
filedistribution_common
diff --git a/filedistribution/src/apps/status/vespa-status-filedistribution.sh b/filedistribution/src/apps/status/vespa-status-filedistribution.sh
index 104688a4883..1ba56d6c798 100644
--- a/filedistribution/src/apps/status/vespa-status-filedistribution.sh
+++ b/filedistribution/src/apps/status/vespa-status-filedistribution.sh
@@ -65,4 +65,4 @@ ROOT=${VESPA_HOME%/}
ZKSTRING=$($ROOT/libexec/vespa/vespa-config.pl -zkstring)
test -z "$VESPA_LOG_LEVEL" && VESPA_LOG_LEVEL=warning
export VESPA_LOG_LEVEL
-exec $ROOT/bin/status-filedistribution --zkstring "$ZKSTRING" $@
+exec $ROOT/bin/vespa-status-filedistribution-bin --zkstring "$ZKSTRING" $@
diff --git a/filedistributionmanager/src/main/java/com/yahoo/vespa/filedistribution/FileDistributionManager.java b/filedistributionmanager/src/main/java/com/yahoo/vespa/filedistribution/FileDistributionManager.java
index 64cdd9da416..afbc879e40f 100644
--- a/filedistributionmanager/src/main/java/com/yahoo/vespa/filedistribution/FileDistributionManager.java
+++ b/filedistributionmanager/src/main/java/com/yahoo/vespa/filedistribution/FileDistributionManager.java
@@ -110,7 +110,12 @@ public class FileDistributionManager {
public void reloadDeployFileDistributor() {
try (LockGuard guard = new LockGuard(lock)) {
- Runtime.getRuntime().exec("pkill -SIGUSR1 -x filedistributor");
+ /*
+ * Try sending signal to vespa-filedistributor and
+ * filedistributor processes. Note 15 char limit for process
+ * name on Linux, see pkill manual page for details.
+ */
+ Runtime.getRuntime().exec("pkill -SIGUSR1 ^(vespa-filedistr|filedistributor)$");
} catch (IOException e) {
throw new RuntimeException("Failed to reinitialize the filedistributor", e);
}
diff --git a/install_java.cmake b/install_java.cmake
index 450bbdd9b5e..c4a7ab3d99e 100644
--- a/install_java.cmake
+++ b/install_java.cmake
@@ -50,30 +50,32 @@ install_fat_java_artifact(vespaclient-java)
install_fat_java_artifact(zkfacade)
vespa_install_script(application-preprocessor/src/main/sh/vespa-preprocess-application bin)
-vespa_install_script(jdisc_core/src/main/perl/jdisc_logfmt bin)
-vespa_install_script(config-proxy/src/main/sh/config-ctl bin)
+vespa_install_script(jdisc_core/src/main/perl/vespa-jdisc-logfmt bin)
+vespa_install_script(config-proxy/src/main/sh/vespa-config-ctl bin)
+vespa_install_script(config-proxy/src/main/sh/vespa-config-loadtester bin)
+vespa_install_script(config-proxy/src/main/sh/vespa-config-verification bin)
vespa_install_script(config-model/src/main/perl/vespa-deploy bin)
vespa_install_script(config-model/src/main/perl/vespa-deploy-application bin)
vespa_install_script(config-model/src/main/perl/vespa-expand-config.pl bin)
vespa_install_script(config-model/src/main/perl/vespa-replicate-log-stream bin)
vespa_install_script(config-model/src/main/sh/vespa-validate-application bin)
vespa_install_script(container-disc/src/main/sh/vespa-start-container-daemon.sh vespa-start-container-daemon bin)
-vespa_install_script(vespaclient-java/src/main/sh/vds-document-statistics.sh vds-document-statistics bin)
-vespa_install_script(vespaclient-java/src/main/sh/vdsstat.sh vdsstat bin)
+vespa_install_script(vespaclient-java/src/main/sh/vespa-document-statistics.sh vespa-document-statistics bin)
+vespa_install_script(vespaclient-java/src/main/sh/vespa-stat.sh vespa-stat bin)
vespa_install_script(vespaclient-java/src/main/sh/vespa-query-profile-dump-tool.sh vespa-query-profile-dump-tool bin)
vespa_install_script(vespaclient-java/src/main/sh/vespa-summary-benchmark.sh vespa-summary-benchmark bin)
-vespa_install_script(vespaclient-java/src/main/sh/vespadestination.sh vespadestination bin)
-vespa_install_script(vespaclient-java/src/main/sh/vespafeeder.sh vespafeeder bin)
-vespa_install_script(vespaclient-java/src/main/sh/vespaget.sh vespaget bin)
-vespa_install_script(vespaclient-java/src/main/sh/vespavisit.sh vespavisit bin)
-vespa_install_script(vespaclient-java/src/main/sh/vespavisittarget.sh vespavisittarget bin)
+vespa_install_script(vespaclient-java/src/main/sh/vespa-destination.sh vespa-destination bin)
+vespa_install_script(vespaclient-java/src/main/sh/vespa-feeder.sh vespa-feeder bin)
+vespa_install_script(vespaclient-java/src/main/sh/vespa-get.sh vespa-get bin)
+vespa_install_script(vespaclient-java/src/main/sh/vespa-visit.sh vespa-visit bin)
+vespa_install_script(vespaclient-java/src/main/sh/vespa-visit-target.sh vespa-visit-target bin)
-vespa_install_script(logserver/bin/logserver-start.sh logserver-start bin)
+vespa_install_script(logserver/bin/logserver-start.sh vespa-logserver-start bin)
install(DIRECTORY config-model/src/main/resources/schema DESTINATION share/vespa PATTERN ".gitignore" EXCLUDE)
install(DIRECTORY config-model/src/main/resources/schema DESTINATION share/vespa/schema/version/6.x PATTERN ".gitignore" EXCLUDE)
-install(FILES jdisc_core/src/main/perl/jdisc_logfmt.1 DESTINATION man/man1)
+install(FILES jdisc_core/src/main/perl/vespa-jdisc-logfmt.1 DESTINATION man/man1)
install(FILES
config-model-fat/src/main/resources/config-models.xml
diff --git a/jdisc_core/pom.xml b/jdisc_core/pom.xml
index b289d5816cd..3206e70ad34 100644
--- a/jdisc_core/pom.xml
+++ b/jdisc_core/pom.xml
@@ -295,9 +295,9 @@
<goal>exec</goal>
</goals>
<configuration>
- <executable>${project.basedir}/src/test/perl/jdisc_logfmt_test.sh</executable>
+ <executable>${project.basedir}/src/test/perl/vespa-jdisc-logfmt-test.sh</executable>
<arguments>
- <argument>${project.basedir}/src/main/perl/jdisc_logfmt</argument>
+ <argument>${project.basedir}/src/main/perl/vespa-jdisc-logfmt</argument>
</arguments>
</configuration>
</execution>
diff --git a/jdisc_core/src/main/java/com/yahoo/jdisc/core/ActiveContainer.java b/jdisc_core/src/main/java/com/yahoo/jdisc/core/ActiveContainer.java
index fbc45f000d2..27ce25affef 100644
--- a/jdisc_core/src/main/java/com/yahoo/jdisc/core/ActiveContainer.java
+++ b/jdisc_core/src/main/java/com/yahoo/jdisc/core/ActiveContainer.java
@@ -17,6 +17,7 @@ import com.yahoo.jdisc.service.ServerProvider;
import java.net.URI;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* @author <a href="mailto:simon@yahoo-inc.com">Simon Thoresen</a>
@@ -31,6 +32,7 @@ public class ActiveContainer extends AbstractResource implements CurrentContaine
private final Map<String, BindingSet<RequestHandler>> clientBindings;
private final BindingSetSelector bindingSetSelector;
private final TimeoutManagerImpl timeoutMgr;
+ final Destructor destructor;
public ActiveContainer(ContainerBuilder builder) {
serverProviders = builder.serverProviders().activate();
@@ -55,13 +57,16 @@ public class ActiveContainer extends AbstractResource implements CurrentContaine
});
guiceInjector = builder.guiceModules().activate();
termination = new ContainerTermination(builder.appContext());
+ destructor = new Destructor(resourceReferences, timeoutMgr, termination);
}
@Override
protected void destroy() {
- resourceReferences.release();
- timeoutMgr.shutdown();
- termination.run();
+ boolean alreadyDestructed = destructor.destruct();
+ if (alreadyDestructed) {
+ throw new IllegalStateException(
+ "Already destructed! This should not occur unless destroy have been called directly!");
+ }
}
/**
@@ -116,4 +121,30 @@ public class ActiveContainer extends AbstractResource implements CurrentContaine
}
return new ContainerSnapshot(this, serverBindings, clientBindings);
}
+
+ // NOTE: An instance of this class must never contain a reference to the outer class (ActiveContainer).
+ static class Destructor {
+ private final ResourcePool resourceReferences;
+ private final TimeoutManagerImpl timeoutMgr;
+ private final ContainerTermination termination;
+ private final AtomicBoolean done = new AtomicBoolean();
+
+ private Destructor(ResourcePool resourceReferences,
+ TimeoutManagerImpl timeoutMgr,
+ ContainerTermination termination) {
+ this.resourceReferences = resourceReferences;
+ this.timeoutMgr = timeoutMgr;
+ this.termination = termination;
+ }
+
+ boolean destruct() {
+ boolean alreadyDestructed = this.done.getAndSet(true);
+ if (!alreadyDestructed) {
+ resourceReferences.release();
+ timeoutMgr.shutdown();
+ termination.run();
+ }
+ return alreadyDestructed;
+ }
+ }
}
diff --git a/jdisc_core/src/main/java/com/yahoo/jdisc/core/ActiveContainerDeactivationWatchdog.java b/jdisc_core/src/main/java/com/yahoo/jdisc/core/ActiveContainerDeactivationWatchdog.java
index 0004d1d818b..90c410d5e22 100644
--- a/jdisc_core/src/main/java/com/yahoo/jdisc/core/ActiveContainerDeactivationWatchdog.java
+++ b/jdisc_core/src/main/java/com/yahoo/jdisc/core/ActiveContainerDeactivationWatchdog.java
@@ -5,10 +5,14 @@ import com.google.inject.Inject;
import com.yahoo.jdisc.Metric;
import com.yahoo.jdisc.statistics.ActiveContainerMetrics;
+import java.lang.ref.PhantomReference;
+import java.lang.ref.ReferenceQueue;
import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
@@ -29,11 +33,16 @@ class ActiveContainerDeactivationWatchdog implements ActiveContainerMetrics, Aut
static final Duration WATCHDOG_FREQUENCY = Duration.ofMinutes(20);
static final Duration ACTIVE_CONTAINER_GRACE_PERIOD = Duration.ofHours(1);
static final Duration GC_TRIGGER_FREQUENCY = ACTIVE_CONTAINER_GRACE_PERIOD.minusMinutes(5);
+ static final Duration ENFORCE_DESTRUCTION_GCED_CONTAINERS_FREQUENCY = Duration.ofMinutes(5);
private static final Logger log = Logger.getLogger(ActiveContainerDeactivationWatchdog.class.getName());
private final Object monitor = new Object();
private final WeakHashMap<ActiveContainer, LifecycleStats> deactivatedContainers = new WeakHashMap<>();
+ private final ReferenceQueue<ActiveContainer> garbageCollectedContainers = new ReferenceQueue<>();
+ @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
+ // Instances of the phantom references must be kept alive until they are polled from the reference queue
+ private final Set<ActiveContainerPhantomReference> destructorReferences = new HashSet<>();
private final ScheduledExecutorService scheduler;
private final Clock clock;
@@ -44,7 +53,7 @@ class ActiveContainerDeactivationWatchdog implements ActiveContainerMetrics, Aut
ActiveContainerDeactivationWatchdog() {
this(
Clock.systemUTC(),
- new ScheduledThreadPoolExecutor(2, runnable -> {
+ new ScheduledThreadPoolExecutor(3, runnable -> {
Thread thread = new Thread(runnable, "active-container-deactivation-watchdog");
thread.setDaemon(true);
return thread;
@@ -54,26 +63,30 @@ class ActiveContainerDeactivationWatchdog implements ActiveContainerMetrics, Aut
ActiveContainerDeactivationWatchdog(Clock clock, ScheduledExecutorService scheduler) {
this.clock = clock;
this.scheduler = scheduler;
- this.scheduler.scheduleAtFixedRate(
- this::warnOnStaleContainers,
- WATCHDOG_FREQUENCY.getSeconds(),
- WATCHDOG_FREQUENCY.getSeconds(),
- TimeUnit.SECONDS);
- this.scheduler.scheduleAtFixedRate(
- System::gc,
- GC_TRIGGER_FREQUENCY.getSeconds(),
- GC_TRIGGER_FREQUENCY.getSeconds(),
- TimeUnit.SECONDS);
+ this.scheduler.scheduleAtFixedRate(this::warnOnStaleContainers,
+ WATCHDOG_FREQUENCY.getSeconds(),
+ WATCHDOG_FREQUENCY.getSeconds(),
+ TimeUnit.SECONDS);
+ this.scheduler.scheduleAtFixedRate(System::gc,
+ GC_TRIGGER_FREQUENCY.getSeconds(),
+ GC_TRIGGER_FREQUENCY.getSeconds(),
+ TimeUnit.SECONDS);
+ this.scheduler.scheduleAtFixedRate(this::enforceDestructionOfGarbageCollectedContainers,
+ ENFORCE_DESTRUCTION_GCED_CONTAINERS_FREQUENCY.getSeconds(),
+ ENFORCE_DESTRUCTION_GCED_CONTAINERS_FREQUENCY.getSeconds(),
+ TimeUnit.SECONDS);
}
void onContainerActivation(ActiveContainer nextContainer) {
synchronized (monitor) {
Instant now = clock.instant();
- if (currentContainer != null) {
- deactivatedContainers.put(currentContainer, new LifecycleStats(currentContainerActivationTime, now));
- }
+ ActiveContainer previousContainer = currentContainer;
currentContainer = nextContainer;
currentContainerActivationTime = now;
+ if (previousContainer != null) {
+ deactivatedContainers.put(previousContainer, new LifecycleStats(currentContainerActivationTime, now));
+ destructorReferences.add(new ActiveContainerPhantomReference(previousContainer, garbageCollectedContainers));
+ }
}
}
@@ -92,6 +105,7 @@ class ActiveContainerDeactivationWatchdog implements ActiveContainerMetrics, Aut
synchronized (monitor) {
scheduler.shutdown();
deactivatedContainers.clear();
+ destructorReferences.clear();
currentContainer = null;
currentContainerActivationTime = null;
}
@@ -107,6 +121,20 @@ class ActiveContainerDeactivationWatchdog implements ActiveContainerMetrics, Aut
}
}
+ private void enforceDestructionOfGarbageCollectedContainers() {
+ ActiveContainerPhantomReference reference;
+ while ((reference = (ActiveContainerPhantomReference) garbageCollectedContainers.poll()) != null) {
+ try {
+ reference.enforceDestruction();
+ } catch (Throwable t) {
+ log.log(Level.SEVERE, "Failed to do post-GC destruction of " + reference.containerName, t);
+ } finally {
+ destructorReferences.remove(reference);
+ reference.clear();
+ }
+ }
+ }
+
private List<DeactivatedContainer> getDeactivatedContainersSnapshot() {
Instant now = clock.instant();
synchronized (monitor) {
@@ -157,4 +185,23 @@ class ActiveContainerDeactivationWatchdog implements ActiveContainerMetrics, Aut
}
}
+ private static class ActiveContainerPhantomReference extends PhantomReference<ActiveContainer> {
+ public final String containerName;
+ private final ActiveContainer.Destructor destructor;
+
+ public ActiveContainerPhantomReference(ActiveContainer activeContainer,
+ ReferenceQueue<? super ActiveContainer> q) {
+ super(activeContainer, q);
+ this.containerName = activeContainer.toString();
+ this.destructor = activeContainer.destructor;
+ }
+
+ public void enforceDestruction() {
+ boolean alreadyCompleted = destructor.destruct();
+ if (!alreadyCompleted) {
+ log.severe(containerName + " was not correctly cleaned up " +
+ "because of a resource leak or invalid use of reference counting.");
+ }
+ }
+ }
}
diff --git a/jdisc_core/src/main/perl/jdisc_logfmt b/jdisc_core/src/main/perl/vespa-jdisc-logfmt
index 11a21cbe01a..11a21cbe01a 100755
--- a/jdisc_core/src/main/perl/jdisc_logfmt
+++ b/jdisc_core/src/main/perl/vespa-jdisc-logfmt
diff --git a/jdisc_core/src/main/perl/jdisc_logfmt.1 b/jdisc_core/src/main/perl/vespa-jdisc-logfmt.1
index 0a884c0ec85..c79ee2165f2 100644
--- a/jdisc_core/src/main/perl/jdisc_logfmt.1
+++ b/jdisc_core/src/main/perl/vespa-jdisc-logfmt.1
@@ -1,11 +1,11 @@
.\" $Id: logfmt.1,v 1.12 2007-06-19 09:37:25 daljord Exp $
.\"
.Dd October 29, 2004
-.Dt LOGFMT \&1 "JDisc documentation"
+.Dt VESPA-JDISC-LOGFMT \&1 "JDisc documentation"
.Os "Yahoo! JDisc" "2.3"
.Os
.Sh NAME
-.Nm logfmt
+.Nm vespa-jdisc-logfmt
.Nd select and format messages from JDisc log files
.Sh SYNOPSIS
.Nm
@@ -73,7 +73,7 @@ is shown.
Print the time in human-readable [YYYY-MM-DD HH:mm:ss] format.
Note that the time is printed in the local timezone; to get GMT
output use
-.Nm "\*[q]env TZ=GMT logfmt\*[q]"
+.Nm "\*[q]env TZ=GMT vespa-jdisc-logfmt\*[q]"
as your command.
.It msecs
Add milliseconds after the seconds in
@@ -151,7 +151,7 @@ truncating if necessary.
The command:
.Pp
.Bd -literal -offset indent
-logfmt -l event -s service,message,fmttime,message
+vespa-jdisc-logfmt -l event -s service,message,fmttime,message
.Ed
.Pp
will display only messages with log level "event",
@@ -175,7 +175,7 @@ order is.
The command:
.Pp
.Bd -literal -offset indent
-logfmt -l all-info,-debug -s level \e
+vespa-jdisc-logfmt -l all-info,-debug -s level \e
-s time,usecs,component,message -t -l -event
.Ed
.Pp
diff --git a/jdisc_core/src/test/java/com/yahoo/jdisc/core/ActiveContainerDeactivationWatchdogTest.java b/jdisc_core/src/test/java/com/yahoo/jdisc/core/ActiveContainerDeactivationWatchdogTest.java
index 1a776f59e29..8d0f09cf5f8 100644
--- a/jdisc_core/src/test/java/com/yahoo/jdisc/core/ActiveContainerDeactivationWatchdogTest.java
+++ b/jdisc_core/src/test/java/com/yahoo/jdisc/core/ActiveContainerDeactivationWatchdogTest.java
@@ -5,14 +5,22 @@ import com.yahoo.jdisc.ResourceReference;
import com.yahoo.jdisc.statistics.ActiveContainerMetrics;
import com.yahoo.jdisc.test.TestDriver;
import com.yahoo.test.ManualClock;
+import org.junit.Ignore;
import org.junit.Test;
+import java.lang.ref.WeakReference;
import java.time.Duration;
import java.time.Instant;
import java.util.Map;
import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
/**
* @author bjorncs
@@ -59,6 +67,32 @@ public class ActiveContainerDeactivationWatchdogTest {
}
+ @Test
+ @Ignore("JVM does not give any guarantee when phantom references will be enqueued to reference queues")
+ public void deactivated_container_destructed_if_its_reference_counter_is_nonzero() {
+ ExecutorMock executor = new ExecutorMock();
+ ActiveContainerDeactivationWatchdog watchdog =
+ new ActiveContainerDeactivationWatchdog(new ManualClock(), executor);
+ ActiveContainer container =
+ new ActiveContainer(TestDriver.newSimpleApplicationInstanceWithoutOsgi().newContainerBuilder());
+ AtomicBoolean destructed = new AtomicBoolean(false);
+ container.shutdown().notifyTermination(() -> destructed.set(true));
+
+ container.refer(); // increase reference counter to simluate a leaking resource
+ watchdog.onContainerActivation(container);
+ container.release(); // release resource
+ watchdog.onContainerActivation(null); // deactive container
+
+ WeakReference<ActiveContainer> containerWeakReference = new WeakReference<>(container);
+ container = null; // make container instance collectable by GC
+ System.gc();
+
+ assertNull("Container is not GCed - probably because the watchdog has a concrete reference to it",
+ containerWeakReference.get());
+ executor.containerDestructorCommand.run();
+ assertTrue("Destructor is not called on deactivated container", destructed.get());
+ }
+
private static class MockMetric implements Metric {
public int totalCount;
public int withRetainedReferencesCount;
@@ -88,4 +122,25 @@ public class ActiveContainerDeactivationWatchdogTest {
}
}
+ private static class ExecutorMock extends ScheduledThreadPoolExecutor {
+
+ public Runnable containerDestructorCommand;
+ private int registrationCounter = 0;
+
+ public ExecutorMock() {
+ super(1);
+ }
+
+ @Override
+ public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
+ if (registrationCounter == 2) {
+ containerDestructorCommand = command;
+ } else if (registrationCounter > 2){
+ throw new IllegalStateException("Unexpected registration");
+ }
+ ++registrationCounter;
+ return null;
+ }
+ }
+
}
diff --git a/jdisc_core/src/test/perl/help.Levent.expected b/jdisc_core/src/test/perl/help.Levent.expected
index b35e2d9c36b..1f7c17cd81c 100644
--- a/jdisc_core/src/test/perl/help.Levent.expected
+++ b/jdisc_core/src/test/perl/help.Levent.expected
@@ -1,4 +1,4 @@
-Usage: jdisc_logfmt [options] [inputfile ...]
+Usage: vespa-jdisc-logfmt [options] [inputfile ...]
Options:
-l LEVELLIST --level=LEVELLIST select levels to include
-L LEVELLIST --add-level=LEVELLIST define extra levels
diff --git a/jdisc_core/src/test/perl/help.expected b/jdisc_core/src/test/perl/help.expected
index 58da8183696..cadddb4cf63 100644
--- a/jdisc_core/src/test/perl/help.expected
+++ b/jdisc_core/src/test/perl/help.expected
@@ -1,4 +1,4 @@
-Usage: jdisc_logfmt [options] [inputfile ...]
+Usage: vespa-jdisc-logfmt [options] [inputfile ...]
Options:
-l LEVELLIST --level=LEVELLIST select levels to include
-L LEVELLIST --add-level=LEVELLIST define extra levels
diff --git a/jdisc_core/src/test/perl/jdisc_logfmt_test.sh b/jdisc_core/src/test/perl/vespa-jdisc-logfmt-test.sh
index 0166d33d8ab..106db534ee3 100755
--- a/jdisc_core/src/test/perl/jdisc_logfmt_test.sh
+++ b/jdisc_core/src/test/perl/vespa-jdisc-logfmt-test.sh
@@ -5,9 +5,9 @@ DIFF=/usr/bin/diff
LOGFMT=${1}
if which perl &> /dev/null; then
- echo "Running jdisc_logfmt test suite."
+ echo "Running vespa-jdisc-logfmt test suite."
else
- echo "Ignoring jdisc_logfmt test suite as there is no perl executable."
+ echo "Ignoring vespa-jdisc-logfmt test suite as there is no perl executable."
exit 0
fi
diff --git a/jdisc_http_service/docs/class-diagram.graffle b/jdisc_http_service/docs/class-diagram.graffle
deleted file mode 100644
index 938459c6571..00000000000
--- a/jdisc_http_service/docs/class-diagram.graffle
+++ /dev/null
@@ -1,1856 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>ActiveLayerIndex</key>
- <integer>0</integer>
- <key>ApplicationVersion</key>
- <array>
- <string>com.omnigroup.OmniGrafflePro</string>
- <string>139.7.0.167456</string>
- </array>
- <key>AutoAdjust</key>
- <true/>
- <key>BackgroundGraphic</key>
- <dict>
- <key>Bounds</key>
- <string>{{0, 0}, {558.99999713897705, 783}}</string>
- <key>Class</key>
- <string>SolidGraphic</string>
- <key>ID</key>
- <integer>2</integer>
- <key>Style</key>
- <dict>
- <key>shadow</key>
- <dict>
- <key>Draws</key>
- <string>NO</string>
- </dict>
- <key>stroke</key>
- <dict>
- <key>Draws</key>
- <string>NO</string>
- </dict>
- </dict>
- </dict>
- <key>BaseZoom</key>
- <integer>0</integer>
- <key>CanvasOrigin</key>
- <string>{0, 0}</string>
- <key>ColumnAlign</key>
- <integer>1</integer>
- <key>ColumnSpacing</key>
- <real>36</real>
- <key>CreationDate</key>
- <string>2012-06-18 12:41:37 +0000</string>
- <key>Creator</key>
- <string>Einar Rosenvinge</string>
- <key>DisplayScale</key>
- <string>1.000 cm = 1.000 cm</string>
- <key>GraphDocumentVersion</key>
- <integer>8</integer>
- <key>GraphicsList</key>
- <array>
- <dict>
- <key>Bounds</key>
- <string>{{404.66666889190674, 39.999999999999936}, {151.17318725585938, 14}}</string>
- <key>Class</key>
- <string>ShapedGraphic</string>
- <key>ID</key>
- <integer>114</integer>
- <key>Magnets</key>
- <array>
- <string>{0, 1}</string>
- <string>{0, -1}</string>
- <string>{1, 0}</string>
- <string>{-1, 0}</string>
- </array>
- <key>Shape</key>
- <string>Rectangle</string>
- <key>Style</key>
- <dict>
- <key>stroke</key>
- <dict>
- <key>Color</key>
- <dict>
- <key>b</key>
- <string>0</string>
- <key>g</key>
- <string>1</string>
- <key>r</key>
- <string>0</string>
- </dict>
- </dict>
- </dict>
- <key>Text</key>
- <dict>
- <key>Text</key>
- <string>{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
-
-\f0\b\fs24 \cf0 J2SE API}</string>
- <key>VerticalPad</key>
- <integer>0</integer>
- </dict>
- </dict>
- <dict>
- <key>Class</key>
- <string>TableGroup</string>
- <key>Graphics</key>
- <array>
- <dict>
- <key>Bounds</key>
- <string>{{404.66666889190674, 18.66666666666665}, {151.17318725585938, 14}}</string>
- <key>Class</key>
- <string>ShapedGraphic</string>
- <key>FitText</key>
- <string>Vertical</string>
- <key>Flow</key>
- <string>Resize</string>
- <key>ID</key>
- <integer>109</integer>
- <key>Shape</key>
- <string>Rectangle</string>
- <key>Style</key>
- <dict>
- <key>fill</key>
- <dict>
- <key>GradientCenter</key>
- <string>{-0.29411799999999999, -0.264706}</string>
- </dict>
- <key>stroke</key>
- <dict>
- <key>Color</key>
- <dict>
- <key>b</key>
- <string>0</string>
- <key>g</key>
- <string>0</string>
- <key>r</key>
- <string>1</string>
- </dict>
- </dict>
- </dict>
- <key>Text</key>
- <dict>
- <key>Text</key>
- <string>{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
-
-\f0\b\fs24 \cf0 Netty API}</string>
- <key>VerticalPad</key>
- <integer>0</integer>
- </dict>
- <key>TextPlacement</key>
- <integer>0</integer>
- </dict>
- </array>
- <key>ID</key>
- <integer>108</integer>
- </dict>
- <dict>
- <key>Bounds</key>
- <string>{{404.66666666666731, 7.9472862957175039e-08}, {151.17318725585938, 14}}</string>
- <key>Class</key>
- <string>ShapedGraphic</string>
- <key>ID</key>
- <integer>107</integer>
- <key>Magnets</key>
- <array>
- <string>{0, 1}</string>
- <string>{0, -1}</string>
- <string>{1, 0}</string>
- <string>{-1, 0}</string>
- </array>
- <key>Shape</key>
- <string>Rectangle</string>
- <key>Style</key>
- <dict>
- <key>stroke</key>
- <dict>
- <key>Color</key>
- <dict>
- <key>b</key>
- <string>1</string>
- <key>g</key>
- <string>0</string>
- <key>r</key>
- <string>0</string>
- </dict>
- </dict>
- </dict>
- <key>Text</key>
- <dict>
- <key>Text</key>
- <string>{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
-
-\f0\b\fs24 \cf0 jDISC core API}</string>
- <key>VerticalPad</key>
- <integer>0</integer>
- </dict>
- </dict>
- <dict>
- <key>Bounds</key>
- <string>{{328.46341597965198, 296.25884156306495}, {29.333332061767578, 14}}</string>
- <key>Class</key>
- <string>ShapedGraphic</string>
- <key>FitText</key>
- <string>Vertical</string>
- <key>Flow</key>
- <string>Resize</string>
- <key>ID</key>
- <integer>106</integer>
- <key>Line</key>
- <dict>
- <key>ID</key>
- <integer>105</integer>
- <key>Offset</key>
- <real>6.6666665077209473</real>
- <key>Position</key>
- <real>0.91559326648712158</real>
- <key>RotationType</key>
- <integer>0</integer>
- </dict>
- <key>Shape</key>
- <string>Rectangle</string>
- <key>Style</key>
- <dict>
- <key>fill</key>
- <dict>
- <key>Draws</key>
- <string>NO</string>
- </dict>
- <key>shadow</key>
- <dict>
- <key>Draws</key>
- <string>NO</string>
- </dict>
- <key>stroke</key>
- <dict>
- <key>Draws</key>
- <string>NO</string>
- </dict>
- </dict>
- <key>Text</key>
- <dict>
- <key>Align</key>
- <integer>0</integer>
- <key>Text</key>
- <string>{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
-
-\f0\fs24 \cf0 1}</string>
- <key>VerticalPad</key>
- <integer>0</integer>
- </dict>
- </dict>
- <dict>
- <key>Class</key>
- <string>LineGraphic</string>
- <key>Head</key>
- <dict>
- <key>ID</key>
- <integer>52</integer>
- </dict>
- <key>ID</key>
- <integer>105</integer>
- <key>Points</key>
- <array>
- <string>{225.55682373046864, 284.810302734375}</string>
- <string>{352.43905966196957, 312.07829430296113}</string>
- </array>
- <key>Style</key>
- <dict>
- <key>stroke</key>
- <dict>
- <key>HeadArrow</key>
- <string>StickArrow</string>
- <key>Legacy</key>
- <true/>
- <key>LineType</key>
- <integer>1</integer>
- <key>TailArrow</key>
- <string>0</string>
- </dict>
- </dict>
- <key>Tail</key>
- <dict>
- <key>ID</key>
- <integer>104</integer>
- </dict>
- </dict>
- <dict>
- <key>Bounds</key>
- <string>{{101.99999999999997, 277.810302734375}, {123.55682373046864, 14}}</string>
- <key>Class</key>
- <string>ShapedGraphic</string>
- <key>ID</key>
- <integer>104</integer>
- <key>Magnets</key>
- <array>
- <string>{0, 1}</string>
- <string>{0, -1}</string>
- <string>{1, 0}</string>
- <string>{-1, 0}</string>
- </array>
- <key>Shape</key>
- <string>Rectangle</string>
- <key>Style</key>
- <dict>
- <key>stroke</key>
- <dict>
- <key>Color</key>
- <dict>
- <key>b</key>
- <string>0</string>
- <key>g</key>
- <string>0</string>
- <key>r</key>
- <string>1</string>
- </dict>
- </dict>
- </dict>
- <key>Text</key>
- <dict>
- <key>Text</key>
- <string>{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
-
-\f0\b\fs24 \cf0 ChannelPipeline}</string>
- <key>VerticalPad</key>
- <integer>0</integer>
- </dict>
- </dict>
- <dict>
- <key>Bounds</key>
- <string>{{166.25436339285309, 474.88842165638926}, {29.333332061767578, 14}}</string>
- <key>Class</key>
- <string>ShapedGraphic</string>
- <key>FitText</key>
- <string>Vertical</string>
- <key>Flow</key>
- <string>Resize</string>
- <key>ID</key>
- <integer>103</integer>
- <key>Line</key>
- <dict>
- <key>ID</key>
- <integer>102</integer>
- <key>Offset</key>
- <real>6.6666665077209473</real>
- <key>Position</key>
- <real>0.78203368186950684</real>
- <key>RotationType</key>
- <integer>0</integer>
- </dict>
- <key>Shape</key>
- <string>Rectangle</string>
- <key>Style</key>
- <dict>
- <key>fill</key>
- <dict>
- <key>Draws</key>
- <string>NO</string>
- </dict>
- <key>shadow</key>
- <dict>
- <key>Draws</key>
- <string>NO</string>
- </dict>
- <key>stroke</key>
- <dict>
- <key>Draws</key>
- <string>NO</string>
- </dict>
- </dict>
- <key>Text</key>
- <dict>
- <key>Align</key>
- <integer>0</integer>
- <key>Text</key>
- <string>{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
-
-\f0\fs24 \cf0 1}</string>
- <key>VerticalPad</key>
- <integer>0</integer>
- </dict>
- </dict>
- <dict>
- <key>Class</key>
- <string>LineGraphic</string>
- <key>Head</key>
- <dict>
- <key>ID</key>
- <integer>89</integer>
- </dict>
- <key>ID</key>
- <integer>102</integer>
- <key>Points</key>
- <array>
- <string>{291.52424638132226, 513.75253787937902}</string>
- <string>{148.21246360738095, 481.32189037141075}</string>
- </array>
- <key>Style</key>
- <dict>
- <key>stroke</key>
- <dict>
- <key>HeadArrow</key>
- <string>StickArrow</string>
- <key>Legacy</key>
- <true/>
- <key>LineType</key>
- <integer>1</integer>
- <key>TailArrow</key>
- <string>0</string>
- </dict>
- </dict>
- <key>Tail</key>
- <dict>
- <key>ID</key>
- <integer>58</integer>
- </dict>
- </dict>
- <dict>
- <key>Class</key>
- <string>LineGraphic</string>
- <key>Head</key>
- <dict>
- <key>ID</key>
- <integer>95</integer>
- </dict>
- <key>ID</key>
- <integer>96</integer>
- <key>Points</key>
- <array>
- <string>{116.77841269969511, 466.71157835576878}</string>
- <string>{116.77840998702608, 420.16666668003933}</string>
- </array>
- <key>Style</key>
- <dict>
- <key>stroke</key>
- <dict>
- <key>HeadArrow</key>
- <string>Arrow</string>
- <key>Legacy</key>
- <true/>
- <key>LineType</key>
- <integer>1</integer>
- <key>TailArrow</key>
- <string>0</string>
- </dict>
- </dict>
- <key>Tail</key>
- <dict>
- <key>ID</key>
- <integer>89</integer>
- </dict>
- </dict>
- <dict>
- <key>Bounds</key>
- <string>{{58.945077896118171, 405.66666666666708}, {115.66666412353516, 14}}</string>
- <key>Class</key>
- <string>ShapedGraphic</string>
- <key>ID</key>
- <integer>95</integer>
- <key>Magnets</key>
- <array>
- <string>{0, 1}</string>
- <string>{0, -1}</string>
- <string>{1, 0}</string>
- <string>{-1, 0}</string>
- </array>
- <key>Shape</key>
- <string>Rectangle</string>
- <key>Style</key>
- <dict>
- <key>stroke</key>
- <dict>
- <key>Color</key>
- <dict>
- <key>b</key>
- <string>1</string>
- <key>g</key>
- <string>0</string>
- <key>r</key>
- <string>0</string>
- </dict>
- </dict>
- </dict>
- <key>Text</key>
- <dict>
- <key>Text</key>
- <string>{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
-
-\f0\b\fs24 \cf0 Request}</string>
- <key>VerticalPad</key>
- <integer>0</integer>
- </dict>
- </dict>
- <dict>
- <key>Class</key>
- <string>TableGroup</string>
- <key>Graphics</key>
- <array>
- <dict>
- <key>Bounds</key>
- <string>{{68.3333333333334, 467.21157836914102}, {96.890159606933594, 14}}</string>
- <key>Class</key>
- <string>ShapedGraphic</string>
- <key>FitText</key>
- <string>Vertical</string>
- <key>Flow</key>
- <string>Resize</string>
- <key>ID</key>
- <integer>89</integer>
- <key>Shape</key>
- <string>Rectangle</string>
- <key>Style</key>
- <dict>
- <key>fill</key>
- <dict>
- <key>GradientCenter</key>
- <string>{-0.29411799999999999, -0.264706}</string>
- </dict>
- </dict>
- <key>Text</key>
- <dict>
- <key>Text</key>
- <string>{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
-
-\f0\b\fs24 \cf0 HttpRequest}</string>
- <key>VerticalPad</key>
- <integer>0</integer>
- </dict>
- <key>TextPlacement</key>
- <integer>0</integer>
- </dict>
- </array>
- <key>ID</key>
- <integer>88</integer>
- </dict>
- <dict>
- <key>Class</key>
- <string>LineGraphic</string>
- <key>Head</key>
- <dict>
- <key>ID</key>
- <integer>86</integer>
- </dict>
- <key>ID</key>
- <integer>87</integer>
- <key>Points</key>
- <array>
- <string>{350.25724339020428, 513.73666184812191}</string>
- <string>{432.54926154576208, 492.26520134230651}</string>
- </array>
- <key>Style</key>
- <dict>
- <key>stroke</key>
- <dict>
- <key>HeadArrow</key>
- <string>Arrow</string>
- <key>Legacy</key>
- <true/>
- <key>Pattern</key>
- <integer>1</integer>
- <key>TailArrow</key>
- <string>0</string>
- </dict>
- </dict>
- <key>Tail</key>
- <dict>
- <key>ID</key>
- <integer>58</integer>
- </dict>
- </dict>
- <dict>
- <key>Class</key>
- <string>TableGroup</string>
- <key>Graphics</key>
- <array>
- <dict>
- <key>Bounds</key>
- <string>{{429.24670918782579, 464.13918876647955}, {115.08661651611328, 28}}</string>
- <key>Class</key>
- <string>ShapedGraphic</string>
- <key>FitText</key>
- <string>Vertical</string>
- <key>Flow</key>
- <string>Resize</string>
- <key>ID</key>
- <integer>86</integer>
- <key>Shape</key>
- <string>Rectangle</string>
- <key>Style</key>
- <dict>
- <key>fill</key>
- <dict>
- <key>GradientCenter</key>
- <string>{-0.29411799999999999, -0.264706}</string>
- </dict>
- <key>stroke</key>
- <dict>
- <key>Color</key>
- <dict>
- <key>b</key>
- <string>1</string>
- <key>g</key>
- <string>0</string>
- <key>r</key>
- <string>0</string>
- </dict>
- </dict>
- </dict>
- <key>Text</key>
- <dict>
- <key>Text</key>
- <string>{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
-
-\f0\b\fs24 \cf0 &lt;&lt;interface&gt;&gt;\
-ResponseHandler}</string>
- <key>VerticalPad</key>
- <integer>0</integer>
- </dict>
- <key>TextPlacement</key>
- <integer>0</integer>
- </dict>
- </array>
- <key>ID</key>
- <integer>85</integer>
- </dict>
- <dict>
- <key>Class</key>
- <string>LineGraphic</string>
- <key>Head</key>
- <dict>
- <key>ID</key>
- <integer>80</integer>
- </dict>
- <key>ID</key>
- <integer>81</integer>
- <key>Points</key>
- <array>
- <string>{388.98464357649044, 311.73041212162735}</string>
- <string>{421.12154403577119, 242.99627753494852}</string>
- </array>
- <key>Style</key>
- <dict>
- <key>stroke</key>
- <dict>
- <key>HeadArrow</key>
- <string>Arrow</string>
- <key>Legacy</key>
- <true/>
- <key>LineType</key>
- <integer>1</integer>
- <key>TailArrow</key>
- <string>0</string>
- </dict>
- </dict>
- <key>Tail</key>
- <dict>
- <key>ID</key>
- <integer>52</integer>
- </dict>
- </dict>
- <dict>
- <key>Bounds</key>
- <string>{{298.33331664403278, 228.54334004720087}, {246, 14}}</string>
- <key>Class</key>
- <string>ShapedGraphic</string>
- <key>ID</key>
- <integer>80</integer>
- <key>Magnets</key>
- <array>
- <string>{0, 1}</string>
- <string>{0, -1}</string>
- <string>{1, 0}</string>
- <string>{-1, 0}</string>
- </array>
- <key>Shape</key>
- <string>Rectangle</string>
- <key>Style</key>
- <dict>
- <key>stroke</key>
- <dict>
- <key>Color</key>
- <dict>
- <key>b</key>
- <string>0</string>
- <key>g</key>
- <string>0</string>
- <key>r</key>
- <string>1</string>
- </dict>
- </dict>
- </dict>
- <key>Text</key>
- <dict>
- <key>Text</key>
- <string>{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
-
-\f0\b\fs24 \cf0 IdleStateAwareChannelUpstreamHandler}</string>
- <key>VerticalPad</key>
- <integer>0</integer>
- </dict>
- </dict>
- <dict>
- <key>Class</key>
- <string>LineGraphic</string>
- <key>Head</key>
- <dict>
- <key>ID</key>
- <integer>10</integer>
- </dict>
- <key>ID</key>
- <integer>27</integer>
- <key>Points</key>
- <array>
- <string>{129.27841644847507, 130.04334003445351}</string>
- <string>{129.27841313680011, 80.666667938232422}</string>
- </array>
- <key>Style</key>
- <dict>
- <key>stroke</key>
- <dict>
- <key>HeadArrow</key>
- <string>Arrow</string>
- <key>Legacy</key>
- <true/>
- <key>LineType</key>
- <integer>1</integer>
- <key>TailArrow</key>
- <string>0</string>
- </dict>
- </dict>
- <key>Tail</key>
- <dict>
- <key>ID</key>
- <integer>69</integer>
- </dict>
- </dict>
- <dict>
- <key>Bounds</key>
- <string>{{71.445081075032547, 66.666667938232422}, {115.66666412353516, 14}}</string>
- <key>Class</key>
- <string>ShapedGraphic</string>
- <key>ID</key>
- <integer>10</integer>
- <key>Magnets</key>
- <array>
- <string>{0, 1}</string>
- <string>{0, -1}</string>
- <string>{1, 0}</string>
- <string>{-1, 0}</string>
- </array>
- <key>Shape</key>
- <string>Rectangle</string>
- <key>Style</key>
- <dict>
- <key>stroke</key>
- <dict>
- <key>Color</key>
- <dict>
- <key>b</key>
- <string>1</string>
- <key>g</key>
- <string>0</string>
- <key>r</key>
- <string>0</string>
- </dict>
- </dict>
- </dict>
- <key>Text</key>
- <dict>
- <key>Text</key>
- <string>{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
-
-\f0\b\fs24 \cf0 AbstractResource}</string>
- <key>VerticalPad</key>
- <integer>0</integer>
- </dict>
- </dict>
- <dict>
- <key>Class</key>
- <string>LineGraphic</string>
- <key>Head</key>
- <dict>
- <key>ID</key>
- <integer>78</integer>
- </dict>
- <key>ID</key>
- <integer>79</integer>
- <key>Points</key>
- <array>
- <string>{185.26276724928567, 130.48075966792658}</string>
- <string>{297.8372493866778, 116.27917789513803}</string>
- </array>
- <key>Style</key>
- <dict>
- <key>stroke</key>
- <dict>
- <key>HeadArrow</key>
- <string>Arrow</string>
- <key>Legacy</key>
- <true/>
- <key>Pattern</key>
- <integer>1</integer>
- <key>TailArrow</key>
- <string>0</string>
- </dict>
- </dict>
- <key>Tail</key>
- <dict>
- <key>ID</key>
- <integer>69</integer>
- </dict>
- </dict>
- <dict>
- <key>Class</key>
- <string>TableGroup</string>
- <key>Graphics</key>
- <array>
- <dict>
- <key>Bounds</key>
- <string>{{298.3333059188999, 92.666666666666913}, {151.17318725585938, 28}}</string>
- <key>Class</key>
- <string>ShapedGraphic</string>
- <key>FitText</key>
- <string>Vertical</string>
- <key>Flow</key>
- <string>Resize</string>
- <key>ID</key>
- <integer>78</integer>
- <key>Shape</key>
- <string>Rectangle</string>
- <key>Style</key>
- <dict>
- <key>fill</key>
- <dict>
- <key>GradientCenter</key>
- <string>{-0.29411799999999999, -0.264706}</string>
- </dict>
- <key>stroke</key>
- <dict>
- <key>Color</key>
- <dict>
- <key>b</key>
- <string>0</string>
- <key>g</key>
- <string>0</string>
- <key>r</key>
- <string>1</string>
- </dict>
- </dict>
- </dict>
- <key>Text</key>
- <dict>
- <key>Text</key>
- <string>{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
-
-\f0\b\fs24 \cf0 &lt;&lt;interface&gt;&gt;\
-ChannelPipelineFactory}</string>
- <key>VerticalPad</key>
- <integer>0</integer>
- </dict>
- <key>TextPlacement</key>
- <integer>0</integer>
- </dict>
- </array>
- <key>ID</key>
- <integer>77</integer>
- </dict>
- <dict>
- <key>Class</key>
- <string>LineGraphic</string>
- <key>Head</key>
- <dict>
- <key>ID</key>
- <integer>75</integer>
- </dict>
- <key>ID</key>
- <integer>76</integer>
- <key>Points</key>
- <array>
- <string>{402.97819417613408, 311.99312587103537}</string>
- <string>{465.1473485992222, 286.41782928501391}</string>
- </array>
- <key>Style</key>
- <dict>
- <key>stroke</key>
- <dict>
- <key>HeadArrow</key>
- <string>Arrow</string>
- <key>Legacy</key>
- <true/>
- <key>Pattern</key>
- <integer>1</integer>
- <key>TailArrow</key>
- <string>0</string>
- </dict>
- </dict>
- <key>Tail</key>
- <dict>
- <key>ID</key>
- <integer>52</integer>
- </dict>
- </dict>
- <dict>
- <key>Class</key>
- <string>TableGroup</string>
- <key>Graphics</key>
- <array>
- <dict>
- <key>Bounds</key>
- <string>{{454.91339111328136, 258.22751967112259}, {89.419929504394531, 28}}</string>
- <key>Class</key>
- <string>ShapedGraphic</string>
- <key>FitText</key>
- <string>Vertical</string>
- <key>Flow</key>
- <string>Resize</string>
- <key>ID</key>
- <integer>75</integer>
- <key>Shape</key>
- <string>Rectangle</string>
- <key>Style</key>
- <dict>
- <key>fill</key>
- <dict>
- <key>GradientCenter</key>
- <string>{-0.29411799999999999, -0.264706}</string>
- </dict>
- <key>stroke</key>
- <dict>
- <key>Color</key>
- <dict>
- <key>b</key>
- <string>0</string>
- <key>g</key>
- <string>1</string>
- <key>r</key>
- <string>0</string>
- </dict>
- </dict>
- </dict>
- <key>Text</key>
- <dict>
- <key>Text</key>
- <string>{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
-
-\f0\b\fs24 \cf0 &lt;&lt;interface&gt;&gt;\
-Runnable}</string>
- <key>VerticalPad</key>
- <integer>0</integer>
- </dict>
- <key>TextPlacement</key>
- <integer>0</integer>
- </dict>
- </array>
- <key>ID</key>
- <integer>74</integer>
- </dict>
- <dict>
- <key>Class</key>
- <string>LineGraphic</string>
- <key>Head</key>
- <dict>
- <key>ID</key>
- <integer>34</integer>
- </dict>
- <key>ID</key>
- <integer>9</integer>
- <key>Points</key>
- <array>
- <string>{143.15706944536032, 130.31230832708621}</string>
- <string>{250.79491585172687, 74.231022194055214}</string>
- </array>
- <key>Style</key>
- <dict>
- <key>stroke</key>
- <dict>
- <key>HeadArrow</key>
- <string>Arrow</string>
- <key>Legacy</key>
- <true/>
- <key>Pattern</key>
- <integer>1</integer>
- <key>TailArrow</key>
- <string>0</string>
- </dict>
- </dict>
- <key>Tail</key>
- <dict>
- <key>ID</key>
- <integer>69</integer>
- </dict>
- </dict>
- <dict>
- <key>Class</key>
- <string>TableGroup</string>
- <key>Graphics</key>
- <array>
- <dict>
- <key>Bounds</key>
- <string>{{226.66667683919275, 45.999999999999929}, {102.88706970214844, 28}}</string>
- <key>Class</key>
- <string>ShapedGraphic</string>
- <key>FitText</key>
- <string>Vertical</string>
- <key>Flow</key>
- <string>Resize</string>
- <key>ID</key>
- <integer>34</integer>
- <key>Shape</key>
- <string>Rectangle</string>
- <key>Style</key>
- <dict>
- <key>fill</key>
- <dict>
- <key>GradientCenter</key>
- <string>{-0.29411799999999999, -0.264706}</string>
- </dict>
- <key>stroke</key>
- <dict>
- <key>Color</key>
- <dict>
- <key>b</key>
- <string>1</string>
- <key>g</key>
- <string>0</string>
- <key>r</key>
- <string>0</string>
- </dict>
- </dict>
- </dict>
- <key>Text</key>
- <dict>
- <key>Text</key>
- <string>{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
-
-\f0\b\fs24 \cf0 &lt;&lt;interface&gt;&gt;\
-ServerProvider}</string>
- <key>VerticalPad</key>
- <integer>0</integer>
- </dict>
- <key>TextPlacement</key>
- <integer>0</integer>
- </dict>
- </array>
- <key>ID</key>
- <integer>33</integer>
- </dict>
- <dict>
- <key>Bounds</key>
- <string>{{344.6666666666668, 438.85001627604163}, {17, 14}}</string>
- <key>Class</key>
- <string>ShapedGraphic</string>
- <key>FitText</key>
- <string>YES</string>
- <key>Flow</key>
- <string>Resize</string>
- <key>ID</key>
- <integer>63</integer>
- <key>Shape</key>
- <string>Rectangle</string>
- <key>Style</key>
- <dict>
- <key>fill</key>
- <dict>
- <key>Draws</key>
- <string>NO</string>
- </dict>
- <key>shadow</key>
- <dict>
- <key>Draws</key>
- <string>NO</string>
- </dict>
- <key>stroke</key>
- <dict>
- <key>Draws</key>
- <string>NO</string>
- </dict>
- </dict>
- <key>Text</key>
- <dict>
- <key>Align</key>
- <integer>0</integer>
- <key>Text</key>
- <string>{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
-
-\f0\fs24 \cf0 1}</string>
- <key>VerticalPad</key>
- <integer>0</integer>
- </dict>
- <key>Wrap</key>
- <string>NO</string>
- </dict>
- <dict>
- <key>Bounds</key>
- <string>{{308.27841186523432, 496.00000000000023}, {29.333332061767578, 14}}</string>
- <key>Class</key>
- <string>ShapedGraphic</string>
- <key>FitText</key>
- <string>Vertical</string>
- <key>Flow</key>
- <string>Resize</string>
- <key>ID</key>
- <integer>62</integer>
- <key>Shape</key>
- <string>Rectangle</string>
- <key>Style</key>
- <dict>
- <key>fill</key>
- <dict>
- <key>Draws</key>
- <string>NO</string>
- </dict>
- <key>shadow</key>
- <dict>
- <key>Draws</key>
- <string>NO</string>
- </dict>
- <key>stroke</key>
- <dict>
- <key>Draws</key>
- <string>NO</string>
- </dict>
- </dict>
- <key>Text</key>
- <dict>
- <key>Align</key>
- <integer>0</integer>
- <key>Text</key>
- <string>{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
-
-\f0\fs24 \cf0 1..*}</string>
- <key>VerticalPad</key>
- <integer>0</integer>
- </dict>
- </dict>
- <dict>
- <key>Class</key>
- <string>LineGraphic</string>
- <key>Head</key>
- <dict>
- <key>ID</key>
- <integer>58</integer>
- </dict>
- <key>ID</key>
- <integer>61</integer>
- <key>Points</key>
- <array>
- <string>{364.20702685721608, 438.63027009978003}</string>
- <string>{326.6915789284576, 513.41623846111793}</string>
- </array>
- <key>Style</key>
- <dict>
- <key>stroke</key>
- <dict>
- <key>HeadArrow</key>
- <string>0</string>
- <key>Legacy</key>
- <true/>
- <key>LineType</key>
- <integer>1</integer>
- <key>TailArrow</key>
- <string>0</string>
- </dict>
- </dict>
- <key>Tail</key>
- <dict>
- <key>ID</key>
- <integer>54</integer>
- </dict>
- </dict>
- <dict>
- <key>Class</key>
- <string>TableGroup</string>
- <key>Graphics</key>
- <array>
- <dict>
- <key>Bounds</key>
- <string>{{226.66666603088379, 513.86289469401004}, {192.55682373046875, 14}}</string>
- <key>Class</key>
- <string>ShapedGraphic</string>
- <key>FitText</key>
- <string>Vertical</string>
- <key>Flow</key>
- <string>Resize</string>
- <key>ID</key>
- <integer>58</integer>
- <key>Shape</key>
- <string>Rectangle</string>
- <key>Style</key>
- <dict>
- <key>fill</key>
- <dict>
- <key>GradientCenter</key>
- <string>{-0.29411799999999999, -0.264706}</string>
- </dict>
- </dict>
- <key>Text</key>
- <dict>
- <key>Text</key>
- <string>{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
-
-\f0\b\fs24 \cf0 RequestContext}</string>
- <key>VerticalPad</key>
- <integer>0</integer>
- </dict>
- <key>TextPlacement</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>Bounds</key>
- <string>{{226.66666603088379, 527.86289469401004}, {192.55682373046875, 42}}</string>
- <key>Class</key>
- <string>ShapedGraphic</string>
- <key>FitText</key>
- <string>Vertical</string>
- <key>Flow</key>
- <string>Resize</string>
- <key>ID</key>
- <integer>59</integer>
- <key>Shape</key>
- <string>Rectangle</string>
- <key>Style</key>
- <dict>
- <key>fill</key>
- <dict>
- <key>GradientCenter</key>
- <string>{-0.29411799999999999, -0.264706}</string>
- </dict>
- </dict>
- <key>Text</key>
- <dict>
- <key>Align</key>
- <integer>0</integer>
- <key>Text</key>
- <string>{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
-
-\f0\fs24 \cf0 HttpRequest request\
-ContentChannel requestContent\
-ContentChannel responseContent}</string>
- <key>VerticalPad</key>
- <integer>0</integer>
- </dict>
- <key>TextPlacement</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>Bounds</key>
- <string>{{226.66666603088379, 569.86289469401004}, {192.55682373046875, 28}}</string>
- <key>Class</key>
- <string>ShapedGraphic</string>
- <key>FitText</key>
- <string>Vertical</string>
- <key>Flow</key>
- <string>Resize</string>
- <key>ID</key>
- <integer>60</integer>
- <key>Shape</key>
- <string>Rectangle</string>
- <key>Style</key>
- <dict>
- <key>fill</key>
- <dict>
- <key>GradientCenter</key>
- <string>{-0.29411799999999999, -0.264706}</string>
- </dict>
- </dict>
- <key>Text</key>
- <dict>
- <key>Align</key>
- <integer>0</integer>
- <key>Text</key>
- <string>{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
-
-\f0\fs24 \cf0 connect()\
-handleResponse(Response)}</string>
- <key>VerticalPad</key>
- <integer>0</integer>
- </dict>
- <key>TextPlacement</key>
- <integer>0</integer>
- </dict>
- </array>
- <key>GridH</key>
- <array>
- <integer>58</integer>
- <integer>59</integer>
- <integer>60</integer>
- <array/>
- </array>
- <key>ID</key>
- <integer>57</integer>
- </dict>
- <dict>
- <key>Class</key>
- <string>TableGroup</string>
- <key>Graphics</key>
- <array>
- <dict>
- <key>Bounds</key>
- <string>{{226.66666666666663, 312.183349609375}, {317.66665649414062, 14}}</string>
- <key>Class</key>
- <string>ShapedGraphic</string>
- <key>FitText</key>
- <string>Vertical</string>
- <key>Flow</key>
- <string>Resize</string>
- <key>ID</key>
- <integer>52</integer>
- <key>Shape</key>
- <string>Rectangle</string>
- <key>Style</key>
- <dict>
- <key>fill</key>
- <dict>
- <key>GradientCenter</key>
- <string>{-0.29411799999999999, -0.264706}</string>
- </dict>
- </dict>
- <key>Text</key>
- <dict>
- <key>Text</key>
- <string>{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
-
-\f0\b\fs24 \cf0 ChannelContext}</string>
- <key>VerticalPad</key>
- <integer>0</integer>
- </dict>
- <key>TextPlacement</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>Bounds</key>
- <string>{{226.66666666666652, 326.183349609375}, {317.66665649414062, 28}}</string>
- <key>Class</key>
- <string>ShapedGraphic</string>
- <key>FitText</key>
- <string>Vertical</string>
- <key>Flow</key>
- <string>Resize</string>
- <key>ID</key>
- <integer>53</integer>
- <key>Shape</key>
- <string>Rectangle</string>
- <key>Style</key>
- <dict>
- <key>fill</key>
- <dict>
- <key>GradientCenter</key>
- <string>{-0.29411799999999999, -0.264706}</string>
- </dict>
- </dict>
- <key>Text</key>
- <dict>
- <key>Align</key>
- <integer>0</integer>
- <key>Text</key>
- <string>{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
-
-\f0\fs24 \cf0 LinkedBlockingQueue&lt;ResponsePart&gt; responseOutputs\
-Channel serverChannel}</string>
- <key>VerticalPad</key>
- <integer>0</integer>
- </dict>
- <key>TextPlacement</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>Bounds</key>
- <string>{{226.66666666666663, 354.183349609375}, {317.66665649414062, 84}}</string>
- <key>Class</key>
- <string>ShapedGraphic</string>
- <key>FitText</key>
- <string>Vertical</string>
- <key>Flow</key>
- <string>Resize</string>
- <key>ID</key>
- <integer>54</integer>
- <key>Shape</key>
- <string>Rectangle</string>
- <key>Style</key>
- <dict>
- <key>fill</key>
- <dict>
- <key>GradientCenter</key>
- <string>{-0.29411799999999999, -0.264706}</string>
- </dict>
- </dict>
- <key>Text</key>
- <dict>
- <key>Align</key>
- <integer>0</integer>
- <key>Text</key>
- <string>{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
-
-\f0\fs24 \cf0 channelConnected()\
-messageReceived()\
-exceptionCaught()\
-channelDisconnected()\
-channelIdle()\
-run()}</string>
- <key>VerticalPad</key>
- <integer>0</integer>
- </dict>
- <key>TextPlacement</key>
- <integer>0</integer>
- </dict>
- </array>
- <key>GridH</key>
- <array>
- <integer>52</integer>
- <integer>53</integer>
- <integer>54</integer>
- <array/>
- </array>
- <key>ID</key>
- <integer>51</integer>
- </dict>
- <dict>
- <key>Bounds</key>
- <string>{{158.97158196265923, 262.43389980796718}, {29.333332061767578, 14}}</string>
- <key>Class</key>
- <string>ShapedGraphic</string>
- <key>FitText</key>
- <string>Vertical</string>
- <key>Flow</key>
- <string>Resize</string>
- <key>ID</key>
- <integer>47</integer>
- <key>Line</key>
- <dict>
- <key>ID</key>
- <integer>16</integer>
- <key>Offset</key>
- <real>12.666667938232422</real>
- <key>Position</key>
- <real>0.93361091613769531</real>
- <key>RotationType</key>
- <integer>0</integer>
- </dict>
- <key>Shape</key>
- <string>Rectangle</string>
- <key>Style</key>
- <dict>
- <key>fill</key>
- <dict>
- <key>Draws</key>
- <string>NO</string>
- </dict>
- <key>shadow</key>
- <dict>
- <key>Draws</key>
- <string>NO</string>
- </dict>
- <key>stroke</key>
- <dict>
- <key>Draws</key>
- <string>NO</string>
- </dict>
- </dict>
- <key>Text</key>
- <dict>
- <key>Align</key>
- <integer>0</integer>
- <key>Text</key>
- <string>{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
-
-\f0\fs24 \cf0 0..*}</string>
- <key>VerticalPad</key>
- <integer>0</integer>
- </dict>
- </dict>
- <dict>
- <key>Class</key>
- <string>LineGraphic</string>
- <key>Head</key>
- <dict>
- <key>ID</key>
- <integer>104</integer>
- </dict>
- <key>ID</key>
- <integer>16</integer>
- <key>Points</key>
- <array>
- <string>{144.7864237041758, 242.98231480726633}</string>
- <string>{163.77841186523429, 277.810302734375}</string>
- </array>
- <key>Style</key>
- <dict>
- <key>stroke</key>
- <dict>
- <key>HeadArrow</key>
- <string>StickArrow</string>
- <key>Legacy</key>
- <true/>
- <key>LineType</key>
- <integer>1</integer>
- <key>TailArrow</key>
- <string>0</string>
- </dict>
- </dict>
- <key>Tail</key>
- <dict>
- <key>ID</key>
- <integer>71</integer>
- </dict>
- </dict>
- <dict>
- <key>Class</key>
- <string>TableGroup</string>
- <key>Graphics</key>
- <array>
- <dict>
- <key>Bounds</key>
- <string>{{33.000005086262888, 130.54334004720062}, {192.55682373046875, 14}}</string>
- <key>Class</key>
- <string>ShapedGraphic</string>
- <key>FitText</key>
- <string>Vertical</string>
- <key>Flow</key>
- <string>Resize</string>
- <key>ID</key>
- <integer>69</integer>
- <key>Shape</key>
- <string>Rectangle</string>
- <key>Style</key>
- <dict>
- <key>fill</key>
- <dict>
- <key>GradientCenter</key>
- <string>{-0.29411799999999999, -0.264706}</string>
- </dict>
- </dict>
- <key>Text</key>
- <dict>
- <key>Text</key>
- <string>{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
-
-\f0\b\fs24 \cf0 HttpServer}</string>
- <key>VerticalPad</key>
- <integer>0</integer>
- </dict>
- <key>TextPlacement</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>Bounds</key>
- <string>{{33.000005086262888, 144.54334004720062}, {192.55682373046875, 42}}</string>
- <key>Class</key>
- <string>ShapedGraphic</string>
- <key>FitText</key>
- <string>Vertical</string>
- <key>Flow</key>
- <string>Resize</string>
- <key>ID</key>
- <integer>70</integer>
- <key>Shape</key>
- <string>Rectangle</string>
- <key>Style</key>
- <dict>
- <key>fill</key>
- <dict>
- <key>GradientCenter</key>
- <string>{-0.29411799999999999, -0.264706}</string>
- </dict>
- </dict>
- <key>Text</key>
- <dict>
- <key>Align</key>
- <integer>0</integer>
- <key>Text</key>
- <string>{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
-
-\f0\fs24 \cf0 Channel serverChannel\
-Executor channelWorkerExecutor\
-HttpServerConfig config}</string>
- <key>VerticalPad</key>
- <integer>0</integer>
- </dict>
- <key>TextPlacement</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>Bounds</key>
- <string>{{33.000005086262888, 186.54334004720062}, {192.55682373046875, 56}}</string>
- <key>Class</key>
- <string>ShapedGraphic</string>
- <key>FitText</key>
- <string>Vertical</string>
- <key>Flow</key>
- <string>Resize</string>
- <key>ID</key>
- <integer>71</integer>
- <key>Shape</key>
- <string>Rectangle</string>
- <key>Style</key>
- <dict>
- <key>fill</key>
- <dict>
- <key>GradientCenter</key>
- <string>{-0.29411799999999999, -0.264706}</string>
- </dict>
- </dict>
- <key>Text</key>
- <dict>
- <key>Align</key>
- <integer>0</integer>
- <key>Text</key>
- <string>{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
-
-\f0\fs24 \cf0 start()\
-close()\
-destroy()\
-getPipeline()}</string>
- <key>VerticalPad</key>
- <integer>0</integer>
- </dict>
- <key>TextPlacement</key>
- <integer>0</integer>
- </dict>
- </array>
- <key>GridH</key>
- <array>
- <integer>69</integer>
- <integer>70</integer>
- <integer>71</integer>
- <array/>
- </array>
- <key>ID</key>
- <integer>68</integer>
- </dict>
- </array>
- <key>GridInfo</key>
- <dict/>
- <key>GuidesLocked</key>
- <string>NO</string>
- <key>GuidesVisible</key>
- <string>YES</string>
- <key>HPages</key>
- <integer>1</integer>
- <key>ImageCounter</key>
- <integer>1</integer>
- <key>KeepToScale</key>
- <false/>
- <key>Layers</key>
- <array>
- <dict>
- <key>Lock</key>
- <string>NO</string>
- <key>Name</key>
- <string>Layer 1</string>
- <key>Print</key>
- <string>YES</string>
- <key>View</key>
- <string>YES</string>
- </dict>
- </array>
- <key>LayoutInfo</key>
- <dict>
- <key>Animate</key>
- <string>NO</string>
- <key>circoMinDist</key>
- <real>18</real>
- <key>circoSeparation</key>
- <real>0.0</real>
- <key>layoutEngine</key>
- <string>dot</string>
- <key>neatoSeparation</key>
- <real>0.0</real>
- <key>twopiSeparation</key>
- <real>0.0</real>
- </dict>
- <key>LinksVisible</key>
- <string>NO</string>
- <key>MagnetsVisible</key>
- <string>NO</string>
- <key>MasterSheets</key>
- <array/>
- <key>ModificationDate</key>
- <string>2012-06-19 09:20:43 +0000</string>
- <key>Modifier</key>
- <string>Einar Rosenvinge</string>
- <key>NotesVisible</key>
- <string>NO</string>
- <key>Orientation</key>
- <integer>2</integer>
- <key>OriginVisible</key>
- <string>NO</string>
- <key>PageBreaks</key>
- <string>YES</string>
- <key>PrintInfo</key>
- <dict>
- <key>NSBottomMargin</key>
- <array>
- <string>float</string>
- <string>41</string>
- </array>
- <key>NSHorizonalPagination</key>
- <array>
- <string>coded</string>
- <string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG</string>
- </array>
- <key>NSLeftMargin</key>
- <array>
- <string>float</string>
- <string>18</string>
- </array>
- <key>NSPaperSize</key>
- <array>
- <string>size</string>
- <string>{594.99999713897705, 842}</string>
- </array>
- <key>NSPrintReverseOrientation</key>
- <array>
- <string>int</string>
- <string>0</string>
- </array>
- <key>NSRightMargin</key>
- <array>
- <string>float</string>
- <string>18</string>
- </array>
- <key>NSTopMargin</key>
- <array>
- <string>float</string>
- <string>18</string>
- </array>
- </dict>
- <key>PrintOnePage</key>
- <false/>
- <key>ReadOnly</key>
- <string>NO</string>
- <key>RowAlign</key>
- <integer>1</integer>
- <key>RowSpacing</key>
- <real>36</real>
- <key>SheetTitle</key>
- <string>Canvas 1</string>
- <key>SmartAlignmentGuidesActive</key>
- <string>YES</string>
- <key>SmartDistanceGuidesActive</key>
- <string>YES</string>
- <key>UniqueID</key>
- <integer>1</integer>
- <key>UseEntirePage</key>
- <false/>
- <key>VPages</key>
- <integer>1</integer>
- <key>WindowInfo</key>
- <dict>
- <key>CurrentSheet</key>
- <integer>0</integer>
- <key>ExpandedCanvases</key>
- <array>
- <dict>
- <key>name</key>
- <string>Canvas 1</string>
- </dict>
- </array>
- <key>Frame</key>
- <string>{{246, 375}, {1064, 803}}</string>
- <key>ListView</key>
- <true/>
- <key>OutlineWidth</key>
- <integer>142</integer>
- <key>RightSidebar</key>
- <false/>
- <key>ShowRuler</key>
- <true/>
- <key>Sidebar</key>
- <true/>
- <key>SidebarWidth</key>
- <integer>120</integer>
- <key>VisibleRegion</key>
- <string>{{-25, 0}, {610, 442.66666666666669}}</string>
- <key>Zoom</key>
- <real>1.5</real>
- <key>ZoomValues</key>
- <array>
- <array>
- <string>Canvas 1</string>
- <real>1.5</real>
- <real>0.25</real>
- </array>
- </array>
- </dict>
-</dict>
-</plist>
diff --git a/jdisc_http_service/docs/class-diagram.png b/jdisc_http_service/docs/class-diagram.png
deleted file mode 100644
index ebccfd75bf9..00000000000
--- a/jdisc_http_service/docs/class-diagram.png
+++ /dev/null
Binary files differ
diff --git a/jdisc_http_service/docs/httpserver.html b/jdisc_http_service/docs/httpserver.html
deleted file mode 100644
index 66afeb687fe..00000000000
--- a/jdisc_http_service/docs/httpserver.html
+++ /dev/null
@@ -1,96 +0,0 @@
-<!-- Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
-<!-- Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
- "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<head>
- <title>HTTP Server Architecture</title>
- <style type="text/css">
- body {
- font: 13px/1.231 arial,helvetica,clean,sans-serif;
- *font-size: small;
- *font: x-small;
- }
- select,input,button,textarea {
- font: 99% arial,helvetica,clean,sans-serif;
- }
- table{
- font-size: inherit;
- font: 100%;
- }
- pre,code,kbd,samp,tt {
- font-family: monospace;
- *font-size: 108%;
- line-height: 100%;
- }
- </style>
-</head>
-<body>
-<p>The HTTP server is started by calling <code>HttpServer.start()</code>, which in turn calls <code>ServerBootstrap.bind()</code>
- provided by
- Netty.</p>
-
-<img src="class-diagram.png" alt="Class diagram">
-
-<p>Since our HttpServer implements <code>ChannelPipelineFactory</code> (provided by jetty), its
- <code>getPipeline()</code> method is called for every new channel that is connected. There is hence a one-to-many
- relationship between a <code>HttpServer</code> and a pipeline (and a one-to-one relationship between an actual
- channel and a pipeline).</p>
-
-<p>The pipeline is responsible for decoding (and possibly deflating etc.) every new request that is received on a
- channel. The final element in the pipeline is a <code>ChannelContext</code>, which is the jDISC class for handling
- requests on a channel.</p>
-
-<p>The <code>ChannelContext</code> implements <code>SimpleChannelUpstreamHandler</code> (provided by Jetty), which has
- simple callback methods for various event types. <br/>Examples:</p>
-
-<ul>
- <li><code>channelConnected()</code></li>
- <li><code>channelDisconnected()</code></li>
- <li><code>messageReceived()</code></li>
-</ul>
-
-<p>Since <code>ChannelContext</code> supports HTTP keep-alive and HTTP pipelining, it needs to keep track of multiple
- requests made on the channel, and their order.</p>
-
-<p>In <code>messageReceived()</code> it will:</p>
-<ul>
- <li>Determine if the element received is a new HTTP request, or a chunk belonging to the previous one.</li>
- <li>If it's a request, create a DISC <code>Request</code> object for it, and call <code>Request.connect()</code>,
- which will in turn give it to the actual application, through the use of
- <code>RequestHandler.handleRequest()</code>.
- </li>
- <li>If it's a chunk, fetch the previously added <code>RequestContext</code>, and use it to write the data received
- into the <code>ContentChannel</code>.
- </li>
-</ul>
-
-<p><code>RequestContext</code> keeps track of a request and its input and output <code>ContentChannel</code>s, and
- related objects. Since <code>RequestContext</code> is a <code>ResponseHandler</code>, it is responsible for
- instantiating and returning a <code>ContentChannel</code> when an application calls <code>handleResponse()</code>.
- Two types are supported, one that supports HTTP response chunking, and one that does not. The type used is chosen
- automatically based on HTTP version, headers etc.</p>
-
-<p>Since the jDISC API is fully asynchronous, operations can occur in any order. This is very extensively tested in the
- HTTP server implementation. For instance, an application (<code>RequestHandler</code>) may choose to respond and
- close the output <code>ContentChannel</code> immediately upon receiving the request, before the body of the request
- has been written into the input <code>ContentChannel</code> of the <code>RequestHandler</code>. All such cases are
- tested and properly handled.</p>
-
-<p>As one can see from the illustration, <code>ChannelContext</code> is also a <code>Runnable</code>, i.e. it keeps one
- thread per channel. The HTTP server has two modes of operation, <code>optimizeForPipeline</code> <code>true</code>
- or <code>false</code> in <code>HttpServerConfig</code>.</p>
-
-<p>If <code>optimizeForPipeline</code> is set to <code>true</code>, response chunks are enqueued on a blocking queue in
- <code>ChannelContext</code> when <code>ContentChannel.write()</code> is called. The <code>ChannelContext</code>
- thread is responsible for actually writing them, and closing the channel when appropriate. Since the HTTP server
- supports pipelining, and writes from an application may occur in any order, special care is taken to write response
- chunks in the correct order.</p>
-
-<p>If <code>optimizeForPipeline</code> is set to <code>false</code>, a call to <code>ContentChannel.write()</code> will
- lead to an actual write on the wire, iff. the given chunk to be written is the next in line. Otherwise this is a
- no-op. This also means that a <code>ContentChannel.write()</code> may lead to a cascade of writes that have been
- enqueued since they were out-of-order when their <code>write()</code> was called. The <code>ChannelContext</code>
- thread still takes care of channel closing in most cases.</p>
-</body>
-</html>
diff --git a/jrt/pom.xml b/jrt/pom.xml
index 6592cd84638..08ef9693750 100644
--- a/jrt/pom.xml
+++ b/jrt/pom.xml
@@ -52,7 +52,6 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
- <version>2.3.1</version>
<configuration>
<updateReleaseInfo>true</updateReleaseInfo>
</configuration>
diff --git a/jrt_test/src/jrt-test/simpleserver/CMakeLists.txt b/jrt_test/src/jrt-test/simpleserver/CMakeLists.txt
index 922fa7edf49..9c88dacdb1d 100644
--- a/jrt_test/src/jrt-test/simpleserver/CMakeLists.txt
+++ b/jrt_test/src/jrt-test/simpleserver/CMakeLists.txt
@@ -2,6 +2,5 @@
vespa_add_executable(jrt_test_simpleserver_app
SOURCES
simpleserver.cpp
- INSTALL bin
DEPENDS
)
diff --git a/juniper/src/testproject.el b/juniper/src/testproject.el
index 56cc68fe61d..8b52d77d651 100644
--- a/juniper/src/testproject.el
+++ b/juniper/src/testproject.el
@@ -6,7 +6,7 @@
;; the class(es) you want to test.
;; $Revision: 1.2 $ $Date: 2003-02-27 12:32:24 $
-;; Author: Nils Sandøy <nils.sandoy@fast.no>
+;; Author: Nils Sandøy <nils.sandoy@fast.no>
;; Just a message to show that this file is beeing read. Look for this
;; in the *Messages* buffer.
diff --git a/libmlr/pom.xml b/libmlr/pom.xml
index 53ac04ffcc7..46f2e5447fa 100644
--- a/libmlr/pom.xml
+++ b/libmlr/pom.xml
@@ -39,7 +39,6 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
- <version>2.3.1</version>
<configuration>
<updateReleaseInfo>true</updateReleaseInfo>
</configuration>
diff --git a/logd/src/apps/logd/.gitignore b/logd/src/apps/logd/.gitignore
index cad0e581304..a9a724ce05c 100644
--- a/logd/src/apps/logd/.gitignore
+++ b/logd/src/apps/logd/.gitignore
@@ -1,3 +1,3 @@
/.depend
/Makefile
-/logd
+/vespa-logd
diff --git a/logd/src/apps/logd/CMakeLists.txt b/logd/src/apps/logd/CMakeLists.txt
index 7caf8300617..24b39c45144 100644
--- a/logd/src/apps/logd/CMakeLists.txt
+++ b/logd/src/apps/logd/CMakeLists.txt
@@ -2,7 +2,7 @@
vespa_add_executable(logd_app
SOURCES
main.cpp
- OUTPUT_NAME logd
+ OUTPUT_NAME vespa-logd
INSTALL sbin
DEPENDS
logd
diff --git a/logd/src/tests/rotate/rotate_test.sh b/logd/src/tests/rotate/rotate_test.sh
index 2af4d92e078..053a6a3670c 100755
--- a/logd/src/tests/rotate/rotate_test.sh
+++ b/logd/src/tests/rotate/rotate_test.sh
@@ -18,7 +18,7 @@ sleep 5
$SOURCE_DIRECTORY/create_configfile.sh
export VESPA_CONFIG_ID=file:logd.cfg
-../../apps/logd/logd &
+../../apps/logd/vespa-logd &
echo $! > logd.pid
./logd_dummylogger_app
diff --git a/messagebus/src/apps/printversion/CMakeLists.txt b/messagebus/src/apps/printversion/CMakeLists.txt
index 2576eef901e..03f351bbda7 100644
--- a/messagebus/src/apps/printversion/CMakeLists.txt
+++ b/messagebus/src/apps/printversion/CMakeLists.txt
@@ -2,7 +2,6 @@
vespa_add_executable(messagebus_printversion_app
SOURCES
printversion.cpp
- INSTALL bin
DEPENDS
messagebus
)
diff --git a/messagebus/src/main/java/com/yahoo/messagebus/routing/RoutingNode.java b/messagebus/src/main/java/com/yahoo/messagebus/routing/RoutingNode.java
index e394b133bca..26c103e7877 100755
--- a/messagebus/src/main/java/com/yahoo/messagebus/routing/RoutingNode.java
+++ b/messagebus/src/main/java/com/yahoo/messagebus/routing/RoutingNode.java
@@ -234,7 +234,7 @@ public class RoutingNode implements ReplyHandler {
policy.merge(routingContext);
} catch (RuntimeException e) {
setError(ErrorCode.POLICY_ERROR,
- "Policy '" + dir.getName() + "' threw an exception; " + e.toString());
+ "Policy '" + dir.getName() + "' threw an exception; " + exceptionMessageWithTrace(e));
}
if (reply == null) {
setError(ErrorCode.APP_FATAL_ERROR,
diff --git a/node-admin/README.md b/node-admin/README.md
index 8352cbd3c43..bab4c17ffbf 100644
--- a/node-admin/README.md
+++ b/node-admin/README.md
@@ -31,7 +31,7 @@ implements all of the basic methods you need to get started.
To start a local zone, simply run:
```
- DockerImage dockerImage = new DockerImage("docker-registry.ops.yahoo.com:4443/vespa/ci:6.111.21");
+ DockerImage dockerImage = new DockerImage("docker-registry.domain.tld:8080/vespa/ci:6.111.21");
Path pathToVespaRoot = Paths.get("/home/valerijf/dev/vespa");
Path pathToContainerStorage = Paths.get("/home/docker/container-storage");
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImpl.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImpl.java
index 8e67cac5b2f..0fbd69708db 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImpl.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImpl.java
@@ -1,6 +1,7 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.node.admin.nodeagent;
+import com.fasterxml.jackson.core.JsonProcessingException;
import com.yahoo.vespa.hosted.dockerapi.Container;
import com.yahoo.vespa.hosted.dockerapi.ContainerName;
import com.yahoo.vespa.hosted.dockerapi.Docker;
@@ -575,14 +576,20 @@ public class NodeAgentImpl implements NodeAgent {
// Push metrics to the metrics proxy in each container - give it maximum 1 seconds to complete
try {
- //TODO The command here is almost a dummy command until we have the proper RPC method in place
- // Remember proper argument encoding
- dockerOperations.executeCommandInContainerAsRoot(containerName, 1L, "sh", "-c", "'echo " + metricReceiver.toString() + "'");
- } catch (DockerExecTimeoutException e) {
+ dockerOperations.executeCommandInContainerAsRoot(containerName, 1L, "rpc_invoke", "-t 1", "tcp/localhost:19091", "setExtraMetrics", buildRPCArgumentFromMetrics());
+ } catch (DockerExecTimeoutException|JsonProcessingException e) {
logger.warning("Unable to push metrics to container: " + containerName, e);
}
}
+ protected String buildRPCArgumentFromMetrics() throws JsonProcessingException {
+ StringBuilder params = new StringBuilder();
+ for (MetricReceiverWrapper.DimensionMetrics dimensionMetrics : metricReceiver.getAllMetrics()) {
+ params.append(dimensionMetrics.toSecretAgentReport());
+ }
+ return "s:'" + params.toString() + "'";
+ }
+
@SuppressWarnings("unchecked")
private void addIfNotNull(Dimensions dimensions, String yamasName, Object metrics, String metricName) {
Map<String, Object> metricsMap = (Map<String, Object>) metrics;
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImplTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImplTest.java
index 83a00241919..174c9eeb695 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImplTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImplTest.java
@@ -488,8 +488,6 @@ public class NodeAgentImplTest {
verify(nodeAgent, times(3)).converge();
}
-
-
@Test
@SuppressWarnings("unchecked")
public void testGetRelevantMetrics() throws Exception {
@@ -536,6 +534,11 @@ public class NodeAgentImplTest {
Set<Map<String, Object>> expectedMetrics = objectMapper.readValue(expectedMetricsFile, Set.class);
Set<Map<String, Object>> actualMetrics = metricReceiver.getAllMetricsRaw();
+ String arg = nodeAgent.buildRPCArgumentFromMetrics();
+ arg = arg.replaceAll("\"timestamp\":\\d+", "\"timestamp\":0");
+
+ assertEquals("s:'{\"routing\":{\"yamas\":{\"namespaces\":[\"Vespa\"]}},\"application\":\"vespa.node\",\"metrics\":{\"mem.limit\":4.294967296E9,\"mem.used\":1.073741824E9,\"alive\":1.0,\"disk.used\":4.2547019776E10,\"disk.util\":15.85,\"cpu.util\":6.75,\"disk.limit\":2.68435456E11,\"mem.util\":25.0},\"dimensions\":{\"app\":\"testapp.testinstance\",\"role\":\"tenants\",\"instanceName\":\"testinstance\",\"vespaVersion\":\"1.2.3\",\"clusterid\":\"clustId\",\"parentHostname\":\"parent.host.name.yahoo.com\",\"flavor\":\"docker\",\"clustertype\":\"clustType\",\"tenantName\":\"tester\",\"zone\":\"dev.us-east-1\",\"host\":\"host1.test.yahoo.com\",\"state\":\"active\",\"applicationId\":\"tester.testapp.testinstance\",\"applicationName\":\"testapp\"},\"timestamp\":0}{\"routing\":{\"yamas\":{\"namespaces\":[\"Vespa\"]}},\"application\":\"vespa.node\",\"metrics\":{\"net.out.bytes\":2.0303455E7,\"net.out.dropped\":13.0,\"net.in.dropped\":4.0,\"net.in.bytes\":1.949927E7,\"net.out.errors\":3.0,\"net.in.errors\":55.0},\"dimensions\":{\"app\":\"testapp.testinstance\",\"role\":\"tenants\",\"instanceName\":\"testinstance\",\"vespaVersion\":\"1.2.3\",\"clusterid\":\"clustId\",\"interface\":\"eth0\",\"parentHostname\":\"parent.host.name.yahoo.com\",\"flavor\":\"docker\",\"clustertype\":\"clustType\",\"tenantName\":\"tester\",\"zone\":\"dev.us-east-1\",\"host\":\"host1.test.yahoo.com\",\"state\":\"active\",\"applicationId\":\"tester.testapp.testinstance\",\"applicationName\":\"testapp\"},\"timestamp\":0}{\"routing\":{\"yamas\":{\"namespaces\":[\"Vespa\"]}},\"application\":\"vespa.node\",\"metrics\":{\"net.out.bytes\":5.4246745E7,\"net.out.dropped\":0.0,\"net.in.dropped\":0.0,\"net.in.bytes\":3245766.0,\"net.out.errors\":0.0,\"net.in.errors\":0.0},\"dimensions\":{\"app\":\"testapp.testinstance\",\"role\":\"tenants\",\"instanceName\":\"testinstance\",\"vespaVersion\":\"1.2.3\",\"clusterid\":\"clustId\",\"interface\":\"eth1\",\"parentHostname\":\"parent.host.name.yahoo.com\",\"flavor\":\"docker\",\"clustertype\":\"clustType\",\"tenantName\":\"tester\",\"zone\":\"dev.us-east-1\",\"host\":\"host1.test.yahoo.com\",\"state\":\"active\",\"applicationId\":\"tester.testapp.testinstance\",\"applicationName\":\"testapp\"},\"timestamp\":0}{\"routing\":{\"yamas\":{\"namespaces\":[\"Vespa\"]}},\"application\":\"host_life\",\"metrics\":{\"alive\":1.0,\"uptime\":1234.0},\"dimensions\":{\"app\":\"testapp.testinstance\",\"role\":\"tenants\",\"instanceName\":\"testinstance\",\"vespaVersion\":\"1.2.3\",\"clusterid\":\"clustId\",\"parentHostname\":\"parent.host.name.yahoo.com\",\"flavor\":\"docker\",\"clustertype\":\"clustType\",\"tenantName\":\"tester\",\"zone\":\"dev.us-east-1\",\"host\":\"host1.test.yahoo.com\",\"state\":\"active\",\"applicationId\":\"tester.testapp.testinstance\",\"applicationName\":\"testapp\"},\"timestamp\":0}{\"routing\":{\"yamas\":{\"namespaces\":[\"Vespa\"]}},\"application\":\"docker\",\"metrics\":{\"node.disk.limit\":2.68435456E11,\"node.disk.used\":4.2547019776E10,\"node.memory.usage\":1.073741824E9,\"node.cpu.busy.pct\":6.75,\"node.cpu.throttled_time\":4523.0,\"node.memory.limit\":4.294967296E9,\"node.alive\":1.0},\"dimensions\":{\"app\":\"testapp.testinstance\",\"role\":\"tenants\",\"instanceName\":\"testinstance\",\"vespaVersion\":\"1.2.3\",\"clusterid\":\"clustId\",\"parentHostname\":\"parent.host.name.yahoo.com\",\"flavor\":\"docker\",\"clustertype\":\"clustType\",\"tenantName\":\"tester\",\"zone\":\"dev.us-east-1\",\"host\":\"host1.test.yahoo.com\",\"state\":\"active\",\"applicationId\":\"tester.testapp.testinstance\",\"applicationName\":\"testapp\"},\"timestamp\":0}{\"routing\":{\"yamas\":{\"namespaces\":[\"Vespa\"]}},\"application\":\"docker\",\"metrics\":{\"node.net.in.dropped\":4.0,\"node.net.out.errors\":3.0,\"node.net.out.bytes\":2.0303455E7,\"node.net.in.bytes\":1.949927E7,\"node.net.out.dropped\":13.0,\"node.net.in.errors\":55.0},\"dimensions\":{\"app\":\"testapp.testinstance\",\"role\":\"tenants\",\"instanceName\":\"testinstance\",\"vespaVersion\":\"1.2.3\",\"clusterid\":\"clustId\",\"interface\":\"eth0\",\"parentHostname\":\"parent.host.name.yahoo.com\",\"flavor\":\"docker\",\"clustertype\":\"clustType\",\"tenantName\":\"tester\",\"zone\":\"dev.us-east-1\",\"host\":\"host1.test.yahoo.com\",\"state\":\"active\",\"applicationId\":\"tester.testapp.testinstance\",\"applicationName\":\"testapp\"},\"timestamp\":0}{\"routing\":{\"yamas\":{\"namespaces\":[\"Vespa\"]}},\"application\":\"docker\",\"metrics\":{\"node.net.in.dropped\":0.0,\"node.net.out.errors\":0.0,\"node.net.out.bytes\":5.4246745E7,\"node.net.in.bytes\":3245766.0,\"node.net.out.dropped\":0.0,\"node.net.in.errors\":0.0},\"dimensions\":{\"app\":\"testapp.testinstance\",\"role\":\"tenants\",\"instanceName\":\"testinstance\",\"vespaVersion\":\"1.2.3\",\"clusterid\":\"clustId\",\"interface\":\"eth1\",\"parentHostname\":\"parent.host.name.yahoo.com\",\"flavor\":\"docker\",\"clustertype\":\"clustType\",\"tenantName\":\"tester\",\"zone\":\"dev.us-east-1\",\"host\":\"host1.test.yahoo.com\",\"state\":\"active\",\"applicationId\":\"tester.testapp.testinstance\",\"applicationName\":\"testapp\"},\"timestamp\":0}'", arg);
+
assertEquals(expectedMetrics, actualMetrics);
}
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/noderepository/NodeRepositoryImplTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/noderepository/NodeRepositoryImplTest.java
index 15dce02f336..f5f98910694 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/noderepository/NodeRepositoryImplTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/noderepository/NodeRepositoryImplTest.java
@@ -83,14 +83,14 @@ public class NodeRepositoryImplTest {
}
@Test
- public void testGetContainersToRunAPi() throws IOException, InterruptedException {
+ public void testGetContainersToRunApi() throws IOException, InterruptedException {
waitForJdiscContainerToServe();
NodeRepository nodeRepositoryApi = new NodeRepositoryImpl(requestExecutor, port, "dockerhost4");
final List<ContainerNodeSpec> containersToRun = nodeRepositoryApi.getContainersToRun();
assertThat(containersToRun.size(), is(1));
final ContainerNodeSpec nodeSpec = containersToRun.get(0);
assertThat(nodeSpec.hostname, is("host4.yahoo.com"));
- assertThat(nodeSpec.wantedDockerImage.get(), is(new DockerImage("docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.0")));
+ assertThat(nodeSpec.wantedDockerImage.get(), is(new DockerImage("docker-registry.domain.tld:8080/dist/vespa:6.42.0")));
assertThat(nodeSpec.nodeState, is(Node.State.reserved));
assertThat(nodeSpec.wantedRestartGeneration.get(), is(0L));
assertThat(nodeSpec.currentRestartGeneration.get(), is(0L));
diff --git a/node-repository/src/main/config/node-repository.xml b/node-repository/src/main/config/node-repository.xml
index 90f47e0acc8..0f39b190ed1 100644
--- a/node-repository/src/main/config/node-repository.xml
+++ b/node-repository/src/main/config/node-repository.xml
@@ -14,3 +14,4 @@
</handler>
<preprocess:include file="node-flavors.xml" required="false" />
+<preprocess:include file="node-repository-config.xml" required="false" />
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java
index 14d5549d0b2..2dd632ce45a 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java
@@ -6,10 +6,12 @@ import com.google.inject.Inject;
import com.yahoo.collections.ListMap;
import com.yahoo.component.AbstractComponent;
import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.DockerImage;
import com.yahoo.config.provision.Flavor;
import com.yahoo.config.provision.NodeFlavors;
import com.yahoo.config.provision.NodeType;
import com.yahoo.config.provision.Zone;
+import com.yahoo.config.provisioning.NodeRepositoryConfig;
import com.yahoo.path.Path;
import com.yahoo.transaction.Mutex;
import com.yahoo.transaction.NestedTransaction;
@@ -73,26 +75,29 @@ public class NodeRepository extends AbstractComponent {
private final Clock clock;
private final NodeFlavors flavors;
private final NameResolver nameResolver;
+ private final DockerImage dockerImage;
/**
* Creates a node repository form a zookeeper provider.
* This will use the system time to make time-sensitive decisions
*/
@Inject
- public NodeRepository(NodeFlavors flavors, Curator curator, Zone zone) {
- this(flavors, curator, Clock.systemUTC(), zone, new DnsNameResolver());
+ public NodeRepository(NodeRepositoryConfig config, NodeFlavors flavors, Curator curator, Zone zone) {
+ this(flavors, curator, Clock.systemUTC(), zone, new DnsNameResolver(), new DockerImage(config.dockerImage()));
}
/**
* Creates a node repository form a zookeeper provider and a clock instance
* which will be used for time-sensitive decisions.
*/
- public NodeRepository(NodeFlavors flavors, Curator curator, Clock clock, Zone zone, NameResolver nameResolver) {
+ public NodeRepository(NodeFlavors flavors, Curator curator, Clock clock, Zone zone, NameResolver nameResolver,
+ DockerImage dockerImage) {
this.db = new CuratorDatabaseClient(flavors, curator, clock, zone);
this.curator = curator;
this.clock = clock;
this.flavors = flavors;
this.nameResolver = nameResolver;
+ this.dockerImage = dockerImage;
// read and write all nodes to make sure they are stored in the latest version of the serialized format
for (Node.State state : Node.State.values())
@@ -101,6 +106,9 @@ public class NodeRepository extends AbstractComponent {
/** Returns the curator database client used by this */
public CuratorDatabaseClient database() { return db; }
+
+ /** Returns the Docker image to use for nodes in this */
+ public DockerImage dockerImage() { return dockerImage; }
// ---------------- Query API ----------------------------------------------------------------
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirer.java
index d89a4761b5d..f1981ced48e 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirer.java
@@ -1,6 +1,7 @@
package com.yahoo.vespa.hosted.provision.maintenance;
import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.Deployer;
import com.yahoo.config.provision.Deployment;
import com.yahoo.config.provision.Flavor;
@@ -15,6 +16,7 @@ import com.yahoo.vespa.hosted.provision.provisioning.FlavorSpareChecker;
import java.time.Duration;
import java.util.Arrays;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -35,7 +37,7 @@ public class NodeRetirer extends Maintainer {
public static final FlavorSpareChecker.SpareNodesPolicy SPARE_NODES_POLICY = flavorSpareCount ->
flavorSpareCount.getNumReadyAmongReplacees() > 2;
- private static final long MAX_SIMULTANEOUS_RETIRES_PER_APPLICATION = 1;
+ private static final long MAX_SIMULTANEOUS_RETIRES_PER_CLUSTER = 1;
private static final Logger log = Logger.getLogger(NodeRetirer.class.getName());
private final Deployer deployer;
@@ -115,16 +117,19 @@ public class NodeRetirer extends Maintainer {
Map<Deployment, Set<Node>> nodesToRetireByDeployment = new HashMap<>();
for (ApplicationId applicationId : activeApplications) {
List<Node> applicationNodes = getNodesBelongingToApplication(allNodes, applicationId);
- Set<Node> retireableNodes = getRetireableNodesForApplication(applicationNodes);
- long numNodesAllowedToRetire = getNumberNodesAllowToRetireForApplication(applicationNodes, MAX_SIMULTANEOUS_RETIRES_PER_APPLICATION);
- if (retireableNodes.isEmpty() || numNodesAllowedToRetire == 0) continue;
+ Map<ClusterSpec, Set<Node>> retireableNodesByCluster = getRetireableNodesForApplication(applicationNodes).stream()
+ .collect(Collectors.groupingBy(
+ node -> node.allocation().get().membership().cluster(),
+ Collectors.toSet()));
+ if (retireableNodesByCluster.isEmpty()) continue;
Optional<Deployment> deployment = deployer.deployFromLocalActive(applicationId, Duration.ofMinutes(30));
if ( ! deployment.isPresent()) continue; // this will be done at another config server
- Set<Node> replaceableNodes = retireableNodes.stream()
- .filter(node -> flavorSpareChecker.canRetireAllocatedNodeWithFlavor(node.flavor()))
- .limit(numNodesAllowedToRetire)
+ Set<Node> replaceableNodes = retireableNodesByCluster.values().stream()
+ .flatMap(nodes -> nodes.stream()
+ .filter(node -> flavorSpareChecker.canRetireAllocatedNodeWithFlavor(node.flavor()))
+ .limit(getNumberNodesAllowToRetireForCluster(nodes, MAX_SIMULTANEOUS_RETIRES_PER_CLUSTER)))
.collect(Collectors.toSet());
if (! replaceableNodes.isEmpty()) nodesToRetireByDeployment.put(deployment.get(), replaceableNodes);
}
@@ -162,7 +167,7 @@ public class NodeRetirer extends Maintainer {
}));
}
- private List<Node> getNodesBelongingToApplication(List<Node> allNodes, ApplicationId applicationId) {
+ private List<Node> getNodesBelongingToApplication(Collection<Node> allNodes, ApplicationId applicationId) {
return allNodes.stream()
.filter(node -> node.allocation().isPresent())
.filter(node -> node.allocation().get().owner().equals(applicationId))
@@ -172,7 +177,7 @@ public class NodeRetirer extends Maintainer {
/**
* Returns a list of ApplicationIds sorted by number of active nodes the application has allocated to it
*/
- List<ApplicationId> getActiveApplicationIds(List<Node> nodes) {
+ List<ApplicationId> getActiveApplicationIds(Collection<Node> nodes) {
return nodes.stream()
.filter(node -> node.state() == Node.State.active)
.collect(Collectors.groupingBy(
@@ -188,7 +193,7 @@ public class NodeRetirer extends Maintainer {
* @param applicationNodes All the nodes allocated to an application
* @return Set of nodes that all should eventually be retired
*/
- Set<Node> getRetireableNodesForApplication(List<Node> applicationNodes) {
+ Set<Node> getRetireableNodesForApplication(Collection<Node> applicationNodes) {
return applicationNodes.stream()
.filter(node -> node.state() == Node.State.active)
.filter(node -> !node.status().wantToRetire())
@@ -197,18 +202,18 @@ public class NodeRetirer extends Maintainer {
}
/**
- * @param applicationNodes All the nodes allocated to an application
+ * @param clusterNodes All the nodes allocated to an application belonging to a single cluster
* @return number of nodes we can safely start retiring
*/
- long getNumberNodesAllowToRetireForApplication(List<Node> applicationNodes, long maxSimultaneousRetires) {
- long numNodesInWantToRetire = applicationNodes.stream()
+ long getNumberNodesAllowToRetireForCluster(Collection<Node> clusterNodes, long maxSimultaneousRetires) {
+ long numNodesInWantToRetire = clusterNodes.stream()
.filter(node -> node.status().wantToRetire())
.filter(node -> node.state() != Node.State.parked)
.count();
return Math.max(0, maxSimultaneousRetires - numNodesInWantToRetire);
}
- private Map<Flavor, Map<Node.State, Long>> getNumberOfNodesByFlavorByNodeState(List<Node> allNodes) {
+ private Map<Flavor, Map<Node.State, Long>> getNumberOfNodesByFlavorByNodeState(Collection<Node> allNodes) {
return allNodes.stream()
.collect(Collectors.groupingBy(
Node::flavor,
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Status.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Status.java
index e8a24b85714..c1d7ee0cae2 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Status.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Status.java
@@ -2,7 +2,6 @@
package com.yahoo.vespa.hosted.provision.node;
import com.yahoo.component.Version;
-import com.yahoo.config.provision.DockerImage;
import javax.annotation.concurrent.Immutable;
import java.util.Optional;
@@ -17,8 +16,6 @@ public class Status {
private final Generation reboot;
private final Optional<Version> vespaVersion;
- private final Optional<Version> hostedVersion; // TODO: Remove when all nodes have started using vespaVersion
- private final Optional<String> stateVersion; // TODO: Remove when all nodes have started using vespaVersion
private final int failCount;
private final Optional<HardwareFailureType> hardwareFailure;
private final boolean wantToRetire;
@@ -37,16 +34,12 @@ public class Status {
public Status(Generation generation,
Optional<Version> vespaVersion,
- Optional<Version> hostedVersion,
- Optional<String> stateVersion,
int failCount,
Optional<HardwareFailureType> hardwareFailure,
boolean wantToRetire,
boolean wantToDeprovision) {
this.reboot = generation;
this.vespaVersion = vespaVersion;
- this.hostedVersion = hostedVersion;
- this.stateVersion = stateVersion;
this.failCount = failCount;
this.hardwareFailure = hardwareFailure;
this.wantToRetire = wantToRetire;
@@ -54,63 +47,34 @@ public class Status {
}
/** Returns a copy of this with the reboot generation changed */
- public Status withReboot(Generation reboot) { return new Status(reboot, vespaVersion, hostedVersion, stateVersion, failCount, hardwareFailure, wantToRetire, wantToDeprovision); }
+ public Status withReboot(Generation reboot) { return new Status(reboot, vespaVersion, failCount, hardwareFailure, wantToRetire, wantToDeprovision); }
/** Returns the reboot generation of this node */
public Generation reboot() { return reboot; }
/** Returns a copy of this with the vespa version changed */
- public Status withVespaVersion(Version version) { return new Status(reboot, Optional.of(version), hostedVersion, stateVersion, failCount, hardwareFailure, wantToRetire, wantToDeprovision); }
+ public Status withVespaVersion(Version version) { return new Status(reboot, Optional.of(version), failCount, hardwareFailure, wantToRetire, wantToDeprovision); }
/** Returns the Vespa version installed on the node, if known */
public Optional<Version> vespaVersion() { return vespaVersion; }
- /** Returns a copy of this with the hosted version changed */
- public Status withHostedVersion(Version version) { return new Status(reboot, vespaVersion, Optional.of(version), stateVersion, failCount, hardwareFailure, wantToRetire, wantToDeprovision); }
+ public Status withIncreasedFailCount() { return new Status(reboot, vespaVersion, failCount + 1, hardwareFailure, wantToRetire, wantToDeprovision); }
- /** Returns the hosted version installed on the node, if known */
- public Optional<Version> hostedVersion() { return hostedVersion; }
+ public Status withDecreasedFailCount() { return new Status(reboot, vespaVersion, failCount - 1, hardwareFailure, wantToRetire, wantToDeprovision); }
- /** Returns a copy of this with the state version changed */
- public Status withStateVersion(String version) { return new Status(reboot, vespaVersion, hostedVersion, Optional.of(version), failCount, hardwareFailure, wantToRetire, wantToDeprovision); }
-
- /**
- * Returns the state version the node last successfully converged with.
- * The state version contains the version-specific parts in identifying state
- * files on dist, and is of the form HOSTEDVERSION.
- * It's also used to uniquely identify a hosted Vespa release.
- */
- public Optional<String> stateVersion() { return stateVersion; }
-
- /** Returns a copy of this with the docker image changed */
- public Status withDockerImage(String dockerImage) {
- Optional<Version> vespaVersion = Optional.of(dockerImage)
- .filter(image -> !image.isEmpty())
- .map(DockerImage::new)
- .map(DockerImage::tagAsVersion);
- return new Status(reboot, vespaVersion, hostedVersion, stateVersion, failCount, hardwareFailure, wantToRetire, wantToDeprovision);
- }
-
- /** Returns the current docker image the node is running, if known. */
- public Optional<String> dockerImage() { return vespaVersion.map(DockerImage.defaultImage::withTag).map(DockerImage::toString); }
-
- public Status withIncreasedFailCount() { return new Status(reboot, vespaVersion, hostedVersion, stateVersion, failCount + 1, hardwareFailure, wantToRetire, wantToDeprovision); }
-
- public Status withDecreasedFailCount() { return new Status(reboot, vespaVersion, hostedVersion, stateVersion, failCount - 1, hardwareFailure, wantToRetire, wantToDeprovision); }
-
- public Status setFailCount(Integer value) { return new Status(reboot, vespaVersion, hostedVersion, stateVersion, value, hardwareFailure, wantToRetire, wantToDeprovision); }
+ public Status setFailCount(Integer value) { return new Status(reboot, vespaVersion, value, hardwareFailure, wantToRetire, wantToDeprovision); }
/** Returns how many times this node has been moved to the failed state. */
public int failCount() { return failCount; }
- public Status withHardwareFailure(Optional<HardwareFailureType> hardwareFailure) { return new Status(reboot, vespaVersion, hostedVersion, stateVersion, failCount, hardwareFailure, wantToRetire, wantToDeprovision); }
+ public Status withHardwareFailure(Optional<HardwareFailureType> hardwareFailure) { return new Status(reboot, vespaVersion, failCount, hardwareFailure, wantToRetire, wantToDeprovision); }
/** Returns the type of the last hardware failure detected on this node, or empty if none */
public Optional<HardwareFailureType> hardwareFailure() { return hardwareFailure; }
/** Returns a copy of this with the want to retire flag changed */
public Status withWantToRetire(boolean wantToRetire) {
- return new Status(reboot, vespaVersion, hostedVersion, stateVersion, failCount, hardwareFailure, wantToRetire, wantToDeprovision);
+ return new Status(reboot, vespaVersion, failCount, hardwareFailure, wantToRetire, wantToDeprovision);
}
/**
@@ -121,19 +85,19 @@ public class Status {
return wantToRetire;
}
- /** Returns a copy of this with the want to deprovision flag changed */
+ /** Returns a copy of this with the want to de-provision flag changed */
public Status withWantToDeprovision(boolean wantToDeprovision) {
- return new Status(reboot, vespaVersion, hostedVersion, stateVersion, failCount, hardwareFailure, wantToRetire, wantToDeprovision);
+ return new Status(reboot, vespaVersion, failCount, hardwareFailure, wantToRetire, wantToDeprovision);
}
/**
- * Returns whether this node should be deprovisioned when possible.
+ * Returns whether this node should be de-provisioned when possible.
*/
public boolean wantToDeprovision() {
return wantToDeprovision;
}
/** Returns the initial status of a newly provisioned node */
- public static Status initial() { return new Status(Generation.inital(), Optional.empty(), Optional.empty(), Optional.empty(), 0, Optional.empty(), false, false); }
+ public static Status initial() { return new Status(Generation.inital(), Optional.empty(), 0, Optional.empty(), false, false); }
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java
index 582f97361b2..a090ee9f3e5 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java
@@ -30,8 +30,6 @@ import java.util.List;
import java.util.Optional;
import java.util.Set;
-import static com.yahoo.vespa.config.SlimeUtils.optionalString;
-
/**
* Serializes a node to/from JSON.
* Instances of this are multithread safe and can be reused
@@ -54,8 +52,6 @@ public class NodeSerializer {
private static final String rebootGenerationKey = "rebootGeneration";
private static final String currentRebootGenerationKey = "currentRebootGeneration";
private static final String vespaVersionKey = "vespaVersion";
- private static final String hostedVersionKey = "hostedVersion";
- private static final String stateVersionKey = "stateVersion";
private static final String failCountKey = "failCount";
private static final String hardwareFailureKey = "hardwareFailure";
private static final String nodeTypeKey = "type";
@@ -108,8 +104,6 @@ public class NodeSerializer {
object.setLong(rebootGenerationKey, node.status().reboot().wanted());
object.setLong(currentRebootGenerationKey, node.status().reboot().current());
node.status().vespaVersion().ifPresent(version -> object.setString(vespaVersionKey, version.toString()));
- node.status().hostedVersion().ifPresent(version -> object.setString(hostedVersionKey, version.toString()));
- node.status().stateVersion().ifPresent(version -> object.setString(stateVersionKey, version));
object.setLong(failCountKey, node.status().failCount());
node.status().hardwareFailure().ifPresent(failure -> object.setString(hardwareFailureKey, toString(failure)));
object.setBool(wantToRetireKey, node.status().wantToRetire());
@@ -170,8 +164,6 @@ public class NodeSerializer {
boolean wantToDeprovision = object.field(wantToDeprovisionKey).valid() && object.field(wantToDeprovisionKey).asBool();
return new Status(generationFromSlime(object, rebootGenerationKey, currentRebootGenerationKey),
versionFromSlime(object.field(vespaVersionKey)),
- versionFromSlime(object.field(hostedVersionKey)),
- optionalString(object.field(stateVersionKey)),
(int)object.field(failCountKey).asLong(),
hardwareFailureFromSlime(object.field(hardwareFailureKey)),
object.field(wantToRetireKey).asBool(),
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java
index d5c32286cc5..e7cc369d538 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java
@@ -61,9 +61,9 @@ public class CapacityPolicies {
* @throws IllegalArgumentException if only one node is requested
*/
private int ensureRedundancy(int nodeCount) {
- // TODO: Reactivate this check when we have sufficient capacity in ap-northeast
- // if (nodeCount == 1)
- // throw new IllegalArgumentException("Deployments to prod require at least 2 nodes per cluster for redundancy");
+ if (nodeCount == 1) {
+ throw new IllegalArgumentException("Deployments to prod require at least 2 nodes per cluster for redundancy");
+ }
return nodeCount;
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodePatcher.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodePatcher.java
index b410b0c8ead..d21ab77e403 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodePatcher.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodePatcher.java
@@ -2,6 +2,7 @@
package com.yahoo.vespa.hosted.provision.restapi.v2;
import com.yahoo.component.Version;
+import com.yahoo.config.provision.DockerImage;
import com.yahoo.io.IOUtils;
import com.yahoo.slime.Inspector;
import com.yahoo.slime.Type;
@@ -62,17 +63,22 @@ public class NodePatcher {
private Node applyField(String name, Inspector value) {
switch (name) {
case "convergedStateVersion" :
- return node.with(node.status().withStateVersion(asString(value)));
+ return node; // TODO: Ignored, can be removed when callers no longer include this field
case "currentRebootGeneration" :
return node.withCurrentRebootGeneration(asLong(value), clock.instant());
case "currentRestartGeneration" :
return patchCurrentRestartGeneration(asLong(value));
case "currentDockerImage" :
- return node.with(node.status().withDockerImage(asString(value)));
+ Version versionFromImage = Optional.of(asString(value))
+ .filter(s -> !s.isEmpty())
+ .map(DockerImage::new)
+ .map(DockerImage::tagAsVersion)
+ .orElse(Version.emptyVersion);
+ return node.with(node.status().withVespaVersion(versionFromImage));
case "currentVespaVersion" :
return node.with(node.status().withVespaVersion(Version.fromString(asString(value))));
case "currentHostedVersion" :
- return node.with(node.status().withHostedVersion(Version.fromString(asString(value))));
+ return node; // TODO: Ignored, can be removed when callers no longer include this field
case "failCount" :
return node.with(node.status().setFailCount(asLong(value).intValue()));
case "flavor" :
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodesResponse.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodesResponse.java
index 00bec80b758..3360ce3ffe1 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodesResponse.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodesResponse.java
@@ -1,7 +1,6 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.provision.restapi.v2;
-import com.yahoo.component.Version;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ClusterMembership;
import com.yahoo.config.provision.NodeType;
@@ -156,17 +155,20 @@ class NodesResponse extends HttpResponse {
toSlime(node.allocation().get().membership(), object.setObject("membership"));
object.setLong("restartGeneration", node.allocation().get().restartGeneration().wanted());
object.setLong("currentRestartGeneration", node.allocation().get().restartGeneration().current());
- object.setString("wantedDockerImage", node.allocation().get().membership().cluster().dockerImage());
+ object.setString("wantedDockerImage", nodeRepository.dockerImage().withTag(node.allocation().get().membership().cluster().vespaVersion()).asString());
object.setString("wantedVespaVersion", node.allocation().get().membership().cluster().vespaVersion().toFullString());
}
object.setLong("rebootGeneration", node.status().reboot().wanted());
object.setLong("currentRebootGeneration", node.status().reboot().current());
- node.status().vespaVersion().ifPresent(version -> {
- if (! version.equals(Version.emptyVersion)) object.setString("vespaVersion", version.toFullString());
- });
- node.status().hostedVersion().ifPresent(version -> object.setString("hostedVersion", version.toFullString()));
- node.status().dockerImage().ifPresent(image -> object.setString("currentDockerImage", image));
- node.status().stateVersion().ifPresent(version -> object.setString("convergedStateVersion", version));
+ node.status().vespaVersion()
+ .filter(version -> !version.isEmpty())
+ .ifPresent(version -> {
+ object.setString("vespaVersion", version.toFullString());
+ object.setString("currentDockerImage", nodeRepository.dockerImage().withTag(version).asString());
+ // TODO: Remove these when they are no longer read
+ object.setString("hostedVersion", version.toFullString());
+ object.setString("convergedStateVersion", version.toFullString());
+ });
object.setLong("failCount", node.status().failCount());
object.setBool("hardwareFailure", node.status().hardwareFailure().isPresent());
node.status().hardwareFailure().ifPresent(failure -> object.setString("hardwareFailureType", toString(failure)));
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockDeployer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockDeployer.java
index e46797240f2..d39b61f367d 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockDeployer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockDeployer.java
@@ -17,6 +17,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.stream.Collectors;
/**
* @author bratseth
@@ -87,11 +88,39 @@ public class MockDeployer implements Deployer {
public static class ApplicationContext {
private final ApplicationId id;
+ private final List<ClusterContext> clusterContexts;
+
+ public ApplicationContext(ApplicationId id, List<ClusterContext> clusterContexts) {
+ this.id = id;
+ this.clusterContexts = clusterContexts;
+ }
+
+ public ApplicationContext(ApplicationId id, ClusterSpec cluster, Capacity capacity, int groups) {
+ this(id, Collections.singletonList(new ClusterContext(id, cluster, capacity, groups)));
+ }
+
+ public ApplicationId id() { return id; }
+
+ /** Returns list of cluster specs of this application. */
+ public List<ClusterContext> clusterContexts() { return clusterContexts; }
+
+ private List<HostSpec> prepare(NodeRepositoryProvisioner provisioner) {
+ return clusterContexts.stream()
+ .map(clusterContext -> clusterContext.prepare(provisioner))
+ .flatMap(List::stream)
+ .collect(Collectors.toList());
+ }
+
+ }
+
+ public static class ClusterContext {
+
+ private final ApplicationId id;
private final ClusterSpec cluster;
private final Capacity capacity;
private final int groups;
- public ApplicationContext(ApplicationId id, ClusterSpec cluster, Capacity capacity, int groups) {
+ public ClusterContext(ApplicationId id, ClusterSpec cluster, Capacity capacity, int groups) {
this.id = id;
this.cluster = cluster;
this.capacity = capacity;
@@ -100,7 +129,6 @@ public class MockDeployer implements Deployer {
public ApplicationId id() { return id; }
- /** Returns the spec of the cluster of this application. Only a single cluster per application is supported */
public ClusterSpec cluster() { return cluster; }
private List<HostSpec> prepare(NodeRepositoryProvisioner provisioner) {
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java
index adfccd1f874..12b687c7646 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java
@@ -6,17 +6,17 @@ import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ApplicationName;
import com.yahoo.config.provision.Capacity;
import com.yahoo.config.provision.ClusterSpec;
+import com.yahoo.config.provision.DockerImage;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.InstanceName;
+import com.yahoo.config.provision.NodeFlavors;
import com.yahoo.config.provision.NodeType;
import com.yahoo.config.provision.TenantName;
import com.yahoo.config.provision.Zone;
import com.yahoo.transaction.NestedTransaction;
-import com.yahoo.vespa.curator.Curator;
import com.yahoo.vespa.curator.mock.MockCurator;
import com.yahoo.vespa.hosted.provision.Node;
import com.yahoo.vespa.hosted.provision.NodeRepository;
-import com.yahoo.config.provision.NodeFlavors;
import com.yahoo.vespa.hosted.provision.node.Agent;
import com.yahoo.vespa.hosted.provision.node.Status;
import com.yahoo.vespa.hosted.provision.provisioning.NodeRepositoryProvisioner;
@@ -45,7 +45,7 @@ public class MockNodeRepository extends NodeRepository {
*/
public MockNodeRepository(MockCurator curator, NodeFlavors flavors) throws Exception {
super(flavors, curator, Clock.fixed(Instant.ofEpochMilli(123), ZoneId.of("Z")), Zone.defaultZone(),
- new MockNameResolver().mockAnyLookup());
+ new MockNameResolver().mockAnyLookup(), new DockerImage("docker-registry.domain.tld:8080/dist/vespa"));
this.flavors = flavors;
curator.setConnectionSpec("cfg1:1234,cfg2:1234,cfg3:1234");
populate();
@@ -66,11 +66,11 @@ public class MockNodeRepository extends NodeRepository {
// TODO: Use docker flavor
Node node4 = createNode("node4", "host4.yahoo.com", ipAddresses, Optional.of("dockerhost4"), flavors.getFlavorOrThrow("default"), NodeType.tenant);
- node4 = node4.with(node4.status().withDockerImage("image-12:6.41.0"));
+ node4 = node4.with(node4.status().withVespaVersion(new Version("6.41.0")));
nodes.add(node4);
Node node5 = createNode("node5", "host5.yahoo.com", ipAddresses, Optional.of("parent1.yahoo.com"), flavors.getFlavorOrThrow("default"), NodeType.tenant);
- nodes.add(node5.with(node5.status().withDockerImage("image-123:1.2.3").withVespaVersion(new Version("1.2.3"))));
+ nodes.add(node5.with(node5.status().withVespaVersion(new Version("1.2.3"))));
nodes.add(createNode("node6", "host6.yahoo.com", ipAddresses, Optional.empty(), flavors.getFlavorOrThrow("default"), NodeType.tenant));
nodes.add(createNode("node7", "host7.yahoo.com", ipAddresses, Optional.empty(), flavors.getFlavorOrThrow("default"), NodeType.tenant));
@@ -78,9 +78,7 @@ public class MockNodeRepository extends NodeRepository {
Node node10 = createNode("node10", "host10.yahoo.com", ipAddresses, Optional.of("parent1.yahoo.com"), flavors.getFlavorOrThrow("default"), NodeType.tenant);
Status node10newStatus = node10.status();
node10newStatus = node10newStatus
- .withVespaVersion(Version.fromString("5.104.142"))
- .withHostedVersion(Version.fromString("2.1.2408"))
- .withStateVersion("5.104.142-2.1.2408");
+ .withVespaVersion(Version.fromString("5.104.142"));
node10 = node10.with(node10newStatus);
nodes.add(node10);
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/ServiceMonitorStub.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/ServiceMonitorStub.java
index 983f81be126..e6a50cbbc64 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/ServiceMonitorStub.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/ServiceMonitorStub.java
@@ -77,7 +77,7 @@ public class ServiceMonitorStub implements ServiceMonitor {
getHostStatus(node.hostname())));
}
Set<ServiceCluster<ServiceMonitorStatus>> serviceClusters = new HashSet<>();
- serviceClusters.add(new ServiceCluster<>(new ClusterId(app.getValue().cluster().id().value()),
+ serviceClusters.add(new ServiceCluster<>(new ClusterId(app.getValue().clusterContexts().get(0).cluster().id().value()),
new ServiceType("serviceType"),
serviceInstances));
TenantId tenantId = new TenantId(app.getKey().tenant().value());
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/NodeRepositoryTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/NodeRepositoryTester.java
index 66e580d9039..8563d189658 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/NodeRepositoryTester.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/NodeRepositoryTester.java
@@ -1,12 +1,13 @@
package com.yahoo.vespa.hosted.provision;
+import com.yahoo.config.provision.DockerImage;
+import com.yahoo.config.provision.Flavor;
+import com.yahoo.config.provision.NodeFlavors;
import com.yahoo.config.provision.NodeType;
import com.yahoo.config.provision.Zone;
-import com.yahoo.test.ManualClock;
import com.yahoo.config.provisioning.FlavorsConfig;
+import com.yahoo.test.ManualClock;
import com.yahoo.vespa.curator.mock.MockCurator;
-import com.yahoo.config.provision.Flavor;
-import com.yahoo.config.provision.NodeFlavors;
import com.yahoo.vespa.hosted.provision.provisioning.FlavorConfigBuilder;
import com.yahoo.vespa.hosted.provision.testutils.MockNameResolver;
@@ -32,7 +33,8 @@ public class NodeRepositoryTester {
curator = new MockCurator();
curator.setConnectionSpec("server1:1234,server2:5678");
nodeRepository = new NodeRepository(nodeFlavors, curator, clock, Zone.defaultZone(),
- new MockNameResolver().mockAnyLookup());
+ new MockNameResolver().mockAnyLookup(),
+ new DockerImage("docker-registry.domain.tld:8080/dist/vespa"));
}
public NodeRepository nodeRepository() { return nodeRepository; }
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/FailedExpirerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/FailedExpirerTest.java
index bcb85af6f9c..35f83fffb03 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/FailedExpirerTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/FailedExpirerTest.java
@@ -6,9 +6,11 @@ import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ApplicationName;
import com.yahoo.config.provision.Capacity;
import com.yahoo.config.provision.ClusterSpec;
+import com.yahoo.config.provision.DockerImage;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.Flavor;
import com.yahoo.config.provision.InstanceName;
+import com.yahoo.config.provision.NodeFlavors;
import com.yahoo.config.provision.NodeType;
import com.yahoo.config.provision.RegionName;
import com.yahoo.config.provision.SystemName;
@@ -21,12 +23,11 @@ import com.yahoo.vespa.curator.mock.MockCurator;
import com.yahoo.vespa.curator.transaction.CuratorTransaction;
import com.yahoo.vespa.hosted.provision.Node;
import com.yahoo.vespa.hosted.provision.NodeRepository;
-import com.yahoo.config.provision.NodeFlavors;
import com.yahoo.vespa.hosted.provision.node.Agent;
import com.yahoo.vespa.hosted.provision.node.Status;
+import com.yahoo.vespa.hosted.provision.provisioning.FlavorConfigBuilder;
import com.yahoo.vespa.hosted.provision.provisioning.NodeRepositoryProvisioner;
import com.yahoo.vespa.hosted.provision.provisioning.ProvisioningTester;
-import com.yahoo.vespa.hosted.provision.provisioning.FlavorConfigBuilder;
import com.yahoo.vespa.hosted.provision.testutils.MockNameResolver;
import org.junit.Test;
@@ -84,7 +85,8 @@ public class FailedExpirerTest {
ManualClock clock = new ManualClock();
NodeFlavors nodeFlavors = FlavorConfigBuilder.createDummies("default", flavorName);
NodeRepository nodeRepository = new NodeRepository(nodeFlavors, curator, clock, Zone.defaultZone(),
- new MockNameResolver().mockAnyLookup());
+ new MockNameResolver().mockAnyLookup(),
+ new DockerImage("docker-registry.domain.tld:8080/dist/vespa"));
NodeRepositoryProvisioner provisioner = new NodeRepositoryProvisioner(nodeRepository, nodeFlavors, Zone.defaultZone(), clock, (x,y) -> {});
Flavor defaultFlavor = nodeFlavors.getFlavorOrThrow("default");
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/InactiveAndFailedExpirerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/InactiveAndFailedExpirerTest.java
index 47055af075e..edc2c637827 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/InactiveAndFailedExpirerTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/InactiveAndFailedExpirerTest.java
@@ -77,18 +77,18 @@ public class InactiveAndFailedExpirerTest {
@Test
public void reboot_generation_is_increased_when_node_moves_to_dirty() {
ProvisioningTester tester = new ProvisioningTester(new Zone(Environment.prod, RegionName.from("us-east")));
- List<Node> nodes = tester.makeReadyNodes(1, "default");
+ List<Node> nodes = tester.makeReadyNodes(2, "default");
// Allocate and deallocate a single node
- ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.content,
+ ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.content,
ClusterSpec.Id.from("test"),
Version.fromString("6.42"));
- tester.prepare(applicationId, cluster, Capacity.fromNodeCount(1), 1);
+ tester.prepare(applicationId, cluster, Capacity.fromNodeCount(2), 1);
tester.activate(applicationId, ProvisioningTester.toHostSpecs(nodes));
- assertEquals(1, tester.getNodes(applicationId, Node.State.active).size());
+ assertEquals(2, tester.getNodes(applicationId, Node.State.active).size());
tester.deactivate(applicationId);
List<Node> inactiveNodes = tester.getNodes(applicationId, Node.State.inactive).asList();
- assertEquals(1, inactiveNodes.size());
+ assertEquals(2, inactiveNodes.size());
// Check reboot generation before node is moved. New nodes transition from provisioned to dirty, so their
// wanted reboot generation will always be 1.
@@ -99,7 +99,7 @@ public class InactiveAndFailedExpirerTest {
tester.advanceTime(Duration.ofMinutes(14));
new InactiveExpirer(tester.nodeRepository(), tester.clock(), Duration.ofMinutes(10), new JobControl(tester.nodeRepository().database())).run();
List<Node> dirty = tester.nodeRepository().getNodes(Node.State.dirty);
- assertEquals(1, dirty.size());
+ assertEquals(2, dirty.size());
// Reboot generation is increased
assertEquals(wantedRebootGeneration + 1, dirty.get(0).status().reboot().wanted());
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MaintenanceTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MaintenanceTester.java
index 573e14fa4f9..d0558296e7c 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MaintenanceTester.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MaintenanceTester.java
@@ -1,5 +1,6 @@
package com.yahoo.vespa.hosted.provision.maintenance;
+import com.yahoo.config.provision.DockerImage;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.NodeFlavors;
import com.yahoo.config.provision.NodeType;
@@ -31,7 +32,8 @@ public class MaintenanceTester {
private final Zone zone = new Zone(Environment.prod, RegionName.from("us-east"));
private final NodeFlavors nodeFlavors = FlavorConfigBuilder.createDummies("default");
public final NodeRepository nodeRepository = new NodeRepository(nodeFlavors, curator, clock, zone,
- new MockNameResolver().mockAnyLookup());
+ new MockNameResolver().mockAnyLookup(),
+ new DockerImage("docker-registry.domain.tld:8080/dist/vespa"));
public NodeRepository nodeRepository() { return nodeRepository; }
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailTester.java
index ec85b72b61a..de2c68aa43e 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailTester.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailTester.java
@@ -5,6 +5,7 @@ import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ApplicationName;
import com.yahoo.config.provision.Capacity;
import com.yahoo.config.provision.ClusterSpec;
+import com.yahoo.config.provision.DockerImage;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.Flavor;
import com.yahoo.config.provision.HostSpec;
@@ -21,8 +22,8 @@ import com.yahoo.vespa.curator.mock.MockCurator;
import com.yahoo.vespa.curator.transaction.CuratorTransaction;
import com.yahoo.vespa.hosted.provision.Node;
import com.yahoo.vespa.hosted.provision.NodeRepository;
-import com.yahoo.vespa.hosted.provision.provisioning.NodeRepositoryProvisioner;
import com.yahoo.vespa.hosted.provision.provisioning.FlavorConfigBuilder;
+import com.yahoo.vespa.hosted.provision.provisioning.NodeRepositoryProvisioner;
import com.yahoo.vespa.hosted.provision.testutils.MockDeployer;
import com.yahoo.vespa.hosted.provision.testutils.MockNameResolver;
import com.yahoo.vespa.hosted.provision.testutils.OrchestratorMock;
@@ -69,7 +70,8 @@ public class NodeFailTester {
private NodeFailTester() {
clock = new ManualClock();
curator = new MockCurator();
- nodeRepository = new NodeRepository(nodeFlavors, curator, clock, zone, new MockNameResolver().mockAnyLookup());
+ nodeRepository = new NodeRepository(nodeFlavors, curator, clock, zone, new MockNameResolver().mockAnyLookup(),
+ new DockerImage("docker-registry.domain.tld:8080/dist/vespa"));
provisioner = new NodeRepositoryProvisioner(nodeRepository, nodeFlavors, zone);
hostLivenessTracker = new TestHostLivenessTracker(clock);
orchestrator = new OrchestratorMock();
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirerTest.java
index f71d9b75f78..b19d9360e86 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirerTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirerTest.java
@@ -34,24 +34,25 @@ public class NodeRetirerTest {
retirer = tester.makeNodeRetirer(policy);
tester.createReadyNodesByFlavor(21, 42, 27, 15, 8);
- tester.deployApp("vespa", "calendar", 3, 7);
- tester.deployApp("vespa", "notes", 0, 3);
- tester.deployApp("sports", "results", 0, 6);
- tester.deployApp("search", "images", 3, 4);
- tester.deployApp("search", "videos", 2, 2);
+ tester.deployApp("vespa", "calendar", new int[]{3}, new int[]{7});
+ tester.deployApp("vespa", "notes", new int[]{0}, new int[]{3});
+ tester.deployApp("sports", "results", new int[]{0}, new int[]{6});
+ tester.deployApp("search", "images", new int[]{3}, new int[]{4});
+ tester.deployApp("search", "videos", new int[]{2}, new int[]{2});
+ tester.deployApp("tester", "my-app", new int[]{1, 2}, new int[]{4, 6});
}
@Test
public void testRetireUnallocated() {
- tester.assertCountsForStateByFlavor(Node.State.ready, 12, 42, 25, 4, 8);
- tester.setNumberAllowedUnallocatedRetirementsPerFlavor(6, 30, 20, 2, 4);
+ tester.assertCountsForStateByFlavor(Node.State.ready, 12, 38, 19, 4, 8);
+ tester.setNumberAllowedUnallocatedRetirementsPerFlavor(6, 30, 15, 2, 4);
assertFalse(retirer.retireUnallocated());
- tester.assertCountsForStateByFlavor(Node.State.parked, 6, 30, 20, 2, 4);
+ tester.assertCountsForStateByFlavor(Node.State.parked, 6, 30, 15, 2, 4);
- tester.assertCountsForStateByFlavor(Node.State.ready, 6, 12, 5, 2, 4);
+ tester.assertCountsForStateByFlavor(Node.State.ready, 6, 8, 4, 2, 4);
tester.setNumberAllowedUnallocatedRetirementsPerFlavor(10, 20, 5, 5, 4);
assertTrue(retirer.retireUnallocated());
- tester.assertCountsForStateByFlavor(Node.State.parked, 12, 42, 25, 4, 8);
+ tester.assertCountsForStateByFlavor(Node.State.parked, 12, 38, 19, 4, 8);
tester.nodeRepository.getNodes().forEach(node ->
assertEquals(node.status().wantToDeprovision(), node.state() == Node.State.parked));
@@ -63,25 +64,27 @@ public class NodeRetirerTest {
tester.nodeRepository.getNodes(Node.State.ready)
.forEach(node -> tester.nodeRepository.write(node.withIpAddresses(Collections.singleton("::2"))));
- tester.assertCountsForStateByFlavor(Node.State.active, 9, -1, 2, 11, -1);
+ tester.assertCountsForStateByFlavor(Node.State.active, 9, 4, 8, 11, -1);
- tester.setNumberAllowedAllocatedRetirementsPerFlavor(3, 2, 3, 2);
+ tester.setNumberAllowedAllocatedRetirementsPerFlavor(3, 2, 4, 2);
retirer.retireAllocated();
- tester.assertParkedCountsByApplication(-1, -1, -1, -1, -1); // Nodes should be in retired, but not yet parked
+ tester.assertParkedCountsByApplication(-1, -1, -1, -1, -1, -1); // Nodes should be in retired, but not yet parked
tester.iterateMaintainers();
- tester.assertParkedCountsByApplication(1, 1, 1, 1, 1);
+ tester.assertParkedCountsByApplication(1, 1, 1, 1, 1, 2);
- // We can only retire 1 more of flavor 0 and 1 more of flavor 2, app 3 is the largest that is on flavor 0
- // and app 5 is the only one on flavor 2
+ // We can retire 1 more of flavor-0, 1 more of flavor-1, 2 more of flavor-2:
+ // app 6 has the most nodes, so it gets to retire flavor-1 and flavor-2
+ // app 3 is the largest that is on flavor-0, so it gets the last node
+ // app 5 is gets the last node with flavor-2
retirer.retireAllocated();
tester.iterateMaintainers();
- tester.assertParkedCountsByApplication(1, 1, 2, 1, 2);
+ tester.assertParkedCountsByApplication(1, 1, 2, 1, 2, 4);
// No more retirements are possible
retirer.retireAllocated();
tester.iterateMaintainers();
- tester.assertParkedCountsByApplication(1, 1, 2, 1, 2);
+ tester.assertParkedCountsByApplication(1, 1, 2, 1, 2, 4);
tester.nodeRepository.getNodes().forEach(node ->
assertEquals(node.status().wantToDeprovision(), node.state() == Node.State.parked));
@@ -90,7 +93,7 @@ public class NodeRetirerTest {
@Test
public void testGetActiveApplicationIds() {
List<String> expectedOrder = Arrays.asList(
- "vespa.calendar", "sports.results", "search.images", "vespa.notes", "search.videos");
+ "tester.my-app", "vespa.calendar", "sports.results", "search.images", "vespa.notes", "search.videos");
List<String> actualOrder = retirer.getActiveApplicationIds(tester.nodeRepository.getNodes()).stream()
.map(applicationId -> applicationId.toShortString().replace(":default", ""))
.collect(Collectors.toList());
@@ -121,21 +124,21 @@ public class NodeRetirerTest {
}
@Test
- public void testGetNumberNodesAllowToRetireForApplication() {
+ public void testGetNumberNodesAllowToRetireForCluster() {
ApplicationId app = new ApplicationId.Builder().tenant("vespa").applicationName("calendar").build();
- long actualAllActive = retirer.getNumberNodesAllowToRetireForApplication(tester.nodeRepository.getNodes(app), 2);
+ long actualAllActive = retirer.getNumberNodesAllowToRetireForCluster(tester.nodeRepository.getNodes(app), 2);
assertEquals(2, actualAllActive);
// Lets put 3 random nodes in wantToRetire
List<Node> nodesToRetire = tester.nodeRepository.getNodes(app).stream().limit(3).collect(Collectors.toList());
nodesToRetire.forEach(node -> tester.nodeRepository.write(node.with(node.status().withWantToRetire(true))));
- long actualOneWantToRetire = retirer.getNumberNodesAllowToRetireForApplication(tester.nodeRepository.getNodes(app), 2);
+ long actualOneWantToRetire = retirer.getNumberNodesAllowToRetireForCluster(tester.nodeRepository.getNodes(app), 2);
assertEquals(0, actualOneWantToRetire);
// Now 2 of those finish retiring and go to parked
nodesToRetire.stream().limit(2).forEach(node ->
tester.nodeRepository.park(node.hostname(), Agent.system, "Parked for unit testing"));
- long actualOneRetired = retirer.getNumberNodesAllowToRetireForApplication(tester.nodeRepository.getNodes(app), 2);
+ long actualOneRetired = retirer.getNumberNodesAllowToRetireForCluster(tester.nodeRepository.getNodes(app), 2);
assertEquals(1, actualOneRetired);
}
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirerTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirerTester.java
index 7622cbb1714..54690cda6a5 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirerTester.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRetirerTester.java
@@ -5,18 +5,16 @@ import com.yahoo.component.Version;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.Capacity;
import com.yahoo.config.provision.ClusterSpec;
+import com.yahoo.config.provision.DockerImage;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.Flavor;
-import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.NodeFlavors;
import com.yahoo.config.provision.NodeType;
import com.yahoo.config.provision.RegionName;
import com.yahoo.config.provision.Zone;
import com.yahoo.test.ManualClock;
-import com.yahoo.transaction.NestedTransaction;
import com.yahoo.vespa.curator.Curator;
import com.yahoo.vespa.curator.mock.MockCurator;
-import com.yahoo.vespa.curator.transaction.CuratorTransaction;
import com.yahoo.vespa.hosted.provision.Node;
import com.yahoo.vespa.hosted.provision.NodeRepository;
import com.yahoo.vespa.hosted.provision.maintenance.retire.RetirementPolicy;
@@ -54,11 +52,9 @@ public class NodeRetirerTester {
public final ManualClock clock = new ManualClock();
public final NodeRepository nodeRepository;
private final FlavorSpareChecker flavorSpareChecker = mock(FlavorSpareChecker.class);
- private final Curator curator = new MockCurator();
private final MockDeployer deployer;
private final JobControl jobControl;
private final List<Flavor> flavors;
- private final NodeRepositoryProvisioner provisioner;
// Use LinkedHashMap to keep order in which applications were deployed
private final Map<ApplicationId, MockDeployer.ApplicationContext> apps = new LinkedHashMap<>();
@@ -68,9 +64,11 @@ public class NodeRetirerTester {
private int nextNodeId = 0;
NodeRetirerTester(NodeFlavors nodeFlavors) {
- nodeRepository = new NodeRepository(nodeFlavors, curator, clock, zone, new MockNameResolver().mockAnyLookup());
+ Curator curator = new MockCurator();
+ nodeRepository = new NodeRepository(nodeFlavors, curator, clock, zone, new MockNameResolver().mockAnyLookup(),
+ new DockerImage("docker-registry.domain.tld:8080/dist/vespa"));
jobControl = new JobControl(nodeRepository.database());
- provisioner = new NodeRepositoryProvisioner(nodeRepository, nodeFlavors, zone);
+ NodeRepositoryProvisioner provisioner = new NodeRepositoryProvisioner(nodeRepository, nodeFlavors, zone);
deployer = new MockDeployer(provisioner, apps);
flavors = nodeFlavors.getFlavors().stream().sorted(Comparator.comparing(Flavor::name)).collect(Collectors.toList());
}
@@ -95,15 +93,19 @@ public class NodeRetirerTester {
nodeRepository.setReady(nodes);
}
- void deployApp(String tenantName, String applicationName, int flavorId, int numNodes) {
- Flavor flavor = flavors.get(flavorId);
+ void deployApp(String tenantName, String applicationName, int[] flavorIds, int[] numNodes) {
+ final ApplicationId applicationId = ApplicationId.from(tenantName, applicationName, "default");
+ final List<MockDeployer.ClusterContext> clusterContexts = new ArrayList<>();
- ApplicationId applicationId = ApplicationId.from(tenantName, applicationName, "default");
- ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("test"), Version.fromString("6.99"));
- Capacity capacity = Capacity.fromNodeCount(numNodes, flavor.name());
- apps.put(applicationId, new MockDeployer.ApplicationContext(applicationId, cluster, capacity, 1));
+ for (int i = 0; i < flavorIds.length; i++) {
+ Flavor flavor = flavors.get(flavorIds[i]);
+ ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("cluster-" + i), Version.fromString("6.99"));
+ Capacity capacity = Capacity.fromNodeCount(numNodes[i], flavor.name());
+ clusterContexts.add(new MockDeployer.ClusterContext(applicationId, cluster, capacity, 1));
+ }
- activate(applicationId, cluster, capacity);
+ apps.put(applicationId, new MockDeployer.ApplicationContext(applicationId, clusterContexts));
+ deployer.deployFromLocalActive(applicationId, Duration.ZERO).get().activate();
}
void iterateMaintainers() {
@@ -119,13 +121,6 @@ public class NodeRetirerTester {
inactiveExpirer.maintain();
}
- private void activate(ApplicationId applicationId, ClusterSpec cluster, Capacity capacity) {
- List<HostSpec> hosts = provisioner.prepare(applicationId, cluster, capacity, 1, null);
- NestedTransaction transaction = new NestedTransaction().add(new CuratorTransaction(curator));
- provisioner.activate(transaction, applicationId, hosts);
- transaction.commit();
- }
-
void setNumberAllowedUnallocatedRetirementsPerFlavor(int... numAllowed) {
for (int i = 0; i < numAllowed.length; i++) {
Boolean[] responses = new Boolean[numAllowed[i]];
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/OperatorChangeApplicationMaintainerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/OperatorChangeApplicationMaintainerTest.java
index 3849c69b4e1..f2d31fb3b87 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/OperatorChangeApplicationMaintainerTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/OperatorChangeApplicationMaintainerTest.java
@@ -6,6 +6,7 @@ import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ApplicationName;
import com.yahoo.config.provision.Capacity;
import com.yahoo.config.provision.ClusterSpec;
+import com.yahoo.config.provision.DockerImage;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.InstanceName;
@@ -23,8 +24,8 @@ import com.yahoo.vespa.hosted.provision.Node;
import com.yahoo.vespa.hosted.provision.NodeList;
import com.yahoo.vespa.hosted.provision.NodeRepository;
import com.yahoo.vespa.hosted.provision.node.Agent;
-import com.yahoo.vespa.hosted.provision.provisioning.NodeRepositoryProvisioner;
import com.yahoo.vespa.hosted.provision.provisioning.FlavorConfigBuilder;
+import com.yahoo.vespa.hosted.provision.provisioning.NodeRepositoryProvisioner;
import com.yahoo.vespa.hosted.provision.testutils.MockDeployer;
import com.yahoo.vespa.hosted.provision.testutils.MockNameResolver;
import org.junit.Test;
@@ -54,7 +55,8 @@ public class OperatorChangeApplicationMaintainerTest {
Curator curator = new MockCurator();
Zone zone = new Zone(Environment.prod, RegionName.from("us-east"));
this.nodeRepository = new NodeRepository(nodeFlavors, curator, clock, zone,
- new MockNameResolver().mockAnyLookup());
+ new MockNameResolver().mockAnyLookup(),
+ new DockerImage("docker-registry.domain.tld:8080/dist/vespa"));
this.fixture = new Fixture(zone, nodeRepository, nodeFlavors, curator);
createReadyNodes(15, nodeRepository, nodeFlavors);
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainerTest.java
index 8940bb94736..ef45831bdc3 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainerTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainerTest.java
@@ -8,6 +8,7 @@ import com.yahoo.config.provision.Capacity;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.Deployer;
import com.yahoo.config.provision.Deployment;
+import com.yahoo.config.provision.DockerImage;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.InstanceName;
@@ -25,8 +26,8 @@ import com.yahoo.vespa.hosted.provision.Node;
import com.yahoo.vespa.hosted.provision.NodeList;
import com.yahoo.vespa.hosted.provision.NodeRepository;
import com.yahoo.vespa.hosted.provision.node.Agent;
-import com.yahoo.vespa.hosted.provision.provisioning.NodeRepositoryProvisioner;
import com.yahoo.vespa.hosted.provision.provisioning.FlavorConfigBuilder;
+import com.yahoo.vespa.hosted.provision.provisioning.NodeRepositoryProvisioner;
import com.yahoo.vespa.hosted.provision.testutils.MockDeployer;
import com.yahoo.vespa.hosted.provision.testutils.MockNameResolver;
import org.junit.Before;
@@ -56,7 +57,8 @@ public class PeriodicApplicationMaintainerTest {
Curator curator = new MockCurator();
Zone zone = new Zone(Environment.prod, RegionName.from("us-east"));
this.nodeRepository = new NodeRepository(nodeFlavors, curator, new ManualClock(), zone,
- new MockNameResolver().mockAnyLookup());
+ new MockNameResolver().mockAnyLookup(),
+ new DockerImage("docker-registry.domain.tld:8080/dist/vespa"));
this.fixture = new Fixture(zone, nodeRepository, nodeFlavors, curator);
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ReservationExpirerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ReservationExpirerTest.java
index e918681faee..0d21650343f 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ReservationExpirerTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ReservationExpirerTest.java
@@ -5,6 +5,8 @@ import com.yahoo.component.Version;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.Capacity;
import com.yahoo.config.provision.ClusterSpec;
+import com.yahoo.config.provision.DockerImage;
+import com.yahoo.config.provision.NodeFlavors;
import com.yahoo.config.provision.NodeType;
import com.yahoo.config.provision.Zone;
import com.yahoo.test.ManualClock;
@@ -12,9 +14,8 @@ import com.yahoo.vespa.curator.Curator;
import com.yahoo.vespa.curator.mock.MockCurator;
import com.yahoo.vespa.hosted.provision.Node;
import com.yahoo.vespa.hosted.provision.NodeRepository;
-import com.yahoo.config.provision.NodeFlavors;
-import com.yahoo.vespa.hosted.provision.provisioning.NodeRepositoryProvisioner;
import com.yahoo.vespa.hosted.provision.provisioning.FlavorConfigBuilder;
+import com.yahoo.vespa.hosted.provision.provisioning.NodeRepositoryProvisioner;
import com.yahoo.vespa.hosted.provision.testutils.MockNameResolver;
import org.junit.Test;
@@ -39,7 +40,8 @@ public class ReservationExpirerTest {
ManualClock clock = new ManualClock();
NodeFlavors flavors = FlavorConfigBuilder.createDummies("default");
NodeRepository nodeRepository = new NodeRepository(flavors, curator, clock, Zone.defaultZone(),
- new MockNameResolver().mockAnyLookup());
+ new MockNameResolver().mockAnyLookup(),
+ new DockerImage("docker-registry.domain.tld:8080/dist/vespa"));
NodeRepositoryProvisioner provisioner = new NodeRepositoryProvisioner(nodeRepository, flavors, Zone.defaultZone(), clock, (x,y) -> {});
List<Node> nodes = new ArrayList<>(2);
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RetiredExpirerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RetiredExpirerTest.java
index 7f388057f6e..8c5a1a225cf 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RetiredExpirerTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RetiredExpirerTest.java
@@ -6,6 +6,7 @@ import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ApplicationName;
import com.yahoo.config.provision.Capacity;
import com.yahoo.config.provision.ClusterSpec;
+import com.yahoo.config.provision.DockerImage;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.InstanceName;
@@ -21,8 +22,8 @@ import com.yahoo.vespa.curator.mock.MockCurator;
import com.yahoo.vespa.curator.transaction.CuratorTransaction;
import com.yahoo.vespa.hosted.provision.Node;
import com.yahoo.vespa.hosted.provision.NodeRepository;
-import com.yahoo.vespa.hosted.provision.provisioning.NodeRepositoryProvisioner;
import com.yahoo.vespa.hosted.provision.provisioning.FlavorConfigBuilder;
+import com.yahoo.vespa.hosted.provision.provisioning.NodeRepositoryProvisioner;
import com.yahoo.vespa.hosted.provision.testutils.MockDeployer;
import com.yahoo.vespa.hosted.provision.testutils.MockNameResolver;
import com.yahoo.vespa.orchestrator.OrchestrationException;
@@ -56,7 +57,8 @@ public class RetiredExpirerTest {
Zone zone = new Zone(Environment.prod, RegionName.from("us-east"));
NodeFlavors nodeFlavors = FlavorConfigBuilder.createDummies("default");
NodeRepository nodeRepository = new NodeRepository(nodeFlavors, curator, clock, zone,
- new MockNameResolver().mockAnyLookup());
+ new MockNameResolver().mockAnyLookup(),
+ new DockerImage("docker-registry.domain.tld:8080/dist/vespa"));
NodeRepositoryProvisioner provisioner = new NodeRepositoryProvisioner(nodeRepository, nodeFlavors, zone);
createReadyNodes(7, nodeRepository, nodeFlavors);
@@ -95,7 +97,8 @@ public class RetiredExpirerTest {
Zone zone = new Zone(Environment.prod, RegionName.from("us-east"));
NodeFlavors nodeFlavors = FlavorConfigBuilder.createDummies("default");
NodeRepository nodeRepository = new NodeRepository(nodeFlavors, curator, clock, zone,
- new MockNameResolver().mockAnyLookup());
+ new MockNameResolver().mockAnyLookup(),
+ new DockerImage("docker-registry.domain.tld:8080/dist/vespa"));
NodeRepositoryProvisioner provisioner = new NodeRepositoryProvisioner(nodeRepository, nodeFlavors, zone);
createReadyNodes(8, nodeRepository, nodeFlavors);
@@ -105,7 +108,7 @@ public class RetiredExpirerTest {
ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("test"), Version.fromString("6.42"));
activate(applicationId, cluster, 8, 8, provisioner);
- activate(applicationId, cluster, 1, 1, provisioner);
+ activate(applicationId, cluster, 2, 2, provisioner);
assertEquals(8, nodeRepository.getNodes(applicationId, Node.State.active).size());
assertEquals(0, nodeRepository.getNodes(applicationId, Node.State.inactive).size());
@@ -113,10 +116,10 @@ public class RetiredExpirerTest {
clock.advance(Duration.ofHours(30)); // Retire period spent
MockDeployer deployer =
new MockDeployer(provisioner,
- Collections.singletonMap(applicationId, new MockDeployer.ApplicationContext(applicationId, cluster, Capacity.fromNodeCount(1, Optional.of("default")), 1)));
+ Collections.singletonMap(applicationId, new MockDeployer.ApplicationContext(applicationId, cluster, Capacity.fromNodeCount(2, Optional.of("default")), 1)));
new RetiredExpirer(nodeRepository, deployer, clock, Duration.ofHours(12), new JobControl(nodeRepository.database())).run();
- assertEquals(1, nodeRepository.getNodes(applicationId, Node.State.active).size());
- assertEquals(7, nodeRepository.getNodes(applicationId, Node.State.inactive).size());
+ assertEquals(2, nodeRepository.getNodes(applicationId, Node.State.active).size());
+ assertEquals(6, nodeRepository.getNodes(applicationId, Node.State.inactive).size());
assertEquals(1, deployer.redeployments);
// inactivated nodes are not retired
@@ -130,7 +133,8 @@ public class RetiredExpirerTest {
Zone zone = new Zone(Environment.prod, RegionName.from("us-east"));
NodeFlavors nodeFlavors = FlavorConfigBuilder.createDummies("default");
NodeRepository nodeRepository = new NodeRepository(nodeFlavors, curator, clock, zone,
- new MockNameResolver().mockAnyLookup());
+ new MockNameResolver().mockAnyLookup(),
+ new DockerImage("docker-registry.domain.tld:8080/dist/vespa"));
NodeRepositoryProvisioner provisioner = new NodeRepositoryProvisioner(nodeRepository, nodeFlavors, zone);
createReadyNodes(7, nodeRepository, nodeFlavors);
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/monitoring/MetricsReporterTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/monitoring/MetricsReporterTest.java
index febda1300ee..8c12d5f1f2a 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/monitoring/MetricsReporterTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/monitoring/MetricsReporterTest.java
@@ -4,6 +4,7 @@ package com.yahoo.vespa.hosted.provision.monitoring;
import com.yahoo.component.Version;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ClusterMembership;
+import com.yahoo.config.provision.DockerImage;
import com.yahoo.config.provision.NodeFlavors;
import com.yahoo.config.provision.NodeType;
import com.yahoo.config.provision.Zone;
@@ -44,7 +45,8 @@ public class MetricsReporterTest {
NodeFlavors nodeFlavors = FlavorConfigBuilder.createDummies("default");
Curator curator = new MockCurator();
NodeRepository nodeRepository = new NodeRepository(nodeFlavors, curator, Clock.systemUTC(), Zone.defaultZone(),
- new MockNameResolver().mockAnyLookup());
+ new MockNameResolver().mockAnyLookup(),
+ new DockerImage("docker-registry.domain.tld:8080/dist/vespa"));
Node node = nodeRepository.createNode("openStackId", "hostname", Optional.empty(), nodeFlavors.getFlavorOrThrow("default"), NodeType.tenant);
nodeRepository.addNodes(Collections.singletonList(node));
Node hostNode = nodeRepository.createNode("openStackId2", "parent", Optional.empty(), nodeFlavors.getFlavorOrThrow("default"), NodeType.proxy);
@@ -78,7 +80,8 @@ public class MetricsReporterTest {
NodeFlavors nodeFlavors = FlavorConfigBuilder.createDummies("host", "docker", "docker2");
Curator curator = new MockCurator();
NodeRepository nodeRepository = new NodeRepository(nodeFlavors, curator, Clock.systemUTC(), Zone.defaultZone(),
- new MockNameResolver().mockAnyLookup());
+ new MockNameResolver().mockAnyLookup(),
+ new DockerImage("docker-registry.domain.tld:8080/dist/vespa"));
// Allow 4 containers
Set<String> additionalIps = new HashSet<>();
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/SerializationTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/SerializationTest.java
index 5674d5c3ff0..00120d5a8b0 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/SerializationTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/SerializationTest.java
@@ -7,7 +7,6 @@ import com.yahoo.component.Vtag;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ApplicationName;
import com.yahoo.config.provision.ClusterMembership;
-import com.yahoo.config.provision.DockerImage;
import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.NodeFlavors;
import com.yahoo.config.provision.NodeType;
@@ -17,7 +16,6 @@ import com.yahoo.text.Utf8;
import com.yahoo.vespa.hosted.provision.Node;
import com.yahoo.vespa.hosted.provision.Node.State;
import com.yahoo.vespa.hosted.provision.node.Agent;
-import com.yahoo.vespa.hosted.provision.node.Allocation;
import com.yahoo.vespa.hosted.provision.node.Generation;
import com.yahoo.vespa.hosted.provision.node.History;
import com.yahoo.vespa.hosted.provision.node.Status;
@@ -218,25 +216,6 @@ public class SerializationTest {
}
@Test
- public void serialize_docker_image() {
- Node node = createNode();
-
- Version version = new DockerImage("docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.0").tagAsVersion();
- ClusterMembership clusterMembership = ClusterMembership.from("content/myId/0", version);
-
- Node nodeWithAllocation = node.with(
- new Allocation(ApplicationId.from(TenantName.from("myTenant"),
- ApplicationName.from("myApplication"),
- InstanceName.from("myInstance")),
- clusterMembership,
- new Generation(0, 0),
- false));
-
- Node deserializedNode = nodeSerializer.fromJson(State.provisioned, nodeSerializer.toJson(nodeWithAllocation));
- assertEquals("docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.0", deserializedNode.allocation().get().membership().cluster().dockerImage());
- }
-
- @Test
public void serialize_parentHostname() {
final String parentHostname = "parent.yahoo.com";
Node node = Node.create("myId", singleton("127.0.0.1"), Collections.emptySet(), "myHostname", Optional.of(parentHostname), nodeFlavors.getFlavorOrThrow("default"), NodeType.tenant);
@@ -296,7 +275,7 @@ public class SerializationTest {
" },\n" +
" \"restartGeneration\": 0,\n" +
" \"currentRestartGeneration\": 0,\n" +
- " \"wantedDockerImage\":\"docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.0\",\n" +
+ " \"wantedDockerImage\":\"foo:6.42.0\",\n" +
" \"wantedVespaVersion\":\"6.42.0\",\n" +
" \"rebootGeneration\": 1,\n" +
" \"currentRebootGeneration\": 0,\n" +
@@ -354,22 +333,6 @@ public class SerializationTest {
"}";
Node node = nodeSerializer.fromJson(State.active, Utf8.toBytes(nodeWithWantedVespaVersion));
assertEquals("6.42.2", node.allocation().get().membership().cluster().vespaVersion().toString());
- assertEquals("docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.2", node.allocation().get().membership().cluster().dockerImage());
- }
-
- @Test
- public void docker_image_is_derived_from_vespa_version() throws Exception {
- String nodeData =
- "{\n" +
- " \"type\" : \"tenant\",\n" +
- " \"flavor\" : \"large\",\n" +
- " \"openStackId\" : \"myId\",\n" +
- " \"hostname\" : \"myHostname\",\n" +
- " \"ipAddresses\" : [\"127.0.0.1\"],\n" +
- " \"vespaVersion\": \"6.42.1\"\n" +
- "}";
- Node node = nodeSerializer.fromJson(State.active, Utf8.toBytes(nodeData));
- assertEquals("docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.1", node.status().dockerImage().get());
}
private byte[] createNodeJson(String hostname, String... ipAddress) {
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java
index 2e5b47c6ddb..fe82b0fa6e6 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java
@@ -28,7 +28,6 @@ import com.yahoo.vespa.hosted.provision.node.Agent;
import com.yahoo.vespa.hosted.provision.node.History;
import com.yahoo.vespa.hosted.provision.persistence.NameResolver;
import com.yahoo.vespa.hosted.provision.testutils.MockNameResolver;
-import org.junit.Ignore;
import org.junit.Test;
import java.util.Collections;
@@ -357,7 +356,6 @@ public class ProvisioningTest {
tester.activate(application, state.allHosts);
}
- @Ignore // TODO: Re-activate when the check is reactivate in CapacityPolicies
@Test(expected = IllegalArgumentException.class)
public void prod_deployment_requires_redundancy() {
ProvisioningTester tester = new ProvisioningTester(new Zone(Environment.prod, RegionName.from("us-east")));
@@ -516,25 +514,27 @@ public class ProvisioningTest {
ApplicationId application1 = tester.makeApplicationId();
- tester.makeReadyNodes(10, "default");
+ tester.makeReadyNodes(14, "default");
// deploy
- SystemState state1 = prepare(application1, 2, 2, 3, 3, "default", tester);
+ SystemState state1 = prepare(application1, 3, 3, 4, 4, "default", tester);
tester.activate(application1, state1.allHosts);
// decrease cluster sizes
- SystemState state2 = prepare(application1, 1, 1, 1, 1, "default", tester);
+ SystemState state2 = prepare(application1, 2, 2, 2, 2, "default", tester);
tester.activate(application1, state2.allHosts);
// content0
assertFalse(state2.hostByMembership("content0", 0, 0).membership().get().retired());
- assertTrue( state2.hostByMembership("content0", 0, 1).membership().get().retired());
+ assertFalse( state2.hostByMembership("content0", 0, 1).membership().get().retired());
assertTrue( state2.hostByMembership("content0", 0, 2).membership().get().retired());
+ assertTrue( state2.hostByMembership("content0", 0, 3).membership().get().retired());
// content1
assertFalse(state2.hostByMembership("content1", 0, 0).membership().get().retired());
- assertTrue( state2.hostByMembership("content1", 0, 1).membership().get().retired());
+ assertFalse(state2.hostByMembership("content1", 0, 1).membership().get().retired());
assertTrue( state2.hostByMembership("content1", 0, 2).membership().get().retired());
+ assertTrue( state2.hostByMembership("content1", 0, 3).membership().get().retired());
}
@Test
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java
index 1bfe533b6c0..58d2507f9b8 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java
@@ -5,6 +5,7 @@ import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ApplicationName;
import com.yahoo.config.provision.Capacity;
import com.yahoo.config.provision.ClusterSpec;
+import com.yahoo.config.provision.DockerImage;
import com.yahoo.config.provision.Flavor;
import com.yahoo.config.provision.HostFilter;
import com.yahoo.config.provision.HostSpec;
@@ -76,7 +77,8 @@ public class ProvisioningTester implements AutoCloseable {
this.nodeFlavors = new NodeFlavors(config);
this.clock = new ManualClock();
this.curator = curator;
- this.nodeRepository = new NodeRepository(nodeFlavors, curator, clock, zone, nameResolver);
+ this.nodeRepository = new NodeRepository(nodeFlavors, curator, clock, zone, nameResolver,
+ new DockerImage("docker-registry.domain.tld:8080/dist/vespa"));
this.provisioner = new NodeRepositoryProvisioner(nodeRepository, nodeFlavors, zone, clock,
(x,y) -> allocationSnapshots.add(new AllocationSnapshot(new NodeList(x), "Provision tester", y)));
this.capacityPolicies = new CapacityPolicies(zone, nodeFlavors);
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node1.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node1.json
index 3fbe1d900c5..5879a612791 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node1.json
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node1.json
@@ -26,7 +26,7 @@
},
"restartGeneration": 0,
"currentRestartGeneration": 0,
- "wantedDockerImage":"docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.0",
+ "wantedDockerImage":"docker-registry.domain.tld:8080/dist/vespa:6.42.0",
"wantedVespaVersion":"6.42.0",
"rebootGeneration": 1,
"currentRebootGeneration": 0,
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node10.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node10.json
index f6368c58196..55342de4c9e 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node10.json
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node10.json
@@ -27,14 +27,14 @@
},
"restartGeneration": 0,
"currentRestartGeneration": 0,
- "wantedDockerImage":"docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.0",
+ "wantedDockerImage":"docker-registry.domain.tld:8080/dist/vespa:6.42.0",
"wantedVespaVersion": "6.42.0",
"rebootGeneration": 1,
"currentRebootGeneration": 0,
"vespaVersion": "5.104.142",
- "hostedVersion": "2.1.2408",
- "currentDockerImage": "docker-registry.ops.yahoo.com:4443/vespa/ci:5.104.142",
- "convergedStateVersion": "5.104.142-2.1.2408",
+ "currentDockerImage": "docker-registry.domain.tld:8080/dist/vespa:5.104.142",
+ "hostedVersion": "5.104.142",
+ "convergedStateVersion": "5.104.142",
"failCount": 0,
"hardwareFailure" : false,
"wantToRetire" : false,
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node2.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node2.json
index faaff6337db..2e599fe6add 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node2.json
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node2.json
@@ -26,7 +26,7 @@
},
"restartGeneration": 0,
"currentRestartGeneration": 0,
- "wantedDockerImage":"docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.0",
+ "wantedDockerImage":"docker-registry.domain.tld:8080/dist/vespa:6.42.0",
"wantedVespaVersion":"6.42.0",
"rebootGeneration": 1,
"currentRebootGeneration": 0,
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node3.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node3.json
index dd9213b9110..955d469a3f8 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node3.json
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node3.json
@@ -24,7 +24,7 @@
},
"restartGeneration": 0,
"currentRestartGeneration": 0,
- "wantedDockerImage":"docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.0",
+ "wantedDockerImage":"docker-registry.domain.tld:8080/dist/vespa:6.42.0",
"wantedVespaVersion":"6.42.0",
"rebootGeneration": 1,
"currentRebootGeneration": 0,
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node4-after-changes.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node4-after-changes.json
index cc907a2280c..d0103b79b7b 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node4-after-changes.json
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node4-after-changes.json
@@ -27,14 +27,14 @@
},
"restartGeneration": 0,
"currentRestartGeneration": 1,
- "wantedDockerImage": "docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.0",
+ "wantedDockerImage": "docker-registry.domain.tld:8080/dist/vespa:6.42.0",
"wantedVespaVersion": "6.42.0",
"rebootGeneration": 2,
"currentRebootGeneration": 1,
"vespaVersion": "6.43.0",
- "hostedVersion": "2.1.2408",
- "currentDockerImage": "docker-registry.ops.yahoo.com:4443/vespa/ci:6.43.0",
- "convergedStateVersion": "5.104.142-2.1.2408",
+ "currentDockerImage": "docker-registry.domain.tld:8080/dist/vespa:6.43.0",
+ "hostedVersion": "6.43.0",
+ "convergedStateVersion": "6.43.0",
"failCount": 0,
"hardwareFailure": true,
"hardwareFailureType": "memory_mcelog",
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node4.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node4.json
index e416634bbe5..06e0bcac683 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node4.json
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node4.json
@@ -27,12 +27,14 @@
},
"restartGeneration": 0,
"currentRestartGeneration": 0,
- "wantedDockerImage":"docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.0",
+ "wantedDockerImage":"docker-registry.domain.tld:8080/dist/vespa:6.42.0",
"wantedVespaVersion": "6.42.0",
"rebootGeneration": 1,
"currentRebootGeneration": 0,
"vespaVersion": "6.41.0",
- "currentDockerImage": "docker-registry.ops.yahoo.com:4443/vespa/ci:6.41.0",
+ "currentDockerImage": "docker-registry.domain.tld:8080/dist/vespa:6.41.0",
+ "hostedVersion": "6.41.0",
+ "convergedStateVersion": "6.41.0",
"failCount": 0,
"hardwareFailure" : false,
"wantToRetire" : false,
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node5.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node5.json
index f8e18a08ae6..bd13e305e1d 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node5.json
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node5.json
@@ -16,7 +16,9 @@
"rebootGeneration": 1,
"currentRebootGeneration": 0,
"vespaVersion": "1.2.3",
- "currentDockerImage": "docker-registry.ops.yahoo.com:4443/vespa/ci:1.2.3",
+ "currentDockerImage": "docker-registry.domain.tld:8080/dist/vespa:1.2.3",
+ "hostedVersion": "1.2.3",
+ "convergedStateVersion": "1.2.3",
"failCount": 1,
"hardwareFailure" : false,
"wantToRetire" : false,
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node6.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node6.json
index 6910c132206..a78ece62469 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node6.json
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node6.json
@@ -26,7 +26,7 @@
},
"restartGeneration": 0,
"currentRestartGeneration": 0,
- "wantedDockerImage":"docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.0",
+ "wantedDockerImage":"docker-registry.domain.tld:8080/dist/vespa:6.42.0",
"wantedVespaVersion":"6.42.0",
"rebootGeneration": 1,
"currentRebootGeneration": 0,
diff --git a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/resources/HostResource.java b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/resources/HostResource.java
index 54f1723c914..916ab9d3e5e 100644
--- a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/resources/HostResource.java
+++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/resources/HostResource.java
@@ -21,7 +21,6 @@ import javax.ws.rs.BadRequestException;
import javax.ws.rs.InternalServerErrorException;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@@ -54,7 +53,7 @@ public class HostResource implements HostApi {
}
@Override
- public PatchHostResponse patch(@PathParam("hostname") String hostNameString, PatchHostRequest request) {
+ public PatchHostResponse patch(String hostNameString, PatchHostRequest request) {
HostName hostName = new HostName(hostNameString);
if (request.state != null) {
diff --git a/persistence/src/tests/proxy/.gitignore b/persistence/src/tests/proxy/.gitignore
index 9bd2934723e..03bce028dd9 100644
--- a/persistence/src/tests/proxy/.gitignore
+++ b/persistence/src/tests/proxy/.gitignore
@@ -3,7 +3,7 @@
/providerstub_test
/providerproxy_test
/providerproxy_conformancetest
-/external_providerproxy_conformancetest
+/vespa-external-providerproxy-conformancetest
persistence_providerproxy_conformance_test_app
persistence_providerproxy_test_app
persistence_providerstub_test_app
diff --git a/persistence/src/tests/proxy/CMakeLists.txt b/persistence/src/tests/proxy/CMakeLists.txt
index 14d19f6d4c6..f727773f564 100644
--- a/persistence/src/tests/proxy/CMakeLists.txt
+++ b/persistence/src/tests/proxy/CMakeLists.txt
@@ -21,7 +21,7 @@ vespa_add_executable(persistence_providerproxy_conformance_test_app TEST
vespa_add_executable(persistence_external_providerproxy_conformancetest_app
SOURCES
external_providerproxy_conformancetest.cpp
- OUTPUT_NAME external_providerproxy_conformancetest
+ OUTPUT_NAME vespa-external-providerproxy-conformancetest
INSTALL bin
DEPENDS
persistence
diff --git a/pom.xml b/pom.xml
index 42665292a23..7e3f15ee9be 100644
--- a/pom.xml
+++ b/pom.xml
@@ -121,7 +121,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
- <version>2.3.1</version>
+ <version>2.5.2</version>
<configuration>
<updateReleaseInfo>true</updateReleaseInfo>
</configuration>
diff --git a/sample-apps/http-api-using-request-handlers-and-processors/README.md b/sample-apps/http-api-using-request-handlers-and-processors/README.md
new file mode 100644
index 00000000000..27cfb8f3014
--- /dev/null
+++ b/sample-apps/http-api-using-request-handlers-and-processors/README.md
@@ -0,0 +1,4 @@
+# Vespa sample applications - Building a HTTP API using request handlers and processors
+
+Refer to the http-api-tutorial.html for documentation FIXME proper link soon
+
diff --git a/sample-apps/http-api-using-request-handlers-and-processors/pom.xml b/sample-apps/http-api-using-request-handlers-and-processors/pom.xml
new file mode 100644
index 00000000000..8141a0b91b1
--- /dev/null
+++ b/sample-apps/http-api-using-request-handlers-and-processors/pom.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0"?>
+<!-- Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+ http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>com.yahoo.demo</groupId>
+ <artifactId>sample-app-http-api-processor</artifactId>
+ <version>1.0.1</version>
+ <packaging>container-plugin</packaging> <!-- Use Vespa packaging -->
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <test.hide>true</test.hide>
+ <vespa_version>6-SNAPSHOT</vespa_version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.11</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>application</artifactId> <!-- Is this needed? -->
+ <version>${vespa_version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>container-dev</artifactId> <!-- not container-dev -->
+ <version>${vespa_version}</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.6.1</version>
+ <configuration>
+ <optimize>true</optimize>
+ <showDeprecation>true</showDeprecation>
+ <showWarnings>true</showWarnings>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.19.1</version>
+ <configuration>
+ <systemPropertyVariables>
+ <isMavenSurefirePlugin>true</isMavenSurefirePlugin>
+ </systemPropertyVariables>
+ <redirectTestOutputToFile>${test.hide}</redirectTestOutputToFile>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>vespa-application-maven-plugin</artifactId> <!-- Zip the application package -->
+ <version>${vespa_version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>packageApplication</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>bundle-plugin</artifactId>
+ <version>${vespa_version}</version>
+ <extensions>true</extensions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/sample-apps/http-api-using-request-handlers-and-processors/src/main/application/services.xml b/sample-apps/http-api-using-request-handlers-and-processors/src/main/application/services.xml
new file mode 100644
index 00000000000..add155c2279
--- /dev/null
+++ b/sample-apps/http-api-using-request-handlers-and-processors/src/main/application/services.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!-- Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
+<services version="1.0">
+ <container id="default" version="1.0">
+ <processing>
+ <chain id="default">
+ <processor id="com.yahoo.demo.AnnotatingProcessor" bundle="demo">
+ <config name="demo.demo">
+ <demo>
+ <item>
+ <term>smurf</term>
+ </item>
+ </demo>
+ </config>
+ </processor>
+ <processor id="com.yahoo.demo.DataProcessor" bundle="demo" />
+ </chain>
+ <renderer id="demo" class="com.yahoo.demo.DemoRenderer" bundle="demo" />
+ </processing>
+ <handler id="com.yahoo.demo.DemoHandler" bundle="demo">
+ <binding>http://*/demo</binding>
+ </handler>
+ <component id="com.yahoo.demo.DemoComponent" bundle="demo"/>
+ </container>
+</services>
diff --git a/sample-apps/http-api-using-request-handlers-and-processors/src/main/java/com/yahoo/demo/AnnotatingProcessor.java b/sample-apps/http-api-using-request-handlers-and-processors/src/main/java/com/yahoo/demo/AnnotatingProcessor.java
new file mode 100644
index 00000000000..e241d59f5d7
--- /dev/null
+++ b/sample-apps/http-api-using-request-handlers-and-processors/src/main/java/com/yahoo/demo/AnnotatingProcessor.java
@@ -0,0 +1,97 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.demo;
+
+import com.google.common.base.Splitter;
+import com.yahoo.processing.Processor;
+import com.yahoo.processing.Request;
+import com.yahoo.processing.Response;
+import com.yahoo.processing.execution.Execution;
+import com.yahoo.processing.request.CompoundName;
+import com.yahoo.processing.request.ErrorMessage;
+import com.yahoo.processing.response.DataList;
+import com.yahoo.yolean.chain.Before;
+import com.yahoo.yolean.chain.Provides;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A processor which processes the incoming query property "terms", then checks
+ * whether there are any smurfs, i.e. DemoData instances containing the string
+ * {@link DemoComponent#SMURF}, and adds errors if that is the case.
+ */
+@Provides(AnnotatingProcessor.DemoProperty.NAME)
+@Before(DataProcessor.DemoData.NAME)
+public class AnnotatingProcessor extends Processor {
+
+ public static class DemoProperty {
+
+ public static final String NAME = "demo.property";
+ public static final CompoundName NAME_AS_COMPOUND = new CompoundName(NAME);
+
+ private final List<String> terms = new ArrayList<>();
+
+ public void add(String term) {
+ terms.add(term);
+ }
+
+ public List<String> terms() {
+ return terms;
+ }
+ }
+
+ private final DemoConfig defaultTermSet;
+
+ public final CompoundName TERMS = new CompoundName("terms");
+
+ private static final Splitter splitter = Splitter.on(' ').omitEmptyStrings();
+
+ public AnnotatingProcessor(DemoConfig defaultTermSet) {
+ this.defaultTermSet = defaultTermSet;
+ }
+
+ @Override
+ public Response process(Request request, Execution execution) {
+ Response response;
+ List<?> d;
+ DemoProperty p = new DemoProperty();
+ String terms = request.properties().getString(TERMS);
+
+ if (terms != null) {
+ for (String s : splitter.split(terms)) {
+ p.add(s);
+ }
+ } else {
+ for (DemoConfig.Demo demo : defaultTermSet.demo()) {
+ p.add(demo.term());
+ }
+ }
+ request.properties().set(DemoProperty.NAME_AS_COMPOUND, p);
+ response = execution.process(request);
+ d = response.data().asList();
+ traverse(d, response.data().request().errors());
+ return response;
+ }
+
+ private boolean traverse(List<?> list, List<ErrorMessage> topLevelErrors) {
+ boolean smurfFound = false;
+ // traverse the tree in the response, and react to the known types
+ for (Object data : list) {
+ if (data instanceof DataList) {
+ smurfFound = traverse(((DataList<?>) data).asList(),
+ topLevelErrors);
+ } else if (data instanceof DataProcessor.DemoData) {
+ DataProcessor.DemoData content = (DataProcessor.DemoData) data;
+ if (DemoComponent.SMURF.equals(content.content())) {
+ topLevelErrors.add(new ErrorMessage("There's a smurf!"));
+ smurfFound = true;
+ }
+ }
+ if (smurfFound) {
+ break;
+ }
+ }
+ return smurfFound;
+ }
+
+} \ No newline at end of file
diff --git a/sample-apps/http-api-using-request-handlers-and-processors/src/main/java/com/yahoo/demo/DataProcessor.java b/sample-apps/http-api-using-request-handlers-and-processors/src/main/java/com/yahoo/demo/DataProcessor.java
new file mode 100644
index 00000000000..915beb38f5e
--- /dev/null
+++ b/sample-apps/http-api-using-request-handlers-and-processors/src/main/java/com/yahoo/demo/DataProcessor.java
@@ -0,0 +1,87 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.demo;
+
+import com.yahoo.component.provider.ListenableFreezableClass;
+import com.yahoo.processing.Processor;
+import com.yahoo.processing.Request;
+import com.yahoo.processing.Response;
+import com.yahoo.processing.execution.Execution;
+import com.yahoo.processing.response.ArrayDataList;
+import com.yahoo.processing.response.Data;
+import com.yahoo.processing.response.DataList;
+import com.yahoo.yolean.chain.After;
+import com.yahoo.yolean.chain.Provides;
+
+/**
+ * A processor making a nested result sets of "normalized" strings from the
+ * request property {@link AnnotatingProcessor.DemoProperty#NAME}.
+ */
+@Provides(DataProcessor.DemoData.NAME)
+@After(AnnotatingProcessor.DemoProperty.NAME)
+public class DataProcessor extends Processor {
+ public static class DemoData extends ListenableFreezableClass implements Data {
+ public static final String NAME = "DemoData";
+
+ private final Request request;
+ private final String content;
+
+ DemoData(Request request, String content) {
+ this.request = request;
+ this.content = content;
+ }
+
+ @Override
+ public Request request() {
+ return request;
+ }
+
+ public String content() {
+ return content;
+ }
+
+ public String toString() {
+ return NAME + "(\"" + content + "\")";
+ }
+ }
+
+ private final DemoComponent termChecker;
+
+ public DataProcessor(DemoComponent termChecker) {
+ this.termChecker = termChecker;
+ }
+
+ @Override
+ public Response process(Request request, Execution execution) {
+ Response r = new Response(request);
+ @SuppressWarnings("unchecked")
+ DataList<Data> current = r.data();
+ DataList<Data> previous = null;
+ String exampleProperty = request.properties().getString(DemoHandler.REQUEST_URI);
+ Object o = request.properties().get(AnnotatingProcessor.DemoProperty.NAME_AS_COMPOUND);
+
+
+ if (exampleProperty != null) {
+ current.add(new DemoData(request, exampleProperty));
+ }
+
+ if (o instanceof AnnotatingProcessor.DemoProperty) {
+ // create a nested result set with a level for each term
+ for (String s : ((AnnotatingProcessor.DemoProperty) o).terms()) {
+ String normalized = termChecker.normalize(s);
+ DemoData data = new DemoData(request, normalized);
+
+ if (current == null) {
+ current = ArrayDataList.create(request);
+ }
+ current.add(data);
+ if (previous != null) {
+ previous.add(current);
+ }
+ previous = current;
+ current = null;
+ }
+ }
+ return r;
+ }
+
+} \ No newline at end of file
diff --git a/sample-apps/http-api-using-request-handlers-and-processors/src/main/java/com/yahoo/demo/DemoComponent.java b/sample-apps/http-api-using-request-handlers-and-processors/src/main/java/com/yahoo/demo/DemoComponent.java
new file mode 100644
index 00000000000..455784525e1
--- /dev/null
+++ b/sample-apps/http-api-using-request-handlers-and-processors/src/main/java/com/yahoo/demo/DemoComponent.java
@@ -0,0 +1,47 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.demo;
+
+import com.yahoo.component.AbstractComponent;
+
+import java.text.Normalizer;
+import java.util.HashSet;
+import java.util.Random;
+import java.util.Set;
+
+/**
+ * A shared component with an "expensive" constructor exposing a shared,
+ * thread-safe service.
+ */
+public class DemoComponent extends AbstractComponent {
+ public static final String SMURF = "smurf";
+
+ private final Set<Integer> illegalHashes;
+
+ public DemoComponent() {
+ illegalHashes = new HashSet<Integer>();
+ Random r = new Random();
+ // generate up to 1e6 unique hashes
+ for (int i = 0; i < 1000 * 1000; ++i) {
+ illegalHashes.add(r.nextInt());
+ }
+ }
+
+ /**
+ * NFKC-normalize term, or replace it with "smurf" with a low probability.
+ * Will change choice for each run, but will be constant in a single run of
+ * the container.
+ *
+ * @param term
+ * term to normalize or replace with "smurf"
+ * @return NFKC-normalized term or "smurf"
+ */
+ public String normalize(String term) {
+ String normalized = Normalizer.normalize(term, Normalizer.Form.NFKC);
+ if (illegalHashes.contains(normalized.hashCode())) {
+ return SMURF;
+ } else {
+ return normalized;
+ }
+ }
+
+}
diff --git a/sample-apps/http-api-using-request-handlers-and-processors/src/main/java/com/yahoo/demo/DemoHandler.java b/sample-apps/http-api-using-request-handlers-and-processors/src/main/java/com/yahoo/demo/DemoHandler.java
new file mode 100644
index 00000000000..b7ceab55609
--- /dev/null
+++ b/sample-apps/http-api-using-request-handlers-and-processors/src/main/java/com/yahoo/demo/DemoHandler.java
@@ -0,0 +1,76 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.demo;
+
+import com.google.inject.Inject;
+import com.yahoo.container.jdisc.HttpRequest;
+import com.yahoo.container.jdisc.HttpResponse;
+import com.yahoo.container.jdisc.ThreadedHttpRequestHandler;
+import com.yahoo.jdisc.handler.ContentChannel;
+import com.yahoo.processing.handler.ProcessingHandler;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Annotate an incoming request with the URI string used to query from the
+ * network, and pass the request on to the processing handler.
+ */
+public class DemoHandler extends ThreadedHttpRequestHandler {
+
+ /** The name used by the processing handler to choose output renderer. */
+ private static final String FORMAT = "format";
+
+ /** The property name for the incoming URI as a string. */
+ public static final String REQUEST_URI = "request.uri";
+
+ private final ProcessingHandler processingHandler;
+
+ /**
+ * Constructor for use in injection. The requested objects are subclasses of
+ * component or have dedicated providers, so the container will know how to
+ * create this handler.
+ *
+ * @param executor
+ * threadpool, provided by the container
+ * @param processingHandler
+ * the processing handler, also automatically injected
+ */
+ @Inject
+ public DemoHandler(Executor executor, ProcessingHandler processingHandler) {
+ super(executor, null, true);
+ this.processingHandler = processingHandler;
+ }
+
+ @Override
+ public HttpResponse handle(HttpRequest request) {
+ // We have implemented #handle(HttpRequest, ContentChannel) to be
+ // able to use the ProcessingHandler, so this will never be called.
+ // An implementation is needed, though, as the method is abstract.
+ throw new UnsupportedOperationException("See #handle(HttpRequest, ContentChannel)");
+ }
+
+ @Override
+ public HttpResponse handle(HttpRequest request, ContentChannel channel) {
+ HttpRequest.Builder builder =
+ new HttpRequest.Builder(request).put(REQUEST_URI, request.getUri().toString());
+ setFormat(builder, request);
+ return processingHandler.handle(builder.createDirectRequest(),
+ channel);
+ }
+
+ /**
+ * Set the output format to the renderer with id = "demo" in services.xml if
+ * no explicit format parameter is present. This allows using e.g. the
+ * default processing renderer by adding <code>&amp;format=default</code> to
+ * the HTTP request.
+ *
+ * @param builder
+ * the mutable builder instance used for creating the forwarding request
+ * @param request
+ * the incoming HTTP request
+ */
+ private void setFormat(HttpRequest.Builder builder, HttpRequest request) {
+ if ( ! request.hasProperty(FORMAT)) {
+ builder.put(FORMAT, "demo");
+ }
+ }
+}
diff --git a/sample-apps/http-api-using-request-handlers-and-processors/src/main/java/com/yahoo/demo/DemoRenderer.java b/sample-apps/http-api-using-request-handlers-and-processors/src/main/java/com/yahoo/demo/DemoRenderer.java
new file mode 100644
index 00000000000..c30adbcf7aa
--- /dev/null
+++ b/sample-apps/http-api-using-request-handlers-and-processors/src/main/java/com/yahoo/demo/DemoRenderer.java
@@ -0,0 +1,119 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.demo;
+
+import com.yahoo.processing.Response;
+import com.yahoo.processing.rendering.AsynchronousSectionedRenderer;
+import com.yahoo.processing.response.Data;
+import com.yahoo.processing.response.DataList;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Render a response as plain text. First line is whether an error occurred,
+ * second rendering initialization time stamp, then each line is response data
+ * (indented according to its place in the hierarchic response), and the last
+ * line is time stamp for when the renderer was finished.
+ */
+public class DemoRenderer extends AsynchronousSectionedRenderer<Response> {
+
+ /**
+ * Indent size for rendering hierarchic response data.
+ */
+ public static final int INDENT_SIZE = 4;
+
+ // Response heading
+ private String heading;
+
+ // Just a utility to write strings to output stream
+ private Writer writer;
+
+ // current indent in the rendered tree
+ String indent;
+
+ /**
+ * No global, shared state to set.
+ */
+ public DemoRenderer() {
+ }
+
+ @Override
+ public void beginResponse(OutputStream stream) throws IOException {
+ writer = new OutputStreamWriter(stream, StandardCharsets.UTF_8.newEncoder());
+ if (getResponse().data().request().errors().size() == 0) {
+ writer.write("OK\n");
+ } else {
+ writer.write("Oops!\n");
+ }
+ writer.write(heading);
+ writer.write('\n');
+ }
+
+ /**
+ * Indent {@link #INDENT_SIZE} spaces for each level in the tree.
+ */
+ @Override
+ public void beginList(DataList<?> list) throws IOException {
+ indent = spaces((getRecursionLevel() - 1) * INDENT_SIZE);
+ }
+
+ @Override
+ public void data(Data data) throws IOException {
+ if (!(data instanceof DataProcessor.DemoData)) {
+ return;
+ }
+ writer.write(indent);
+ writer.write(((DataProcessor.DemoData) data).content());
+ writer.write('\n');
+ }
+
+ private static String spaces(int len) {
+ StringBuilder s = new StringBuilder(len);
+ for (int i = 0; i < len; ++i) {
+ s.append(' ');
+ }
+ return s.toString();
+ }
+
+ /**
+ * Out-dent one level if not at outermost level.
+ */
+ @Override
+ public void endList(DataList<?> list) throws IOException {
+ if (indent.length() == 0) {
+ return;
+ }
+ indent = spaces(indent.length() - INDENT_SIZE);
+ }
+
+ @Override
+ public void endResponse() throws IOException {
+ writer.write("Rendering finished work: " + System.currentTimeMillis());
+ writer.write('\n');
+ writer.close();
+ }
+
+ @Override
+ public String getEncoding() {
+ return StandardCharsets.UTF_8.name();
+ }
+
+ @Override
+ public String getMimeType() {
+ return "text/plain";
+ }
+
+ /**
+ * Initialize mutable, per-result set state here.
+ */
+ @Override
+ public void init() {
+ long time = System.currentTimeMillis();
+
+ super.init(); // Important! The base class needs to initialize itself.
+ heading = "Renderer initialized: " + time;
+ }
+}
diff --git a/sample-apps/http-api-using-request-handlers-and-processors/src/main/resources/configdefinitions/demo.def b/sample-apps/http-api-using-request-handlers-and-processors/src/main/resources/configdefinitions/demo.def
new file mode 100644
index 00000000000..9a804089433
--- /dev/null
+++ b/sample-apps/http-api-using-request-handlers-and-processors/src/main/resources/configdefinitions/demo.def
@@ -0,0 +1,5 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+namespace=demo
+
+demo[].term string
+
diff --git a/sample-apps/http-api-using-request-handlers-and-processors/src/test/java/com/yahoo/example/ApplicationMain.java b/sample-apps/http-api-using-request-handlers-and-processors/src/test/java/com/yahoo/example/ApplicationMain.java
new file mode 100644
index 00000000000..da85e486602
--- /dev/null
+++ b/sample-apps/http-api-using-request-handlers-and-processors/src/test/java/com/yahoo/example/ApplicationMain.java
@@ -0,0 +1,27 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.example;
+
+import com.yahoo.application.Networking;
+import org.junit.Test;
+
+import java.nio.file.FileSystems;
+
+import static org.junit.Assume.assumeTrue;
+
+public class ApplicationMain {
+
+ @Test
+ public void runFromMaven() throws Exception {
+ assumeTrue(Boolean.valueOf(System.getProperty("isMavenSurefirePlugin")));
+ main(null);
+ }
+
+ public static void main(String[] args) throws Exception {
+ try (com.yahoo.application.Application app = com.yahoo.application.Application.fromApplicationPackage(
+ FileSystems.getDefault().getPath("src/main/application"),
+ Networking.enable)) {
+ app.getClass(); // throws NullPointerException
+ Thread.sleep(Long.MAX_VALUE);
+ }
+ }
+} \ No newline at end of file
diff --git a/sample-apps/http-api-using-searcher/README.md b/sample-apps/http-api-using-searcher/README.md
new file mode 100644
index 00000000000..6511db54b7e
--- /dev/null
+++ b/sample-apps/http-api-using-searcher/README.md
@@ -0,0 +1,4 @@
+# Vespa sample applications - Building a HTTP API using a searcher
+
+Refer to search/handler-tutorial.html for documentation FIXME real link soon
+
diff --git a/sample-apps/http-api-using-searcher/feed.json b/sample-apps/http-api-using-searcher/feed.json
new file mode 100644
index 00000000000..bbd91c314de
--- /dev/null
+++ b/sample-apps/http-api-using-searcher/feed.json
@@ -0,0 +1,14 @@
+[
+ {
+ "put": "id:test:basic::http://demo/0/",
+ "fields": {
+ "description": "red hat smurf demo"
+ }
+ },
+ {
+ "put": "id:test:basic::http://demo/1/",
+ "fields": {
+ "description": "red smurf hat demo something"
+ }
+ }
+]
diff --git a/sample-apps/http-api-using-searcher/pom.xml b/sample-apps/http-api-using-searcher/pom.xml
new file mode 100644
index 00000000000..6dfee6026ee
--- /dev/null
+++ b/sample-apps/http-api-using-searcher/pom.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0"?>
+<!-- Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+ http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>com.yahoo.demo</groupId>
+ <artifactId>sample-app-http-api-searcher</artifactId>
+ <version>1.0.1</version>
+ <packaging>container-plugin</packaging> <!-- Use Vespa packaging -->
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <test.hide>true</test.hide>
+ <vespa_version>6-SNAPSHOT</vespa_version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.11</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>application</artifactId> <!-- Is this needed? -->
+ <version>${vespa_version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>container-dev</artifactId> <!-- not container-dev -->
+ <version>${vespa_version}</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.6.1</version>
+ <configuration>
+ <optimize>true</optimize>
+ <showDeprecation>true</showDeprecation>
+ <showWarnings>true</showWarnings>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.19.1</version>
+ <configuration>
+ <systemPropertyVariables>
+ <isMavenSurefirePlugin>true</isMavenSurefirePlugin>
+ </systemPropertyVariables>
+ <redirectTestOutputToFile>${test.hide}</redirectTestOutputToFile>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>vespa-application-maven-plugin</artifactId> <!-- Zip the application package -->
+ <version>${vespa_version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>packageApplication</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>bundle-plugin</artifactId>
+ <version>${vespa_version}</version>
+ <extensions>true</extensions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/sample-apps/http-api-using-searcher/src/main/application/searchdefinitions/basic.sd b/sample-apps/http-api-using-searcher/src/main/application/searchdefinitions/basic.sd
new file mode 100644
index 00000000000..3c4920a1912
--- /dev/null
+++ b/sample-apps/http-api-using-searcher/src/main/application/searchdefinitions/basic.sd
@@ -0,0 +1,16 @@
+search basic {
+
+ document basic {
+
+ field description type string {
+ indexing: summary | index
+ }
+
+ }
+
+ fieldset default {
+ fields: description
+ }
+
+}
+
diff --git a/sample-apps/http-api-using-searcher/src/main/application/services.xml b/sample-apps/http-api-using-searcher/src/main/application/services.xml
new file mode 100644
index 00000000000..fe16ec42260
--- /dev/null
+++ b/sample-apps/http-api-using-searcher/src/main/application/services.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
+<services version="1.0">
+ <admin version="2.0">
+ <adminserver hostalias="node1"/>
+ </admin>
+
+ <container id="default" version="1.0">
+
+ <document-api /> <!-- Enable feed endpoint -->
+
+ <search>
+ <chain inherits="vespa" id="default">
+ <searcher id="com.yahoo.demo.DemoSearcher" bundle="demo">
+ <config name="demo.demo">
+ <demo>
+ <item>
+ <term>smurf</term>
+ </item>
+ </demo>
+ </config>
+ </searcher>
+ </chain>
+ <renderer id="demo" class="com.yahoo.demo.DemoRenderer" bundle="demo" />
+ </search>
+
+ <handler id="com.yahoo.demo.DemoHandler" bundle="demo">
+ <binding>http://*:8080/demo</binding>
+ </handler>
+
+ <component id="com.yahoo.demo.DemoComponent" bundle="demo"/>
+
+ <nodes>
+ <node hostalias="node1"/>
+ </nodes>
+ </container>
+
+ <content id="logical" version="1.0">
+ <redundancy>1</redundancy>
+ <documents>
+ <document mode="index" type="basic"/>
+ </documents>
+
+ <group name="mygroup" distribution-key="0">
+ <node distribution-key="0" hostalias="node1"/>
+ </group>
+
+ <engine>
+ <proton>
+ <searchable-copies>1</searchable-copies>
+ </proton>
+ </engine>
+ </content>
+
+</services>
diff --git a/sample-apps/http-api-using-searcher/src/main/java/com/yahoo/demo/DemoComponent.java b/sample-apps/http-api-using-searcher/src/main/java/com/yahoo/demo/DemoComponent.java
new file mode 100644
index 00000000000..2182cebecb9
--- /dev/null
+++ b/sample-apps/http-api-using-searcher/src/main/java/com/yahoo/demo/DemoComponent.java
@@ -0,0 +1,45 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.demo;
+
+import com.yahoo.component.AbstractComponent;
+
+import java.text.Normalizer;
+import java.util.HashSet;
+import java.util.Random;
+import java.util.Set;
+
+/**
+ * A shared component with an "expensive" constructor exposing a shared,
+ * thread-safe service.
+ */
+public class DemoComponent extends AbstractComponent {
+ private final Set<Integer> illegalHashes;
+
+ public DemoComponent() {
+ illegalHashes = new HashSet<Integer>();
+ Random r = new Random();
+ // generate up to 1e6 unique hashes
+ for (int i = 0; i < 1000 * 1000; ++i) {
+ illegalHashes.add(r.nextInt());
+ }
+ }
+
+ /**
+ * NFKC-normalize term, or replace it with "smurf" with a low probability.
+ * Will change choice for each run, but will be constant in a single run of
+ * the container.
+ *
+ * @param term
+ * term to normalize or replace with "smurf"
+ * @return NFKC-normalized term or "smurf"
+ */
+ public String normalize(String term) {
+ String normalized = Normalizer.normalize(term, Normalizer.Form.NFKC);
+ if (illegalHashes.contains(normalized.hashCode())) {
+ return "smurf";
+ } else {
+ return normalized;
+ }
+ }
+
+}
diff --git a/sample-apps/http-api-using-searcher/src/main/java/com/yahoo/demo/DemoHandler.java b/sample-apps/http-api-using-searcher/src/main/java/com/yahoo/demo/DemoHandler.java
new file mode 100644
index 00000000000..cf14f6d58cd
--- /dev/null
+++ b/sample-apps/http-api-using-searcher/src/main/java/com/yahoo/demo/DemoHandler.java
@@ -0,0 +1,50 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.demo;
+
+import com.google.inject.Inject;
+import com.yahoo.container.jdisc.HttpRequest;
+import com.yahoo.container.jdisc.HttpResponse;
+import com.yahoo.container.jdisc.LoggingRequestHandler;
+import com.yahoo.container.logging.AccessLog;
+import com.yahoo.search.handler.SearchHandler;
+import com.yahoo.search.query.Model;
+import com.yahoo.search.query.Presentation;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Forward requests to search handler after adding "Red Hat" as query and "demo"
+ * as renderer ID.
+ */
+public class DemoHandler extends LoggingRequestHandler {
+
+ private final SearchHandler searchHandler;
+
+ /**
+ * Constructor for use in injection. The requested objects are subclasses of
+ * component or have dedicated providers, so the container will know how to
+ * create this handler.
+ *
+ * @param executor
+ * threadpool, provided by Vespa
+ * @param accessLog
+ * access log for incoming queries, provided by Vespa
+ * @param searchHandler
+ * the Vespa search handler, also automatically injected
+ */
+ @Inject
+ public DemoHandler(Executor executor, AccessLog accessLog,
+ SearchHandler searchHandler) {
+ super(executor, accessLog, null, true);
+ this.searchHandler = searchHandler;
+ }
+
+ @Override
+ public HttpResponse handle(HttpRequest request) {
+ HttpRequest searchRequest = new HttpRequest.Builder(request)
+ .put(Model.QUERY_STRING, "Red Hat")
+ .put(Presentation.FORMAT, "demo").createDirectRequest();
+ HttpResponse r = searchHandler.handle(searchRequest);
+ return r;
+ }
+}
diff --git a/sample-apps/http-api-using-searcher/src/main/java/com/yahoo/demo/DemoRenderer.java b/sample-apps/http-api-using-searcher/src/main/java/com/yahoo/demo/DemoRenderer.java
new file mode 100644
index 00000000000..979c50f7f8f
--- /dev/null
+++ b/sample-apps/http-api-using-searcher/src/main/java/com/yahoo/demo/DemoRenderer.java
@@ -0,0 +1,74 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.demo;
+
+import com.yahoo.search.Result;
+import com.yahoo.search.rendering.Renderer;
+import com.yahoo.search.result.Hit;
+import com.yahoo.search.result.HitGroup;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Iterator;
+
+/**
+ * Render result sets as plain text. First line is whether an error occurred,
+ * second rendering initialization time stamp, then each line is the ID of each
+ * document returned, and the last line is time stamp for when the renderer was
+ * finished.
+ */
+public class DemoRenderer extends Renderer {
+ private String heading;
+
+ /**
+ * No global, shared state to set.
+ */
+ public DemoRenderer() {
+ }
+
+ @Override
+ protected void render(Writer writer, Result result) throws IOException {
+ if (result.hits().getErrorHit() == null) {
+ writer.write("OK\n");
+ } else {
+ writer.write("Oops!\n");
+ }
+ writer.write(heading);
+ writer.write("\n");
+ renderHits(writer, result.hits());
+ writer.write("Rendering finished work: " + System.currentTimeMillis());
+ writer.write("\n");
+ }
+
+ private void renderHits(Writer writer, HitGroup hits) throws IOException {
+ for (Iterator<Hit> i = hits.deepIterator(); i.hasNext();) {
+ Hit h = i.next();
+ if (h.types().contains("summary")) {
+ String id = h.getDisplayId();
+ if (id != null) {
+ writer.write(id);
+ writer.write("\n");
+ }
+ }
+ }
+ }
+
+ @Override
+ public String getEncoding() {
+ return "utf-8";
+ }
+
+ @Override
+ public String getMimeType() {
+ return "text/plain";
+ }
+
+ /**
+ * Initialize mutable, per-result set state here.
+ */
+ @Override
+ public void init() {
+ long time = System.currentTimeMillis();
+ heading = "Renderer initialized: " + time;
+ }
+
+}
diff --git a/sample-apps/http-api-using-searcher/src/main/java/com/yahoo/demo/DemoSearcher.java b/sample-apps/http-api-using-searcher/src/main/java/com/yahoo/demo/DemoSearcher.java
new file mode 100644
index 00000000000..e749a3c1556
--- /dev/null
+++ b/sample-apps/http-api-using-searcher/src/main/java/com/yahoo/demo/DemoSearcher.java
@@ -0,0 +1,76 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.demo;
+
+import com.yahoo.component.chain.dependencies.After;
+import com.yahoo.component.chain.dependencies.Before;
+import com.yahoo.component.chain.dependencies.Provides;
+import com.yahoo.demo.DemoConfig.Demo;
+import com.yahoo.prelude.query.AndItem;
+import com.yahoo.prelude.query.CompositeItem;
+import com.yahoo.prelude.query.Item;
+import com.yahoo.prelude.query.WordItem;
+import com.yahoo.processing.request.CompoundName;
+import com.yahoo.search.Query;
+import com.yahoo.search.Result;
+import com.yahoo.search.Searcher;
+import com.yahoo.search.query.QueryTree;
+import com.yahoo.search.searchchain.Execution;
+import com.yahoo.search.searchchain.PhaseNames;
+
+import java.util.List;
+
+/**
+ * A searcher for adding a set of configured terms as AND terms, and add a
+ * single term from the request to the query tree (after running the term
+ * through a shared component).
+ */
+@After(PhaseNames.RAW_QUERY)
+@Before(PhaseNames.TRANSFORMED_QUERY)
+@Provides(DemoSearcher.DEMO_TRANSFORM)
+public class DemoSearcher extends Searcher {
+ public static final String DEMO_TRANSFORM = "com.yahoo.demo.DemoSearcher.NothingUseful";
+
+ /**
+ * The request property with this name will be filtered and added to the
+ * query as an AND term.
+ */
+ public static final CompoundName EXTRA_TERM = new CompoundName("extraTerm");
+
+ private final List<Demo> extraTerms;
+
+ private final DemoComponent infrastructure;
+
+ public DemoSearcher(DemoComponent infrastructure, DemoConfig extraTerms) {
+ this.extraTerms = extraTerms.demo();
+ this.infrastructure = infrastructure;
+ }
+
+ /**
+ * Programmatic query transform, add terms from config and the EXTRA_TERM
+ * request property.
+ */
+ @Override
+ public Result search(Query query, Execution execution) {
+ QueryTree q = query.getModel().getQueryTree();
+ addAndItem(q, infrastructure.normalize(
+ query.properties().getString(EXTRA_TERM)));
+ for (Demo d : extraTerms) {
+ addAndItem(q, d.term());
+ }
+ return execution.search(query);
+ }
+
+ private void addAndItem(QueryTree q, String term) {
+ Item root = q.getRoot();
+ CompositeItem compositeRoot;
+ if (root instanceof AndItem) {
+ compositeRoot = (CompositeItem) root;
+ } else {
+ compositeRoot = new AndItem();
+ compositeRoot.addItem(root);
+ q.setRoot(compositeRoot);
+ }
+ compositeRoot.addItem(new WordItem(term));
+ }
+
+}
diff --git a/sample-apps/http-api-using-searcher/src/main/resources/configdefinitions/demo.def b/sample-apps/http-api-using-searcher/src/main/resources/configdefinitions/demo.def
new file mode 100644
index 00000000000..9a804089433
--- /dev/null
+++ b/sample-apps/http-api-using-searcher/src/main/resources/configdefinitions/demo.def
@@ -0,0 +1,5 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+namespace=demo
+
+demo[].term string
+
diff --git a/sample-apps/http-api-using-searcher/src/test/java/com/yahoo/example/ApplicationMain.java b/sample-apps/http-api-using-searcher/src/test/java/com/yahoo/example/ApplicationMain.java
new file mode 100644
index 00000000000..da85e486602
--- /dev/null
+++ b/sample-apps/http-api-using-searcher/src/test/java/com/yahoo/example/ApplicationMain.java
@@ -0,0 +1,27 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.example;
+
+import com.yahoo.application.Networking;
+import org.junit.Test;
+
+import java.nio.file.FileSystems;
+
+import static org.junit.Assume.assumeTrue;
+
+public class ApplicationMain {
+
+ @Test
+ public void runFromMaven() throws Exception {
+ assumeTrue(Boolean.valueOf(System.getProperty("isMavenSurefirePlugin")));
+ main(null);
+ }
+
+ public static void main(String[] args) throws Exception {
+ try (com.yahoo.application.Application app = com.yahoo.application.Application.fromApplicationPackage(
+ FileSystems.getDefault().getPath("src/main/application"),
+ Networking.enable)) {
+ app.getClass(); // throws NullPointerException
+ Thread.sleep(Long.MAX_VALUE);
+ }
+ }
+} \ No newline at end of file
diff --git a/sample-apps/pom.xml b/sample-apps/pom.xml
index 1114ff2ec4b..d39e3d1e13f 100644
--- a/sample-apps/pom.xml
+++ b/sample-apps/pom.xml
@@ -13,5 +13,7 @@
<module>basic-search-java</module>
<module>blog-recommendation</module>
<module>boolean-search</module>
+ <module>http-api-using-request-handlers-and-processors</module>
+ <module>http-api-using-searcher</module>
</modules>
</project>
diff --git a/searchcommon/src/vespa/searchcommon/attribute/search_context_params.h b/searchcommon/src/vespa/searchcommon/attribute/search_context_params.h
index 96c3d7f3470..bd88c5e5901 100644
--- a/searchcommon/src/vespa/searchcommon/attribute/search_context_params.h
+++ b/searchcommon/src/vespa/searchcommon/attribute/search_context_params.h
@@ -2,10 +2,9 @@
#pragma once
-#include <stddef.h>
+#include <cstddef>
-namespace search {
-namespace attribute {
+namespace search::attribute {
class IAttributeVector;
@@ -45,4 +44,3 @@ public:
};
}
-}
diff --git a/searchcommon/src/vespa/searchcommon/common/range.h b/searchcommon/src/vespa/searchcommon/common/range.h
index 5bcf2355eb9..f3e3156491a 100644
--- a/searchcommon/src/vespa/searchcommon/common/range.h
+++ b/searchcommon/src/vespa/searchcommon/common/range.h
@@ -5,10 +5,9 @@
#pragma once
#include <limits>
-#include <stdint.h>
+#include <cstdint>
-namespace search
-{
+namespace search {
template <typename T>
class Range {
@@ -30,4 +29,3 @@ private:
using Int64Range = Range<int64_t>;
} // namespace search
-
diff --git a/searchcore/src/apps/vespa-dump-feed/CMakeLists.txt b/searchcore/src/apps/vespa-dump-feed/CMakeLists.txt
index 85a704a7318..0d837bf05e2 100644
--- a/searchcore/src/apps/vespa-dump-feed/CMakeLists.txt
+++ b/searchcore/src/apps/vespa-dump-feed/CMakeLists.txt
@@ -2,7 +2,6 @@
vespa_add_executable(searchcore_vespa-dump-feed_app
SOURCES
vespa-dump-feed.cpp
- INSTALL bin
DEPENDS
)
vespa_add_target_system_dependency(searchcore_vespa-dump-feed_app boost boost_system-mt-d)
diff --git a/searchcore/src/apps/vespa-dump-feed/vespa-dump-feed.cpp b/searchcore/src/apps/vespa-dump-feed/vespa-dump-feed.cpp
index 59f0635d56a..a849a6fc91b 100644
--- a/searchcore/src/apps/vespa-dump-feed/vespa-dump-feed.cpp
+++ b/searchcore/src/apps/vespa-dump-feed/vespa-dump-feed.cpp
@@ -169,7 +169,7 @@ int usage() {
fprintf(stderr, " Takes an XML vespa feed as input and dumps its contents as serialized documents.\n");
fprintf(stderr, " In addition to the actual documents, an index file containing document sizes\n");
fprintf(stderr, " and the appropriate config file(s) needed for deserialization are also stored.\n");
- fprintf(stderr, " This utility can be run anywhere vespafeeder can be run with default config id.\n");
+ fprintf(stderr, " This utility can be run anywhere vespa-feeder can be run with default config id.\n");
return 1;
}
@@ -205,7 +205,7 @@ App::Main()
FeedHandler feedHooks(repo, idxFile, datFile);
std::string route = feedHooks.getRoute();
fprintf(stderr, "route to self: %s\n", route.c_str());
- std::string feedCmd(vespalib::make_string("vespafeeder --route \"%s\" %s",
+ std::string feedCmd(vespalib::make_string("vespa-feeder --route \"%s\" %s",
route.c_str(), feedFile.c_str()));
fprintf(stderr, "running feed command: %s\n", feedCmd.c_str());
std::string feederOutput;
diff --git a/searchcore/src/tests/proton/summaryengine/summaryengine.cpp b/searchcore/src/tests/proton/summaryengine/summaryengine.cpp
index 80b78d420ec..dab4dcf1dff 100644
--- a/searchcore/src/tests/proton/summaryengine/summaryengine.cpp
+++ b/searchcore/src/tests/proton/summaryengine/summaryengine.cpp
@@ -381,7 +381,7 @@ verifyReply(size_t count, document::CompressionConfig::Type encoding, size_t org
DataBuffer uncompressed;
ConstBufferRef blob(ret[2]._data._buf, ret[2]._data._len);
- document::decompress(CompressionConfig::toType(ret[0]._intval8), ret[1]._intval32, blob, uncompressed, false);
+ compression::decompress(CompressionConfig::toType(ret[0]._intval8), ret[1]._intval32, blob, uncompressed, false);
EXPECT_EQUAL(orgSize, uncompressed.getDataLen());
vespalib::Slime summaries;
@@ -402,7 +402,7 @@ verifyRPC(size_t count,
CompressionConfig config(requestCompression, 9, 100);
DataBuffer compressed(const_cast<char *>(buf.get().data), buf.get().size);
- CompressionConfig::Type type = document::compress(config, ConstBufferRef(buf.get().data, buf.get().size), compressed, true);
+ CompressionConfig::Type type = compression::compress(config, ConstBufferRef(buf.get().data, buf.get().size), compressed, true);
EXPECT_EQUAL(type, requestCompression);
FRT_RPCRequest * request = new FRT_RPCRequest();
diff --git a/searchcore/src/vespa/searchcore/config/proton.def b/searchcore/src/vespa/searchcore/config/proton.def
index c851d124970..8c4e7b4571a 100644
--- a/searchcore/src/vespa/searchcore/config/proton.def
+++ b/searchcore/src/vespa/searchcore/config/proton.def
@@ -210,21 +210,21 @@ summary.cache.allowvisitcaching bool default=false restart
summary.cache.initialentries long default=0 restart
## Control compression type of the summary while in the cache.
-summary.cache.compression.type enum {NONE, LZ4} default=LZ4 restart
+summary.cache.compression.type enum {NONE, LZ4, ZSTD} default=LZ4 restart
## Control compression level of the summary while in cache.
summary.cache.compression.level int default=9 restart
## Control compression type of the summary while in memory during compaction
## NB So far only stragey=LOG honours it.
-summary.log.compact.compression.type enum {NONE, LZ4} default=LZ4 restart
+summary.log.compact.compression.type enum {NONE, LZ4, ZSTD} default=LZ4 restart
## Control compression level of the summary while in memory during compaction
summary.log.compact.compression.level int default=9 restart
## Control compression type of the summary
## NB So far only stragey=LOG honours it.
-summary.log.chunk.compression.type enum {NONE, LZ4} default=LZ4 restart
+summary.log.chunk.compression.type enum {NONE, LZ4, ZSTD} default=LZ4 restart
## Control compression level of the summary
summary.log.chunk.compression.level int default=9 restart
diff --git a/searchcore/src/vespa/searchcore/proton/docsummary/summarymanager.cpp b/searchcore/src/vespa/searchcore/proton/docsummary/summarymanager.cpp
index 0253e943883..e5a6d6aed22 100644
--- a/searchcore/src/vespa/searchcore/proton/docsummary/summarymanager.cpp
+++ b/searchcore/src/vespa/searchcore/proton/docsummary/summarymanager.cpp
@@ -117,6 +117,8 @@ deriveCompression(const T & config) {
document::CompressionConfig compression;
if (config.type == T::LZ4) {
compression.type = document::CompressionConfig::LZ4;
+ } else if (config.type == T::ZSTD) {
+ compression.type = document::CompressionConfig::ZSTD;
}
compression.compressionLevel = config.level;
return compression;
@@ -160,6 +162,8 @@ SummaryManager::SummaryManager(vespalib::ThreadExecutor & executor,
summary.compact2buckets ? bucketizer : search::IBucketizer::SP()));
}
+SummaryManager::~SummaryManager() {}
+
void
SummaryManager::putDocument(uint64_t syncToken, const Document & doc, search::DocumentIdT lid)
{
diff --git a/searchcore/src/vespa/searchcore/proton/docsummary/summarymanager.h b/searchcore/src/vespa/searchcore/proton/docsummary/summarymanager.h
index b55345ae470..a1bcd34fd0f 100644
--- a/searchcore/src/vespa/searchcore/proton/docsummary/summarymanager.h
+++ b/searchcore/src/vespa/searchcore/proton/docsummary/summarymanager.h
@@ -82,6 +82,7 @@ public:
const search::common::FileHeaderContext &fileHeaderContext,
search::transactionlog::SyncProxy &tlSyncer,
const std::shared_ptr<search::IBucketizer> & bucketizer);
+ ~SummaryManager();
void putDocument(uint64_t syncToken, const document::Document & doc,
search::DocumentIdT lid);
diff --git a/searchcore/src/vespa/searchcore/proton/summaryengine/docsum_by_slime.cpp b/searchcore/src/vespa/searchcore/proton/summaryengine/docsum_by_slime.cpp
index 99b39f68006..465c6fa9d03 100644
--- a/searchcore/src/vespa/searchcore/proton/summaryengine/docsum_by_slime.cpp
+++ b/searchcore/src/vespa/searchcore/proton/summaryengine/docsum_by_slime.cpp
@@ -4,9 +4,9 @@
#include <vespa/searchlib/util/slime_output_raw_buf_adapter.h>
#include <vespa/searchlib/common/packets.h>
#include <vespa/fnet/frt/rpcrequest.h>
+#include <vespa/vespalib/data/databuffer.h>
#include <vespa/log/log.h>
-
LOG_SETUP(".proton.summaryengine.docsum_by_slime");
namespace proton {
@@ -90,12 +90,14 @@ DocsumByRPC::DocsumByRPC(DocsumBySlime & slimeDocsumServer) :
void
DocsumByRPC::getDocsums(FRT_RPCRequest & req)
{
+ using document::compression::decompress;
+ using document::compression::compress;
FRT_Values &arg = *req.GetParams();
uint8_t encoding = arg[0]._intval8;
uint32_t uncompressedSize = arg[1]._intval32;
DataBuffer uncompressed(arg[2]._data._buf, arg[2]._data._len);
ConstBufferRef blob(arg[2]._data._buf, arg[2]._data._len);
- document::decompress(CompressionConfig::toType(encoding), uncompressedSize, blob, uncompressed, true);
+ decompress(CompressionConfig::toType(encoding), uncompressedSize, blob, uncompressed, true);
assert(uncompressedSize == uncompressed.getDataLen());
vespalib::Slime summariesToGet;
BinaryFormat::decode(Memory(uncompressed.getData(), uncompressed.getDataLen()), summariesToGet);
@@ -108,7 +110,7 @@ DocsumByRPC::getDocsums(FRT_RPCRequest & req)
BinaryFormat::encode(*summaries, output);
ConstBufferRef buf(rbuf.GetDrainPos(), rbuf.GetUsedLen());
DataBuffer compressed(rbuf.GetWritableDrainPos(0), rbuf.GetUsedLen());
- CompressionConfig::Type type = document::compress(getCompressionConfig(), buf, compressed, true);
+ CompressionConfig::Type type = compress(getCompressionConfig(), buf, compressed, true);
FRT_Values &ret = *req.GetReturn();
ret.AddInt8(type);
diff --git a/searchlib/src/tests/docstore/chunk/chunk_test.cpp b/searchlib/src/tests/docstore/chunk/chunk_test.cpp
index 8b08fb278e3..9be11dba84b 100644
--- a/searchlib/src/tests/docstore/chunk/chunk_test.cpp
+++ b/searchlib/src/tests/docstore/chunk/chunk_test.cpp
@@ -68,4 +68,34 @@ TEST("require that Chunk formats does not change between releases")
testChunkFormat(v2, 34, "34 015BA32DE7000000220000000010ABCDEF987654321000000000000000074D000694");
}
+constexpr const char * MY_LONG_STRING = "This is medium long string that hopefully will compress to something where lz4, zstandard and none"
+" will make a difference. The intentions is to verify that we trigger all compresssions possible and are able to decompress them too."
+" I guess that we need a considerable length in order to get the rather inefficient lz4 compression triger. ZStandard compression"
+" should trigger a lot earlier";
+
+void verifyChunkCompression(CompressionConfig::Type cfgType, const void * buf, size_t sz, size_t expectedLen) {
+ uint64_t MAGIC_CONTENT(0xabcdef9876543210);
+ ChunkFormatV2 chunk(10);
+ chunk.getBuffer() << MAGIC_CONTENT;
+ chunk.getBuffer().write(buf, sz);
+ vespalib::DataBuffer buffer;
+ CompressionConfig cfg(cfgType);
+ chunk.pack(7, buffer, cfg);
+ EXPECT_EQUAL(expectedLen, buffer.getDataLen());
+ vespalib::nbostream is(buffer.getData(), buffer.getDataLen());
+ ChunkFormat::UP deserialized = ChunkFormat::deserialize(buffer.getData(), buffer.getDataLen(), false);
+ uint64_t magic(0);
+ deserialized->getBuffer() >> magic;
+ EXPECT_EQUAL(MAGIC_CONTENT, magic);
+ std::vector<char> v(sz);
+ deserialized->getBuffer().read(&v[0], sz);
+ EXPECT_EQUAL(0, memcmp(buf, &v[0], sz));
+}
+
+TEST("require that V2 can create and handle lz4, zstd, and none") {
+ verifyChunkCompression(CompressionConfig::NONE, MY_LONG_STRING, strlen(MY_LONG_STRING), 421);
+ verifyChunkCompression(CompressionConfig::LZ4, MY_LONG_STRING, strlen(MY_LONG_STRING), 360);
+ verifyChunkCompression(CompressionConfig::ZSTD, MY_LONG_STRING, strlen(MY_LONG_STRING), 282);
+}
+
TEST_MAIN() { TEST_RUN_ALL(); }
diff --git a/searchlib/src/vespa/searchlib/attribute/attributevector.cpp b/searchlib/src/vespa/searchlib/attribute/attributevector.cpp
index 6abf0ac5f27..1908d22d7b9 100644
--- a/searchlib/src/vespa/searchlib/attribute/attributevector.cpp
+++ b/searchlib/src/vespa/searchlib/attribute/attributevector.cpp
@@ -579,10 +579,10 @@ AttributeVector::SearchContext::
createIterator(fef::TermFieldMatchData *matchData, bool strict)
{
if (_plsc != NULL) {
- SearchIterator::UP res =
- _plsc->createPostingIterator(matchData, strict);
- if (res.get() != NULL)
+ SearchIterator::UP res = _plsc->createPostingIterator(matchData, strict);
+ if (res) {
return res;
+ }
}
return createFilterIterator(matchData, strict);
}
diff --git a/searchlib/src/vespa/searchlib/attribute/enumstorebase.h b/searchlib/src/vespa/searchlib/attribute/enumstorebase.h
index 2960d573098..fe96928dccd 100644
--- a/searchlib/src/vespa/searchlib/attribute/enumstorebase.h
+++ b/searchlib/src/vespa/searchlib/attribute/enumstorebase.h
@@ -7,8 +7,8 @@
#include <vespa/searchlib/datastore/datastore.h>
#include <vespa/searchlib/util/memoryusage.h>
#include <vespa/vespalib/util/array.h>
-#include <set>
#include <vespa/searchlib/btree/btree.h>
+#include <set>
#include <atomic>
namespace vespalib { class asciistream; }
diff --git a/searchlib/src/vespa/searchlib/attribute/postingchange.cpp b/searchlib/src/vespa/searchlib/attribute/postingchange.cpp
index c972e25a7cf..0b7430599b9 100644
--- a/searchlib/src/vespa/searchlib/attribute/postingchange.cpp
+++ b/searchlib/src/vespa/searchlib/attribute/postingchange.cpp
@@ -4,6 +4,7 @@
#include "multivalue.h"
#include "multi_value_mapping.h"
#include "postinglistattribute.h"
+#include <vespa/searchlib/common/growablebitvector.h>
#include <vespa/vespalib/util/array.hpp>
namespace search {
diff --git a/searchlib/src/vespa/searchlib/attribute/postinglistsearchcontext.h b/searchlib/src/vespa/searchlib/attribute/postinglistsearchcontext.h
index 9665872f8de..cb3dd844041 100644
--- a/searchlib/src/vespa/searchlib/attribute/postinglistsearchcontext.h
+++ b/searchlib/src/vespa/searchlib/attribute/postinglistsearchcontext.h
@@ -6,13 +6,11 @@
#include "postinglisttraits.h"
#include "postingstore.h"
#include "ipostinglistsearchcontext.h"
-#include "attributevector.h"
+#include <vespa/searchcommon/attribute/search_context_params.h>
+#include <vespa/searchcommon/common/range.h>
#include <vespa/vespalib/util/regexp.h>
-#include <cstdlib>
-namespace search {
-
-namespace attribute {
+namespace search::attribute {
/**
* Search context helper for posting list attributes, used to instantiate
@@ -22,11 +20,11 @@ namespace attribute {
class PostingListSearchContext : public IPostingListSearchContext
{
protected:
- typedef EnumPostingTree Dictionary;
- typedef Dictionary::ConstIterator DictionaryConstIterator;
- typedef Dictionary::FrozenView FrozenDictionary;
- typedef EnumStoreBase::Index EnumIndex;
-
+ using Dictionary = EnumPostingTree;
+ using DictionaryConstIterator = Dictionary::ConstIterator;
+ using FrozenDictionary = Dictionary::FrozenView;
+ using EnumIndex = EnumStoreBase::Index;
+
const FrozenDictionary _frozenDictionary;
DictionaryConstIterator _lowerDictItr;
DictionaryConstIterator _upperDictItr;
@@ -36,22 +34,17 @@ protected:
uint64_t _numValues; // attr.getStatus().getNumValues();
bool _hasWeight;
bool _useBitVector;
- search::datastore::EntryRef _pidx;
- search::datastore::EntryRef _frozenRoot; // Posting list in tree form
+ datastore::EntryRef _pidx;
+ datastore::EntryRef _frozenRoot; // Posting list in tree form
float _FSTC; // Filtering Search Time Constant
float _PLSTC; // Posting List Search Time Constant
const EnumStoreBase &_esb;
uint32_t _minBvDocFreq;
const GrowableBitVector *_gbv; // bitvector if _useBitVector has been set
-
- PostingListSearchContext(const Dictionary &dictionary,
- uint32_t docIdLimit,
- uint64_t numValues,
- bool hasWeight,
- const EnumStoreBase &esb,
- uint32_t minBvDocFreq,
- bool useBitVector);
+
+ PostingListSearchContext(const Dictionary &dictionary, uint32_t docIdLimit, uint64_t numValues, bool hasWeight,
+ const EnumStoreBase &esb, uint32_t minBvDocFreq, bool useBitVector);
~PostingListSearchContext();
@@ -96,13 +89,13 @@ template <class DataT>
class PostingListSearchContextT : public PostingListSearchContext
{
protected:
- typedef DataT DataType;
- typedef PostingListTraits<DataType> Traits;
- typedef typename Traits::PostingList PostingList;
- typedef typename Traits::Posting Posting;
- typedef std::vector<Posting> PostingVector;
- typedef datastore::EntryRef EntryRef;
- typedef typename PostingList::ConstIterator PostingConstIterator;
+ using DataType = DataT;
+ using Traits = PostingListTraits<DataType>;
+ using PostingList = typename Traits::PostingList;
+ using Posting = typename Traits::Posting;
+ using PostingVector = std::vector<Posting>;
+ using EntryRef = datastore::EntryRef;
+ using FrozenView = typename PostingList::BTreeType::FrozenView;
const PostingList &_postingList;
/*
@@ -112,19 +105,14 @@ protected:
std::unique_ptr<BitVector> _bitVector;
bool _fetchPostingsDone;
bool _arrayValid;
-
+
static const long MIN_UNIQUE_VALUES_BEFORE_APPROXIMATION = 100;
static const long MIN_UNIQUE_VALUES_TO_NUMDOCS_RATIO_BEFORE_APPROXIMATION = 20;
static const long MIN_APPROXHITS_TO_NUMDOCS_RATIO_BEFORE_APPROXIMATION = 10;
- PostingListSearchContextT(const Dictionary &dictionary,
- uint32_t docIdLimit,
- uint64_t numValues,
- bool hasWeight,
- const PostingList &postingList,
- const EnumStoreBase &esb,
- uint32_t minBvCocFreq,
- bool useBitVector);
+ PostingListSearchContextT(const Dictionary &dictionary, uint32_t docIdLimit, uint64_t numValues,
+ bool hasWeight, const PostingList &postingList, const EnumStoreBase &esb,
+ uint32_t minBvCocFreq, bool useBitVector);
~PostingListSearchContextT();
void lookupSingle();
@@ -133,16 +121,14 @@ protected:
void fillBitVector();
PostingVector &
- merge(PostingVector &v, PostingVector &temp,
- const std::vector<size_t> & startPos) __attribute__((noinline));
+ merge(PostingVector &v, PostingVector &temp, const std::vector<size_t> & startPos) __attribute__((noinline));
void fetchPostings(bool strict) override;
// this will be called instead of the fetchPostings function in some cases
- void diversify(bool forward, size_t wanted_hits,
- const IAttributeVector &diversity_attr, size_t max_per_group,
- size_t cutoff_groups, bool cutoff_strict);
+ void diversify(bool forward, size_t wanted_hits, const IAttributeVector &diversity_attr,
+ size_t max_per_group, size_t cutoff_groups, bool cutoff_strict);
- queryeval::SearchIterator::UP
+ std::unique_ptr<queryeval::SearchIterator>
createPostingIterator(fef::TermFieldMatchData *matchData, bool strict) override;
unsigned int singleHits() const;
@@ -155,9 +141,9 @@ template <class DataT>
class PostingListFoldedSearchContextT : public PostingListSearchContextT<DataT>
{
protected:
- typedef PostingListSearchContextT<DataT> Parent;
- typedef typename Parent::Dictionary Dictionary;
- typedef typename Parent::PostingList PostingList;
+ using Parent = PostingListSearchContextT<DataT>;
+ using Dictionary = typename Parent::Dictionary;
+ using PostingList = typename Parent::PostingList;
using Parent::_lowerDictItr;
using Parent::_uniqueValues;
using Parent::_postingList;
@@ -165,14 +151,9 @@ protected:
using Parent::countHits;
using Parent::singleHits;
- PostingListFoldedSearchContextT(const Dictionary &dictionary,
- uint32_t docIdLimit,
- uint64_t numValues,
- bool hasWeight,
- const PostingList &postingList,
- const EnumStoreBase &esb,
- uint32_t minBvCocFreq,
- bool useBitVector);
+ PostingListFoldedSearchContextT(const Dictionary &dictionary, uint32_t docIdLimit, uint64_t numValues,
+ bool hasWeight, const PostingList &postingList, const EnumStoreBase &esb,
+ uint32_t minBvCocFreq, bool useBitVector);
unsigned int approximateHits() const override;
};
@@ -183,12 +164,12 @@ class PostingSearchContext: public BaseSC,
public BaseSC2
{
public:
- typedef typename AttrT::EnumStore EnumStore;
+ using EnumStore = typename AttrT::EnumStore;
using QueryTermSimpleUP = std::unique_ptr<QueryTermSimple>;
protected:
const AttrT &_toBeSearched;
const EnumStore &_enumStore;
-
+
PostingSearchContext(QueryTermSimpleUP qTerm, bool useBitVector, const AttrT &toBeSearched);
~PostingSearchContext();
};
@@ -198,14 +179,11 @@ class StringPostingSearchContext
: public PostingSearchContext<BaseSC, PostingListFoldedSearchContextT<DataT>, AttrT>
{
private:
- typedef PostingListTraits<DataT> AggregationTraits;
- typedef typename AggregationTraits::PostingList PostingList;
- typedef typename PostingList::Iterator PostingIterator;
- typedef typename PostingList::ConstIterator PostingConstIterator;
- typedef PostingSearchContext<BaseSC, PostingListFoldedSearchContextT<DataT>, AttrT> Parent;
- typedef typename Parent::EnumStore EnumStore;
- typedef typename EnumStore::FoldedComparatorType FoldedComparatorType;
- typedef vespalib::Regexp Regexp;
+ using AggregationTraits = PostingListTraits<DataT>;
+ using PostingList = typename AggregationTraits::PostingList;
+ using Parent = PostingSearchContext<BaseSC, PostingListFoldedSearchContextT<DataT>, AttrT>;
+ using FoldedComparatorType = typename Parent::EnumStore::FoldedComparatorType;
+ using Regexp = vespalib::Regexp;
using QueryTermSimpleUP = typename Parent::QueryTermSimpleUP;
using Parent::_toBeSearched;
using Parent::_enumStore;
@@ -225,10 +203,7 @@ private:
typedef PostingSearchContext<BaseSC, PostingListSearchContextT<DataT>, AttrT> Parent;
typedef PostingListTraits<DataT> AggregationTraits;
typedef typename AggregationTraits::PostingList PostingList;
- typedef typename PostingList::Iterator PostingIterator;
- typedef typename PostingList::ConstIterator PostingConstIterator;
- typedef typename Parent::EnumStore EnumStore;
- typedef typename EnumStore::ComparatorType ComparatorType;
+ typedef typename Parent::EnumStore::ComparatorType ComparatorType;
typedef typename AttrT::T BaseType;
using Params = attribute::SearchContextParams;
using QueryTermSimpleUP = typename Parent::QueryTermSimpleUP;
@@ -237,7 +212,7 @@ private:
using Parent::_toBeSearched;
using Parent::_enumStore;
Params _params;
-
+
void getIterators(bool shouldApplyRangeLimit);
bool valid() const override { return this->isValid(); }
@@ -269,8 +244,8 @@ public:
NumericPostingSearchContext(QueryTermSimpleUP qTerm, const Params & params, const AttrT &toBeSearched);
const Params &params() const { return _params; }
};
-
-
+
+
template <typename BaseSC, typename BaseSC2, typename AttrT>
PostingSearchContext<BaseSC, BaseSC2, AttrT>::
PostingSearchContext(QueryTermSimpleUP qTerm, bool useBitVector, const AttrT &toBeSearched)
@@ -305,7 +280,7 @@ StringPostingSearchContext(QueryTermSimpleUP qTerm, bool useBitVector, const Att
// after benchmarking prefix search performance on single, array, and weighted set fast-search string attributes
// with 1M values the following constant has been derived:
this->_PLSTC = 0.000000;
-
+
if (this->valid()) {
if (this->isPrefix()) {
FoldedComparatorType comp(_enumStore, this->queryTerm().getTerm(), true);
@@ -386,7 +361,4 @@ extern template class PostingListSearchContextT<int32_t>;
extern template class PostingListFoldedSearchContextT<btree::BTreeNoLeafData>;
extern template class PostingListFoldedSearchContextT<int32_t>;
-} // namespace attribute
-
-} // namespace search
-
+}
diff --git a/searchlib/src/vespa/searchlib/attribute/postinglistsearchcontext.hpp b/searchlib/src/vespa/searchlib/attribute/postinglistsearchcontext.hpp
index 270ae161f4c..573af5f40bd 100644
--- a/searchlib/src/vespa/searchlib/attribute/postinglistsearchcontext.hpp
+++ b/searchlib/src/vespa/searchlib/attribute/postinglistsearchcontext.hpp
@@ -5,28 +5,23 @@
#include "dociditerator.h"
#include "attributeiterators.h"
#include "diversity.h"
+#include "postingstore.hpp"
#include <vespa/searchlib/queryeval/emptysearch.h>
#include <vespa/searchlib/common/bitvectoriterator.h>
+#include <vespa/searchlib/common/growablebitvector.h>
-namespace search {
-using queryeval::EmptySearch;
-using queryeval::SearchIterator;
+using search::queryeval::EmptySearch;
+using search::queryeval::SearchIterator;
-namespace attribute {
+namespace search::attribute {
template <typename DataT>
PostingListSearchContextT<DataT>::
-PostingListSearchContextT(const Dictionary &dictionary,
- uint32_t docIdLimit,
- uint64_t numValues,
- bool hasWeight,
- const PostingList &postingList,
- const EnumStoreBase &esb,
- uint32_t minBvDocFreq,
- bool useBitVector)
- : PostingListSearchContext(dictionary, docIdLimit, numValues, hasWeight,
- esb, minBvDocFreq, useBitVector),
+PostingListSearchContextT(const Dictionary &dictionary, uint32_t docIdLimit, uint64_t numValues, bool hasWeight,
+ const PostingList &postingList, const EnumStoreBase &esb,
+ uint32_t minBvDocFreq, bool useBitVector)
+ : PostingListSearchContext(dictionary, docIdLimit, numValues, hasWeight, esb, minBvDocFreq, useBitVector),
_postingList(postingList),
_array(),
_bitVector(),
@@ -56,9 +51,7 @@ PostingListSearchContextT<DataT>::lookupSingle()
} else {
_pidx = bve->_tree;
if (_pidx.valid()) {
- typename PostingList::BTreeType::FrozenView
- frozenView(_postingList.getTreeEntry(_pidx)->
- getFrozenView(_postingList.getAllocator()));
+ auto frozenView = _postingList.getTreeEntry(_pidx)->getFrozenView(_postingList.getAllocator());
_frozenRoot = frozenView.getRoot();
if (!_frozenRoot.valid()) {
_pidx = datastore::EntryRef();
@@ -68,9 +61,7 @@ PostingListSearchContextT<DataT>::lookupSingle()
}
}
} else {
- typename PostingList::BTreeType::FrozenView
- frozenView(_postingList.getTreeEntry(_pidx)->
- getFrozenView(_postingList.getAllocator()));
+ auto frozenView = _postingList.getTreeEntry(_pidx)->getFrozenView(_postingList.getAllocator());
_frozenRoot = frozenView.getRoot();
if (!_frozenRoot.valid()) {
_pidx = datastore::EntryRef();
@@ -106,8 +97,8 @@ PostingListSearchContextT<DataT>::fillArray(size_t numDocs)
for (auto it(_lowerDictItr); it != _upperDictItr; ++it) {
if (useThis(it)) {
_postingList.foreach_frozen(it.getData(),
- [&](uint32_t key, const DataT &data)
- { _array.push_back(Posting(key, data));
+ [&](uint32_t key, const DataT &data) {
+ _array.push_back(Posting(key, data));
});
startPos.push_back(_array.size());
}
@@ -130,8 +121,8 @@ PostingListSearchContextT<DataT>::fillBitVector()
for (auto it(_lowerDictItr); it != _upperDictItr; ++it) {
if (useThis(it)) {
_postingList.foreach_frozen_key(it.getData(),
- [&](uint32_t key)
- { if (key < limit) {
+ [&](uint32_t key) {
+ if (key < limit) {
bv.setBit(key);
}
});
@@ -193,9 +184,8 @@ PostingListSearchContextT<DataT>::fetchPostings(bool strict)
template <typename DataT>
void
-PostingListSearchContextT<DataT>::diversify(bool forward, size_t wanted_hits,
- const IAttributeVector &diversity_attr, size_t max_per_group,
- size_t cutoff_groups, bool cutoff_strict)
+PostingListSearchContextT<DataT>::diversify(bool forward, size_t wanted_hits, const IAttributeVector &diversity_attr,
+ size_t max_per_group, size_t cutoff_groups, bool cutoff_strict)
{
assert(!_fetchPostingsDone);
_fetchPostingsDone = true;
@@ -203,9 +193,8 @@ PostingListSearchContextT<DataT>::diversify(bool forward, size_t wanted_hits,
_array.reserve(wanted_hits);
std::vector<size_t> fragments;
fragments.push_back(0);
- diversity::diversify(forward, _lowerDictItr, _upperDictItr, _postingList, wanted_hits,
- diversity_attr, max_per_group, cutoff_groups, cutoff_strict,
- _array, fragments);
+ diversity::diversify(forward, _lowerDictItr, _upperDictItr, _postingList, wanted_hits, diversity_attr,
+ max_per_group, cutoff_groups, cutoff_strict, _array, fragments);
if (fragments.size() > 2) {
PostingVector temp(_array.size());
_array.swap(merge(_array, temp, fragments));
@@ -226,12 +215,14 @@ createPostingIterator(fef::TermFieldMatchData *matchData, bool strict)
if (_arrayValid || (_bitVector.get() != nullptr)) { // synthetic results are available
if (!_array.empty()) {
assert(_arrayValid);
- typedef DocIdIterator<Posting> DocIt;
+ using DocIt = DocIdIterator<Posting>;
DocIt postings;
postings.set(&_array[0], &_array[_array.size()]);
- return (_postingList._isFilter)
- ? SearchIterator::UP(new FilterAttributePostingListIteratorT<DocIt>(matchData, postings))
- : SearchIterator::UP(new AttributePostingListIteratorT<DocIt>(_hasWeight, matchData, postings));
+ if (_postingList._isFilter) {
+ return std::make_unique<FilterAttributePostingListIteratorT<DocIt>>(matchData, postings);
+ } else {
+ return std::make_unique<AttributePostingListIteratorT<DocIt>>(_hasWeight, matchData, postings);
+ }
}
if (_arrayValid) {
return SearchIterator::UP(new EmptySearch());
@@ -251,19 +242,24 @@ createPostingIterator(fef::TermFieldMatchData *matchData, bool strict)
if (!_frozenRoot.valid()) {
uint32_t clusterSize = _postingList.getClusterSize(_pidx);
assert(clusterSize != 0);
- typedef DocIdMinMaxIterator<Posting> DocIt;
+ using DocIt = DocIdMinMaxIterator<Posting>;
DocIt postings;
const Posting *array = postingList.getKeyDataEntry(_pidx, clusterSize);
postings.set(array, array + clusterSize);
- return (postingList._isFilter)
- ? SearchIterator::UP(new FilterAttributePostingListIteratorT<DocIt>(matchData, postings))
- : SearchIterator::UP(new AttributePostingListIteratorT<DocIt>(_hasWeight, matchData, postings));
+ if (postingList._isFilter) {
+ return std::make_unique<FilterAttributePostingListIteratorT<DocIt>>(matchData, postings);
+ } else {
+ return std::make_unique<AttributePostingListIteratorT<DocIt>>(_hasWeight, matchData, postings);
+ }
}
typename PostingList::BTreeType::FrozenView frozen(_frozenRoot, postingList.getAllocator());
- return (_postingList._isFilter)
- ? SearchIterator::UP(new FilterAttributePostingListIteratorT<PostingConstIterator> (matchData, frozen.getRoot(), frozen.getAllocator()))
- : SearchIterator::UP(new AttributePostingListIteratorT<PostingConstIterator> (_hasWeight, matchData, frozen.getRoot(), frozen.getAllocator()));
+ using DocIt = typename PostingList::ConstIterator;
+ if (_postingList._isFilter) {
+ return std::make_unique<FilterAttributePostingListIteratorT<DocIt>>(matchData, frozen.getRoot(), frozen.getAllocator());
+ } else {
+ return std::make_unique<AttributePostingListIteratorT<DocIt>> (_hasWeight, matchData, frozen.getRoot(), frozen.getAllocator());
+ }
}
// returning nullptr will trigger fallback to filter iterator
return SearchIterator::UP();
@@ -300,12 +296,10 @@ PostingListSearchContextT<DataT>::approximateHits() const
if (this->fallbackToFiltering()) {
numHits = _docIdLimit;
} else if (_uniqueValues > MIN_UNIQUE_VALUES_BEFORE_APPROXIMATION) {
- if ((_uniqueValues *
- MIN_UNIQUE_VALUES_TO_NUMDOCS_RATIO_BEFORE_APPROXIMATION >
- static_cast<int>(_docIdLimit)) ||
- (this->calculateApproxNumHits() *
- MIN_APPROXHITS_TO_NUMDOCS_RATIO_BEFORE_APPROXIMATION >
- _docIdLimit)) {
+ if ((_uniqueValues * MIN_UNIQUE_VALUES_TO_NUMDOCS_RATIO_BEFORE_APPROXIMATION > static_cast<int>(_docIdLimit)) ||
+ (this->calculateApproxNumHits() * MIN_APPROXHITS_TO_NUMDOCS_RATIO_BEFORE_APPROXIMATION > _docIdLimit) ||
+ (_uniqueValues > MIN_UNIQUE_VALUES_BEFORE_APPROXIMATION*10))
+ {
numHits = this->calculateApproxNumHits();
} else {
// XXX: Unsafe
@@ -346,16 +340,10 @@ PostingListSearchContextT<DataT>::applyRangeLimit(int rangeLimit)
template <typename DataT>
PostingListFoldedSearchContextT<DataT>::
-PostingListFoldedSearchContextT(const Dictionary &dictionary,
- uint32_t docIdLimit,
- uint64_t numValues,
- bool hasWeight,
- const PostingList &postingList,
- const EnumStoreBase &esb,
- uint32_t minBvDocFreq,
- bool useBitVector)
- : Parent(dictionary, docIdLimit, numValues, hasWeight, postingList,
- esb, minBvDocFreq, useBitVector)
+PostingListFoldedSearchContextT(const Dictionary &dictionary, uint32_t docIdLimit, uint64_t numValues,
+ bool hasWeight, const PostingList &postingList, const EnumStoreBase &esb,
+ uint32_t minBvDocFreq, bool useBitVector)
+ : Parent(dictionary, docIdLimit, numValues, hasWeight, postingList, esb, minBvDocFreq, useBitVector)
{
}
@@ -379,7 +367,4 @@ PostingListFoldedSearchContextT<DataT>::approximateHits() const
return numHits;
}
-} // namespace attribute
-
-} // namespace search
-
+}
diff --git a/searchlib/src/vespa/searchlib/attribute/postinglisttraits.h b/searchlib/src/vespa/searchlib/attribute/postinglisttraits.h
index c2504f779a1..d619751d451 100644
--- a/searchlib/src/vespa/searchlib/attribute/postinglisttraits.h
+++ b/searchlib/src/vespa/searchlib/attribute/postinglisttraits.h
@@ -4,11 +4,9 @@
#include <vespa/searchlib/btree/btreestore.h>
-namespace search
-{
+namespace search {
-namespace attribute
-{
+namespace attribute {
template <typename DataT> class PostingListTraits;
template <typename DataT> class PostingStore;
diff --git a/searchlib/src/vespa/searchlib/attribute/postingstore.cpp b/searchlib/src/vespa/searchlib/attribute/postingstore.cpp
index a21884bca4a..e1b0cf24305 100644
--- a/searchlib/src/vespa/searchlib/attribute/postingstore.cpp
+++ b/searchlib/src/vespa/searchlib/attribute/postingstore.cpp
@@ -3,12 +3,11 @@
#include "postingstore.h"
#include <vespa/searchlib/datastore/datastore.hpp>
#include <vespa/searchlib/btree/btreeiterator.hpp>
+#include <vespa/searchlib/common/growablebitvector.h>
#include <vespa/searchcommon/attribute/config.h>
#include <vespa/searchcommon/attribute/status.h>
-namespace search {
-
-namespace attribute {
+namespace search::attribute {
using btree::BTreeNoLeafData;
@@ -635,6 +634,4 @@ template class PostingStore<BTreeNoLeafData>;
template class PostingStore<int32_t>;
-} // namespace btree
-
-} // namespace search
+}
diff --git a/searchlib/src/vespa/searchlib/attribute/postingstore.h b/searchlib/src/vespa/searchlib/attribute/postingstore.h
index 9aae723db73..9c34344451a 100644
--- a/searchlib/src/vespa/searchlib/attribute/postingstore.h
+++ b/searchlib/src/vespa/searchlib/attribute/postingstore.h
@@ -5,12 +5,13 @@
#include "postinglisttraits.h"
#include "enumstorebase.h"
#include <set>
-#include <vespa/searchlib/common/bitvector.h>
-#include <vespa/searchlib/common/growablebitvector.h>
namespace search {
+ class BitVector;
+ class GrowableBitVector;
+}
-namespace attribute {
+namespace search::attribute {
class Status;
class Config;
@@ -43,9 +44,9 @@ public:
uint32_t _maxBvDocFreq; // Greater than or equal to this ==> create bv
protected:
std::set<uint32_t> _bvs; // Current bitvectors
- EnumPostingTree &_dict;
- Status &_status;
- uint64_t _bvExtraBytes;
+ EnumPostingTree &_dict;
+ Status &_status;
+ uint64_t _bvExtraBytes;
static constexpr uint32_t BUFFERTYPE_BITVECTOR = 9u;
@@ -197,90 +198,4 @@ PostingStore<int32_t>::bitVectorWeight()
return 1;
}
-template <typename DataT>
-template <typename FunctionType>
-void
-PostingStore<DataT>::foreach_frozen_key(EntryRef ref, FunctionType func) const
-{
- if (!ref.valid())
- return;
- RefType iRef(ref);
- uint32_t typeId = getTypeId(iRef);
- uint32_t clusterSize = getClusterSize(typeId);
- if (clusterSize == 0) {
- if (isBitVector(typeId)) {
- const BitVectorEntry *bve = getBitVectorEntry(iRef);
- EntryRef ref2(bve->_tree);
- RefType iRef2(ref2);
- if (iRef2.valid()) {
- assert(isBTree(iRef2));
- const BTreeType *tree = getTreeEntry(iRef2);
- _allocator.getNodeStore().foreach_key(tree->getFrozenRoot(), func);
- } else {
- const BitVector *bv = bve->_bv.get();
- uint32_t docIdLimit = bv->size();
- uint32_t docId = bv->getFirstTrueBit(1);
- while (docId < docIdLimit) {
- func(docId);
- docId = bv->getNextTrueBit(docId + 1);
- }
- }
- } else {
- assert(isBTree(typeId));
- const BTreeType *tree = getTreeEntry(iRef);
- _allocator.getNodeStore().foreach_key(tree->getFrozenRoot(), func);
- }
- } else {
- const KeyDataType *p = getKeyDataEntry(iRef, clusterSize);
- const KeyDataType *pe = p + clusterSize;
- for (; p != pe; ++p) {
- func(p->_key);
- }
- }
-}
-
-
-template <typename DataT>
-template <typename FunctionType>
-void
-PostingStore<DataT>::foreach_frozen(EntryRef ref, FunctionType func) const
-{
- if (!ref.valid())
- return;
- RefType iRef(ref);
- uint32_t typeId = getTypeId(iRef);
- uint32_t clusterSize = getClusterSize(typeId);
- if (clusterSize == 0) {
- if (isBitVector(typeId)) {
- const BitVectorEntry *bve = getBitVectorEntry(iRef);
- EntryRef ref2(bve->_tree);
- RefType iRef2(ref2);
- if (iRef2.valid()) {
- assert(isBTree(iRef2));
- const BTreeType *tree = getTreeEntry(iRef2);
- _allocator.getNodeStore().foreach(tree->getFrozenRoot(), func);
- } else {
- const BitVector *bv = bve->_bv.get();
- uint32_t docIdLimit = bv->size();
- uint32_t docId = bv->getFirstTrueBit(1);
- while (docId < docIdLimit) {
- func(docId, bitVectorWeight());
- docId = bv->getNextTrueBit(docId + 1);
- }
- }
- } else {
- const BTreeType *tree = getTreeEntry(iRef);
- _allocator.getNodeStore().foreach(tree->getFrozenRoot(), func);
- }
- } else {
- const KeyDataType *p = getKeyDataEntry(iRef, clusterSize);
- const KeyDataType *pe = p + clusterSize;
- for (; p != pe; ++p) {
- func(p->_key, p->getData());
- }
- }
}
-
-} // namespace attribute
-
-} // namespace search
diff --git a/searchlib/src/vespa/searchlib/attribute/postingstore.hpp b/searchlib/src/vespa/searchlib/attribute/postingstore.hpp
new file mode 100644
index 00000000000..6680fc86f71
--- /dev/null
+++ b/searchlib/src/vespa/searchlib/attribute/postingstore.hpp
@@ -0,0 +1,90 @@
+#pragma once
+
+#include "postingstore.h"
+#include <vespa/searchlib/common/growablebitvector.h>
+
+namespace search::attribute {
+
+template<typename DataT>
+template<typename FunctionType>
+void
+PostingStore<DataT>::foreach_frozen_key(EntryRef ref, FunctionType func) const {
+ if (!ref.valid())
+ return;
+ RefType iRef(ref);
+ uint32_t typeId = getTypeId(iRef);
+ uint32_t clusterSize = getClusterSize(typeId);
+ if (clusterSize == 0) {
+ if (isBitVector(typeId)) {
+ const BitVectorEntry *bve = getBitVectorEntry(iRef);
+ EntryRef ref2(bve->_tree);
+ RefType iRef2(ref2);
+ if (iRef2.valid()) {
+ assert(isBTree(iRef2));
+ const BTreeType *tree = getTreeEntry(iRef2);
+ _allocator.getNodeStore().foreach_key(tree->getFrozenRoot(), func);
+ } else {
+ const BitVector *bv = bve->_bv.get();
+ uint32_t docIdLimit = bv->size();
+ uint32_t docId = bv->getFirstTrueBit(1);
+ while (docId < docIdLimit) {
+ func(docId);
+ docId = bv->getNextTrueBit(docId + 1);
+ }
+ }
+ } else {
+ assert(isBTree(typeId));
+ const BTreeType *tree = getTreeEntry(iRef);
+ _allocator.getNodeStore().foreach_key(tree->getFrozenRoot(), func);
+ }
+ } else {
+ const KeyDataType *p = getKeyDataEntry(iRef, clusterSize);
+ const KeyDataType *pe = p + clusterSize;
+ for (; p != pe; ++p) {
+ func(p->_key);
+ }
+ }
+}
+
+
+template<typename DataT>
+template<typename FunctionType>
+void
+PostingStore<DataT>::foreach_frozen(EntryRef ref, FunctionType func) const {
+ if (!ref.valid())
+ return;
+ RefType iRef(ref);
+ uint32_t typeId = getTypeId(iRef);
+ uint32_t clusterSize = getClusterSize(typeId);
+ if (clusterSize == 0) {
+ if (isBitVector(typeId)) {
+ const BitVectorEntry *bve = getBitVectorEntry(iRef);
+ EntryRef ref2(bve->_tree);
+ RefType iRef2(ref2);
+ if (iRef2.valid()) {
+ assert(isBTree(iRef2));
+ const BTreeType *tree = getTreeEntry(iRef2);
+ _allocator.getNodeStore().foreach(tree->getFrozenRoot(), func);
+ } else {
+ const BitVector *bv = bve->_bv.get();
+ uint32_t docIdLimit = bv->size();
+ uint32_t docId = bv->getFirstTrueBit(1);
+ while (docId < docIdLimit) {
+ func(docId, bitVectorWeight());
+ docId = bv->getNextTrueBit(docId + 1);
+ }
+ }
+ } else {
+ const BTreeType *tree = getTreeEntry(iRef);
+ _allocator.getNodeStore().foreach(tree->getFrozenRoot(), func);
+ }
+ } else {
+ const KeyDataType *p = getKeyDataEntry(iRef, clusterSize);
+ const KeyDataType *pe = p + clusterSize;
+ for (; p != pe; ++p) {
+ func(p->_key, p->getData());
+ }
+ }
+}
+
+}
diff --git a/searchlib/src/vespa/searchlib/btree/btreestore.h b/searchlib/src/vespa/searchlib/btree/btreestore.h
index e8153f94363..c22d2dd3f55 100644
--- a/searchlib/src/vespa/searchlib/btree/btreestore.h
+++ b/searchlib/src/vespa/searchlib/btree/btreestore.h
@@ -10,11 +10,7 @@
#include <vespa/searchlib/datastore/datastore.h>
#include <vespa/searchlib/datastore/handle.h>
-namespace search
-{
-
-namespace btree
-{
+namespace search::btree {
template <typename KeyT,
typename DataT,
@@ -508,8 +504,6 @@ extern template class BTreeStore<uint32_t, int32_t,
BTreeDefaultTraits,
MinMaxAggrCalc>;
-} // namespace btree
-
-} // namespace search
+}
diff --git a/searchlib/src/vespa/searchlib/common/packets.cpp b/searchlib/src/vespa/searchlib/common/packets.cpp
index 531305789b3..d885442ec03 100644
--- a/searchlib/src/vespa/searchlib/common/packets.cpp
+++ b/searchlib/src/vespa/searchlib/common/packets.cpp
@@ -7,6 +7,7 @@
#include <vespa/document/util/compressor.h>
#include <vespa/vespalib/util/exceptions.h>
#include <vespa/vespalib/data/slime/slime.h>
+#include <vespa/vespalib/data/databuffer.h>
#include <vespa/log/log.h>
LOG_SETUP(".searchlib.common.fs4packets");
@@ -150,7 +151,7 @@ FS4PersistentPacketStreamer::Decode(FNET_DataBuffer *src, uint32_t plen, uint32_
uint32_t uncompressed_size = src->ReadInt32();
ConstBufferRef org(src->GetData(), plen - sizeof(uint32_t));
vespalib::DataBuffer uncompressed(uncompressed_size);
- document::decompress(compressionType, uncompressed_size, org, uncompressed, false);
+ document::compression::decompress(compressionType, uncompressed_size, org, uncompressed, false);
FNET_DataBuffer buf(uncompressed.getData(), uncompressed.getDataLen());
decodePacket(packet, buf, uncompressed_size, pcode);
src->DataToDead(plen - sizeof(uint32_t));
@@ -191,7 +192,7 @@ FS4PersistentPacketStreamer::Encode(FNET_Packet *packet, uint32_t chid, FNET_Dat
CompressionConfig config(_compressionType, _compressionLevel, 90);
ConstBufferRef org(dst->GetData() + packet_start + header_len, body_len);
vespalib::DataBuffer compressed(org.size());
- CompressionConfig::Type r = document::compress(config, org, compressed, false);
+ CompressionConfig::Type r = document::compression::compress(config, org, compressed, false);
if (r != CompressionConfig::NONE) {
dst->DataToFree(body_len + header_len);
// sizeof(data + header + uncompressed_size) - sizeof(uint32_t)
@@ -454,7 +455,7 @@ FS4Packet_PreSerialized::FS4Packet_PreSerialized(FNET_Packet & packet)
90);
ConstBufferRef org(tmp.GetData(), tmp.GetDataLen());
vespalib::DataBuffer compressed(org.size());
- _compressionType = document::compress(config, org, compressed, false);
+ _compressionType = document::compression::compress(config, org, compressed, false);
if (_compressionType != CompressionConfig::NONE) {
_data.WriteInt32Fast(body_len);
_data.WriteBytes(compressed.getData(), compressed.getDataLen());
diff --git a/searchlib/src/vespa/searchlib/docstore/chunkformat.cpp b/searchlib/src/vespa/searchlib/docstore/chunkformat.cpp
index cddf8c96b2e..4d4d4c48130 100644
--- a/searchlib/src/vespa/searchlib/docstore/chunkformat.cpp
+++ b/searchlib/src/vespa/searchlib/docstore/chunkformat.cpp
@@ -8,6 +8,10 @@ namespace search {
using vespalib::make_string;
using vespalib::Exception;
+using document::compression::compress;
+using document::compression::decompress;
+using document::compression::computeMaxCompressedsize;
+using document::CompressionConfig;
ChunkException::ChunkException(const vespalib::stringref & msg, const vespalib::stringref & location) :
Exception(make_string("Illegal chunk: %s", msg.c_str()), location)
@@ -15,7 +19,7 @@ ChunkException::ChunkException(const vespalib::stringref & msg, const vespalib::
}
void
-ChunkFormat::pack(uint64_t lastSerial, vespalib::DataBuffer & compressed, const document::CompressionConfig & compression)
+ChunkFormat::pack(uint64_t lastSerial, vespalib::DataBuffer & compressed, const CompressionConfig & compression)
{
vespalib::nbostream & os = _dataBuf;
os << lastSerial;
@@ -29,7 +33,7 @@ ChunkFormat::pack(uint64_t lastSerial, vespalib::DataBuffer & compressed, const
const size_t oldPos(compressed.getDataLen());
compressed.writeInt8(compression.type);
compressed.writeInt32(os.size());
- document::CompressionConfig::Type type(document::compress(compression, vespalib::ConstBufferRef(os.c_str(), os.size()), compressed, false));
+ CompressionConfig::Type type(compress(compression, vespalib::ConstBufferRef(os.c_str(), os.size()), compressed, false));
if (compression.type != type) {
compressed.getData()[oldPos] = type;
}
@@ -42,28 +46,22 @@ ChunkFormat::pack(uint64_t lastSerial, vespalib::DataBuffer & compressed, const
}
size_t
-ChunkFormat::getMaxPackSize(const document::CompressionConfig & compression) const
+ChunkFormat::getMaxPackSize(const CompressionConfig & compression) const
{
const size_t OVERHEAD(0);
const size_t MINSIZE(1 + 1 + 4 + 4 + includeSerializedSize() ? 4 : 0); // version + type + real length + crc + lastserial
const size_t formatSpecificSize(getHeaderSize());
size_t rawSize(MINSIZE + formatSpecificSize + OVERHEAD);
const size_t payloadSize(_dataBuf.size() + 8);
- // This is a little dirty -> need interface.
- if (compression.type == document::CompressionConfig::LZ4) {
- document::LZ4Compressor lz4;
- rawSize += lz4.adjustProcessLen(0, payloadSize);
- } else {
- rawSize += payloadSize;
- }
- return rawSize;
+ return rawSize + computeMaxCompressedsize(compression.type, payloadSize);
}
void
ChunkFormat::verifyCompression(uint8_t type)
{
- if ((type != document::CompressionConfig::LZ4) &&
- (type != document::CompressionConfig::NONE)) {
+ if ((type != CompressionConfig::LZ4) &&
+ (type != CompressionConfig::ZSTD) &&
+ (type != CompressionConfig::NONE)) {
throw ChunkException(make_string("Unknown compressiontype %d", type), VESPA_STRLOC);
}
}
@@ -145,7 +143,7 @@ ChunkFormat::deserializeBody(vespalib::nbostream & is)
// This is a dirty trick to fool some odd sanity checking in DataBuffer::swap
vespalib::DataBuffer uncompressed(const_cast<char *>(is.peek()), (size_t)0);
vespalib::ConstBufferRef data(is.peek(), is.size() - sizeof(uint32_t));
- document::decompress(document::CompressionConfig::Type(type), uncompressedLen, data, uncompressed, true);
+ decompress(CompressionConfig::Type(type), uncompressedLen, data, uncompressed, true);
assert(uncompressed.getData() == uncompressed.getDead());
if (uncompressed.getData() != data.c_str()) {
const size_t sz(uncompressed.getDataLen());
diff --git a/searchlib/src/vespa/searchlib/docstore/documentstore.cpp b/searchlib/src/vespa/searchlib/docstore/documentstore.cpp
index fd7df29cd49..ffb56407198 100644
--- a/searchlib/src/vespa/searchlib/docstore/documentstore.cpp
+++ b/searchlib/src/vespa/searchlib/docstore/documentstore.cpp
@@ -8,6 +8,11 @@
#include <vespa/vespalib/data/databuffer.h>
#include <vespa/document/util/compressor.h>
+using document::DocumentTypeRepo;
+using document::CompressionConfig;
+using document::compression::compress;
+using document::compression::decompress;
+
namespace search {
namespace {
@@ -15,13 +20,13 @@ namespace {
class DocumentVisitorAdapter : public IBufferVisitor
{
public:
- DocumentVisitorAdapter(const document::DocumentTypeRepo & repo, IDocumentVisitor & visitor) :
+ DocumentVisitorAdapter(const DocumentTypeRepo & repo, IDocumentVisitor & visitor) :
_repo(repo),
_visitor(visitor)
{ }
void visit(uint32_t lid, vespalib::ConstBufferRef buf) override;
private:
- const document::DocumentTypeRepo & _repo;
+ const DocumentTypeRepo & _repo;
IDocumentVisitor & _visitor;
};
@@ -45,7 +50,7 @@ public:
using Alloc = vespalib::alloc::Alloc;
typedef std::unique_ptr<Value> UP;
- Value() : _compressedSize(0), _uncompressedSize(0), _compression(document::CompressionConfig::NONE) {}
+ Value() : _compressedSize(0), _uncompressedSize(0), _compression(CompressionConfig::NONE) {}
Value(Value &&rhs) :
_compressedSize(rhs._compressedSize),
@@ -69,12 +74,12 @@ public:
return *this;
}
- void setCompression(document::CompressionConfig::Type comp, size_t uncompressedSize) {
+ void setCompression(CompressionConfig::Type comp, size_t uncompressedSize) {
_compression = comp;
_uncompressedSize = uncompressedSize;
}
- document::CompressionConfig::Type getCompression() const { return _compression; }
+ CompressionConfig::Type getCompression() const { return _compression; }
size_t getUncompressedSize() const { return _uncompressedSize; }
@@ -82,13 +87,13 @@ public:
* Compress buffer into temporary buffer and copy temporary buffer to
* value along with compression config.
*/
- void set(vespalib::DataBuffer &&buf, ssize_t len, const document::CompressionConfig &compression);
+ void set(vespalib::DataBuffer &&buf, ssize_t len, const CompressionConfig &compression);
/**
* Decompress value into temporary buffer and deserialize document from
* the temporary buffer.
*/
- document::Document::UP deserializeDocument(const document::DocumentTypeRepo &repo);
+ document::Document::UP deserializeDocument(const DocumentTypeRepo &repo);
size_t size() const { return _compressedSize; }
bool empty() const { return size() == 0; }
@@ -98,36 +103,32 @@ public:
private:
size_t _compressedSize;
size_t _uncompressedSize;
- document::CompressionConfig::Type _compression;
+ CompressionConfig::Type _compression;
Alloc _buf;
};
class BackingStore {
public:
- BackingStore(IDataStore &store, const document::CompressionConfig &compression) :
+ BackingStore(IDataStore &store, const CompressionConfig &compression) :
_backingStore(store),
_compression(compression) { }
bool read(DocumentIdT key, Value &value) const;
- void visit(const IDocumentStore::LidVector &lids, const document::DocumentTypeRepo &repo, IDocumentVisitor &visitor) const;
+ void visit(const IDocumentStore::LidVector &lids, const DocumentTypeRepo &repo, IDocumentVisitor &visitor) const;
void write(DocumentIdT, const Value &) {}
void erase(DocumentIdT) {}
- const document::CompressionConfig &getCompression(void) const { return _compression; }
+ const CompressionConfig &getCompression(void) const { return _compression; }
private:
IDataStore &_backingStore;
- const document::CompressionConfig _compression;
+ const CompressionConfig _compression;
};
void
-Value::set(vespalib::DataBuffer &&buf,
- ssize_t len,
- const document::CompressionConfig &compression) {
+Value::set(vespalib::DataBuffer &&buf, ssize_t len, const CompressionConfig &compression) {
//Underlying buffer must be identical to allow swap.
vespalib::DataBuffer compressed(buf.getData(), 0u);
- document::CompressionConfig::Type type =
- document::compress(compression,
- vespalib::ConstBufferRef(buf.getData(), len),
- compressed, true);
+ CompressionConfig::Type type = compress(compression, vespalib::ConstBufferRef(buf.getData(), len),
+ compressed, true);
_compressedSize = compressed.getDataLen();
if (buf.getData() == compressed.getData()) {
// Uncompressed so we can just steal the underlying buffer.
@@ -135,28 +136,25 @@ Value::set(vespalib::DataBuffer &&buf,
} else {
compressed.stealBuffer().swap(_buf);
}
- assert(((type == document::CompressionConfig::NONE) &&
+ assert(((type == CompressionConfig::NONE) &&
(len == ssize_t(_compressedSize))) ||
- ((type != document::CompressionConfig::NONE) &&
+ ((type != CompressionConfig::NONE) &&
(len > ssize_t(_compressedSize))));
setCompression(type, len);
}
document::Document::UP
-Value::deserializeDocument(const document::DocumentTypeRepo &repo) {
+Value::deserializeDocument(const DocumentTypeRepo &repo) {
vespalib::DataBuffer uncompressed((char *) _buf.get(), (size_t) 0);
- document::decompress(getCompression(),
- getUncompressedSize(),
- vespalib::ConstBufferRef(*this, size()),
- uncompressed, true);
+ decompress(getCompression(), getUncompressedSize(), vespalib::ConstBufferRef(*this, size()), uncompressed, true);
vespalib::nbostream is(uncompressed.getData(), uncompressed.getDataLen());
return document::Document::UP(new document::Document(repo, is));
}
void
-BackingStore::visit(const IDocumentStore::LidVector &lids, const document::DocumentTypeRepo &repo,
+BackingStore::visit(const IDocumentStore::LidVector &lids, const DocumentTypeRepo &repo,
IDocumentVisitor &visitor) const {
DocumentVisitorAdapter adapter(repo, visitor);
_backingStore.read(lids, adapter);
@@ -213,7 +211,7 @@ DocumentStore::useCache() const {
}
void
-DocumentStore::visit(const LidVector & lids, const document::DocumentTypeRepo &repo, IDocumentVisitor & visitor) const
+DocumentStore::visit(const LidVector & lids, const DocumentTypeRepo &repo, IDocumentVisitor & visitor) const
{
if (useCache() && _config.allowVisitCaching() && visitor.allowVisitCaching()) {
docstore::BlobSet blobSet = _visitCache->read(lids).getBlobSet();
@@ -227,7 +225,7 @@ DocumentStore::visit(const LidVector & lids, const document::DocumentTypeRepo &r
}
document::Document::UP
-DocumentStore::read(DocumentIdT lid, const document::DocumentTypeRepo &repo) const
+DocumentStore::read(DocumentIdT lid, const DocumentTypeRepo &repo) const
{
document::Document::UP retval;
Value value;
@@ -305,25 +303,23 @@ DocumentStore::getLastFlushTime() const
template <class Visitor>
class DocumentStore::WrapVisitor : public IDataStoreVisitor
{
- Visitor &_visitor;
- const document::DocumentTypeRepo &_repo;
- const document::CompressionConfig &_compression;
- IDocumentStore &_ds;
- uint64_t _syncToken;
+ Visitor &_visitor;
+ const DocumentTypeRepo &_repo;
+ const CompressionConfig &_compression;
+ IDocumentStore &_ds;
+ uint64_t _syncToken;
public:
void visit(uint32_t lid, const void *buffer, size_t sz) override;
WrapVisitor(Visitor &visitor,
- const document::DocumentTypeRepo &repo,
- const document::CompressionConfig &compresion,
+ const DocumentTypeRepo &repo,
+ const CompressionConfig &compresion,
IDocumentStore &ds,
uint64_t syncToken);
inline void rewrite(uint32_t lid, const document::Document &doc);
-
inline void rewrite(uint32_t lid);
-
inline void visitRemove(uint32_t lid);
};
@@ -429,8 +425,8 @@ DocumentStore::WrapVisitor<Visitor>::visit(uint32_t lid,
template <class Visitor>
DocumentStore::WrapVisitor<Visitor>::
WrapVisitor(Visitor &visitor,
- const document::DocumentTypeRepo &repo,
- const document::CompressionConfig &compression,
+ const DocumentTypeRepo &repo,
+ const CompressionConfig &compression,
IDocumentStore &ds,
uint64_t syncToken)
: _visitor(visitor),
@@ -445,7 +441,7 @@ WrapVisitor(Visitor &visitor,
void
DocumentStore::accept(IDocumentStoreReadVisitor &visitor,
IDocumentStoreVisitorProgress &visitorProgress,
- const document::DocumentTypeRepo &repo)
+ const DocumentTypeRepo &repo)
{
WrapVisitor<IDocumentStoreReadVisitor> wrap(visitor, repo,
_store->getCompression(),
@@ -460,7 +456,7 @@ DocumentStore::accept(IDocumentStoreReadVisitor &visitor,
void
DocumentStore::accept(IDocumentStoreRewriteVisitor &visitor,
IDocumentStoreVisitorProgress &visitorProgress,
- const document::DocumentTypeRepo &repo)
+ const DocumentTypeRepo &repo)
{
WrapVisitor<IDocumentStoreRewriteVisitor> wrap(visitor,
repo,
diff --git a/searchlib/src/vespa/searchlib/docstore/visitcache.cpp b/searchlib/src/vespa/searchlib/docstore/visitcache.cpp
index 8fac288a23a..6771fb3bec6 100644
--- a/searchlib/src/vespa/searchlib/docstore/visitcache.cpp
+++ b/searchlib/src/vespa/searchlib/docstore/visitcache.cpp
@@ -90,7 +90,7 @@ CompressedBlobSet::CompressedBlobSet(const document::CompressionConfig &compress
if ( ! _positions.empty() ) {
DataBuffer compressed;
ConstBufferRef org = uncompressed.getBuffer();
- _compression = document::compress(compression, org, compressed, false);
+ _compression = document::compression::compress(compression, org, compressed, false);
_buffer.resize(compressed.getDataLen());
memcpy(_buffer, compressed.getData(), compressed.getDataLen());
}
@@ -99,10 +99,12 @@ CompressedBlobSet::CompressedBlobSet(const document::CompressionConfig &compress
BlobSet
CompressedBlobSet::getBlobSet() const
{
+ using document::compression::decompress;
// These are frequent lage allocations that are to expensive to mmap.
DataBuffer uncompressed(0, 1, Alloc::alloc(0, 16 * MemoryAllocator::HUGEPAGE_SIZE));
if ( ! _positions.empty() ) {
- document::decompress(_compression, getBufferSize(_positions), ConstBufferRef(_buffer.c_str(), _buffer.size()), uncompressed, false);
+ decompress(_compression, getBufferSize(_positions),
+ ConstBufferRef(_buffer.c_str(), _buffer.size()), uncompressed, false);
}
return BlobSet(_positions, uncompressed.stealBuffer());
}
diff --git a/searchlib/src/vespa/searchlib/grouping/sketch.h b/searchlib/src/vespa/searchlib/grouping/sketch.h
index 50209b19bbd..a036d23ef36 100644
--- a/searchlib/src/vespa/searchlib/grouping/sketch.h
+++ b/searchlib/src/vespa/searchlib/grouping/sketch.h
@@ -209,7 +209,7 @@ compress_buckets_into(char *buffer, uint32_t size) const {
vespalib::ConstBufferRef org(&bucket[0], BUCKET_COUNT);
vespalib::DataBuffer compress_buffer(buffer, size);
document::CompressionConfig::Type r =
- document::compress(config, org, compress_buffer, false);
+ document::compression::compress(config, org, compress_buffer, false);
assert(compress_buffer.getDead() == buffer);
if (r == document::CompressionConfig::LZ4) {
assert(compress_buffer.getDataLen() < BUCKET_COUNT);
@@ -228,7 +228,7 @@ decompress_buckets_from(char *buffer, uint32_t size) {
} else {
vespalib::ConstBufferRef compressed(buffer, size);
vespalib::DataBuffer uncompressed(reinterpret_cast<char *>(&bucket[0]), BUCKET_COUNT);
- document::decompress(document::CompressionConfig::LZ4, BUCKET_COUNT, compressed, uncompressed, false);
+ document::compression::decompress(document::CompressionConfig::LZ4, BUCKET_COUNT, compressed, uncompressed, false);
}
}
template <int BucketBits, typename HashT>
diff --git a/staging_vespalib/src/vespa/vespalib/data/databuffer.h b/staging_vespalib/src/vespa/vespalib/data/databuffer.h
index a9ed53e2f84..875aa2f0074 100644
--- a/staging_vespalib/src/vespa/vespalib/data/databuffer.h
+++ b/staging_vespalib/src/vespa/vespalib/data/databuffer.h
@@ -1,10 +1,8 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#pragma once
-#include <string.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <assert.h>
+#include <cstring>
+#include <cassert>
#include <vespa/vespalib/util/alloc.h>
namespace vespalib {
diff --git a/storage/src/vespa/storage/tools/.gitignore b/storage/src/vespa/storage/tools/.gitignore
index ba1c4352573..9f66a0b7157 100644
--- a/storage/src/vespa/storage/tools/.gitignore
+++ b/storage/src/vespa/storage/tools/.gitignore
@@ -21,7 +21,6 @@ throttlingsim
vdsclient
vdsdisktool
vdsidealstate
-vdsstat
vesparemovelocation
storage_analyzedistribution_app
storage_generatedistributionbits_app
diff --git a/storageapi/src/vespa/storageapi/app/CMakeLists.txt b/storageapi/src/vespa/storageapi/app/CMakeLists.txt
index 45f48e4d1a0..639b866a123 100644
--- a/storageapi/src/vespa/storageapi/app/CMakeLists.txt
+++ b/storageapi/src/vespa/storageapi/app/CMakeLists.txt
@@ -2,7 +2,6 @@
vespa_add_executable(storageapi_getbucketid_app
SOURCES
getbucketid.cpp
- INSTALL bin
DEPENDS
storageapi
)
diff --git a/vbench/src/apps/dumpurl/CMakeLists.txt b/vbench/src/apps/dumpurl/CMakeLists.txt
index 00f00da47e8..0a6fb03919f 100644
--- a/vbench/src/apps/dumpurl/CMakeLists.txt
+++ b/vbench/src/apps/dumpurl/CMakeLists.txt
@@ -2,7 +2,6 @@
vespa_add_executable(vbench_dumpurl_app
SOURCES
dumpurl.cpp
- INSTALL bin
DEPENDS
vbench
)
diff --git a/vbench/src/apps/vbench/CMakeLists.txt b/vbench/src/apps/vbench/CMakeLists.txt
index 5c9e423db3c..df125830924 100644
--- a/vbench/src/apps/vbench/CMakeLists.txt
+++ b/vbench/src/apps/vbench/CMakeLists.txt
@@ -2,7 +2,6 @@
vespa_add_executable(vbench_app
SOURCES
vbench.cpp
- INSTALL bin
DEPENDS
vbench
)
diff --git a/vdslib/pom.xml b/vdslib/pom.xml
index a4ada46c89e..26d210f14dc 100644
--- a/vdslib/pom.xml
+++ b/vdslib/pom.xml
@@ -99,7 +99,6 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
- <version>2.3.1</version>
<configuration>
<updateReleaseInfo>true</updateReleaseInfo>
</configuration>
diff --git a/vespabase/CMakeLists.txt b/vespabase/CMakeLists.txt
index d7743d42744..9c0aced2319 100644
--- a/vespabase/CMakeLists.txt
+++ b/vespabase/CMakeLists.txt
@@ -1,22 +1,17 @@
# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
vespa_install_script(src/start-cbinaries.sh vespa-get-config bin)
-vespa_install_script(src/start-cbinaries.sh vds-document-statistics bin)
-vespa_install_script(src/start-cbinaries.sh vdsstat bin)
vespa_install_script(src/start-cbinaries.sh vespa-verify-ranksetup bin)
vespa_install_script(src/start-cbinaries.sh vespa-config-status bin)
vespa_install_script(src/start-cbinaries.sh vespa-doclocator bin)
-vespa_install_script(src/start-cbinaries.sh vespaget bin)
vespa_install_script(src/start-cbinaries.sh vespa-model-inspect bin)
vespa_install_script(src/start-cbinaries.sh vespa-proton-cmd bin)
vespa_install_script(src/start-cbinaries.sh vespa-query-profile-dump-tool bin)
vespa_install_script(src/start-cbinaries.sh vespa-route bin)
vespa_install_script(src/start-cbinaries.sh vespa-transactionlog-inspect bin)
-vespa_install_script(src/start-cbinaries.sh vespavisit bin)
-vespa_install_script(src/start-cbinaries.sh vespavisittarget bin)
vespa_install_script(src/start-cbinaries.sh vespa-vds-disktool bin)
vespa_install_script(src/start-cbinaries.sh vespa-distributord sbin)
vespa_install_script(src/start-cbinaries.sh vespa-fdispatch sbin)
-vespa_install_script(src/start-cbinaries.sh filedistributor sbin)
+vespa_install_script(src/start-cbinaries.sh vespa-filedistributor sbin)
vespa_install_script(src/start-cbinaries.sh vespa-proton sbin)
vespa_install_script(src/start-cbinaries.sh vespa-storaged sbin)
diff --git a/vespabase/src/start-vespa-base.sh b/vespabase/src/start-vespa-base.sh
index ad6b58f61b1..e8ac4fcd670 100755
--- a/vespabase/src/start-vespa-base.sh
+++ b/vespabase/src/start-vespa-base.sh
@@ -73,4 +73,4 @@ if [ -f /tmp/.ylock-arena.shm ]; then
chown yahoo:wheel /tmp/.ylock-arena.shm
fi
-exec run-as-yahoo ${VESPA_HOME}/bin/config-ctl start
+exec vespa-run-as-vespa-user ${VESPA_HOME}/bin/vespa-config-ctl start
diff --git a/vespabase/src/stop-vespa-base.sh b/vespabase/src/stop-vespa-base.sh
index 6e2fccc5664..eb85cdf14f6 100755
--- a/vespabase/src/stop-vespa-base.sh
+++ b/vespabase/src/stop-vespa-base.sh
@@ -64,4 +64,4 @@ cd ${VESPA_HOME} || { echo "Cannot cd to ${VESPA_HOME}" 1>&2; exit 1; }
fixlimits
-exec run-as-yahoo ${VESPA_HOME}/bin/config-ctl stop
+exec vespa-run-as-vespa-user ${VESPA_HOME}/bin/vespa-config-ctl stop
diff --git a/vespaclient-java/src/main/java/com/yahoo/vespafeeder/Arguments.java b/vespaclient-java/src/main/java/com/yahoo/vespafeeder/Arguments.java
index 249ed1fd70c..4c588e6e318 100644
--- a/vespaclient-java/src/main/java/com/yahoo/vespafeeder/Arguments.java
+++ b/vespaclient-java/src/main/java/com/yahoo/vespafeeder/Arguments.java
@@ -71,7 +71,7 @@ public class Arguments {
" are allowed to be pending at any given time. \n" +
" --maxfeedrate arg Limits the feed rate to the given number (operations/second). You may still want to increase\n" +
" the max pending size if your feed rate doesn't reach the desired number.\n" +
- " --mode arg (=standard) The mode to run vespafeeder in (standard | benchmark).\n" +
+ " --mode arg (=standard) The mode to run vespa-feeder in (standard | benchmark).\n" +
" --noretry Turns off retries of recoverable failures.\n" +
" --retrydelay arg (=1) The time (in seconds) to wait between retries of \n" +
" a failed operation.\n" +
diff --git a/vespaclient-java/src/main/java/com/yahoo/vespafeeder/VespaFeeder.java b/vespaclient-java/src/main/java/com/yahoo/vespafeeder/VespaFeeder.java
index a6ede66c43d..66eb17a744f 100755
--- a/vespaclient-java/src/main/java/com/yahoo/vespafeeder/VespaFeeder.java
+++ b/vespaclient-java/src/main/java/com/yahoo/vespafeeder/VespaFeeder.java
@@ -22,7 +22,7 @@ public class VespaFeeder {
Arguments args;
DocumentTypeManager manager;
- Executor threadPool = Executors.newCachedThreadPool(ThreadFactoryFactory.getThreadFactory("vespafeeder"));
+ Executor threadPool = Executors.newCachedThreadPool(ThreadFactoryFactory.getThreadFactory("vespa-feeder"));
public VespaFeeder(Arguments args, DocumentTypeManager manager) {
this.args = args;
@@ -141,7 +141,7 @@ public class VespaFeeder {
}
public static void main(String[] args) {
- LogSetup.initVespaLogging("vespafeeder");
+ LogSetup.initVespaLogging("vespa-feeder");
try {
Arguments arguments = new Arguments(args, null);
diff --git a/vespaclient-java/src/main/java/com/yahoo/vespaget/CommandLineOptions.java b/vespaclient-java/src/main/java/com/yahoo/vespaget/CommandLineOptions.java
index cbaef17a70a..89d48caceb2 100644
--- a/vespaclient-java/src/main/java/com/yahoo/vespaget/CommandLineOptions.java
+++ b/vespaclient-java/src/main/java/com/yahoo/vespaget/CommandLineOptions.java
@@ -143,7 +143,7 @@ public class CommandLineOptions {
HelpFormatter formatter = new HelpFormatter();
formatter.printHelp(
- "vespaget <options> [documentid...]", "Fetch a document from a Vespa Content cluster.", options,
+ "vespa-get <options> [documentid...]", "Fetch a document from a Vespa Content cluster.", options,
"If one or more document identifier are specified, these documents will be " +
"retrieved. Otherwise, document identifiers (separated with line break) will be read from standard in.\n",
false);
diff --git a/vespaclient-java/src/main/java/com/yahoo/vespaget/Main.java b/vespaclient-java/src/main/java/com/yahoo/vespaget/Main.java
index 324107d8909..eb840a9c271 100644
--- a/vespaclient-java/src/main/java/com/yahoo/vespaget/Main.java
+++ b/vespaclient-java/src/main/java/com/yahoo/vespaget/Main.java
@@ -6,7 +6,7 @@ import com.yahoo.documentapi.messagebus.loadtypes.LoadTypeSet;
import com.yahoo.vespaclient.ClusterList;
/**
- * The vespaget tool retrieves documents from a Vespa Document Storage cluster, and prints them to stdout as XML.
+ * The vespa-get tool retrieves documents from a Vespa Document Storage cluster, and prints them to stdout as XML.
*
* @author bjorncs
*/
diff --git a/vespaclient-java/src/main/java/com/yahoo/vespastat/CommandLineOptions.java b/vespaclient-java/src/main/java/com/yahoo/vespastat/CommandLineOptions.java
index b0b6246a262..042b2ecc426 100644
--- a/vespaclient-java/src/main/java/com/yahoo/vespastat/CommandLineOptions.java
+++ b/vespaclient-java/src/main/java/com/yahoo/vespastat/CommandLineOptions.java
@@ -96,7 +96,7 @@ public class CommandLineOptions {
public void printHelp() {
HelpFormatter formatter = new HelpFormatter();
- formatter.printHelp("vdsstat [options]",
+ formatter.printHelp("vespa-stat [options]",
"Fetch statistics about a specific user, group, bucket, gid or document.", options, "", false);
}
diff --git a/vespaclient-java/src/main/java/com/yahoo/vespavisit/VdsVisit.java b/vespaclient-java/src/main/java/com/yahoo/vespavisit/VdsVisit.java
index ff072b845de..f0b3df4d5d7 100644
--- a/vespaclient-java/src/main/java/com/yahoo/vespavisit/VdsVisit.java
+++ b/vespaclient-java/src/main/java/com/yahoo/vespavisit/VdsVisit.java
@@ -103,7 +103,7 @@ public class VdsVisit {
}
public static void main(String args[]) {
- LogSetup.initVespaLogging("vespavisit");
+ LogSetup.initVespaLogging("vespa-visit");
VdsVisit vdsVisit = new VdsVisit();
Options options = createOptions();
@@ -140,7 +140,7 @@ public class VdsVisit {
private void printSyntax(Options options) {
HelpFormatter formatter = new HelpFormatter();
- formatter.printHelp("vespavisit <options>", "Visit documents from VDS", options , "");
+ formatter.printHelp("vespa-visit <options>", "Visit documents from VDS", options , "");
}
@SuppressWarnings("AccessStaticViaInstance")
@@ -204,7 +204,7 @@ public class VdsVisit {
.longOpt("maxpendingsuperbuckets")
.hasArg(true)
.argName("num")
- .desc("Maximum pending visitor messages from the vespavisit client. If set, dynamic throttling of visitors will be disabled!")
+ .desc("Maximum pending visitor messages from the vespa-visit client. If set, dynamic throttling of visitors will be disabled!")
.type(Number.class)
.build());
diff --git a/vespaclient-java/src/main/java/com/yahoo/vespavisit/VdsVisitTarget.java b/vespaclient-java/src/main/java/com/yahoo/vespavisit/VdsVisitTarget.java
index 3ef0619cfd8..301d0989d65 100644
--- a/vespaclient-java/src/main/java/com/yahoo/vespavisit/VdsVisitTarget.java
+++ b/vespaclient-java/src/main/java/com/yahoo/vespavisit/VdsVisitTarget.java
@@ -72,7 +72,7 @@ public class VdsVisitTarget {
}
public static void main(String args[]) {
- LogSetup.initVespaLogging("vespavisittarget");
+ LogSetup.initVespaLogging("vespa-visit-target");
VdsVisitTarget visitTarget = new VdsVisitTarget();
@@ -144,11 +144,11 @@ public class VdsVisitTarget {
private void printSyntax(Options options) {
HelpFormatter formatter = new HelpFormatter();
- formatter.printHelp("vespavisittarget <options>", "Retrieve results from a visitor", options ,
+ formatter.printHelp("vespa-visit-target <options>", "Retrieve results from a visitor", options ,
"One, and only one, of the binding options must be present.\n" +
"\n" +
"For more detailed information, such as defaults and format of\n" +
- "arguments, refer to 'man vespavisittarget'.\n");
+ "arguments, refer to 'man vespa-visit-target'.\n");
}
class HelpShownException extends Exception {}
diff --git a/vespaclient-java/src/main/sh/vespadestination.sh b/vespaclient-java/src/main/sh/vespa-destination.sh
index a56e7033784..a56e7033784 100755
--- a/vespaclient-java/src/main/sh/vespadestination.sh
+++ b/vespaclient-java/src/main/sh/vespa-destination.sh
diff --git a/vespaclient-java/src/main/sh/vds-document-statistics.sh b/vespaclient-java/src/main/sh/vespa-document-statistics.sh
index bf8191e8b02..bbe9c210d3c 100755
--- a/vespaclient-java/src/main/sh/vds-document-statistics.sh
+++ b/vespaclient-java/src/main/sh/vespa-document-statistics.sh
@@ -61,10 +61,10 @@ findroot
# END environment bootstrap section
function help {
- echo "Usage: vds-document-statistics [ category, ... ]"
+ echo "Usage: vespa-document-statistics [ category, ... ]"
echo " Where category is one or more of: user, group, scheme, namespace"
echo ""
- echo "vds-document-statistics generates documents counts based on one or more categories."
+ echo "vespa-document-statistics generates documents counts based on one or more categories."
exit 0
}
if [ "$1" == "-h" ]; then
diff --git a/vespaclient-java/src/main/sh/vespafeeder.sh b/vespaclient-java/src/main/sh/vespa-feeder.sh
index ba3aa9012a2..ba3aa9012a2 100755
--- a/vespaclient-java/src/main/sh/vespafeeder.sh
+++ b/vespaclient-java/src/main/sh/vespa-feeder.sh
diff --git a/vespaclient-java/src/main/sh/vespaget.sh b/vespaclient-java/src/main/sh/vespa-get.sh
index 5111714b71d..5111714b71d 100644
--- a/vespaclient-java/src/main/sh/vespaget.sh
+++ b/vespaclient-java/src/main/sh/vespa-get.sh
diff --git a/vespaclient-java/src/main/sh/vdsstat.sh b/vespaclient-java/src/main/sh/vespa-stat.sh
index ec3cc70ef48..ec3cc70ef48 100644
--- a/vespaclient-java/src/main/sh/vdsstat.sh
+++ b/vespaclient-java/src/main/sh/vespa-stat.sh
diff --git a/vespaclient-java/src/main/sh/vespavisittarget.1 b/vespaclient-java/src/main/sh/vespa-visit-target.1
index ab0b0b5d105..a75ee4090f4 100644
--- a/vespaclient-java/src/main/sh/vespavisittarget.1
+++ b/vespaclient-java/src/main/sh/vespa-visit-target.1
@@ -1,9 +1,9 @@
." Copyright 2017 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-.TH VESPAVISITTARGET 1 2008-03-07 "Vespa" "Vespa Documentation"
+.TH VESPA-VISIT-TARGET 1 2008-03-07 "Vespa" "Vespa Documentation"
.SH NAME
-vespavisittarget \- An endpoint for documents visited from a Vespa installation
+vespa-visit-target \- An endpoint for documents visited from a Vespa installation
.SH SYNPOSIS
-.B vespavisittarget
+.B vespa-visit-target
[\fIOPTION\fR]...
.SH DESCRIPTION
.PP
diff --git a/vespaclient-java/src/main/sh/vespavisittarget.sh b/vespaclient-java/src/main/sh/vespa-visit-target.sh
index 42cffe9978d..42cffe9978d 100755
--- a/vespaclient-java/src/main/sh/vespavisittarget.sh
+++ b/vespaclient-java/src/main/sh/vespa-visit-target.sh
diff --git a/vespaclient-java/src/main/sh/vespavisit.1 b/vespaclient-java/src/main/sh/vespa-visit.1
index 4873f3ac74e..80557035abe 100644
--- a/vespaclient-java/src/main/sh/vespavisit.1
+++ b/vespaclient-java/src/main/sh/vespa-visit.1
@@ -1,9 +1,9 @@
." Copyright 2017 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-.TH VESPAVISIT 1 2008-03-07 "Vespa" "Vespa Documentation"
+.TH VESPA-VISIT 1 2008-03-07 "Vespa" "Vespa Documentation"
.SH NAME
-vespavisit \- Visit documents from a Vespa installation
+vespa-visit \- Visit documents from a Vespa installation
.SH SYNPOSIS
-.B vespavisit
+.B vespa-visit
[\fIOPTION\fR]...
.SH DESCRIPTION
.PP
@@ -49,7 +49,7 @@ visiting, and can only be used if no datahandler is specified.
.TP
\fB\-d\fR, \fB\-\-datahandler\fR \fIVISITTARGET\fR
The data handler is the destination of messages sent from the visitor library.
-By default, the data handler is the vespavisit process you start, which will
+By default, the data handler is the vespa-visit process you start, which will
merely print all returned data to STDOUT. A visit target can be specified
instead. See the chapter below on visit targets.
.TP
@@ -140,20 +140,20 @@ not send all the data to one or all the nodes. The data sent from the visitor
will be distributed among the matching nodes, but each message will just be sent
to one node.
-Slobrok names may also be used if you use the \fBvespavisittarget\fR tool to
-retrieve the data at some location. If you start vespavisittarget on two nodes,
+Slobrok names may also be used if you use the \fBvespa-visit-target\fR tool to
+retrieve the data at some location. If you start vespa-visit-target on two nodes,
listening to slobrok names \fImynode/0/visit-destination\fR and
\fImynode/1/visit-destination\fR you can send the results to these nodes by
specifying \fImynode/*/visit-destination\fR as the data handler. See
-\fBman vespavisittarget\fR for naming conventions used for such targets.
+\fBman vespa-visit-target\fR for naming conventions used for such targets.
.TP
\fBTCP socket\fR
TCP sockets can also be specified directly. This requires that the endpoint
speaks FNET RPC though. This is typically done, either by using the
-\fBvespavisittarget\fR tool, or by using a visitor destination programmatically
+\fBvespa-visit-target\fR tool, or by using a visitor destination programmatically
by using utility class in the document API. A socket address looks like the
following: tcp/\fIhostname\fR:\fIport\fR/\fIservicename\fR. For instance, an
-address generated by the \fBvespavisittarget\fR tool might look like the
+address generated by the \fBvespa-visit-target\fR tool might look like the
following: \fItcp/myhost.com:12345/visit-destination\fR.
.SH AUTHOR
diff --git a/vespaclient-java/src/main/sh/vespavisit.sh b/vespaclient-java/src/main/sh/vespa-visit.sh
index bca8d1881fa..bca8d1881fa 100755
--- a/vespaclient-java/src/main/sh/vespavisit.sh
+++ b/vespaclient-java/src/main/sh/vespa-visit.sh
diff --git a/vespaclient-java/src/test/java/com/yahoo/vespaget/CommandLineOptionsTest.java b/vespaclient-java/src/test/java/com/yahoo/vespaget/CommandLineOptionsTest.java
index 3e707b04256..4b849828a27 100644
--- a/vespaclient-java/src/test/java/com/yahoo/vespaget/CommandLineOptionsTest.java
+++ b/vespaclient-java/src/test/java/com/yahoo/vespaget/CommandLineOptionsTest.java
@@ -184,7 +184,7 @@ public class CommandLineOptionsTest {
options.printHelp();
String output = outContent.toString();
- assertTrue(output.contains("vespaget <options> [documentid...]"));
+ assertTrue(output.contains("vespa-get <options> [documentid...]"));
assertTrue(output.contains("Fetch a document from a Vespa Content cluster."));
} finally {
System.setOut(oldOut);
diff --git a/vespaclient-java/src/test/java/com/yahoo/vespastat/CommandLineOptionsTest.java b/vespaclient-java/src/test/java/com/yahoo/vespastat/CommandLineOptionsTest.java
index e90c47e3150..8e0ecdcaa64 100644
--- a/vespaclient-java/src/test/java/com/yahoo/vespastat/CommandLineOptionsTest.java
+++ b/vespaclient-java/src/test/java/com/yahoo/vespastat/CommandLineOptionsTest.java
@@ -63,7 +63,7 @@ public class CommandLineOptionsTest {
CommandLineOptions options = new CommandLineOptions();
options.printHelp();
String output = outContent.toString();
- assertTrue(output.contains("vdsstat [options]"));
+ assertTrue(output.contains("vespa-stat [options]"));
} finally {
System.setOut(oldOut);
outContent.reset();
diff --git a/vespajlib/src/main/java/com/yahoo/compress/Compressor.java b/vespajlib/src/main/java/com/yahoo/compress/Compressor.java
index 681f95142ab..4cdade4de01 100644
--- a/vespajlib/src/main/java/com/yahoo/compress/Compressor.java
+++ b/vespajlib/src/main/java/com/yahoo/compress/Compressor.java
@@ -80,7 +80,7 @@ public class Compressor {
int dataSize = uncompressedSize.isPresent() ? uncompressedSize.get() : data.length;
if (dataSize < compressMinSizeBytes) return new Compression(CompressionType.INCOMPRESSIBLE, dataSize, data);
LZ4Compressor compressor = level < 7 ? factory.fastCompressor() : factory.highCompressor();
- byte[] compressedData = compressor.compress(data);
+ byte[] compressedData = compressor.compress(data, 0, dataSize);
if (compressedData.length + 8 >= dataSize * compressionThresholdFactor)
return new Compression(CompressionType.INCOMPRESSIBLE, dataSize, data);
return new Compression(CompressionType.LZ4, dataSize, compressedData);
diff --git a/vespajlib/src/test/java/com/yahoo/compress/LZ4CompressorTest.java b/vespajlib/src/test/java/com/yahoo/compress/LZ4CompressorTest.java
new file mode 100644
index 00000000000..c33dabf04da
--- /dev/null
+++ b/vespajlib/src/test/java/com/yahoo/compress/LZ4CompressorTest.java
@@ -0,0 +1,25 @@
+// Copyright 2017 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.compress;
+
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Optional;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class LZ4CompressorTest {
+
+ @Test
+ public void can_compress_and_decompress_partial_buffer_range() {
+ byte[] toCompress = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".getBytes();
+ int compressBytes = 30;
+ Compressor compressor = new Compressor();
+ Compressor.Compression compressed = compressor.compress(CompressionType.LZ4, toCompress, Optional.of(compressBytes));
+ assertEquals(compressBytes, compressed.uncompressedSize());
+ byte[] decompressed = compressor.decompress(compressed);
+ assertTrue(Arrays.equals(decompressed, Arrays.copyOf(toCompress, compressBytes)));
+ }
+
+}
diff --git a/vespalib/src/apps/make_fixture_macros/CMakeLists.txt b/vespalib/src/apps/make_fixture_macros/CMakeLists.txt
index 33709d7c047..17678acc92f 100644
--- a/vespalib/src/apps/make_fixture_macros/CMakeLists.txt
+++ b/vespalib/src/apps/make_fixture_macros/CMakeLists.txt
@@ -2,6 +2,5 @@
vespa_add_executable(vespalib_make_fixture_macros_app
SOURCES
make_fixture_macros.cpp
- INSTALL bin
DEPENDS
)
diff --git a/vespalib/src/vespa/vespalib/util/optimized.h b/vespalib/src/vespa/vespalib/util/optimized.h
index ec11bbb686a..c5d0404e310 100644
--- a/vespalib/src/vespa/vespalib/util/optimized.h
+++ b/vespalib/src/vespa/vespalib/util/optimized.h
@@ -4,7 +4,7 @@
#pragma once
-#include <stdint.h>
+#include <cstdint>
namespace vespalib {
diff --git a/vespalog/src/vespa/log/bufferedlogger.cpp b/vespalog/src/vespa/log/bufferedlogger.cpp
index db2021324c3..fe6a03ebf69 100644
--- a/vespalog/src/vespa/log/bufferedlogger.cpp
+++ b/vespalog/src/vespa/log/bufferedlogger.cpp
@@ -10,11 +10,9 @@
#include <boost/multi_index/sequenced_index.hpp>
#include <iomanip>
-#include <iostream>
#include <sstream>
#include <vector>
#include <cstdarg>
-#include <ctime>
namespace ns_log {
@@ -381,5 +379,4 @@ BufferedLogger::setTimer(std::unique_ptr<Timer> timer)
_backing->_timer = std::move(timer);
}
-
} // ns_log
diff --git a/vespamalloc/CMakeLists.txt b/vespamalloc/CMakeLists.txt
index 11bc1b60983..ec4293979f8 100644
--- a/vespamalloc/CMakeLists.txt
+++ b/vespamalloc/CMakeLists.txt
@@ -24,5 +24,5 @@ vespa_define_module(
src/vespamalloc/util
)
-vespa_install_script(bin/parsememorydump.pl vespamalloc-parsememorydump.pl bin)
+vespa_install_script(bin/parsememorydump.pl vespa-malloc-parse-memorydump.pl bin)
install(FILES etc/vespamalloc.conf PERMISSIONS OWNER_READ GROUP_READ WORLD_READ DESTINATION etc)