Thomas Vachuska
Committed by Gerrit Code Review

ONOS-4129 Fixing issue where two pending configurations with the same config key…

…, but for two different subject classes are encountered.

Change-Id: I4de7f6e22bdf038dff91630f4cf576d9c38e9807
...@@ -29,7 +29,6 @@ import com.fasterxml.jackson.databind.node.ShortNode; ...@@ -29,7 +29,6 @@ import com.fasterxml.jackson.databind.node.ShortNode;
29 import com.fasterxml.jackson.databind.node.TextNode; 29 import com.fasterxml.jackson.databind.node.TextNode;
30 import com.google.common.collect.ImmutableSet; 30 import com.google.common.collect.ImmutableSet;
31 import com.google.common.collect.Maps; 31 import com.google.common.collect.Maps;
32 -import com.google.common.collect.Sets;
33 import org.apache.felix.scr.annotations.Activate; 32 import org.apache.felix.scr.annotations.Activate;
34 import org.apache.felix.scr.annotations.Component; 33 import org.apache.felix.scr.annotations.Component;
35 import org.apache.felix.scr.annotations.Deactivate; 34 import org.apache.felix.scr.annotations.Deactivate;
...@@ -124,14 +123,18 @@ public class DistributedNetworkConfigStore ...@@ -124,14 +123,18 @@ public class DistributedNetworkConfigStore
124 123
125 // Sweep through any pending configurations, validate them and then prune them. 124 // Sweep through any pending configurations, validate them and then prune them.
126 private void processPendingConfigs(ConfigFactory configFactory) { 125 private void processPendingConfigs(ConfigFactory configFactory) {
127 - Set<ConfigKey> toBePruned = Sets.newHashSet(); 126 + ImmutableSet.copyOf(configs.keySet()).forEach(k -> {
128 - configs.keySet().forEach(k -> { 127 + if (Objects.equals(k.configKey, configFactory.configKey()) &&
129 - if (Objects.equals(k.configKey, configFactory.configKey())) { 128 + isAssignableFrom(configFactory, k)) {
130 validateConfig(k, configFactory, configs.get(k).value()); 129 validateConfig(k, configFactory, configs.get(k).value());
131 - toBePruned.add(k); // Prune whether valid or not 130 + configs.remove(k); // Prune whether valid or not
132 } 131 }
133 }); 132 });
134 - toBePruned.forEach(configs::remove); 133 + }
134 +
135 + @SuppressWarnings("unchecked")
136 + private boolean isAssignableFrom(ConfigFactory configFactory, ConfigKey k) {
137 + return configFactory.subjectFactory().subjectClass().isAssignableFrom(k.subject.getClass());
135 } 138 }
136 139
137 @SuppressWarnings("unchecked") 140 @SuppressWarnings("unchecked")
......
...@@ -59,6 +59,11 @@ public class DistributedNetworkConfigStoreTest { ...@@ -59,6 +59,11 @@ public class DistributedNetworkConfigStoreTest {
59 public class BasicConfig extends Config<String> { } 59 public class BasicConfig extends Config<String> { }
60 60
61 /** 61 /**
62 + * Config class for testing.
63 + */
64 + public class BasicIntConfig extends Config<Integer> { }
65 +
66 + /**
62 * Config factory class for testing. 67 * Config factory class for testing.
63 */ 68 */
64 public class MockConfigFactory extends ConfigFactory<String, BasicConfig> { 69 public class MockConfigFactory extends ConfigFactory<String, BasicConfig> {
...@@ -72,6 +77,19 @@ public class DistributedNetworkConfigStoreTest { ...@@ -72,6 +77,19 @@ public class DistributedNetworkConfigStoreTest {
72 } 77 }
73 78
74 /** 79 /**
80 + * Config factory class for testing.
81 + */
82 + public class MockIntConfigFactory extends ConfigFactory<Integer, BasicIntConfig> {
83 + protected MockIntConfigFactory(Class<BasicIntConfig> configClass, String configKey) {
84 + super(new MockIntSubjectFactory("strings"), configClass, configKey);
85 + }
86 + @Override
87 + public BasicIntConfig createConfig() {
88 + return new BasicIntConfig();
89 + }
90 + }
91 +
92 + /**
75 * Subject factory class for testing. 93 * Subject factory class for testing.
76 */ 94 */
77 public class MockSubjectFactory extends SubjectFactory<String> { 95 public class MockSubjectFactory extends SubjectFactory<String> {
...@@ -86,6 +104,19 @@ public class DistributedNetworkConfigStoreTest { ...@@ -86,6 +104,19 @@ public class DistributedNetworkConfigStoreTest {
86 } 104 }
87 105
88 /** 106 /**
107 + * Subject factory class for testing.
108 + */
109 + public class MockIntSubjectFactory extends SubjectFactory<Integer> {
110 + protected MockIntSubjectFactory(String subjectClassKey) {
111 + super(Integer.class, subjectClassKey);
112 + }
113 +
114 + @Override
115 + public Integer createSubject(String subjectKey) {
116 + return Integer.parseInt(subjectKey);
117 + }
118 + }
119 + /**
89 * Tests creation, query and removal of a config. 120 * Tests creation, query and removal of a config.
90 */ 121 */
91 @Test 122 @Test
...@@ -132,9 +163,44 @@ public class DistributedNetworkConfigStoreTest { ...@@ -132,9 +163,44 @@ public class DistributedNetworkConfigStoreTest {
132 public void testApplyConfig() { 163 public void testApplyConfig() {
133 configStore.addConfigFactory(new MockConfigFactory(BasicConfig.class, "config1")); 164 configStore.addConfigFactory(new MockConfigFactory(BasicConfig.class, "config1"));
134 165
135 - configStore.applyConfig("config1", BasicConfig.class, new ObjectMapper().createObjectNode()); 166 + configStore.applyConfig("subject", BasicConfig.class, new ObjectMapper().createObjectNode());
136 - assertThat(configStore.getConfigClasses("config1"), hasSize(1)); 167 + assertThat(configStore.getConfigClasses("subject"), hasSize(1));
137 assertThat(configStore.getSubjects(String.class, BasicConfig.class), hasSize(1)); 168 assertThat(configStore.getSubjects(String.class, BasicConfig.class), hasSize(1));
138 assertThat(configStore.getSubjects(String.class), hasSize(1)); 169 assertThat(configStore.getSubjects(String.class), hasSize(1));
139 } 170 }
171 +
172 + /**
173 + * Tests inserting a pending configuration.
174 + */
175 + @Test
176 + public void testPendingConfig() {
177 + configStore.queueConfig("subject", "config1", new ObjectMapper().createObjectNode());
178 + configStore.addConfigFactory(new MockConfigFactory(BasicConfig.class, "config1"));
179 +
180 + assertThat(configStore.getConfigClasses("subject"), hasSize(1));
181 + assertThat(configStore.getSubjects(String.class, BasicConfig.class), hasSize(1));
182 + assertThat(configStore.getSubjects(String.class), hasSize(1));
183 + }
184 +
185 + /**
186 + * Tests inserting a pending configuration for the same key, different subject.
187 + */
188 + @Test
189 + public void testPendingConfigSameKey() {
190 + configStore.queueConfig("subject", "config1", new ObjectMapper().createObjectNode());
191 + configStore.queueConfig(123, "config1", new ObjectMapper().createObjectNode());
192 + configStore.addConfigFactory(new MockConfigFactory(BasicConfig.class, "config1"));
193 +
194 + assertThat(configStore.getConfigClasses("subject"), hasSize(1));
195 + assertThat(configStore.getConfigClasses(123), hasSize(0));
196 + assertThat(configStore.getSubjects(String.class, BasicConfig.class), hasSize(1));
197 + assertThat(configStore.getSubjects(String.class), hasSize(1));
198 +
199 + configStore.addConfigFactory(new MockIntConfigFactory(BasicIntConfig.class, "config1"));
200 +
201 + assertThat(configStore.getConfigClasses("subject"), hasSize(1));
202 + assertThat(configStore.getConfigClasses(123), hasSize(1));
203 + assertThat(configStore.getSubjects(Integer.class, BasicIntConfig.class), hasSize(1));
204 + assertThat(configStore.getSubjects(Integer.class), hasSize(1));
205 + }
140 } 206 }
......