diff options
27 files changed, 116 insertions, 87 deletions
diff --git a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/NodeStateChangeChecker.java b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/NodeStateChangeChecker.java index 4ae45701344..eb4a5cc00b0 100644 --- a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/NodeStateChangeChecker.java +++ b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/NodeStateChangeChecker.java @@ -21,11 +21,12 @@ import java.util.Optional; * @author Haakon Dybdahl */ public class NodeStateChangeChecker { + public static final String BUCKETS_METRIC_NAME = "vds.datastored.bucket_space.buckets_total"; public static final Map<String, String> BUCKETS_METRIC_DIMENSIONS = Map.of("bucketSpace", "default"); private final int minStorageNodesUp; - private double minRatioOfStorageNodesUp; + private final double minRatioOfStorageNodesUp; private final int requiredRedundancy; private final ClusterInfo clusterInfo; @@ -296,4 +297,5 @@ public class NodeStateChangeChecker { return Result.allowSettingOfWantedState(); } + } diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterResources.java b/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterResources.java index 20e5e887c72..7f7357ea77f 100644 --- a/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterResources.java +++ b/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterResources.java @@ -1,9 +1,6 @@ // Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.config.provision; -import com.yahoo.config.Node; - -import java.util.List; import java.util.Objects; /** diff --git a/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/Subscriber.java b/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/Subscriber.java index f96d6470679..e79497e0dd3 100644 --- a/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/Subscriber.java +++ b/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/Subscriber.java @@ -43,7 +43,7 @@ public class Subscriber { } public Optional<RawConfig> nextGeneration() { - if (subscriber.nextGeneration(0)) { + if (subscriber.nextGeneration(0, true)) { // Proxy should never skip config due to not initializing try { return Optional.of(handle.getRawConfig()); } catch (Exception e) { // To avoid thread throwing exception and loop never running this again diff --git a/config/abi-spec.json b/config/abi-spec.json index a41df9aa60d..fa016fd91da 100644 --- a/config/abi-spec.json +++ b/config/abi-spec.json @@ -202,9 +202,13 @@ "public com.yahoo.config.subscription.ConfigHandle subscribe(java.lang.Class, java.lang.String, long)", "protected void checkStateBeforeSubscribe()", "protected void subscribeAndHandleErrors(com.yahoo.config.subscription.impl.ConfigSubscription, com.yahoo.vespa.config.ConfigKey, com.yahoo.config.subscription.ConfigHandle, com.yahoo.vespa.config.TimingValues)", + "public boolean nextConfig(boolean)", "public boolean nextConfig()", + "public boolean nextConfig(long, boolean)", "public boolean nextConfig(long)", + "public boolean nextGeneration(boolean)", "public boolean nextGeneration()", + "public boolean nextGeneration(long, boolean)", "public boolean nextGeneration(long)", "protected void throwIfExceptionSet(com.yahoo.config.subscription.impl.ConfigSubscription)", "public void close()", diff --git a/config/src/main/java/com/yahoo/config/subscription/ConfigGetter.java b/config/src/main/java/com/yahoo/config/subscription/ConfigGetter.java index b2aa0147259..e3d1f2eac55 100755 --- a/config/src/main/java/com/yahoo/config/subscription/ConfigGetter.java +++ b/config/src/main/java/com/yahoo/config/subscription/ConfigGetter.java @@ -50,7 +50,7 @@ public class ConfigGetter<T extends ConfigInstance> { try (ConfigSubscriber subscriber = source == null ? new ConfigSubscriber() : new ConfigSubscriber(source)) { ConfigHandle<T> handle = subscriber.subscribe(clazz, configId); - subscriber.nextConfig(); + subscriber.nextConfig(true); return handle.getConfig(); } } diff --git a/config/src/main/java/com/yahoo/config/subscription/ConfigHandle.java b/config/src/main/java/com/yahoo/config/subscription/ConfigHandle.java index c0eb3e98157..6a271f6a401 100644 --- a/config/src/main/java/com/yahoo/config/subscription/ConfigHandle.java +++ b/config/src/main/java/com/yahoo/config/subscription/ConfigHandle.java @@ -1,7 +1,6 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.config.subscription; - import com.yahoo.config.ConfigInstance; import com.yahoo.config.subscription.impl.ConfigSubscription; @@ -23,7 +22,6 @@ public class ConfigHandle<T extends ConfigInstance> { /** * Returns true if: - * * The config generation for the {@link ConfigSubscriber} that produced this is the first one in its life cycle. (Typically first time config.) * or * All configs for the subscriber have a new generation since the last time nextConfig() was called diff --git a/config/src/main/java/com/yahoo/config/subscription/ConfigSubscriber.java b/config/src/main/java/com/yahoo/config/subscription/ConfigSubscriber.java index 57dbe22a65a..558213c43b9 100644 --- a/config/src/main/java/com/yahoo/config/subscription/ConfigSubscriber.java +++ b/config/src/main/java/com/yahoo/config/subscription/ConfigSubscriber.java @@ -155,11 +155,18 @@ public class ConfigSubscriber implements AutoCloseable { * * If the call times out (timeout 1000 ms), no handle will have the changed flag set. You should not configure anything then. * + * @param isInitializing true if this the config is needed to create the initial configuration for the caller, + * false if this is for reconfiguration * @return true if a config/reconfig of your system should happen * @throws ConfigInterruptedException if thread performing this call interrupted. */ + public boolean nextConfig(boolean isInitializing) { + return nextConfig(TimingValues.defaultNextConfigTimeout, isInitializing); + } + + @Deprecated // TODO: Remove on Vespa 8 public boolean nextConfig() { - return nextConfig(TimingValues.defaultNextConfigTimeout); + return nextConfig(false); } /** @@ -179,11 +186,18 @@ public class ConfigSubscriber implements AutoCloseable { * If the call times out, no handle will have the changed flag set. You should not configure anything then. * * @param timeoutMillis timeout in milliseconds + * @param isInitializing true if this the config is needed to create the initial configuration for the caller, + * false if this is for reconfiguration * @return true if a config/reconfig of your system should happen * @throws ConfigInterruptedException if thread performing this call interrupted. */ + public boolean nextConfig(long timeoutMillis, boolean isInitializing) { + return acquireSnapshot(timeoutMillis, true, isInitializing); + } + + @Deprecated // TODO: Remove on Vespa 8 public boolean nextConfig(long timeoutMillis) { - return acquireSnapshot(timeoutMillis, true); + return nextConfig(timeoutMillis, false); } /** @@ -203,11 +217,18 @@ public class ConfigSubscriber implements AutoCloseable { * * If the call times out (timeout 1000 ms), no handle will have the changed flag set. You should not configure anything then. * + * @param isInitializing true if this the next generation is needed to create the initial configuration for the caller, + * false if this is for reconfiguration * @return true if generations for all configs have been updated. * @throws ConfigInterruptedException if thread performing this call interrupted. */ + public boolean nextGeneration(boolean isInitializing) { + return nextGeneration(TimingValues.defaultNextConfigTimeout, isInitializing); + } + + @Deprecated // TODO: Remove on Vespa 8 public boolean nextGeneration() { - return nextGeneration(TimingValues.defaultNextConfigTimeout); + return nextGeneration(false); } /** @@ -227,11 +248,18 @@ public class ConfigSubscriber implements AutoCloseable { * If the call times out (timeout 1000 ms), no handle will have the changed flag set. You should not configure anything then. * * @param timeoutMillis timeout in milliseconds + * @param isInitializing true if this the next generation is needed to create the initial configuration for the caller, + * false if this is for reconfiguration * @return true if generations for all configs have been updated. * @throws ConfigInterruptedException if thread performing this call interrupted. */ + public boolean nextGeneration(long timeoutMillis, boolean isInitializing) { + return acquireSnapshot(timeoutMillis, false, isInitializing); + } + + @Deprecated // TODO: Remov4e on Vespa 8 public boolean nextGeneration(long timeoutMillis) { - return acquireSnapshot(timeoutMillis, false); + return nextGeneration(timeoutMillis, false); } /** @@ -243,14 +271,12 @@ public class ConfigSubscriber implements AutoCloseable { * that at lest one of them has changed if <code>requireChange</code> is true), and * the config should be applied at this time, false otherwise */ - private boolean acquireSnapshot(long timeoutInMillis, boolean requireChange) { - boolean initialConfiguration; + private boolean acquireSnapshot(long timeoutInMillis, boolean requireChange, boolean isInitializing) { boolean applyOnRestartOnly; synchronized (monitor) { if (state == State.CLOSED) return false; state = State.FROZEN; applyOnRestartOnly = applyOnRestart; - initialConfiguration = generation == -1; } long started = System.currentTimeMillis(); long timeLeftMillis = timeoutInMillis; @@ -276,14 +302,14 @@ public class ConfigSubscriber implements AutoCloseable { if (currentGen == null) currentGen = config.getGeneration(); allGenerationsTheSame &= currentGen.equals(config.getGeneration()); allGenerationsChanged &= config.isGenerationChanged(); - anyConfigChanged |= config.isConfigChanged(); + anyConfigChanged |= config.isConfigChanged(); applyOnRestartOnly |= config.applyOnRestart(); timeLeftMillis = timeoutInMillis + started - System.currentTimeMillis(); } - reconfigDue = (initialConfiguration || !applyOnRestartOnly) && (anyConfigChanged || !requireChange) + reconfigDue = (isInitializing || !applyOnRestartOnly) && (anyConfigChanged || !requireChange) && allGenerationsChanged && allGenerationsTheSame; - if (applyOnRestartOnly && ! initialConfiguration) { // disable any reconfig until restart + if (applyOnRestartOnly && ! isInitializing) { // disable any reconfig until restart synchronized (monitor) { applyOnRestart = applyOnRestartOnly; } diff --git a/config/src/test/java/com/yahoo/config/subscription/AppService.java b/config/src/test/java/com/yahoo/config/subscription/AppService.java index 0f8d93e6fe0..3cf301a9b03 100644 --- a/config/src/test/java/com/yahoo/config/subscription/AppService.java +++ b/config/src/test/java/com/yahoo/config/subscription/AppService.java @@ -11,6 +11,7 @@ import com.yahoo.vespa.config.TimingValues; * generated code in AppConfig.java. */ class AppService { + private int timesConfigured = 0; private AppConfig config = null; @@ -33,17 +34,17 @@ class AppService { } else { temp = subscriber.subscribe(AppConfig.class, configId, csource, timingValues); } - final ConfigHandle<AppConfig> handle = temp; + ConfigHandle<AppConfig> handle = temp; Thread configThread = new Thread(() -> { while (!stopThread) { - boolean changed = subscriber.nextConfig(500); + boolean changed = subscriber.nextConfig(500, false); if (changed) { configure(handle.getConfig()); timesConfigured++; } } }); - subscriber.nextConfig(5000); + subscriber.nextConfig(5000, false); timesConfigured++; configure(handle.getConfig()); configThread.setDaemon(true); diff --git a/config/src/test/java/com/yahoo/config/subscription/BasicTest.java b/config/src/test/java/com/yahoo/config/subscription/BasicTest.java index 5b145d40b7f..5af45e3a999 100644 --- a/config/src/test/java/com/yahoo/config/subscription/BasicTest.java +++ b/config/src/test/java/com/yahoo/config/subscription/BasicTest.java @@ -15,7 +15,7 @@ public class BasicTest { public void testSubBasic() { ConfigSubscriber s = new ConfigSubscriber(); ConfigHandle<AppConfig> h = s.subscribe(AppConfig.class, "raw:times 0"); - s.nextConfig(0); + s.nextConfig(0, false); AppConfig c = h.getConfig(); assertEquals(0, c.times()); s.close(); @@ -25,7 +25,7 @@ public class BasicTest { public void testSubBasicGeneration() { ConfigSubscriber s = new ConfigSubscriber(); ConfigHandle<AppConfig> h = s.subscribe(AppConfig.class, "raw:times 2"); - s.nextGeneration(0); + s.nextGeneration(0, false); AppConfig c = h.getConfig(); assertEquals(2, c.times()); s.close(); diff --git a/config/src/test/java/com/yahoo/config/subscription/ConfigApiTest.java b/config/src/test/java/com/yahoo/config/subscription/ConfigApiTest.java index af2df2bcae7..be09e57b27e 100755 --- a/config/src/test/java/com/yahoo/config/subscription/ConfigApiTest.java +++ b/config/src/test/java/com/yahoo/config/subscription/ConfigApiTest.java @@ -23,7 +23,7 @@ public class ConfigApiTest { ConfigSubscriber subscriber = new ConfigSubscriber(); ConfigHandle<AppConfig> h = subscriber.subscribe(AppConfig.class, CONFIG_ID); assertNotNull(h); - subscriber.nextConfig(); + subscriber.nextConfig(false); assertNotNull(h.getConfig()); assertEquals(AppConfig.CONFIG_DEF_NAME, ConfigInstance.getDefName(h.getConfig().getClass())); assertTrue(h.isChanged()); @@ -40,7 +40,7 @@ public class ConfigApiTest { public void testSubscribeAfterClose() { ConfigSubscriber subscriber = new ConfigSubscriber(); subscriber.subscribe(AppConfig.class, CONFIG_ID); - subscriber.nextConfig(); + subscriber.nextConfig(false); subscriber.close(); subscriber.subscribe(AppConfig.class, CONFIG_ID); } @@ -52,7 +52,7 @@ public class ConfigApiTest { public void testSubscribeAfterNextConfig() { ConfigSubscriber subscriber = new ConfigSubscriber(); subscriber.subscribe(AppConfig.class, CONFIG_ID); - subscriber.nextConfig(); + subscriber.nextConfig(false); subscriber.subscribe(AppConfig.class, CONFIG_ID); subscriber.close(); } diff --git a/config/src/test/java/com/yahoo/config/subscription/ConfigInstanceTest.java b/config/src/test/java/com/yahoo/config/subscription/ConfigInstanceTest.java index 4da0c3f51e0..f706f021ba0 100644 --- a/config/src/test/java/com/yahoo/config/subscription/ConfigInstanceTest.java +++ b/config/src/test/java/com/yahoo/config/subscription/ConfigInstanceTest.java @@ -114,8 +114,9 @@ public class ConfigInstanceTest { public TestNonstring(String configId) { ConfigSubscriber subscriber = new ConfigSubscriber(); ConfigHandle<TestNonstringConfig> handle = subscriber.subscribe(TestNonstringConfig.class, configId); - subscriber.nextConfig(); + subscriber.nextConfig(false); handle.getConfig(); } } + } diff --git a/config/src/test/java/com/yahoo/config/subscription/ConfigSetSubscriptionTest.java b/config/src/test/java/com/yahoo/config/subscription/ConfigSetSubscriptionTest.java index db30e7b7389..b31924e94e7 100644 --- a/config/src/test/java/com/yahoo/config/subscription/ConfigSetSubscriptionTest.java +++ b/config/src/test/java/com/yahoo/config/subscription/ConfigSetSubscriptionTest.java @@ -65,7 +65,7 @@ public class ConfigSetSubscriptionTest { ConfigHandle<AppConfig> hA1 = subscriber.subscribe(AppConfig.class, "app/1"); ConfigHandle<StringConfig> hS = subscriber.subscribe(StringConfig.class, "bar"); - assertTrue(subscriber.nextConfig(0)); + assertTrue(subscriber.nextConfig(0, false)); assertTrue(hA0.isChanged()); assertTrue(hA1.isChanged()); assertTrue(hS.isChanged()); @@ -75,7 +75,7 @@ public class ConfigSetSubscriptionTest { assertEquals(hA0.getConfig().times(), 88); assertEquals(hA1.getConfig().times(), 89); - assertFalse(subscriber.nextConfig(10)); + assertFalse(subscriber.nextConfig(10, false)); assertFalse(hA0.isChanged()); assertFalse(hA1.isChanged()); assertFalse(hS.isChanged()); @@ -90,7 +90,7 @@ public class ConfigSetSubscriptionTest { a1builder.message("A new message, 1").times(890); barBuilder.stringVal("new StringVal"); subscriber.reload(1); - assertTrue(subscriber.nextConfig(0)); + assertTrue(subscriber.nextConfig(0, false)); assertTrue(hA0.isChanged()); assertTrue(hA1.isChanged()); assertTrue(hS.isChanged()); @@ -104,7 +104,7 @@ public class ConfigSetSubscriptionTest { // Reconfigure only one a0builder.message("Another new message, 0").times(8800); subscriber.reload(2); - assertTrue(subscriber.nextConfig(0)); + assertTrue(subscriber.nextConfig(0, false)); assertTrue(hA0.isChanged()); assertFalse(hA1.isChanged()); assertFalse(hS.isChanged()); @@ -118,7 +118,7 @@ public class ConfigSetSubscriptionTest { //Reconfigure only one, and only one field on the builder a1builder.message("Yet another message, 1"); subscriber.reload(3); - assertTrue(subscriber.nextConfig(0)); + assertTrue(subscriber.nextConfig(0, false)); assertFalse(hA0.isChanged()); assertTrue(hA1.isChanged()); assertFalse(hS.isChanged()); @@ -139,11 +139,11 @@ public class ConfigSetSubscriptionTest { ConfigSubscriber subscriber = new ConfigSubscriber(myConfigs); ConfigHandle<AppConfig> hA0 = subscriber.subscribe(AppConfig.class, "app/0"); - assertTrue(subscriber.nextConfig(0)); + assertTrue(subscriber.nextConfig(0, false)); assertTrue(hA0.isChanged()); assertEquals(hA0.getConfig().message(), "A message, 1"); - assertFalse(subscriber.nextConfig(10)); + assertFalse(subscriber.nextConfig(10, false)); assertFalse(hA0.isChanged()); assertEquals(hA0.getConfig().message(), "A message, 1"); @@ -154,7 +154,7 @@ public class ConfigSetSubscriptionTest { subscriber.reload(2); // Should pick up the last one - assertTrue(subscriber.nextConfig(0)); + assertTrue(subscriber.nextConfig(0, false)); assertTrue(hA0.isChanged()); assertEquals(hA0.getConfig().message(), "An even newer message, 3"); } diff --git a/config/src/test/java/com/yahoo/config/subscription/ConfigSubscriptionTest.java b/config/src/test/java/com/yahoo/config/subscription/ConfigSubscriptionTest.java index c8d4c081fc9..f70602c64e7 100644 --- a/config/src/test/java/com/yahoo/config/subscription/ConfigSubscriptionTest.java +++ b/config/src/test/java/com/yahoo/config/subscription/ConfigSubscriptionTest.java @@ -68,7 +68,7 @@ public class ConfigSubscriptionTest { ConfigSubscriber sub = new ConfigSubscriber(); ConfigHandle<SimpletypesConfig> handle = sub.subscribe(SimpletypesConfig.class, "raw:boolval true", 10000); assertNotNull(handle); - sub.nextConfig(); + sub.nextConfig(false); assertTrue(handle.getConfig().boolval()); //assertTrue(sub.getSource() instanceof RawSource); sub.close(); diff --git a/config/src/test/java/com/yahoo/config/subscription/DefaultConfigTest.java b/config/src/test/java/com/yahoo/config/subscription/DefaultConfigTest.java index 1bcf09a4028..21bf7469591 100644 --- a/config/src/test/java/com/yahoo/config/subscription/DefaultConfigTest.java +++ b/config/src/test/java/com/yahoo/config/subscription/DefaultConfigTest.java @@ -34,9 +34,8 @@ public class DefaultConfigTest { @Test(expected = IllegalArgumentException.class) public void testFailUponUnitializedValue() { ConfigSubscriber subscriber = new ConfigSubscriber(); - subscriber.subscribe(DefaulttestConfig.class, "raw:" + - "defaultstring \"new value\""); - subscriber.nextConfig(); + subscriber.subscribe(DefaulttestConfig.class, "raw:defaultstring \"new value\""); + subscriber.nextConfig(false); subscriber.close(); } @@ -51,7 +50,7 @@ public class DefaultConfigTest { public void testDefaultConfig() { ConfigSubscriber subscriber = new ConfigSubscriber(); ConfigHandle<DefaulttestConfig> h = subscriber.subscribe(DefaulttestConfig.class, CONFIG_ID); - assertTrue(subscriber.nextConfig()); + assertTrue(subscriber.nextConfig(false)); DefaulttestConfig config = h.getConfig(); verifyConfigValues(config); subscriber.close(); diff --git a/config/src/test/java/com/yahoo/config/subscription/GenericConfigSubscriberTest.java b/config/src/test/java/com/yahoo/config/subscription/GenericConfigSubscriberTest.java index 9c83f2f3c9a..d5eccdfe94b 100644 --- a/config/src/test/java/com/yahoo/config/subscription/GenericConfigSubscriberTest.java +++ b/config/src/test/java/com/yahoo/config/subscription/GenericConfigSubscriberTest.java @@ -38,10 +38,10 @@ public class GenericConfigSubscriberTest { GenericConfigSubscriber sub = new GenericConfigSubscriber(requesters); final List<String> defContent = List.of("myVal int"); GenericConfigHandle handle = sub.subscribe(new ConfigKey<>("simpletypes", "id", "config"), defContent, sourceSet, JRTConfigRequesterTest.getTestTimingValues()); - assertTrue(sub.nextConfig()); + assertTrue(sub.nextConfig(false)); assertTrue(handle.isChanged()); assertThat(handle.getRawConfig().getPayload().withCompression(CompressionType.UNCOMPRESSED).toString(), is("{}")); // MockConnection returns empty string - assertFalse(sub.nextConfig()); + assertFalse(sub.nextConfig(false)); assertFalse(handle.isChanged()); } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/application/Application.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/Application.java index 55ef05650af..e77592dc011 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/application/Application.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/Application.java @@ -61,11 +61,7 @@ public class Application implements ModelResult { this.app = app; } - /** - * Returns the generation for the config we are currently serving - * - * @return the config generation - */ + /** Returns the generation for the config we are currently serving. */ public Long getApplicationGeneration() { return applicationGeneration; } /** Returns the application model, never null */ diff --git a/container-core/src/main/java/com/yahoo/container/core/config/HandlersConfigurerDi.java b/container-core/src/main/java/com/yahoo/container/core/config/HandlersConfigurerDi.java index ac632f5acce..26f11b98366 100644 --- a/container-core/src/main/java/com/yahoo/container/core/config/HandlersConfigurerDi.java +++ b/container-core/src/main/java/com/yahoo/container/core/config/HandlersConfigurerDi.java @@ -74,7 +74,7 @@ public class HandlersConfigurerDi { this.vespaContainer = vespaContainer; container = new Container(subscriberFactory, configId, deconstructor, osgiWrapper); - getNewComponentGraph(discInjector); + getNewComponentGraph(discInjector, true); } private static class ContainerAndDiOsgi extends OsgiImpl implements OsgiWrapper { @@ -128,9 +128,10 @@ public class HandlersConfigurerDi { /** * Wait for new config to arrive and produce the new graph */ - public void getNewComponentGraph(Injector discInjector) { + public void getNewComponentGraph(Injector discInjector, boolean isInitializing) { currentGraph = container.getNewComponentGraph(currentGraph, - createFallbackInjector(vespaContainer, discInjector)); + createFallbackInjector(vespaContainer, discInjector), + isInitializing); } private Injector createFallbackInjector(com.yahoo.container.Container vespaContainer, Injector discInjector) { diff --git a/container-core/src/main/java/com/yahoo/container/core/config/testutil/HandlersConfigurerTestWrapper.java b/container-core/src/main/java/com/yahoo/container/core/config/testutil/HandlersConfigurerTestWrapper.java index 42e54d3a78f..d98a865e1fb 100644 --- a/container-core/src/main/java/com/yahoo/container/core/config/testutil/HandlersConfigurerTestWrapper.java +++ b/container-core/src/main/java/com/yahoo/container/core/config/testutil/HandlersConfigurerTestWrapper.java @@ -117,7 +117,7 @@ public class HandlersConfigurerTestWrapper { public void reloadConfig() { configurer.reloadConfig(++lastGeneration); - configurer.getNewComponentGraph(guiceInjector()); + configurer.getNewComponentGraph(guiceInjector(), false); } public void shutdown() { diff --git a/container-di/src/main/java/com/yahoo/container/di/CloudSubscriberFactory.java b/container-di/src/main/java/com/yahoo/container/di/CloudSubscriberFactory.java index 75a660789e2..d43f96c9b4a 100644 --- a/container-di/src/main/java/com/yahoo/container/di/CloudSubscriberFactory.java +++ b/container-di/src/main/java/com/yahoo/container/di/CloudSubscriberFactory.java @@ -95,7 +95,7 @@ public class CloudSubscriberFactory implements SubscriberFactory { } @Override - public long waitNextGeneration() { + public long waitNextGeneration(boolean isInitializing) { if (handles.isEmpty()) throw new IllegalStateException("No config keys registered"); @@ -108,7 +108,7 @@ public class CloudSubscriberFactory implements SubscriberFactory { int numExceptions = 0; while ( ! gotNextGen) { try { - if (subscriber.nextGeneration()) + if (subscriber.nextGeneration(isInitializing)) gotNextGen = true; } catch (IllegalArgumentException e) { diff --git a/container-di/src/main/java/com/yahoo/container/di/ConfigRetriever.java b/container-di/src/main/java/com/yahoo/container/di/ConfigRetriever.java index cf80009f3f6..a7ff6c46a8b 100644 --- a/container-di/src/main/java/com/yahoo/container/di/ConfigRetriever.java +++ b/container-di/src/main/java/com/yahoo/container/di/ConfigRetriever.java @@ -46,10 +46,10 @@ public final class ConfigRetriever { } public ConfigSnapshot getConfigs(Set<ConfigKey<? extends ConfigInstance>> componentConfigKeys, - long leastGeneration) { + long leastGeneration, boolean isInitializing) { // Loop until we get config. while (true) { - Optional<ConfigSnapshot> maybeSnapshot = getConfigsOnce(componentConfigKeys, leastGeneration); + Optional<ConfigSnapshot> maybeSnapshot = getConfigsOnce(componentConfigKeys, leastGeneration, isInitializing); if (maybeSnapshot.isPresent()) { var configSnapshot = maybeSnapshot.get(); resetComponentSubscriberIfBootstrap(configSnapshot); @@ -59,7 +59,7 @@ public final class ConfigRetriever { } Optional<ConfigSnapshot> getConfigsOnce(Set<ConfigKey<? extends ConfigInstance>> componentConfigKeys, - long leastGeneration) { + long leastGeneration, boolean isInitializing) { if (!Sets.intersection(componentConfigKeys, bootstrapKeys).isEmpty()) { throw new IllegalArgumentException( "Component config keys [" + componentConfigKeys + "] overlaps with bootstrap config keys [" + bootstrapKeys + "]"); @@ -70,18 +70,18 @@ public final class ConfigRetriever { allKeys.addAll(bootstrapKeys); setupComponentSubscriber(allKeys); - return getConfigsOptional(leastGeneration); + return getConfigsOptional(leastGeneration, isInitializing); } - private Optional<ConfigSnapshot> getConfigsOptional(long leastGeneration) { - long newestComponentGeneration = componentSubscriber.waitNextGeneration(); + private Optional<ConfigSnapshot> getConfigsOptional(long leastGeneration, boolean isInitializing) { + long newestComponentGeneration = componentSubscriber.waitNextGeneration(isInitializing); log.log(FINE, "getConfigsOptional: new component generation: " + newestComponentGeneration); // leastGeneration is only used to ensure newer generation when the previous generation was invalidated due to an exception if (newestComponentGeneration < leastGeneration) { return Optional.empty(); } else if (bootstrapSubscriber.generation() < newestComponentGeneration) { - long newestBootstrapGeneration = bootstrapSubscriber.waitNextGeneration(); + long newestBootstrapGeneration = bootstrapSubscriber.waitNextGeneration(isInitializing); log.log(FINE, "getConfigsOptional: new bootstrap generation: " + bootstrapSubscriber.generation()); Optional<ConfigSnapshot> bootstrapConfig = bootstrapConfigIfChanged(); if (bootstrapConfig.isPresent()) { @@ -92,8 +92,8 @@ public final class ConfigRetriever { return componentsConfigIfChanged(); } else { // This should not be a normal case, and hence a warning to allow investigation. - log.warning("Did not get same generation for bootstrap (" + newestBootstrapGeneration + ") and components configs (" - + newestComponentGeneration + ")."); + log.warning("Did not get same generation for bootstrap (" + newestBootstrapGeneration + + ") and components configs (" + newestComponentGeneration + ")."); return Optional.empty(); } } diff --git a/container-di/src/main/java/com/yahoo/container/di/Container.java b/container-di/src/main/java/com/yahoo/container/di/Container.java index 7855cd6b2f1..82c7f65bc2a 100644 --- a/container-di/src/main/java/com/yahoo/container/di/Container.java +++ b/container-di/src/main/java/com/yahoo/container/di/Container.java @@ -44,9 +44,9 @@ public class Container { private static final Logger log = Logger.getLogger(Container.class.getName()); private final SubscriberFactory subscriberFactory; - private ConfigKey<ApplicationBundlesConfig> applicationBundlesConfigKey; - private ConfigKey<PlatformBundlesConfig> platformBundlesConfigKey; - private ConfigKey<ComponentsConfig> componentsConfigKey; + private final ConfigKey<ApplicationBundlesConfig> applicationBundlesConfigKey; + private final ConfigKey<PlatformBundlesConfig> platformBundlesConfigKey; + private final ConfigKey<ComponentsConfig> componentsConfigKey; private final ComponentDeconstructor componentDeconstructor; private final Osgi osgi; @@ -72,10 +72,10 @@ public class Container { }); } - public ComponentGraph getNewComponentGraph(ComponentGraph oldGraph, Injector fallbackInjector) { + public ComponentGraph getNewComponentGraph(ComponentGraph oldGraph, Injector fallbackInjector, boolean isInitializing) { try { Collection<Bundle> obsoleteBundles = new HashSet<>(); - ComponentGraph newGraph = getConfigAndCreateGraph(oldGraph, fallbackInjector, obsoleteBundles); + ComponentGraph newGraph = getConfigAndCreateGraph(oldGraph, fallbackInjector, isInitializing, obsoleteBundles); newGraph.reuseNodes(oldGraph); constructComponents(newGraph); deconstructObsoleteComponents(oldGraph, newGraph, obsoleteBundles); @@ -88,11 +88,12 @@ public class Container { private ComponentGraph getConfigAndCreateGraph(ComponentGraph graph, Injector fallbackInjector, + boolean isInitializing, Collection<Bundle> obsoleteBundles) // NOTE: Return value { ConfigSnapshot snapshot; while (true) { - snapshot = configurer.getConfigs(graph.configKeys(), leastGeneration); + snapshot = configurer.getConfigs(graph.configKeys(), leastGeneration, isInitializing); log.log(FINE, String.format("createNewGraph:\n" + "graph.configKeys = %s\n" + "graph.generation = %s\n" + "snapshot = %s\n", graph.configKeys(), graph.generation(), snapshot)); diff --git a/container-di/src/main/java/com/yahoo/container/di/config/Subscriber.java b/container-di/src/main/java/com/yahoo/container/di/config/Subscriber.java index 9fd30f888b9..60207447bfd 100644 --- a/container-di/src/main/java/com/yahoo/container/di/config/Subscriber.java +++ b/container-di/src/main/java/com/yahoo/container/di/config/Subscriber.java @@ -12,7 +12,7 @@ import java.util.Map; */ public interface Subscriber { - long waitNextGeneration(); + long waitNextGeneration(boolean isInitializing); long generation(); boolean configChanged(); diff --git a/container-di/src/test/java/com/yahoo/container/di/ConfigRetrieverTest.java b/container-di/src/test/java/com/yahoo/container/di/ConfigRetrieverTest.java index 4751b9b74b7..290836d7842 100644 --- a/container-di/src/test/java/com/yahoo/container/di/ConfigRetrieverTest.java +++ b/container-di/src/test/java/com/yahoo/container/di/ConfigRetrieverTest.java @@ -51,7 +51,7 @@ public class ConfigRetrieverTest { public void require_that_bootstrap_configs_come_first() { writeConfigs(); ConfigRetriever retriever = createConfigRetriever(); - ConfigSnapshot bootstrapConfigs = retriever.getConfigs(Collections.emptySet(), 0); + ConfigSnapshot bootstrapConfigs = retriever.getConfigs(Collections.emptySet(), 0, true); assertThat(bootstrapConfigs, Matchers.instanceOf(BootstrapConfigs.class)); } @@ -61,10 +61,10 @@ public class ConfigRetrieverTest { public void require_that_components_comes_after_bootstrap() { writeConfigs(); ConfigRetriever retriever = createConfigRetriever(); - ConfigSnapshot bootstrapConfigs = retriever.getConfigs(Collections.emptySet(), 0); + ConfigSnapshot bootstrapConfigs = retriever.getConfigs(Collections.emptySet(), 0, true); ConfigKey<? extends ConfigInstance> testConfigKey = new ConfigKey<>(TestConfig.class, dirConfigSource.configId()); - ConfigSnapshot componentsConfigs = retriever.getConfigs(Collections.singleton(testConfigKey), 0); + ConfigSnapshot componentsConfigs = retriever.getConfigs(Collections.singleton(testConfigKey), 0, true); if (componentsConfigs instanceof ComponentsConfigs) { assertThat(componentsConfigs.size(), is(3)); @@ -84,20 +84,20 @@ public class ConfigRetrieverTest { writeConfigs(); ConfigRetriever retriever = createConfigRetriever(); ConfigKey<? extends ConfigInstance> testConfigKey = new ConfigKey<>(TestConfig.class, dirConfigSource.configId()); - ConfigSnapshot bootstrapConfigs = retriever.getConfigs(Collections.emptySet(), 0); - ConfigSnapshot componentsConfigs = retriever.getConfigs(Collections.singleton(testConfigKey), 0); + ConfigSnapshot bootstrapConfigs = retriever.getConfigs(Collections.emptySet(), 0, true); + ConfigSnapshot componentsConfigs = retriever.getConfigs(Collections.singleton(testConfigKey), 0, true); Set<ConfigKey<? extends ConfigInstance>> keys = new HashSet<>(); keys.add(testConfigKey); keys.add(new ConfigKey<>(TestConfig.class, "")); - retriever.getConfigs(keys, 0); + retriever.getConfigs(keys, 0, true); } @Test public void require_that_empty_components_keys_after_bootstrap_returns_components_configs() { writeConfigs(); ConfigRetriever retriever = createConfigRetriever(); - assertThat(retriever.getConfigs(Collections.emptySet(), 0), instanceOf(BootstrapConfigs.class)); - assertThat(retriever.getConfigs(Collections.emptySet(), 0), instanceOf(ComponentsConfigs.class)); + assertThat(retriever.getConfigs(Collections.emptySet(), 0, true), instanceOf(BootstrapConfigs.class)); + assertThat(retriever.getConfigs(Collections.emptySet(), 0, true), instanceOf(ComponentsConfigs.class)); } public void writeConfigs() { diff --git a/container-di/src/test/java/com/yahoo/container/di/ContainerTest.java b/container-di/src/test/java/com/yahoo/container/di/ContainerTest.java index b8a5c7a236f..b596246a43d 100644 --- a/container-di/src/test/java/com/yahoo/container/di/ContainerTest.java +++ b/container-di/src/test/java/com/yahoo/container/di/ContainerTest.java @@ -394,11 +394,11 @@ public class ContainerTest extends ContainerTestBase { } ComponentGraph getNewComponentGraph(Container container, ComponentGraph oldGraph) { - return container.getNewComponentGraph(oldGraph, Guice.createInjector()); + return container.getNewComponentGraph(oldGraph, Guice.createInjector(), true); } ComponentGraph getNewComponentGraph(Container container) { - return container.getNewComponentGraph(new ComponentGraph(), Guice.createInjector()); + return container.getNewComponentGraph(new ComponentGraph(), Guice.createInjector(), true); } private ComponentTakingConfig createComponentTakingConfig(ComponentGraph componentGraph) { diff --git a/container-di/src/test/java/com/yahoo/container/di/ContainerTestBase.java b/container-di/src/test/java/com/yahoo/container/di/ContainerTestBase.java index 815865536f0..2106a1f3671 100644 --- a/container-di/src/test/java/com/yahoo/container/di/ContainerTestBase.java +++ b/container-di/src/test/java/com/yahoo/container/di/ContainerTestBase.java @@ -23,6 +23,7 @@ import static java.util.Collections.emptySet; * @author ollivir */ public class ContainerTestBase { + private ComponentGraph componentGraph; protected DirConfigSource dirConfigSource = null; @@ -70,7 +71,7 @@ public class ContainerTestBase { throw new UnsupportedOperationException("getBundle not supported."); } }); - componentGraph = container.getNewComponentGraph(componentGraph, Guice.createInjector()); + componentGraph = container.getNewComponentGraph(componentGraph, Guice.createInjector(), true); } catch (Exception e) { throw new RuntimeException(e); } @@ -120,4 +121,5 @@ public class ContainerTestBase { "</config>"; } } + } diff --git a/container-disc/src/main/java/com/yahoo/container/jdisc/ConfiguredApplication.java b/container-disc/src/main/java/com/yahoo/container/jdisc/ConfiguredApplication.java index f266e3782ef..a30bcaa82e1 100644 --- a/container-disc/src/main/java/com/yahoo/container/jdisc/ConfiguredApplication.java +++ b/container-disc/src/main/java/com/yahoo/container/jdisc/ConfiguredApplication.java @@ -133,7 +133,7 @@ public final class ConfiguredApplication implements Application { @Override public void start() { - qrConfig = getConfig(QrConfig.class); + qrConfig = getConfig(QrConfig.class, true); hackToInitializeServer(qrConfig); @@ -182,7 +182,7 @@ public final class ConfiguredApplication implements Application { slobrokList = slobrokConfigSubscriber.get().getSlobroks(); } else { slobrokList = new SlobrokList(); - SlobroksConfig slobrokConfig = getConfig(SlobroksConfig.class); + SlobroksConfig slobrokConfig = getConfig(SlobroksConfig.class, true); slobrokList.setup(slobrokConfig.slobrok().stream().map(SlobroksConfig.Slobrok::connectionspec).toArray(String[]::new)); } return slobrokList; @@ -207,10 +207,10 @@ public final class ConfiguredApplication implements Application { } } - private <T extends ConfigInstance> T getConfig(Class<T> configClass) { + private <T extends ConfigInstance> T getConfig(Class<T> configClass, boolean isInitializing) { Subscriber subscriber = subscriberFactory.getSubscriber(Collections.singleton(new ConfigKey<>(configClass, configId))); try { - subscriber.waitNextGeneration(); + subscriber.waitNextGeneration(isInitializing); return configClass.cast(first(subscriber.config().values())); } finally { subscriber.close(); @@ -221,7 +221,7 @@ public final class ConfiguredApplication implements Application { Subscriber subscriber = subscriberFactory.getSubscriber(Collections.singleton(new ConfigKey<>(QrConfig.class, configId))); try { while (true) { - subscriber.waitNextGeneration(); + subscriber.waitNextGeneration(false); QrConfig newConfig = QrConfig.class.cast(first(subscriber.config().values())); if (qrConfig.rpc().port() != newConfig.rpc().port()) { com.yahoo.protect.Process.logAndDie( @@ -264,7 +264,7 @@ public final class ConfiguredApplication implements Application { ContainerBuilder builder = createBuilderWithGuiceBindings(); // Block until new config arrives, and it should be applied - configurer.getNewComponentGraph(builder.guiceModules().activate()); + configurer.getNewComponentGraph(builder.guiceModules().activate(), false); initializeAndActivateContainer(builder); } catch (ConfigInterruptedException e) { break; diff --git a/standalone-container/src/main/java/com/yahoo/container/standalone/StandaloneSubscriberFactory.java b/standalone-container/src/main/java/com/yahoo/container/standalone/StandaloneSubscriberFactory.java index 7b23f190daa..e9d8dbd3642 100644 --- a/standalone-container/src/main/java/com/yahoo/container/standalone/StandaloneSubscriberFactory.java +++ b/standalone-container/src/main/java/com/yahoo/container/standalone/StandaloneSubscriberFactory.java @@ -20,6 +20,7 @@ import java.util.Set; * @author ollivir */ public class StandaloneSubscriberFactory implements SubscriberFactory { + private final VespaModel root; public StandaloneSubscriberFactory(VespaModel root) { @@ -57,7 +58,7 @@ public class StandaloneSubscriberFactory implements SubscriberFactory { } @Override - public long waitNextGeneration() { + public long waitNextGeneration(boolean isInitializing) { generation++; if (generation != 0) { |