andrea
Committed by Gerrit Code Review

Simplified component config loader with preset method that sets the configuratio…

…n regardless of the component state

Change-Id: Ia2e987c3b6d15339396737dfa68c6973d714798c
......@@ -63,6 +63,16 @@ public interface ComponentConfigService {
void setProperty(String componentName, String name, String value);
/**
* Presets the value of the specified configuration property, regardless
* of the component's state.
*
* @param componentName component name
* @param name property name
* @param value new property value
*/
void preSetProperty(String componentName, String name, String value);
/**
* Clears the value of the specified configuration property thus making
* the property take on its default value.
*
......@@ -72,3 +82,4 @@ public interface ComponentConfigService {
void unsetProperty(String componentName, String name);
}
......
......@@ -50,6 +50,10 @@ public class ComponentConfigAdapter implements ComponentConfigService {
}
@Override
public void preSetProperty(String componentName, String name, String value) {
}
@Override
public void unsetProperty(String componentName, String name) {
}
......
......@@ -18,19 +18,14 @@ package org.onosproject.cfg.impl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.util.SharedExecutors;
import org.onosproject.cfg.ComponentConfigService;
import org.slf4j.Logger;
import java.io.File;
import java.util.Set;
import java.util.TimerTask;
import static org.slf4j.LoggerFactory.getLogger;
......@@ -44,50 +39,31 @@ public class ComponentConfigLoader {
private static final String CFG_JSON = "../config/component-cfg.json";
static File cfgFile = new File(CFG_JSON);
protected int retryDelay = 5_000; // millis between retries
protected int stopRetryTime = 60_000; // deadline in millis
private final Logger log = getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ComponentConfigService configService;
private ObjectNode root;
private final Set<String> pendingComponents = Sets.newHashSet();
private long initialTimestamp;
// TimerTask object that calls the load configuration for each component
// in the pending components set and cancels itself if the set is empty or
// after a set period of time.
protected final TimerTask loader = new TimerTask() {
@Override
public void run() {
ImmutableSet.copyOf(pendingComponents)
.forEach(k -> loadConfig(k, (ObjectNode) root.path(k)));
if (pendingComponents.isEmpty()
|| System.currentTimeMillis() - initialTimestamp >= stopRetryTime) {
this.cancel();
}
}
};
@Activate
protected void activate() {
initialTimestamp = System.currentTimeMillis();
this.loadConfigs();
log.info("Started");
}
// Loads the configurations for each component from the file in
// ../config/component-cfg.json, adds them to a set and schedules a task
// to try and load them.
// ../config/component-cfg.json, using the preSetProperty method.
private void loadConfigs() {
try {
if (cfgFile.exists()) {
root = (ObjectNode) new ObjectMapper().readTree(cfgFile);
root.fieldNames().forEachRemaining(pendingComponents::add);
SharedExecutors.getTimer().schedule(loader, 0, retryDelay);
root.fieldNames().
forEachRemaining(component -> root.path(component).fieldNames()
.forEachRemaining(k -> configService
.preSetProperty(component, k,
root.path(component).path(k)
.asText())));
log.info("Loaded initial component configuration from {}", cfgFile);
}
} catch (Exception e) {
......@@ -95,15 +71,4 @@ public class ComponentConfigLoader {
cfgFile, e);
}
}
// Loads a configuration for a single component and removes it from the
// components set.
private void loadConfig(String component, ObjectNode config) {
if (configService.getComponentNames().contains(component)) {
config.fieldNames()
.forEachRemaining(k -> configService.setProperty(component, k,
config.path(k).asText()));
pendingComponents.remove(component);
}
}
}
......
......@@ -172,6 +172,17 @@ public class ComponentConfigManager implements ComponentConfigService {
}
@Override
public void preSetProperty(String componentName, String name, String value) {
checkPermission(CONFIG_WRITE);
checkNotNull(componentName, COMPONENT_NULL);
checkNotNull(name, PROPERTY_NULL);
store.setProperty(componentName, name, value);
}
@Override
public void unsetProperty(String componentName, String name) {
checkPermission(CONFIG_WRITE);
......
......@@ -21,17 +21,17 @@ import com.google.common.io.Files;
import org.junit.Before;
import org.junit.Test;
import org.onosproject.cfg.ComponentConfigAdapter;
import org.slf4j.Logger;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Set;
import java.util.TimerTask;
import static com.google.common.io.ByteStreams.toByteArray;
import static com.google.common.io.Files.write;
import static org.junit.Assert.*;
import static org.onlab.junit.TestTools.assertAfter;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.slf4j.LoggerFactory.getLogger;
/**
* UnitTest for ComponentLoader.
......@@ -46,6 +46,8 @@ public class ComponentConfigLoaderTest {
private TestConfigService service;
private final Logger log = getLogger(getClass());
/*
* Method to SetUp the test environment with test file, a config loader a service,
* and assign it to the loader.configService for the test.
......@@ -56,8 +58,6 @@ public class ComponentConfigLoaderTest {
loader = new ComponentConfigLoader();
service = new TestConfigService();
loader.configService = service;
loader.retryDelay = 50;
loader.stopRetryTime = 200;
}
/*
......@@ -67,7 +67,7 @@ public class ComponentConfigLoaderTest {
public void basics() throws IOException {
stageTestResource("basic.json");
loader.activate();
assertAfter(1_000, () -> assertEquals("incorrect component", FOO_COMPONENT, service.component));
assertEquals("incorrect component", FOO_COMPONENT, service.component);
}
/*
......@@ -79,28 +79,7 @@ public class ComponentConfigLoaderTest {
public void badConfig() throws IOException {
stageTestResource("badConfig.json");
loader.activate();
assertAfter(1_000, () -> assertNull("incorrect configuration", service.component));
}
/*
* Tests that tasks stops itself after the stopRetryTime if the component was
* not loaded.
*/
@Test
public void noComponentForConfig() throws IOException {
stageTestResource("badComponent.json");
loader.activate();
assertAfter(loader.stopRetryTime + loader.retryDelay, () -> {
try {
Field state = TimerTask.class.getDeclaredField("state");
state.setAccessible(true);
assertEquals("incorrect component", state.getInt(loader.loader), 3);
} catch (Exception e) {
e.printStackTrace();
fail();
}
});
assertNull("incorrect configuration", service.component);
}
......@@ -117,9 +96,9 @@ public class ComponentConfigLoaderTest {
*/
private class TestConfigService extends ComponentConfigAdapter {
private String component;
private String name;
private String value;
protected String component;
protected String name;
protected String value;
@Override
public Set<String> getComponentNames() {
......@@ -127,7 +106,17 @@ public class ComponentConfigLoaderTest {
}
@Override
public void preSetProperty(String componentName, String name, String value) {
log.info("preSet");
this.component = componentName;
this.name = name;
this.value = value;
}
@Override
public void setProperty(String componentName, String name, String value) {
log.info("Set");
this.component = componentName;
this.name = name;
this.value = value;
......