diff options
37 files changed, 302 insertions, 234 deletions
diff --git a/config-model-api/abi-spec.json b/config-model-api/abi-spec.json index 6e02b88e22e..847defb92db 100644 --- a/config-model-api/abi-spec.json +++ b/config-model-api/abi-spec.json @@ -195,7 +195,7 @@ "public" ], "methods": [ - "public void <init>(com.yahoo.config.provision.InstanceName, java.util.List, com.yahoo.config.application.api.DeploymentSpec$UpgradePolicy, com.yahoo.config.application.api.DeploymentSpec$RevisionTarget, com.yahoo.config.application.api.DeploymentSpec$RevisionChange, com.yahoo.config.application.api.DeploymentSpec$UpgradeRollout, int, int, int, java.util.List, java.util.Optional, java.util.Optional, com.yahoo.config.application.api.Notifications, java.util.List, java.time.Instant)", + "public void <init>(com.yahoo.config.provision.InstanceName, java.util.List, com.yahoo.config.application.api.DeploymentSpec$UpgradePolicy, com.yahoo.config.application.api.DeploymentSpec$RevisionTarget, com.yahoo.config.application.api.DeploymentSpec$RevisionChange, com.yahoo.config.application.api.DeploymentSpec$UpgradeRollout, int, int, int, java.util.List, java.util.Optional, java.util.Optional, java.util.Optional, com.yahoo.config.application.api.Notifications, java.util.List, java.time.Instant)", "public com.yahoo.config.provision.InstanceName name()", "public com.yahoo.config.application.api.DeploymentSpec$UpgradePolicy upgradePolicy()", "public com.yahoo.config.application.api.DeploymentSpec$RevisionTarget revisionTarget()", @@ -209,6 +209,7 @@ "public boolean canUpgradeAt(java.time.Instant)", "public boolean canChangeRevisionAt(java.time.Instant)", "public java.util.Optional athenzService(com.yahoo.config.provision.Environment, com.yahoo.config.provision.RegionName)", + "public java.util.Optional cloudAccount(com.yahoo.config.provision.Environment, com.yahoo.config.provision.RegionName)", "public com.yahoo.config.application.api.Notifications notifications()", "public java.util.List endpoints()", "public boolean deploysTo(com.yahoo.config.provision.Environment, com.yahoo.config.provision.RegionName)", @@ -258,12 +259,13 @@ ], "methods": [ "public void <init>(com.yahoo.config.provision.Environment)", - "public void <init>(com.yahoo.config.provision.Environment, java.util.Optional, boolean, java.util.Optional, java.util.Optional)", + "public void <init>(com.yahoo.config.provision.Environment, java.util.Optional, boolean, java.util.Optional, java.util.Optional, java.util.Optional)", "public com.yahoo.config.provision.Environment environment()", "public java.util.Optional region()", "public boolean active()", "public java.util.Optional testerFlavor()", "public java.util.Optional athenzService()", + "public java.util.Optional cloudAccount()", "public java.util.List zones()", "public boolean concerns(com.yahoo.config.provision.Environment, java.util.Optional)", "public boolean isTest()", diff --git a/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentInstanceSpec.java b/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentInstanceSpec.java index 9d90167a0ef..5f6d47fb586 100644 --- a/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentInstanceSpec.java +++ b/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentInstanceSpec.java @@ -1,9 +1,8 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.config.application.api; -import ai.vespa.validation.Validation; -import com.yahoo.config.application.api.DeploymentSpec.RevisionTarget; import com.yahoo.config.provision.AthenzService; +import com.yahoo.config.provision.CloudAccount; import com.yahoo.config.provision.Environment; import com.yahoo.config.provision.InstanceName; import com.yahoo.config.provision.RegionName; @@ -14,11 +13,9 @@ import java.time.temporal.ChronoUnit; import java.util.Arrays; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; -import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -29,7 +26,6 @@ import static com.yahoo.config.application.api.DeploymentSpec.RevisionChange.whe import static com.yahoo.config.application.api.DeploymentSpec.RevisionTarget.next; import static com.yahoo.config.provision.Environment.prod; import static java.util.stream.Collectors.toList; -import static java.util.stream.Collectors.toSet; /** * The deployment spec for an application instance @@ -54,6 +50,7 @@ public class DeploymentInstanceSpec extends DeploymentSpec.Steps { private final List<DeploymentSpec.ChangeBlocker> changeBlockers; private final Optional<String> globalServiceId; private final Optional<AthenzService> athenzService; + private final Optional<CloudAccount> cloudAccount; private final Notifications notifications; private final List<Endpoint> endpoints; @@ -67,25 +64,29 @@ public class DeploymentInstanceSpec extends DeploymentSpec.Steps { List<DeploymentSpec.ChangeBlocker> changeBlockers, Optional<String> globalServiceId, Optional<AthenzService> athenzService, + Optional<CloudAccount> cloudAccount, Notifications notifications, List<Endpoint> endpoints, Instant now) { super(steps); - this.name = name; - this.upgradePolicy = upgradePolicy; + this.name = Objects.requireNonNull(name); + this.upgradePolicy = Objects.requireNonNull(upgradePolicy); + Objects.requireNonNull(revisionTarget); + Objects.requireNonNull(revisionChange); this.revisionTarget = require(maxRisk == 0 || revisionTarget == next, revisionTarget, "revision-target must be 'next' when max-risk is specified"); this.revisionChange = require(maxRisk == 0 || revisionChange == whenClear, revisionChange, "revision-change must be 'when-clear' when max-risk is specified"); - this.upgradeRollout = upgradeRollout; + this.upgradeRollout = Objects.requireNonNull(upgradeRollout); this.minRisk = requireAtLeast(minRisk, "minimum risk score", 0); this.maxRisk = require(maxRisk >= minRisk, maxRisk, "maximum risk cannot be less than minimum risk score"); this.maxIdleHours = requireInRange(maxIdleHours, "maximum idle hours", 0, 168); - this.changeBlockers = changeBlockers; - this.globalServiceId = globalServiceId; - this.athenzService = athenzService; - this.notifications = notifications; - this.endpoints = List.copyOf(endpoints); + this.changeBlockers = Objects.requireNonNull(changeBlockers); + this.globalServiceId = Objects.requireNonNull(globalServiceId); + this.athenzService = Objects.requireNonNull(athenzService); + this.cloudAccount = Objects.requireNonNull(cloudAccount); + this.notifications = Objects.requireNonNull(notifications); + this.endpoints = List.copyOf(Objects.requireNonNull(endpoints)); validateZones(new HashSet<>(), new HashSet<>(), this); validateEndpoints(steps(), globalServiceId, this.endpoints); validateChangeBlockers(changeBlockers, now); @@ -224,6 +225,15 @@ public class DeploymentInstanceSpec extends DeploymentSpec.Steps { .or(() -> this.athenzService); } + /** Returns the cloud account to use for given environment and region, if any */ + public Optional<CloudAccount> cloudAccount(Environment environment, RegionName region) { + return zones().stream() + .filter(zone -> zone.concerns(environment, Optional.of(region))) + .findFirst() + .flatMap(DeploymentSpec.DeclaredZone::cloudAccount) + .or(() -> cloudAccount); + } + /** Returns the notification configuration of these instances */ public Notifications notifications() { return notifications; } diff --git a/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java b/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java index e5ea65b6d4e..22ffdeb7262 100644 --- a/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java +++ b/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java @@ -5,6 +5,7 @@ import com.yahoo.collections.Comparables; import com.yahoo.config.application.api.xml.DeploymentSpecXmlReader; import com.yahoo.config.provision.AthenzDomain; import com.yahoo.config.provision.AthenzService; +import com.yahoo.config.provision.CloudAccount; import com.yahoo.config.provision.Environment; import com.yahoo.config.provision.InstanceName; import com.yahoo.config.provision.RegionName; @@ -362,22 +363,27 @@ public class DeploymentSpec { private final boolean active; private final Optional<AthenzService> athenzService; private final Optional<String> testerFlavor; + private final Optional<CloudAccount> cloudAccount; public DeclaredZone(Environment environment) { - this(environment, Optional.empty(), false, Optional.empty(), Optional.empty()); + this(environment, Optional.empty(), false, Optional.empty(), Optional.empty(), Optional.empty()); } public DeclaredZone(Environment environment, Optional<RegionName> region, boolean active, - Optional<AthenzService> athenzService, Optional<String> testerFlavor) { + Optional<AthenzService> athenzService, Optional<String> testerFlavor, + Optional<CloudAccount> cloudAccount) { if (environment != Environment.prod && region.isPresent()) illegal("Non-prod environments cannot specify a region"); if (environment == Environment.prod && region.isEmpty()) illegal("Prod environments must be specified with a region"); - this.environment = environment; - this.region = region; + if (environment != Environment.prod && cloudAccount.isPresent()) + illegal("Non-prod environments cannot specify cloud account"); + this.environment = Objects.requireNonNull(environment); + this.region = Objects.requireNonNull(region); this.active = active; - this.athenzService = athenzService; - this.testerFlavor = testerFlavor; + this.athenzService = Objects.requireNonNull(athenzService); + this.testerFlavor = Objects.requireNonNull(testerFlavor); + this.cloudAccount = Objects.requireNonNull(cloudAccount); } public Environment environment() { return environment; } @@ -392,6 +398,10 @@ public class DeploymentSpec { public Optional<AthenzService> athenzService() { return athenzService; } + public Optional<CloudAccount> cloudAccount() { + return cloudAccount; + } + @Override public List<DeclaredZone> zones() { return Collections.singletonList(this); } diff --git a/config-model-api/src/main/java/com/yahoo/config/application/api/xml/DeploymentSpecXmlReader.java b/config-model-api/src/main/java/com/yahoo/config/application/api/xml/DeploymentSpecXmlReader.java index 96cc33d44b4..8166fb33b78 100644 --- a/config-model-api/src/main/java/com/yahoo/config/application/api/xml/DeploymentSpecXmlReader.java +++ b/config-model-api/src/main/java/com/yahoo/config/application/api/xml/DeploymentSpecXmlReader.java @@ -21,6 +21,7 @@ import com.yahoo.config.application.api.Notifications.When; import com.yahoo.config.application.api.TimeWindow; import com.yahoo.config.provision.AthenzDomain; import com.yahoo.config.provision.AthenzService; +import com.yahoo.config.provision.CloudAccount; import com.yahoo.config.provision.Environment; import com.yahoo.config.provision.InstanceName; import com.yahoo.config.provision.RegionName; @@ -72,6 +73,8 @@ public class DeploymentSpecXmlReader { private static final String athenzDomainAttribute = "athenz-domain"; private static final String testerFlavorAttribute = "tester-flavor"; private static final String majorVersionAttribute = "major-version"; + private static final String globalServiceIdAttribute = "global-service-id"; + private static final String cloudAccountAttribute = "cloud-account"; private final boolean validate; private final Clock clock; @@ -118,7 +121,7 @@ public class DeploymentSpecXmlReader { List<Step> steps = new ArrayList<>(); List<Endpoint> applicationEndpoints = List.of(); if ( ! containsTag(instanceTag, root)) { // deployment spec skipping explicit instance -> "default" instance - steps.addAll(readInstanceContent("default", root, new MutableOptional<>(), root)); + steps.addAll(readInstanceContent("default", root, new HashMap<>(), root)); } else { if (XML.getChildren(root).stream().anyMatch(child -> child.getTagName().equals(prodTag))) @@ -129,9 +132,9 @@ public class DeploymentSpecXmlReader { for (Element child : XML.getChildren(root)) { String tagName = child.getTagName(); if (tagName.equals(instanceTag)) { - steps.addAll(readInstanceContent(child.getAttribute(idAttribute), child, new MutableOptional<>(), root)); + steps.addAll(readInstanceContent(child.getAttribute(idAttribute), child, new HashMap<>(), root)); } else { - steps.addAll(readNonInstanceSteps(child, new MutableOptional<>(), root)); // (No global service id here) + steps.addAll(readNonInstanceSteps(child, new HashMap<>(), root)); // (No global service id here) } } applicationEndpoints = readEndpoints(root, Optional.empty(), steps); @@ -156,7 +159,7 @@ public class DeploymentSpecXmlReader { */ private List<DeploymentInstanceSpec> readInstanceContent(String instanceNameString, Element instanceTag, - MutableOptional<String> globalServiceId, + Map<String, String> prodAttributes, Element parentTag) { if (instanceNameString.isBlank()) illegal("<instance> attribute 'id' must be specified, and not be blank"); @@ -183,7 +186,7 @@ public class DeploymentSpecXmlReader { // Values where there is no default List<Step> steps = new ArrayList<>(); for (Element instanceChild : XML.getChildren(instanceTag)) - steps.addAll(readNonInstanceSteps(instanceChild, globalServiceId, instanceChild)); + steps.addAll(readNonInstanceSteps(instanceChild, prodAttributes, instanceChild)); List<Endpoint> endpoints = readEndpoints(instanceTag, Optional.of(instanceNameString), steps); // Build and return instances with these values @@ -198,43 +201,49 @@ public class DeploymentSpecXmlReader { upgradeRollout, minRisk, maxRisk, maxIdleHours, changeBlockers, - globalServiceId.asOptional(), + Optional.ofNullable(prodAttributes.get(globalServiceIdAttribute)), athenzService, + Optional.ofNullable(prodAttributes.get(cloudAccountAttribute)) + .map(CloudAccount::new), notifications, endpoints, now)) .collect(Collectors.toList()); } - private List<Step> readSteps(Element stepTag, MutableOptional<String> globalServiceId, Element parentTag) { + private List<Step> readSteps(Element stepTag, Map<String, String> prodAttributes, Element parentTag) { if (stepTag.getTagName().equals(instanceTag)) - return new ArrayList<>(readInstanceContent(stepTag.getAttribute(idAttribute), stepTag, globalServiceId, parentTag)); + return new ArrayList<>(readInstanceContent(stepTag.getAttribute(idAttribute), stepTag, prodAttributes, parentTag)); else - return readNonInstanceSteps(stepTag, globalServiceId, parentTag); + return readNonInstanceSteps(stepTag, prodAttributes, parentTag); } // Consume the given tag as 0-N steps. 0 if it is not a step, >1 if it contains multiple nested steps that should be flattened - @SuppressWarnings("fallthrough") - private List<Step> readNonInstanceSteps(Element stepTag, MutableOptional<String> globalServiceId, Element parentTag) { + private List<Step> readNonInstanceSteps(Element stepTag, Map<String, String> prodAttributes, Element parentTag) { Optional<AthenzService> athenzService = mostSpecificAttribute(stepTag, athenzServiceAttribute).map(AthenzService::from); Optional<String> testerFlavor = mostSpecificAttribute(stepTag, testerFlavorAttribute); - if (prodTag.equals(stepTag.getTagName())) - globalServiceId.set(readGlobalServiceId(stepTag)); - else if (readGlobalServiceId(stepTag).isPresent()) - illegal("Attribute 'global-service-id' is only valid on 'prod' tag."); + if (prodTag.equals(stepTag.getTagName())) { + readGlobalServiceId(stepTag).ifPresent(id -> prodAttributes.put(globalServiceIdAttribute, id)); + readCloudAccount(stepTag).ifPresent(account -> prodAttributes.put(cloudAccountAttribute, account)); + } else { + if (readGlobalServiceId(stepTag).isPresent()) illegal("Attribute '" + globalServiceIdAttribute + "' is only valid on 'prod' tag"); + if (!regionTag.equals(stepTag.getTagName()) && readCloudAccount(stepTag).isPresent()) illegal("Attribute '" + cloudAccountAttribute + "' is only valid on 'prod' or 'region' tag"); + } switch (stepTag.getTagName()) { case testTag: if (Stream.iterate(stepTag, Objects::nonNull, Node::getParentNode) - .anyMatch(node -> prodTag.equals(node.getNodeName()))) + .anyMatch(node -> prodTag.equals(node.getNodeName()))) { return List.of(new DeclaredTest(RegionName.from(XML.getValue(stepTag).trim()))); + } + return List.of(new DeclaredZone(Environment.from(stepTag.getTagName()), Optional.empty(), false, athenzService, testerFlavor, Optional.empty())); case stagingTag: - return List.of(new DeclaredZone(Environment.from(stepTag.getTagName()), Optional.empty(), false, athenzService, testerFlavor)); + return List.of(new DeclaredZone(Environment.from(stepTag.getTagName()), Optional.empty(), false, athenzService, testerFlavor, Optional.empty())); case prodTag: // regions, delay and parallel may be nested within, but we can flatten them return XML.getChildren(stepTag).stream() - .flatMap(child -> readNonInstanceSteps(child, globalServiceId, stepTag).stream()) + .flatMap(child -> readNonInstanceSteps(child, prodAttributes, stepTag).stream()) .collect(Collectors.toList()); case delayTag: return List.of(new Delay(Duration.ofSeconds(longAttribute("hours", stepTag) * 60 * 60 + @@ -242,11 +251,11 @@ public class DeploymentSpecXmlReader { longAttribute("seconds", stepTag)))); case parallelTag: // regions and instances may be nested within return List.of(new ParallelSteps(XML.getChildren(stepTag).stream() - .flatMap(child -> readSteps(child, globalServiceId, parentTag).stream()) + .flatMap(child -> readSteps(child, prodAttributes, parentTag).stream()) .collect(Collectors.toList()))); case stepsTag: // regions and instances may be nested within return List.of(new Steps(XML.getChildren(stepTag).stream() - .flatMap(child -> readSteps(child, globalServiceId, parentTag).stream()) + .flatMap(child -> readSteps(child, prodAttributes, parentTag).stream()) .collect(Collectors.toList()))); case regionTag: return List.of(readDeclaredZone(Environment.prod, athenzService, testerFlavor, stepTag)); @@ -425,13 +434,19 @@ public class DeploymentSpecXmlReader { private DeclaredZone readDeclaredZone(Environment environment, Optional<AthenzService> athenzService, Optional<String> testerFlavor, Element regionTag) { return new DeclaredZone(environment, Optional.of(RegionName.from(XML.getValue(regionTag).trim())), - readActive(regionTag), athenzService, testerFlavor); + readActive(regionTag), athenzService, testerFlavor, + readCloudAccount(regionTag).map(CloudAccount::new)); + } + + private Optional<String> readCloudAccount(Element tag) { + return Optional.of(tag.getAttribute(cloudAccountAttribute)) + .filter(account -> !account.isEmpty()); } private Optional<String> readGlobalServiceId(Element environmentTag) { - String globalServiceId = environmentTag.getAttribute("global-service-id"); + String globalServiceId = environmentTag.getAttribute(globalServiceIdAttribute); if (globalServiceId.isEmpty()) return Optional.empty(); - deprecate(environmentTag, List.of("global-service-id"), "See https://cloud.vespa.ai/en/reference/routing#deprecated-syntax"); + deprecate(environmentTag, List.of(globalServiceIdAttribute), "See https://cloud.vespa.ai/en/reference/routing#deprecated-syntax"); return Optional.of(globalServiceId); } @@ -546,14 +561,4 @@ public class DeploymentSpecXmlReader { throw new IllegalArgumentException(message); } - private static class MutableOptional<T> { - - private Optional<T> value = Optional.empty(); - - public void set(Optional<T> value) { this.value = value; } - - public Optional<T> asOptional() { return value; } - - } - } diff --git a/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecTest.java b/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecTest.java index 5073c6b9fb2..dfe8b324d1c 100644 --- a/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecTest.java +++ b/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecTest.java @@ -3,6 +3,7 @@ package com.yahoo.config.application.api; import com.google.common.collect.ImmutableSet; import com.yahoo.config.application.api.xml.DeploymentSpecXmlReader; +import com.yahoo.config.provision.CloudAccount; import com.yahoo.config.provision.Environment; import com.yahoo.config.provision.InstanceName; import com.yahoo.config.provision.RegionName; @@ -1509,6 +1510,27 @@ public class DeploymentSpecTest { "</deployment>").deployableHashCode()); } + @Test + public void cloudAccount() { + StringReader r = new StringReader( + "<deployment version='1.0'>" + + " <instance id='beta'>" + + " <prod cloud-account='219876543210'>" + + " <region>us-west-1</region>" + + " </prod>" + + " </instance>" + + " <instance id='main'>" + + " <prod cloud-account='012345678912'>" + + " <region>us-east-1</region>" + + " </prod>" + + " </instance>" + + "</deployment>" + ); + DeploymentSpec spec = DeploymentSpec.fromXml(r); + assertEquals(Optional.of(new CloudAccount("219876543210")), spec.requireInstance("beta").cloudAccount(Environment.prod, RegionName.from("us-east-1"))); + assertEquals(Optional.of(new CloudAccount("012345678912")), spec.requireInstance("main").cloudAccount(Environment.prod, RegionName.from("us-west-1"))); + } + private static void assertInvalid(String deploymentSpec, String errorMessagePart) { assertInvalid(deploymentSpec, errorMessagePart, new ManualClock()); } diff --git a/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecWithoutInstanceTest.java b/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecWithoutInstanceTest.java index efed8ecc06c..8baeeb79441 100644 --- a/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecWithoutInstanceTest.java +++ b/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecWithoutInstanceTest.java @@ -2,6 +2,7 @@ package com.yahoo.config.application.api; import com.google.common.collect.ImmutableSet; +import com.yahoo.config.provision.CloudAccount; import com.yahoo.config.provision.Environment; import com.yahoo.config.provision.RegionName; import org.junit.Test; @@ -702,6 +703,33 @@ public class DeploymentSpecWithoutInstanceTest { assertEquals(Set.of("us-east", "us-west"), endpointRegions("default", spec)); } + @Test + public void productionSpecWithCloudAccount() { + StringReader r = new StringReader( + "<deployment version='1.0'>" + + " <prod cloud-account='012345678912'>" + + " <region cloud-account='219876543210'>us-east-1</region>" + + " <region>us-west-1</region>" + + " </prod>" + + "</deployment>" + ); + DeploymentSpec spec = DeploymentSpec.fromXml(r); + assertEquals(Optional.of(new CloudAccount("219876543210")), spec.requireInstance("default").cloudAccount(Environment.prod, RegionName.from("us-east-1"))); + assertEquals(Optional.of(new CloudAccount("012345678912")), spec.requireInstance("default").cloudAccount(Environment.prod, RegionName.from("us-west-1"))); + + r = new StringReader( + "<deployment version='1.0'>" + + " <prod>" + + " <region cloud-account='219876543210'>us-east-1</region>" + + " <region>us-west-1</region>" + + " </prod>" + + "</deployment>" + ); + spec = DeploymentSpec.fromXml(r); + assertEquals(Optional.of(new CloudAccount("219876543210")), spec.requireInstance("default").cloudAccount(Environment.prod, RegionName.from("us-east-1"))); + assertEquals(Optional.empty(), spec.requireInstance("default").cloudAccount(Environment.prod, RegionName.from("us-west-1"))); + } + private static Set<String> endpointRegions(String endpointId, DeploymentSpec spec) { return spec.requireInstance("default").endpoints().stream() .filter(endpoint -> endpoint.endpointId().equals(endpointId)) diff --git a/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java b/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java index 9eef1dc2447..74d92bcfd02 100644 --- a/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java +++ b/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java @@ -28,6 +28,7 @@ import com.yahoo.config.model.test.MockApplicationPackage; import com.yahoo.config.provision.DockerImage; import com.yahoo.config.provision.Zone; import com.yahoo.io.IOUtils; +import com.yahoo.search.query.profile.QueryProfileRegistry; import com.yahoo.searchdefinition.Application; import com.yahoo.searchdefinition.RankProfileRegistry; import com.yahoo.searchdefinition.Schema; @@ -334,6 +335,8 @@ public class DeployState implements ConfigDefinitionStore { private boolean accessLoggingEnabledByDefault = true; private Optional<DockerImage> wantedDockerImageRepo = Optional.empty(); private Reindexing reindexing = null; + private RankProfileRegistry rankProfileRegistry = new RankProfileRegistry(); + private QueryProfiles queryProfiles = null; public Builder() {} @@ -431,6 +434,21 @@ public class DeployState implements ConfigDefinitionStore { return this; } + public Builder rankProfileRegistry(RankProfileRegistry rankProfileRegistry) { + this.rankProfileRegistry = rankProfileRegistry; + return this; + } + + public Builder queryProfiles(QueryProfiles queryProfiles) { + this.queryProfiles = queryProfiles; + return this; + } + + public Builder queryProfiles(QueryProfileRegistry queryProfileRegistry) { + this.queryProfiles = new QueryProfiles(queryProfileRegistry, logger); + return this; + } + public Builder reindexing(Reindexing reindexing) { this.reindexing = Objects.requireNonNull(reindexing); return this; } public DeployState build() { @@ -438,8 +456,8 @@ public class DeployState implements ConfigDefinitionStore { } public DeployState build(ValidationParameters validationParameters) { - RankProfileRegistry rankProfileRegistry = new RankProfileRegistry(); - QueryProfiles queryProfiles = new QueryProfilesBuilder().build(applicationPackage, logger); + if (queryProfiles == null) + queryProfiles = new QueryProfilesBuilder().build(applicationPackage, logger); SemanticRules semanticRules = new SemanticRuleBuilder().build(applicationPackage); Application application = new ApplicationBuilder(applicationPackage, fileRegistry, logger, properties, rankProfileRegistry, queryProfiles.getRegistry()) diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/derived/DerivedConfiguration.java b/config-model/src/main/java/com/yahoo/searchdefinition/derived/DerivedConfiguration.java index 0c7c507f32d..8dec0e8339a 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/derived/DerivedConfiguration.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/derived/DerivedConfiguration.java @@ -1,13 +1,8 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.searchdefinition.derived; -import ai.vespa.rankingexpression.importer.configmodelview.ImportedMlModels; -import com.yahoo.concurrent.InThreadExecutorService; import com.yahoo.config.ConfigInstance; -import com.yahoo.config.model.api.ModelContext; -import com.yahoo.config.model.application.provider.BaseDeployLogger; -import com.yahoo.config.application.api.DeployLogger; -import com.yahoo.config.model.deploy.TestProperties; +import com.yahoo.config.model.deploy.DeployState; import com.yahoo.document.config.DocumenttypesConfig; import com.yahoo.document.config.DocumentmanagerConfig; import com.yahoo.io.IOUtils; @@ -21,7 +16,6 @@ import com.yahoo.vespa.model.container.search.QueryProfiles; import java.io.IOException; import java.io.Writer; -import java.util.concurrent.ExecutorService; /** * A set of all derived configuration of a schema. Use this as a facade to individual configurations when @@ -62,47 +56,36 @@ public class DerivedConfiguration implements AttributesConfig.Producer { } DerivedConfiguration(Schema schema, RankProfileRegistry rankProfileRegistry, QueryProfileRegistry queryProfiles) { - this(schema, new BaseDeployLogger(), new TestProperties(), rankProfileRegistry, queryProfiles, new ImportedMlModels(), new InThreadExecutorService()); + this(schema, new DeployState.Builder().rankProfileRegistry(rankProfileRegistry).queryProfiles(queryProfiles).build()); } /** - * Creates a complete derived configuration snapshot from a search definition. + * Creates a complete derived configuration snapshot from a schema. * - * @param schema the search to derive a configuration from. Derived objects will be snapshots, but this - * argument is live. Which means that this object will be inconsistent when the given - * search definition is later modified. - * @param deployLogger a {@link DeployLogger} for logging when doing operations on this - * @param deployProperties properties set on deploy - * @param rankProfileRegistry a {@link com.yahoo.searchdefinition.RankProfileRegistry} - * @param queryProfiles the query profiles of this application + * @param schema the schema to derive a configuration from. Derived objects will be snapshots, but this + * argument is live. Which means that this object will be inconsistent if the given + * schema is later modified. */ - public DerivedConfiguration(Schema schema, - DeployLogger deployLogger, - ModelContext.Properties deployProperties, - RankProfileRegistry rankProfileRegistry, - QueryProfileRegistry queryProfiles, - ImportedMlModels importedModels, - ExecutorService executor) { - Validator.ensureNotNull("Search definition", schema); + public DerivedConfiguration(Schema schema, DeployState deployState) { + Validator.ensureNotNull("Schema", schema); this.schema = schema; - this.queryProfiles = queryProfiles; - this.maxUncommittedMemory = deployProperties.featureFlags().maxUnCommittedMemory(); - this.enableBitVectors = deployProperties.featureFlags().enableBitVectors(); + this.queryProfiles = deployState.getQueryProfiles().getRegistry(); + this.maxUncommittedMemory = deployState.getProperties().featureFlags().maxUnCommittedMemory(); + this.enableBitVectors = deployState.getProperties().featureFlags().enableBitVectors(); if ( ! schema.isDocumentsOnly()) { streamingFields = new VsmFields(schema); streamingSummary = new VsmSummary(schema); } if ( ! schema.isDocumentsOnly()) { attributeFields = new AttributeFields(schema); - summaries = new Summaries(schema, deployLogger, deployProperties.featureFlags()); + summaries = new Summaries(schema, deployState.getDeployLogger(), deployState.getProperties().featureFlags()); summaryMap = new SummaryMap(schema); juniperrc = new Juniperrc(schema); rankProfileList = new RankProfileList(schema, schema.rankingConstants(), schema.rankExpressionFiles(), - schema.onnxModels(), attributeFields, rankProfileRegistry, - queryProfiles, importedModels, deployProperties, executor); + schema.onnxModels(), attributeFields, deployState); indexingScript = new IndexingScript(schema); indexInfo = new IndexInfo(schema); - schemaInfo = new SchemaInfo(schema, rankProfileRegistry, summaries, summaryMap); + schemaInfo = new SchemaInfo(schema, deployState.rankProfileRegistry(), summaries, summaryMap); indexSchema = new IndexSchema(schema); importedFields = new ImportedFields(schema); } diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/derived/RankProfileList.java b/config-model/src/main/java/com/yahoo/searchdefinition/derived/RankProfileList.java index c36bd96d309..a55c97f4ebb 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/derived/RankProfileList.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/derived/RankProfileList.java @@ -3,6 +3,7 @@ package com.yahoo.searchdefinition.derived; import ai.vespa.rankingexpression.importer.configmodelview.ImportedMlModels; import com.yahoo.config.model.api.ModelContext; +import com.yahoo.config.model.deploy.DeployState; import com.yahoo.search.query.profile.QueryProfileRegistry; import com.yahoo.searchdefinition.OnnxModel; import com.yahoo.searchdefinition.OnnxModels; @@ -60,16 +61,12 @@ public class RankProfileList extends Derived implements RankProfilesConfig.Produ LargeRankExpressions largeRankExpressions, OnnxModels onnxModels, AttributeFields attributeFields, - RankProfileRegistry rankProfileRegistry, - QueryProfileRegistry queryProfiles, - ImportedMlModels importedModels, - ModelContext.Properties deployProperties, - ExecutorService executor) { + DeployState deployState) { setName(schema == null ? "default" : schema.getName()); this.rankingConstants = rankingConstants; this.largeRankExpressions = largeRankExpressions; this.onnxModels = onnxModels; // as ONNX models come from parsing rank expressions - deriveRankProfiles(rankProfileRegistry, queryProfiles, importedModels, schema, attributeFields, deployProperties, executor); + deriveRankProfiles(schema, attributeFields, deployState); } private boolean areDependenciesReady(RankProfile rank, RankProfileRegistry registry) { @@ -78,28 +75,34 @@ public class RankProfileList extends Derived implements RankProfilesConfig.Produ (rank.schema() != null && rank.inheritedNames().stream().allMatch(name -> registry.resolve(rank.schema().getDocument(), name) != null)); } - private void deriveRankProfiles(RankProfileRegistry rankProfileRegistry, - QueryProfileRegistry queryProfiles, - ImportedMlModels importedModels, - Schema schema, + private void deriveRankProfiles(Schema schema, AttributeFields attributeFields, - ModelContext.Properties deployProperties, - ExecutorService executor) { + DeployState deployState) { if (schema != null) { // profiles belonging to a search have a default profile - RawRankProfile rawRank = new RawRankProfile(rankProfileRegistry.get(schema, "default"), - largeRankExpressions, queryProfiles, importedModels, attributeFields, deployProperties); + RawRankProfile rawRank = new RawRankProfile(deployState.rankProfileRegistry().get(schema, "default"), + largeRankExpressions, + deployState.getQueryProfiles().getRegistry(), + deployState.getImportedModels(), + attributeFields, + deployState.getProperties()); rankProfiles.put(rawRank.getName(), rawRank); } Map<String, RankProfile> remaining = new LinkedHashMap<>(); - rankProfileRegistry.rankProfilesOf(schema).forEach(rank -> remaining.put(rank.name(), rank)); + deployState.rankProfileRegistry().rankProfilesOf(schema).forEach(rank -> remaining.put(rank.name(), rank)); remaining.remove("default"); while (!remaining.isEmpty()) { List<RankProfile> ready = new ArrayList<>(); remaining.forEach((name, rank) -> { - if (areDependenciesReady(rank, rankProfileRegistry)) ready.add(rank); + if (areDependenciesReady(rank, deployState.rankProfileRegistry())) ready.add(rank); }); - processRankProfiles(ready, queryProfiles, importedModels, schema, attributeFields, deployProperties, executor); + processRankProfiles(ready, + deployState.getQueryProfiles().getRegistry(), + deployState.getImportedModels(), + schema, + attributeFields, + deployState.getProperties(), + deployState.getExecutor()); ready.forEach(rank -> remaining.remove(rank.name())); } } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/VespaModel.java b/config-model/src/main/java/com/yahoo/vespa/model/VespaModel.java index c671ad5bd17..6c04ebbc31e 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/VespaModel.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/VespaModel.java @@ -186,11 +186,7 @@ public final class VespaModel extends AbstractConfigProducerRoot implements Seri new LargeRankExpressions(deployState.getFileRegistry()), new OnnxModels(deployState.getFileRegistry(), Optional.empty()), AttributeFields.empty, - deployState.rankProfileRegistry(), - deployState.getQueryProfiles().getRegistry(), - deployState.getImportedModels(), - deployState.getProperties(), - deployState.getExecutor()); + deployState); HostSystem hostSystem = root.hostSystem(); if (complete) { // create a completed, frozen model diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/component/ConnectionLogComponent.java b/config-model/src/main/java/com/yahoo/vespa/model/container/component/ConnectionLogComponent.java index 07a48e94399..0c65aee798b 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/component/ConnectionLogComponent.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/component/ConnectionLogComponent.java @@ -10,21 +10,26 @@ public class ConnectionLogComponent extends SimpleComponent implements Connectio private final String logDirectoryName; private final String clusterName; + private final boolean isHostedVespa; public ConnectionLogComponent(ContainerCluster<?> cluster, Class<? extends ConnectionLog> cls, String logDirectoryName) { - this(cls, logDirectoryName, cluster.getName()); + this(cls, logDirectoryName, cluster.getName(), cluster.isHostedVespa()); } - public ConnectionLogComponent(Class<? extends ConnectionLog> cls, String logDirectoryName, String clusterName) { + public ConnectionLogComponent(Class<? extends ConnectionLog> cls, String logDirectoryName, String clusterName, boolean isHostedVespa) { super(cls.getName()); this.logDirectoryName = logDirectoryName; this.clusterName = clusterName; + this.isHostedVespa = isHostedVespa; } @Override public void getConfig(ConnectionLogConfig.Builder builder) { builder.cluster(clusterName); builder.logDirectoryName(logDirectoryName); + if (isHostedVespa) { + builder.useClusterIdInFileName(false); + } builder.queueSize(-1); } } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java index 18399e67ba2..bb84f809fc4 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java @@ -436,7 +436,12 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> { // Add connection log if access log is configured if (cluster.getAllComponents().stream().anyMatch(component -> component instanceof AccessLogComponent)) { - cluster.addComponent(new ConnectionLogComponent(cluster, FileConnectionLog.class, "qrs")); + // TODO: clean up after Vespa 8 + if (cluster.isHostedVespa() || deployState.getVespaVersion().getMajor() == 8) { + cluster.addComponent(new ConnectionLogComponent(cluster, FileConnectionLog.class, "access")); + } else { + cluster.addComponent(new ConnectionLogComponent(cluster, FileConnectionLog.class, "qrs")); + } } } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/search/IndexedSearchCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/search/IndexedSearchCluster.java index d5bf12df559..44e574199ea 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/search/IndexedSearchCluster.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/search/IndexedSearchCluster.java @@ -189,13 +189,7 @@ public class IndexedSearchCluster extends SearchCluster for (SchemaInfo spec : schemas().values()) { if (spec.fullSchema() instanceof DocumentOnlySchema) continue; DocumentDatabase db = new DocumentDatabase(this, spec.fullSchema().getName(), - new DerivedConfiguration(spec.fullSchema(), - deployState.getDeployLogger(), - deployState.getProperties(), - deployState.rankProfileRegistry(), - deployState.getQueryProfiles().getRegistry(), - deployState.getImportedModels(), - deployState.getExecutor())); + new DerivedConfiguration(spec.fullSchema(), deployState)); documentDbs.add(db); } } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/search/StreamingSearchCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/search/StreamingSearchCluster.java index df266ab77dd..09ed8bad403 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/search/StreamingSearchCluster.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/search/StreamingSearchCluster.java @@ -77,13 +77,7 @@ public class StreamingSearchCluster extends SearchCluster implements if ( ! schema.getName().equals(docTypeName)) throw new IllegalArgumentException("Document type name '" + docTypeName + "' must be the same as the schema name '" + schema.getName() + "'"); - this.schemaConfig = new DerivedConfiguration(schema, - deployState.getDeployLogger(), - deployState.getProperties(), - deployState.rankProfileRegistry(), - deployState.getQueryProfiles().getRegistry(), - deployState.getImportedModels(), - deployState.getExecutor()); + this.schemaConfig = new DerivedConfiguration(schema, deployState); } @Override diff --git a/config-model/src/main/resources/schema/deployment.rnc b/config-model/src/main/resources/schema/deployment.rnc index 08b23f77bc9..bda3f0c0896 100644 --- a/config-model/src/main/resources/schema/deployment.rnc +++ b/config-model/src/main/resources/schema/deployment.rnc @@ -97,6 +97,7 @@ Prod = element prod { attribute global-service-id { text }? & attribute athenz-service { xsd:string }? & attribute tester-flavor { xsd:string }? & + attribute cloud-account { xsd:string }? & Region* & Delay* & ProdTest* & @@ -110,6 +111,7 @@ ProdTest = element test { Region = element region { attribute active { xsd:boolean }? & attribute athenz-service { xsd:string }? & + attribute cloud-account { xsd:string }? & text } diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/derived/AbstractExportingTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/derived/AbstractExportingTestCase.java index 8548e50d4bc..992d770d851 100644 --- a/config-model/src/test/java/com/yahoo/searchdefinition/derived/AbstractExportingTestCase.java +++ b/config-model/src/test/java/com/yahoo/searchdefinition/derived/AbstractExportingTestCase.java @@ -4,6 +4,7 @@ package com.yahoo.searchdefinition.derived; import com.yahoo.concurrent.InThreadExecutorService; import com.yahoo.config.application.api.DeployLogger; import com.yahoo.config.model.application.provider.MockFileRegistry; +import com.yahoo.config.model.deploy.DeployState; import com.yahoo.config.model.deploy.TestProperties; import com.yahoo.document.config.DocumenttypesConfig; import com.yahoo.document.config.DocumentmanagerConfig; @@ -49,12 +50,11 @@ public abstract class AbstractExportingTestCase extends AbstractSchemaTestCase { ApplicationBuilder builder, DeployLogger logger) throws IOException { DerivedConfiguration config = new DerivedConfiguration(builder.getSchema(schemaName), - logger, - properties, - builder.getRankProfileRegistry(), - builder.getQueryProfileRegistry(), - new ImportedMlModels(), - new InThreadExecutorService()); + new DeployState.Builder().properties(properties) + .deployLogger(logger) + .rankProfileRegistry(builder.getRankProfileRegistry()) + .queryProfiles(builder.getQueryProfileRegistry()) + .build()); return export(dirName, builder, config); } @@ -108,10 +108,10 @@ public abstract class AbstractExportingTestCase extends AbstractSchemaTestCase { } protected DerivedConfiguration assertCorrectDeriving(String dirName, - String searchDefinitionName, + String schemaName, TestProperties properties, DeployLogger logger) throws IOException, ParseException { - DerivedConfiguration derived = derive(dirName, searchDefinitionName, properties, logger); + DerivedConfiguration derived = derive(dirName, schemaName, properties, logger); assertCorrectConfigFiles(dirName); return derived; } 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 bbcf4b48c1d..b9693685cf6 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 @@ -24,6 +24,9 @@ public class DockerImage { this.registry = Objects.requireNonNull(registry, "registry must be non-null"); this.repository = Objects.requireNonNull(repository, "repository must be non-null"); this.tag = Objects.requireNonNull(tag, "tag must be non-null"); + + if (tag.isPresent() && tag.get().isBlank()) + throw new IllegalArgumentException("Set tag cannot be empty"); } /** Returns the registry-part of this, i.e. the host/port of the registry. */ @@ -58,6 +61,8 @@ public class DockerImage { /** Returns a copy of this with registry set to given value */ public DockerImage withRegistry(String registry) { + if (registry.isBlank()) throw new IllegalArgumentException("Registry cannot be empty"); + if (registry.charAt(registry.length() - 1) == '/') throw new IllegalArgumentException("Registry cannot end with '/': " + registry); return new DockerImage(registry, repository, tag); } @@ -86,26 +91,21 @@ public class DockerImage { return Objects.hash(registry, repository, tag); } - public static DockerImage from(String registry, String repository) { - return new DockerImage(registry, repository, Optional.empty()); - } - public static DockerImage fromString(String s) { if (s.isEmpty()) return EMPTY; - int firstPathSeparator = s.indexOf('/'); - if (firstPathSeparator < 0) throw new IllegalArgumentException("Missing path separator in '" + s + "'"); + int repositoryStart = s.lastIndexOf('/', s.lastIndexOf('/') - 1); + if (repositoryStart < 0) throw new IllegalArgumentException("Expected to find at least 2 path segments in: " + s); - String registry = s.substring(0, firstPathSeparator); - String repository = s.substring(firstPathSeparator + 1); - if (repository.isEmpty()) throw new IllegalArgumentException("Repository must be non-empty in '" + s + "'"); + String registry = s.substring(0, repositoryStart); + String repository = s.substring(repositoryStart + 1); int tagStart = repository.indexOf(':'); - if (tagStart < 0) return new DockerImage(registry, repository, Optional.empty()); + Optional<String> tag = tagStart < 0 ? Optional.empty() : Optional.of(repository.substring(tagStart + 1)); - String tag = repository.substring(tagStart + 1); - repository = repository.substring(0, tagStart); - return new DockerImage(registry, repository, Optional.of(tag)); + if (tagStart >= 0) repository = repository.substring(0, tagStart); + if (repository.isEmpty()) throw new IllegalArgumentException("Repository must be non-empty in '" + s + "'"); + return new DockerImage(registry, repository, tag); } } diff --git a/config-provisioning/src/test/java/com/yahoo/config/provision/DockerImageTest.java b/config-provisioning/src/test/java/com/yahoo/config/provision/DockerImageTest.java index 71fd453aa26..2e0de192f03 100644 --- a/config-provisioning/src/test/java/com/yahoo/config/provision/DockerImageTest.java +++ b/config-provisioning/src/test/java/com/yahoo/config/provision/DockerImageTest.java @@ -8,6 +8,7 @@ import java.util.Map; import java.util.Optional; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.fail; /** @@ -22,7 +23,8 @@ public class DockerImageTest { "registry.example.com:9999/vespa/vespa:7.42", new DockerImage("registry.example.com:9999", "vespa/vespa", Optional.of("7.42")), "registry.example.com/vespa/vespa:7.42", new DockerImage("registry.example.com", "vespa/vespa", Optional.of("7.42")), "registry.example.com:9999/vespa/vespa", new DockerImage("registry.example.com:9999", "vespa/vespa", Optional.empty()), - "registry.example.com/vespa/vespa", new DockerImage("registry.example.com", "vespa/vespa", Optional.empty()) + "registry.example.com/vespa/vespa", new DockerImage("registry.example.com", "vespa/vespa", Optional.empty()), + "registry.example.com/project/repo/vespa/vespa", new DockerImage("registry.example.com/project/repo", "vespa/vespa", Optional.empty()) ); tests.forEach((value, expected) -> { DockerImage parsed = DockerImage.fromString(value); @@ -36,17 +38,26 @@ public class DockerImageTest { } @Test + public void registry_cannot_contain_slash() { + DockerImage image = DockerImage.fromString("registry.example.com/vespa/vespa"); + assertThrows(IllegalArgumentException.class, () -> image.withRegistry("")); + assertThrows(IllegalArgumentException.class, () -> image.withRegistry("my-registry/path/")); + } + + @Test public void parse_invalid() { List<String> tests = List.of( "registry.example.com", "registry.example.com/", + "registry.example.com/repository", + "registry.example.com/repository:", "foo", "foo:1.2.3" ); for (var value : tests) { try { DockerImage.fromString(value); - fail("Expected failure"); + fail("Expected failure for: " + value); } catch (IllegalArgumentException ignored) { } } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java index edcb9a0fd4b..66da009946e 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java @@ -30,6 +30,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; + import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; @@ -291,7 +292,7 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest { @Test public void test_docker_image_repository() { long sessionId = createSession(applicationId()); - String dockerImageRepository = "foo.bar.com:4443/baz"; + String dockerImageRepository = "foo.bar.com:4443/baz/qux"; request(HttpRequest.Method.PUT, sessionId, Map.of("dockerImageRepository", dockerImageRepository, "applicationName", applicationId().application().value())); applicationRepository.activate(tenantRepository.getTenant(tenant), sessionId, timeoutBudget, false); diff --git a/container-core/src/main/java/com/yahoo/container/logging/ConnectionLogHandler.java b/container-core/src/main/java/com/yahoo/container/logging/ConnectionLogHandler.java index a572f0be998..90d7aef1803 100644 --- a/container-core/src/main/java/com/yahoo/container/logging/ConnectionLogHandler.java +++ b/container-core/src/main/java/com/yahoo/container/logging/ConnectionLogHandler.java @@ -9,13 +9,15 @@ class ConnectionLogHandler { private final LogFileHandler<ConnectionLogEntry> logFileHandler; public ConnectionLogHandler(String logDirectoryName, int bufferSize, String clusterName, - int queueSize, LogWriter<ConnectionLogEntry> logWriter) { + int queueSize, LogWriter<ConnectionLogEntry> logWriter, boolean useClusterIdInFileName) { logFileHandler = new LogFileHandler<>( LogFileHandler.Compression.ZSTD, bufferSize, - String.format("logs/vespa/%s/ConnectionLog.%s.%s", logDirectoryName, clusterName, "%Y%m%d%H%M%S"), + useClusterIdInFileName ? String.format("logs/vespa/%s/ConnectionLog.%s.%s", logDirectoryName, clusterName, "%Y%m%d%H%M%S") : + String.format("logs/vespa/%s/ConnectionLog.%s", logDirectoryName, "%Y%m%d%H%M%S"), "0 60 ...", - String.format("ConnectionLog.%s", clusterName), + useClusterIdInFileName ? String.format("ConnectionLog.%s", clusterName) : + "ConnectionLog.", queueSize, "connection-logger", logWriter); diff --git a/container-core/src/main/java/com/yahoo/container/logging/FileConnectionLog.java b/container-core/src/main/java/com/yahoo/container/logging/FileConnectionLog.java index 72c93443d31..57b4783153d 100644 --- a/container-core/src/main/java/com/yahoo/container/logging/FileConnectionLog.java +++ b/container-core/src/main/java/com/yahoo/container/logging/FileConnectionLog.java @@ -15,7 +15,7 @@ public class FileConnectionLog extends AbstractComponent implements ConnectionLo @Inject public FileConnectionLog(ConnectionLogConfig config) { logHandler = new ConnectionLogHandler(config.logDirectoryName(), config.bufferSize(), config.cluster(), - queueSize(config), new JsonConnectionLogWriter()); + queueSize(config), new JsonConnectionLogWriter(), config.useClusterIdInFileName()); } private static int queueSize(ConnectionLogConfig config) { diff --git a/container-core/src/main/resources/configdefinitions/container.logging.connection-log.def b/container-core/src/main/resources/configdefinitions/container.logging.connection-log.def index 026e2a85a8d..0d58684538a 100644 --- a/container-core/src/main/resources/configdefinitions/container.logging.connection-log.def +++ b/container-core/src/main/resources/configdefinitions/container.logging.connection-log.def @@ -12,3 +12,6 @@ queueSize int default=10000 # Buffer size for the output stream has a default of 256k bufferSize int default=262144 + +# In hosted Vespa we do not use the clusterId in file names for application containers +useClusterIdInFileName bool default=true
\ No newline at end of file diff --git a/container-search/src/main/java/com/yahoo/search/query/profile/QueryProfileRegistry.java b/container-search/src/main/java/com/yahoo/search/query/profile/QueryProfileRegistry.java index 1910078058a..e942d5dbdef 100644 --- a/container-search/src/main/java/com/yahoo/search/query/profile/QueryProfileRegistry.java +++ b/container-search/src/main/java/com/yahoo/search/query/profile/QueryProfileRegistry.java @@ -49,30 +49,30 @@ public class QueryProfileRegistry extends ComponentRegistry<QueryProfile> { * which has a type which allows path mahting is used. If there is no such profile, null is returned. */ public QueryProfile findQueryProfile(String idString) { - if (idString==null) return getComponent("default"); - ComponentSpecification id=new ComponentSpecification(idString); - QueryProfile profile=getComponent(id); - if (profile!=null) return profile; + if (idString == null) return getComponent("default"); + ComponentSpecification id = new ComponentSpecification(idString); + QueryProfile profile = getComponent(id); + if (profile != null) return profile; return findPathParentQueryProfile(new ComponentSpecification(idString)); } private QueryProfile findPathParentQueryProfile(ComponentSpecification id) { // Try the name with "/" appended - should have the same semantics with path matching - QueryProfile slashedProfile=getComponent(new ComponentSpecification(id.getName() + "/",id.getVersionSpecification())); - if (slashedProfile!=null && slashedProfile.getType()!=null && slashedProfile.getType().getMatchAsPath()) + QueryProfile slashedProfile = getComponent(new ComponentSpecification(id.getName() + "/", id.getVersionSpecification())); + if (slashedProfile != null && slashedProfile.getType() != null && slashedProfile.getType().getMatchAsPath()) return slashedProfile; // Extract the parent (if any) - int slashIndex=id.getName().lastIndexOf("/"); - if (slashIndex<1) return null; - String parentName=id.getName().substring(0,slashIndex); + int slashIndex = id.getName().lastIndexOf("/"); + if (slashIndex < 1) return null; + String parentName = id.getName().substring(0,slashIndex); - ComponentSpecification parentId=new ComponentSpecification(parentName,id.getVersionSpecification()); + ComponentSpecification parentId = new ComponentSpecification(parentName, id.getVersionSpecification()); - QueryProfile pathParentProfile=getComponent(parentId); + QueryProfile pathParentProfile = getComponent(parentId); - if (pathParentProfile!=null && pathParentProfile.getType()!=null && pathParentProfile.getType().getMatchAsPath()) + if (pathParentProfile != null && pathParentProfile.getType() != null && pathParentProfile.getType().getMatchAsPath()) return pathParentProfile; return findPathParentQueryProfile(parentId); } diff --git a/dist/vespa.spec b/dist/vespa.spec index 029346686a0..c45fb81f7a6 100644 --- a/dist/vespa.spec +++ b/dist/vespa.spec @@ -110,7 +110,7 @@ BuildRequires: vespa-gtest = 1.11.0 BuildRequires: vespa-icu-devel >= 65.1.0-1 BuildRequires: vespa-lz4-devel >= 1.9.2-2 BuildRequires: vespa-onnxruntime-devel = 1.11.0 -BuildRequires: vespa-openssl-devel >= 1.1.1n-1 +BuildRequires: vespa-openssl-devel >= 1.1.1o-1 %define _use_vespa_openssl 1 BuildRequires: vespa-protobuf-devel = 3.19.1 BuildRequires: vespa-libzstd-devel >= 1.4.5-2 @@ -132,7 +132,7 @@ BuildRequires: (llvm-devel >= 12.0.0 and llvm-devel < 13) BuildRequires: (llvm-devel >= 12.0.1 and llvm-devel < 13) %endif BuildRequires: vespa-boost-devel >= 1.76.0-1 -BuildRequires: vespa-openssl-devel >= 1.1.1n-1 +BuildRequires: vespa-openssl-devel >= 1.1.1o-1 %define _use_vespa_openssl 1 BuildRequires: vespa-gtest = 1.11.0 %define _use_vespa_gtest 1 @@ -386,7 +386,7 @@ Requires: vespa-xxhash = 0.8.0 Requires: xxhash-libs >= 0.8.0 %endif %if 0%{?el7} || 0%{?el8} -Requires: vespa-openssl >= 1.1.1n-1 +Requires: vespa-openssl >= 1.1.1o-1 %else Requires: openssl-libs %endif @@ -423,7 +423,7 @@ Requires: vespa-protobuf = 3.19.1 Requires: libicu %endif %if 0%{?el7} || 0%{?el8} -Requires: vespa-openssl >= 1.1.1n-1 +Requires: vespa-openssl >= 1.1.1o-1 %else Requires: openssl-libs %endif diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/maintenance/StorageMaintainer.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/maintenance/StorageMaintainer.java index 30fb9ac03de..b820bf42287 100644 --- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/maintenance/StorageMaintainer.java +++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/maintenance/StorageMaintainer.java @@ -153,7 +153,7 @@ public class StorageMaintainer { rules.add(CoredumpCleanupRule.forContainer(context.paths().underVespaHome("var/crash"))); if (context.node().membership().map(m -> m.type().hasContainer()).orElse(false)) - rules.add(new LinearCleanupRule(() -> FileFinder.files(context.paths().underVespaHome("logs/vespa/qrs")).list(), + rules.add(new LinearCleanupRule(() -> FileFinder.files(context.paths().underVespaHome("logs/vespa/access")).list(), fa -> monthNormalizer.apply(fa.lastModifiedTime()), Priority.LOWEST, Priority.HIGHEST)); if (context.nodeType() == NodeType.tenant && context.node().membership().map(m -> m.type().isAdmin()).orElse(false)) diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/RealNodeRepositoryTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/RealNodeRepositoryTest.java index 3f07a8f5c90..98a85085b4a 100644 --- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/RealNodeRepositoryTest.java +++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/RealNodeRepositoryTest.java @@ -135,7 +135,7 @@ public class RealNodeRepositoryTest { hostname, new NodeAttributes() .withRestartGeneration(1) - .withDockerImage(DockerImage.fromString("registry.example.com/image-1:6.2.3"))); + .withDockerImage(DockerImage.fromString("registry.example.com/repo/image-1:6.2.3"))); } @Test diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/container/image/ContainerImageDownloaderTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/container/image/ContainerImageDownloaderTest.java index 12482b07b91..7db8cb79949 100644 --- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/container/image/ContainerImageDownloaderTest.java +++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/container/image/ContainerImageDownloaderTest.java @@ -21,7 +21,7 @@ public class ContainerImageDownloaderTest { ContainerEngineMock podman = new ContainerEngineMock().asyncImageDownload(true); ContainerImageDownloader downloader = new ContainerImageDownloader(podman); TaskContext context = new TestTaskContext(); - DockerImage image = DockerImage.fromString("registry.example.com/vespa:7.42"); + DockerImage image = DockerImage.fromString("registry.example.com/repo/vespa:7.42"); assertFalse("Download started", downloader.get(context, image, RegistryCredentials.none)); assertFalse("Download pending", downloader.get(context, image, RegistryCredentials.none)); diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integration/ContainerFailTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integration/ContainerFailTest.java index 5649da7c4ea..c22f2b0ab50 100644 --- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integration/ContainerFailTest.java +++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integration/ContainerFailTest.java @@ -23,7 +23,7 @@ public class ContainerFailTest { @Test public void test() { - DockerImage dockerImage = DockerImage.fromString("registry.example.com/dockerImage"); + DockerImage dockerImage = DockerImage.fromString("registry.example.com/repo/image"); try (ContainerTester tester = new ContainerTester(List.of(dockerImage))) { ContainerName containerName = new ContainerName("host1"); String hostname = "host1.test.yahoo.com"; diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integration/MultiContainerTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integration/MultiContainerTest.java index 79546d8cf78..eab320733ee 100644 --- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integration/MultiContainerTest.java +++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integration/MultiContainerTest.java @@ -21,8 +21,8 @@ public class MultiContainerTest { @Test public void test() { - DockerImage image1 = DockerImage.fromString("registry.example.com/image1"); - DockerImage image2 = DockerImage.fromString("registry.example.com/image2"); + DockerImage image1 = DockerImage.fromString("registry.example.com/repo/image1"); + DockerImage image2 = DockerImage.fromString("registry.example.com/repo/image2"); try (ContainerTester tester = new ContainerTester(List.of(image1, image2))) { addAndWaitForNode(tester, "host1.test.yahoo.com", image1); NodeSpec nodeSpec2 = addAndWaitForNode(tester, "host2.test.yahoo.com", image2); diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integration/RebootTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integration/RebootTest.java index 277f9906dde..8498fa57084 100644 --- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integration/RebootTest.java +++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integration/RebootTest.java @@ -23,7 +23,7 @@ import static org.mockito.ArgumentMatchers.eq; public class RebootTest { private final String hostname = "host1.test.yahoo.com"; - private final DockerImage dockerImage = DockerImage.fromString("registry.example.com/dockerImage"); + private final DockerImage dockerImage = DockerImage.fromString("registry.example.com/repo/image"); @Test public void test() { diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integration/RestartTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integration/RestartTest.java index 0675626c0e2..9a481959c63 100644 --- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integration/RestartTest.java +++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integration/RestartTest.java @@ -22,7 +22,7 @@ public class RestartTest { @Test public void test() { - DockerImage dockerImage = DockerImage.fromString("registry.example.com/dockerImage:1.2.3"); + DockerImage dockerImage = DockerImage.fromString("registry.example.com/repo/image:1.2.3"); try (ContainerTester tester = new ContainerTester(List.of(dockerImage))) { String hostname = "host1.test.yahoo.com"; NodeSpec nodeSpec = NodeSpec.Builder.testSpec(hostname).wantedDockerImage(dockerImage).build(); diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/maintenance/sync/SyncFileInfoTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/maintenance/sync/SyncFileInfoTest.java index 1b5c51082c5..94c2ce6d106 100644 --- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/maintenance/sync/SyncFileInfoTest.java +++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/maintenance/sync/SyncFileInfoTest.java @@ -25,12 +25,12 @@ public class SyncFileInfoTest { private static final FileSystem fileSystem = TestFileSystem.create(); private static final URI nodeArchiveUri = URI.create("s3://vespa-data-bucket/vespa/music/main/h432a/"); - private static final Path accessLogPath1 = fileSystem.getPath("/opt/vespa/logs/qrs/access.log.20210211"); - private static final Path accessLogPath2 = fileSystem.getPath("/opt/vespa/logs/qrs/access.log.20210212.zst"); - private static final Path accessLogPath3 = fileSystem.getPath("/opt/vespa/logs/qrs/access-json.log.20210213.zst"); - private static final Path accessLogPath4 = fileSystem.getPath("/opt/vespa/logs/qrs/JsonAccessLog.default.20210214.zst"); - private static final Path connectionLogPath1 = fileSystem.getPath("/opt/vespa/logs/qrs/ConnectionLog.default.20210210"); - private static final Path connectionLogPath2 = fileSystem.getPath("/opt/vespa/logs/qrs/ConnectionLog.default.20210212.zst"); + private static final Path accessLogPath1 = fileSystem.getPath("/opt/vespa/logs/access/access.log.20210211"); + private static final Path accessLogPath2 = fileSystem.getPath("/opt/vespa/logs/access/access.log.20210212.zst"); + private static final Path accessLogPath3 = fileSystem.getPath("/opt/vespa/logs/access/access-json.log.20210213.zst"); + private static final Path accessLogPath4 = fileSystem.getPath("/opt/vespa/logs/access/JsonAccessLog.20210214.zst"); + private static final Path connectionLogPath1 = fileSystem.getPath("/opt/vespa/logs/access/ConnectionLog.20210210"); + private static final Path connectionLogPath2 = fileSystem.getPath("/opt/vespa/logs/access/ConnectionLog.20210212.zst"); private static final Path vespaLogPath1 = fileSystem.getPath("/opt/vespa/logs/vespa.log"); private static final Path vespaLogPath2 = fileSystem.getPath("/opt/vespa/logs/vespa.log-2021-02-12"); private static final Path zkLogPath0 = fileSystem.getPath("/opt/vespa/logs/zookeeper.configserver.0.log"); @@ -47,17 +47,17 @@ public class SyncFileInfoTest { assertForLogFile(accessLogPath3, "s3://vespa-data-bucket/vespa/music/main/h432a/logs/access/access-json.log.20210213.zst", NONE, true); assertForLogFile(accessLogPath3, "s3://vespa-data-bucket/vespa/music/main/h432a/logs/access/access-json.log.20210213.zst", NONE, false); - assertForLogFile(accessLogPath4, "s3://vespa-data-bucket/vespa/music/main/h432a/logs/access/JsonAccessLog.default.20210214.zst", NONE, true); - assertForLogFile(accessLogPath4, "s3://vespa-data-bucket/vespa/music/main/h432a/logs/access/JsonAccessLog.default.20210214.zst", NONE, false); + assertForLogFile(accessLogPath4, "s3://vespa-data-bucket/vespa/music/main/h432a/logs/access/JsonAccessLog.20210214.zst", NONE, true); + assertForLogFile(accessLogPath4, "s3://vespa-data-bucket/vespa/music/main/h432a/logs/access/JsonAccessLog.20210214.zst", NONE, false); } @Test public void connection_logs() { assertForLogFile(connectionLogPath1, null, null, true); - assertForLogFile(connectionLogPath1, "s3://vespa-data-bucket/vespa/music/main/h432a/logs/connection/ConnectionLog.default.20210210.zst", ZSTD, false); + assertForLogFile(connectionLogPath1, "s3://vespa-data-bucket/vespa/music/main/h432a/logs/connection/ConnectionLog.20210210.zst", ZSTD, false); - assertForLogFile(connectionLogPath2, "s3://vespa-data-bucket/vespa/music/main/h432a/logs/connection/ConnectionLog.default.20210212.zst", NONE, true); - assertForLogFile(connectionLogPath2, "s3://vespa-data-bucket/vespa/music/main/h432a/logs/connection/ConnectionLog.default.20210212.zst", NONE, false); + assertForLogFile(connectionLogPath2, "s3://vespa-data-bucket/vespa/music/main/h432a/logs/connection/ConnectionLog.20210212.zst", NONE, true); + assertForLogFile(connectionLogPath2, "s3://vespa-data-bucket/vespa/music/main/h432a/logs/connection/ConnectionLog.20210212.zst", NONE, false); } @Test 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 2eff2c64cec..d31c341532f 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 @@ -64,7 +64,7 @@ public class NodeAgentImplTest { private static final String hostName = "host1.test.yahoo.com"; private final NodeAgentContextSupplier contextSupplier = mock(NodeAgentContextSupplier.class); - private final DockerImage dockerImage = DockerImage.fromString("registry.example.com/dockerImage"); + private final DockerImage dockerImage = DockerImage.fromString("registry.example.com/repo/image"); private final ContainerOperations containerOperations = mock(ContainerOperations.class); private final NodeRepository nodeRepository = mock(NodeRepository.class); private final Orchestrator orchestrator = mock(Orchestrator.class); @@ -193,7 +193,7 @@ public class NodeAgentImplTest { @Test public void containerIsNotStoppedIfNewImageMustBePulled() { - final DockerImage newDockerImage = DockerImage.fromString("registry.example.com/new-image"); + final DockerImage newDockerImage = DockerImage.fromString("registry.example.com/repo/new-image"); final NodeSpec node = nodeBuilder(NodeState.active) .wantedDockerImage(newDockerImage).currentDockerImage(dockerImage) .wantedVespaVersion(vespaVersion).currentVespaVersion(vespaVersion) diff --git a/searchcore/src/apps/proton/proton.cpp b/searchcore/src/apps/proton/proton.cpp index c823ee8a09f..386ceb4eeda 100644 --- a/searchcore/src/apps/proton/proton.cpp +++ b/searchcore/src/apps/proton/proton.cpp @@ -203,6 +203,21 @@ buildTransportConfig() { return fnet::TransportConfig(std::max(1u, std::min(4u, numProcs/8))); } +class Transport { +public: + Transport(const fnet::TransportConfig & config, FastOS_ThreadPool & threadPool) + : _transport(config) + { + _transport.Start(&threadPool); + } + ~Transport() { + _transport.ShutDown(true); + } + FNET_Transport & transport() { return _transport; } +private: + FNET_Transport _transport; +}; + } void @@ -268,10 +283,8 @@ App::main(int argc, char **argv) setupSignals(); setup_fadvise(); FastOS_ThreadPool threadPool(128_Ki); - FNET_Transport transport(buildTransportConfig()); - transport.Start(&threadPool); - startAndRun(threadPool, transport, argc, argv); - transport.ShutDown(true); + Transport transport(buildTransportConfig(), threadPool); + startAndRun(threadPool, transport.transport(), argc, argv); } catch (const vespalib::InvalidCommandLineArgumentsException &e) { LOG(warning, "Invalid commandline arguments: '%s'", e.what()); return 1; diff --git a/searchlib/src/vespa/searchlib/common/allocatedbitvector.cpp b/searchlib/src/vespa/searchlib/common/allocatedbitvector.cpp index f37968c70a0..33f044845aa 100644 --- a/searchlib/src/vespa/searchlib/common/allocatedbitvector.cpp +++ b/searchlib/src/vespa/searchlib/common/allocatedbitvector.cpp @@ -108,23 +108,4 @@ AllocatedBitVector::resize(Index newLength) clear(); } -AllocatedBitVector & -AllocatedBitVector::operator=(const AllocatedBitVector & rhs) -{ - AllocatedBitVector tmp(rhs); - swap(tmp); - assert(testBit(size())); - - return *this; -} -AllocatedBitVector & -AllocatedBitVector::operator=(const BitVector & rhs) -{ - AllocatedBitVector tmp(rhs); - swap(tmp); - assert(testBit(size())); - - return *this; -} - } // namespace search diff --git a/searchlib/src/vespa/searchlib/common/allocatedbitvector.h b/searchlib/src/vespa/searchlib/common/allocatedbitvector.h index 5106717dad0..a47082dc413 100644 --- a/searchlib/src/vespa/searchlib/common/allocatedbitvector.h +++ b/searchlib/src/vespa/searchlib/common/allocatedbitvector.h @@ -41,8 +41,6 @@ public: AllocatedBitVector(const BitVector &other); AllocatedBitVector(const AllocatedBitVector &other); ~AllocatedBitVector() override; - AllocatedBitVector &operator=(const AllocatedBitVector &other); - AllocatedBitVector &operator=(const BitVector &other); /** * Query the size of the bit vector. @@ -67,14 +65,8 @@ protected: private: friend class BitVectorTest; friend class GrowableBitVector; - void swap(AllocatedBitVector & rhs) { - std::swap(_capacityBits, rhs._capacityBits); - _alloc.swap(rhs._alloc); - BitVector::swap(rhs); - } AllocatedBitVector(const BitVector &other, std::pair<Index, Index> size_capacity); }; } // namespace search - diff --git a/searchlib/src/vespa/searchlib/common/bitvector.h b/searchlib/src/vespa/searchlib/common/bitvector.h index dfc3d0b280a..3f11e2a257e 100644 --- a/searchlib/src/vespa/searchlib/common/bitvector.h +++ b/searchlib/src/vespa/searchlib/common/bitvector.h @@ -207,17 +207,6 @@ public: _numTrueBits.store(invalidCount(), std::memory_order_relaxed); } - void swap(BitVector & rhs) { - auto my_words = _words; - vespalib::atomic::store_ref_release(_words, rhs._words); - vespalib::atomic::store_ref_release(rhs._words, my_words); - std::swap(_startOffset, rhs._startOffset); - std::swap(_sz, rhs._sz); - Index tmp = rhs._numTrueBits; - rhs._numTrueBits = _numTrueBits.load(std::memory_order_relaxed); - _numTrueBits.store(tmp, std::memory_order_relaxed); - } - /** * Count bits in partial bitvector [..>. * @@ -393,4 +382,3 @@ void BitVector::andNotWithT(T it) { } } // namespace search - |