summaryrefslogtreecommitdiffstats
path: root/config-model
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2019-08-02 22:39:15 +0200
committerGitHub <noreply@github.com>2019-08-02 22:39:15 +0200
commitcef3960c32187712b6aa16e6243e0233846725e3 (patch)
tree57abfff0b8849192a4f22a5aa5aa686ba53a9a79 /config-model
parentc8e788d9bd47fa1184fe843b4efd05c914a33c7e (diff)
Revert "As redundancy and searchable copies depends on group setup normally,"
Diffstat (limited to 'config-model')
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/ContentSearchCluster.java8
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/IndexedHierarchicDistributionValidator.java38
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/Redundancy.java48
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/StorageGroup.java84
-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/content/cluster/RedundancyBuilder.java24
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/content/DistributorTest.java1
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/content/RedundancyTest.java4
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/content/StorageClusterTest.java4
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/content/StorageGroupTest.java2
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/content/cluster/ClusterTest.java2
11 files changed, 131 insertions, 116 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/ContentSearchCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/content/ContentSearchCluster.java
index a6228af8991..b324b496b1a 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/ContentSearchCluster.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/ContentSearchCluster.java
@@ -233,7 +233,7 @@ public class ContentSearchCluster extends AbstractConfigProducer implements Prot
Optional<Tuning> tuning = Optional.ofNullable(this.tuning);
if (element == null) {
snode = SearchNode.create(parent, "" + node.getDistributionKey(), node.getDistributionKey(), spec,
- clusterName, node, flushOnShutdown, tuning, parentGroup.isHosted());
+ clusterName, node, flushOnShutdown, tuning, parentGroup.getOwner().isHostedVespa());
snode.setHostResource(node.getHostResource());
snode.initService(deployState.getDeployLogger());
@@ -283,12 +283,12 @@ public class ContentSearchCluster extends AbstractConfigProducer implements Prot
if (usesHierarchicDistribution()) {
indexedCluster.setMaxNodesDownPerFixedRow((redundancy.effectiveFinalRedundancy() / groupToSpecMap.size()) - 1);
}
- indexedCluster.setSearchableCopies(redundancy.readyCopies());
+ indexedCluster.setSearchableCopies(redundancy.searchableCopies());
}
this.redundancy = redundancy;
for (SearchNode node : getSearchNodes()) {
- node.setRedundancy(redundancy.finalRedundancy());
- node.setSearchableCopies(redundancy.readyCopies());
+ node.setRedundancy(redundancy.redundancyFromSearchNodePerspective());
+ node.setSearchableCopies(redundancy.searchableCopies());
}
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/IndexedHierarchicDistributionValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/content/IndexedHierarchicDistributionValidator.java
index 7ab5ee9fd80..c721d3d48bc 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/IndexedHierarchicDistributionValidator.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/IndexedHierarchicDistributionValidator.java
@@ -33,15 +33,15 @@ public class IndexedHierarchicDistributionValidator {
public void validate() throws Exception {
validateThatWeHaveOneGroupLevel();
validateThatLeafGroupsHasEqualNumberOfNodes();
- validateThatLeafGroupsCountIsAFactorOfRedundancy(clusterName, redundancy.effectiveFinalRedundancy(), rootGroup.getSubgroups().size());
+ validateThatLeafGroupsCountIsAFactorOfRedundancy();
validateThatRedundancyPerGroupIsEqual();
- validateThatReadyCopiesIsCompatibleWithRedundancy(clusterName, redundancy.effectiveFinalRedundancy(), redundancy.effectiveReadyCopies(), rootGroup.getSubgroups().size());
+ validateThatReadyCopiesIsCompatibleWithRedundancy(rootGroup.getSubgroups().size());
}
private void validateThatWeHaveOneGroupLevel() {
for (StorageGroup group : rootGroup.getSubgroups()) {
if (group.getSubgroups().size() > 0) {
- throw new IllegalArgumentException(getErrorMsgPrefix(clusterName) + "Expected all groups under root group '" +
+ throw new IllegalArgumentException(getErrorMsgPrefix() + "Expected all groups under root group '" +
rootGroup.getName() + "' to be leaf groups only containing nodes, but sub group '" + group.getName() + "' contains " +
group.getSubgroups().size() + " sub groups.");
}
@@ -59,18 +59,18 @@ public class IndexedHierarchicDistributionValidator {
}
if (group.getNodes().size() != previousGroup.getNodes().size())
- throw new IllegalArgumentException(getErrorMsgPrefix(clusterName) + "Expected leaf groups to contain an equal number of nodes, but leaf group '" +
+ throw new IllegalArgumentException(getErrorMsgPrefix() + "Expected leaf groups to contain an equal number of nodes, but leaf group '" +
previousGroup.getName() + "' contains " + previousGroup.getNodes().size() + " node(s) while leaf group '" +
group.getName() + "' contains " + group.getNodes().size() + " node(s).");
previousGroup = group;
}
}
- static public void validateThatLeafGroupsCountIsAFactorOfRedundancy(String clusterName, int totalRedundancy, int subGroups) {
- if (totalRedundancy % subGroups != 0) {
- throw new IllegalArgumentException(getErrorMsgPrefix(clusterName) + "Expected number of leaf groups (" +
- subGroups + ") to be a factor of redundancy (" +
- totalRedundancy + "), but it is not.");
+ private void validateThatLeafGroupsCountIsAFactorOfRedundancy() {
+ if (redundancy.effectiveFinalRedundancy() % rootGroup.getSubgroups().size() != 0) {
+ throw new IllegalArgumentException(getErrorMsgPrefix() + "Expected number of leaf groups (" +
+ rootGroup.getSubgroups().size() + ") to be a factor of redundancy (" +
+ redundancy.effectiveFinalRedundancy() + "), but it is not.");
}
}
@@ -78,7 +78,7 @@ public class IndexedHierarchicDistributionValidator {
int redundancyPerGroup = redundancy.effectiveFinalRedundancy() / rootGroup.getSubgroups().size();
String expPartitions = createDistributionPartitions(redundancyPerGroup, rootGroup.getSubgroups().size());
if (!rootGroup.getPartitions().get().equals(expPartitions)) {
- throw new IllegalArgumentException(getErrorMsgPrefix(clusterName) + "Expected redundancy per leaf group to be " +
+ throw new IllegalArgumentException(getErrorMsgPrefix() + "Expected redundancy per leaf group to be " +
redundancyPerGroup + ", but it is not according to distribution partitions '" +
rootGroup.getPartitions().get() + "'. Expected distribution partitions should be '" + expPartitions + "'.");
}
@@ -98,20 +98,20 @@ public class IndexedHierarchicDistributionValidator {
return sb.toString();
}
- static public void validateThatReadyCopiesIsCompatibleWithRedundancy(String clusterName, int totalRedundancy, int totalReadyCopies, int groupCount) {
- if (totalRedundancy % groupCount != 0) {
- throw new IllegalArgumentException(getErrorMsgPrefix(clusterName) + "Expected equal redundancy per group.");
+ private void validateThatReadyCopiesIsCompatibleWithRedundancy(int groupCount) throws Exception {
+ if (redundancy.effectiveFinalRedundancy() % groupCount != 0) {
+ throw new Exception(getErrorMsgPrefix() + "Expected equal redundancy per group.");
}
- if (totalReadyCopies % groupCount != 0) {
- throw new IllegalArgumentException(getErrorMsgPrefix(clusterName) + "Expected equal amount of ready copies per group, but " +
- totalReadyCopies + " ready copies is specified with " + groupCount + " groups");
+ if (redundancy.effectiveReadyCopies() % groupCount != 0) {
+ throw new Exception(getErrorMsgPrefix() + "Expected equal amount of ready copies per group, but " +
+ redundancy.effectiveReadyCopies() + " ready copies is specified with " + groupCount + " groups");
}
- if (totalReadyCopies == 0) {
- System.err.println(getErrorMsgPrefix(clusterName) + "Warning. No ready copies configured. At least one is recommended.");
+ if (redundancy.effectiveReadyCopies() == 0) {
+ System.err.println(getErrorMsgPrefix() + "Warning. No ready copies configured. At least one is recommended.");
}
}
- static private String getErrorMsgPrefix(String clusterName) {
+ private String getErrorMsgPrefix() {
return "In indexed content cluster '" + clusterName + "' using hierarchic distribution: ";
}
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/Redundancy.java b/config-model/src/main/java/com/yahoo/vespa/model/content/Redundancy.java
index 0ff41019ae8..09a6f9b5c53 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/Redundancy.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/Redundancy.java
@@ -11,35 +11,55 @@ import com.yahoo.vespa.config.search.core.ProtonConfig;
*/
public class Redundancy implements StorDistributionConfig.Producer, ProtonConfig.Producer {
- // This numbers are all per group as wanted numbers.
private final int initialRedundancy ;
private final int finalRedundancy;
private final int readyCopies;
- private final int groups;
+ private int implicitGroups = 1;
+ private int explicitGroups = 1;
/** The total number of nodes available in this cluster (assigned when this becomes known) */
- private final int totalNodes;
+ private int totalNodes = 0;
- public Redundancy(int initialRedundancy, int finalRedundancy, int readyCopies, int groups, int totalNodes) {
+ public Redundancy(int initialRedundancy, int finalRedundancy, int readyCopies) {
this.initialRedundancy = initialRedundancy;
this.finalRedundancy = finalRedundancy;
this.readyCopies = readyCopies;
- this.groups = groups;
- this.totalNodes = totalNodes;
}
- public int finalRedundancy() { return effectiveFinalRedundancy()/groups; }
- public int readyCopies() { return effectiveReadyCopies()/groups; }
- public int groups() { return groups; }
+ /**
+ * Set the total number of nodes available in this cluster.
+ * This impacts the effective redundancy in the case where there are fewer nodes available than
+ * the requested redundancy.
+ */
+ public void setTotalNodes(int totalNodes) { this.totalNodes = totalNodes; }
- public int effectiveInitialRedundancy() { return Math.min(totalNodes, initialRedundancy * groups); }
- public int effectiveFinalRedundancy() { return Math.min(totalNodes, finalRedundancy * groups); }
- public int effectiveReadyCopies() { return Math.min(totalNodes, readyCopies * groups); }
+ /**
+ * Sets the number of groups resulting from implicit setup (groups attribute)
+ * in this cluster. With implicit groups the redundancy settings are taken to be
+ * <i>per group</i> and are multiplied by this number to get the effective <i>total</i>
+ * values returned in the config.
+ */
+ public void setImplicitGroups(int implicitGroups) { this.implicitGroups = implicitGroups; }
+
+ public void setExplicitGroups(int explicitGroups) { this.explicitGroups = explicitGroups; }
+
+ public int initialRedundancy() { return initialRedundancy; }
+ public int finalRedundancy() { return finalRedundancy; }
+ public int readyCopies() { return readyCopies; }
+ public int totalNodes() {
+ return totalNodes;
+ }
+
+ public int effectiveInitialRedundancy() { return Math.min(totalNodes, initialRedundancy * implicitGroups); }
+ public int effectiveFinalRedundancy() { return Math.min(totalNodes, finalRedundancy * implicitGroups); }
+ public int effectiveReadyCopies() { return Math.min(totalNodes, readyCopies * implicitGroups); }
public boolean isEffectivelyGloballyDistributed() {
return totalNodes == effectiveFinalRedundancy();
}
+ public int redundancyFromSearchNodePerspective() { return finalRedundancy/explicitGroups; }
+ public int searchableCopies() { return readyCopies/(explicitGroups*implicitGroups); }
@Override
public void getConfig(StorDistributionConfig.Builder builder) {
@@ -50,8 +70,8 @@ public class Redundancy implements StorDistributionConfig.Producer, ProtonConfig
@Override
public void getConfig(ProtonConfig.Builder builder) {
ProtonConfig.Distribution.Builder distBuilder = new ProtonConfig.Distribution.Builder();
- distBuilder.redundancy(finalRedundancy());
- distBuilder.searchablecopies(readyCopies());
+ distBuilder.redundancy(redundancyFromSearchNodePerspective());
+ distBuilder.searchablecopies(searchableCopies());
builder.distribution(distBuilder);
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/StorageGroup.java b/config-model/src/main/java/com/yahoo/vespa/model/content/StorageGroup.java
index 4d1252a2618..84132427427 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/StorageGroup.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/StorageGroup.java
@@ -15,7 +15,6 @@ import com.yahoo.vespa.model.builder.xml.dom.NodesSpecification;
import com.yahoo.vespa.model.builder.xml.dom.VespaDomBuilder;
import com.yahoo.vespa.model.container.Container;
import com.yahoo.vespa.model.content.cluster.ContentCluster;
-import com.yahoo.vespa.model.content.cluster.RedundancyBuilder;
import com.yahoo.vespa.model.content.engines.PersistenceEngine;
import java.util.ArrayList;
@@ -38,7 +37,7 @@ public class StorageGroup {
private final String index;
private Optional<String> partitions;
String name;
- private final boolean isHosted;
+ private final ContentCluster owner;
private final Optional<Long> mmapNoCoreLimit;
private final Optional<Boolean> coreOnOOM;
private final Optional<String> noVespaMalloc;
@@ -52,7 +51,7 @@ public class StorageGroup {
/**
* Creates a storage group
*
- * @param isHosted true if this is in a hosted setup
+ * @param owner the cluster this group belongs to
* @param name the name of this group
* @param index the distribution-key index og this group
* @param partitions the distribution strategy to use to distribute content to subgroups or empty
@@ -60,12 +59,12 @@ public class StorageGroup {
* (having nodes, not subgroups as children).
* @param useCpuSocketAffinity whether processes should be started with socket affinity
*/
- private StorageGroup(boolean isHosted, String name, String index, Optional<String> partitions,
+ private StorageGroup(ContentCluster owner, String name, String index, Optional<String> partitions,
boolean useCpuSocketAffinity, Optional<Long> mmapNoCoreLimit, Optional<Boolean> coreOnOOM,
Optional<String> noVespaMalloc, Optional<String> vespaMalloc,
Optional<String> vespaMallocDebug, Optional<String> vespaMallocDebugStackTrace)
{
- this.isHosted = isHosted;
+ this.owner = owner;
this.index = index;
this.name = name;
this.partitions = partitions;
@@ -77,8 +76,8 @@ public class StorageGroup {
this.vespaMallocDebug = vespaMallocDebug;
this.vespaMallocDebugStackTrace = vespaMallocDebugStackTrace;
}
- private StorageGroup(boolean isHosted, String name, String index) {
- this(isHosted, name, index, Optional.empty(), false, Optional.empty(),Optional.empty(), Optional.empty(),
+ private StorageGroup(ContentCluster owner, String name, String index) {
+ this(owner, name, index, Optional.empty(), false, Optional.empty(),Optional.empty(), Optional.empty(),
Optional.empty(), Optional.empty(), Optional.empty());
}
@@ -91,7 +90,7 @@ public class StorageGroup {
/** Returns the nodes of this, or an empty list of it is not a leaf group */
public List<StorageNode> getNodes() { return nodes; }
- public boolean isHosted() { return isHosted; }
+ public ContentCluster getOwner() { return owner; }
/** Returns the index of this group, or null if it is the root group */
public String getIndex() { return index; }
@@ -195,14 +194,16 @@ public class StorageGroup {
public static class Builder {
private final ModelElement clusterElement;
+ private final ContentCluster owner;
private final ConfigModelContext context;
- public Builder(ModelElement clusterElement, ConfigModelContext context) {
+ public Builder(ModelElement clusterElement, ContentCluster owner, ConfigModelContext context) {
this.clusterElement = clusterElement;
+ this.owner = owner;
this.context = context;
}
- public StorageGroup buildRootGroup(DeployState deployState, RedundancyBuilder redundancyBuilder, ContentCluster owner) {
+ public StorageGroup buildRootGroup(DeployState deployState) {
Optional<ModelElement> group = Optional.ofNullable(clusterElement.child("group"));
Optional<ModelElement> nodes = getNodes(clusterElement);
@@ -211,28 +212,12 @@ public class StorageGroup {
if (group.isPresent() && (group.get().stringAttribute("name") != null || group.get().integerAttribute("distribution-key") != null))
deployState.getDeployLogger().log(LogLevel.INFO, "'distribution-key' attribute on a content cluster's root group is ignored");
- GroupBuilder groupBuilder = collectGroup(owner.isHosted(), group, nodes, null, null);
- StorageGroup storageGroup = (owner.isHosted())
- ? groupBuilder.buildHosted(deployState, owner, Optional.empty())
- : groupBuilder.buildNonHosted(deployState, owner, Optional.empty());
- Redundancy redundancy = redundancyBuilder.build(owner.getName(), owner.isHosted(), storageGroup.subgroups.size(), storageGroup.getNumberOfLeafGroups(), storageGroup.countNodes());
- owner.setRedundancy(redundancy);
- if (storageGroup.partitions.isEmpty() && (redundancy.groups() > 1)) {
- storageGroup.partitions = Optional.of(computePartitions(redundancy.finalRedundancy(), redundancy.groups()));
+ GroupBuilder groupBuilder = collectGroup(group, nodes, null, null);
+ if (owner.isHostedVespa()) {
+ return groupBuilder.buildHosted(deployState, owner, Optional.empty());
+ } else {
+ return groupBuilder.buildNonHosted(deployState, owner, Optional.empty());
}
- return storageGroup;
- }
-
- /** This returns a partition string which specifies equal distribution between all groups */
- // TODO: Make a partitions object
- static private String computePartitions(int redundancyPerGroup, int numGroups) {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < numGroups - 1; ++i) {
- sb.append(redundancyPerGroup);
- sb.append("|");
- }
- sb.append("*");
- return sb.toString();
}
/**
@@ -277,6 +262,9 @@ public class StorageGroup {
if ( ! parent.isPresent() && subGroups.isEmpty() && nodeBuilders.isEmpty()) // no nodes or groups: create single node
storageGroup.nodes.add(buildSingleNode(deployState, owner));
+
+ if ( ! parent.isPresent())
+ owner.redundancy().setTotalNodes(storageGroup.countNodes());
return storageGroup;
}
@@ -309,11 +297,19 @@ public class StorageGroup {
if (hostGroups.size() > 1) {
if (parent.isPresent())
throw new IllegalArgumentException("Cannot specify groups using the groups attribute in nested content groups");
+ owner.redundancy().setTotalNodes(hostMapping.size());
+
+ // Switch redundancy settings to meaning "per group"
+ owner.redundancy().setImplicitGroups(hostGroups.size());
+
+ // Compute partitions expression
+ int redundancyPerGroup = (int)Math.floor(owner.redundancy().effectiveFinalRedundancy() / hostGroups.size());
+ storageGroup.partitions = Optional.of(computePartitions(redundancyPerGroup, hostGroups.size()));
// create subgroups as returned from allocation
for (Map.Entry<Optional<ClusterSpec.Group>, Map<HostResource, ClusterMembership>> hostGroup : hostGroups.entrySet()) {
String groupIndex = String.valueOf(hostGroup.getKey().get().index());
- StorageGroup subgroup = new StorageGroup(true, groupIndex, groupIndex);
+ StorageGroup subgroup = new StorageGroup(owner, groupIndex, groupIndex);
for (Map.Entry<HostResource, ClusterMembership> host : hostGroup.getValue().entrySet()) {
subgroup.nodes.add(createStorageNode(deployState, owner, host.getKey(), subgroup, host.getValue()));
}
@@ -327,10 +323,24 @@ public class StorageGroup {
for (GroupBuilder subGroup : subGroups) {
storageGroup.subgroups.add(subGroup.buildHosted(deployState, owner, Optional.of(this)));
}
+ if ( ! parent.isPresent())
+ owner.redundancy().setTotalNodes(storageGroup.countNodes());
}
return storageGroup;
}
+ /** This returns a partition string which specifies equal distribution between all groups */
+ // TODO: Make a partitions object
+ private String computePartitions(int redundancyPerGroup, int numGroups) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < numGroups - 1; ++i) {
+ sb.append(redundancyPerGroup);
+ sb.append("|");
+ }
+ sb.append("*");
+ return sb.toString();
+ }
+
/** Collect hosts per group */
private Map<Optional<ClusterSpec.Group>, Map<HostResource, ClusterMembership>> collectAllocatedSubgroups(Map<HostResource, ClusterMembership> hostMapping) {
Map<Optional<ClusterSpec.Group>, Map<HostResource, ClusterMembership>> hostsPerGroup = new LinkedHashMap<>();
@@ -377,9 +387,9 @@ public class StorageGroup {
* <li>Neither element is present: Create a single node.
* </ul>
*/
- private GroupBuilder collectGroup(boolean isHosted, Optional<ModelElement> groupElement, Optional<ModelElement> nodesElement, String name, String index) {
+ private GroupBuilder collectGroup(Optional<ModelElement> groupElement, Optional<ModelElement> nodesElement, String name, String index) {
StorageGroup group = new StorageGroup(
- isHosted, name, index,
+ owner, name, index,
childAsString(groupElement, "distribution.partitions"),
booleanAttributeOr(groupElement, VespaDomBuilder.CPU_SOCKET_AFFINITY_ATTRIB_NAME, false),
childAsLong(groupElement, VespaDomBuilder.MMAP_NOCORE_LIMIT),
@@ -389,7 +399,7 @@ public class StorageGroup {
childAsString(groupElement, VespaDomBuilder.VESPAMALLOC_DEBUG),
childAsString(groupElement, VespaDomBuilder.VESPAMALLOC_DEBUG_STACKTRACE));
- List<GroupBuilder> subGroups = groupElement.isPresent() ? collectSubGroups(isHosted, group, groupElement.get()) : Collections.emptyList();
+ List<GroupBuilder> subGroups = groupElement.isPresent() ? collectSubGroups(group, groupElement.get()) : Collections.emptyList();
List<XmlNodeBuilder> explicitNodes = new ArrayList<>();
explicitNodes.addAll(collectExplicitNodes(groupElement));
@@ -440,7 +450,7 @@ public class StorageGroup {
return nodes;
}
- private List<GroupBuilder> collectSubGroups(boolean isHosted, StorageGroup parentGroup, ModelElement parentGroupElement) {
+ private List<GroupBuilder> collectSubGroups(StorageGroup parentGroup, ModelElement parentGroupElement) {
List<ModelElement> subGroupElements = parentGroupElement.subElements("group");
if (subGroupElements.size() > 1 && ! parentGroup.getPartitions().isPresent())
throw new IllegalArgumentException("'distribution' attribute is required with multiple subgroups");
@@ -451,7 +461,7 @@ public class StorageGroup {
indexPrefix = parentGroup.index + ".";
}
for (ModelElement g : subGroupElements) {
- subGroups.add(collectGroup(isHosted, Optional.of(g), Optional.ofNullable(g.child("nodes")), g.stringAttribute("name"),
+ subGroups.add(collectGroup(Optional.of(g), Optional.ofNullable(g.child("nodes")), g.stringAttribute("name"),
indexPrefix + g.integerAttribute("distribution-key")));
}
return subGroups;
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 48779657162..833afb67f58 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
@@ -80,9 +80,9 @@ public class ContentCluster extends AbstractConfigProducer implements
MessagetyperouteselectorpolicyConfig.Producer,
BucketspacesConfig.Producer {
- private final String documentSelection;
+ private String documentSelection;
private ContentSearchCluster search;
- private final boolean isHosted;
+ private final boolean isHostedVespa;
private final Map<String, NewDocumentType> documentDefinitions;
private final Set<NewDocumentType> globallyDistributedDocuments;
private com.yahoo.vespa.model.content.StorageGroup rootGroup;
@@ -91,9 +91,9 @@ public class ContentCluster extends AbstractConfigProducer implements
private Redundancy redundancy;
private ClusterControllerConfig clusterControllerConfig;
private PersistenceEngine.PersistenceFactory persistenceFactory;
- private final String clusterName;
+ private String clusterName;
private Integer maxNodesPerMerge;
- private final Zone zone;
+ private Zone zone;
/**
* If multitenant or a cluster controller was explicitly configured in this cluster:
@@ -124,20 +124,21 @@ public class ContentCluster extends AbstractConfigProducer implements
new SearchDefinitionBuilder().build(deployState.getDocumentModel().getDocumentManager(), documentsElement);
String routingSelection = new DocumentSelectionBuilder().build(documentsElement);
- RedundancyBuilder redundancyBuilder = new RedundancyBuilder(contentElement);
+ Redundancy redundancy = new RedundancyBuilder().build(contentElement);
Set<NewDocumentType> globallyDistributedDocuments = new GlobalDistributionBuilder(documentDefinitions).build(documentsElement);
ContentCluster c = new ContentCluster(context.getParentProducer(), getClusterName(contentElement), documentDefinitions,
- globallyDistributedDocuments, routingSelection,
+ globallyDistributedDocuments, routingSelection, redundancy,
deployState.zone(), deployState.isHosted());
c.clusterControllerConfig = new ClusterControllerConfig.Builder(getClusterName(contentElement), contentElement).build(deployState, c, contentElement.getXml());
c.search = new ContentSearchCluster.Builder(documentDefinitions, globallyDistributedDocuments).build(deployState, c, contentElement.getXml());
c.persistenceFactory = new EngineFactoryBuilder().build(contentElement, c);
c.storageNodes = new StorageCluster.Builder().build(deployState, c, w3cContentElement);
c.distributorNodes = new DistributorCluster.Builder(c).build(deployState, c, w3cContentElement);
- c.rootGroup = new StorageGroup.Builder(contentElement, context).buildRootGroup(deployState, redundancyBuilder, c);
+ c.rootGroup = new StorageGroup.Builder(contentElement, c, context).buildRootGroup(deployState);
validateThatGroupSiblingsAreUnique(c.clusterName, c.rootGroup);
- c.search.handleRedundancy(c.redundancy);
+ redundancy.setExplicitGroups(c.getRootGroup().getNumberOfLeafGroups());
+ c.search.handleRedundancy(redundancy);
IndexedSearchCluster index = c.search.getIndexed();
if (index != null) {
@@ -491,13 +492,14 @@ public class ContentCluster extends AbstractConfigProducer implements
private ContentCluster(AbstractConfigProducer parent, String clusterName,
Map<String, NewDocumentType> documentDefinitions,
Set<NewDocumentType> globallyDistributedDocuments,
- String routingSelection, Zone zone, boolean isHosted) {
+ String routingSelection, Redundancy redundancy, Zone zone, boolean isHostedVespa) {
super(parent, clusterName);
- this.isHosted = isHosted;
+ this.isHostedVespa = isHostedVespa;
this.clusterName = clusterName;
this.documentDefinitions = documentDefinitions;
this.globallyDistributedDocuments = globallyDistributedDocuments;
this.documentSelection = routingSelection;
+ this.redundancy = redundancy;
this.zone = zone;
}
@@ -551,10 +553,6 @@ public class ContentCluster extends AbstractConfigProducer implements
public final ContentSearchCluster getSearch() { return search; }
public Redundancy redundancy() { return redundancy; }
- public ContentCluster setRedundancy(Redundancy redundancy) {
- this.redundancy = redundancy;
- return this;
- }
@Override
public void getConfig(MessagetyperouteselectorpolicyConfig.Builder builder) {
@@ -641,14 +639,14 @@ public class ContentCluster extends AbstractConfigProducer implements
}
}
- public boolean isHosted() {
- return isHosted;
+ public boolean isHostedVespa() {
+ return isHostedVespa;
}
@Override
public void validate() throws Exception {
super.validate();
- if (search.usesHierarchicDistribution() && !isHosted) {
+ if (search.usesHierarchicDistribution() && ! isHostedVespa) {
// validate manually configured groups
new IndexedHierarchicDistributionValidator(search.getClusterName(), rootGroup, redundancy, search.getIndexed().getTuning().dispatch.policy).validate();
if (search.getIndexed().useMultilevelDispatchSetup()) {
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/RedundancyBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/RedundancyBuilder.java
index 3b6ba6a6b85..fe73fcc904b 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/RedundancyBuilder.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/RedundancyBuilder.java
@@ -2,22 +2,22 @@
package com.yahoo.vespa.model.content.cluster;
import com.yahoo.vespa.model.builder.xml.dom.ModelElement;
-import com.yahoo.vespa.model.content.IndexedHierarchicDistributionValidator;
import com.yahoo.vespa.model.content.Redundancy;
/**
* Builds redundancy config for a content cluster.
*/
public class RedundancyBuilder {
- Integer initialRedundancy = 2;
- Integer finalRedundancy = 3;
- Integer readyCopies = 2;
- RedundancyBuilder(ModelElement clusterXml) {
+ Redundancy build(ModelElement clusterXml) {
+ Integer initialRedundancy = 2;
+ Integer finalRedundancy = 3;
+ Integer readyCopies = 2;
+
ModelElement redundancyElement = clusterXml.child("redundancy");
if (redundancyElement != null) {
initialRedundancy = redundancyElement.integerAttribute("reply-after");
- finalRedundancy = (int) redundancyElement.asLong();
+ finalRedundancy = (int)redundancyElement.asLong();
if (initialRedundancy == null) {
initialRedundancy = finalRedundancy;
@@ -35,16 +35,8 @@ public class RedundancyBuilder {
throw new IllegalArgumentException("Number of searchable copies can not be higher than final redundancy");
}
}
- }
- public Redundancy build(String clusterName, boolean isHosted, int subGroups, int leafGroups, int totalNodes) {
- if (isHosted) {
- return new Redundancy(initialRedundancy, finalRedundancy, readyCopies, leafGroups, totalNodes);
- } else {
- subGroups = Math.max(1, subGroups);
- IndexedHierarchicDistributionValidator.validateThatLeafGroupsCountIsAFactorOfRedundancy(clusterName, finalRedundancy, subGroups);
- IndexedHierarchicDistributionValidator.validateThatReadyCopiesIsCompatibleWithRedundancy(clusterName, finalRedundancy, readyCopies, subGroups);
- return new Redundancy(initialRedundancy/leafGroups, finalRedundancy/leafGroups, readyCopies/leafGroups, leafGroups, totalNodes);
- }
+
+ return new Redundancy(initialRedundancy, finalRedundancy, readyCopies);
}
}
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/content/DistributorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/content/DistributorTest.java
index f36ef6c3ba3..8ae68468374 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/content/DistributorTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/content/DistributorTest.java
@@ -113,7 +113,6 @@ public class DistributorTest {
assertEquals(true, conf.inlinebucketsplitting());
cluster = parseCluster("<cluster id=\"storage\">\n" +
- " <redundancy>2</redundancy>" +
" <documents/>" +
" <tuning>" +
" <distribution type=\"legacy\"/>" +
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/content/RedundancyTest.java b/config-model/src/test/java/com/yahoo/vespa/model/content/RedundancyTest.java
index eef48120da8..3b2a741a177 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/content/RedundancyTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/content/RedundancyTest.java
@@ -22,7 +22,9 @@ public class RedundancyTest {
}
private static Redundancy createRedundancy(int redundancy, int implicitGroups, int totalNodes) {
- Redundancy r = new Redundancy(1, redundancy, 1, implicitGroups, totalNodes);
+ Redundancy r = new Redundancy(1, redundancy, 1);
+ r.setImplicitGroups(implicitGroups);
+ r.setTotalNodes(totalNodes);
return r;
}
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/content/StorageClusterTest.java b/config-model/src/test/java/com/yahoo/vespa/model/content/StorageClusterTest.java
index 21c384dfc69..bbb101dbb08 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/content/StorageClusterTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/content/StorageClusterTest.java
@@ -305,8 +305,7 @@ public class StorageClusterTest {
public void requireThatGroupNamesMustBeUniqueAmongstSiblings() {
String xml =
"<cluster id=\"storage\">\n" +
- " <redundancy>2</redundancy>" +
- " <documents/>\n" +
+ "<documents/>\n" +
" <group>\n" +
" <distribution partitions=\"*\"/>\n" +
" <group distribution-key=\"0\" name=\"bar\">\n" +
@@ -331,7 +330,6 @@ public class StorageClusterTest {
public void requireThatGroupNamesCanBeDuplicatedAcrossLevels() {
String xml =
"<cluster id=\"storage\">\n" +
- " <redundancy>2</redundancy>" +
"<documents/>\n" +
" <group>\n" +
" <distribution partitions=\"*\"/>\n" +
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/content/StorageGroupTest.java b/config-model/src/test/java/com/yahoo/vespa/model/content/StorageGroupTest.java
index cb457cabf6c..c1789a05f3c 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/content/StorageGroupTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/content/StorageGroupTest.java
@@ -80,7 +80,6 @@ public class StorageGroupTest {
StorDistributionConfig.Builder builder = new StorDistributionConfig.Builder();
parse(
"<content version=\"1.0\" id=\"storage\">\n" +
- " <redundancy>4</redundancy>" +
" <documents/>" +
" <group>\n" +
" <distribution partitions=\"1|*\"/>\n" +
@@ -135,7 +134,6 @@ public class StorageGroupTest {
StorDistributionConfig.Builder builder = new StorDistributionConfig.Builder();
parse(
"<content version=\"1.0\" id=\"storage\">\n" +
- " <redundancy>2</redundancy>" +
" <documents/>" +
" <group>\n" +
" <distribution partitions=\"1|*\"/>\n" +
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/content/cluster/ClusterTest.java b/config-model/src/test/java/com/yahoo/vespa/model/content/cluster/ClusterTest.java
index 4fadea74feb..e4decbc9a10 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/content/cluster/ClusterTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/content/cluster/ClusterTest.java
@@ -124,8 +124,6 @@ public class ClusterTest {
" </engine>",
" <group>",
" <node hostalias='my_host' distribution-key='0' />",
- " <node hostalias='my_host' distribution-key='1' />",
- " <node hostalias='my_host' distribution-key='2' />",
" </group>",
contentSearchXml,
" </content>",