summaryrefslogtreecommitdiffstats
path: root/config-model/src/main/java/com/yahoo/config/model/producer
diff options
context:
space:
mode:
authorArne Juul <arnej@yahooinc.com>2023-02-13 10:28:48 +0000
committerArne Juul <arnej@yahooinc.com>2023-02-13 14:52:35 +0000
commit4426f0ee45846a905d2fe47bb0b998014d86ad39 (patch)
tree303e32cfd33ea36aab6fed03b56c1186cef5b388 /config-model/src/main/java/com/yahoo/config/model/producer
parent3da5e19509fcc10d4cdbcc49747cacc7cac2ae2e (diff)
split AbstractConfigProducer
Diffstat (limited to 'config-model/src/main/java/com/yahoo/config/model/producer')
-rw-r--r--config-model/src/main/java/com/yahoo/config/model/producer/AbstractConfigProducerRoot.java2
-rw-r--r--config-model/src/main/java/com/yahoo/config/model/producer/AnyConfigProducer.java (renamed from config-model/src/main/java/com/yahoo/config/model/producer/AbstractConfigProducer.java)169
-rw-r--r--config-model/src/main/java/com/yahoo/config/model/producer/TreeConfigProducer.java199
-rw-r--r--config-model/src/main/java/com/yahoo/config/model/producer/UserConfigRepo.java2
4 files changed, 232 insertions, 140 deletions
diff --git a/config-model/src/main/java/com/yahoo/config/model/producer/AbstractConfigProducerRoot.java b/config-model/src/main/java/com/yahoo/config/model/producer/AbstractConfigProducerRoot.java
index d6c03a0f668..6dd94028e9c 100644
--- a/config-model/src/main/java/com/yahoo/config/model/producer/AbstractConfigProducerRoot.java
+++ b/config-model/src/main/java/com/yahoo/config/model/producer/AbstractConfigProducerRoot.java
@@ -15,7 +15,7 @@ import java.util.Optional;
*
* @author Tony Vaagenes
*/
-public abstract class AbstractConfigProducerRoot extends AbstractConfigProducer<AbstractConfigProducer<?>>
+public abstract class AbstractConfigProducerRoot extends TreeConfigProducer<TreeConfigProducer<?>>
implements ConfigProducerRoot {
/** The ConfigProducers contained in this model indexed by config id */
diff --git a/config-model/src/main/java/com/yahoo/config/model/producer/AbstractConfigProducer.java b/config-model/src/main/java/com/yahoo/config/model/producer/AnyConfigProducer.java
index b86230c97e6..2cfe1590ad9 100644
--- a/config-model/src/main/java/com/yahoo/config/model/producer/AbstractConfigProducer.java
+++ b/config-model/src/main/java/com/yahoo/config/model/producer/AnyConfigProducer.java
@@ -34,34 +34,32 @@ import java.util.logging.Logger;
*
* @author gjoranv
*/
-public abstract class AbstractConfigProducer<CHILD extends AbstractConfigProducer<?>>
+public abstract class AnyConfigProducer
implements ConfigProducer, ConfigInstance.Producer, Serializable {
private static final long serialVersionUID = 1L;
- public static final Logger log = Logger.getLogger(AbstractConfigProducer.class.getPackage().toString());
+ public static final Logger log = Logger.getLogger(AnyConfigProducer.class.getPackage().toString());
private final String subId;
private String configId = null;
private final List<Service> descendantServices = new ArrayList<>();
- private AbstractConfigProducer parent = null;
+ private TreeConfigProducer parent = null;
private UserConfigRepo userConfigs = new UserConfigRepo();
- private final FreezableMap<String, CHILD> childrenBySubId = new FreezableMap<>(LinkedHashMap.class);
-
protected static boolean stateIsHosted(DeployState deployState) {
return (deployState != null) && deployState.isHosted();
}
/**
- * Creates a new AbstractConfigProducer with the given parent and subId.
+ * Creates a new AnyConfigProducer with the given parent and subId.
* This constructor will add the resulting producer to the children of parent.
*
* @param parent the parent of this ConfigProducer
* @param subId the fragment of the config id for the producer
*/
- public AbstractConfigProducer(AbstractConfigProducer parent, String subId) {
+ public AnyConfigProducer(TreeConfigProducer parent, String subId) {
this(subId);
if (parent != null) {
parent.addChild(this);
@@ -74,7 +72,7 @@ public abstract class AbstractConfigProducer<CHILD extends AbstractConfigProduce
parent.removeChild(this);
}
- protected final void setParent(AbstractConfigProducer<?> parent) {
+ protected final void setParent(TreeConfigProducer parent) {
this.parent = parent;
computeConfigId();
}
@@ -83,11 +81,11 @@ public abstract class AbstractConfigProducer<CHILD extends AbstractConfigProduce
/**
* Create an config producer with a configId only. Used e.g. to create root nodes, and producers
- * that are given children after construction using {@link #addChild(AbstractConfigProducer)}.
+ * that are given parents after construction using {@link TreeConfigProducer#addChild(AnyConfigProducer)}.
*
* @param subId The sub configId. Note that this can be prefixed when calling addChild with this producer as arg.
*/
- public AbstractConfigProducer(String subId) {
+ public AnyConfigProducer(String subId) {
if (subId.indexOf('/') != -1) {
throw new IllegalArgumentException("A subId might not contain '/' : '" + subId + "'");
}
@@ -95,49 +93,9 @@ public abstract class AbstractConfigProducer<CHILD extends AbstractConfigProduce
}
/**
- * Adds a child to this config producer.
- *
- * @param child the child config producer to add
- */
- protected void addChild(CHILD child) {
- if (child == null) {
- throw new IllegalArgumentException("Trying to add null child for: " + this);
- }
- if (child instanceof AbstractConfigProducerRoot) {
- throw new IllegalArgumentException("Child cannot be a root node: " + child);
- }
-
- child.setParent(this);
- if (childrenBySubId.get(child.getSubId()) != null) {
- throw new IllegalArgumentException("Multiple services/instances of the id '" + child.getSubId() + "' under the service/instance " +
- errorMsgClassName() + " '" + subId + "'. (This is commonly caused by service/node index " +
- "collisions in the config.)." +
- "\nExisting instance: " + childrenBySubId.get(child.getSubId()) +
- "\nAttempted to add: " + child);
- }
- childrenBySubId.put(child.getSubId(), child);
-
- if (child instanceof Service) {
- addDescendantService((Service)child);
- }
- }
-
- public void removeChild(CHILD child) {
- if (child.getParent() != this)
- throw new IllegalArgumentException("Could not remove " + child + ": Expected its parent to be " +
- this + ", but was " + child.getParent());
-
- if (child instanceof Service)
- descendantServices.remove(child);
-
- childrenBySubId.remove(child.getSubId());
- child.setParent(null);
- }
-
- /**
* Helper to provide an error message on collisions of sub ids (ignore SimpleConfigProducer, use the parent in that case)
*/
- private String errorMsgClassName() {
+ protected String errorMsgClassName() {
if (getClass().equals(SimpleConfigProducer.class)) return parent.getClass().getSimpleName();
return getClass().getSimpleName();
}
@@ -163,6 +121,10 @@ public abstract class AbstractConfigProducer<CHILD extends AbstractConfigProduce
return configId;
}
+ protected final String currentConfigId() {
+ return configId;
+ }
+
/**
* Sets the config id for this producer. Will also add this
* service to the root node, so the new config id will be picked
@@ -176,30 +138,6 @@ public abstract class AbstractConfigProducer<CHILD extends AbstractConfigProduce
getVespa().addDescendant(this);
}
- /** Returns this ConfigProducer's children (only 1st level) */
- public Map<String, CHILD> getChildren() { return Collections.unmodifiableMap(childrenBySubId); }
-
- @Beta
- public <J extends AbstractConfigProducer<?>> List<J> getChildrenByTypeRecursive(Class<J> type) {
- List<J> validChildren = new ArrayList<>();
-
- if (this.getClass().equals(type)) {
- validChildren.add(type.cast(this));
- }
-
- Map<String, ? extends AbstractConfigProducer<?>> children = this.getChildren();
- for (AbstractConfigProducer<?> child : children.values()) {
- validChildren.addAll(child.getChildrenByTypeRecursive(type));
- }
-
- return Collections.unmodifiableList(validChildren);
- }
-
- /** Returns a list of all the children of this who are instances of Service */
- public List<Service> getDescendantServices() { return Collections.unmodifiableList(descendantServices); }
-
- protected void addDescendantService(Service s) { descendantServices.add(s); }
-
@Override
public final boolean cascadeConfig(ConfigInstance.Builder builder) {
boolean found = false;
@@ -271,7 +209,11 @@ public abstract class AbstractConfigProducer<CHILD extends AbstractConfigProduce
*/
private ApplicationConfigProducerRoot getVespa() {
if (isRoot()) return null;
- return isVespa() ? (ApplicationConfigProducerRoot)this : parent.getVespa();
+ if (isVespa()) {
+ return (ApplicationConfigProducerRoot)this;
+ } else {
+ return getParent().getVespa();
+ }
}
private boolean isRoot() {
@@ -279,19 +221,10 @@ public abstract class AbstractConfigProducer<CHILD extends AbstractConfigProduce
}
private boolean isVespa() {
- return ((this instanceof ApplicationConfigProducerRoot) && parent.isRoot());
+ return ((this instanceof ApplicationConfigProducerRoot) && getParent().isRoot());
}
- public AbstractConfigProducer getParent() { return parent; }
-
- public void dump(PrintStream out) {
- for (ConfigProducer c : getChildren().values()) {
- out.println("id: " + c.getConfigId());
- if (c.getChildren().size() > 0) {
- c.dump(out);
- }
- }
- }
+ public AnyConfigProducer getParent() { return parent; }
void setupConfigId(String parentConfigId) {
if (this instanceof AbstractConfigProducerRoot) {
@@ -301,15 +234,6 @@ public abstract class AbstractConfigProducer<CHILD extends AbstractConfigProduce
addConfigId(configId);
}
computeConfigId();
- setupChildConfigIds(getConfigIdPrefix());
- }
-
- private String getConfigIdPrefix() {
- if (this instanceof AbstractConfigProducerRoot || this instanceof ApplicationConfigProducerRoot) {
- return "";
- }
- if (configId == null) return null;
- return configId + "/";
}
private void computeConfigId() {
@@ -328,7 +252,7 @@ public abstract class AbstractConfigProducer<CHILD extends AbstractConfigProduce
}
}
- private static ClassLoader findInheritedClassLoader(Class clazz, String producerName) {
+ protected static ClassLoader findInheritedClassLoader(Class clazz, String producerName) {
Class<?>[] interfazes = clazz.getInterfaces();
for (Class interfaze : interfazes) {
if (producerName.equals(interfaze.getName())) {
@@ -341,53 +265,13 @@ public abstract class AbstractConfigProducer<CHILD extends AbstractConfigProduce
}
protected ClassLoader getConfigClassLoader(String producerName) {
- ClassLoader classLoader = findInheritedClassLoader(getClass(), producerName);
- if (classLoader != null)
- return classLoader;
-
- // TODO: Make logic correct, so that the deepest child will be the one winning.
- for (AbstractConfigProducer child : childrenBySubId.values()) {
- ClassLoader loader = child.getConfigClassLoader(producerName);
- if (loader != null) {
- return loader;
- }
- }
- return null;
- }
-
- private void setupChildConfigIds(String currentConfigId) {
- for (AbstractConfigProducer child : childrenBySubId.values()) {
- child.setupConfigId(currentConfigId);
- }
- }
-
- void aggregateDescendantServices() {
- for (AbstractConfigProducer child : childrenBySubId.values()) {
- child.aggregateDescendantServices();
- descendantServices.addAll(child.descendantServices);
- }
- }
-
- void freeze() {
- childrenBySubId.freeze();
- for (AbstractConfigProducer child : childrenBySubId.values()) {
- child.freeze();
- }
+ return findInheritedClassLoader(getClass(), producerName);
}
public void mergeUserConfigs(UserConfigRepo newRepo) {
userConfigs.merge(newRepo);
}
- @Override
- public void validate() throws Exception {
- assert (childrenBySubId.isFrozen());
-
- for (AbstractConfigProducer<?> child : childrenBySubId.values()) {
- child.validate();
- }
- }
-
// TODO: Make producers depend on AdminModel instead
/** Returns a monitoring service if configured, null otherwise */
protected Monitoring getMonitoringService() {
@@ -401,4 +285,13 @@ public abstract class AbstractConfigProducer<CHILD extends AbstractConfigProduce
}
return null;
}
+
+ // NOPs for all config producers without children; overridden in TreeConfigProducer
+ void aggregateDescendantServices() { }
+ public List<Service> getDescendantServices() { return List.of(); }
+ <J extends AnyConfigProducer> List<J> getChildrenByTypeRecursive(Class<J> type) { return List.of(); }
+ void freeze() { }
+ @Override
+ public void validate() throws Exception { }
+
}
diff --git a/config-model/src/main/java/com/yahoo/config/model/producer/TreeConfigProducer.java b/config-model/src/main/java/com/yahoo/config/model/producer/TreeConfigProducer.java
new file mode 100644
index 00000000000..6b632572250
--- /dev/null
+++ b/config-model/src/main/java/com/yahoo/config/model/producer/TreeConfigProducer.java
@@ -0,0 +1,199 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.config.model.producer;
+
+import com.yahoo.api.annotations.Beta;
+import com.yahoo.config.ConfigInstance;
+import com.yahoo.config.model.ApplicationConfigProducerRoot;
+import com.yahoo.config.model.deploy.DeployState;
+import com.yahoo.config.subscription.ConfigInstanceUtil;
+import com.yahoo.vespa.config.ConfigDefinitionKey;
+import com.yahoo.vespa.config.ConfigPayload;
+import com.yahoo.vespa.config.ConfigPayloadBuilder;
+import com.yahoo.vespa.config.ConfigTransformer;
+import com.yahoo.vespa.config.GenericConfig;
+import com.yahoo.vespa.model.ConfigProducer;
+import com.yahoo.vespa.model.HostSystem;
+import com.yahoo.vespa.model.Service;
+import com.yahoo.vespa.model.SimpleConfigProducer;
+import com.yahoo.vespa.model.admin.Admin;
+import com.yahoo.vespa.model.admin.monitoring.Monitoring;
+import com.yahoo.vespa.model.utils.FreezableMap;
+import java.io.PrintStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Superclass for all config producers with children.
+ * Config producers constructs and returns config instances on request.
+ *
+ * @author gjoranv
+ */
+public abstract class TreeConfigProducer<CHILD extends AnyConfigProducer>
+ extends AnyConfigProducer
+{
+ private static final long serialVersionUID = 1L;
+ private final List<Service> descendantServices = new ArrayList<>();
+ private final FreezableMap<String, CHILD> childrenBySubId = new FreezableMap<>(LinkedHashMap.class);
+
+ /**
+ * Creates a new TreeConfigProducer with the given parent and subId.
+ * This constructor will add the resulting producer to the children of parent.
+ *
+ * @param parent the parent of this ConfigProducer
+ * @param subId the fragment of the config id for the producer
+ */
+ public TreeConfigProducer(TreeConfigProducer parent, String subId) {
+ super(parent, subId);
+ }
+
+ /**
+ * Create an config producer with a configId only. Used e.g. to create root nodes, and producers
+ * that are given children after construction using {@link #addChild(AnyConfigProducer)}.
+ *
+ * @param subId The sub configId. Note that this can be prefixed when calling addChild with this producer as arg.
+ */
+ public TreeConfigProducer(String subId) {
+ super(subId);
+ }
+
+ /**
+ * Adds a child to this config producer.
+ *
+ * @param child the child config producer to add
+ */
+ protected void addChild(CHILD child) {
+ if (child == null) {
+ throw new IllegalArgumentException("Trying to add null child for: " + this);
+ }
+ if (child instanceof AbstractConfigProducerRoot) {
+ throw new IllegalArgumentException("Child cannot be a root node: " + child);
+ }
+
+ child.setParent(this);
+ if (childrenBySubId.get(child.getSubId()) != null) {
+ throw new IllegalArgumentException("Multiple services/instances of the id '" + child.getSubId() + "' under the service/instance " +
+ errorMsgClassName() + " '" + getSubId() + "'. (This is commonly caused by service/node index " +
+ "collisions in the config.)." +
+ "\nExisting instance: " + childrenBySubId.get(child.getSubId()) +
+ "\nAttempted to add: " + child);
+ }
+ childrenBySubId.put(child.getSubId(), child);
+
+ if (child instanceof Service) {
+ addDescendantService((Service)child);
+ }
+ }
+
+ public void removeChild(CHILD child) {
+ if (child.getParent() != this)
+ throw new IllegalArgumentException("Could not remove " + child + ": Expected its parent to be " +
+ this + ", but was " + child.getParent());
+
+ if (child instanceof Service)
+ descendantServices.remove(child);
+
+ childrenBySubId.remove(child.getSubId());
+ child.setParent(null);
+ }
+
+ /** Returns this ConfigProducer's children (only 1st level) */
+ public Map<String, CHILD> getChildren() { return Collections.unmodifiableMap(childrenBySubId); }
+
+ @Beta
+ public <J extends AnyConfigProducer> List<J> getChildrenByTypeRecursive(Class<J> type) {
+ List<J> validChildren = new ArrayList<>();
+
+ if (this.getClass().equals(type)) {
+ validChildren.add(type.cast(this));
+ }
+
+ Map<String, CHILD> children = this.getChildren();
+ for (CHILD child : children.values()) {
+ validChildren.addAll(child.getChildrenByTypeRecursive(type));
+ }
+
+ return Collections.unmodifiableList(validChildren);
+ }
+
+ /** Returns a list of all the children of this who are instances of Service */
+ public List<Service> getDescendantServices() { return Collections.unmodifiableList(descendantServices); }
+
+ protected void addDescendantService(Service s) { descendantServices.add(s); }
+
+ public void dump(PrintStream out) {
+ for (ConfigProducer c : getChildren().values()) {
+ out.println("id: " + c.getConfigId());
+ if (c.getChildren().size() > 0) {
+ c.dump(out);
+ }
+ }
+ }
+
+ void setupConfigId(String parentConfigId) {
+ super.setupConfigId(parentConfigId);
+ setupChildConfigIds(getConfigIdPrefix());
+ }
+
+ String getConfigIdPrefix() {
+ if (this instanceof AbstractConfigProducerRoot || this instanceof ApplicationConfigProducerRoot) {
+ return "";
+ }
+ if (currentConfigId() == null) {
+ return null;
+ }
+ return getConfigId() + "/";
+ }
+
+ @Override
+ protected ClassLoader getConfigClassLoader(String producerName) {
+ ClassLoader classLoader = findInheritedClassLoader(getClass(), producerName);
+ if (classLoader != null)
+ return classLoader;
+
+ // TODO: Make logic correct, so that the deepest child will be the one winning.
+ for (AnyConfigProducer child : childrenBySubId.values()) {
+ ClassLoader loader = child.getConfigClassLoader(producerName);
+ if (loader != null) {
+ return loader;
+ }
+ }
+ return null;
+ }
+
+ private void setupChildConfigIds(String currentConfigId) {
+ for (AnyConfigProducer child : childrenBySubId.values()) {
+ child.setupConfigId(currentConfigId);
+ }
+ }
+
+ @Override
+ void aggregateDescendantServices() {
+ for (CHILD child : childrenBySubId.values()) {
+ child.aggregateDescendantServices();
+ descendantServices.addAll(child.getDescendantServices());
+ }
+ }
+
+ @Override
+ void freeze() {
+ childrenBySubId.freeze();
+ for (CHILD child : childrenBySubId.values()) {
+ child.freeze();
+ }
+ }
+
+ @Override
+ public void validate() throws Exception {
+ assert (childrenBySubId.isFrozen());
+ for (CHILD child : childrenBySubId.values()) {
+ child.validate();
+ }
+ }
+
+}
diff --git a/config-model/src/main/java/com/yahoo/config/model/producer/UserConfigRepo.java b/config-model/src/main/java/com/yahoo/config/model/producer/UserConfigRepo.java
index afa3e2de85f..3d7eafe658f 100644
--- a/config-model/src/main/java/com/yahoo/config/model/producer/UserConfigRepo.java
+++ b/config-model/src/main/java/com/yahoo/config/model/producer/UserConfigRepo.java
@@ -28,7 +28,7 @@ public class UserConfigRepo {
}
/**
- * Must copy the builder, because the merge method on {@link AbstractConfigProducer} might override the row's builders otherwise
+ * Must copy the builder, because the merge method on {@link TreeConfigProducer} might override the row's builders otherwise
*/
private Map<ConfigDefinitionKey, ConfigPayloadBuilder> copyBuilders(Map<ConfigDefinitionKey, ConfigPayloadBuilder> source) {
Map<ConfigDefinitionKey, ConfigPayloadBuilder> ret = new LinkedHashMap<>();