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;
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 @@ public abstract class Config<S> {
* @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 @@ public abstract class Config<S> {
/**
* 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
/**
......
......@@ -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 class NetworkConfigEvent extends AbstractEvent<NetworkConfigEvent.Type, O
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 class NetworkConfigEvent extends AbstractEvent<NetworkConfigEvent.Type, O
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 @@ public class NetworkConfigEvent extends AbstractEvent<NetworkConfigEvent.Type, O
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();
}
}
......
......@@ -267,6 +267,33 @@ public class DistributedNetworkConfigStore
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 @@ public class DistributedNetworkConfigStore
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()));
}
}
}
......