Passing current and previous config value in NetworkConfigEvent
Change-Id: I4ed16f17b5fc991594d1b83b6c0ffca7aa2130fa
diff --git a/core/api/src/main/java/org/onosproject/net/config/Config.java b/core/api/src/main/java/org/onosproject/net/config/Config.java
index 1e2ee12..58219d2 100644
--- a/core/api/src/main/java/org/onosproject/net/config/Config.java
+++ b/core/api/src/main/java/org/onosproject/net/config/Config.java
@@ -32,6 +32,7 @@
import java.util.function.Function;
import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
/**
* Base abstraction of a configuration facade for a specific subject. Derived
@@ -77,17 +78,17 @@
* @param key configuration key
* @param node JSON node where configuration data is stored
* @param mapper JSON object mapper
- * @param delegate delegate context
+ * @param delegate delegate context, or null for detached configs.
*/
- public void init(S subject, String key, JsonNode node, ObjectMapper mapper,
+ public final void init(S subject, String key, JsonNode node, ObjectMapper mapper,
ConfigApplyDelegate delegate) {
- this.subject = checkNotNull(subject);
+ this.subject = checkNotNull(subject, "Subject cannot be null");
this.key = key;
- this.node = checkNotNull(node);
+ this.node = checkNotNull(node, "Node cannot be null");
this.object = node instanceof ObjectNode ? (ObjectNode) node : null;
this.array = node instanceof ArrayNode ? (ArrayNode) node : null;
- this.mapper = checkNotNull(mapper);
- this.delegate = checkNotNull(delegate);
+ this.mapper = checkNotNull(mapper, "Mapper cannot be null");
+ this.delegate = delegate;
}
/**
@@ -144,12 +145,14 @@
/**
* Applies any configuration changes made via this configuration.
+ *
+ * Not effective for detached configs.
*/
public void apply() {
+ checkState(delegate != null, "Cannot apply detached config");
delegate.onApply(this);
}
-
// Miscellaneous helpers for interacting with JSON
/**
diff --git a/core/api/src/main/java/org/onosproject/net/config/NetworkConfigEvent.java b/core/api/src/main/java/org/onosproject/net/config/NetworkConfigEvent.java
index ee9cead..433eb9d 100644
--- a/core/api/src/main/java/org/onosproject/net/config/NetworkConfigEvent.java
+++ b/core/api/src/main/java/org/onosproject/net/config/NetworkConfigEvent.java
@@ -15,14 +15,21 @@
*/
package org.onosproject.net.config;
+import org.joda.time.LocalDateTime;
import org.onosproject.event.AbstractEvent;
+import java.util.Optional;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
/**
* Describes network configuration event.
*/
public class NetworkConfigEvent extends AbstractEvent<NetworkConfigEvent.Type, Object> {
private final Class configClass;
+ private final Config config;
+ private final Config prevConfig;
/**
* Type of network configuration events.
@@ -65,6 +72,8 @@
public NetworkConfigEvent(Type type, Object subject, Class configClass) {
super(type, subject);
this.configClass = configClass;
+ this.config = null;
+ this.prevConfig = null;
}
/**
@@ -78,6 +87,26 @@
public NetworkConfigEvent(Type type, Object subject, Class configClass, long time) {
super(type, subject, time);
this.configClass = configClass;
+ this.config = null;
+ this.prevConfig = null;
+ }
+
+ /**
+ * Creates an event of a given type and for the specified subject,
+ * previous config and time.
+ *
+ * @param type device event type
+ * @param subject event subject
+ * @param configClass configuration class
+ * @param config current config
+ * @param prevConfig previous config
+ */
+ public NetworkConfigEvent(Type type, Object subject, Config config,
+ Config prevConfig, Class configClass) {
+ super(type, subject);
+ this.configClass = configClass;
+ this.config = config;
+ this.prevConfig = prevConfig;
}
/**
@@ -89,4 +118,34 @@
return configClass;
}
+ /**
+ * Returns current config.
+ *
+ * @return current config; value presents only when the type is
+ * CONFIG_ADDED or CONFIG_UPDATED
+ */
+ public Optional<Config> config() {
+ return (config != null) ? Optional.of(config) : Optional.empty();
+ }
+
+ /**
+ * Returns previous config.
+ *
+ * @return previous config; value presents only when the type is
+ * CONFIG_UPDATED or CONFIG_REMOVED
+ */
+ public Optional<Config> prevConfig() {
+ return (prevConfig != null) ? Optional.of(prevConfig) : Optional.empty();
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("time", new LocalDateTime(time()))
+ .add("type", type())
+ .add("config", config())
+ .add("prevConfig", prevConfig())
+ .add("configClass", configClass())
+ .toString();
+ }
}
diff --git a/core/store/dist/src/main/java/org/onosproject/store/config/impl/DistributedNetworkConfigStore.java b/core/store/dist/src/main/java/org/onosproject/store/config/impl/DistributedNetworkConfigStore.java
index d0a9920..4a31aff 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/config/impl/DistributedNetworkConfigStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/config/impl/DistributedNetworkConfigStore.java
@@ -267,6 +267,33 @@
return null;
}
+ /**
+ * Produces a detached config from the specified subject, config class and
+ * raw JSON.
+ *
+ * A detached config can no longer be applied. This should be used only for
+ * passing the config object in the NetworkConfigEvent.
+ *
+ * @param subject config subject
+ * @param configClass config class
+ * @param json raw JSON data
+ * @return config object or null of no factory found or if the specified
+ * JSON is null
+ */
+ @SuppressWarnings("unchecked")
+ private Config createDetachedConfig(Object subject,
+ Class configClass, JsonNode json) {
+ if (json != null) {
+ ConfigFactory factory = factoriesByConfig.get(configClass.getName());
+ if (factory != null) {
+ Config config = factory.createConfig();
+ config.init(subject, factory.configKey(), json, mapper, null);
+ return config;
+ }
+ }
+ return null;
+ }
+
// Auxiliary delegate to receive notifications about changes applied to
// the network configuration - by the apps.
@@ -336,23 +363,35 @@
return;
}
- NetworkConfigEvent.Type type;
- switch (event.type()) {
- case INSERT:
- type = CONFIG_ADDED;
- break;
- case UPDATE:
- type = CONFIG_UPDATED;
- break;
- case REMOVE:
- default:
- type = CONFIG_REMOVED;
- break;
- }
ConfigFactory factory = factoriesByConfig.get(event.key().configClass);
if (factory != null) {
+ Object subject = event.key().subject;
+ Class configClass = factory.configClass();
+ Versioned<JsonNode> newValue = event.newValue();
+ Versioned<JsonNode> oldValue = event.oldValue();
+
+ Config config = (newValue != null) ?
+ createDetachedConfig(subject, configClass, newValue.value()) :
+ null;
+ Config prevConfig = (oldValue != null) ?
+ createDetachedConfig(subject, configClass, oldValue.value()) :
+ null;
+
+ NetworkConfigEvent.Type type;
+ switch (event.type()) {
+ case INSERT:
+ type = CONFIG_ADDED;
+ break;
+ case UPDATE:
+ type = CONFIG_UPDATED;
+ break;
+ case REMOVE:
+ default:
+ type = CONFIG_REMOVED;
+ break;
+ }
notifyDelegate(new NetworkConfigEvent(type, event.key().subject,
- factory.configClass()));
+ config, prevConfig, factory.configClass()));
}
}
}