aboutsummaryrefslogtreecommitdiffstats
path: root/config-lib
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@gmail.com>2020-11-30 21:24:44 +0100
committerJon Bratseth <bratseth@gmail.com>2020-11-30 21:24:44 +0100
commit3d56e0f71adf16f8842f157c5f47c2c952377526 (patch)
treeafcec984bb33e81b83cd84aa71e5907e53e5c4f0 /config-lib
parent0f2e5b7dba8f7009d227722b9491cc800d4f371b (diff)
Revert "Merge pull request #15549 from vespa-engine/revert-15543-bratseth/apply-on-restart-take-7"
This reverts commit 0f2e5b7dba8f7009d227722b9491cc800d4f371b, reversing changes made to 1d5e07a044bff2aef764cfee0de10802c376e4b7.
Diffstat (limited to 'config-lib')
-rw-r--r--config-lib/abi-spec.json6
-rw-r--r--config-lib/pom.xml6
-rw-r--r--config-lib/src/main/java/com/yahoo/config/ConfigBuilder.java1
-rw-r--r--config-lib/src/main/java/com/yahoo/config/ConfigInstance.java107
-rw-r--r--config-lib/src/main/java/com/yahoo/config/Node.java4
5 files changed, 120 insertions, 4 deletions
diff --git a/config-lib/abi-spec.json b/config-lib/abi-spec.json
index fa352d8f6bd..a9c57c2d1a2 100644
--- a/config-lib/abi-spec.json
+++ b/config-lib/abi-spec.json
@@ -73,7 +73,11 @@
"public abstract boolean dispatchGetConfig(com.yahoo.config.ConfigInstance$Producer)",
"public abstract java.lang.String getDefName()",
"public abstract java.lang.String getDefNamespace()",
- "public abstract java.lang.String getDefMd5()"
+ "public abstract java.lang.String getDefMd5()",
+ "public boolean getApplyOnRestart()",
+ "public void setApplyOnRestart(boolean)",
+ "public com.yahoo.config.ConfigInstance buildInstance(com.yahoo.config.codegen.InnerCNode)",
+ "public static void applyDef(com.yahoo.config.ConfigBuilder, com.yahoo.config.codegen.InnerCNode)"
],
"fields": []
},
diff --git a/config-lib/pom.xml b/config-lib/pom.xml
index 1002d43bc37..90c61725466 100644
--- a/config-lib/pom.xml
+++ b/config-lib/pom.xml
@@ -26,6 +26,12 @@
<artifactId>annotations</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>configgen</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
</dependencies>
<build>
<plugins>
diff --git a/config-lib/src/main/java/com/yahoo/config/ConfigBuilder.java b/config-lib/src/main/java/com/yahoo/config/ConfigBuilder.java
index e35e6916849..30bef223045 100644
--- a/config-lib/src/main/java/com/yahoo/config/ConfigBuilder.java
+++ b/config-lib/src/main/java/com/yahoo/config/ConfigBuilder.java
@@ -5,7 +5,6 @@ package com.yahoo.config;
* Root interface for all config builders.
*
* @author gjoranv
- * @since 5.1.6
*/
public interface ConfigBuilder {
}
diff --git a/config-lib/src/main/java/com/yahoo/config/ConfigInstance.java b/config-lib/src/main/java/com/yahoo/config/ConfigInstance.java
index 04405839a9b..b47bd17a5ba 100644
--- a/config-lib/src/main/java/com/yahoo/config/ConfigInstance.java
+++ b/config-lib/src/main/java/com/yahoo/config/ConfigInstance.java
@@ -1,9 +1,16 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.config;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.logging.Level;
+
+import com.yahoo.config.codegen.CNode;
+import com.yahoo.config.codegen.InnerCNode;
+import com.yahoo.config.codegen.LeafCNode;
/**
* Represents an instance of an application config with a specific configId.
@@ -13,10 +20,13 @@ import java.util.Map;
*/
public abstract class ConfigInstance extends InnerNode {
+ private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(ConfigInstance.class.getName());
+
public interface Builder extends ConfigBuilder {
/**
* Dispatches a getConfig() call if this instance's producer is of the right type
+ *
* @param producer a config producer
* @return true if this instance's producer was the correct type, and hence a getConfig call was dispatched
*/
@@ -26,6 +36,103 @@ public abstract class ConfigInstance extends InnerNode {
String getDefNamespace();
String getDefMd5();
+ /** Returns true if this instance should be applied on restart, false if it should be applied immediately */
+ default boolean getApplyOnRestart() { return false; }
+
+ default void setApplyOnRestart(boolean applyOnRestart) { throw new java.lang.UnsupportedOperationException(); }
+
+ default ConfigInstance buildInstance(InnerCNode targetDef) {
+ try {
+ if (targetDef != null) applyDef(this, targetDef);
+ Class<? extends ConfigInstance> clazz = getConfigClass(getClass());
+ return clazz.getConstructor(getClass()).newInstance(this);
+ } catch (Exception e) {
+ throw new ConfigurationRuntimeException(e);
+ }
+ }
+
+ /**
+ * If some fields on the builder are null now, set them from the def. Do recursively.
+ * <p>
+ * If the targetDef has some schema incompatibilities, they are not handled here
+ * (except logging in some cases), but in ConfigInstance.serialize().
+ *
+ * @param builder a {@link com.yahoo.config.ConfigBuilder}
+ * @param targetDef a config definition
+ * @throws Exception if applying values form config definitions fails
+ */
+ static void applyDef(ConfigBuilder builder, InnerCNode targetDef) throws Exception {
+ for (Map.Entry<String, CNode> e: targetDef.children().entrySet()) {
+ CNode node = e.getValue();
+ if (node instanceof LeafCNode) {
+ setLeafValueIfUnset(targetDef, builder, (LeafCNode)node);
+ } else if (node instanceof InnerCNode) {
+ // Is there a private field on the builder that matches this inner node in the def?
+ if (hasField(builder.getClass(), node.getName())) {
+ Field innerField = builder.getClass().getDeclaredField(node.getName());
+ innerField.setAccessible(true);
+ Object innerFieldVal = innerField.get(builder);
+ if (innerFieldVal instanceof List) {
+ // inner array? Check that list elems are ConfigBuilder
+ List<?> innerList = (List<?>) innerFieldVal;
+ for (Object b : innerList) {
+ if (b instanceof ConfigBuilder) {
+ applyDef((ConfigBuilder) b, (InnerCNode) node);
+ }
+ }
+ } else if (innerFieldVal instanceof ConfigBuilder) {
+ // Struct perhaps
+ applyDef((ConfigBuilder) innerFieldVal, (InnerCNode) node);
+ } else {
+ // Likely a config value mismatch. That is handled in ConfigInstance.serialize() (error message, omit from response.)
+ }
+ }
+ }
+ }
+ }
+
+ private static boolean hasField(Class<?> aClass, String name) {
+ for (Field field : aClass.getDeclaredFields()) {
+ if (name.equals(field.getName())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static void setLeafValueIfUnset(InnerCNode targetDef, Object builder, LeafCNode node) throws Exception {
+ if (hasField(builder.getClass(), node.getName())) {
+ Field field = builder.getClass().getDeclaredField(node.getName());
+ field.setAccessible(true);
+ Object val = field.get(builder);
+ if (val==null) {
+ // Not set on builder, if the leaf node has a default value, try the private setter that takes String
+ try {
+ if (node.getDefaultValue()!=null) {
+ Method setter = builder.getClass().getDeclaredMethod(node.getName(), String.class);
+ setter.setAccessible(true);
+ setter.invoke(builder, node.getDefaultValue().getValue());
+ }
+ } catch (Exception e) {
+ log.log(Level.SEVERE,
+ "For config '" + targetDef.getFullName() + "': " +
+ "Unable to apply the default value for field '" + node.getName() +
+ "' to config Builder (where it wasn't set)",
+ e);
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private static Class<? extends ConfigInstance> getConfigClass(Class<? extends ConfigInstance.Builder> builderClass) {
+ Class<?> configClass = builderClass.getEnclosingClass();
+ if (configClass == null || ! ConfigInstance.class.isAssignableFrom(configClass)) {
+ throw new ConfigurationRuntimeException("Builder class " + builderClass + " has enclosing class " + configClass + ", which is not a ConfigInstance");
+ }
+ return (Class<? extends ConfigInstance>) configClass;
+ }
+
}
public interface Producer {}
diff --git a/config-lib/src/main/java/com/yahoo/config/Node.java b/config-lib/src/main/java/com/yahoo/config/Node.java
index 8d16b9727c1..ed11bdc9891 100644
--- a/config-lib/src/main/java/com/yahoo/config/Node.java
+++ b/config-lib/src/main/java/com/yahoo/config/Node.java
@@ -5,7 +5,6 @@ package com.yahoo.config;
* The Node class is superclass for all nodes in a {@link
* ConfigInstance}. Important subclasses of this node are {@link
* InnerNode} and {@link LeafNode}.
- *
*/
public abstract class Node {
@@ -13,7 +12,7 @@ public abstract class Node {
* Postinitialize this node. Any node needing to process its values depending on the config
* id should override this method.
*
- * @param configId the configId of the ConfigInstance that owns (or is) this node
+ * @param configId the configId of the ConfigInstance that owns (or is) this node
*/
public void postInitialize(String configId) { return; }
@@ -26,4 +25,5 @@ public abstract class Node {
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
+
}