<arphandler.version>0.5.2-SNAPSHOT</arphandler.version>
<forwarding.staticrouting>0.5.2-SNAPSHOT</forwarding.staticrouting>
<samples.loadbalancer>0.5.2-SNAPSHOT</samples.loadbalancer>
- <config.version>0.2.4-SNAPSHOT</config.version>
- <netconf.version>0.2.4-SNAPSHOT</netconf.version>
+ <config.version>0.2.5-SNAPSHOT</config.version>
+ <netconf.version>0.2.5-SNAPSHOT</netconf.version>
<mdsal.version>1.1-SNAPSHOT</mdsal.version>
<containermanager.version>0.5.2-SNAPSHOT</containermanager.version>
<containermanager.it.version>0.5.2-SNAPSHOT</containermanager.it.version>
<switchmanager.api.version>0.7.1-SNAPSHOT</switchmanager.api.version>
<connectionmanager.version>0.1.2-SNAPSHOT</connectionmanager.version>
- <sal.version>0.7.1-SNAPSHOT</sal.version>
+ <sal.version>0.8.1-SNAPSHOT</sal.version>
<sal.networkconfiguration.version>0.0.3-SNAPSHOT</sal.networkconfiguration.version>
<sal.connection.version>0.1.2-SNAPSHOT</sal.connection.version>
<networkconfig.bridgedomain.northbound.version>0.0.3-SNAPSHOT</networkconfig.bridgedomain.northbound.version>
<java.version.target>1.7</java.version.target>
<!-- enforcer version -->
<enforcer.version>1.3.1</enforcer.version>
+ <xtend.version>2.4.3</xtend.version>
+ <xtend.dstdir>${project.build.directory}/generated-sources/xtend-gen</xtend.dstdir>
</properties>
<dependencyManagement>
</dependency>
<!-- md-sal -->
+ <dependency>
+ <groupId>org.eclipse.xtend</groupId>
+ <artifactId>org.eclipse.xtend.lib</artifactId>
+ <version>${xtend.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-common</artifactId>
<artifactId>config-persister-impl</artifactId>
<version>${netconf.version}</version>
</dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>ietf-netconf-monitoring</artifactId>
- <version>${netconf.version}</version>
- </dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>ietf-netconf-monitoring-extension</artifactId>
- <version>${netconf.version}</version>
- </dependency>
<!-- threadpool -->
<dependency>
<artifactId>maven-release-plugin</artifactId>
<version>${releaseplugin.version}</version>
</plugin>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <version>${yangtools.version}</version>
+ </plugin>
<!-- Ignore/Execute plugin execution -->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<testTarget>${java.version.target}</testTarget>
</configuration>
</plugin>
+ <plugin>
+ <groupId>org.eclipse.xtend</groupId>
+ <artifactId>xtend-maven-plugin</artifactId>
+ <version>${xtend.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>compile</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>${xtend.dstdir}</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
</plugins>
</pluginManagement>
</build>
}
@Override
+ @SuppressWarnings("unchecked")
protected final void channelRead0(final ChannelHandlerContext ctx, final Object msg) {
LOG.debug("Message was received: {}", msg);
handleMessage((M) msg);
}
@Override
+ @SuppressWarnings("unchecked")
public final void channelRead(final ChannelHandlerContext ctx, final Object msg) {
LOG.debug("Negotiation read invoked on channel {}", channel);
try {
<parent>
<artifactId>config-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
</parent>
<artifactId>config-api</artifactId>
* transaction was committed after creating this transaction. Clients can create
* new transaction and merge the changes.
*/
-public class ConflictingVersionException extends RuntimeException {
+public class ConflictingVersionException extends Exception {
private static final long serialVersionUID = 1L;
public ConflictingVersionException() {
@ConstructorProperties(QNAME_ATTR_NAME)
public IdentityAttributeRef(String qNameOfIdentity) {
- if (qNameOfIdentity == null)
+ if (qNameOfIdentity == null) {
throw new NullPointerException("Parameter " + QNAME_ATTR_NAME + " is null");
+ }
this.qNameOfIdentity = qNameOfIdentity;
}
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (!(o instanceof IdentityAttributeRef)) return false;
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof IdentityAttributeRef)) {
+ return false;
+ }
IdentityAttributeRef that = (IdentityAttributeRef) o;
- if (!qNameOfIdentity.equals(that.qNameOfIdentity)) return false;
+ if (!qNameOfIdentity.equals(that.qNameOfIdentity)) {
+ return false;
+ }
return true;
}
private final String attributeName;
public JmxAttribute(String attributeName) {
- if (attributeName == null)
+ if (attributeName == null) {
throw new NullPointerException("Parameter 'attributeName' is null");
+ }
this.attributeName = attributeName;
}
@Override
public boolean equals(Object o) {
- if (this == o)
+ if (this == o) {
return true;
- if (o == null || getClass() != o.getClass())
+ }
+ if (o == null || getClass() != o.getClass()) {
return false;
+ }
JmxAttribute that = (JmxAttribute) o;
if (attributeName != null ? !attributeName.equals(that.attributeName)
- : that.attributeName != null)
+ : that.attributeName != null) {
return false;
+ }
return true;
}
private final String factoryName, instanceName;
public ModuleIdentifier(String factoryName, String instanceName) {
- if (factoryName == null)
- throw new IllegalArgumentException(
- "Parameter 'factoryName' is null");
- if (instanceName == null)
- throw new IllegalArgumentException(
- "Parameter 'instanceName' is null");
+ if (factoryName == null) {
+ throw new IllegalArgumentException("Parameter 'factoryName' is null");
+ }
+ if (instanceName == null) {
+ throw new IllegalArgumentException("Parameter 'instanceName' is null");
+ }
this.factoryName = factoryName;
this.instanceName = instanceName;
}
@Override
public boolean equals(Object o) {
- if (this == o)
+ if (this == o) {
return true;
- if (o == null || getClass() != o.getClass())
+ }
+ if (o == null || getClass() != o.getClass()) {
return false;
+ }
ModuleIdentifier that = (ModuleIdentifier) o;
- if (!factoryName.equals(that.factoryName))
+ if (!factoryName.equals(that.factoryName)) {
return false;
- if (!instanceName.equals(that.instanceName))
+ }
+ if (!instanceName.equals(that.instanceName)) {
return false;
+ }
return true;
}
/**
* This exception is not intended to be used while implementing modules,
- * itaggregates validation exceptions and sends them back to the user.
+ * it aggregates validation exceptions and sends them back to the user.
+ * Use {@link org.opendaylight.controller.config.api.JmxAttributeValidationException} for
+ * validating modules instead.
*/
-public class ValidationException extends RuntimeException {
+public class ValidationException extends Exception {
private static final long serialVersionUID = -6072893219820274247L;
private final Map<String/* module name */, Map<String/* instance name */, ExceptionMessageWithStackTrace>> failedValidations;
@Override
public boolean equals(Object obj) {
- if (this == obj)
+ if (this == obj) {
return true;
- if (obj == null)
+ }
+ if (obj == null) {
return false;
- if (getClass() != obj.getClass())
+ }
+ if (getClass() != obj.getClass()) {
return false;
+ }
ExceptionMessageWithStackTrace other = (ExceptionMessageWithStackTrace) obj;
if (message == null) {
- if (other.message != null)
+ if (other.message != null) {
return false;
- } else if (!message.equals(other.message))
+ }
+ } else if (!message.equals(other.message)) {
return false;
+ }
if (stackTrace == null) {
- if (other.stackTrace != null)
+ if (other.stackTrace != null) {
return false;
- } else if (!stackTrace.equals(other.stackTrace))
+ }
+ } else if (!stackTrace.equals(other.stackTrace)) {
return false;
+ }
return true;
}
*/
package org.opendaylight.controller.config.api.jmx;
+import javax.annotation.concurrent.Immutable;
+import javax.management.ObjectName;
import java.beans.ConstructorProperties;
import java.util.Collections;
import java.util.List;
-import javax.annotation.concurrent.Immutable;
-import javax.management.ObjectName;
-
@Immutable
public class CommitStatus {
private final List<ObjectName> newInstances, reusedInstances,
recreatedInstances;
/**
- *
- * @param newInstances
- * newly created instances
- * @param reusedInstances
- * reused instances
- * @param recreatedInstances
- * recreated instances
+ * @param newInstances newly created instances
+ * @param reusedInstances reused instances
+ * @param recreatedInstances recreated instances
*/
- @ConstructorProperties({ "newInstances", "reusedInstances",
- "recreatedInstances" })
+ @ConstructorProperties({"newInstances", "reusedInstances",
+ "recreatedInstances"})
public CommitStatus(List<ObjectName> newInstances,
- List<ObjectName> reusedInstances,
- List<ObjectName> recreatedInstances) {
+ List<ObjectName> reusedInstances,
+ List<ObjectName> recreatedInstances) {
this.newInstances = Collections.unmodifiableList(newInstances);
this.reusedInstances = Collections.unmodifiableList(reusedInstances);
this.recreatedInstances = Collections
}
/**
- *
* @return list of objectNames representing newly created instances
*/
public List<ObjectName> getNewInstances() {
}
/**
- *
* @return list of objectNames representing reused instances
*/
public List<ObjectName> getReusedInstances() {
}
/**
- *
* @return list of objectNames representing recreated instances
*/
public List<ObjectName> getRecreatedInstances() {
result = prime
* result
+ ((recreatedInstances == null) ? 0 : recreatedInstances
- .hashCode());
+ .hashCode());
result = prime * result
+ ((reusedInstances == null) ? 0 : reusedInstances.hashCode());
return result;
@Override
public boolean equals(Object obj) {
- if (this == obj)
+ if (this == obj) {
return true;
- if (obj == null)
+ }
+ if (obj == null) {
return false;
- if (getClass() != obj.getClass())
+ }
+ if (getClass() != obj.getClass()) {
return false;
+ }
CommitStatus other = (CommitStatus) obj;
if (newInstances == null) {
- if (other.newInstances != null)
+ if (other.newInstances != null) {
return false;
- } else if (!newInstances.equals(other.newInstances))
+ }
+ } else if (!newInstances.equals(other.newInstances)) {
return false;
+ }
if (recreatedInstances == null) {
- if (other.recreatedInstances != null)
+ if (other.recreatedInstances != null) {
return false;
- } else if (!recreatedInstances.equals(other.recreatedInstances))
+ }
+ } else if (!recreatedInstances.equals(other.recreatedInstances)) {
return false;
+ }
if (reusedInstances == null) {
- if (other.reusedInstances != null)
+ if (other.reusedInstances != null) {
return false;
- } else if (!reusedInstances.equals(other.reusedInstances))
+ }
+ } else if (!reusedInstances.equals(other.reusedInstances)) {
return false;
+ }
return true;
}
import org.opendaylight.controller.config.api.jmx.constants.ConfigRegistryConstants;
import javax.annotation.concurrent.ThreadSafe;
+import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import java.util.Arrays;
import java.util.HashMap;
public static ObjectName createON(String on) {
try {
return new ObjectName(on);
- } catch (Exception e) {
- throw new RuntimeException(e);
+ } catch (MalformedObjectNameException e) {
+ throw new IllegalArgumentException(e);
}
}
Hashtable<String, String> table = new Hashtable<>(attribs);
try {
return new ObjectName(domain, table);
- } catch (Exception e) {
- throw new RuntimeException(e);
+ } catch (MalformedObjectNameException e) {
+ throw new IllegalArgumentException(e);
}
}
public static String getServiceQName(ObjectName objectName) {
checkType(objectName, TYPE_SERVICE_REFERENCE);
String quoted = objectName.getKeyProperty(SERVICE_QNAME_KEY);
- String result = unquoteAndUnescape(objectName, quoted);
- return result;
+ return unquoteAndUnescape(objectName, quoted);
}
// ObjectName supports quotation and ignores tokens like =, but fails to ignore ? sign.
}
}
- public static void checkTypeOneOf(ObjectName objectName, String ... types) {
- for(String type: types) {
+ public static void checkTypeOneOf(ObjectName objectName, String... types) {
+ for (String type : types) {
if (type.equals(objectName.getKeyProperty(TYPE_KEY))) {
return;
}
public static ObjectName createModulePattern(String moduleName,
String instanceName) {
- if (moduleName == null)
+ if (moduleName == null) {
moduleName = "*";
- if (instanceName == null)
+ }
+ if (instanceName == null) {
instanceName = "*";
+ }
// do not return object names containing transaction name
ObjectName namePattern = ObjectNameUtil
.createON(ObjectNameUtil.ON_DOMAIN + ":"
String expectedType) {
checkType(objectName, expectedType);
String factoryName = getFactoryName(objectName);
- if (factoryName == null)
+ if (factoryName == null) {
throw new IllegalArgumentException(
"ObjectName does not contain module name");
+ }
String instanceName = getInstanceName(objectName);
- if (instanceName == null)
+ if (instanceName == null) {
throw new IllegalArgumentException(
"ObjectName does not contain instance name");
+ }
return new ModuleIdentifier(factoryName, instanceName);
}
*/
package org.opendaylight.controller.config.api.jmx.constants;
+import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
public class ConfigRegistryConstants {
public static final ObjectName OBJECT_NAME = createONWithDomainAndType(TYPE_CONFIG_REGISTRY);
- public static String GET_AVAILABLE_MODULE_NAMES_ATTRIBUT_NAME = "AvailableModuleNames";
+ public static final String GET_AVAILABLE_MODULE_NAMES_ATTRIBUT_NAME = "AvailableModuleNames";
public static ObjectName createONWithDomainAndType(String type) {
return createON(ON_DOMAIN, TYPE_KEY, type);
public static ObjectName createON(String name, String key, String value) {
try {
return new ObjectName(name, key, value);
- } catch (Exception e) {
- throw new RuntimeException(e);
+ } catch (MalformedObjectNameException e) {
+ throw new IllegalArgumentException(e);
}
}
*/
package org.opendaylight.controller.config.spi;
-import javax.annotation.concurrent.NotThreadSafe;
-
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.opendaylight.yangtools.concepts.Identifiable;
+import javax.annotation.concurrent.NotThreadSafe;
+
/**
* Represents one service that is to be configured. These methods need to be
* ConfigBeans.
* <p>
* In order to guide dependency resolution, the setter method should be
- * annotated with {@link RequireInterface}.
+ * annotated with {@link org.opendaylight.controller.config.api.annotations.RequireInterface}.
* </p>
* <p>
* Thread safety note: implementations of this interface are not required to be
* Returns 'live' object that was configured using this object. It is
* allowed to call this method only after all ConfigBeans were validated. In
* this method new resources might be opened or old instance might be
- * modified. Note that when obtaining dependent Module using
- * {@link org.opendaylight.controller.config.api.DependencyResolver#validateDependency(Class, javax.management.ObjectName, String)}
- * a proxy will be created that will disallow calling this method before
- * second commit phase begins.
+ * modified. This method must be implemented so that it returns same
+ * result for a single transaction. Since Module is created per transaction
+ * this means that it must be safe to cache result of first call.
+ *
*
* @return closeable instance: After bundle update the factory might be able
* to copy old configuration into new one without being able to cast
<parent>
<artifactId>config-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>config-manager</artifactId>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
- <scope>test</scope>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
import javax.annotation.concurrent.Immutable;
import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.config.manager.impl.dependencyresolver.DestroyedModule;
+import org.opendaylight.controller.config.manager.impl.dependencyresolver.ModuleInternalTransactionalInfo;
/**
* Structure obtained during first phase commit, contains destroyed modules from
*/
package org.opendaylight.controller.config.manager.impl;
+import com.google.common.collect.Maps;
import org.opendaylight.controller.config.api.ConflictingVersionException;
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.opendaylight.controller.config.api.RuntimeBeanRegistratorAwareModule;
import org.opendaylight.controller.config.api.ValidationException;
import org.opendaylight.controller.config.api.jmx.CommitStatus;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.config.manager.impl.dependencyresolver.DestroyedModule;
+import org.opendaylight.controller.config.manager.impl.dependencyresolver.ModuleInternalTransactionalInfo;
import org.opendaylight.controller.config.manager.impl.dynamicmbean.DynamicReadableWrapper;
import org.opendaylight.controller.config.manager.impl.factoriesresolver.HierarchicalConfigMBeanFactoriesHolder;
import org.opendaylight.controller.config.manager.impl.factoriesresolver.ModuleFactoriesResolver;
private List<ModuleFactory> lastListOfFactories = Collections.emptyList();
@GuardedBy("this") // switched in every 2ndPC
- private CloseableServiceReferenceReadableRegistry readableSRRegistry = ServiceReferenceRegistryImpl.createInitialSRLookupRegistry();
+ private CloseableServiceReferenceReadableRegistry readableSRRegistry = ServiceReferenceRegistryImpl.createInitialSRLookupRegistry();
// constructor
public ConfigRegistryImpl(ModuleFactoriesResolver resolver,
- MBeanServer configMBeanServer, CodecRegistry codecRegistry) {
+ MBeanServer configMBeanServer, CodecRegistry codecRegistry) {
this(resolver, configMBeanServer,
new BaseJMXRegistrator(configMBeanServer), codecRegistry);
}
// constructor
public ConfigRegistryImpl(ModuleFactoriesResolver resolver,
- MBeanServer configMBeanServer,
- BaseJMXRegistrator baseJMXRegistrator, CodecRegistry codecRegistry) {
+ MBeanServer configMBeanServer,
+ BaseJMXRegistrator baseJMXRegistrator, CodecRegistry codecRegistry) {
this.resolver = resolver;
this.beanToOsgiServiceManager = new BeanToOsgiServiceManager();
this.configMBeanServer = configMBeanServer;
throw new IllegalStateException(e);
}
transactionController.copyExistingModulesAndProcessFactoryDiff(currentConfig.getEntries(), lastListOfFactories);
- transactionsHolder.add(transactionName, transactionController);
+ transactionsHolder.add(transactionName, transactionController, txLookupRegistry);
return transactionController;
}
* {@inheritDoc}
*/
@Override
+ @SuppressWarnings("PMD.AvoidCatchingThrowable")
public synchronized CommitStatus commitConfig(ObjectName transactionControllerON)
throws ConflictingVersionException, ValidationException {
final String transactionName = ObjectNameUtil
logger.trace("About to commit {}. Current parentVersion: {}, versionCounter {}", transactionName, version, versionCounter);
// find ConfigTransactionController
- Map<String, ConfigTransactionControllerInternal> transactions = transactionsHolder.getCurrentTransactions();
- ConfigTransactionControllerInternal configTransactionController = transactions.get(transactionName);
- if (configTransactionController == null) {
+ Map<String, Entry<ConfigTransactionControllerInternal, ConfigTransactionLookupRegistry>> transactions = transactionsHolder.getCurrentTransactions();
+ Entry<ConfigTransactionControllerInternal, ConfigTransactionLookupRegistry> configTransactionControllerEntry = transactions.get(transactionName);
+ if (configTransactionControllerEntry == null) {
throw new IllegalArgumentException(String.format(
"Transaction with name '%s' not found", transactionName));
}
+ ConfigTransactionControllerInternal configTransactionController = configTransactionControllerEntry.getKey();
// check optimistic lock
if (version != configTransactionController.getParentVersion()) {
throw new ConflictingVersionException(
lastListOfFactories = Collections.unmodifiableList(configTransactionController.getCurrentlyRegisteredFactories());
// non recoverable from here:
try {
- return secondPhaseCommit(
- configTransactionController, commitInfo);
+ return secondPhaseCommit(configTransactionController, commitInfo, configTransactionControllerEntry.getValue());
} catch (Throwable t) { // some libs throw Errors: e.g.
- // javax.xml.ws.spi.FactoryFinder$ConfigurationError
+ // javax.xml.ws.spi.FactoryFinder$ConfigurationError
isHealthy = false;
logger.error("Configuration Transaction failed on 2PC, server is unhealthy", t);
if (t instanceof RuntimeException) {
}
private CommitStatus secondPhaseCommit(ConfigTransactionControllerInternal configTransactionController,
- CommitInfo commitInfo) {
+ CommitInfo commitInfo, ConfigTransactionLookupRegistry txLookupRegistry) {
// close instances which were destroyed by the user, including
// (hopefully) runtime beans
for (DestroyedModule toBeDestroyed : commitInfo
.getDestroyedFromPreviousTransactions()) {
toBeDestroyed.close(); // closes instance (which should close
- // runtime jmx registrator),
+ // runtime jmx registrator),
// also closes osgi registration and ModuleJMXRegistrator
// registration
currentConfig.remove(toBeDestroyed.getIdentifier());
.getRuntimeBeanRegistrator();
}
// set runtime jmx registrator if required
- Module module = entry.getModule();
+ Module module = entry.getProxiedModule();
if (module instanceof RuntimeBeanRegistratorAwareModule) {
((RuntimeBeanRegistratorAwareModule) module)
.setRuntimeBeanRegistrator(runtimeBeanRegistrator);
}
// can register runtime beans
- List<ModuleIdentifier> orderedModuleIdentifiers = configTransactionController
- .secondPhaseCommit();
+ List<ModuleIdentifier> orderedModuleIdentifiers = configTransactionController.secondPhaseCommit();
+ txLookupRegistry.close();
+ configTransactionController.close();
// copy configuration to read only mode
List<ObjectName> newInstances = new LinkedList<>();
for (ModuleIdentifier moduleIdentifier : orderedModuleIdentifiers) {
ModuleInternalTransactionalInfo entry = commitInfo.getCommitted()
.get(moduleIdentifier);
- if (entry == null)
+ if (entry == null) {
throw new NullPointerException("Module not found "
+ moduleIdentifier);
- Module module = entry.getModule();
+ }
+
ObjectName primaryReadOnlyON = ObjectNameUtil
.createReadOnlyModuleON(moduleIdentifier);
.createModuleJMXRegistrator();
OsgiRegistration osgiRegistration = null;
+ AutoCloseable instance = entry.getProxiedModule().getInstance();
if (entry.hasOldModule()) {
ModuleInternalInfo oldInternalInfo = entry.getOldInternalInfo();
DynamicReadableWrapper oldReadableConfigBean = oldInternalInfo.getReadableModule();
currentConfig.remove(entry.getIdentifier());
// test if old instance == new instance
- if (oldReadableConfigBean.getInstance().equals(module.getInstance())) {
+ if (oldReadableConfigBean.getInstance().equals(instance)) {
// reused old instance:
// wrap in readable dynamic mbean
reusedInstances.add(primaryReadOnlyON);
// wrap in readable dynamic mbean
newInstances.add(primaryReadOnlyON);
}
+ Module realModule = entry.getRealModule();
DynamicReadableWrapper newReadableConfigBean = new DynamicReadableWrapper(
- module, module.getInstance(), moduleIdentifier,
+ realModule, instance, moduleIdentifier,
registryMBeanServer, configMBeanServer);
// register to JMX
// register to OSGi
if (osgiRegistration == null) {
ModuleFactory moduleFactory = entry.getModuleFactory();
- if(moduleFactory != null) {
+ if (moduleFactory != null) {
BundleContext bc = configTransactionController.
getModuleFactoryBundleContext(moduleFactory.getImplementationName());
- osgiRegistration = beanToOsgiServiceManager.registerToOsgi(module.getClass(),
+ osgiRegistration = beanToOsgiServiceManager.registerToOsgi(realModule.getClass(),
newReadableConfigBean.getInstance(), entry.getIdentifier(), bc);
} else {
throw new NullPointerException(entry.getIdentifier().getFactoryName() + " ModuleFactory not found.");
runtimeBeanRegistrator, newModuleJMXRegistrator,
orderingIdx, entry.isDefaultBean());
- newConfigEntries.put(module, newInfo);
+ newConfigEntries.put(realModule, newInfo);
orderingIdx++;
}
currentConfig.addAll(newConfigEntries.values());
*/
@Override
public synchronized List<ObjectName> getOpenConfigs() {
- Map<String, ConfigTransactionControllerInternal> transactions = transactionsHolder
+ Map<String, Entry<ConfigTransactionControllerInternal, ConfigTransactionLookupRegistry>> transactions = transactionsHolder
.getCurrentTransactions();
List<ObjectName> result = new ArrayList<>(transactions.size());
- for (ConfigTransactionControllerInternal configTransactionController : transactions
+ for (Entry<ConfigTransactionControllerInternal, ConfigTransactionLookupRegistry> configTransactionControllerEntry : transactions
.values()) {
- result.add(configTransactionController.getControllerObjectName());
+ result.add(configTransactionControllerEntry.getKey().getControllerObjectName());
}
return result;
}
@Override
public synchronized void close() {
// abort transactions
- Map<String, ConfigTransactionControllerInternal> transactions = transactionsHolder
+ Map<String, Entry<ConfigTransactionControllerInternal, ConfigTransactionLookupRegistry>> transactions = transactionsHolder
.getCurrentTransactions();
- for (ConfigTransactionControllerInternal configTransactionController : transactions
+ for (Entry<ConfigTransactionControllerInternal, ConfigTransactionLookupRegistry> configTransactionControllerEntry : transactions
.values()) {
+
+ ConfigTransactionControllerInternal configTransactionController = configTransactionControllerEntry.getKey();
try {
+ configTransactionControllerEntry.getValue().close();
configTransactionController.abortConfig();
} catch (RuntimeException e) {
logger.warn("Ignoring exception while aborting {}",
*/
@Override
public Set<ObjectName> lookupConfigBeans(String moduleName,
- String instanceName) {
+ String instanceName) {
ObjectName namePattern = ObjectNameUtil.createModulePattern(moduleName,
instanceName);
return baseJMXRegistrator.queryNames(namePattern, null);
*/
@Override
public Set<ObjectName> lookupRuntimeBeans(String moduleName,
- String instanceName) {
- if (moduleName == null)
+ String instanceName) {
+ if (moduleName == null) {
moduleName = "*";
- if (instanceName == null)
+ }
+ if (instanceName == null) {
instanceName = "*";
+ }
ObjectName namePattern = ObjectNameUtil.createRuntimeBeanPattern(
moduleName, instanceName);
return baseJMXRegistrator.queryNames(namePattern, null);
* {@link ConfigTransactionControllerInternal} instances, because platform
* MBeanServer transforms mbeans into another representation. Map is cleaned
* every time current transactions are requested.
- *
*/
@GuardedBy("ConfigRegistryImpl.this")
- private final Map<String /* transactionName */, ConfigTransactionControllerInternal> transactions = new HashMap<>();
+ private final Map<String /* transactionName */,
+ Entry<ConfigTransactionControllerInternal, ConfigTransactionLookupRegistry>> transactions = new HashMap<>();
/**
* Can only be called from within synchronized method.
*/
public void add(String transactionName,
- ConfigTransactionControllerInternal transactionController) {
+ ConfigTransactionControllerInternal transactionController, ConfigTransactionLookupRegistry txLookupRegistry) {
Object oldValue = transactions.put(transactionName,
- transactionController);
+ Maps.immutableEntry(transactionController, txLookupRegistry));
if (oldValue != null) {
throw new IllegalStateException(
"Error: two transactions with same name");
*
* @return current view on transactions map.
*/
- public Map<String, ConfigTransactionControllerInternal> getCurrentTransactions() {
+ public Map<String, Entry<ConfigTransactionControllerInternal, ConfigTransactionLookupRegistry>> getCurrentTransactions() {
// first, remove closed transaction
- for (Iterator<Entry<String, ConfigTransactionControllerInternal>> it = transactions
- .entrySet().iterator(); it.hasNext();) {
- Entry<String, ConfigTransactionControllerInternal> entry = it
+ for (Iterator<Entry<String, Entry<ConfigTransactionControllerInternal, ConfigTransactionLookupRegistry>>> it = transactions
+ .entrySet().iterator(); it.hasNext(); ) {
+ Entry<String, Entry<ConfigTransactionControllerInternal, ConfigTransactionLookupRegistry>> entry = it
.next();
- if (entry.getValue().isClosed()) {
+ if (entry.getValue().getKey().isClosed()) {
it.remove();
}
}
import org.opendaylight.controller.config.api.ValidationException;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
import org.opendaylight.controller.config.manager.impl.dependencyresolver.DependencyResolverManager;
+import org.opendaylight.controller.config.manager.impl.dependencyresolver.ModuleInternalTransactionalInfo;
import org.opendaylight.controller.config.manager.impl.dynamicmbean.DynamicWritableWrapper;
import org.opendaylight.controller.config.manager.impl.dynamicmbean.ReadOnlyAtomicBoolean;
import org.opendaylight.controller.config.manager.impl.dynamicmbean.ReadOnlyAtomicBoolean.ReadOnlyAtomicBooleanImpl;
class ConfigTransactionControllerImpl implements
ConfigTransactionControllerInternal,
ConfigTransactionControllerImplMXBean,
- Identifiable<TransactionIdentifier>{
+ Identifiable<TransactionIdentifier> {
private static final Logger logger = LoggerFactory.getLogger(ConfigTransactionControllerImpl.class);
private final ConfigTransactionLookupRegistry txLookupRegistry;
this.currentlyRegisteredFactories = currentlyRegisteredFactories;
this.factoriesHolder = new HierarchicalConfigMBeanFactoriesHolder(currentlyRegisteredFactories);
this.transactionStatus = new TransactionStatus();
- this.dependencyResolverManager = new DependencyResolverManager(transactionName, transactionStatus, writableSRRegistry, codecRegistry);
+ this.dependencyResolverManager = new DependencyResolverManager(txLookupRegistry.getTransactionIdentifier(),
+ transactionStatus, writableSRRegistry, codecRegistry);
this.transactionsMBeanServer = transactionsMBeanServer;
this.configMBeanServer = configMBeanServer;
this.blankTransaction = blankTransaction;
List<ModuleFactory> toBeAdded = new ArrayList<>();
List<ModuleFactory> toBeRemoved = new ArrayList<>();
- for(ModuleFactory moduleFactory: factoriesHolder.getModuleFactories()) {
- if (oldSet.contains(moduleFactory) == false){
+ for (ModuleFactory moduleFactory : factoriesHolder.getModuleFactories()) {
+ if (oldSet.contains(moduleFactory) == false) {
toBeAdded.add(moduleFactory);
}
}
- for(ModuleFactory moduleFactory: lastListOfFactories){
+ for (ModuleFactory moduleFactory : lastListOfFactories) {
if (newSet.contains(moduleFactory) == false) {
toBeRemoved.add(moduleFactory);
}
}
// remove modules belonging to removed factories
- for(ModuleFactory removedFactory: toBeRemoved){
+ for (ModuleFactory removedFactory : toBeRemoved) {
List<ModuleIdentifier> modulesOfRemovedFactory = dependencyResolverManager.findAllByFactory(removedFactory);
for (ModuleIdentifier name : modulesOfRemovedFactory) {
destroyModule(name);
@Override
public synchronized ObjectName createModule(String factoryName,
- String instanceName) throws InstanceAlreadyExistsException {
+ String instanceName) throws InstanceAlreadyExistsException {
transactionStatus.checkNotCommitStarted();
transactionStatus.checkNotAborted();
throws InstanceAlreadyExistsException {
logger.debug("Adding module {} to transaction {}", moduleIdentifier, this);
- if (moduleIdentifier.equals(module.getIdentifier())==false) {
+ if (moduleIdentifier.equals(module.getIdentifier()) == false) {
throw new IllegalStateException("Incorrect name reported by module. Expected "
- + moduleIdentifier + ", got " + module.getIdentifier());
+ + moduleIdentifier + ", got " + module.getIdentifier());
}
- if (dependencyResolver.getIdentifier().equals(moduleIdentifier) == false ) {
+ if (dependencyResolver.getIdentifier().equals(moduleIdentifier) == false) {
throw new IllegalStateException("Incorrect name reported by dependency resolver. Expected "
+ moduleIdentifier + ", got " + dependencyResolver.getIdentifier());
}
// put wrapper to jmx
TransactionModuleJMXRegistration transactionModuleJMXRegistration = getTxModuleJMXRegistrator()
.registerMBean(writableDynamicWrapper, writableON);
- ModuleInternalTransactionalInfo moduleInternalTransactionalInfo = new ModuleInternalTransactionalInfo(
+
+ dependencyResolverManager.put(
moduleIdentifier, module, moduleFactory,
maybeOldConfigBeanInfo, transactionModuleJMXRegistration, isDefaultBean);
-
- dependencyResolverManager.put(moduleInternalTransactionalInfo);
return writableON;
}
// first remove refNames, it checks for objectname existence
try {
writableSRRegistry.removeServiceReferences(
- ObjectNameUtil.createTransactionModuleON(getTransactionName(),moduleIdentifier));
+ ObjectNameUtil.createTransactionModuleON(getTransactionName(), moduleIdentifier));
} catch (InstanceNotFoundException e) {
logger.error("Possible code error: cannot find {} in {}", moduleIdentifier, writableSRRegistry);
throw new IllegalStateException("Possible code error: cannot find " + moduleIdentifier, e);
@Override
public synchronized void validateConfig() throws ValidationException {
- if (configBeanModificationDisabled.get())
+ if (configBeanModificationDisabled.get()) {
throw new IllegalStateException("Cannot start validation");
+ }
configBeanModificationDisabled.set(true);
try {
validate_noLocks();
logger.error("Commit failed on {} in transaction {}", name,
getTransactionIdentifier(), e);
internalAbort();
- throw new RuntimeException(
+ throw new IllegalStateException(
format("Error - getInstance() failed for %s in transaction %s",
name, getTransactionIdentifier()), e);
}
logger.trace("Committed configuration {}", getTransactionIdentifier());
transactionStatus.setCommitted();
- // unregister this and all modules from jmx
- close();
return dependencyResolverManager.getSortedModuleIdentifiers();
}
}
public void close() {
- //FIXME: should not close object that was retrieved in constructor, a wrapper object should do that perhaps
- txLookupRegistry.close();
+ dependencyResolverManager.close();
}
@Override
return writableSRRegistry;
}
+ @Override
public TransactionIdentifier getTransactionIdentifier() {
return txLookupRegistry.getTransactionIdentifier();
}
* and {@link ConfigRegistryImpl} (consumer).
*/
interface ConfigTransactionControllerInternal extends
- ConfigTransactionControllerImplMXBean {
+ ConfigTransactionControllerImplMXBean, AutoCloseable {
ServiceReferenceWritableRegistry getWritableRegistry();
+ TransactionIdentifier getTransactionIdentifier();
+
+ @Override
+ void close();
}
--- /dev/null
+package org.opendaylight.controller.config.manager.impl;
+
+import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.GuardedBy;
+import java.util.concurrent.TimeUnit;
+
+public class DeadlockMonitor implements AutoCloseable {
+ private static final Logger logger = LoggerFactory.getLogger(DeadlockMonitorRunnable.class);
+
+ private static final long WARN_AFTER_MILLIS = 5000;
+
+ private final TransactionIdentifier transactionIdentifier;
+ private final DeadlockMonitorRunnable thread;
+ @GuardedBy("this")
+ private ModuleIdentifierWithNanos moduleIdentifierWithNanos = new ModuleIdentifierWithNanos();
+
+ public DeadlockMonitor(TransactionIdentifier transactionIdentifier) {
+ this.transactionIdentifier = transactionIdentifier;
+ thread = new DeadlockMonitorRunnable();
+ thread.start();
+ }
+
+ public synchronized void setCurrentlyInstantiatedModule(ModuleIdentifier currentlyInstantiatedModule) {
+ this.moduleIdentifierWithNanos = new ModuleIdentifierWithNanos(currentlyInstantiatedModule);
+ }
+
+ public boolean isAlive() {
+ return thread.isAlive();
+ }
+
+ @Override
+ public void close() {
+ thread.interrupt();
+ }
+
+ @Override
+ public String toString() {
+ return "DeadlockMonitor{" + transactionIdentifier + '}';
+ }
+
+ private class DeadlockMonitorRunnable extends Thread {
+
+ private DeadlockMonitorRunnable() {
+ super(DeadlockMonitor.this.toString());
+ }
+
+ @Override
+ public void run() {
+ ModuleIdentifierWithNanos old = new ModuleIdentifierWithNanos(); // null moduleId
+ while (this.isInterrupted() == false) {
+ ModuleIdentifierWithNanos copy = new ModuleIdentifierWithNanos(DeadlockMonitor.this.moduleIdentifierWithNanos);
+ if (old.moduleIdentifier == null) {
+ // started
+ old = copy;
+ } else if (old.moduleIdentifier != null && old.equals(copy)) {
+ // is the getInstance() running longer than WARN_AFTER_MILLIS ?
+ long runningTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - copy.nanoTime);
+ if (runningTime > WARN_AFTER_MILLIS) {
+ logger.warn("{} did not finish after {} ms", copy.moduleIdentifier, runningTime);
+ }
+ }
+ try {
+ sleep(1000);
+ } catch (InterruptedException e) {
+ interrupt();
+ }
+ }
+ logger.trace("Exiting {}", this);
+ }
+
+ @Override
+ public String toString() {
+ return "DeadLockMonitorRunnable{" + transactionIdentifier + "}";
+ }
+ }
+
+ private class ModuleIdentifierWithNanos {
+ @Nullable
+ private final ModuleIdentifier moduleIdentifier;
+ private final long nanoTime;
+
+ private ModuleIdentifierWithNanos() {
+ moduleIdentifier = null;
+ nanoTime = System.nanoTime();
+ }
+
+ private ModuleIdentifierWithNanos(ModuleIdentifier moduleIdentifier) {
+ this.moduleIdentifier = moduleIdentifier;
+ nanoTime = System.nanoTime();
+ }
+
+ private ModuleIdentifierWithNanos(ModuleIdentifierWithNanos copy) {
+ moduleIdentifier = copy.moduleIdentifier;
+ nanoTime = copy.nanoTime;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ModuleIdentifierWithNanos that = (ModuleIdentifierWithNanos) o;
+
+ if (nanoTime != that.nanoTime) return false;
+ if (moduleIdentifier != null ? !moduleIdentifier.equals(that.moduleIdentifier) : that.moduleIdentifier != null)
+ return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = moduleIdentifier != null ? moduleIdentifier.hashCode() : 0;
+ result = 31 * result + (int) (nanoTime ^ (nanoTime >>> 32));
+ return result;
+ }
+ }
+}
import javax.annotation.Nullable;
import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.config.manager.impl.dependencyresolver.DestroyedModule;
import org.opendaylight.controller.config.manager.impl.dynamicmbean.DynamicReadableWrapper;
import org.opendaylight.controller.config.manager.impl.jmx.ModuleJMXRegistrator;
import org.opendaylight.controller.config.manager.impl.jmx.RootRuntimeBeanRegistratorImpl;
this.serviceReferenceRegistrator = serviceReferenceRegistratorFactory.create();
- Map<String, Set<String /* QName */>> factoryNamesToQNames = new HashMap<>();
+ Map<String, Set<String /* QName */>> modifiableFactoryNamesToQNames = new HashMap<>();
Set<ServiceInterfaceAnnotation> allAnnotations = new HashSet<>();
Set<String /* qName */> allQNames = new HashSet<>();
for (Entry<String, ModuleFactory> entry : factories.entrySet()) {
}
allAnnotations.addAll(siAnnotations);
allQNames.addAll(qNames);
- factoryNamesToQNames.put(entry.getKey(), Collections.unmodifiableSet(qNames));
+ modifiableFactoryNamesToQNames.put(entry.getKey(), Collections.unmodifiableSet(qNames));
}
- this.factoryNamesToQNames = Collections.unmodifiableMap(factoryNamesToQNames);
+ this.factoryNamesToQNames = Collections.unmodifiableMap(modifiableFactoryNamesToQNames);
this.allQNames = Collections.unmodifiableSet(allQNames);
// fill namespacesToAnnotations
- Map<String /* namespace */, Map<String /* localName */, ServiceInterfaceAnnotation>> namespacesToAnnotations =
+ Map<String /* namespace */, Map<String /* localName */, ServiceInterfaceAnnotation>> modifiableNamespacesToAnnotations =
new HashMap<>();
for (ServiceInterfaceAnnotation sia : allAnnotations) {
- Map<String, ServiceInterfaceAnnotation> ofNamespace = namespacesToAnnotations.get(sia.namespace());
+ Map<String, ServiceInterfaceAnnotation> ofNamespace = modifiableNamespacesToAnnotations.get(sia.namespace());
if (ofNamespace == null) {
ofNamespace = new HashMap<>();
- namespacesToAnnotations.put(sia.namespace(), ofNamespace);
+ modifiableNamespacesToAnnotations.put(sia.namespace(), ofNamespace);
}
if (ofNamespace.containsKey(sia.localName())) {
logger.error("Cannot construct namespacesToAnnotations map, conflict between local names in {}, offending local name: {}, map so far {}",
- sia.namespace(), sia.localName(), namespacesToAnnotations);
+ sia.namespace(), sia.localName(), modifiableNamespacesToAnnotations);
throw new IllegalArgumentException("Conflict between local names in " + sia.namespace() + " : " + sia.localName());
}
ofNamespace.put(sia.localName(), sia);
}
- this.namespacesToAnnotations = Collections.unmodifiableMap(namespacesToAnnotations);
+ this.namespacesToAnnotations = Collections.unmodifiableMap(modifiableNamespacesToAnnotations);
// copy refNames
logger.trace("factoryNamesToQNames:{}", this.factoryNamesToQNames);
}
@Override
public boolean equals(Object o) {
- if (this == o)
+ if (this == o) {
return true;
- if (o == null || getClass() != o.getClass())
+ }
+ if (o == null || getClass() != o.getClass()) {
return false;
+ }
TransactionIdentifier that = (TransactionIdentifier) o;
- if (name != null ? !name.equals(that.name) : that.name != null)
+ if (name != null ? !name.equals(that.name) : that.name != null) {
return false;
+ }
return true;
}
}
public synchronized void checkNotCommitStarted() {
- if (secondPhaseCommitStarted == true)
+ if (secondPhaseCommitStarted == true) {
throw new IllegalStateException("Commit was triggered");
+ }
}
public synchronized void checkCommitStarted() {
- if (secondPhaseCommitStarted == false)
+ if (secondPhaseCommitStarted == false) {
throw new IllegalStateException("Commit was not triggered");
+ }
}
public synchronized void checkNotAborted() {
- if (aborted == true)
+ if (aborted == true) {
throw new IllegalStateException("Configuration was aborted");
+ }
}
public synchronized void checkNotCommitted() {
* during validation. Tracks dependencies for ordering purposes.
*/
final class DependencyResolverImpl implements DependencyResolver,
- Comparable<DependencyResolverImpl> {
+ Comparable<DependencyResolverImpl> {
private static final Logger logger = LoggerFactory.getLogger(DependencyResolverImpl.class);
private final ModulesHolder modulesHolder;
throw new NullPointerException(
"Parameter 'expectedServiceInterface' is null");
}
- if (jmxAttribute == null)
+ if (jmxAttribute == null) {
throw new NullPointerException("Parameter 'jmxAttribute' is null");
+ }
JmxAttributeValidationException.checkNotNull(dependentReadOnlyON,
"is null, expected dependency implementing "
+ expectedServiceInterface, jmxAttribute);
-
// check that objectName belongs to this transaction - this should be
// stripped
// in DynamicWritableWrapper
}
}
- // transalate from serviceref to module ON
+ // translate from serviceref to module ON
private ObjectName translateServiceRefIfPossible(ObjectName dependentReadOnlyON) {
if (ObjectNameUtil.isServiceReference(dependentReadOnlyON)) {
String serviceQName = ObjectNameUtil.getServiceQName(dependentReadOnlyON);
//TODO: check for cycles
@Override
public <T> T resolveInstance(Class<T> expectedType, ObjectName dependentReadOnlyON,
- JmxAttribute jmxAttribute) {
+ JmxAttribute jmxAttribute) {
if (expectedType == null || dependentReadOnlyON == null || jmxAttribute == null) {
throw new IllegalArgumentException(format(
"Null parameters not allowed, got %s %s %s", expectedType,
throw new JmxAttributeValidationException(message, jmxAttribute);
}
try {
- T result = expectedType.cast(instance);
- return result;
+ return expectedType.cast(instance);
} catch (ClassCastException e) {
String message = format(
"Instance cannot be cast to expected type. Instance class is %s , "
IdentityCodec<?> identityCodec = codecRegistry.getIdentityCodec();
Class<? extends BaseIdentity> deserialized = identityCodec.deserialize(qName);
if (deserialized == null) {
- throw new RuntimeException("Unable to retrieve identity class for " + qName + ", null response from "
+ throw new IllegalStateException("Unable to retrieve identity class for " + qName + ", null response from "
+ codecRegistry);
}
if (expectedBaseClass.isAssignableFrom(deserialized)) {
public <T extends BaseIdentity> void validateIdentity(IdentityAttributeRef identityRef, Class<T> expectedBaseClass, JmxAttribute jmxAttribute) {
try {
resolveIdentity(identityRef, expectedBaseClass);
- } catch(Exception e) {
+ } catch (Exception e) {
throw JmxAttributeValidationException.wrap(e, jmxAttribute);
}
}
return maxDependencyDepth;
}
- public void countMaxDependencyDepth(DependencyResolverManager manager) {
+ void countMaxDependencyDepth(DependencyResolverManager manager) {
transactionStatus.checkCommitted();
if (maxDependencyDepth == null) {
maxDependencyDepth = getMaxDepth(this, manager,
}
private static int getMaxDepth(DependencyResolverImpl impl,
- DependencyResolverManager manager,
- LinkedHashSet<ModuleIdentifier> chainForDetectingCycles) {
+ DependencyResolverManager manager,
+ LinkedHashSet<ModuleIdentifier> chainForDetectingCycles) {
int maxDepth = 0;
LinkedHashSet<ModuleIdentifier> chainForDetectingCycles2 = new LinkedHashSet<>(
chainForDetectingCycles);
public ModuleIdentifier getIdentifier() {
return name;
}
+
}
*/
package org.opendaylight.controller.config.manager.impl.dependencyresolver;
+import com.google.common.reflect.AbstractInvocationHandler;
+import com.google.common.reflect.Reflection;
import org.opendaylight.controller.config.api.DependencyResolver;
import org.opendaylight.controller.config.api.DependencyResolverFactory;
import org.opendaylight.controller.config.api.JmxAttribute;
import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.config.api.RuntimeBeanRegistratorAwareModule;
import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
import org.opendaylight.controller.config.manager.impl.CommitInfo;
-import org.opendaylight.controller.config.manager.impl.ModuleInternalTransactionalInfo;
+import org.opendaylight.controller.config.manager.impl.DeadlockMonitor;
+import org.opendaylight.controller.config.manager.impl.ModuleInternalInfo;
+import org.opendaylight.controller.config.manager.impl.TransactionIdentifier;
import org.opendaylight.controller.config.manager.impl.TransactionStatus;
+import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator.TransactionModuleJMXRegistration;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
import javax.annotation.concurrent.GuardedBy;
import javax.management.InstanceAlreadyExistsException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import static com.google.common.base.Preconditions.checkState;
+
/**
* Holds information about modules being created and destroyed within this
* transaction. Observes usage of DependencyResolver within modules to figure
* out dependency tree.
*/
-public class DependencyResolverManager implements TransactionHolder, DependencyResolverFactory {
+public class DependencyResolverManager implements DependencyResolverFactory, AutoCloseable {
@GuardedBy("this")
private final Map<ModuleIdentifier, DependencyResolverImpl> moduleIdentifiersToDependencyResolverMap = new HashMap<>();
private final ModulesHolder modulesHolder;
private final TransactionStatus transactionStatus;
private final ServiceReferenceReadableRegistry readableRegistry;
private final CodecRegistry codecRegistry;
+ private final DeadlockMonitor deadlockMonitor;
- public DependencyResolverManager(String transactionName,
+ public DependencyResolverManager(TransactionIdentifier transactionIdentifier,
TransactionStatus transactionStatus, ServiceReferenceReadableRegistry readableRegistry, CodecRegistry codecRegistry) {
- this.modulesHolder = new ModulesHolder(transactionName);
+ this.modulesHolder = new ModulesHolder(transactionIdentifier);
this.transactionStatus = transactionStatus;
this.readableRegistry = readableRegistry;
this.codecRegistry = codecRegistry;
+ this.deadlockMonitor = new DeadlockMonitor(transactionIdentifier);
}
@Override
return result;
}
- @Override
public ModuleInternalTransactionalInfo destroyModule(
ModuleIdentifier moduleIdentifier) {
transactionStatus.checkNotCommitted();
}
// protect write access
- @Override
+
public void put(
- ModuleInternalTransactionalInfo moduleInternalTransactionalInfo) {
+ final ModuleIdentifier moduleIdentifier,
+ final Module module,
+ ModuleFactory moduleFactory,
+ ModuleInternalInfo maybeOldInternalInfo,
+ TransactionModuleJMXRegistration transactionModuleJMXRegistration,
+ boolean isDefaultBean) {
transactionStatus.checkNotCommitted();
+
+ Class<? extends Module> moduleClass = Module.class;
+ if (module instanceof RuntimeBeanRegistratorAwareModule) {
+ moduleClass = RuntimeBeanRegistratorAwareModule.class;
+ }
+ Module proxiedModule = Reflection.newProxy(moduleClass, new AbstractInvocationHandler() {
+ // optimization: subsequent calls to getInstance MUST return the same value during transaction,
+ // so it is safe to cache the response
+ private Object cachedInstance;
+
+ @Override
+ protected Object handleInvocation(Object proxy, Method method, Object[] args) throws Throwable {
+ boolean isGetInstance = method.getName().equals("getInstance");
+ if (isGetInstance) {
+ if (cachedInstance != null) {
+ return cachedInstance;
+ }
+
+ checkState(deadlockMonitor.isAlive(), "Deadlock monitor is not alive");
+ deadlockMonitor.setCurrentlyInstantiatedModule(moduleIdentifier);
+ }
+ try {
+ Object response = method.invoke(module, args);
+ if (isGetInstance) {
+ cachedInstance = response;
+ }
+ return response;
+ } catch(InvocationTargetException e) {
+ throw e.getCause();
+ } finally {
+ if (isGetInstance) {
+ deadlockMonitor.setCurrentlyInstantiatedModule(null);
+ }
+ }
+ }
+ });
+
+
+ ModuleInternalTransactionalInfo moduleInternalTransactionalInfo = new ModuleInternalTransactionalInfo(
+ moduleIdentifier, proxiedModule, moduleFactory,
+ maybeOldInternalInfo, transactionModuleJMXRegistration, isDefaultBean, module);
modulesHolder.put(moduleInternalTransactionalInfo);
}
// wrapped methods:
- @Override
public CommitInfo toCommitInfo() {
return modulesHolder.toCommitInfo();
}
- @Override
public Module findModule(ModuleIdentifier moduleIdentifier,
- JmxAttribute jmxAttributeForReporting) {
+ JmxAttribute jmxAttributeForReporting) {
return modulesHolder.findModule(moduleIdentifier,
jmxAttributeForReporting);
}
- @Override
public ModuleInternalTransactionalInfo findModuleInternalTransactionalInfo(ModuleIdentifier moduleIdentifier) {
return modulesHolder.findModuleInternalTransactionalInfo(moduleIdentifier);
}
- @Override
public ModuleFactory findModuleFactory(ModuleIdentifier moduleIdentifier,
- JmxAttribute jmxAttributeForReporting) {
+ JmxAttribute jmxAttributeForReporting) {
return modulesHolder.findModuleFactory(moduleIdentifier,
jmxAttributeForReporting);
}
- @Override
public Map<ModuleIdentifier, Module> getAllModules() {
return modulesHolder.getAllModules();
}
- @Override
public void assertNotExists(ModuleIdentifier moduleIdentifier)
throws InstanceAlreadyExistsException {
modulesHolder.assertNotExists(moduleIdentifier);
public List<ModuleIdentifier> findAllByFactory(ModuleFactory factory) {
List<ModuleIdentifier> result = new ArrayList<>();
- for( ModuleInternalTransactionalInfo info : modulesHolder.getAllInfos()) {
+ for (ModuleInternalTransactionalInfo info : modulesHolder.getAllInfos()) {
if (factory.equals(info.getModuleFactory())) {
result.add(info.getIdentifier());
}
}
return result;
}
+
+ public void close() {
+ deadlockMonitor.close();
+ }
+
}
* 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.config.manager.impl;
+package org.opendaylight.controller.config.manager.impl.dependencyresolver;
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.opendaylight.controller.config.manager.impl.jmx.ModuleJMXRegistrator;
private final OsgiRegistration osgiRegistration;
private final int orderingIdx;
- DestroyedModule(ModuleIdentifier identifier, AutoCloseable instance,
+ public DestroyedModule(ModuleIdentifier identifier, AutoCloseable instance,
ModuleJMXRegistrator oldJMXRegistrator,
OsgiRegistration osgiRegistration, int orderingIdx) {
this.identifier = identifier;
* 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.config.manager.impl;
-
-import javax.annotation.Nullable;
+package org.opendaylight.controller.config.manager.impl.dependencyresolver;
import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.config.manager.impl.ModuleInternalInfo;
import org.opendaylight.controller.config.manager.impl.dynamicmbean.DynamicReadableWrapper;
-import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator
- .TransactionModuleJMXRegistration;
+import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator.TransactionModuleJMXRegistration;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
import org.opendaylight.yangtools.concepts.Identifiable;
+import javax.annotation.Nullable;
+
public class ModuleInternalTransactionalInfo implements Identifiable<ModuleIdentifier> {
private final ModuleIdentifier name;
- private final Module module;
+ private final Module proxiedModule, realModule;
private final ModuleFactory moduleFactory;
@Nullable
private final ModuleInternalInfo maybeOldInternalInfo;
private final TransactionModuleJMXRegistration transactionModuleJMXRegistration;
private final boolean isDefaultBean;
- ModuleInternalTransactionalInfo(ModuleIdentifier name, Module module,
- ModuleFactory moduleFactory,
- ModuleInternalInfo maybeOldInternalInfo,
- TransactionModuleJMXRegistration transactionModuleJMXRegistration,
- boolean isDefaultBean) {
+ public ModuleInternalTransactionalInfo(ModuleIdentifier name, Module proxiedModule,
+ ModuleFactory moduleFactory,
+ ModuleInternalInfo maybeOldInternalInfo,
+ TransactionModuleJMXRegistration transactionModuleJMXRegistration,
+ boolean isDefaultBean, Module realModule) {
this.name = name;
- this.module = module;
+ this.proxiedModule = proxiedModule;
this.moduleFactory = moduleFactory;
this.maybeOldInternalInfo = maybeOldInternalInfo;
this.transactionModuleJMXRegistration = transactionModuleJMXRegistration;
this.isDefaultBean = isDefaultBean;
+ this.realModule = realModule;
}
}
- public Module getModule() {
- return module;
+ public Module getProxiedModule() {
+ return proxiedModule;
}
public ModuleFactory getModuleFactory() {
@Nullable
public ModuleInternalInfo getOldInternalInfo() {
- if (maybeOldInternalInfo == null)
+ if (maybeOldInternalInfo == null) {
throw new NullPointerException();
+ }
return maybeOldInternalInfo;
}
public boolean isDefaultBean() {
return isDefaultBean;
}
+
+ public Module getRealModule() {
+ return realModule;
+ }
}
import org.opendaylight.controller.config.api.JmxAttributeValidationException;
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.opendaylight.controller.config.manager.impl.CommitInfo;
-import org.opendaylight.controller.config.manager.impl.DestroyedModule;
-import org.opendaylight.controller.config.manager.impl.ModuleInternalTransactionalInfo;
+import org.opendaylight.controller.config.manager.impl.TransactionIdentifier;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
/**
* Represents modules to be committed.
*/
-class ModulesHolder implements TransactionHolder {
- private final String transactionName;
+class ModulesHolder {
+ private final TransactionIdentifier transactionIdentifier;
@GuardedBy("this")
private final Map<ModuleIdentifier, ModuleInternalTransactionalInfo> commitMap = new HashMap<>();
@GuardedBy("this")
private final Set<ModuleInternalTransactionalInfo> unorderedDestroyedFromPreviousTransactions = new HashSet<>();
- ModulesHolder(String transactionName) {
- this.transactionName = transactionName;
+ ModulesHolder(TransactionIdentifier transactionIdentifier) {
+ this.transactionIdentifier = transactionIdentifier;
}
- @Override
+
public CommitInfo toCommitInfo() {
List<DestroyedModule> orderedDestroyedFromPreviousTransactions = new ArrayList<>(
unorderedDestroyedFromPreviousTransactions.size());
.get(moduleIdentifier);
JmxAttributeValidationException.checkNotNull(
moduleInternalTransactionalInfo, "Module " + moduleIdentifier
- + "" + " not found in transaction " + transactionName,
+ + "" + " not found in transaction " + transactionIdentifier,
jmxAttributeForReporting);
return moduleInternalTransactionalInfo;
}
- @Override
public Module findModule(ModuleIdentifier moduleIdentifier,
JmxAttribute jmxAttributeForReporting) {
return findModuleInternalTransactionalInfo(moduleIdentifier,
- jmxAttributeForReporting).getModule();
+ jmxAttributeForReporting).getProxiedModule();
}
- @Override
public ModuleFactory findModuleFactory(ModuleIdentifier moduleIdentifier,
JmxAttribute jmxAttributeForReporting) {
return findModuleInternalTransactionalInfo(moduleIdentifier,
jmxAttributeForReporting).getModuleFactory();
}
- @Override
public Map<ModuleIdentifier, Module> getAllModules() {
Map<ModuleIdentifier, Module> result = new HashMap<>();
for (ModuleInternalTransactionalInfo entry : commitMap.values()) {
ModuleIdentifier name = entry.getIdentifier();
- result.put(name, entry.getModule());
+ result.put(name, entry.getProxiedModule());
}
return result;
}
- @Override
public void put(
ModuleInternalTransactionalInfo moduleInternalTransactionalInfo) {
commitMap.put(moduleInternalTransactionalInfo.getIdentifier(),
moduleInternalTransactionalInfo);
}
- @Override
public ModuleInternalTransactionalInfo destroyModule(
ModuleIdentifier moduleIdentifier) {
ModuleInternalTransactionalInfo found = commitMap.remove(moduleIdentifier);
return found;
}
- @Override
public void assertNotExists(ModuleIdentifier moduleIdentifier)
throws InstanceAlreadyExistsException {
if (commitMap.containsKey(moduleIdentifier)) {
return commitMap.values();
}
- @Override
public ModuleInternalTransactionalInfo findModuleInternalTransactionalInfo(ModuleIdentifier moduleIdentifier) {
ModuleInternalTransactionalInfo found = commitMap.get(moduleIdentifier);
if (found == null) {
+++ /dev/null
-/*
- * Copyright (c) 2013 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.config.manager.impl.dependencyresolver;
-
-import org.opendaylight.controller.config.api.JmxAttribute;
-import org.opendaylight.controller.config.api.ModuleIdentifier;
-import org.opendaylight.controller.config.manager.impl.CommitInfo;
-import org.opendaylight.controller.config.manager.impl.ModuleInternalTransactionalInfo;
-import org.opendaylight.controller.config.spi.Module;
-import org.opendaylight.controller.config.spi.ModuleFactory;
-
-import javax.management.InstanceAlreadyExistsException;
-import java.util.Map;
-
-interface TransactionHolder {
- CommitInfo toCommitInfo();
-
- Module findModule(ModuleIdentifier moduleIdentifier,
- JmxAttribute jmxAttributeForReporting);
-
- ModuleFactory findModuleFactory(ModuleIdentifier moduleIdentifier,
- JmxAttribute jmxAttributeForReporting);
-
- Map<ModuleIdentifier, Module> getAllModules();
-
- void put(ModuleInternalTransactionalInfo moduleInternalTransactionalInfo);
-
- ModuleInternalTransactionalInfo destroyModule(
- ModuleIdentifier moduleIdentifier);
-
- void assertNotExists(ModuleIdentifier moduleIdentifier)
- throws InstanceAlreadyExistsException;
-
- ModuleInternalTransactionalInfo findModuleInternalTransactionalInfo(ModuleIdentifier moduleIdentifier);
-
-}
* requests (getAttribute, setAttribute, invoke) into the actual instance, but
* provides additional functionality - namely it disallows setting attribute on
* a read only wrapper.
- *
*/
abstract class AbstractDynamicWrapper implements DynamicMBeanModuleWrapper {
private static final Logger logger = LoggerFactory
protected final MBeanServer internalServer;
public AbstractDynamicWrapper(Module module, boolean writable,
- ModuleIdentifier moduleIdentifier,
- ObjectName thisWrapperObjectName, MBeanOperationInfo[] dOperations,
- MBeanServer internalServer, MBeanServer configMBeanServer) {
+ ModuleIdentifier moduleIdentifier,
+ ObjectName thisWrapperObjectName, MBeanOperationInfo[] dOperations,
+ MBeanServer internalServer, MBeanServer configMBeanServer) {
this.writable = writable;
this.module = module;
* case unregister the module and remove listener.
*/
private final NotificationListener registerActualModule(Module module,
- final ObjectName thisWrapperObjectName,
- final ObjectName objectNameInternal,
- final MBeanServer internalServer,
- final MBeanServer configMBeanServer) {
+ final ObjectName thisWrapperObjectName,
+ final ObjectName objectNameInternal,
+ final MBeanServer internalServer,
+ final MBeanServer configMBeanServer) {
try {
internalServer.registerMBean(module, objectNameInternal);
public void handleNotification(Notification n, Object handback) {
if (n instanceof MBeanServerNotification
&& n.getType()
- .equals(MBeanServerNotification.UNREGISTRATION_NOTIFICATION)) {
+ .equals(MBeanServerNotification.UNREGISTRATION_NOTIFICATION)) {
if (((MBeanServerNotification) n).getMBeanName().equals(
thisWrapperObjectName)) {
try {
}
private static MBeanInfo generateMBeanInfo(String className, Module module,
- Map<String, AttributeHolder> attributeHolderMap,
- MBeanOperationInfo[] dOperations, Set<Class<?>> jmxInterfaces) {
+ Map<String, AttributeHolder> attributeHolderMap,
+ MBeanOperationInfo[] dOperations, Set<Class<?>> jmxInterfaces) {
String dDescription = findDescription(module.getClass(), jmxInterfaces);
MBeanConstructorInfo[] dConstructors = new MBeanConstructorInfo[0];
// inspect all exported interfaces ending with MXBean, extract getters &
// setters into attribute holder
private static Map<String, AttributeHolder> buildMBeanInfo(Module module,
- boolean writable, ModuleIdentifier moduleIdentifier,
- Set<Class<?>> jmxInterfaces, MBeanServer internalServer,
- ObjectName internalObjectName) {
+ boolean writable, ModuleIdentifier moduleIdentifier,
+ Set<Class<?>> jmxInterfaces, MBeanServer internalServer,
+ ObjectName internalObjectName) {
// internal variables for describing MBean elements
Set<Method> methods = new HashSet<>();
}
AttributeHolder attributeHolder = new AttributeHolder(
attribName, module, attributeMap.get(attribName)
- .getType(), writable, ifc, description);
+ .getType(), writable, ifc, description);
attributeHolderMap.put(attribName, attributeHolder);
}
}
}
- if(isDependencyListAttr(attributeName, obj)) {
+ if (isDependencyListAttr(attributeName, obj)) {
obj = fixDependencyListAttribute(obj);
}
}
private Object fixDependencyListAttribute(Object attribute) {
- if(attribute.getClass().isArray() == false)
+ if (attribute.getClass().isArray() == false) {
throw new IllegalArgumentException("Unexpected attribute type, should be an array, but was " + attribute.getClass());
+ }
for (int i = 0; i < Array.getLength(attribute); i++) {
Object on = Array.get(attribute, i);
- if(on instanceof ObjectName == false)
+ if (on instanceof ObjectName == false) {
throw new IllegalArgumentException("Unexpected attribute type, should be an ObjectName, but was " + on.getClass());
+ }
on = fixObjectName((ObjectName) on);
Array.set(attribute, i, on);
}
private boolean isDependencyListAttr(String attributeName, Object attribute) {
- if (attributeHolderMap.containsKey(attributeName) == false)
+ if (attributeHolderMap.containsKey(attributeName) == false) {
return false;
+ }
AttributeHolder attributeHolder = attributeHolderMap.get(attributeName);
}
protected ObjectName fixObjectName(ObjectName on) {
- if (!ObjectNameUtil.ON_DOMAIN.equals(on.getDomain()))
+ if (!ObjectNameUtil.ON_DOMAIN.equals(on.getDomain())) {
throw new IllegalArgumentException("Wrong domain, expected "
+ ObjectNameUtil.ON_DOMAIN + " setter on " + on);
+ }
// if on contains transaction name, remove it
String transactionName = ObjectNameUtil.getTransactionName(on);
- if (transactionName != null)
+ if (transactionName != null) {
return ObjectNameUtil.withoutTransactionName(on);
- else
+ } else {
return on;
+ }
}
@Override
*/
package org.opendaylight.controller.config.manager.impl.dynamicmbean;
+import org.opendaylight.controller.config.api.annotations.Description;
+
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
-import org.opendaylight.controller.config.api.annotations.Description;
-
-class AnnotationsHelper {
+public class AnnotationsHelper {
/**
* Look for annotation specified by annotationType on method. First observe
}
public AttributeHolder(String name, Object object, String returnType,
- boolean writable,
- @Nullable RequireInterface requireInterfaceAnnotation,
- String description) {
+ boolean writable,
+ @Nullable RequireInterface requireInterfaceAnnotation,
+ String description) {
if (name == null) {
throw new NullPointerException();
}
/**
* @return annotation if setter sets ObjectName or ObjectName[], and is
- * annotated. Return null otherwise.
+ * annotated. Return null otherwise.
*/
RequireInterface getRequireInterfaceOrNull() {
return requireInterfaceAnnotation;
* @param setter
* @param jmxInterfaces
* @return empty string if no annotation is found, or list of descriptions
- * separated by newline
+ * separated by newline
*/
static String findDescription(Method setter, Set<Class<?>> jmxInterfaces) {
List<Description> descriptions = AnnotationsHelper
*
* @param setter
* @param inspectedInterfaces
- * @throws IllegalStateException
- * if more than one value is specified by found annotations
- * @throws IllegalArgumentException
- * if set of exported interfaces contains non interface type
* @return null if no annotation is found, otherwise return the annotation
+ * @throws IllegalStateException if more than one value is specified by found annotations
+ * @throws IllegalArgumentException if set of exported interfaces contains non interface type
*/
static RequireInterface findRequireInterfaceAnnotation(final Method setter,
- Set<Class<?>> inspectedInterfaces) {
+ Set<Class<?>> inspectedInterfaces) {
// only allow setX(ObjectName y) or setX(ObjectName[] y) or setX(List<ObjectName> y) to continue
- if (setter.getParameterTypes().length > 1)
+ if (setter.getParameterTypes().length > 1) {
return null;
- if(PERMITTED_PARAMETER_TYPES_FOR_DEPENDENCY_SETTER.contains(setter.getParameterTypes()[0]) == false)
+ }
+ if (PERMITTED_PARAMETER_TYPES_FOR_DEPENDENCY_SETTER.contains(setter.getParameterTypes()[0]) == false) {
return null;
+ }
List<RequireInterface> foundRequireInterfaces = AnnotationsHelper
.findMethodAnnotationInSuperClassesAndIfcs(setter, RequireInterface.class, inspectedInterfaces);
try {
validate();
} catch (Exception e) {
- throw ValidationException.createForSingleException(
- moduleIdentifier, e);
+
+ throw new MBeanException(ValidationException.createForSingleException(
+ moduleIdentifier, e));
}
return Void.TYPE;
}
import org.opendaylight.controller.config.spi.ModuleFactory;
import org.osgi.framework.BundleContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import java.util.Map.Entry;
-import java.util.Set;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
-import java.util.Collections;
+import java.util.Map.Entry;
+import java.util.Set;
import java.util.TreeSet;
-import java.util.Collection;
-import java.util.ArrayList;
/**
* Hold sorted ConfigMBeanFactories by their module names. Check that module
* names are globally unique.
*/
public class HierarchicalConfigMBeanFactoriesHolder {
- private static final Logger logger = LoggerFactory
- .getLogger(HierarchicalConfigMBeanFactoriesHolder.class);
private final Map<String, Map.Entry<ModuleFactory, BundleContext>> moduleNamesToConfigBeanFactories;
private final Set<String> moduleNames;
*/
package org.opendaylight.controller.config.manager.impl.jmx;
-import java.io.Closeable;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import javax.annotation.concurrent.GuardedBy;
import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
import javax.management.JMX;
+import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
+import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.QueryExp;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import java.io.Closeable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
public class InternalJMXRegistrator implements Closeable {
private static final Logger logger = LoggerFactory
private final ObjectName on;
InternalJMXRegistration(InternalJMXRegistrator internalJMXRegistrator,
- ObjectName on) {
+ ObjectName on) {
this.internalJMXRegistrator = internalJMXRegistrator;
this.on = on;
}
private final List<InternalJMXRegistrator> children = new ArrayList<>();
public synchronized InternalJMXRegistration registerMBean(Object object,
- ObjectName on) throws InstanceAlreadyExistsException {
+ ObjectName on) throws InstanceAlreadyExistsException {
try {
configMBeanServer.registerMBean(object, on);
- } catch (InstanceAlreadyExistsException e) {
- throw e;
- } catch (Exception e) {
- throw new RuntimeException(e);
+ } catch (MBeanRegistrationException | NotCompliantMBeanException e) {
+ throw new IllegalStateException(e);
}
registeredObjectNames.add(on);
return new InternalJMXRegistration(this, on);
private synchronized void unregisterMBean(ObjectName on) {
// first check that on was registered using this instance
boolean removed = registeredObjectNames.remove(on);
- if (!removed)
- throw new IllegalStateException(
- "Cannot unregister - ObjectName not found in 'registeredObjectNames': "
- + on);
+ if (!removed) {
+ throw new IllegalStateException("Cannot unregister - ObjectName not found in 'registeredObjectNames': " + on);
+ }
try {
configMBeanServer.unregisterMBean(on);
- } catch (Exception e) {
- throw new RuntimeException(e);
+ } catch (InstanceNotFoundException | MBeanRegistrationException e) {
+ throw new IllegalStateException(e);
}
}
}
public <T> T newMBeanProxy(ObjectName objectName, Class<T> interfaceClass,
- boolean notificationBroadcaster) {
+ boolean notificationBroadcaster) {
return JMX.newMBeanProxy(configMBeanServer, objectName, interfaceClass,
notificationBroadcaster);
}
}
public <T> T newMXBeanProxy(ObjectName objectName, Class<T> interfaceClass,
- boolean notificationBroadcaster) {
+ boolean notificationBroadcaster) {
return JMX.newMXBeanProxy(configMBeanServer, objectName,
interfaceClass, notificationBroadcaster);
}
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
ServiceReference that = (ServiceReference) o;
- if (!refName.equals(that.refName)) return false;
- if (!serviceInterfaceName.equals(that.serviceInterfaceName)) return false;
+ if (!refName.equals(that.refName)) {
+ return false;
+ }
+ if (!serviceInterfaceName.equals(that.serviceInterfaceName)) {
+ return false;
+ }
return true;
}
*/
package org.opendaylight.controller.config.manager.impl.jmx;
-import java.io.Closeable;
-import java.util.Set;
+import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.config.manager.impl.jmx.InternalJMXRegistrator.InternalJMXRegistration;
import javax.management.InstanceAlreadyExistsException;
import javax.management.ObjectName;
import javax.management.QueryExp;
-
-import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
-import org.opendaylight.controller.config.manager.impl.jmx.InternalJMXRegistrator.InternalJMXRegistration;
+import java.io.Closeable;
+import java.util.Set;
/**
* Contains constraints on passed {@link ObjectName} parameters. Only allow (un)
private final String transactionName;
TransactionJMXRegistrator(InternalJMXRegistrator internalJMXRegistrator,
- String transactionName) {
+ String transactionName) {
this.childJMXRegistrator = internalJMXRegistrator.createChild();
this.transactionName = transactionName;
}
public TransactionJMXRegistration registerMBean(Object object, ObjectName on)
throws InstanceAlreadyExistsException {
- if (!transactionName.equals(ObjectNameUtil.getTransactionName(on)))
+ if (!transactionName.equals(ObjectNameUtil.getTransactionName(on))) {
throw new IllegalArgumentException(
"Transaction name mismatch between expected "
+ transactionName + " " + "and " + on);
+ }
ObjectNameUtil.checkType(on, ObjectNameUtil.TYPE_CONFIG_TRANSACTION);
return new TransactionJMXRegistration(
childJMXRegistrator.registerMBean(object, on));
package org.opendaylight.controller.config.manager.impl.osgi;
import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ValidationException;
import org.opendaylight.controller.config.api.jmx.CommitStatus;
import org.opendaylight.controller.config.manager.impl.ConfigRegistryImpl;
import org.opendaylight.controller.config.spi.ModuleFactory;
synchronized void blankTransaction() {
// race condition check: config-persister might push new configuration while server is starting up.
ConflictingVersionException lastException = null;
- for (int i = 0; i < 10; i++) {
+ int maxAttempts = 10;
+ for (int i = 0; i < maxAttempts; i++) {
try {
// create transaction
boolean blankTransaction = true;
Thread.currentThread().interrupt();
throw new IllegalStateException(interruptedException);
}
+ } catch (ValidationException e) {
+ logger.error("Validation exception while running blank transaction indicates programming error", e);
+ throw new RuntimeException("Validation exception while running blank transaction indicates programming error", e);
}
}
- throw lastException;
+ throw new RuntimeException("Maximal number of attempts reached and still cannot get optimistic lock from " +
+ "config manager",lastException);
}
@Override
if(factory == null) {
throw new NullPointerException("ServiceReference of class" + serviceReference.getClass() + "not found.");
}
- StringBuffer errors = new StringBuffer();
+
String moduleName = factory.getImplementationName();
if (moduleName == null || moduleName.isEmpty()) {
throw new IllegalStateException(
throw new NullPointerException("Bundle context of " + factory + " ModuleFactory not found.");
}
logger.debug("Reading factory {} {}", moduleName, factory);
- String error = null;
+
Map.Entry<ModuleFactory, BundleContext> conflicting = result.get(moduleName);
if (conflicting != null) {
- error = String
- .format("Module name is not unique. Found two conflicting factories with same name '%s': " +
- "\n\t%s\n\t%s\n", moduleName, conflicting.getKey(), factory);
-
- }
-
- if (error == null) {
+ String error = String
+ .format("Module name is not unique. Found two conflicting factories with same name '%s': '%s' '%s'",
+ moduleName, conflicting.getKey(), factory);
+ logger.error(error);
+ throw new IllegalArgumentException(error);
+ } else {
result.put(moduleName, new AbstractMap.SimpleImmutableEntry<>(factory,
serviceReference.getBundle().getBundleContext()));
- } else {
- errors.append(error);
- }
- if (errors.length() > 0) {
- throw new IllegalArgumentException(errors.toString());
}
}
return result;
private RuntimeGeneratedMappingServiceActivator mappingServiceActivator;
@Override
- public void start(BundleContext context) throws Exception {
+ public void start(BundleContext context) {
// track bundles containing YangModuleInfo
ModuleInfoBundleTracker moduleInfoBundleTracker = new ModuleInfoBundleTracker();
try {
configRegistryJMXRegistrator.registerToJMX(configRegistry);
} catch (InstanceAlreadyExistsException e) {
- throw new RuntimeException("Config Registry was already registered to JMX", e);
+ throw new IllegalStateException("Config Registry was already registered to JMX", e);
}
ServiceTracker<ModuleFactory, Object> serviceTracker = new ServiceTracker<>(context, ModuleFactory.class,
}
@Override
- public void stop(BundleContext context) throws Exception {
+ public void stop(BundleContext context) {
try {
configRegistry.close();
} catch (Exception e) {
import org.slf4j.LoggerFactory;
import java.io.InputStream;
-import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.Collection;
import java.util.LinkedList;
errorMessage = logMessage("Class {} does not implement {} in bundle {}", clazz, YangModelBindingProvider.class, bundle);
throw new IllegalStateException(errorMessage);
}
-
+ YangModelBindingProvider instance;
try {
- Object instance = clazz.newInstance();
- Object result = clazz.getMethod(GET_MODULE_INFO_METHOD).invoke(instance);
-
- if (YangModuleInfo.class.isAssignableFrom(result.getClass()) == false) {
- errorMessage = logMessage("Error invoking method not found {} in bundle {}, reason {}",
- GET_MODULE_INFO_METHOD, bundle, "Not assignable from " + YangModuleInfo.class);
- } else {
- return (YangModuleInfo) result;
- }
-
+ Object instanceObj = clazz.newInstance();
+ instance = YangModelBindingProvider.class.cast(instanceObj);
} catch (InstantiationException e) {
errorMessage = logMessage("Could not instantiate {} in bundle {}, reason {}", moduleInfoClass, bundle, e);
+ throw new IllegalStateException(errorMessage, e);
} catch (IllegalAccessException e) {
errorMessage = logMessage("Illegal access during instatiation of class {} in bundle {}, reason {}",
moduleInfoClass, bundle, e);
- } catch (NoSuchMethodException e) {
- errorMessage = logMessage("Method not found {} in bundle {}, reason {}", GET_MODULE_INFO_METHOD, bundle, e);
- } catch (InvocationTargetException e) {
- errorMessage = logMessage("Error invoking method {} in bundle {}, reason {}", GET_MODULE_INFO_METHOD,
- bundle, e);
+ throw new IllegalStateException(errorMessage, e);
}
+ try{
+ return instance.getModuleInfo();
+ } catch (NoClassDefFoundError e) {
- throw new IllegalStateException(errorMessage);
+
+ logger.error("Error while executing getModuleInfo on {}", instance, e);
+ throw e;
+ }
}
private static Class<?> loadClass(String moduleInfoClass, Bundle bundle) {
*/
package org.opendaylight.controller.config.manager.impl.dependencyresolver;
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.reset;
-
-import java.util.Arrays;
-import java.util.List;
-
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.config.api.JmxAttribute;
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
-import org.opendaylight.controller.config.manager.impl.ModuleInternalTransactionalInfo;
+import org.opendaylight.controller.config.manager.impl.ModuleInternalInfo;
+import org.opendaylight.controller.config.manager.impl.TransactionIdentifier;
import org.opendaylight.controller.config.manager.impl.TransactionStatus;
+import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator.TransactionModuleJMXRegistration;
import org.opendaylight.controller.config.spi.Module;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
public class DependencyResolverManagerTest {
public void setUp() {
transactionStatus = mock(TransactionStatus.class);
ServiceReferenceReadableRegistry mockedRegistry = mock(ServiceReferenceReadableRegistry.class);
- tested = new DependencyResolverManager("txName", transactionStatus, mockedRegistry, null);
+ tested = new DependencyResolverManager(new TransactionIdentifier("txName"), transactionStatus, mockedRegistry, null);
doNothing().when(transactionStatus).checkCommitStarted();
doNothing().when(transactionStatus).checkNotCommitted();
}
private static void mockGetInstance(DependencyResolverManager tested,
ModuleIdentifier moduleIdentifier) {
- ModuleInternalTransactionalInfo mock = mock(ModuleInternalTransactionalInfo.class);
- doReturn(moduleIdentifier).when(mock).getIdentifier();
- doReturn(mockedModule()).when(mock).getModule();
- tested.put(mock);
+
+ ModuleFactory moduleFactory = mock(ModuleFactory.class);
+ ModuleInternalInfo maybeOldInternalInfo = null;
+ TransactionModuleJMXRegistration transactionModuleJMXRegistration = null;
+ boolean isDefaultBean = false;
+
+ tested.put(moduleIdentifier,
+ mockedModule(),
+ moduleFactory,
+ maybeOldInternalInfo,
+ transactionModuleJMXRegistration,
+ isDefaultBean);
}
private static Module mockedModule() {
*/
package org.opendaylight.controller.config.manager.testingservices.parallelapsp;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-
-import java.io.Closeable;
-
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.NotThreadSafe;
-import javax.management.ObjectName;
-
+import com.google.common.base.Strings;
import org.opendaylight.controller.config.api.DependencyResolver;
import org.opendaylight.controller.config.api.JmxAttribute;
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Strings;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.NotThreadSafe;
+import javax.management.ObjectName;
+import java.io.Closeable;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
/**
* Represents service that has dependency to thread pool.
import javax.management.MBeanException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
-import javax.management.RuntimeMBeanException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
private void testValidation(ConfigTransactionClient transaction)
throws InstanceAlreadyExistsException, ReflectionException,
- InstanceNotFoundException, MBeanException {
+ InstanceNotFoundException, MBeanException, ConflictingVersionException {
ObjectName fixed1names = transaction.createModule(
TestingFixedThreadPoolModuleFactory.NAME, fixed1);
// call validate on config bean
platformMBeanServer.invoke(fixed1names, "validate", new Object[0],
new String[0]);
fail();
- } catch (RuntimeMBeanException e) {
- RuntimeException targetException = e.getTargetException();
+ } catch (MBeanException e) {
+ Exception targetException = e.getTargetException();
assertNotNull(targetException);
assertEquals(ValidationException.class, targetException.getClass());
}
}
@Test
- public void testAbort() {
+ public void testAbort() throws InstanceAlreadyExistsException, ValidationException {
ConfigTransactionJMXClient transaction = configRegistryClient
.createTransaction();
assertEquals(1, configRegistryClient.getOpenConfigs().size());
transaction.createModule(TestingFixedThreadPoolModuleFactory.NAME,
fixed1);
fail();
- } catch (Exception e) {
- assertTrue(e.getCause() instanceof InstanceNotFoundException);
+ } catch (IllegalStateException e) {
+ assertEquals("Configuration was aborted", e.getMessage());
}
try {
transaction.validateConfig();
fail();
- } catch (Exception e) {
- assertTrue(e.getCause() instanceof InstanceNotFoundException);
+ } catch (IllegalStateException e) {
+ assertEquals("Configuration was aborted", e.getMessage());
}
assertEquals(0, configRegistryClient.getOpenConfigs().size());
}
<parent>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-subsystem</artifactId>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
</parent>
<artifactId>config-module-archetype</artifactId>
<parent>
<artifactId>config-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>config-persister-api</artifactId>
<parent>
<artifactId>config-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>config-persister-directory-adapter</artifactId>
<parent>
<artifactId>config-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>config-persister-directory-autodetect-adapter</artifactId>
<parent>
<artifactId>config-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>config-persister-directory-xml-adapter</artifactId>
<parent>
<artifactId>config-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>config-persister-file-adapter</artifactId>
<parent>
<artifactId>config-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>config-persister-file-xml-adapter</artifactId>
<parent>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-subsystem</artifactId>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>config-plugin-parent</artifactId>
<properties>
<jmxGeneratorPath>${project.build.directory}/generated-sources/config</jmxGeneratorPath>
- <config.version>0.2.4-SNAPSHOT</config.version>
</properties>
<build>
<parent>
<artifactId>config-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>config-util</artifactId>
*/
package org.opendaylight.controller.config.util;
-import java.util.Map;
-import java.util.Set;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.config.api.jmx.ConfigRegistryMXBean;
+import org.opendaylight.controller.config.api.jmx.ConfigTransactionControllerMXBean;
+import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
import javax.management.Attribute;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.JMException;
import javax.management.JMX;
+import javax.management.MBeanException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
-import javax.management.RuntimeMBeanException;
-
-import org.opendaylight.controller.config.api.ConflictingVersionException;
-import org.opendaylight.controller.config.api.ValidationException;
-import org.opendaylight.controller.config.api.jmx.CommitStatus;
-import org.opendaylight.controller.config.api.jmx.ConfigRegistryMXBean;
-import org.opendaylight.controller.config.api.jmx.ConfigTransactionControllerMXBean;
-import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import java.util.Map;
+import java.util.Set;
public class ConfigTransactionJMXClient implements ConfigTransactionClient {
private final ConfigRegistryMXBean configRegistryMXBeanProxy;
throws ValidationException {
try {
configMBeanServer.invoke(configBeanON, "validate", null, null);
+ } catch (MBeanException e) {
+ Exception targetException = e.getTargetException();
+ if (targetException instanceof ValidationException){
+ throw (ValidationException) targetException;
+ } else {
+ throw new RuntimeException(e);
+ }
} catch (JMException e) {
throw new RuntimeException(e);
- } catch (RuntimeMBeanException e) {
- throw e.getTargetException();
}
}
<parent>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-plugin-parent</artifactId>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
<relativePath>../config-plugin-parent</relativePath>
</parent>
<artifactId>logback-config</artifactId>
*/
package org.opendaylight.controller.config.yang.logback.config;
-import static org.junit.Assert.assertEquals;
-
-import java.io.File;
-import java.io.IOException;
-import java.lang.management.ManagementFactory;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InstanceNotFoundException;
-import javax.management.JMX;
-import javax.management.MalformedObjectNameException;
-import javax.management.ObjectName;
-
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
+import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.joran.spi.JoranException;
+import ch.qos.logback.core.rolling.FixedWindowRollingPolicy;
+import ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy;
+import com.google.common.collect.Lists;
import org.apache.commons.io.FileUtils;
import org.junit.Before;
import org.junit.Test;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ValidationException;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
import org.slf4j.LoggerFactory;
-import ch.qos.logback.classic.LoggerContext;
-import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
-import ch.qos.logback.classic.joran.JoranConfigurator;
-import ch.qos.logback.classic.spi.ILoggingEvent;
-import ch.qos.logback.core.joran.spi.JoranException;
-import ch.qos.logback.core.rolling.FixedWindowRollingPolicy;
-import ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.JMX;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+import java.io.File;
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
-import com.google.common.collect.Lists;
+import static org.junit.Assert.assertEquals;
public class LogbackModuleWithInitialConfigurationTest extends AbstractConfigTest {
}
public ObjectName createBeans() throws JoranException, InstanceAlreadyExistsException, IOException,
- MalformedObjectNameException, InstanceNotFoundException {
+ MalformedObjectNameException, InstanceNotFoundException, ValidationException, ConflictingVersionException {
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
*/
package org.opendaylight.controller.config.yang.logback.config;
-import static org.junit.Assert.assertEquals;
-
-import java.io.File;
-import java.io.IOException;
-import java.lang.management.ManagementFactory;
-import java.util.List;
-
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InstanceNotFoundException;
-import javax.management.JMX;
-import javax.management.MalformedObjectNameException;
-import javax.management.ObjectName;
-
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.core.joran.spi.JoranException;
+import com.google.common.collect.Lists;
import org.apache.commons.io.FileUtils;
import org.junit.Before;
import org.junit.Test;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ValidationException;
import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
import org.slf4j.LoggerFactory;
-import ch.qos.logback.classic.LoggerContext;
-import ch.qos.logback.classic.joran.JoranConfigurator;
-import ch.qos.logback.core.joran.spi.JoranException;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.JMX;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+import java.io.File;
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.util.List;
-import com.google.common.collect.Lists;
+import static org.junit.Assert.assertEquals;
public class LogbackWithXmlConfigModuleTest extends AbstractConfigTest {
* @throws MalformedObjectNameException
*/
@Test
- public void test() throws InstanceAlreadyExistsException, InstanceNotFoundException, MalformedObjectNameException {
+ public void test() throws InstanceAlreadyExistsException, InstanceNotFoundException, MalformedObjectNameException, ValidationException, ConflictingVersionException {
ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
ObjectName nameRetrieved = transaction.lookupConfigBean(factory.getImplementationName(), LogbackModuleFactory.INSTANCE_NAME);
*/
@Test
public void testAddNewLogger() throws InstanceAlreadyExistsException, InstanceNotFoundException,
- MalformedObjectNameException {
+ MalformedObjectNameException, ValidationException, ConflictingVersionException {
ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
ObjectName nameRetrieved = transaction.lookupConfigBean(factory.getImplementationName(), LogbackModuleFactory.INSTANCE_NAME);
<parent>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-plugin-parent</artifactId>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
<relativePath>../config-plugin-parent</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-plugin-parent</artifactId>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
<relativePath>../config-plugin-parent</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
--- /dev/null
+/*
+ * Copyright (c) 2013 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.config.yang.netty.eventexecutor;
+
+import com.google.common.reflect.AbstractInvocationHandler;
+import com.google.common.reflect.Reflection;
+import io.netty.util.concurrent.EventExecutor;
+
+import java.lang.reflect.Method;
+import java.util.concurrent.TimeUnit;
+
+public interface AutoCloseableEventExecutor extends EventExecutor, AutoCloseable {
+
+
+ public static class CloseableEventExecutorMixin implements AutoCloseable {
+ public static final int DEFAULT_SHUTDOWN_SECONDS = 1;
+ private final EventExecutor eventExecutor;
+
+ public CloseableEventExecutorMixin(EventExecutor eventExecutor) {
+ this.eventExecutor = eventExecutor;
+ }
+
+ @Override
+ public void close() {
+ eventExecutor.shutdownGracefully(0, DEFAULT_SHUTDOWN_SECONDS, TimeUnit.SECONDS);
+ }
+
+
+ public static AutoCloseable createCloseableProxy(final EventExecutor eventExecutor) {
+ final CloseableEventExecutorMixin closeableGlobalEventExecutorMixin =
+ new CloseableEventExecutorMixin(eventExecutor);
+ return Reflection.newProxy(AutoCloseableEventExecutor.class, new AbstractInvocationHandler() {
+ @Override
+ protected Object handleInvocation(Object proxy, Method method, Object[] args) throws Throwable {
+ if (method.getName().equals("close")) {
+ closeableGlobalEventExecutorMixin.close();
+ return null;
+ } else {
+ return method.invoke(eventExecutor, args);
+ }
+ }
+ });
+ }
+
+
+ }
+}
\ No newline at end of file
*/
package org.opendaylight.controller.config.yang.netty.eventexecutor;
-import com.google.common.reflect.AbstractInvocationHandler;
-import com.google.common.reflect.Reflection;
import io.netty.util.concurrent.EventExecutor;
import io.netty.util.concurrent.GlobalEventExecutor;
-
-import java.lang.reflect.Method;
-import java.util.concurrent.TimeUnit;
+import org.opendaylight.controller.config.yang.netty.eventexecutor.AutoCloseableEventExecutor.CloseableEventExecutorMixin;
public final class GlobalEventExecutorModule extends
org.opendaylight.controller.config.yang.netty.eventexecutor.AbstractGlobalEventExecutorModule {
@Override
public java.lang.AutoCloseable createInstance() {
- final CloseableGlobalEventExecutorMixin closeableGlobalEventExecutorMixin =
- new CloseableGlobalEventExecutorMixin(GlobalEventExecutor.INSTANCE);
- return Reflection.newProxy(AutoCloseableEventExecutor.class, new AbstractInvocationHandler() {
- @Override
- protected Object handleInvocation(Object proxy, Method method, Object[] args) throws Throwable {
- if (method.getName().equals("close")) {
- closeableGlobalEventExecutorMixin.close();
- return null;
- } else {
- return method.invoke(GlobalEventExecutor.INSTANCE, args);
- }
- }
- });
+ EventExecutor eventExecutor = GlobalEventExecutor.INSTANCE;
+ return CloseableEventExecutorMixin.createCloseableProxy(eventExecutor);
}
- public static interface AutoCloseableEventExecutor extends EventExecutor, AutoCloseable {
-
- }
- public static class CloseableGlobalEventExecutorMixin implements AutoCloseable {
- private final GlobalEventExecutor eventExecutor;
- public CloseableGlobalEventExecutorMixin(GlobalEventExecutor eventExecutor) {
- this.eventExecutor = eventExecutor;
- }
-
- @Override
- public void close() {
- eventExecutor.shutdownGracefully(0, 1, TimeUnit.SECONDS);
- }
- }
}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.config.yang.netty.eventexecutor;
+
+import io.netty.util.concurrent.EventExecutor;
+import io.netty.util.concurrent.ImmediateEventExecutor;
+import org.opendaylight.controller.config.yang.netty.eventexecutor.AutoCloseableEventExecutor.CloseableEventExecutorMixin;
+
+public final class ImmediateEventExecutorModule extends org.opendaylight.controller.config.yang.netty.eventexecutor.AbstractImmediateEventExecutorModule {
+
+ public ImmediateEventExecutorModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public ImmediateEventExecutorModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+ ImmediateEventExecutorModule oldModule, java.lang.AutoCloseable oldInstance) {
+
+ super(identifier, dependencyResolver, oldModule, oldInstance);
+ }
+
+ @Override
+ protected void customValidation() {
+ // Add custom validation for module attributes here.
+ }
+
+ @Override
+ public java.lang.AutoCloseable createInstance() {
+ EventExecutor eventExecutor = ImmediateEventExecutor.INSTANCE;
+ return CloseableEventExecutorMixin.createCloseableProxy(eventExecutor);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.config.yang.netty.eventexecutor;
+
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.osgi.framework.BundleContext;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+public class ImmediateEventExecutorModuleFactory extends org.opendaylight.controller.config.yang.netty.eventexecutor.AbstractImmediateEventExecutorModuleFactory {
+ public static final String SINGLETON_NAME = "singleton";
+
+ @Override
+ public ImmediateEventExecutorModule instantiateModule(String instanceName, DependencyResolver dependencyResolver, ImmediateEventExecutorModule oldModule, AutoCloseable oldInstance, BundleContext bundleContext) {
+ checkArgument(SINGLETON_NAME.equals(instanceName), "Illegal instance name '" + instanceName + "', only allowed name is " + SINGLETON_NAME);
+ return super.instantiateModule(instanceName, dependencyResolver, oldModule, oldInstance, bundleContext);
+ }
+
+ @Override
+ public ImmediateEventExecutorModule instantiateModule(String instanceName, DependencyResolver dependencyResolver, BundleContext bundleContext) {
+ checkArgument(SINGLETON_NAME.equals(instanceName), "Illegal instance name '" + instanceName + "', only allowed name is " + SINGLETON_NAME);
+ return super.instantiateModule(instanceName, dependencyResolver, bundleContext);
+ }
+}
augment "/config:modules/config:module/config:configuration" {
case netty-global-event-executor {
when "/config:modules/config:module/config:type = 'netty-global-event-executor'";
+ }
+ }
+ identity netty-immediate-event-executor {
+ base config:module-type;
+ config:provided-service netty:netty-event-executor;
+ config:java-name-prefix ImmediateEventExecutor;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case netty-immediate-event-executor {
+ when "/config:modules/config:module/config:type = 'netty-immediate-event-executor'";
}
}
}
<parent>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-plugin-parent</artifactId>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
<relativePath>../config-plugin-parent</relativePath>
</parent>
<parent>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-plugin-parent</artifactId>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
<relativePath>../config-plugin-parent</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
</parent>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
<artifactId>config-subsystem</artifactId>
<packaging>pom</packaging>
<name>${project.artifactId}</name>
<jacoco.version>0.6.2.201302030002</jacoco.version>
<slf4j.version>1.7.2</slf4j.version>
<salGeneratorPath>${project.build.directory}/generated-sources/sal</salGeneratorPath>
- <config.version>0.2.4-SNAPSHOT</config.version>
</properties>
<dependencies>
<parent>
<artifactId>config-plugin-parent</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
<relativePath>../config-plugin-parent</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>config-plugin-parent</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
<relativePath>../config-plugin-parent</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ValidationException;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
shutdownViaRuntimeJMX(secret);
}
- private void setSecret(String secret) throws InstanceNotFoundException {
+ private void setSecret(String secret) throws InstanceNotFoundException, ValidationException, ConflictingVersionException {
ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
ObjectName on = transaction.lookupConfigBean(NAME, NAME);
ShutdownModuleMXBean proxy = transaction.newMXBeanProxy(on, ShutdownModuleMXBean.class);
<parent>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-plugin-parent</artifactId>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
<relativePath>../config-plugin-parent</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-plugin-parent</artifactId>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
<relativePath>../config-plugin-parent</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>config-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
</parent>
<artifactId>yang-jmx-generator-it</artifactId>
<parent>
<artifactId>config-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>yang-jmx-generator-plugin</artifactId>
ftlFile.getFtlTempleteLocation());
try {
template.process(ftlFile, writer);
- } catch (Throwable e) {
+ } catch (Exception e) {
throw new IllegalStateException(
"Template error while generating " + ftlFile, e);
}
<parent>
<artifactId>config-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
</parent>
<artifactId>yang-jmx-generator</artifactId>
boolean providedServiceWasSet = false;
for (UnknownSchemaNode unknownNode : id.getUnknownSchemaNodes()) {
// TODO: test this
- if (ConfigConstants.PROVIDED_SERVICE_EXTENSION_QNAME.equals(unknownNode.getNodeType())) {
- // no op: 0 or more provided identities are allowed
- } else if (ConfigConstants.JAVA_NAME_PREFIX_EXTENSION_QNAME.equals(unknownNode.getNodeType())) {
+ boolean unknownNodeIsProvidedServiceExtension = ConfigConstants.PROVIDED_SERVICE_EXTENSION_QNAME.equals(unknownNode.getNodeType());
+ // true => no op: 0 or more provided identities are allowed
+
+ if (ConfigConstants.JAVA_NAME_PREFIX_EXTENSION_QNAME.equals(unknownNode.getNodeType())) {
// 0..1 allowed
checkState(
providedServiceWasSet == false,
format("More than one language extension %s is not allowed here: %s",
ConfigConstants.JAVA_NAME_PREFIX_EXTENSION_QNAME, id));
providedServiceWasSet = true;
- } else {
+ } else if (unknownNodeIsProvidedServiceExtension == false) {
throw new IllegalStateException("Unexpected language extension " + unknownNode.getNodeType());
}
}
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.OpenType;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
@Override
public CompositeType getOpenType() {
- String description = getNullableDescription() == null ? getAttributeYangName()
- : getNullableDescription();
- final String[] itemNames = new String[yangNameToAttributeMap.keySet()
- .size()];
- String[] itemDescriptions = itemNames;
- FunctionImpl functionImpl = new FunctionImpl(itemNames);
+ String description = getNullableDescription() == null ? getAttributeYangName() : getNullableDescription();
+
+ FunctionImpl functionImpl = new FunctionImpl();
Map<String, AttributeIfc> jmxPropertiesToTypesMap = getJmxPropertiesToTypesMap();
OpenType<?>[] itemTypes = Collections2.transform(
jmxPropertiesToTypesMap.entrySet(), functionImpl).toArray(
new OpenType<?>[] {});
+ String[] itemNames = functionImpl.getItemNames();
try {
// TODO add package name to create fully qualified name for this
// type
CompositeType compositeType = new CompositeType(
getUpperCaseCammelCase(), description, itemNames,
- itemDescriptions, itemTypes);
+ itemNames, itemTypes);
return compositeType;
} catch (OpenDataException e) {
throw new RuntimeException("Unable to create CompositeType for "
return packageName;
}
- private static final class FunctionImpl implements
- Function<Entry<String, AttributeIfc>, OpenType<?>> {
- private final String[] itemNames;
- int i = 0;
+}
- private FunctionImpl(String[] itemNames) {
- this.itemNames = itemNames;
- }
+class FunctionImpl implements
+ Function<Entry<String, AttributeIfc>, OpenType<?>> {
+ private final List<String> itemNames = new ArrayList<>();
- @Override
- public OpenType<?> apply(Entry<String, AttributeIfc> input) {
- AttributeIfc innerType = input.getValue();
- itemNames[i++] = input.getKey();
- return innerType.getOpenType();
- }
+ @Override
+ public OpenType<?> apply(Entry<String, AttributeIfc> input) {
+ AttributeIfc innerType = input.getValue();
+ itemNames.add(input.getKey());
+ return innerType.getOpenType();
+ }
+
+ public String[] getItemNames(){
+ return itemNames.toArray(new String[itemNames.size()]);
}
}
<parent>
<artifactId>config-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>yang-store-api</artifactId>
<parent>
<artifactId>config-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>yang-store-impl</artifactId>
<parent>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-plugin-parent</artifactId>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
<relativePath>../config-plugin-parent</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-plugin-parent</artifactId>
- <version>0.2.4-SNAPSHOT</version>
+ <version>0.2.5-SNAPSHOT</version>
<relativePath>../config-plugin-parent</relativePath>
</parent>
@Override
public java.lang.AutoCloseable createInstance() {
- System.err.println(getAfi());
- System.err.println(getAfiIdentity());
+ org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(getClass());
+ logger.info("Afi: {}", getAfi());
+ logger.info("Afi class: {}", getAfiIdentity());
- getAfiIdentity();
for (Identities identities : getIdentities()) {
- identities.resolveAfi();
- identities.resolveSafi();
+ logger.info("Identities Afi class: {}", identities.resolveAfi());
+ logger.info("Identities Safi class: {}", identities.resolveSafi());
+
}
- getIdentitiesContainer().resolveAfi();
+ logger.info("IdentityContainer Afi class: {}", getIdentitiesContainer().resolveAfi());
return new AutoCloseable() {
@Override
- System.err.println(getAfi());
- System.err.println(getAfiIdentity());
+ org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(getClass());
+ logger.info("Afi: {}", getAfi());
+ logger.info("Afi class: {}", getAfiIdentity());
- getAfiIdentity();
for (Identities identities : getIdentities()) {
- identities.resolveAfi();
- identities.resolveSafi();
+ logger.info("Identities Afi class: {}", identities.resolveAfi());
+ logger.info("Identities Safi class: {}", identities.resolveSafi());
+
}
- getIdentitiesContainer().resolveAfi();
+ logger.info("IdentityContainer Afi class: {}", getIdentitiesContainer().resolveAfi());
return new AutoCloseable() {
@Override
fi
function usage {
- echo "Usage: $0 [-jmx] [-jmxport <num>] [-debug] [-debugsuspend] [-debugport <num>] [-start [<console port>]] [-stop] [-status] [-console] [-help] [<other args will automatically be used for the JVM>]"
+ echo "Usage: $0 [-jmx] [-jmxport <num>] [-debug] [-debugsuspend] [-debugport <num>] [-start [<console port>]] [-stop] [-status] [-console] [-help] [-agentpath:<path to lib>] [<other args will automatically be used for the JVM>]"
exit 1
}
consolestart=1
dohelp=0
extraJVMOpts=""
+agentPath=""
unknown_option=0
while true ; do
case "$1" in
-help) dohelp=1; shift;;
-D*) extraJVMOpts="${extraJVMOpts} $1"; shift;;
-X*) extraJVMOpts="${extraJVMOpts} $1"; shift;;
+ -agentpath:*) agentPath="$1"; shift;;
"") break ;;
*) echo "Unknown option $1"; unknown_option=1; shift ;;
esac
exit -1
fi
$JAVA_HOME/bin/java ${extraJVMOpts} \
+ ${agentPath} \
-Djava.io.tmpdir="${iotmpdir}/work/tmp" \
-Dosgi.install.area="${bdir}" \
-Dosgi.configuration.area="${confarea}/configuration" \
exit -1
fi
$JAVA_HOME/bin/java ${extraJVMOpts} \
+ ${agentPath} \
-Djava.io.tmpdir="${iotmpdir}/work/tmp" \
-Dosgi.install.area="${bdir}" \
-Dosgi.configuration.area="${confarea}/configuration" \
List<FlowEntryInstall> list = new ArrayList<FlowEntryInstall>(groupFlows.get(groupName));
toBeRemoved = list.size();
for (FlowEntryInstall entry : list) {
- Status status = this.removeEntry(entry.getOriginal(), false);
+ // since this is the entry that was stored in groupFlows
+ // it is already validated and merged
+ // so can call removeEntryInternal directly
+ Status status = this.removeEntryInternal(entry, false);
if (status.isSuccess()) {
toBeRemoved -= 1;
} else {
package org.opendaylight.controller.sal.compatibility.adsal;
import java.math.BigInteger;
-import java.util.concurrent.Future;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
-import org.opendaylight.controller.sal.common.util.Futures;
import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.controller.sal.compatibility.InventoryMapping;
import org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
public class FlowServiceAdapter implements SalFlowService, IFlowProgrammerListener {
private static final Logger LOG = LoggerFactory.getLogger(FlowServiceAdapter.class);
}
@Override
- public Future<RpcResult<AddFlowOutput>> addFlow(AddFlowInput input) {
+ public ListenableFuture<RpcResult<AddFlowOutput>> addFlow(AddFlowInput input) {
Flow flow = ToSalConversionsUtils.toFlow(input, null);
@SuppressWarnings("unchecked")
}
@Override
- public Future<RpcResult<RemoveFlowOutput>> removeFlow(RemoveFlowInput input) {
+ public ListenableFuture<RpcResult<RemoveFlowOutput>> removeFlow(RemoveFlowInput input) {
Flow flow = ToSalConversionsUtils.toFlow(input, null);
@SuppressWarnings("unchecked")
}
@Override
- public Future<RpcResult<UpdateFlowOutput>> updateFlow(UpdateFlowInput input) {
+ public ListenableFuture<RpcResult<UpdateFlowOutput>> updateFlow(UpdateFlowInput input) {
@SuppressWarnings("unchecked")
org.opendaylight.controller.sal.core.Node node = InventoryMapping.toAdNode((InstanceIdentifier<Node>) input
.getNode().getValue());
import java.util.concurrent.Future;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
-import org.opendaylight.controller.sal.common.util.Futures;
import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.controller.sal.compatibility.FromSalConversionsUtils;
import org.opendaylight.controller.sal.compatibility.InventoryMapping;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
public class FlowStatisticsAdapter implements OpendaylightFlowStatisticsService, IReadServiceListener{
private static final Logger LOG = LoggerFactory.getLogger(FlowStatisticsAdapter.class);
@Override
public Future<RpcResult<GetAggregateFlowStatisticsFromFlowTableForAllFlowsOutput>> getAggregateFlowStatisticsFromFlowTableForAllFlows(
GetAggregateFlowStatisticsFromFlowTableForAllFlowsInput input) {
- //TODO: No supported API exist in AD-SAL, it can either be implemented by fetching all the stats of the flows and
+ //TODO: No supported API exist in AD-SAL, it can either be implemented by fetching all the stats of the flows and
// generating aggregate flow statistics out of those individual flow stats.
return null;
}
@Override
public Future<RpcResult<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput>> getAggregateFlowStatisticsFromFlowTableForGivenMatch(
GetAggregateFlowStatisticsFromFlowTableForGivenMatchInput input) {
- //TODO: No supported API exist in AD-SAL, it can either be implemented by fetching all the stats of the flows and
+ //TODO: No supported API exist in AD-SAL, it can either be implemented by fetching all the stats of the flows and
// generating aggregate flow statistics out of those individual flow stats.
return null;
}
@Override
- public Future<RpcResult<GetAllFlowStatisticsFromFlowTableOutput>> getAllFlowStatisticsFromFlowTable(
+ public ListenableFuture<RpcResult<GetAllFlowStatisticsFromFlowTableOutput>> getAllFlowStatisticsFromFlowTable(
GetAllFlowStatisticsFromFlowTableInput input) {
GetAllFlowStatisticsFromFlowTableOutput rpcResultType = null;
boolean rpcResultBool = false;
GetAllFlowStatisticsFromFlowTableOutputBuilder builder = new GetAllFlowStatisticsFromFlowTableOutputBuilder();
builder.setTransactionId(new TransactionId(new BigInteger("0")));
rpcResultType = builder.setFlowAndStatisticsMapList(flowsStatistics).build();
-
+
rpcResultBool = true;
} catch (ConstructionException e) {
LOG.error(e.getMessage());
* Essentially this API will return the same result as getAllFlowStatisticsFromFlowTable
*/
@Override
- public Future<RpcResult<GetAllFlowsStatisticsFromAllFlowTablesOutput>> getAllFlowsStatisticsFromAllFlowTables(
+ public ListenableFuture<RpcResult<GetAllFlowsStatisticsFromAllFlowTablesOutput>> getAllFlowsStatisticsFromAllFlowTables(
GetAllFlowsStatisticsFromAllFlowTablesInput input) {
-
+
GetAllFlowsStatisticsFromAllFlowTablesOutput rpcResultType = null;
boolean rpcResultBool = false;
GetAllFlowsStatisticsFromAllFlowTablesOutputBuilder builder = new GetAllFlowsStatisticsFromAllFlowTablesOutputBuilder();
builder.setTransactionId(new TransactionId(new BigInteger("0")));
rpcResultType = builder.setFlowAndStatisticsMapList(flowsStatistics).build();
-
+
rpcResultBool = true;
} catch (ConstructionException e) {
LOG.error(e.getMessage());
}
@Override
- public Future<RpcResult<GetFlowStatisticsFromFlowTableOutput>> getFlowStatisticsFromFlowTable(
+ public ListenableFuture<RpcResult<GetFlowStatisticsFromFlowTableOutput>> getFlowStatisticsFromFlowTable(
GetFlowStatisticsFromFlowTableInput input) {
GetFlowStatisticsFromFlowTableOutput rpcResultType = null;
boolean rpcResultBool = false;
public void nodeConnectorStatisticsUpdated(Node node, List<NodeConnectorStatistics> ncStatsList) {
NodeConnectorStatisticsUpdateBuilder nodeConnectorStatisticsUpdateBuilder = new NodeConnectorStatisticsUpdateBuilder();
List<NodeConnectorStatisticsAndPortNumberMap> nodeConnectorStatistics = toOdNodeConnectorStatistics(ncStatsList);
-
+
nodeConnectorStatisticsUpdateBuilder.setNodeConnectorStatisticsAndPortNumberMap(nodeConnectorStatistics);
nodeConnectorStatisticsUpdateBuilder.setMoreReplies(false);
nodeConnectorStatisticsUpdateBuilder.setTransactionId(null);
@Override
public void nodeTableStatisticsUpdated(Node node, List<NodeTableStatistics> tableStatsList) {
-
- FlowTableStatisticsUpdateBuilder flowTableStatisticsUpdateBuilder = new FlowTableStatisticsUpdateBuilder();
-
+
+ FlowTableStatisticsUpdateBuilder flowTableStatisticsUpdateBuilder = new FlowTableStatisticsUpdateBuilder();
+
List<FlowTableAndStatisticsMap> flowTableStatistics = toOdFlowTableStatistics(tableStatsList);
flowTableStatisticsUpdateBuilder.setFlowTableAndStatisticsMap(flowTableStatistics);
flowTableStatisticsUpdateBuilder.setMoreReplies(false);
@Override
public void descriptionStatisticsUpdated(Node node, NodeDescription nodeDescription) {
// TODO which *StatisticsUpdated interface should be used?
-
+
}
private List<FlowAndStatisticsMapList> toOdFlowsStatistics(List<FlowOnNode> flowsOnNode) {
}
private List<FlowTableAndStatisticsMap> toOdFlowTableStatistics(List<NodeTableStatistics> tableStatsList) {
-
+
List<FlowTableAndStatisticsMap> flowTableStatsMap = new ArrayList<FlowTableAndStatisticsMap>();
for (NodeTableStatistics nodeTableStatistics : tableStatsList) {
FlowTableAndStatisticsMapBuilder flowTableAndStatisticsMapBuilder = new FlowTableAndStatisticsMapBuilder();
flowTableAndStatisticsMapBuilder.setTableId(new TableId((short)nodeTableStatistics.getNodeTable().getID()));
flowTableStatsMap.add(flowTableAndStatisticsMapBuilder.build());
}
-
+
return flowTableStatsMap;
}
List<NodeConnectorStatisticsAndPortNumberMap> nodeConnectorStatisticsList = new ArrayList<NodeConnectorStatisticsAndPortNumberMap>();
for(NodeConnectorStatistics ofNodeConnectorStatistics : ncStatsList){
NodeConnectorStatisticsAndPortNumberMapBuilder nodeConnectorStatisticsAndPortNumberMapBuilder = new NodeConnectorStatisticsAndPortNumberMapBuilder();
-
+
nodeConnectorStatisticsAndPortNumberMapBuilder.setBytes(extractBytes(ofNodeConnectorStatistics));
nodeConnectorStatisticsAndPortNumberMapBuilder.setCollisionCount(toBI(ofNodeConnectorStatistics.getCollisionCount()));
nodeConnectorStatisticsAndPortNumberMapBuilder.setDuration(null);
nodeConnectorStatisticsAndPortNumberMapBuilder.setTransmitErrors(toBI(ofNodeConnectorStatistics.getTransmitErrorCount()));
nodeConnectorStatisticsList.add(nodeConnectorStatisticsAndPortNumberMapBuilder.build());
}
-
+
return nodeConnectorStatisticsList;
}
<plugin>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-maven-plugin</artifactId>
- <version>${yangtools.version}</version>
<executions>
<execution>
<goals>
<!-- Dependency Versions -->
<mockito.version>1.9.5</mockito.version>
- <xtend.version>2.4.3</xtend.version>
+
<!-- Sonar properties using jacoco to retrieve integration test results -->
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
<sonar.branch>${user.name}-private-view</sonar.branch>
<sonar.language>java</sonar.language>
<exam.version>3.0.0</exam.version>
- <sal.version>0.7.1-SNAPSHOT</sal.version>
+ <sal.version>0.8.1-SNAPSHOT</sal.version>
</properties>
<dependencyManagement>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
- <dependency>
- <groupId>org.eclipse.xtend</groupId>
- <artifactId>org.eclipse.xtend.lib</artifactId>
- <version>${xtend.version}</version>
- </dependency>
+
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
*/
package org.opendaylight.controller.sal.connector.remoterpc.api;
-import java.util.Map;
import java.util.Set;
public interface RoutingTable<I,R> {
-
-
/**
- * Adds a network address for the route. If address for route
- * exists, appends the address to the list
+ * Adds a network address for the route. If the route already exists,
+ * it throws <code>DuplicateRouteException</code>.
+ * This method would be used when registering a global service.
+ *
*
* @param routeId route identifier
* @param route network address
- * @throws RoutingTableException for any logical exception
+ * @throws DuplicateRouteException
+ * @throws RoutingTableException
+ */
+ public void addGlobalRoute(I routeId, R route) throws RoutingTableException, SystemException;
+
+ /**
+ * Remove the route.
+ * This method would be used when registering a global service.
+ * @param routeId
+ * @throws RoutingTableException
* @throws SystemException
*/
- public void addRoute(I routeId, R route) throws RoutingTableException,SystemException;
+ public void removeGlobalRoute(I routeId) throws RoutingTableException, SystemException;
- /**
+ /**
* Adds a network address for the route. If the route already exists,
* it throws <code>DuplicateRouteException</code>.
* This method would be used when registering a global service.
* @throws DuplicateRouteException
* @throws RoutingTableException
*/
- public void addGlobalRoute(I routeId, R route) throws RoutingTableException, SystemException;
-
+ public R getGlobalRoute(I routeId) throws RoutingTableException, SystemException;
+ /**
+ * Adds a network address for the route. If address for route
+ * exists, appends the address to the list
+ *
+ * @param routeId route identifier
+ * @param route network address
+ * @throws RoutingTableException for any logical exception
+ * @throws SystemException
+ */
+ public void addRoute(I routeId, R route) throws RoutingTableException,SystemException;
/**
* @param routeId
* @param route
*/
- public void removeRoute(I routeId, R route);
+ public void removeRoute(I routeId, R route) throws RoutingTableException,SystemException;
+ /**
+ * Adds address for a set of route identifiers. If address for route
+ * exists, appends the address to the set.
+ *
+ * @param routeIds a set of routeIds
+ * @param route network address
+ * @throws RoutingTableException for any logical exception
+ * @throws SystemException
+ */
+ public void addRoutes(Set<I> routeIds, R route) throws RoutingTableException,SystemException;
- /**
- * Remove the route.
- * This method would be used when registering a global service.
- * @param routeId
- * @throws RoutingTableException
- * @throws SystemException
- */
- public void removeGlobalRoute(I routeId) throws RoutingTableException, SystemException;
+ /**
+ * Removes address for a set of route identifiers.
+ *
+ * @param routeIds a set of routeIds
+ * @param route network address
+ * @throws RoutingTableException for any logical exception
+ * @throws SystemException
+ */
+ public void removeRoutes(Set<I> routeIds, R route) throws RoutingTableException,SystemException;
/**
* Returns a set of network addresses associated with this route
*/
public Set<R> getRoutes(I routeId);
- /**
- * Returns all network addresses stored in the table
- * @return
- */
- public Set<Map.Entry> getAllRoutes();
/**
- * Returns only one address from the list of network addresses
- * associated with the route. The algorithm to determine that
- * one address is upto the implementer
+ * Returns the last inserted address from the list of network addresses
+ * associated with the route.
* @param routeId
* @return
*/
- public R getARoute(I routeId);
-
- /**
- *
- * This will be removed after listeners
- * have made change on their end to use whiteboard pattern
- * @deprecated
- */
-
- public void registerRouteChangeListener(RouteChangeListener listener);
+ public R getLastAddedRoute(I routeId);
public class DuplicateRouteException extends RoutingTableException {
public DuplicateRouteException(String message) {
if (imp.equals(RoutingTableImpl.class)) {
Dictionary<String, Set<String>> props = new Hashtable<String, Set<String>>();
Set<String> propSet = new HashSet<String>();
- propSet.add(RoutingTableImpl.ROUTING_TABLE_GLOBAL_CACHE);
+ propSet.add(RoutingTableImpl.GLOBALRPC_CACHE);
+ propSet.add(RoutingTableImpl.RPC_CACHE);
props.put(CACHE_UPDATE_AWARE_REGISTRY_KEY, propSet);
c.setInterface(new String[] { RoutingTable.class.getName(),ICacheUpdateAware.class.getName() }, props);
package org.opendaylight.controller.sal.connector.remoterpc.impl;
+import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
import org.apache.felix.dm.Component;
-import org.opendaylight.controller.clustering.services.CacheConfigException;
-import org.opendaylight.controller.clustering.services.CacheExistException;
-import org.opendaylight.controller.clustering.services.CacheListenerAddException;
-import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
-import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
-import org.opendaylight.controller.clustering.services.IClusterServices;
-import org.opendaylight.controller.sal.connector.remoterpc.api.RouteChangeListener;
+import org.opendaylight.controller.clustering.services.*;
import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTableException;
import org.opendaylight.controller.sal.connector.remoterpc.api.SystemException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
import java.util.concurrent.ConcurrentMap;
-/**
- * @author: syedbahm
- */
public class RoutingTableImpl<I, R> implements RoutingTable<I, R>, ICacheUpdateAware<I, R> {
- public static final String ROUTING_TABLE_GLOBAL_CACHE = "routing_table_global_cache";
- private Logger log = LoggerFactory.getLogger(RoutingTableImpl.class);
+ private Logger log = LoggerFactory.getLogger(RoutingTableImpl.class);
- private IClusterGlobalServices clusterGlobalServices = null;
- private RoutingTableImpl routingTableInstance = null;
- private ConcurrentMap routingTableCache = null;
- private Set<RouteChangeListener> routeChangeListeners = Collections
- .synchronizedSet(new HashSet<RouteChangeListener>());
+ private IClusterGlobalServices clusterGlobalServices = null;
- public RoutingTableImpl() {
- }
+ private ConcurrentMap<I,R> globalRpcCache = null;
+ private ConcurrentMap<I, LinkedHashSet<R>> rpcCache = null; //need routes to ordered by insert-order
- @Override
- public void addRoute(I routeId, R route) throws RoutingTableException {
- throw new UnsupportedOperationException(" Not implemented yet!");
- }
+ public static final String GLOBALRPC_CACHE = "remoterpc_routingtable.globalrpc_cache";
+ public static final String RPC_CACHE = "remoterpc_routingtable.rpc_cache";
- @Override
- public void addGlobalRoute(I routeId, R route) throws RoutingTableException, SystemException {
- Preconditions.checkNotNull(routeId, "addGlobalRoute: routeId cannot be null!");
- Preconditions.checkNotNull(route, "addGlobalRoute: route cannot be null!");
- try {
-
- Set<R> existingRoute = null;
- // ok does the global route is already registered ?
- if ((existingRoute = getRoutes(routeId)) == null) {
-
- if (log.isDebugEnabled()) {
- log.debug("addGlobalRoute: adding a new route with id" + routeId + " and value = "
- + route);
- }
- // lets start a transaction
- clusterGlobalServices.tbegin();
-
- routingTableCache.put(routeId, route);
- clusterGlobalServices.tcommit();
- } else {
- throw new DuplicateRouteException(" There is already existing route " + existingRoute);
- }
-
- } catch (NotSupportedException|HeuristicRollbackException|RollbackException|HeuristicMixedException e) {
- throw new RoutingTableException("Transaction error - while trying to create route id="
- + routeId + "with route" + route, e);
- } catch (javax.transaction.SystemException e) {
- throw new SystemException("System error occurred - while trying to create with value", e);
- }
+ public RoutingTableImpl() {
+ }
- }
+ @Override
+ public R getGlobalRoute(I routeId) throws RoutingTableException, SystemException {
+ Preconditions.checkNotNull(routeId, "getGlobalRoute: routeId cannot be null!");
+ return globalRpcCache.get(routeId);
+ }
- @Override
- public void removeRoute(I routeId, R route) {
- throw new UnsupportedOperationException("Not implemented yet!");
+ @Override
+ public void addGlobalRoute(I routeId, R route) throws RoutingTableException, SystemException {
+ Preconditions.checkNotNull(routeId, "addGlobalRoute: routeId cannot be null!");
+ Preconditions.checkNotNull(route, "addGlobalRoute: route cannot be null!");
+ try {
+
+ log.debug("addGlobalRoute: adding a new route with id[{}] and value [{}]", routeId, route);
+ clusterGlobalServices.tbegin();
+ if (globalRpcCache.putIfAbsent(routeId, route) != null) {
+ throw new DuplicateRouteException(" There is already existing route " + routeId);
+ }
+ clusterGlobalServices.tcommit();
+
+ } catch (NotSupportedException | HeuristicRollbackException | RollbackException | HeuristicMixedException e) {
+ throw new RoutingTableException("Transaction error - while trying to create route id="
+ + routeId + "with route" + route, e);
+ } catch (javax.transaction.SystemException e) {
+ throw new SystemException("System error occurred - while trying to create with value", e);
}
- @Override
- public void removeGlobalRoute(I routeId) throws RoutingTableException, SystemException {
- Preconditions.checkNotNull(routeId, "removeGlobalRoute: routeId cannot be null!");
- try {
- if (log.isDebugEnabled()) {
- log.debug("removeGlobalRoute: removing a new route with id" + routeId);
- }
- // lets start a transaction
- clusterGlobalServices.tbegin();
-
- routingTableCache.remove(routeId);
- clusterGlobalServices.tcommit();
-
- } catch (NotSupportedException|HeuristicRollbackException|RollbackException|HeuristicMixedException e) {
- throw new RoutingTableException("Transaction error - while trying to remove route id="
- + routeId, e);
- } catch (javax.transaction.SystemException e) {
- throw new SystemException("System error occurred - while trying to remove with value", e);
- }
+ }
+
+ @Override
+ public void removeGlobalRoute(I routeId) throws RoutingTableException, SystemException {