--- /dev/null
+/*
+ * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.cluster.datastore.config;
+
+import static java.util.Objects.requireNonNull;
+
+import com.typesafe.config.Config;
+import com.typesafe.config.ConfigFactory;
+import com.typesafe.config.ConfigObject;
+import java.io.File;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import org.opendaylight.controller.cluster.access.concepts.MemberName;
+import org.opendaylight.controller.cluster.datastore.shardstrategy.ShardStrategyFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+abstract class AbstractModuleShardConfigProvider implements ModuleShardConfigProvider {
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractModuleShardConfigProvider.class);
+
+ static final Config loadConfigFromPath(final String configPath) {
+ final File configFile = new File(configPath);
+ Config config = null;
+ if (configFile.exists()) {
+ LOG.info("Config file exists - reading config from it");
+ config = ConfigFactory.parseFile(configFile);
+ } else {
+ LOG.warn("Reading Config from resource");
+ config = ConfigFactory.load(configPath);
+ }
+ return config;
+ }
+
+ static final void readModulesConfig(final Config modulesConfig,
+ final Map<String, ModuleConfig.Builder> moduleConfigMap, final Configuration configuration) {
+ for (final ConfigObject o : modulesConfig.getObjectList("modules")) {
+ final ConfigObjectWrapper wrapper = new ConfigObjectWrapper(o);
+
+ final String moduleName = wrapper.stringValue("name");
+ final ModuleConfig.Builder builder = moduleConfigMap.computeIfAbsent(moduleName, ModuleConfig::builder);
+
+ builder.nameSpace(wrapper.stringValue("namespace"));
+ builder.shardStrategy(ShardStrategyFactory.newShardStrategyInstance(moduleName,
+ wrapper.stringValue("shard-strategy"), configuration));
+ }
+ }
+
+ static final Map<String, ModuleConfig.Builder> readModuleShardsConfig(final Config moduleShardsConfig) {
+ final Map<String, ModuleConfig.Builder> moduleConfigMap = new HashMap<>();
+ for (final ConfigObject moduleShardConfigObject : moduleShardsConfig.getObjectList("module-shards")) {
+ final String moduleName = moduleShardConfigObject.get("name").unwrapped().toString();
+ final ModuleConfig.Builder builder = ModuleConfig.builder(moduleName);
+
+ for (final ConfigObject shard : moduleShardConfigObject.toConfig().getObjectList("shards")) {
+ final String shardName = shard.get("name").unwrapped().toString();
+ final List<MemberName> replicas = shard.toConfig().getStringList("replicas").stream()
+ .map(MemberName::forName).collect(Collectors.toList());
+ builder.shardConfig(shardName, replicas);
+ }
+
+ moduleConfigMap.put(moduleName, builder);
+ }
+
+ return moduleConfigMap;
+ }
+
+ private static final class ConfigObjectWrapper {
+ private final ConfigObject configObject;
+
+ ConfigObjectWrapper(final ConfigObject configObject) {
+ this.configObject = requireNonNull(configObject);
+ }
+
+ String stringValue(final String name) {
+ return configObject.get(name).unwrapped().toString();
+ }
+ }
+}
package org.opendaylight.controller.cluster.datastore.config;
import com.typesafe.config.Config;
-import com.typesafe.config.ConfigFactory;
-import com.typesafe.config.ConfigObject;
-import java.io.File;
-import java.util.HashMap;
-import java.util.List;
import java.util.Map;
-import java.util.stream.Collectors;
-import org.opendaylight.controller.cluster.access.concepts.MemberName;
-import org.opendaylight.controller.cluster.datastore.shardstrategy.ShardStrategyFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* Implementation of ModuleShardConfigProvider that reads the module and shard configuration from files.
*
* @author Thomas Pantelis
*/
-public class FileModuleShardConfigProvider implements ModuleShardConfigProvider {
- private static final Logger LOG = LoggerFactory.getLogger(FileModuleShardConfigProvider.class);
-
+public class FileModuleShardConfigProvider extends AbstractModuleShardConfigProvider {
private final String moduleShardsConfigPath;
private final String modulesConfigPath;
@Override
public Map<String, ModuleConfig.Builder> retrieveModuleConfigs(final Configuration configuration) {
- final File moduleShardsFile = new File(moduleShardsConfigPath);
- final File modulesFile = new File(modulesConfigPath);
-
- Config moduleShardsConfig = null;
- if (moduleShardsFile.exists()) {
- LOG.info("module shards config file exists - reading config from it");
- moduleShardsConfig = ConfigFactory.parseFile(moduleShardsFile);
- } else {
- LOG.warn("module shards configuration read from resource");
- moduleShardsConfig = ConfigFactory.load(moduleShardsConfigPath);
- }
-
- Config modulesConfig = null;
- if (modulesFile.exists()) {
- LOG.info("modules config file exists - reading config from it");
- modulesConfig = ConfigFactory.parseFile(modulesFile);
- } else {
- LOG.warn("modules configuration read from resource");
- modulesConfig = ConfigFactory.load(modulesConfigPath);
- }
+ Config moduleShardsConfig = loadConfigFromPath(moduleShardsConfigPath);
+ Config modulesConfig = loadConfigFromPath(modulesConfigPath);
final Map<String, ModuleConfig.Builder> moduleConfigMap = readModuleShardsConfig(moduleShardsConfig);
readModulesConfig(modulesConfig, moduleConfigMap, configuration);
-
- return moduleConfigMap;
- }
-
- private static void readModulesConfig(final Config modulesConfig,
- final Map<String, ModuleConfig.Builder> moduleConfigMap, final Configuration configuration) {
- final List<? extends ConfigObject> modulesConfigObjectList = modulesConfig.getObjectList("modules");
-
- for (final ConfigObject o : modulesConfigObjectList) {
- final ConfigObjectWrapper wrapper = new ConfigObjectWrapper(o);
-
- final String moduleName = wrapper.stringValue("name");
- final ModuleConfig.Builder builder = moduleConfigMap.computeIfAbsent(moduleName, ModuleConfig::builder);
-
- builder.nameSpace(wrapper.stringValue("namespace"));
- builder.shardStrategy(ShardStrategyFactory.newShardStrategyInstance(moduleName,
- wrapper.stringValue("shard-strategy"), configuration));
- }
- }
-
- private static Map<String, ModuleConfig.Builder> readModuleShardsConfig(final Config moduleShardsConfig) {
- final List<? extends ConfigObject> moduleShardsConfigObjectList =
- moduleShardsConfig.getObjectList("module-shards");
-
- final Map<String, ModuleConfig.Builder> moduleConfigMap = new HashMap<>();
- for (final ConfigObject moduleShardConfigObject : moduleShardsConfigObjectList) {
- final String moduleName = moduleShardConfigObject.get("name").unwrapped().toString();
- final ModuleConfig.Builder builder = ModuleConfig.builder(moduleName);
-
- final List<? extends ConfigObject> shardsConfigObjectList =
- moduleShardConfigObject.toConfig().getObjectList("shards");
-
- for (final ConfigObject shard : shardsConfigObjectList) {
- final String shardName = shard.get("name").unwrapped().toString();
- final List<MemberName> replicas = shard.toConfig().getStringList("replicas").stream()
- .map(MemberName::forName).collect(Collectors.toList());
- builder.shardConfig(shardName, replicas);
- }
-
- moduleConfigMap.put(moduleName, builder);
- }
-
return moduleConfigMap;
}
-
- private static class ConfigObjectWrapper {
-
- private final ConfigObject configObject;
-
- ConfigObjectWrapper(final ConfigObject configObject) {
- this.configObject = configObject;
- }
-
- public String stringValue(final String name) {
- return configObject.get(name).unwrapped().toString();
- }
- }
}
--- /dev/null
+/*
+ * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.cluster.datastore.config;
+
+import static java.util.Objects.requireNonNull;
+
+import com.typesafe.config.Config;
+import java.util.Map;
+
+public class HybridModuleShardConfigProvider extends AbstractModuleShardConfigProvider {
+ private final Config moduleShardsConfig;
+ private final String modulesConfigPath;
+
+ public HybridModuleShardConfigProvider(final Config moduleShardsConfig, final String modulesConfigPath) {
+ this.moduleShardsConfig = requireNonNull(moduleShardsConfig, "ModuleShardsConfig can't be null");
+ this.modulesConfigPath = modulesConfigPath;
+ }
+
+ @Override
+ public Map<String, ModuleConfig.Builder> retrieveModuleConfigs(final Configuration configuration) {
+ Config modulesConfig = loadConfigFromPath(modulesConfigPath);
+
+ final Map<String, ModuleConfig.Builder> moduleConfigMap = readModuleShardsConfig(this.moduleShardsConfig);
+ readModulesConfig(modulesConfig, moduleConfigMap, configuration);
+ return moduleConfigMap;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014, 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.cluster.datastore.config;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import com.google.common.collect.ImmutableSortedSet;
+import com.google.common.collect.Sets;
+import java.net.URI;
+import java.util.Collection;
+import java.util.Set;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.access.concepts.MemberName;
+import org.opendaylight.controller.cluster.datastore.shardstrategy.ModuleShardStrategy;
+import org.opendaylight.controller.cluster.datastore.shardstrategy.ShardStrategy;
+
+public abstract class ConfigurationImplBaseTest {
+ private static final MemberName MEMBER_1 = MemberName.forName("member-1");
+ private static final MemberName MEMBER_2 = MemberName.forName("member-2");
+ private static final MemberName MEMBER_3 = MemberName.forName("member-3");
+ private static final MemberName MEMBER_4 = MemberName.forName("member-4");
+ private static final MemberName MEMBER_5 = MemberName.forName("member-5");
+ private static final MemberName MEMBER_100 = MemberName.forName("member-100");
+
+ private ConfigurationImpl configuration;
+
+ @Before
+ public void setup() {
+ this.configuration = createConfiguration();
+ }
+
+ public abstract ConfigurationImpl createConfiguration();
+
+ @Test
+ public void testConstructor() {
+ Assert.assertNotNull(configuration);
+ }
+
+ @Test
+ public void testGetMemberShardNames() {
+ Collection<String> memberShardNames = configuration.getMemberShardNames(MEMBER_1);
+ assertEquals("getMemberShardNames", ImmutableSortedSet.of("people-1", "cars-1", "test-1", "default"),
+ ImmutableSortedSet.copyOf(memberShardNames));
+
+ memberShardNames = configuration.getMemberShardNames(MEMBER_2);
+ assertEquals("getMemberShardNames", ImmutableSortedSet.of("default"),
+ ImmutableSortedSet.copyOf(memberShardNames));
+
+ memberShardNames = configuration.getMemberShardNames(MEMBER_100);
+ assertEquals("getMemberShardNames size", 0, memberShardNames.size());
+ }
+
+ @Test
+ public void testGetMembersFromShardName() {
+ Collection<MemberName> members = configuration.getMembersFromShardName("default");
+ assertEquals("getMembersFromShardName", ImmutableSortedSet.of(MEMBER_1, MEMBER_2, MEMBER_3),
+ ImmutableSortedSet.copyOf(members));
+
+ members = configuration.getMembersFromShardName("cars-1");
+ assertEquals("getMembersFromShardName", ImmutableSortedSet.of(MEMBER_1),
+ ImmutableSortedSet.copyOf(members));
+
+ // Try to find a shard which is not present
+
+ members = configuration.getMembersFromShardName("foobar");
+ assertEquals("getMembersFromShardName size", 0, members.size());
+ }
+
+ @Test
+ public void testGetAllShardNames() {
+ Set<String> allShardNames = configuration.getAllShardNames();
+ assertEquals("getAllShardNames", ImmutableSortedSet.of("people-1", "cars-1", "test-1", "default"),
+ ImmutableSortedSet.copyOf(allShardNames));
+ }
+
+ @Test
+ public void testGetModuleNameFromNameSpace() {
+ String moduleName = configuration.getModuleNameFromNameSpace(
+ "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test:cars");
+ assertEquals("getModuleNameFromNameSpace", "cars", moduleName);
+
+ moduleName = configuration.getModuleNameFromNameSpace(
+ "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test");
+ assertEquals("getModuleNameFromNameSpace", "test", moduleName);
+
+ moduleName = configuration.getModuleNameFromNameSpace("non-existent");
+ assertNull("getModuleNameFromNameSpace - expected null", moduleName);
+ }
+
+ @Test
+ public void testGetStrategyForModule() {
+ ShardStrategy strategy = configuration.getStrategyForModule("cars");
+ assertNotNull("getStrategyForModule null", strategy);
+ assertEquals("getStrategyForModule type", ModuleShardStrategy.class, strategy.getClass());
+
+ strategy = configuration.getStrategyForModule("people");
+ assertNotNull("getStrategyForModule null", strategy);
+ assertEquals("getStrategyForModule type", ModuleShardStrategy.class, strategy.getClass());
+
+ strategy = configuration.getStrategyForModule("default");
+ assertNull("getStrategyForModule - expected null", strategy);
+
+ strategy = configuration.getStrategyForModule("non-existent");
+ assertNull("getStrategyForModule - expected null", strategy);
+ }
+
+ @Test
+ public void testGetShardNameForModule() {
+ String shardName = configuration.getShardNameForModule("cars");
+ assertEquals("getShardNameForModule", "cars-1", shardName);
+
+ shardName = configuration.getShardNameForModule("people");
+ assertEquals("getShardNameForModule", "people-1", shardName);
+
+ shardName = configuration.getShardNameForModule("non-existent");
+ assertNull("getShardNameForModule - expected null", shardName);
+ }
+
+ @Test
+ public void testAddModuleShardConfiguration() throws Exception {
+ URI namespace = new URI("urn:opendaylight:test:oven");
+ String moduleName = "oven";
+ String shardName = "oven-shard";
+ String shardStrategyName = ModuleShardStrategy.NAME;
+ Collection<MemberName> shardMemberNames = ImmutableSortedSet.of(MEMBER_1, MEMBER_4, MEMBER_5);
+
+ configuration.addModuleShardConfiguration(new ModuleShardConfiguration(namespace, moduleName, shardName,
+ shardStrategyName, shardMemberNames));
+
+ assertEquals("getMemberShardNames", ImmutableSortedSet.of("people-1", "cars-1", "test-1", "default", shardName),
+ ImmutableSortedSet.copyOf(configuration.getMemberShardNames(MEMBER_1)));
+ assertEquals("getMemberShardNames", ImmutableSortedSet.of(shardName),
+ ImmutableSortedSet.copyOf(configuration.getMemberShardNames(MEMBER_4)));
+ assertEquals("getMemberShardNames", ImmutableSortedSet.of(shardName),
+ ImmutableSortedSet.copyOf(configuration.getMemberShardNames(MEMBER_5)));
+ assertEquals("getMembersFromShardName", shardMemberNames,
+ ImmutableSortedSet.copyOf(configuration.getMembersFromShardName(shardName)));
+ assertEquals("getShardNameForModule", shardName, configuration.getShardNameForModule(moduleName));
+ assertEquals("getModuleNameFromNameSpace", moduleName,
+ configuration.getModuleNameFromNameSpace(namespace.toASCIIString()));
+ assertEquals("getAllShardNames", ImmutableSortedSet.of("people-1", "cars-1", "test-1", "default", shardName),
+ ImmutableSortedSet.copyOf(configuration.getAllShardNames()));
+
+ ShardStrategy strategy = configuration.getStrategyForModule("cars");
+ assertNotNull("getStrategyForModule null", strategy);
+ assertEquals("getStrategyForModule type", ModuleShardStrategy.class, strategy.getClass());
+ }
+
+ @Test
+ public void testGetUniqueMemberNamesForAllShards() {
+ assertEquals("getUniqueMemberNamesForAllShards", Sets.newHashSet(MEMBER_1, MEMBER_2, MEMBER_3),
+ configuration.getUniqueMemberNamesForAllShards());
+ }
+
+ @Test
+ public void testAddMemberReplicaForShard() {
+ configuration.addMemberReplicaForShard("people-1", MEMBER_2);
+ String shardName = configuration.getShardNameForModule("people");
+ assertEquals("ModuleShardName", "people-1", shardName);
+ ShardStrategy shardStrategy = configuration.getStrategyForModule("people");
+ assertEquals("ModuleStrategy", ModuleShardStrategy.class, shardStrategy.getClass());
+ Collection<MemberName> members = configuration.getMembersFromShardName("people-1");
+ assertEquals("Members", ImmutableSortedSet.of(MEMBER_1, MEMBER_2),
+ ImmutableSortedSet.copyOf(members));
+
+ configuration.addMemberReplicaForShard("non-existent", MEMBER_2);
+ Set<String> shardNames = configuration.getAllShardNames();
+ assertEquals("ShardNames", ImmutableSortedSet.of("people-1", "cars-1", "test-1", "default"),
+ ImmutableSortedSet.copyOf(shardNames));
+ }
+
+ @Test
+ public void testRemoveMemberReplicaForShard() {
+ configuration.removeMemberReplicaForShard("default", MEMBER_2);
+ String shardName = configuration.getShardNameForModule("default");
+ assertEquals("ModuleShardName", "default", shardName);
+ ShardStrategy shardStrategy = configuration.getStrategyForModule("default");
+ assertNull("ModuleStrategy", shardStrategy);
+ Collection<MemberName> members = configuration.getMembersFromShardName("default");
+ assertEquals("Members", ImmutableSortedSet.of(MEMBER_1, MEMBER_3),
+ ImmutableSortedSet.copyOf(members));
+
+ configuration.removeMemberReplicaForShard("non-existent", MEMBER_2);
+ Set<String> shardNames = configuration.getAllShardNames();
+ assertEquals("ShardNames", ImmutableSortedSet.of("people-1", "cars-1", "test-1", "default"),
+ ImmutableSortedSet.copyOf(shardNames));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014, 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.cluster.datastore.config;
+
+public class ConfigurationImplFileTest extends ConfigurationImplBaseTest {
+
+ @Override
+ public ConfigurationImpl createConfiguration() {
+ return new ConfigurationImpl("module-shards.conf", "modules.conf");
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.cluster.datastore.config;
+
+import com.typesafe.config.Config;
+import com.typesafe.config.ConfigFactory;
+import java.util.List;
+import org.junit.Test;
+
+public class ConfigurationImplHybridTest extends ConfigurationImplBaseTest {
+
+ @Override
+ public ConfigurationImpl createConfiguration() {
+ Config moduleShardsConf = generateModuleShards(List.of(
+ generateShard("default", "default", List.of("member-1", "member-2", "member-3")),
+ generateShard("people", "people-1", List.of("member-1")),
+ generateShard("cars", "cars-1", List.of("member-1")),
+ generateShard("test", "test-1", List.of("member-1"))
+ ));
+ return new ConfigurationImpl(new HybridModuleShardConfigProvider(moduleShardsConf, "modules.conf"));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testNullModuleShardsConf() {
+ new HybridModuleShardConfigProvider(null, "modules.conf");
+ }
+
+ private static Config generateModuleShards(final List<String> shards) {
+ String moduleShardsContent = String.format("module-shards = [%n%s]", String.join(",\n", shards));
+ return ConfigFactory.parseString(moduleShardsContent);
+ }
+
+ private static String generateShard(final String name, final String shardsName, final List<String> replicas) {
+ return " {"
+ + " name = \"" + name + "\"\n"
+ + " shards = [\n"
+ + " {\n"
+ + " name=\"" + shardsName + "\"\n"
+ + " replicas = " + replicas
+ + " \n"
+ + " }\n"
+ + " ]\n"
+ + " }";
+ }
+}
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-
package org.opendaylight.controller.cluster.datastore.config;
import static org.junit.Assert.assertEquals;