diff options
author | Arne Juul <arnej@yahooinc.com> | 2023-02-13 10:28:48 +0000 |
---|---|---|
committer | Arne Juul <arnej@yahooinc.com> | 2023-02-13 14:52:35 +0000 |
commit | 4426f0ee45846a905d2fe47bb0b998014d86ad39 (patch) | |
tree | 303e32cfd33ea36aab6fed03b56c1186cef5b388 /config-model/src/main/java/com/yahoo/config/model/producer | |
parent | 3da5e19509fcc10d4cdbcc49747cacc7cac2ae2e (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.java | 2 | ||||
-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.java | 199 | ||||
-rw-r--r-- | config-model/src/main/java/com/yahoo/config/model/producer/UserConfigRepo.java | 2 |
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<>(); |