Charles Chan
Committed by Gerrit Code Review

Passing current and previous config value in NetworkConfigEvent

Change-Id: I4ed16f17b5fc991594d1b83b6c0ffca7aa2130fa
...@@ -32,6 +32,7 @@ import java.util.Set; ...@@ -32,6 +32,7 @@ import java.util.Set;
32 import java.util.function.Function; 32 import java.util.function.Function;
33 33
34 import static com.google.common.base.Preconditions.checkNotNull; 34 import static com.google.common.base.Preconditions.checkNotNull;
35 +import static com.google.common.base.Preconditions.checkState;
35 36
36 /** 37 /**
37 * Base abstraction of a configuration facade for a specific subject. Derived 38 * Base abstraction of a configuration facade for a specific subject. Derived
...@@ -77,17 +78,17 @@ public abstract class Config<S> { ...@@ -77,17 +78,17 @@ public abstract class Config<S> {
77 * @param key configuration key 78 * @param key configuration key
78 * @param node JSON node where configuration data is stored 79 * @param node JSON node where configuration data is stored
79 * @param mapper JSON object mapper 80 * @param mapper JSON object mapper
80 - * @param delegate delegate context 81 + * @param delegate delegate context, or null for detached configs.
81 */ 82 */
82 - public void init(S subject, String key, JsonNode node, ObjectMapper mapper, 83 + public final void init(S subject, String key, JsonNode node, ObjectMapper mapper,
83 ConfigApplyDelegate delegate) { 84 ConfigApplyDelegate delegate) {
84 - this.subject = checkNotNull(subject); 85 + this.subject = checkNotNull(subject, "Subject cannot be null");
85 this.key = key; 86 this.key = key;
86 - this.node = checkNotNull(node); 87 + this.node = checkNotNull(node, "Node cannot be null");
87 this.object = node instanceof ObjectNode ? (ObjectNode) node : null; 88 this.object = node instanceof ObjectNode ? (ObjectNode) node : null;
88 this.array = node instanceof ArrayNode ? (ArrayNode) node : null; 89 this.array = node instanceof ArrayNode ? (ArrayNode) node : null;
89 - this.mapper = checkNotNull(mapper); 90 + this.mapper = checkNotNull(mapper, "Mapper cannot be null");
90 - this.delegate = checkNotNull(delegate); 91 + this.delegate = delegate;
91 } 92 }
92 93
93 /** 94 /**
...@@ -144,12 +145,14 @@ public abstract class Config<S> { ...@@ -144,12 +145,14 @@ public abstract class Config<S> {
144 145
145 /** 146 /**
146 * Applies any configuration changes made via this configuration. 147 * Applies any configuration changes made via this configuration.
148 + *
149 + * Not effective for detached configs.
147 */ 150 */
148 public void apply() { 151 public void apply() {
152 + checkState(delegate != null, "Cannot apply detached config");
149 delegate.onApply(this); 153 delegate.onApply(this);
150 } 154 }
151 155
152 -
153 // Miscellaneous helpers for interacting with JSON 156 // Miscellaneous helpers for interacting with JSON
154 157
155 /** 158 /**
......
...@@ -15,14 +15,21 @@ ...@@ -15,14 +15,21 @@
15 */ 15 */
16 package org.onosproject.net.config; 16 package org.onosproject.net.config;
17 17
18 +import org.joda.time.LocalDateTime;
18 import org.onosproject.event.AbstractEvent; 19 import org.onosproject.event.AbstractEvent;
19 20
21 +import java.util.Optional;
22 +
23 +import static com.google.common.base.MoreObjects.toStringHelper;
24 +
20 /** 25 /**
21 * Describes network configuration event. 26 * Describes network configuration event.
22 */ 27 */
23 public class NetworkConfigEvent extends AbstractEvent<NetworkConfigEvent.Type, Object> { 28 public class NetworkConfigEvent extends AbstractEvent<NetworkConfigEvent.Type, Object> {
24 29
25 private final Class configClass; 30 private final Class configClass;
31 + private final Config config;
32 + private final Config prevConfig;
26 33
27 /** 34 /**
28 * Type of network configuration events. 35 * Type of network configuration events.
...@@ -65,6 +72,8 @@ public class NetworkConfigEvent extends AbstractEvent<NetworkConfigEvent.Type, O ...@@ -65,6 +72,8 @@ public class NetworkConfigEvent extends AbstractEvent<NetworkConfigEvent.Type, O
65 public NetworkConfigEvent(Type type, Object subject, Class configClass) { 72 public NetworkConfigEvent(Type type, Object subject, Class configClass) {
66 super(type, subject); 73 super(type, subject);
67 this.configClass = configClass; 74 this.configClass = configClass;
75 + this.config = null;
76 + this.prevConfig = null;
68 } 77 }
69 78
70 /** 79 /**
...@@ -78,6 +87,26 @@ public class NetworkConfigEvent extends AbstractEvent<NetworkConfigEvent.Type, O ...@@ -78,6 +87,26 @@ public class NetworkConfigEvent extends AbstractEvent<NetworkConfigEvent.Type, O
78 public NetworkConfigEvent(Type type, Object subject, Class configClass, long time) { 87 public NetworkConfigEvent(Type type, Object subject, Class configClass, long time) {
79 super(type, subject, time); 88 super(type, subject, time);
80 this.configClass = configClass; 89 this.configClass = configClass;
90 + this.config = null;
91 + this.prevConfig = null;
92 + }
93 +
94 + /**
95 + * Creates an event of a given type and for the specified subject,
96 + * previous config and time.
97 + *
98 + * @param type device event type
99 + * @param subject event subject
100 + * @param configClass configuration class
101 + * @param config current config
102 + * @param prevConfig previous config
103 + */
104 + public NetworkConfigEvent(Type type, Object subject, Config config,
105 + Config prevConfig, Class configClass) {
106 + super(type, subject);
107 + this.configClass = configClass;
108 + this.config = config;
109 + this.prevConfig = prevConfig;
81 } 110 }
82 111
83 /** 112 /**
...@@ -89,4 +118,34 @@ public class NetworkConfigEvent extends AbstractEvent<NetworkConfigEvent.Type, O ...@@ -89,4 +118,34 @@ public class NetworkConfigEvent extends AbstractEvent<NetworkConfigEvent.Type, O
89 return configClass; 118 return configClass;
90 } 119 }
91 120
121 + /**
122 + * Returns current config.
123 + *
124 + * @return current config; value presents only when the type is
125 + * CONFIG_ADDED or CONFIG_UPDATED
126 + */
127 + public Optional<Config> config() {
128 + return (config != null) ? Optional.of(config) : Optional.empty();
129 + }
130 +
131 + /**
132 + * Returns previous config.
133 + *
134 + * @return previous config; value presents only when the type is
135 + * CONFIG_UPDATED or CONFIG_REMOVED
136 + */
137 + public Optional<Config> prevConfig() {
138 + return (prevConfig != null) ? Optional.of(prevConfig) : Optional.empty();
139 + }
140 +
141 + @Override
142 + public String toString() {
143 + return toStringHelper(this)
144 + .add("time", new LocalDateTime(time()))
145 + .add("type", type())
146 + .add("config", config())
147 + .add("prevConfig", prevConfig())
148 + .add("configClass", configClass())
149 + .toString();
150 + }
92 } 151 }
......
...@@ -267,6 +267,33 @@ public class DistributedNetworkConfigStore ...@@ -267,6 +267,33 @@ public class DistributedNetworkConfigStore
267 return null; 267 return null;
268 } 268 }
269 269
270 + /**
271 + * Produces a detached config from the specified subject, config class and
272 + * raw JSON.
273 + *
274 + * A detached config can no longer be applied. This should be used only for
275 + * passing the config object in the NetworkConfigEvent.
276 + *
277 + * @param subject config subject
278 + * @param configClass config class
279 + * @param json raw JSON data
280 + * @return config object or null of no factory found or if the specified
281 + * JSON is null
282 + */
283 + @SuppressWarnings("unchecked")
284 + private Config createDetachedConfig(Object subject,
285 + Class configClass, JsonNode json) {
286 + if (json != null) {
287 + ConfigFactory factory = factoriesByConfig.get(configClass.getName());
288 + if (factory != null) {
289 + Config config = factory.createConfig();
290 + config.init(subject, factory.configKey(), json, mapper, null);
291 + return config;
292 + }
293 + }
294 + return null;
295 + }
296 +
270 297
271 // Auxiliary delegate to receive notifications about changes applied to 298 // Auxiliary delegate to receive notifications about changes applied to
272 // the network configuration - by the apps. 299 // the network configuration - by the apps.
...@@ -336,6 +363,20 @@ public class DistributedNetworkConfigStore ...@@ -336,6 +363,20 @@ public class DistributedNetworkConfigStore
336 return; 363 return;
337 } 364 }
338 365
366 + ConfigFactory factory = factoriesByConfig.get(event.key().configClass);
367 + if (factory != null) {
368 + Object subject = event.key().subject;
369 + Class configClass = factory.configClass();
370 + Versioned<JsonNode> newValue = event.newValue();
371 + Versioned<JsonNode> oldValue = event.oldValue();
372 +
373 + Config config = (newValue != null) ?
374 + createDetachedConfig(subject, configClass, newValue.value()) :
375 + null;
376 + Config prevConfig = (oldValue != null) ?
377 + createDetachedConfig(subject, configClass, oldValue.value()) :
378 + null;
379 +
339 NetworkConfigEvent.Type type; 380 NetworkConfigEvent.Type type;
340 switch (event.type()) { 381 switch (event.type()) {
341 case INSERT: 382 case INSERT:
...@@ -349,10 +390,8 @@ public class DistributedNetworkConfigStore ...@@ -349,10 +390,8 @@ public class DistributedNetworkConfigStore
349 type = CONFIG_REMOVED; 390 type = CONFIG_REMOVED;
350 break; 391 break;
351 } 392 }
352 - ConfigFactory factory = factoriesByConfig.get(event.key().configClass);
353 - if (factory != null) {
354 notifyDelegate(new NetworkConfigEvent(type, event.key().subject, 393 notifyDelegate(new NetworkConfigEvent(type, event.key().subject,
355 - factory.configClass())); 394 + config, prevConfig, factory.configClass()));
356 } 395 }
357 } 396 }
358 } 397 }
......