package org.opendaylight.controller.containermanager.shell;
-import org.apache.felix.gogo.commands.Command;
-import org.apache.felix.gogo.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.opendaylight.controller.containermanager.IContainerManagerShell;
package org.opendaylight.controller.containermanager.shell;
-import org.apache.felix.gogo.commands.Command;
-import org.apache.felix.gogo.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.opendaylight.controller.containermanager.IContainerManagerShell;
package org.opendaylight.controller.containermanager.shell;
-import org.apache.felix.gogo.commands.Command;
-import org.apache.felix.gogo.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.opendaylight.controller.containermanager.IContainerManagerShell;
package org.opendaylight.controller.containermanager.shell;
-import org.apache.felix.gogo.commands.Command;
-import org.apache.felix.gogo.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.opendaylight.controller.containermanager.IContainerManagerShell;
package org.opendaylight.controller.containermanager.shell;
-import org.apache.felix.gogo.commands.Command;
-import org.apache.felix.gogo.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.opendaylight.controller.containermanager.IContainerManagerShell;
package org.opendaylight.controller.containermanager.shell;
-import org.apache.felix.gogo.commands.Command;
-import org.apache.felix.gogo.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.opendaylight.controller.containermanager.IContainerManagerShell;
package org.opendaylight.controller.containermanager.shell;
-import org.apache.felix.gogo.commands.Command;
+import org.apache.karaf.shell.commands.Command;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.opendaylight.controller.containermanager.IContainerManagerShell;
package org.opendaylight.controller.containermanager.shell;
-import org.apache.felix.gogo.commands.Command;
-import org.apache.felix.gogo.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.opendaylight.controller.containermanager.IContainerManagerShell;
package org.opendaylight.controller.containermanager.shell;
-import org.apache.felix.gogo.commands.Command;
-import org.apache.felix.gogo.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.opendaylight.controller.containermanager.IContainerManagerShell;
package org.opendaylight.controller.containermanager.shell;
-import org.apache.felix.gogo.commands.Command;
-import org.apache.felix.gogo.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.opendaylight.controller.containermanager.IContainerManagerShell;
package org.opendaylight.controller.containermanager.shell;
-import org.apache.felix.gogo.commands.Command;
+import org.apache.karaf.shell.commands.Command;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.opendaylight.controller.containermanager.IContainerManagerShell;
package org.opendaylight.controller.containermanager.shell;
-import org.apache.felix.gogo.commands.Command;
+import org.apache.karaf.shell.commands.Command;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.opendaylight.controller.containermanager.IContainerManagerShell;
package org.opendaylight.controller.containermanager.shell;
-import org.apache.felix.gogo.commands.Command;
+import org.apache.karaf.shell.commands.Command;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.opendaylight.controller.containermanager.IContainerManagerShell;
package org.opendaylight.controller.containermanager.shell;
-import org.apache.felix.gogo.commands.Command;
+import org.apache.karaf.shell.commands.Command;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.opendaylight.controller.containermanager.IContainerManagerShell;
package org.opendaylight.controller.containermanager.shell;
-import org.apache.felix.gogo.commands.Command;
+import org.apache.karaf.shell.commands.Command;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.opendaylight.controller.containermanager.IContainerManagerShell;
package org.opendaylight.controller.containermanager.shell;
-import org.apache.felix.gogo.commands.Command;
-import org.apache.felix.gogo.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.opendaylight.controller.containermanager.IContainerManagerShell;
package org.opendaylight.controller.containermanager.shell;
-import org.apache.felix.gogo.commands.Command;
-import org.apache.felix.gogo.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.opendaylight.controller.containermanager.IContainerManagerShell;
package org.opendaylight.controller.containermanager.shell;
-import org.apache.felix.gogo.commands.Command;
-import org.apache.felix.gogo.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.opendaylight.controller.containermanager.IContainerManagerShell;
package org.opendaylight.controller.containermanager.shell;
-import org.apache.felix.gogo.commands.Command;
+import org.apache.karaf.shell.commands.Command;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.opendaylight.controller.containermanager.IContainerManagerShell;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-import org.apache.felix.gogo.commands.Command;
+import org.apache.karaf.shell.commands.Command;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.opendaylight.controller.hosttracker.IHostTrackerShell;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-import org.apache.felix.gogo.commands.Command;
+import org.apache.karaf.shell.commands.Command;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.opendaylight.controller.hosttracker.IHostTrackerShell;
*/
package org.opendaylight.controller.topologymanager.shell;
-import org.apache.felix.gogo.commands.Command;
-import org.apache.felix.gogo.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.opendaylight.controller.topologymanager.ITopologyManagerShell;
*/
package org.opendaylight.controller.topologymanager.shell;
-import org.apache.felix.gogo.commands.Command;
-import org.apache.felix.gogo.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.opendaylight.controller.topologymanager.ITopologyManagerShell;
*/
package org.opendaylight.controller.topologymanager.shell;
-import org.apache.felix.gogo.commands.Command;
+import org.apache.karaf.shell.commands.Command;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.opendaylight.controller.topologymanager.ITopologyManagerShell;
*/
package org.opendaylight.controller.topologymanager.shell;
-import org.apache.felix.gogo.commands.Command;
+import org.apache.karaf.shell.commands.Command;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.opendaylight.controller.topologymanager.ITopologyManagerShell;
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>opendaylight-startup-archetype</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ <packaging>maven-archetype</packaging>
+
+ <name>${project.artifactId}</name>
+
+ <build>
+ <extensions>
+ <extension>
+ <groupId>org.apache.maven.archetype</groupId>
+ <artifactId>archetype-packaging</artifactId>
+ <version>2.2</version>
+ </extension>
+ </extensions>
+
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <artifactId>maven-archetype-plugin</artifactId>
+ <version>2.2</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <configuration>
+ <failsOnError>false</failsOnError>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<archetype-descriptor xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0 http://maven.apache.org/xsd/archetype-descriptor-1.0.0.xsd" name="example-aggregator"
+ xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <requiredProperties>
+ <requiredProperty key="classPrefix" >
+ <defaultValue>
+ ${artifactId.substring(0,1).toUpperCase()}${artifactId.substring(1)}
+ </defaultValue>
+ </requiredProperty>
+ <requiredProperty key="copyright" />
+ </requiredProperties>
+ <fileSets>
+
+ <!-- aggregator -->
+ <fileSet encoding="UTF-8">
+ <directory></directory>
+ <includes>
+ <include>.gitignore</include>
+ </includes>
+ </fileSet>
+ <fileSet filtered="true" encoding="UTF-8">
+ <directory></directory>
+ <includes>
+ <include>pom.xml</include>
+ </includes>
+ </fileSet>
+
+ <!-- karaf distro -->
+ <fileSet filtered="true" encoding="UTF-8">
+ <directory>__artifactId__-karaf</directory>
+ <includes>
+ <include>pom.xml</include>
+ </includes>
+ </fileSet>
+
+ <!-- features -->
+
+ <fileSet filtered="true" encoding="UTF-8">
+ <directory>__artifactId__-features</directory>
+ <includes>
+ <include>pom.xml</include>
+ </includes>
+ </fileSet>
+ <fileSet filtered="true" encoding="UTF-8">
+ <directory>__artifactId__-features/src/main/features</directory>
+ <includes>
+ <include>**/*.xml</include>
+ </includes>
+ </fileSet>
+
+ <!-- impl -->
+
+ <fileSet filtered="true" encoding="UTF-8">
+ <directory>__artifactId__-impl</directory>
+ <includes>
+ <include>pom.xml</include>
+ </includes>
+ </fileSet>
+ <fileSet filtered="true" encoding="UTF-8">
+ <directory>__artifactId__-impl/src/main/java</directory>
+ <includes>
+ <include>**/*.java</include>
+ </includes>
+ </fileSet>
+ <fileSet filtered="true" encoding="UTF-8">
+ <directory>__artifactId__-impl/src/main/config</directory>
+ <includes>
+ <include>**/*.xml</include>
+ </includes>
+ </fileSet>
+ <fileSet filtered="true" encoding="UTF-8">
+ <directory>__artifactId__-impl/src/main/yang</directory>
+ <includes>
+ <include>**/*.yang</include>
+ </includes>
+ </fileSet>
+
+ <!-- api -->
+
+ <fileSet filtered="true" encoding="UTF-8">
+ <directory>__artifactId__-api</directory>
+ <includes>
+ <include>pom.xml</include>
+ </includes>
+ </fileSet>
+ <fileSet filtered="true" encoding="UTF-8">
+ <directory>__artifactId__-api/src/main/yang</directory>
+ <includes>
+ <include>**/*.yang</include>
+ </includes>
+ </fileSet>
+
+ <!-- artifacts -->
+ <fileSet filtered="true" encoding="UTF-8">
+ <directory>__artifactId__-artifacts</directory>
+ <includes>
+ <include>pom.xml</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+</archetype-descriptor>
--- /dev/null
+*.class
+**/target
+bin/
+dist
+**/logs
+*~
+target
+target-ide
+.classpath
+.project
+.settings
+.idea
+xtend-gen
+yang-gen-config
+yang-gen-sal
+classes
+.DS_STORE
+.metadata
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+${copyright} 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>${groupId}</groupId>
+ <artifactId>${artifactId}-api</artifactId>
+ <version>${version}</version>
+ <packaging>bundle</packaging>
+
+</project>
--- /dev/null
+module ${artifactId} {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:${artifactId}";
+ prefix "${artifactId}";
+
+ revision "2015-01-05" {
+ description "Initial revision of ${artifactId} model";
+ }
+}
--- /dev/null
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+${copyright} 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
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>${groupId}</groupId>
+ <artifactId>${artifactId}-artifacts</artifactId>
+ <version>${version}</version>
+ <packaging>pom</packaging>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>${symbol_dollar}{project.groupId}</groupId>
+ <artifactId>${artifactId}-api</artifactId>
+ <version>${symbol_dollar}{project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${symbol_dollar}{project.groupId}</groupId>
+ <artifactId>${artifactId}-impl</artifactId>
+ <version>${symbol_dollar}{project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${symbol_dollar}{project.groupId}</groupId>
+ <artifactId>${artifactId}-features</artifactId>
+ <version>${symbol_dollar}{project.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+</project>
--- /dev/null
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+${copyright} 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 INTERNAL
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <groupId>org.opendaylight.odlparent</groupId>
+ <artifactId>features-parent</artifactId>
+ <version>1.5.0-SNAPSHOT</version>
+ </parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${artifactId}-features</artifactId>
+ <version>${version}</version>
+ <name>${project.artifactId}</name>
+ <modelVersion>4.0.0</modelVersion>
+ <prerequisites>
+ <maven>3.1.1</maven>
+ </prerequisites>
+ <properties>
+ <mdsal.version>1.2.0-SNAPSHOT</mdsal.version>
+ <yangtools.version>0.7.0-SNAPSHOT</yangtools.version>
+ </properties>
+ <dependencyManagement>
+ <dependencies>
+ <!-- project specific dependencies -->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>mdsal-artifacts</artifactId>
+ <version>${mdsal.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>${symbol_dollar}{groupId}</groupId>
+ <artifactId>${artifactId}-impl</artifactId>
+ <version>${symbol_dollar}{project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${symbol_dollar}{groupId}</groupId>
+ <artifactId>${artifactId}-api</artifactId>
+ <version>${symbol_dollar}{project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+${copyright}
+
+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
+-->
+<features name="odl-${artifactId}-${symbol_dollar}{project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+ <repository>mvn:org.opendaylight.yangtools/features-yangtools/${symbol_dollar}{yangtools.version}/xml/features</repository>
+ <repository>mvn:org.opendaylight.controller/features-mdsal/${symbol_dollar}{mdsal.version}/xml/features</repository>
+ <repository>mvn:org.opendaylight.controller/features-restconf/${symbol_dollar}{mdsal.version}/xml/features</repository>
+ <feature name='odl-${artifactId}-api' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${artifactId} :: api '>
+ <feature version='${symbol_dollar}{yangtools.version}'>odl-yangtools-models</feature>
+ <bundle>mvn:${groupId}/${artifactId}-api/${symbol_dollar}{project.version}</bundle>
+ </feature>
+ <feature name='odl-${artifactId}-impl' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${artifactId} :: impl '>
+ <feature version='${symbol_dollar}{mdsal.version}'>odl-mdsal-broker</feature>
+ <feature version='${symbol_dollar}{project.version}'>odl-${artifactId}-api</feature>
+ <bundle>mvn:${groupId}/${artifactId}-impl/${symbol_dollar}{project.version}</bundle>
+ <configfile finalname="${artifactId}-impl-default-config.xml">mvn:${groupId}/${artifactId}-impl/${symbol_dollar}{project.version}/xml/config</configfile>
+ </feature>
+ <feature name='odl-${artifactId}-impl-rest' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${artifactId} :: impl :: REST '>
+ <feature version="${symbol_dollar}{project.version}">odl-${artifactId}-impl</feature>
+ <feature version="${symbol_dollar}{mdsal.version}">odl-restconf</feature>
+ </feature>
+ <feature name='odl-${artifactId}-impl-ui' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${artifactId} :: impl :: UI'>
+ <feature version="${symbol_dollar}{project.version}">odl-${artifactId}-impl-rest</feature>
+ <feature version="${symbol_dollar}{mdsal.version}">odl-mdsal-apidocs</feature>
+ <feature version="${symbol_dollar}{mdsal.version}">odl-mdsal-xsql</feature>
+ </feature>
+
+</features>
--- /dev/null
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: --><!--
+Copyright (c) 2014 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-parent</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>${groupId}</groupId>
+ <artifactId>${artifactId}-impl</artifactId>
+ <version>${version}</version>
+ <packaging>bundle</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>${symbol_dollar}{groupId}</groupId>
+ <artifactId>${artifactId}-api</artifactId>
+ <version>${symbol_dollar}{project.version}</version>
+ </dependency>
+ </dependencies>
+
+</project>
--- /dev/null
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+${copyright} 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
+-->
+<snapshot>
+ <required-capabilities>
+ </required-capabilities>
+ <configuration>
+
+ <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:${artifactId}:impl">prefix:${artifactId}-impl</type>
+ <name>${artifactId}-default</name>
+ <broker>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
+ <name>binding-osgi-broker</name>
+ </broker>
+ </module>
+ </modules>
+ </data>
+ </configuration>
+</snapshot>
--- /dev/null
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+/*
+ * ${copyright} 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 ${package};
+
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ${classPrefix}Provider implements BindingAwareProvider, AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(${classPrefix}Provider.class);
+
+ @Override
+ public void onSessionInitiated(ProviderContext session) {
+ LOG.info("${classPrefix}Provider Session Initiated");
+ }
+
+ @Override
+ public void close() throws Exception {
+ LOG.info("${classPrefix}Provider Closed");
+ }
+
+}
--- /dev/null
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+/*
+ * ${copyright} 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${artifactId}.impl.rev141210;
+
+import ${package}.${classPrefix}Provider;
+
+public class ${classPrefix}ImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${artifactId}.impl.rev141210.Abstract${classPrefix}ImplModule {
+ public ${classPrefix}ImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public ${classPrefix}ImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${artifactId}.impl.rev141210.${classPrefix}ImplModule oldModule, java.lang.AutoCloseable oldInstance) {
+ super(identifier, dependencyResolver, oldModule, oldInstance);
+ }
+
+ @Override
+ public void customValidation() {
+ // add custom validation form module attributes here.
+ }
+
+ @Override
+ public java.lang.AutoCloseable createInstance() {
+ ${classPrefix}Provider provider = new ${classPrefix}Provider();
+ getBrokerDependency().registerProvider(provider);
+ return provider;
+ }
+
+}
--- /dev/null
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+/*
+ * ${copyright} 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
+ */
+/*
+* Generated file
+*
+* Generated from: yang module name: ${artifactId} yang module local name: ${artifactId}
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Fri Jan 02 13:49:24 CST 2015
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${artifactId}.impl.rev141210;
+public class ${classPrefix}ImplModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${artifactId}.impl.rev141210.Abstract${classPrefix}ImplModuleFactory {
+
+}
--- /dev/null
+module ${artifactId}-impl {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:${artifactId}:impl";
+ prefix "${artifactId}-impl";
+
+ import config { prefix config; revision-date 2013-04-05; }
+ import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
+
+ description
+ "Service definition for ${artifactId} project";
+
+ revision "2014-12-10" {
+ description
+ "Initial revision";
+ }
+
+ identity ${artifactId}-impl {
+ base config:module-type;
+ config:java-name-prefix ${classPrefix}Impl;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case ${artifactId}-impl {
+ when "/config:modules/config:module/config:type = '${artifactId}-impl'";
+ container broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-broker-osgi-registry;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+${copyright} 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 INTERNAL
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>karaf-parent</artifactId>
+ <version>1.5.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>${groupId}</groupId>
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.1.1</maven>
+ </prerequisites>
+ <properties>
+ <karaf.localFeature>odl-${artifactId}-impl-ui</karaf.localFeature>
+ </properties>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>${symbol_dollar}{project.groupId}</groupId>
+ <artifactId>${artifactId}-artifacts</artifactId>
+ <version>${symbol_dollar}{project.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <!-- scope is compile so all features (there is only one) are installed
+ into startup.properties and the feature repo itself is not installed -->
+ <groupId>org.apache.karaf.features</groupId>
+ <artifactId>framework</artifactId>
+ <type>kar</type>
+ </dependency>
+
+ <dependency>
+ <groupId>${symbol_dollar}{project.groupId}</groupId>
+ <artifactId>${artifactId}-features</artifactId>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+${copyright} 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 INTERNAL
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <groupId>${groupId}</groupId>
+ <artifactId>${artifactId}-aggregator</artifactId>
+ <version>${version}</version>
+ <name>${project.artifactId}</name>
+ <packaging>pom</packaging>
+ <modelVersion>4.0.0</modelVersion>
+ <prerequisites>
+ <maven>3.1.1</maven>
+ </prerequisites>
+ <modules>
+ <module>${artifactId}-api</module>
+ <module>${artifactId}-impl</module>
+ <module>${artifactId}-karaf</module>
+ <module>${artifactId}-features</module>
+ <module>${artifactId}-artifacts</module>
+ </modules>
+</project>
--- /dev/null
+#Mon Jan 12 13:10:37 CST 2015
+package=it.pkg
+version=0.1-SNAPSHOT
+groupId=archetype.it
+artifactId=basic
+classPrefix=Basic
+copyright=Copyright (c) 2013 Cisco Systems, Inc.
<module>opendaylight-configfile-archetype</module>
<module>opendaylight-karaf-distro-archetype</module>
<module>opendaylight-karaf-features</module>
+ <module>opendaylight-startup</module>
</modules>
</project>
<includeTestSourceDirectory>true</includeTestSourceDirectory>
<sourceDirectory>${project.basedir}</sourceDirectory>
<includes>**\/*.java,**\/*.xml,**\/*.ini,**\/*.sh,**\/*.bat</includes>
- <excludes>**\/target\/,**\/bin\/,**\/target-ide\/,**\/${jmxGeneratorPath}\/,**\/${salGeneratorPath}\/,**\/protobuff\/</excludes>
+ <excludes>**\/target\/,**\/bin\/,**\/target-ide\/,**\/${jmxGeneratorPath}\/,**\/${salGeneratorPath}\/,**\/protobuff\/,**\/src\/main\/resources\/archetype-resources\/**\/*.java</excludes>
</configuration>
<dependencies>
<dependency>
<T> T resolveInstance(Class<T> expectedType, ObjectName objectName,
JmxAttribute jmxAttribute);
+
/**
* To be used during commit phase to resolve identity-ref config attributes.
*
*/
<T> T newMXBeanProxy(ObjectName objectName, Class<T> interfaceClass);
+ /**
+ * Check whether a dependency will be reused or (re)created. Useful when deciding if current module could be also reused.
+ *
+ * @param objectName ObjectName ID of a dependency
+ * @param jmxAttribute JMXAttribute ID of a dependency
+ * @return true if the dependency will be reused false otherwise
+ */
+ boolean canReuseDependency(ObjectName objectName, JmxAttribute jmxAttribute);
}
--- /dev/null
+package org.opendaylight.controller.config.spi;
+
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Base implementation of Module. This implementation contains base logic for Module reconfiguration with associated fields.
+ * @param <M> Type of module implementation. Enables easier implementation for the {@link #isSame} method
+ */
+public abstract class AbstractModule<M extends AbstractModule<M>> implements org.opendaylight.controller.config.spi.Module {
+
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractModule.class);
+
+ private final M oldModule;
+ private final AutoCloseable oldInstance;
+ protected final ModuleIdentifier identifier;
+ private AutoCloseable instance;
+ protected final DependencyResolver dependencyResolver;
+
+ /**
+ * Called when module is configured.
+ *
+ * @param identifier id of current instance.
+ * @param dependencyResolver resolver used in dependency injection and validation.
+ */
+ public AbstractModule(ModuleIdentifier identifier, DependencyResolver dependencyResolver) {
+ this(identifier, dependencyResolver, null, null);
+ }
+
+ /**
+ * Called when module is reconfigured.
+ *
+ * @param identifier id of current instance.
+ * @param dependencyResolver resolver used in dependency injection and validation.
+ * @param oldModule old instance of module that is being reconfigred(replaced) by current instance. The old instance can be examined for reuse.
+ * @param oldInstance old instance wrapped by the old module. This is the resource that is actually being reused if possible or closed otherwise.
+ */
+ public AbstractModule(ModuleIdentifier identifier, DependencyResolver dependencyResolver, M oldModule, AutoCloseable oldInstance) {
+ this.identifier = identifier;
+ this.dependencyResolver = dependencyResolver;
+ this.oldModule = oldModule;
+ this.oldInstance = oldInstance;
+ }
+
+ @Override
+ public ModuleIdentifier getIdentifier() {
+ return identifier;
+ }
+
+ /**
+ *
+ * General algorithm for spawning/closing and reusing wrapped instances.
+ *
+ * @return current instance of wrapped resource either by reusing the old one (if present) or constructing a brand new.
+ */
+ @Override
+ public final AutoCloseable getInstance() {
+ if(instance==null) {
+ if(oldInstance!=null && canReuseInstance(oldModule)) {
+ resolveDependencies();
+ instance = reuseInstance(oldInstance);
+ } else {
+ if(oldInstance!=null) {
+ try {
+ oldInstance.close();
+ } catch(Exception e) {
+ LOG.error("An error occurred while closing old instance {} for module {}", oldInstance, getIdentifier(), e);
+ }
+ }
+ resolveDependencies();
+ instance = createInstance();
+ if (instance == null) {
+ throw new IllegalStateException("Error in createInstance - null is not allowed as return value. Module: " + getIdentifier());
+ }
+ }
+ }
+ return instance;
+ }
+
+ /**
+ * @return Brand new instance of wrapped class in case no previous instance is present or reconfiguration is impossible.
+ */
+ protected abstract AutoCloseable createInstance();
+
+ @Override
+ public final boolean canReuse(Module oldModule) {
+ // Just cast into a specific instance
+ // TODO unify this method with canReuseInstance (required Module interface to be generic which requires quite a lot of changes)
+ return getClass().isInstance(oldModule) ? canReuseInstance((M) oldModule) : false;
+ }
+
+ /**
+ *
+ * Users are welcome to override this method to provide custom logic for advanced reusability detection.
+ *
+ * @param oldModule old instance of a Module
+ * @return true if the old instance is reusable false if a new one should be spawned
+ */
+ protected abstract boolean canReuseInstance(final M oldModule);
+
+ /**
+ * By default the oldInstance is returned since this method is by default called only if the oldModule had the same configuration and dependencies configured.
+ * Users are welcome to override this method to provide custom logic for advanced reusability.
+ *
+ * @param oldInstance old instance of a class wrapped by the module
+ * @return reused instance
+ */
+ protected AutoCloseable reuseInstance(AutoCloseable oldInstance) {
+ // implement if instance reuse should be supported. Override canReuseInstance to change the criteria.
+ return oldInstance;
+ }
+
+ /**
+ * Inject all the dependencies using dependency resolver instance.
+ */
+ protected abstract void resolveDependencies();
+}
*/
AutoCloseable getInstance();
+
+ /**
+ * Compare current module with oldModule and if the instance/live object
+ * produced by the old module can be reused in this module as well return true.
+ * Typically true should be returned if the old module had the same configuration.
+ *
+ *
+ * @param oldModule old instance of Module
+ * @return true if the instance produced by oldModule can be reused with current instance as well.
+ */
+ public boolean canReuse(Module oldModule);
+
+
}
}
}
- // destroy all live objects one after another in order of the dependency
- // hierarchy
+ // destroy all live objects one after another in order of the dependency hierarchy, from top to bottom
List<DestroyedModule> destroyedModules = currentConfig
.getModulesToBeDestroyed();
for (DestroyedModule destroyedModule : destroyedModules) {
import static com.google.common.base.Preconditions.checkNotNull;
import static java.lang.String.format;
+import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
LOG.trace("Committing transaction {}", getTransactionIdentifier());
- // call getInstance()
- for (Entry<ModuleIdentifier, Module> entry : dependencyResolverManager
- .getAllModules().entrySet()) {
- Module module = entry.getValue();
- ModuleIdentifier name = entry.getKey();
+ Map<ModuleIdentifier, Module> allModules = dependencyResolverManager.getAllModules();
+
+ // call getInstance() on all Modules from top to bottom (from source to target of the dependency relation)
+ // The source of a dependency closes itself and calls getInstance recursively on the dependencies (in case of reconfiguration)
+ // This makes close() calls from top to bottom while createInstance() calls are performed bottom to top
+ List<ModuleIdentifier> sortedModuleIdentifiers = Lists.reverse(dependencyResolverManager.getSortedModuleIdentifiers());
+ for (ModuleIdentifier moduleIdentifier : sortedModuleIdentifiers) {
+ Module module = allModules.get(moduleIdentifier);
+
try {
LOG.debug("About to commit {} in transaction {}",
- name, getTransactionIdentifier());
+ moduleIdentifier, getTransactionIdentifier());
AutoCloseable instance = module.getInstance();
- checkNotNull(instance, "Instance is null:{} in transaction {}", name, getTransactionIdentifier());
+ checkNotNull(instance, "Instance is null:{} in transaction {}", moduleIdentifier, getTransactionIdentifier());
} catch (Exception e) {
- LOG.error("Commit failed on {} in transaction {}", name,
+ LOG.error("Commit failed on {} in transaction {}", moduleIdentifier,
getTransactionIdentifier(), e);
internalAbort();
throw new IllegalStateException(
format("Error - getInstance() failed for %s in transaction %s",
- name, getTransactionIdentifier()), e);
+ moduleIdentifier, getTransactionIdentifier()), e);
}
}
- // count dependency order
-
LOG.trace("Committed configuration {}", getTransactionIdentifier());
transactionStatus.setCommitted();
- return dependencyResolverManager.getSortedModuleIdentifiers();
+ return sortedModuleIdentifiers;
}
@Override
import static java.lang.String.format;
+import com.google.common.base.Preconditions;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
@Override
public <T> T resolveInstance(Class<T> expectedType, ObjectName dependentReadOnlyON,
JmxAttribute jmxAttribute) {
- if (expectedType == null || dependentReadOnlyON == null || jmxAttribute == null) {
- throw new IllegalArgumentException(format(
- "Null parameters not allowed, got %s %s %s", expectedType,
- dependentReadOnlyON, jmxAttribute));
- }
- ObjectName translatedDependentReadOnlyON = translateServiceRefIfPossible(dependentReadOnlyON);
- transactionStatus.checkCommitStarted();
- transactionStatus.checkNotCommitted();
+ Module module = resolveModuleInstance(dependentReadOnlyON, jmxAttribute);
- ModuleIdentifier dependentModuleIdentifier = ObjectNameUtil.fromON(
- translatedDependentReadOnlyON, ObjectNameUtil.TYPE_MODULE);
- Module module = modulesHolder.findModule(dependentModuleIdentifier,
- jmxAttribute);
synchronized (this) {
- dependencies.add(dependentModuleIdentifier);
+ dependencies.add(module.getIdentifier());
}
AutoCloseable instance = module.getInstance();
if (instance == null) {
String message = format(
"Error while %s resolving instance %s. getInstance() returned null. "
+ "Expected type %s , attribute %s", name,
- dependentModuleIdentifier, expectedType, jmxAttribute
+ module.getIdentifier(), expectedType, jmxAttribute
);
throw new JmxAttributeValidationException(message, jmxAttribute);
}
}
}
+ private Module resolveModuleInstance(ObjectName dependentReadOnlyON,
+ JmxAttribute jmxAttribute) {
+ Preconditions.checkArgument(dependentReadOnlyON != null ,"dependentReadOnlyON");
+ Preconditions.checkArgument(jmxAttribute != null, "jmxAttribute");
+ ObjectName translatedDependentReadOnlyON = translateServiceRefIfPossible(dependentReadOnlyON);
+ transactionStatus.checkCommitStarted();
+ transactionStatus.checkNotCommitted();
+
+ ModuleIdentifier dependentModuleIdentifier = ObjectNameUtil.fromON(
+ translatedDependentReadOnlyON, ObjectNameUtil.TYPE_MODULE);
+
+ return Preconditions.checkNotNull(modulesHolder.findModule(dependentModuleIdentifier, jmxAttribute));
+ }
+
+ @Override
+ public boolean canReuseDependency(ObjectName objectName, JmxAttribute jmxAttribute) {
+ Preconditions.checkNotNull(objectName);
+ Preconditions.checkNotNull(jmxAttribute);
+
+ Module currentModule = resolveModuleInstance(objectName, jmxAttribute);
+ ModuleIdentifier identifier = currentModule.getIdentifier();
+ ModuleInternalTransactionalInfo moduleInternalTransactionalInfo = modulesHolder.findModuleInternalTransactionalInfo(identifier);
+
+ if(moduleInternalTransactionalInfo.hasOldModule()) {
+ Module oldModule = moduleInternalTransactionalInfo.getOldInternalInfo().getReadableModule().getModule();
+ return currentModule.canReuse(oldModule);
+ }
+ return false;
+ }
+
@Override
public <T extends BaseIdentity> Class<? extends T> resolveIdentity(IdentityAttributeRef identityRef, Class<T> expectedBaseClass) {
final QName qName = QName.create(identityRef.getqNameOfIdentity());
@Override
public int compareTo(DependencyResolverImpl o) {
- transactionStatus.checkCommitted();
+ transactionStatus.checkCommitStarted();
return Integer.compare(getMaxDependencyDepth(),
o.getMaxDependencyDepth());
}
}
void countMaxDependencyDepth(DependencyResolverManager manager) {
- transactionStatus.checkCommitted();
+ // We can calculate the dependency after second phase commit was started
+ // Second phase commit starts after validation and validation adds the dependencies into the dependency resolver, which are necessary for the calculation
+ // FIXME generated code for abstract module declares validate method as non-final
+ // Overriding the validate would cause recreate every time instead of reuse + also possibly wrong close order if there is another module depending
+ transactionStatus.checkCommitStarted();
if (maxDependencyDepth == null) {
maxDependencyDepth = getMaxDepth(this, manager,
new LinkedHashSet<ModuleIdentifier>());
* things?
*/
private List<DependencyResolverImpl> getAllSorted() {
- transactionStatus.checkCommitted();
+ transactionStatus.checkCommitStarted();
List<DependencyResolverImpl> sorted = new ArrayList<>(
moduleIdentifiersToDependencyResolverMap.values());
for (DependencyResolverImpl dri : sorted) {
*/
package org.opendaylight.controller.config.manager.impl.dependencyresolver;
+import com.google.common.base.Preconditions;
import javax.annotation.Nullable;
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.opendaylight.controller.config.manager.impl.ModuleInternalInfo;
@Nullable
public ModuleInternalInfo getOldInternalInfo() {
- if (maybeOldInternalInfo == null) {
- throw new NullPointerException();
- }
- return maybeOldInternalInfo;
+ return Preconditions.checkNotNull(maybeOldInternalInfo);
}
public TransactionModuleJMXRegistration getTransactionModuleJMXRegistration() {
this.id = id==null ? new ModuleIdentifier(getClass().getCanonicalName(), "mock") : id;
}
+
+ @Override
+ public boolean canReuse(Module oldModule) {
+ return instance!=null;
+ }
+
@Override
public void validate() {
}
moduleName124, instanceName134);
assertEquals(Sets.newHashSet(name1), beans);
}
-
-}
+}
\ No newline at end of file
// switch to second phase committed
reset(transactionStatus);
+ doNothing().when(transactionStatus).checkCommitStarted();
doNothing().when(transactionStatus).checkCommitted();
+ doNothing().when(transactionStatus).checkNotCommitted();
+
List<ModuleIdentifier> sortedModuleIdentifiers = tested
.getSortedModuleIdentifiers();
assertEquals(
private static Module mockedModule() {
Module mockedModule = mock(Module.class);
doReturn(mock(AutoCloseable.class)).when(mockedModule).getInstance();
+ doReturn(new ModuleIdentifier("fact", "instance")).when(mockedModule).getIdentifier();
return mockedModule;
}
return instance;
}
+ @Override
+ public boolean canReuse(final Module oldModule) {
+ return false;
+ }
+
@Override
public ModuleIdentifier getIdentifier() {
return identifier;
}
+ @Override
+ public boolean canReuse(Module oldModule) {
+ return false;
+ }
+
@Override
public Closeable getInstance() {
return new MockedThreadPool(threadCount);
"Parameter 'ThreadCount' must be greater than 0");
}
+ @Override
+ public boolean canReuse(final Module oldModule) {
+ return false;
+ }
+
@Override
public int getThreadCount() {
return threadCount;
"Parameter 'threadCount' must be greater than 0");
}
+ @Override
+ public boolean canReuse(final Module oldModule) {
+ return isReusable() && triggerNewInstanceCreation == false;
+ }
+
@Override
public Closeable getInstance() {
if (instance == null) {
<include>**</include>
</includes>
</fileset>
+ <fileset>
+ <directory>${salGeneratorPath}</directory>
+ <includes>
+ <include>**</include>
+ </includes>
+ </fileset>
</filesets>
</configuration>
</plugin>
private FixedThreadPoolModuleFactory factory;
private final String nameInstance = "fixedInstance";
+ private ObjectName threadFactoryON;
@Before
public void setUp() {
assertBeanCount(1, factory.getImplementationName());
transaction = configRegistryClient.createTransaction();
+ NamingThreadFactoryModuleMXBean namingThreadFactoryModuleMXBean = transaction.newMXBeanProxy(threadFactoryON, NamingThreadFactoryModuleMXBean.class);
+ namingThreadFactoryModuleMXBean.setNamePrefix("newPrefix");
CommitStatus status = transaction.commit();
assertBeanCount(1, factory.getImplementationName());
- assertStatus(status, 0, 0, 2);
+ assertStatus(status, 0, 2, 0);
}
@Test
FixedThreadPoolModuleMXBean mxBean = transaction.newMXBeanProxy(nameCreated, FixedThreadPoolModuleMXBean.class);
mxBean.setMaxThreadCount(numberOfThreads);
- ObjectName threadFactoryON = transaction.createModule(NamingThreadFactoryModuleFactory.NAME, "naming");
+ threadFactoryON = transaction.createModule(NamingThreadFactoryModuleFactory.NAME, "naming");
NamingThreadFactoryModuleMXBean namingThreadFactoryModuleMXBean = transaction.newMXBeanProxy(threadFactoryON,
NamingThreadFactoryModuleMXBean.class);
namingThreadFactoryModuleMXBean.setNamePrefix(prefix);
doReturn(mock(ExecutorService.class)).when(pool).getExecutor();
return pool;
}
-
}
return fact;
}
+ @Override
+ public boolean canReuse(Module oldModule) {
+ return false;
+ }
+
}
private final String registratorType;
public AbstractModuleTemplate(Header header, String packageName,
- String abstractModuleName, List<String> implementedIfcs,
- List<ModuleField> moduleFields, List<MethodDefinition> methods,
+ String abstractModuleName, List<String> extendedClasses,
+ List<String> implementedIfcs, List<ModuleField> moduleFields, List<MethodDefinition> methods,
boolean isRuntime, String registratorType) {
- super(header, packageName, abstractModuleName, Collections
- .<String> emptyList(), implementedIfcs, Collections
- .<Field> emptyList(), methods, true, false, Collections
- .<Constructor> emptyList());
+ super(header, packageName, abstractModuleName, extendedClasses,
+ implementedIfcs, Collections.<Field> emptyList(), methods,
+ true, false, Collections.<Constructor> emptyList());
this.moduleFields = moduleFields;
this.runtime = isRuntime;
this.registratorType = registratorType;
static List<String> checkCardinality(List<String> extendedClass) {
if (extendedClass.size() > 1) {
throw new IllegalArgumentException(
- "Class cannot have more than one super " + "class");
+ "Class cannot have more than one super class, found: " + extendedClass);
}
return extendedClass;
}
import org.opendaylight.controller.config.api.RuntimeBeanRegistratorAwareModule;
import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
import org.opendaylight.controller.config.api.runtime.RuntimeBean;
-import org.opendaylight.controller.config.spi.Module;
+import org.opendaylight.controller.config.spi.AbstractModule;
import org.opendaylight.controller.config.yangjmxgenerator.AbstractEntry;
import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry;
List<ModuleField> moduleFields = attrProcessor.getModuleFields();
List<String> implementedIfcs = Lists.newArrayList(
- Module.class.getCanonicalName(),
mbe.getFullyQualifiedName(mbe.getMXBeanInterfaceName()));
for (String implementedService : mbe.getProvidedServices().keySet()) {
.getCanonicalName());
}
+ List<String> extendedClasses = Collections.singletonList(AbstractModule.class.getCanonicalName() + "<" + mbe.getAbstractModuleName() + ">");
+
AbstractModuleTemplate abstractModuleTemplate = new AbstractModuleTemplate(
getHeaderFromEntry(mbe), mbe.getPackageName(),
- mbe.getAbstractModuleName(), implementedIfcs, moduleFields,
+ mbe.getAbstractModuleName(), extendedClasses, implementedIfcs, moduleFields,
attrProcessor.getMethods(), generateRuntime,
registratorFullyQualifiedName);
import static com.google.common.base.Preconditions.checkState;
import static java.lang.String.format;
+import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Optional;
-import java.util.ArrayList;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.AbstractModuleTemplate;
import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.TemplateFactory;
import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Annotation;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Field;
import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.IdentityRefModuleField;
import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Method;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.MethodDefinition;
import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.ModuleField;
import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.FullyQualifiedName;
import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.GeneratedObject;
public class AbsModuleGeneratedObjectFactory {
+ private static final Function<String, FullyQualifiedName> FULLY_QUALIFIED_NAME_FUNCTION = new Function<String, FullyQualifiedName>() {
+ @Override
+ public FullyQualifiedName apply(final String input) {
+ return FullyQualifiedName.fromString(input);
+ }
+ };
+
public GeneratedObject toGeneratedObject(ModuleMXBeanEntry mbe, Optional<String> copyright) {
FullyQualifiedName abstractFQN = new FullyQualifiedName(mbe.getPackageName(), mbe.getAbstractModuleName());
Optional<String> classJavaDoc = Optional.fromNullable(mbe.getNullableDescription());
AbstractModuleTemplate abstractModuleTemplate = TemplateFactory.abstractModuleTemplateFromMbe(mbe);
Optional<String> header = abstractModuleTemplate.getHeaderString();
- List<FullyQualifiedName> implementedInterfaces = new ArrayList<>();
- for(String implemented: abstractModuleTemplate.getTypeDeclaration().getImplemented()) {
- implementedInterfaces.add(FullyQualifiedName.fromString(implemented));
- }
+ List<FullyQualifiedName> implementedInterfaces = Lists.transform(abstractModuleTemplate.getTypeDeclaration().getImplemented(), FULLY_QUALIFIED_NAME_FUNCTION);
+
+ Optional<FullyQualifiedName> extended =
+ Optional.fromNullable(
+ Iterables.getFirst(
+ Collections2.transform(abstractModuleTemplate.getTypeDeclaration().getExtended(), FULLY_QUALIFIED_NAME_FUNCTION), null));
+
Optional<FullyQualifiedName> maybeRegistratorType;
if (abstractModuleTemplate.isRuntime()) {
maybeRegistratorType = Optional.of(FullyQualifiedName.fromString(abstractModuleTemplate.getRegistratorType()));
maybeRegistratorType = Optional.absent();
}
- return toGeneratedObject(abstractFQN, copyright, header, classJavaDoc, implementedInterfaces,
+ return toGeneratedObject(abstractFQN, copyright, header, classJavaDoc, extended, implementedInterfaces,
abstractModuleTemplate.getModuleFields(), maybeRegistratorType, abstractModuleTemplate.getMethods(),
mbe.getYangModuleQName());
}
Optional<String> copyright,
Optional<String> header,
Optional<String> classJavaDoc,
+ Optional<FullyQualifiedName> extended,
List<FullyQualifiedName> implementedInterfaces,
List<ModuleField> moduleFields,
Optional<FullyQualifiedName> maybeRegistratorType,
for(FullyQualifiedName implemented: implementedInterfaces) {
b.addImplementsFQN(implemented);
}
+ if(extended.isPresent()) {
+ b.addExtendsFQN(extended.get());
+ }
if (classJavaDoc.isPresent()) {
b.addClassAnnotation(format("@%s(value=\"%s\")", Description.class.getCanonicalName(), classJavaDoc.get()));
}
b.addToBody("//attributes end");
- b.addToBody(getCommonFields(abstractFQN));
-
-
b.addToBody(getNewConstructor(abstractFQN));
b.addToBody(getCopyFromOldConstructor(abstractFQN));
b.addToBody(getCachesOfResolvedDependencies(moduleFields));
b.addToBody(getCachesOfResolvedIdentityRefs(moduleFields));
- b.addToBody(getGetInstance(moduleFields));
+ b.addToBody(getResolveDependencies(moduleFields));
b.addToBody(getReuseLogic(moduleFields, abstractFQN));
b.addToBody(getEqualsAndHashCode(abstractFQN));
b.addToBody(getMethods(methods));
+ b.addToBody(getGetLogger());
return new GeneratedObjectBuilder(b.build()).toGeneratedObject();
}
// loop through fields, do deep equals on each field
for (ModuleField moduleField : moduleFields) {
+ result += format(
+ "if (java.util.Objects.deepEquals(%s, other.%1$s) == false) {\n"+
+ "return false;\n"+
+ "}\n", moduleField.getName());
+
if (moduleField.isListOfDependencies()) {
result += format(
- "if (%1$sDependency.equals(other.%1$sDependency) == false) {\n"+
- "return false;\n"+
- "}\n"+
- "for (int idx = 0; idx < %1$sDependency.size(); idx++) {\n"+
- "if (%1$sDependency.get(idx) != other.%1$sDependency.get(idx)) {\n"+
- "return false;\n"+
- "}\n"+
- "}\n" ,moduleField.getName());
+ "for (int idx = 0; idx < %1$s.size(); idx++) {\n"+
+ "if (!dependencyResolver.canReuseDependency(%1$s.get(idx), %1$sJmxAttribute)) {\n"+
+ "return false;\n"+
+ "}\n"+
+ "}\n" , moduleField.getName());
} else if (moduleField.isDependent()) {
result += format(
- "if (%sDependency != other.%1$sDependency) { // reference to dependency must be same\n"+
- "return false;\n"+
- "}\n",moduleField.getName());
- } else {
- result += format(
- "if (java.util.Objects.deepEquals(%s, other.%1$s) == false) {\n"+
- "return false;\n"+
- "}\n", moduleField.getName());
+ // If a reference is null (ie optional reference) it makes no sens to call canReuse on it
+ // In such case we continue in the isSame method because if we have null here, the previous value was null as well
+ // If the previous value was not null and current is or vice verse, the deepEquals comparison would return false
+ "if(%1$s!= null) {\n" +
+ "if (!dependencyResolver.canReuseDependency(%1$s, %1$sJmxAttribute)) { // reference to dependency must be reusable as well\n" +
+ "return false;\n" +
+ "}\n" +
+ "}\n", moduleField.getName());
}
}
+
result += "\n"+
"return true;\n"+
"}\n";
return result;
}
- private static String getGetInstance(List<ModuleField> moduleFields) {
- String result = "\n"+
- "@Override\n"+
- format("public final %s getInstance() {\n", AutoCloseable.class.getCanonicalName())+
- "if(instance==null) {\n";
- // create instance start
-
+ private static String getResolveDependencies(final List<ModuleField> moduleFields) {
// loop through dependent fields, use dependency resolver to instantiate dependencies. Do it in loop in case field represents list of dependencies.
Map<ModuleField, String> resolveDependenciesMap = new HashMap<>();
for(ModuleField moduleField: moduleFields) {
String osgi = moduleField.getDependency().getSie().getExportedOsgiClassName();
if (moduleField.isList()) {
str = format(
- "%sDependency = new java.util.ArrayList<%s>();\n"+
- "for(javax.management.ObjectName dep : %1$s) {\n"+
- "%1$sDependency.add(dependencyResolver.resolveInstance(%2$s.class, dep, %1$sJmxAttribute));\n"+
- "}\n", moduleField.getName(), osgi);
+ "%sDependency = new java.util.ArrayList<%s>();\n"+
+ "for(javax.management.ObjectName dep : %1$s) {\n"+
+ "%1$sDependency.add(dependencyResolver.resolveInstance(%2$s.class, dep, %1$sJmxAttribute));\n"+
+ "}\n", moduleField.getName(), osgi);
} else {
str = format(
- "%1$sDependency = dependencyResolver.resolveInstance(%2$s.class, %1$s, %1$sJmxAttribute);\n",
- moduleField.getName(), osgi);
+ "%1$sDependency = dependencyResolver.resolveInstance(%2$s.class, %1$s, %1$sJmxAttribute);\n",
+ moduleField.getName(), osgi);
}
resolveDependenciesMap.put(moduleField, str);
}
}
+ String result = "\n"
+ + "protected final void resolveDependencies() {\n";
// wrap each field resolvation statement with if !=null when dependency is not mandatory
for (Map.Entry<ModuleField, String> entry : resolveDependenciesMap.entrySet()) {
if (entry.getKey().getDependency().isMandatory() == false) {
result += format("if (%s!=null){\n", moduleField.getName());
if (moduleField.isList()) {
result += format(
- "for(%s candidate : %s) {\n"+
- "candidate.injectDependencyResolver(dependencyResolver);\n"+
- "}\n", moduleField.getGenericInnerType(), moduleField.getName());
+ "for(%s candidate : %s) {\n"+
+ "candidate.injectDependencyResolver(dependencyResolver);\n"+
+ "}\n", moduleField.getGenericInnerType(), moduleField.getName());
} else {
result += format("%s.injectDependencyResolver(dependencyResolver);\n", moduleField.getName());
}
result += "}\n";
}
}
-
- // create instance end: reuse and recreate logic
- result += "if(oldInstance!=null && canReuseInstance(oldModule)) {\n"+
- "instance = reuseInstance(oldInstance);\n"+
- "} else {\n"+
- "if(oldInstance!=null) {\n"+
- "try {\n"+
- "oldInstance.close();\n"+
- "} catch(Exception e) {\n"+
- "logger.error(\"An error occurred while closing old instance \" + oldInstance, e);\n"+
- "}\n"+
- "}\n"+
- "instance = createInstance();\n"+
- "if (instance == null) {\n"+
- "throw new IllegalStateException(\"Error in createInstance - null is not allowed as return value\");\n"+
- "}\n"+
- "}\n"+
- "}\n"+
- "return instance;\n"+
- "}\n"+
- format("public abstract %s createInstance();\n", AutoCloseable.class.getCanonicalName());
-
+ result += "}\n";
return result;
}
- private static String getCommonFields(FullyQualifiedName abstractFQN) {
- return "\n"+
- format("private final %s oldModule;\n", abstractFQN.getTypeName())+
- format("private final %s oldInstance;\n", AutoCloseable.class.getCanonicalName())+
- format("private %s instance;\n", AutoCloseable.class.getCanonicalName())+
- format("protected final %s dependencyResolver;\n", DependencyResolver.class.getCanonicalName())+
- format("private final %s identifier;\n", ModuleIdentifier.class.getCanonicalName())+
- "@Override\n"+
- format("public %s getIdentifier() {\n", ModuleIdentifier.class.getCanonicalName())+
- "return identifier;\n"+
- "}\n";
- }
-
private static String getCachesOfResolvedIdentityRefs(List<ModuleField> moduleFields) {
StringBuilder result = new StringBuilder();
for (ModuleField moduleField : moduleFields) {
"public void validate() {\n";
// validate each mandatory dependency
for(ModuleField moduleField: moduleFields) {
- if (moduleField.isDependent() && moduleField.getDependency().isMandatory()) {
+ if (moduleField.isDependent()) {
if (moduleField.isList()) {
result += "" +
format("for(javax.management.ObjectName dep : %s) {\n", moduleField.getName()) +
moduleField.getDependency().getSie().getFullyQualifiedName(), moduleField.getName()) +
"}\n";
} else {
- result += format("dependencyResolver.validateDependency(%s.class, %s, %sJmxAttribute);",
+ if(moduleField.getDependency().isMandatory() == false) {
+ result += format("if(%s != null) {\n", moduleField.getName());
+ }
+ result += format("dependencyResolver.validateDependency(%s.class, %s, %sJmxAttribute);\n",
moduleField.getDependency().getSie().getFullyQualifiedName(), moduleField.getName(), moduleField.getName());
+ if(moduleField.getDependency().isMandatory() == false) {
+ result += "}\n";
+ }
}
}
}
}
private static String getLoggerDefinition(FullyQualifiedName fqn) {
- return format("private static final %s logger = %s.getLogger(%s.class);",
+ return format("private static final %s LOGGER = %s.getLogger(%s.class);",
Logger.class.getCanonicalName(), LoggerFactory.class.getCanonicalName(), fqn);
}
private static String getConstructorStart(FullyQualifiedName fqn,
LinkedHashMap<String, String> parameters, String after) {
String paramString = Joiner.on(",").withKeyValueSeparator(" ").join(parameters);
- String setters = "";
- for (String paramName : parameters.values()) {
- setters += format("this.%s = %1$s;\n", paramName);
- }
return format("public %s(", fqn.getTypeName()) +
paramString +
") {\n" +
- setters +
after +
"}\n";
}
LinkedHashMap<String, String> parameters = new LinkedHashMap<>();
parameters.put(ModuleIdentifier.class.getCanonicalName(), "identifier");
parameters.put(DependencyResolver.class.getCanonicalName(), "dependencyResolver");
-
- String setToNulls = "this.oldInstance=null;\n" +
- "this.oldModule=null;\n";
- return getConstructorStart(abstractFQN, parameters, setToNulls);
+ String init = "super(identifier, dependencyResolver);\n";
+ return getConstructorStart(abstractFQN, parameters, init);
}
private static String getCopyFromOldConstructor(FullyQualifiedName abstractFQN) {
parameters.put(DependencyResolver.class.getCanonicalName(), "dependencyResolver");
parameters.put(abstractFQN.getTypeName(), "oldModule");
parameters.put(AutoCloseable.class.getCanonicalName(), "oldInstance");
- return getConstructorStart(abstractFQN, parameters, "");
+ String init = "super(identifier, dependencyResolver, oldModule, oldInstance);\n";
+ return getConstructorStart(abstractFQN, parameters, init);
+ }
+
+ public String getGetLogger() {
+ return new MethodDefinition(Logger.class.getCanonicalName(), "getLogger", Collections.<Field>emptyList(), "return LOGGER;").toString();
}
}
import org.opendaylight.controller.config.api.annotations.Description;
import org.opendaylight.controller.config.api.annotations.RequireInterface;
import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
+import org.opendaylight.controller.config.spi.AbstractModule;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
import org.opendaylight.controller.config.yangjmxgenerator.ConfigConstants;
assertContains(visitor.implmts,
PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
+ ".threads.java.DynamicThreadPoolModuleMXBean",
- Module.class.getCanonicalName(),
PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
+ ".threads.ScheduledThreadPoolServiceInterface",
PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
+ ".threads.ThreadPoolServiceInterface");
+ assertContains(visitor.extnds, AbstractModule.class.getCanonicalName());
assertEquals(2, visitor.constructors.size());
Set<String> fieldDeclarations = visitor.fieldDeclarations;
assertDeclaredField(fieldDeclarations,
assertDeclaredField(fieldDeclarations,
"private java.lang.Long coreSize");
assertDeclaredField(fieldDeclarations, "private byte[] binary");
- assertEquals(22, fieldDeclarations.size());
+ assertEquals(17, fieldDeclarations.size());
assertEquals(1, visitor.requireIfc.size());
String reqIfc = visitor.requireIfc.get("setThreadfactory");
assertContains(reqIfc, PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
+ ".threads.ThreadFactoryServiceInterface");
- assertEquals("Incorrenct number of generated methods", 27,
+ assertEquals("Incorrenct number of generated methods", 26,
visitor.methods.size());
assertEquals("Incorrenct number of generated method descriptions", 3,
visitor.methodDescriptions.size());
import static com.google.common.base.Preconditions.checkState;
import static java.lang.String.format;
import static org.opendaylight.controller.config.yangjmxgenerator.ConfigConstants.createConfigQName;
-
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Optional;
String moduleLocalNameFromXPath = matcher.group(1);
IdentitySchemaNode moduleIdentity = moduleIdentities.get(moduleLocalNameFromXPath);
unaugmentedModuleIdentities.remove(moduleLocalNameFromXPath);
- checkState(moduleIdentity != null, "Cannot find identity " + moduleLocalNameFromXPath
- + " matching augmentation " + augmentation);
+ checkState(moduleIdentity != null, "Cannot find identity %s matching augmentation %s", moduleLocalNameFromXPath, augmentation);
Map<String, QName> providedServices = findProvidedServices(moduleIdentity, currentModule, qNamesToSIEs,
schemaContext);
- if (moduleIdentity == null) {
- throw new IllegalStateException("Cannot find identity specified by augmentation xpath constraint: "
- + moduleLocalNameFromXPath + " of " + augmentation);
- }
String javaNamePrefix = TypeProviderWrapper.findJavaNamePrefix(moduleIdentity);
Map<String, AttributeIfc> yangToAttributes = null;
}
}
- private void checkUniqueAttributesWithGeneratedClass(final Map<String, QName> uniqueGeneratedClassNames,
+ private static void checkUniqueAttributesWithGeneratedClass(final Map<String, QName> uniqueGeneratedClassNames,
final QName parentQName, final Map<String, AttributeIfc> yangToAttributes) {
for (Map.Entry<String, AttributeIfc> attr : yangToAttributes.entrySet()) {
if (attr.getValue() instanceof TOAttribute) {
}
}
- private void checkUniqueTOAttr(final Map<String, QName> uniqueGeneratedClassNames, final QName parentQName, final TOAttribute attr) {
+ private static void checkUniqueTOAttr(final Map<String, QName> uniqueGeneratedClassNames, final QName parentQName, final TOAttribute attr) {
final String upperCaseCamelCase = attr.getUpperCaseCammelCase();
if (uniqueGeneratedClassNames.containsKey(upperCaseCamelCase)) {
QName firstDefinedQName = uniqueGeneratedClassNames.get(upperCaseCamelCase);
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
-
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Optional;
final List<RuntimeBeanEntry> children, final Set<Rpc> rpcs) {
checkArgument(isRoot == false || keyYangName.isPresent() == false,
- "Root RuntimeBeanEntry must not have key " + "set");
+ "Root RuntimeBeanEntry must not have key set");
this.packageName = packageName;
this.isRoot = isRoot;
this.yangName = yangName;
for (AttributeIfc a : attributes) {
checkState(map.containsKey(a.getAttributeYangName()) == false,
- "Attribute already defined: " + a.getAttributeYangName()
- + " in " + nodeForReporting);
+ "Attribute already defined: %s in %s", a.getAttributeYangName(), nodeForReporting);
map.put(a.getAttributeYangName(), a);
}
if (keyYangName.isPresent()) {
AttributeIfc keyJavaName = map.get(keyYangName.get());
- checkArgument(keyJavaName != null, "Key " + keyYangName.get()
- + " not found in attribute " + "list " + attributes
- + " in " + nodeForReporting);
+ checkArgument(keyJavaName != null, "Key %s not found in attribute list %s in %s", keyYangName.get(),
+ attributes, nodeForReporting);
this.keyJavaName = Optional
.of(keyJavaName.getUpperCaseCammelCase());
} else {
package org.opendaylight.controller.config.yangjmxgenerator;
import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.isA;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
-
import com.google.common.collect.Sets;
import java.net.URI;
import java.net.URISyntaxException;
is("threadFactory"));
assertThat(threadFactoryAttribute.getUpperCaseCammelCase(),
is("ThreadFactory"));
- assertThat(threadFactoryAttribute.getOpenType(), is(SimpleType.class));
+ assertThat(threadFactoryAttribute.getOpenType(), isA(SimpleType.class));
assertNull(threadFactoryAttribute.getNullableDefault());
assertNull(threadFactoryAttribute.getNullableDescription());
assertThat(threadFactoryAttribute.getType().getName(), is("ObjectName"));
assertThat(toAttr.getAttributeYangName(), is("peer"));
assertThat(toAttr.getLowerCaseCammelCase(), is("peer"));
assertThat(toAttr.getUpperCaseCammelCase(), is("Peer"));
- assertThat(toAttr.getOpenType(), is(CompositeType.class));
+ assertThat(toAttr.getOpenType(), isA(CompositeType.class));
Set<String> propsExpected = new HashSet<String>(2);
propsExpected.add("port");
propsExpected.add("core-size");
is("innerStreamList"));
assertThat(innerStream.getUpperCaseCammelCase(),
is("InnerStreamList"));
- assertThat(innerStream.getOpenType(), is(ArrayType.class));
+ assertThat(innerStream.getOpenType(), isA(ArrayType.class));
}
*.java
+!CheckedAutoCloseable.java
--- /dev/null
+package org.opendaylight.controller.config.yang.test.impl;
+
+import com.google.common.base.Preconditions;
+
+public class CheckedAutoCloseable implements AutoCloseable {
+ private boolean closed = false;
+
+ @Override
+ public synchronized void close() throws Exception {
+ Preconditions.checkState(closed == false);
+ this.closed = true;
+ }
+
+ public synchronized boolean isClosed() {
+ return this.closed;
+ }
+}
- return new AutoCloseable() {
- @Override
- public void close() throws Exception {
- }
- };
+ return new org.opendaylight.controller.config.yang.test.impl.CheckedAutoCloseable();
}
logger.info("IdentityContainer Afi class: {}", getIdentitiesContainer().resolveAfi());
- return new AutoCloseable() {
- @Override
- public void close() throws Exception {
- }
- };
+ return new org.opendaylight.controller.config.yang.test.impl.CheckedAutoCloseable();
- return new AutoCloseable() {
+ return new org.opendaylight.controller.config.yang.test.impl.CheckedAutoCloseable() {
@Override
- public void close() throws Exception {
+ public synchronized void close() throws Exception {
+ if(getSingleDependency() != null && getSingleDependency().isClosed() == true) {
+ // Simulate a cleanup on dependencies that should not be closed yet
+ throw new java.lang.Error("Dependency was closed first");
+ }
+ for (org.opendaylight.controller.config.yang.test.impl.CheckedAutoCloseable autoCloseable : getTestingDepsDependency()) {
+ if(autoCloseable.isClosed() == true) {
+ // Simulate a cleanup on dependencies that should not be closed yet
+ throw new java.lang.Error("Dependency was closed first");
+ }
+ }
+ super.close();
}
- };
+ };
\ No newline at end of file
-return org.opendaylight.controller.config.yang.test.util.NetconfTestImplModuleUtil.registerRuntimeBeans(this);
+ final AutoCloseable runtime = org.opendaylight.controller.config.yang.test.util.NetconfTestImplModuleUtil.registerRuntimeBeans(this);
+ return new org.opendaylight.controller.config.yang.test.impl.CheckedAutoCloseable() {
+ @Override
+ public synchronized void close() throws Exception {
+ runtime.close();
+ }
+ };
\ No newline at end of file
- return new AutoCloseable() {
- @Override
- public void close() throws Exception {
- }
- };
+ return new org.opendaylight.controller.config.yang.test.impl.CheckedAutoCloseable();
\ No newline at end of file
}
}
}
+
}
+
}
}
}
}
}
+ container single {
+ uses config:service-ref {
+ refine type {
+ mandatory false;
+ config:required-identity test:testing;
+ }
+ }
+ }
+
+ leaf simple {
+ type boolean;
+ default false;
+ }
}
}
}
"Test api";
base "config:service-type";
- config:java-class "java.lang.AutoCloseable";
+ config:java-class "org.opendaylight.controller.config.yang.test.impl.CheckedAutoCloseable";
}
}
import static java.util.Arrays.asList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
import static org.opendaylight.controller.config.api.jmx.ObjectNameUtil.getInstanceName;
import static org.opendaylight.controller.config.api.jmx.ObjectNameUtil.getTransactionName;
import java.util.List;
import javax.management.ObjectName;
+import org.hamcrest.CoreMatchers;
import org.junit.Before;
import org.junit.Test;
+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;
assertNull(getTransactionName(d1WithoutTxName));
transaction.commit();
}
+
+ @Test
+ public void testCloseOrdering() throws Exception {
+ // Tests whether close is called in correct order on the module instances on following graph
+ // Each module tests whether its dependencies were closed before it (to simulate resource clean up failure)
+ // R1
+ // | \
+ // M1 M2
+ // |
+ // L1
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+ ObjectName r1 = transaction.createModule(factory.getImplementationName(), "root1");
+ ObjectName m1 = transaction.createModule(factory.getImplementationName(), "middle1");
+ ObjectName m2 = transaction.createModule(factory.getImplementationName(), "middle2");
+ ObjectName l1 = transaction.createModule(factory.getImplementationName(), "leaf1");
+
+ MultipleDependenciesModuleMXBean r1Proxy = transaction.newMXBeanProxy(r1, MultipleDependenciesModuleMXBean.class);
+ MultipleDependenciesModuleMXBean i1Proxy = transaction.newMXBeanProxy(m1, MultipleDependenciesModuleMXBean.class);
+ r1Proxy.setSingle(m1);
+ i1Proxy.setSingle(l1);
+ r1Proxy.setTestingDeps(asList(m2));
+ transaction.commit();
+
+ configRegistryClient.createTransaction().commit();
+ transaction = configRegistryClient.createTransaction();
+ MultipleDependenciesModuleMXBean l1Proxy = transaction.newMXBeanProxy(l1, MultipleDependenciesModuleMXBean.class);
+ l1Proxy.setSimple(true);
+ transaction.commit();
+ }
+
+ @Test
+ public void testDestroyModuleDependency() throws Exception {
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+ ObjectName r1 = transaction.createModule(factory.getImplementationName(), "root1");
+ ObjectName m1 = transaction.createModule(factory.getImplementationName(), "middle1");
+
+ MultipleDependenciesModuleMXBean r1Proxy = transaction.newMXBeanProxy(r1, MultipleDependenciesModuleMXBean.class);
+ r1Proxy.setSingle(m1);
+ transaction.commit();
+
+ transaction = configRegistryClient.createTransaction();
+ transaction.destroyModule(factory.getImplementationName(), "middle1");
+ try {
+ transaction.commit();
+ fail("Validation exception expected");
+ } catch (ValidationException e) {
+ assertThat(e.getFailedValidations().keySet(), CoreMatchers.hasItem("multiple-dependencies"));
+ }
+ }
}
*/
package org.opendaylight.controller.sal.compatibility;
-import java.util.Collection;
-import java.util.Collections;
-
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
import org.opendaylight.controller.sal.binding.api.NotificationService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.FlowTopologyDiscoveryService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService;
-import org.opendaylight.yangtools.yang.binding.RpcService;
import com.google.common.base.Preconditions;
this.activator = Preconditions.checkNotNull(cmpAct);
}
- @Override
- public Collection<? extends ProviderFunctionality> getFunctionality() {
- return Collections.emptyList();
- }
-
- @Override
- public Collection<? extends RpcService> getImplementations() {
- return Collections.emptyList();
- }
-
- @Override
- public void onSessionInitialized(final ConsumerContext session) {
- // No-op
- }
-
@Override
public void onSessionInitiated(final ProviderContext session) {
final NotificationService subscribe = session.getSALService(NotificationService.class);
* @return FiniteDuration
*/
FiniteDuration getIsolatedCheckInterval();
+
+
+ /**
+ * The multiplication factor to be used to determine shard election timeout. The election timeout
+ * is determined by multiplying the election timeout factor with the heartbeat duration.
+ */
+ long getElectionTimeoutFactor();
+
}
public static final FiniteDuration HEART_BEAT_INTERVAL =
new FiniteDuration(100, TimeUnit.MILLISECONDS);
-
private FiniteDuration heartBeatInterval = HEART_BEAT_INTERVAL;
private long snapshotBatchCount = SNAPSHOT_BATCH_COUNT;
private int journalRecoveryLogBatchSize = JOURNAL_RECOVERY_LOG_BATCH_SIZE;
// in-memory journal can use before it needs to snapshot
private int snapshotDataThresholdPercentage = 12;
+ private long electionTimeoutFactor = 2;
+
public void setHeartBeatInterval(FiniteDuration heartBeatInterval) {
this.heartBeatInterval = heartBeatInterval;
}
this.isolatedLeaderCheckInterval = isolatedLeaderCheckInterval;
}
+ public void setElectionTimeoutFactor(long electionTimeoutFactor){
+ this.electionTimeoutFactor = electionTimeoutFactor;
+ }
+
@Override
public long getSnapshotBatchCount() {
return snapshotBatchCount;
@Override
public FiniteDuration getElectionTimeOutInterval() {
- // returns 2 times the heart beat interval
- return getHeartBeatInterval().$times(2);
+ return getHeartBeatInterval().$times(electionTimeoutFactor);
}
@Override
public FiniteDuration getIsolatedCheckInterval() {
return isolatedLeaderCheckInterval;
}
+
+ @Override
+ public long getElectionTimeoutFactor() {
+ return electionTimeoutFactor;
+ }
}
private int currentRecoveryBatchCount;
+
+
public RaftActor(String id, Map<String, String> peerAddresses) {
this(id, peerAddresses, Optional.<ConfigParams>absent());
}
onRecoveryComplete();
- RaftActorBehavior oldBehavior = currentBehavior;
- currentBehavior = new Follower(context);
- handleBehaviorChange(oldBehavior, currentBehavior);
+ initializeBehavior();
}
}
}
replicatedLog.lastIndex(), replicatedLog.snapshotIndex,
replicatedLog.snapshotTerm, replicatedLog.size());
+ initializeBehavior();
+ }
+
+ protected void initializeBehavior(){
+ changeCurrentBehavior(new Follower(context));
+ }
+
+ protected void changeCurrentBehavior(RaftActorBehavior newBehavior){
RaftActorBehavior oldBehavior = currentBehavior;
- currentBehavior = new Follower(context);
+ currentBehavior = newBehavior;
handleBehaviorChange(oldBehavior, currentBehavior);
}
if (oldBehavior != currentBehavior){
onStateChanged();
}
- if (oldBehavior != null) {
- // it can happen that the state has not changed but the leader has changed.
- onLeaderChanged(oldBehavior.getLeaderId(), currentBehavior.getLeaderId());
- if (getRoleChangeNotifier().isPresent() && oldBehavior.state() != currentBehavior.state()) {
- // we do not want to notify when the behavior/role is set for the first time (i.e follower)
- getRoleChangeNotifier().get().tell(new RoleChanged(getId(), oldBehavior.state().name(),
- currentBehavior.state().name()), getSelf());
- }
+ String oldBehaviorLeaderId = oldBehavior == null? null : oldBehavior.getLeaderId();
+ String oldBehaviorState = oldBehavior == null? null : oldBehavior.state().name();
+
+ // it can happen that the state has not changed but the leader has changed.
+ onLeaderChanged(oldBehaviorLeaderId, currentBehavior.getLeaderId());
+
+ if (getRoleChangeNotifier().isPresent() &&
+ (oldBehavior == null || (oldBehavior.state() != currentBehavior.state()))) {
+ getRoleChangeNotifier().get().tell(
+ new RoleChanged(getId(), oldBehaviorState , currentBehavior.state().name()),
+ getSelf());
}
}
* @param identifier
* @param data
*/
- protected void persistData(ActorRef clientActor, String identifier,
- Payload data) {
+ protected void persistData(final ActorRef clientActor, final String identifier,
+ final Payload data) {
ReplicatedLogEntry replicatedLogEntry = new ReplicatedLogImplEntry(
context.getReplicatedLog().lastIndex() + 1,
LOG.debug("Persist data {}", replicatedLogEntry);
}
+ final RaftActorContext raftContext = getRaftActorContext();
+
replicatedLog
- .appendAndPersist(clientActor, identifier, replicatedLogEntry);
- }
+ .appendAndPersist(replicatedLogEntry, new Procedure<ReplicatedLogEntry>() {
+ @Override
+ public void apply(ReplicatedLogEntry replicatedLogEntry) throws Exception {
+ if(!hasFollowers()){
+ // Increment the Commit Index and the Last Applied values
+ raftContext.setCommitIndex(replicatedLogEntry.getIndex());
+ raftContext.setLastApplied(replicatedLogEntry.getIndex());
+
+ // Apply the state immediately
+ applyState(clientActor, identifier, data);
+
+ // Send a ApplyLogEntries message so that we write the fact that we applied
+ // the state to durable storage
+ self().tell(new ApplyLogEntries((int) replicatedLogEntry.getIndex()), self());
+
+ // Check if the "real" snapshot capture has been initiated. If no then do the fake snapshot
+ if(!hasSnapshotCaptureInitiated){
+ raftContext.getReplicatedLog().snapshotPreCommit(raftContext.getLastApplied(),
+ raftContext.getTermInformation().getCurrentTerm());
+ raftContext.getReplicatedLog().snapshotCommit();
+ } else {
+ LOG.debug("Skipping fake snapshotting for {} because real snapshotting is in progress", getId());
+ }
+ } else if (clientActor != null) {
+ // Send message for replication
+ currentBehavior.handleMessage(getSelf(),
+ new Replicate(clientActor, identifier,
+ replicatedLogEntry)
+ );
+ }
+
+ }
+ }); }
protected String getId() {
return context.getId();
hasSnapshotCaptureInitiated = false;
}
+ protected boolean hasFollowers(){
+ return getRaftActorContext().getPeerAddresses().keySet().size() > 0;
+ }
+
private class ReplicatedLogImpl extends AbstractReplicatedLogImpl {
+ private static final int DATA_SIZE_DIVIDER = 5;
+ private long dataSizeSinceLastSnapshot = 0;
+
public ReplicatedLogImpl(Snapshot snapshot) {
super(snapshot.getLastAppliedIndex(), snapshot.getLastAppliedTerm(),
snapshot.getUnAppliedEntries());
@Override public void appendAndPersist(
final ReplicatedLogEntry replicatedLogEntry) {
- appendAndPersist(null, null, replicatedLogEntry);
+ appendAndPersist(replicatedLogEntry, null);
}
@Override
return dataSize;
}
- public void appendAndPersist(final ActorRef clientActor,
- final String identifier,
- final ReplicatedLogEntry replicatedLogEntry) {
+ public void appendAndPersist(
+ final ReplicatedLogEntry replicatedLogEntry,
+ final Procedure<ReplicatedLogEntry> callback) {
if(LOG.isDebugEnabled()) {
LOG.debug("Append log entry and persist {} ", replicatedLogEntry);
new Procedure<ReplicatedLogEntry>() {
@Override
public void apply(ReplicatedLogEntry evt) throws Exception {
- dataSize += replicatedLogEntry.size();
+ int logEntrySize = replicatedLogEntry.size();
+
+ dataSize += logEntrySize;
+ long dataSizeForCheck = dataSize;
+
+ dataSizeSinceLastSnapshot += logEntrySize;
+ long journalSize = lastIndex()+1;
+
+ if(!hasFollowers()) {
+ // When we do not have followers we do not maintain an in-memory log
+ // due to this the journalSize will never become anything close to the
+ // snapshot batch count. In fact will mostly be 1.
+ // Similarly since the journal's dataSize depends on the entries in the
+ // journal the journal's dataSize will never reach a value close to the
+ // memory threshold.
+ // By maintaining the dataSize outside the journal we are tracking essentially
+ // what we have written to the disk however since we no longer are in
+ // need of doing a snapshot just for the sake of freeing up memory we adjust
+ // the real size of data by the DATA_SIZE_DIVIDER so that we do not snapshot as often
+ // as if we were maintaining a real snapshot
+ dataSizeForCheck = dataSizeSinceLastSnapshot / DATA_SIZE_DIVIDER;
+ }
long dataThreshold = Runtime.getRuntime().totalMemory() *
getRaftActorContext().getConfigParams().getSnapshotDataThresholdPercentage() / 100;
// when a snaphsot is being taken, captureSnapshot != null
if (hasSnapshotCaptureInitiated == false &&
- ( journal.size() % context.getConfigParams().getSnapshotBatchCount() == 0 ||
- dataSize > dataThreshold)) {
+ ( journalSize % context.getConfigParams().getSnapshotBatchCount() == 0 ||
+ dataSizeForCheck > dataThreshold)) {
+
+ dataSizeSinceLastSnapshot = 0;
LOG.info("Initiating Snapshot Capture..");
long lastAppliedIndex = -1;
long lastAppliedTerm = -1;
ReplicatedLogEntry lastAppliedEntry = get(context.getLastApplied());
- if (lastAppliedEntry != null) {
+ if (!hasFollowers()) {
+ lastAppliedIndex = replicatedLogEntry.getIndex();
+ lastAppliedTerm = replicatedLogEntry.getTerm();
+ } else if (lastAppliedEntry != null) {
lastAppliedIndex = lastAppliedEntry.getIndex();
lastAppliedTerm = lastAppliedEntry.getTerm();
}
null);
hasSnapshotCaptureInitiated = true;
}
- // Send message for replication
- if (clientActor != null) {
- currentBehavior.handleMessage(getSelf(),
- new Replicate(clientActor, identifier,
- replicatedLogEntry)
- );
+ if(callback != null){
+ callback.apply(replicatedLogEntry);
}
}
}
import akka.actor.ActorRef;
import akka.actor.Cancellable;
import akka.event.LoggingAdapter;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
import org.opendaylight.controller.cluster.raft.ClientRequestTracker;
import org.opendaylight.controller.cluster.raft.RaftActorContext;
import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
import org.opendaylight.controller.cluster.raft.messages.RequestVoteReply;
import scala.concurrent.duration.FiniteDuration;
-import java.util.Random;
-import java.util.concurrent.TimeUnit;
-
/**
* Abstract class that represents the behavior of a RaftActor
* <p/>
protected FiniteDuration electionDuration() {
long variance = new Random().nextInt(context.getConfigParams().getElectionTimeVariance());
return context.getConfigParams().getElectionTimeOutInterval().$plus(
- new FiniteDuration(variance, TimeUnit.MILLISECONDS));
+ new FiniteDuration(variance, TimeUnit.MILLISECONDS));
}
/**
TestActorRef<MockRaftActor> mockActorRef = TestActorRef.create(getSystem(), MockRaftActor.props(id,
Collections.<String,String>emptyMap(), Optional.<ConfigParams>of(config), notifierActor), id);
- MockRaftActor mockRaftActor = mockActorRef.underlyingActor();
- mockRaftActor.setCurrentBehavior(new Follower(mockRaftActor.getRaftActorContext()));
-
// sleeping for a minimum of 2 seconds, if it spans more its fine.
Uninterruptibles.sleepUninterruptibly(2, TimeUnit.SECONDS);
List<Object> matches = MessageCollectorActor.getAllMatching(notifierActor, RoleChanged.class);
assertNotNull(matches);
- assertEquals(2, matches.size());
+ assertEquals(3, matches.size());
- // check if the notifier got a role change from Follower to Candidate
+ // check if the notifier got a role change from null to Follower
RoleChanged raftRoleChanged = (RoleChanged) matches.get(0);
assertEquals(id, raftRoleChanged.getMemberId());
+ assertNull(raftRoleChanged.getOldRole());
+ assertEquals(RaftState.Follower.name(), raftRoleChanged.getNewRole());
+
+ // check if the notifier got a role change from Follower to Candidate
+ raftRoleChanged = (RoleChanged) matches.get(1);
+ assertEquals(id, raftRoleChanged.getMemberId());
assertEquals(RaftState.Follower.name(), raftRoleChanged.getOldRole());
assertEquals(RaftState.Candidate.name(), raftRoleChanged.getNewRole());
// check if the notifier got a role change from Candidate to Leader
- raftRoleChanged = (RoleChanged) matches.get(1);
+ raftRoleChanged = (RoleChanged) matches.get(2);
assertEquals(id, raftRoleChanged.getMemberId());
assertEquals(RaftState.Candidate.name(), raftRoleChanged.getOldRole());
assertEquals(RaftState.Leader.name(), raftRoleChanged.getNewRole());
--- /dev/null
+/*
+ * Copyright (c) 2014 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.md.sal.binding.api;
+
+import java.util.concurrent.TimeUnit;
+import org.opendaylight.yangtools.yang.binding.Notification;
+
+/**
+ * A {@link NotificationService} which also allows its users to
+ * submit YANG-modeled notifications for delivery. There are three
+ * methods of submission, following the patters from {@link java.util.concurrent.BlockingQueue}:
+ * - {@link #putNotification(Notification)}, which may block indefinitely
+ * if the implementation cannot allocate resources to accept the notification,
+ * - {@link #offerNotification(Notification)}, which does not block if face
+ * of resource starvation,
+ * - {@link #offerNotification(Notification, int, TimeUnit)}, which may block
+ * for specified time if resources are thin.
+ *
+ * The actual delivery to listeners is asynchronous and implementation-specific.
+ * Users of this interface should not make any assumptions as to whether the
+ * notification has or has not been seen.
+ */
+public interface NotificationPublishService extends BindingService {
+ /**
+ * Publishes a notification to subscribed listeners. This initiates
+ * the process of sending the notification, but delivery to the
+ * listeners can happen asynchronously, potentially after a call to
+ * this method returns.
+ *
+ * <b>Note:</b> This call will block when the notification queue is full.
+ *
+ * @param notification
+ * the notification to publish.
+ * @throws InterruptedException if interrupted while waiting
+ * @throws NullPointerException if the notification is null
+ */
+ void putNotification(Notification notification) throws InterruptedException;
+
+ /**
+ * Publishes a notification to subscribed listeners. This initiates
+ * the process of sending the notification, but delivery to the
+ * listeners can happen asynchronously, potentially after a call to
+ * this method returns.
+ *
+ * This method is guaranteed not to block.
+ *
+ * @param notification
+ * the notification to publish.
+ * @return true if the notification was accepted for processing, false otherwise
+ * @throws NullPointerException if the notification is null
+ */
+ boolean offerNotification(Notification notification);
+
+ /**
+ * Publishes a notification to subscribed listeners. This initiates
+ * the process of sending the notification, but delivery to the
+ * listeners can happen asynchronously, potentially after a call to
+ * this method returns. This method is guaranteed not to block more
+ * than the specified timeout.
+ *
+ * @param notification
+ * the notification to publish.
+ * @param timeout how long to wait before giving up, in units of unit
+ * @param unit a TimeUnit determining how to interpret the
+ * timeout parameter
+ * @return true if the notification was accepted for processing, false otherwise
+ * @throws InterruptedException if interrupted while waiting
+ * @throws NullPointerException if the notification or unit is null
+ * @throws IllegalArgumentException if timeout is negative.
+ */
+ boolean offerNotification(Notification notification, int timeout, TimeUnit unit)
+ throws InterruptedException;
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.md.sal.binding.api;
+
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.NotificationListener;
+
+/**
+ * Notification broker which allows clients to subscribe for and publish YANG-modeled notifications.
+ *
+ * Each YANG module which defines notifications results in a generated interface <code>{ModuleName}Listener</code>
+ * which handles all the notifications defined in the YANG model. Each notification type translates to
+ * a specific method of the form <code>on{NotificationType}</code> on the generated interface.
+ * The generated interface also extends the
+ * {@link org.opendaylight.yangtools.yang.binding.NotificationListener} interface and implementations
+ * are registered using {@link #registerNotificationListener(org.opendaylight.yangtools.yang.binding.NotificationListener)}
+ * method.
+ *
+ * <h5>Dispatch Listener Example</h5>
+ * <p>
+ * Lets assume we have following YANG model:
+ *
+ * <pre>
+ * module example {
+ * ...
+ *
+ * notification start {
+ * ...
+ * }
+ *
+ * notification stop {
+ * ...
+ * }
+ * }
+ * </pre>
+ *
+ * The generated interface will be:
+ * <pre>
+ * public interface ExampleListener extends NotificationListener {
+ * void onStart(Start notification);
+ * void onStop(Stop notification);
+ * }
+ * </pre>
+ * The following defines an implementation of the generated interface:
+ * <pre>
+ * public class MyExampleListener implements ExampleListener {
+ * public void onStart(Start notification) {
+ * // do something
+ * }
+ *
+ * public void onStop(Stop notification) {
+ * // do something
+ * }
+ * }
+ * </pre>
+ * The implementation is registered as follows:
+ * <pre>
+ * MyExampleListener listener = new MyExampleListener();
+ * ListenerRegistration<NotificationListener> reg = service.registerNotificationListener( listener );
+ * </pre>
+ * The <code>onStart</code> method will be invoked when someone publishes a <code>Start</code> notification and
+ * the <code>onStop</code> method will be invoked when someone publishes a <code>Stop</code> notification.
+ */
+public interface NotificationService extends BindingService {
+ /**
+ * Registers a listener which implements a YANG-generated notification interface derived from
+ * {@link NotificationListener}. The listener is registered for all notifications present in
+ * the implemented interface.
+ *
+ * @param listener the listener implementation that will receive notifications.
+ * @return a {@link ListenerRegistration} instance that should be used to unregister the listener
+ * by invoking the {@link ListenerRegistration#close()} method when no longer needed.
+ */
+ <T extends NotificationListener> ListenerRegistration<T> registerNotificationListener(T listener);
+}
*/
package org.opendaylight.controller.sal.binding.api;
-import java.util.Collection;
-import java.util.Collections;
-
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
-import org.opendaylight.yangtools.yang.binding.RpcService;
import org.osgi.framework.BundleContext;
@Deprecated
@Override
protected final void onBrokerAvailable(BindingAwareBroker broker, BundleContext context) {
ProviderContext ctx = broker.registerProvider(this, context);
- registerRpcImplementations(ctx);
- registerFunctionality(ctx);
- }
-
- private void registerFunctionality(ProviderContext ctx) {
- Collection<? extends ProviderFunctionality> functionality = this.getFunctionality();
- if (functionality == null || functionality.isEmpty()) {
- return;
- }
- for (ProviderFunctionality providerFunctionality : functionality) {
- ctx.registerFunctionality(providerFunctionality);
- }
-
- }
-
- private void registerRpcImplementations(ProviderContext ctx) {
- Collection<? extends RpcService> rpcs = this.getImplementations();
- if (rpcs == null || rpcs.isEmpty()) {
- return;
- }
- for (RpcService rpcService : rpcs) {
- // ctx.addRpcImplementation(type, implementation);
- }
-
- }
-
- @Override
- public Collection<? extends ProviderFunctionality> getFunctionality() {
- return Collections.emptySet();
- }
-
- @Override
- public Collection<? extends RpcService> getImplementations() {
- return Collections.emptySet();
- }
-
- /**
- * Initialization of consumer context.
- *
- * {@link ProviderContext} is replacement of {@link ConsumerContext}
- * so this method is not needed in case of Provider.
- *
- */
- @Deprecated
- @Override
- public final void onSessionInitialized(ConsumerContext session) {
- // NOOP
}
}
package org.opendaylight.controller.sal.binding.api;
import org.opendaylight.controller.md.sal.common.api.routing.RoutedRegistration;
-import org.opendaylight.controller.sal.binding.api.BindingAwareProvider.ProviderFunctionality;
import org.opendaylight.yangtools.concepts.ObjectRegistration;
import org.opendaylight.yangtools.yang.binding.BaseIdentity;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
* and {@link ProviderContext}
*/
public interface BindingAwareBroker {
+ /*
+ * @deprecated Use registerConsumer(BindingAwareConsumer cons) instead (BundleContext is no longer used)
+ */
+ @Deprecated
+ ConsumerContext registerConsumer(BindingAwareConsumer consumer, BundleContext ctx);
+
/**
* Registers the {@link BindingAwareConsumer}, which will use the SAL layer.
*
* @throws IllegalStateException
* If the consumer is already registered.
*/
- ConsumerContext registerConsumer(BindingAwareConsumer consumer, BundleContext ctx);
+ ConsumerContext registerConsumer(BindingAwareConsumer consumer);
+
+ /*
+ * @deprecated Use registerProvider(BindingAwareProvider prov) instead (BundleContext is no longer used)
+ */
+ @Deprecated
+ ProviderContext registerProvider(BindingAwareProvider provider, BundleContext ctx);
/**
* Registers the {@link BindingAwareProvider}, which will use the SAL layer.
* @throws IllegalStateException
* If the consumer is already registered.
*/
- ProviderContext registerProvider(BindingAwareProvider provider, BundleContext ctx);
+ ProviderContext registerProvider(BindingAwareProvider provider);
/**
* {@link BindingAwareConsumer} specific access to the SAL functionality.
*/
public interface ProviderContext extends ConsumerContext, RpcProviderRegistry {
- @Deprecated
- void registerFunctionality(ProviderFunctionality functionality);
-
- @Deprecated
- void unregisterFunctionality(ProviderFunctionality functionality);
}
/**
*/
package org.opendaylight.controller.sal.binding.api;
-import java.util.Collection;
-
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
-import org.opendaylight.yangtools.yang.binding.RpcService;
/**
*
*/
public interface BindingAwareProvider {
- /**
- * @deprecated
- *
- * This interface was originally intended to solve problems of how to get Implementations
- * of functionality from a provider, but that is no longer necessary because the Provider
- * Registers RPCs in onSessionInitiated.
- *
- * Recommend:
- * {code
- * public Collection<? extends RpcService> getImplementations() {
- * return Collections.emptySet();
- * }
- * }
- */
- @Deprecated
- Collection<? extends RpcService> getImplementations();
-
- /**
- * @deprecated
- *
- * This interface was originally intended to solve problems of how to get Functionality
- * a provider could provide, but that is no longer necessary because the Provider
- * Registers RPCs in onSessionInitiated.
- *
- * Recommend:
- * {code
- * public Collection<? extends ProviderFunctionality> getFunctionality() {
- * return Collections.emptySet();
- * }
- * }
- *
- */
- @Deprecated
- Collection<? extends ProviderFunctionality> getFunctionality();
-
- /**
- * Functionality provided by the {@link BindingAwareProvider}
- *
- * <p>
- * Marker interface used to mark the interfaces describing specific
- * functionality which could be exposed by providers to other components.
- *
- *
- *
- */
- @Deprecated
- public interface ProviderFunctionality {
-
- }
/**
* Callback signaling initialization of the consumer session to the SAL.
*
* @param session Unique session between consumer and SAL.
*/
void onSessionInitiated(ProviderContext session);
-
- /*
- * @deprecated
- *
- * A provider was at one point considered an extension of a consumer, thus this
- * call. It is deprecated and the @see org.opendaylight.controller.sal.binding.api.BindingAwareConsumer#onSessionInitiated
- * used, or you should simply use {@link #onSessionInitiated(ProviderContext)}
- *
- * Recommend:
- * {code
- * public final void onSessionInitialized(ConsumerContext session) {
- * // NOOP - as method is deprecated
- * }
- * }
- */
- @Deprecated
- void onSessionInitialized(ConsumerContext session);
-
}
+++ /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.sal.binding.api.data;
-
-import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
-
-/**
- * Trigger for refreshing of the data exposed by the {@link Provider}
- *
- *
- * @deprecated Unused, not supported. Replaced by org.opendaylight.controller.sal.core.spi.data.DOMStore.
- */
-@Deprecated
-public interface DataRefresher extends BindingAwareProvider.ProviderFunctionality {
-
- /**
- * Fired when some component explicitly requested the data refresh.
- *
- * The provider which exposed the {@link DataRefresher} should republish its
- * provided data by editing the data in all affected data stores.
- */
- void refreshData();
-}
\ No newline at end of file
+++ /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.sal.binding.api.data;
-
-import org.opendaylight.controller.md.sal.common.api.data.DataReader;
-import org.opendaylight.controller.sal.binding.api.BindingAwareProvider.ProviderFunctionality;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-/**
- * Utility interface which does type capture for BindingAware DataReader.
- *
- *
- * @deprecated Removed, replaced by org.opendaylight.controller.sal.core.spi.data.DOMStore.
- *
- */
-@Deprecated
-public interface RuntimeDataProvider extends ProviderFunctionality,DataReader<InstanceIdentifier<? extends DataObject>, DataObject> {
-
-
-
-}
}
@Override
- public ConsumerContext registerConsumer(final BindingAwareConsumer consumer, final BundleContext ctx) {
+ public ConsumerContext registerConsumer(BindingAwareConsumer consumer,
+ BundleContext ctx) {
+ return registerConsumer(consumer);
+ }
+
+ @Override
+ public ProviderContext registerProvider(BindingAwareProvider provider,
+ BundleContext ctx) {
+ return registerProvider(provider);
+ }
+
+ @Override
+ public ConsumerContext registerConsumer(final BindingAwareConsumer consumer) {
checkState(supportedConsumerServices != null, "Broker is not initialized.");
return BindingContextUtils.createConsumerContextAndInitialize(consumer, supportedConsumerServices);
}
@Override
- public ProviderContext registerProvider(final BindingAwareProvider provider, final BundleContext ctx) {
+ public ProviderContext registerProvider(final BindingAwareProvider provider) {
checkState(supportedProviderServices != null, "Broker is not initialized.");
return BindingContextUtils.createProviderContextAndInitialize(provider, supportedProviderServices);
}
import java.util.Collection;
import java.util.Collections;
-
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+
import org.opendaylight.controller.md.sal.binding.impl.AbstractForwardedDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
import org.opendaylight.controller.md.sal.common.api.routing.RouteChangePublisher;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
-import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider;
import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;
import org.opendaylight.controller.sal.binding.impl.MountPointManagerImpl.BindingMountPointImpl;
import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl;
import org.slf4j.LoggerFactory;
public class BindingIndependentConnector implements //
- RuntimeDataProvider, //
+ DataReader<InstanceIdentifier<? extends DataObject>, DataObject>, //
Provider, //
AutoCloseable {
*/
package org.opendaylight.controller.test.sal.binding.it;
-import java.util.Collection;
-import java.util.Collections;
-
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
-import org.opendaylight.yangtools.yang.binding.RpcService;
public abstract class AbstractTestProvider implements BindingAwareProvider {
- @Override
- public Collection<? extends RpcService> getImplementations() {
- return Collections.emptySet();
- }
-
- @Override
- public Collection<? extends ProviderFunctionality> getFunctionality() {
- return Collections.emptySet();
- }
-
- @Override
- public void onSessionInitialized(ConsumerContext session) {
- // Noop
-
- }
}
import java.math.BigInteger;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Before;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.NotificationListener;
-import org.opendaylight.yangtools.yang.binding.RpcService;
@Ignore
public class NotificationTest extends AbstractTest {
listener2Reg = session.getSALService(NotificationProviderService.class).registerNotificationListener(
listener2);
}
-
- @Override
- public void onSessionInitialized(ConsumerContext session) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public Collection<? extends RpcService> getImplementations() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Collection<? extends ProviderFunctionality> getFunctionality() {
- // TODO Auto-generated method stub
- return null;
- }
-
};
// registerConsumer method calls onSessionInitialized method above
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer;
import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
-import org.opendaylight.controller.sal.binding.api.BindingAwareProvider.ProviderFunctionality;
import org.opendaylight.controller.sal.binding.api.BindingAwareService;
import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
throws IllegalStateException {
return getSALService(RpcProviderRegistry.class).addRpcImplementation(type, implementation);
}
-
- @Deprecated
- @Override
- public void registerFunctionality(ProviderFunctionality functionality) {
- // NOOP
- }
-
- @Deprecated
- @Override
- public void unregisterFunctionality(ProviderFunctionality functionality) {
- // NOOP
- }
}
}
<type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
<name>yang-schema-service</name>
</operational-schema-service>
+ <operational-properties>
+ <persistent>false</persistent>
+ </operational-properties>
</module>
<module>
private final Timeout shardLeaderElectionTimeout;
private final boolean persistent;
private final ConfigurationReader configurationReader;
+ private final long shardElectionTimeoutFactor;
private DatastoreContext(InMemoryDOMDataStoreConfigProperties dataStoreProperties,
ConfigParams shardRaftConfig, String dataStoreMXBeanType, int operationTimeoutInSeconds,
Duration shardTransactionIdleTimeout, int shardTransactionCommitTimeoutInSeconds,
int shardTransactionCommitQueueCapacity, Timeout shardInitializationTimeout,
Timeout shardLeaderElectionTimeout,
- boolean persistent, ConfigurationReader configurationReader) {
+ boolean persistent, ConfigurationReader configurationReader, long shardElectionTimeoutFactor) {
this.dataStoreProperties = dataStoreProperties;
this.shardRaftConfig = shardRaftConfig;
this.dataStoreMXBeanType = dataStoreMXBeanType;
this.shardLeaderElectionTimeout = shardLeaderElectionTimeout;
this.persistent = persistent;
this.configurationReader = configurationReader;
+ this.shardElectionTimeoutFactor = shardElectionTimeoutFactor;
}
public static Builder newBuilder() {
return configurationReader;
}
+ public long getShardElectionTimeoutFactor(){
+ return this.shardElectionTimeoutFactor;
+ }
+
public static class Builder {
private InMemoryDOMDataStoreConfigProperties dataStoreProperties;
private Duration shardTransactionIdleTimeout = Duration.create(10, TimeUnit.MINUTES);
private ConfigurationReader configurationReader = new FileConfigurationReader();
private int shardIsolatedLeaderCheckIntervalInMillis = shardHeartbeatIntervalInMillis * 10;
private int shardSnapshotDataThresholdPercentage = 12;
+ private long shardElectionTimeoutFactor = 2;
public Builder shardTransactionIdleTimeout(Duration shardTransactionIdleTimeout) {
this.shardTransactionIdleTimeout = shardTransactionIdleTimeout;
return this;
}
+ public Builder shardElectionTimeoutFactor(long shardElectionTimeoutFactor){
+ this.shardElectionTimeoutFactor = shardElectionTimeoutFactor;
+ return this;
+ }
+
public DatastoreContext build() {
DefaultConfigParamsImpl raftConfig = new DefaultConfigParamsImpl();
raftConfig.setJournalRecoveryLogBatchSize(shardJournalRecoveryLogBatchSize);
raftConfig.setSnapshotBatchCount(shardSnapshotBatchCount);
raftConfig.setSnapshotDataThresholdPercentage(shardSnapshotDataThresholdPercentage);
+ raftConfig.setElectionTimeoutFactor(shardElectionTimeoutFactor);
raftConfig.setIsolatedLeaderCheckInterval(
new FiniteDuration(shardIsolatedLeaderCheckIntervalInMillis, TimeUnit.MILLISECONDS));
operationTimeoutInSeconds, shardTransactionIdleTimeout,
shardTransactionCommitTimeoutInSeconds, shardTransactionCommitQueueCapacity,
shardInitializationTimeout, shardLeaderElectionTimeout,
- persistent, configurationReader);
+ persistent, configurationReader, shardElectionTimeoutFactor);
}
}
}
private Cancellable txCommitTimeoutCheckSchedule;
- private Optional<ActorRef> roleChangeNotifier;
+ private final Optional<ActorRef> roleChangeNotifier;
/**
* Coordinates persistence recovery on startup.
// currently uses a same thread executor anyway.
cohortEntry.getCohort().preCommit().get();
- Shard.this.persistData(getSender(), transactionID,
- new CompositeModificationByteStringPayload(cohortEntry.getModification().toSerializable()));
+ // If we do not have any followers and we are not using persistence we can
+ // apply modification to the state immediately
+ if(!hasFollowers() && !persistence().isRecoveryApplicable()){
+ applyModificationToState(getSender(), transactionID, cohortEntry.getModification());
+ } else {
+ Shard.this.persistData(getSender(), transactionID,
+ new CompositeModificationByteStringPayload(cohortEntry.getModification().toSerializable()));
+ }
} catch (InterruptedException | ExecutionException e) {
LOG.error(e, "An exception occurred while preCommitting transaction {}",
cohortEntry.getTransactionID());
doAbortTransaction(abort.getTransactionID(), getSender());
}
- private void doAbortTransaction(final String transactionID, final ActorRef sender) {
+ void doAbortTransaction(final String transactionID, final ActorRef sender) {
final CohortEntry cohortEntry = commitCoordinator.getCohortEntryIfCurrent(transactionID);
if(cohortEntry != null) {
LOG.debug("Aborting transaction {}", transactionID);
.persistent(props.getPersistent().booleanValue())
.shardIsolatedLeaderCheckIntervalInMillis(
props.getShardIsolatedLeaderCheckIntervalInMillis().getValue())
+ .shardElectionTimeoutFactor(props.getShardElectionTimeoutFactor().getValue())
.build();
return DistributedDataStoreFactory.createInstance("config", getConfigSchemaServiceDependency(),
.persistent(props.getPersistent().booleanValue())
.shardIsolatedLeaderCheckIntervalInMillis(
props.getShardIsolatedLeaderCheckIntervalInMillis().getValue())
+ .shardElectionTimeoutFactor(props.getShardElectionTimeoutFactor().getValue())
.build();
return DistributedDataStoreFactory.createInstance("operational",
description "The interval at which a shard will send a heart beat message to its remote shard.";
}
+ leaf shard-election-timeout-factor {
+ default 2;
+ type non-zero-uint32-type;
+ description "The multiplication factor to be used to determine shard election timeout. The shard election timeout
+ is determined by multiplying shard-heartbeat-interval-in-millis with the shard-election-timeout-factor";
+ }
+
leaf operation-timeout-in-seconds {
default 5;
type operation-timeout-type;
new JavaTestKit(getSystem()) {{
final ActorRef shardManager = getSystem().actorOf(newShardMgrProps());
- shardManager.tell(new UpdateSchemaContext(TestModel.createTestContext()), getRef());
-
shardManager.tell(new FindPrimary(Shard.DEFAULT_NAME, false).toSerializable(), getRef());
expectMsgClass(duration("5 seconds"), ActorNotInitialized.class);
new JavaTestKit(getSystem()) {{
final ActorRef shardManager = getSystem().actorOf(newShardMgrProps());
- shardManager.tell(new UpdateSchemaContext(TestModel.createTestContext()), getRef());
-
shardManager.tell(new FindLocalShard(Shard.DEFAULT_NAME, false), getRef());
expectMsgClass(duration("5 seconds"), ActorNotInitialized.class);
import org.mockito.InOrder;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.cluster.datastore.DatastoreContext.Builder;
import org.opendaylight.controller.cluster.datastore.identifiers.ShardIdentifier;
import org.opendaylight.controller.cluster.datastore.messages.AbortTransaction;
import org.opendaylight.controller.cluster.datastore.messages.AbortTransactionReply;
private final ShardIdentifier shardID = ShardIdentifier.builder().memberName("member-1")
.shardName("inventory").type("config" + NEXT_SHARD_NUM.getAndIncrement()).build();
- private DatastoreContext dataStoreContext = DatastoreContext.newBuilder().
+ private final Builder dataStoreContextBuilder = DatastoreContext.newBuilder().
shardJournalRecoveryLogBatchSize(3).shardSnapshotBatchCount(5000).
- shardHeartbeatIntervalInMillis(100).build();
+ shardHeartbeatIntervalInMillis(100);
@Before
public void setUp() {
+ Builder newBuilder = DatastoreContext.newBuilder();
InMemorySnapshotStore.clear();
InMemoryJournal.clear();
}
InMemoryJournal.clear();
}
+ private DatastoreContext newDatastoreContext() {
+ return dataStoreContextBuilder.build();
+ }
+
private Props newShardProps() {
return Shard.props(shardID, Collections.<ShardIdentifier,String>emptyMap(),
- dataStoreContext, SCHEMA_CONTEXT);
+ newDatastoreContext(), SCHEMA_CONTEXT);
}
@Test
@Override
public Shard create() throws Exception {
return new Shard(shardID, Collections.<ShardIdentifier,String>emptyMap(),
- dataStoreContext, SCHEMA_CONTEXT) {
+ newDatastoreContext(), SCHEMA_CONTEXT) {
@Override
public void onReceiveCommand(final Object message) throws Exception {
if(message instanceof ElectionTimeout && firstElectionTimeout) {
class TestShard extends Shard {
TestShard() {
super(shardID, Collections.<ShardIdentifier, String>singletonMap(shardID, null),
- dataStoreContext, SCHEMA_CONTEXT);
+ newDatastoreContext(), SCHEMA_CONTEXT);
}
Map<String, String> getPeerAddresses() {
@Override
public Shard create() throws Exception {
return new Shard(shardID, Collections.<ShardIdentifier,String>emptyMap(),
- dataStoreContext, SCHEMA_CONTEXT) {
+ newDatastoreContext(), SCHEMA_CONTEXT) {
@Override
protected void onRecoveryComplete() {
try {
assertTrue("Missing leaf " + TestModel.ID_QNAME.getLocalName(), idLeaf.isPresent());
assertEquals(TestModel.ID_QNAME.getLocalName() + " value", 1, idLeaf.get().getValue());
- for(int i = 0; i < 20 * 5; i++) {
- long lastLogIndex = shard.underlyingActor().getShardMBean().getLastLogIndex();
- if(lastLogIndex == 2) {
- break;
- }
- Uninterruptibles.sleepUninterruptibly(50, TimeUnit.MILLISECONDS);
+ verifyLastLogIndex(shard, 2);
+
+ shard.tell(PoisonPill.getInstance(), ActorRef.noSender());
+ }};
+ }
+
+ private void verifyLastLogIndex(TestActorRef<Shard> shard, long expectedValue) {
+ for(int i = 0; i < 20 * 5; i++) {
+ long lastLogIndex = shard.underlyingActor().getShardMBean().getLastLogIndex();
+ if(lastLogIndex == expectedValue) {
+ break;
}
+ Uninterruptibles.sleepUninterruptibly(50, TimeUnit.MILLISECONDS);
+ }
+
+ assertEquals("Last log index", expectedValue, shard.underlyingActor().getShardMBean().getLastLogIndex());
+ }
+
+ @Test
+ public void testCommitWithPersistenceDisabled() throws Throwable {
+ dataStoreContextBuilder.persistent(false);
+ new ShardTestKit(getSystem()) {{
+ final TestActorRef<Shard> shard = TestActorRef.create(getSystem(),
+ newShardProps().withDispatcher(Dispatchers.DefaultDispatcherId()),
+ "testCommitPhaseFailure");
- assertEquals("Last log index", 2, shard.underlyingActor().getShardMBean().getLastLogIndex());
+ waitUntilLeader(shard);
+
+ InMemoryDOMDataStore dataStore = shard.underlyingActor().getDataStore();
+
+ // Setup a simulated transactions with a mock cohort.
+
+ String transactionID = "tx";
+ MutableCompositeModification modification = new MutableCompositeModification();
+ NormalizedNode<?, ?> containerNode = ImmutableNodes.containerNode(TestModel.TEST_QNAME);
+ DOMStoreThreePhaseCommitCohort cohort = setupMockWriteTransaction("cohort", dataStore,
+ TestModel.TEST_PATH, containerNode, modification);
+
+ FiniteDuration duration = duration("5 seconds");
+
+ // Simulate the ForwardedReadyTransaction messages that would be sent
+ // by the ShardTransaction.
+
+ shard.tell(new ForwardedReadyTransaction(transactionID, CURRENT_VERSION,
+ cohort, modification, true), getRef());
+ expectMsgClass(duration, ReadyTransactionReply.SERIALIZABLE_CLASS);
+
+ // Send the CanCommitTransaction message.
+
+ shard.tell(new CanCommitTransaction(transactionID).toSerializable(), getRef());
+ CanCommitTransactionReply canCommitReply = CanCommitTransactionReply.fromSerializable(
+ expectMsgClass(duration, CanCommitTransactionReply.SERIALIZABLE_CLASS));
+ assertEquals("Can commit", true, canCommitReply.getCanCommit());
+
+ // Send the CanCommitTransaction message.
+
+ shard.tell(new CommitTransaction(transactionID).toSerializable(), getRef());
+ expectMsgClass(duration, CommitTransactionReply.SERIALIZABLE_CLASS);
+
+ InOrder inOrder = inOrder(cohort);
+ inOrder.verify(cohort).canCommit();
+ inOrder.verify(cohort).preCommit();
+ inOrder.verify(cohort).commit();
+
+ NormalizedNode<?, ?> actualNode = readStore(shard, TestModel.TEST_PATH);
+ assertEquals(TestModel.TEST_QNAME.getLocalName(), containerNode, actualNode);
shard.tell(PoisonPill.getInstance(), ActorRef.noSender());
}};
waitUntilLeader(shard);
final FiniteDuration duration = duration("5 seconds");
- final Timeout timeout = new Timeout(duration);
-
InMemoryDOMDataStore dataStore = shard.underlyingActor().getDataStore();
final String transactionID = "tx1";
- final CountDownLatch abortComplete = new CountDownLatch(1);
Function<DOMStoreThreePhaseCommitCohort,ListenableFuture<Void>> preCommit =
new Function<DOMStoreThreePhaseCommitCohort,ListenableFuture<Void>>() {
@Override
public ListenableFuture<Void> apply(final DOMStoreThreePhaseCommitCohort cohort) {
ListenableFuture<Void> preCommitFuture = cohort.preCommit();
- Future<Object> abortFuture = Patterns.ask(shard,
- new AbortTransaction(transactionID).toSerializable(), timeout);
- abortFuture.onComplete(new OnComplete<Object>() {
- @Override
- public void onComplete(final Throwable e, final Object resp) {
- abortComplete.countDown();
- }
- }, getSystem().dispatcher());
+ // Simulate an AbortTransaction message occurring during replication, after
+ // persisting and before finishing the commit to the in-memory store.
+ // We have no followers so due to optimizations in the RaftActor, it does not
+ // attempt replication and thus we can't send an AbortTransaction message b/c
+ // it would be processed too late after CommitTransaction completes. So we'll
+ // simulate an AbortTransaction message occurring during replication by calling
+ // the shard directly.
+ //
+ shard.underlyingActor().doAbortTransaction(transactionID, null);
return preCommitFuture;
}
expectMsgClass(duration, CanCommitTransactionReply.SERIALIZABLE_CLASS));
assertEquals("Can commit", true, canCommitReply.getCanCommit());
- Future<Object> commitFuture = Patterns.ask(shard,
- new CommitTransaction(transactionID).toSerializable(), timeout);
-
- assertEquals("Abort complete", true, abortComplete.await(5, TimeUnit.SECONDS));
-
- Await.result(commitFuture, duration);
+ shard.tell(new CommitTransaction(transactionID).toSerializable(), getRef());
+ expectMsgClass(duration, CommitTransactionReply.SERIALIZABLE_CLASS);
NormalizedNode<?, ?> node = readStore(shard, TestModel.TEST_PATH);
+
+ // Since we're simulating an abort occurring during replication and before finish commit,
+ // the data should still get written to the in-memory store since we've gotten past
+ // canCommit and preCommit and persisted the data.
assertNotNull(TestModel.TEST_QNAME.getLocalName() + " not found", node);
shard.tell(PoisonPill.getInstance(), ActorRef.noSender());
@Test
public void testTransactionCommitTimeout() throws Throwable {
- dataStoreContext = DatastoreContext.newBuilder().shardTransactionCommitTimeoutInSeconds(1).build();
+ dataStoreContextBuilder.shardTransactionCommitTimeoutInSeconds(1);
new ShardTestKit(getSystem()) {{
final TestActorRef<Shard> shard = TestActorRef.create(getSystem(),
@Test
public void testTransactionCommitQueueCapacityExceeded() throws Throwable {
- dataStoreContext = DatastoreContext.newBuilder().shardTransactionCommitQueueCapacity(1).build();
+ dataStoreContextBuilder.shardTransactionCommitQueueCapacity(1);
new ShardTestKit(getSystem()) {{
final TestActorRef<Shard> shard = TestActorRef.create(getSystem(),
// Wait for the 2nd Tx to complete the canCommit phase.
- final CountDownLatch latch = new CountDownLatch(1);
- canCommitFuture.onComplete(new OnComplete<Object>() {
- @Override
- public void onComplete(final Throwable t, final Object resp) {
- latch.countDown();
- }
- }, getSystem().dispatcher());
-
- assertEquals("2nd CanCommit complete", true, latch.await(5, TimeUnit.SECONDS));
+ Await.ready(canCommitFuture, duration);
InOrder inOrder = inOrder(cohort1, cohort2);
inOrder.verify(cohort1).canCommit();
@Override
public Shard create() throws Exception {
return new Shard(shardID, Collections.<ShardIdentifier,String>emptyMap(),
- dataStoreContext, SCHEMA_CONTEXT) {
+ newDatastoreContext(), SCHEMA_CONTEXT) {
@Override
protected void commitSnapshot(final long sequenceNumber) {
super.commitSnapshot(sequenceNumber);
import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
import org.opendaylight.controller.sal.core.api.data.DataProviderService;
-import org.opendaylight.controller.sal.core.api.data.DataStore;
import org.opendaylight.controller.sal.core.api.model.SchemaService;
import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
import org.opendaylight.controller.sal.core.api.mount.MountService;
import org.opendaylight.controller.sal.dom.broker.BackwardsCompatibleMountPointManager;
import org.opendaylight.controller.sal.dom.broker.BrokerImpl;
-import org.opendaylight.controller.sal.dom.broker.DataBrokerImpl;
import org.opendaylight.controller.sal.dom.broker.GlobalBundleScanningSchemaServiceImpl;
-import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter;
import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareRpcBroker;
import org.opendaylight.controller.sal.dom.broker.impl.SchemaContextProviders;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
/**
*
@Override
public java.lang.AutoCloseable createInstance() {
- final DataStore legacyStore = getDataStoreDependency();
final DOMDataBroker asyncBroker= getAsyncDataBrokerDependency();
- ClassToInstanceMap<BrokerService> services = MutableClassToInstanceMap.create();
+ final ClassToInstanceMap<BrokerService> services = MutableClassToInstanceMap.create();
- SchemaService schemaService = getSchemaServiceImpl();
+ final SchemaService schemaService = getSchemaServiceImpl();
services.putInstance(SchemaService.class, schemaService);
- SchemaAwareRpcBroker router = new SchemaAwareRpcBroker("/", SchemaContextProviders
+ final SchemaAwareRpcBroker router = new SchemaAwareRpcBroker("/", SchemaContextProviders
.fromSchemaService(schemaService));
services.putInstance(RpcProvisionRegistry.class, router);
- final DataProviderService legacyData;
- if(asyncBroker != null) {
- services.putInstance(DOMDataBroker.class, asyncBroker);
- legacyData = new BackwardsCompatibleDataBroker(asyncBroker,schemaService);
- } else {
- legacyData = createLegacyDataService(legacyStore,schemaService);
- }
+ services.putInstance(DOMDataBroker.class, asyncBroker);
+ final DataProviderService legacyData = new BackwardsCompatibleDataBroker(asyncBroker,schemaService);
services.putInstance(DataProviderService.class,legacyData);
services.putInstance(DataBrokerService.class, legacyData);
return new BrokerImpl(router, services);
}
- @Deprecated
- private DataProviderService createLegacyDataService(final DataStore legacyStore, final SchemaService schemaService) {
- YangInstanceIdentifier rootPath = YangInstanceIdentifier.builder().toInstance();
- DataBrokerImpl dataService = new DataBrokerImpl();
- SchemaAwareDataStoreAdapter wrappedStore = new SchemaAwareDataStoreAdapter();
- wrappedStore.changeDelegate(legacyStore);
- wrappedStore.setValidationEnabled(false);
-
- schemaService.registerSchemaContextListener(wrappedStore);
-
- dataService.registerConfigurationReader(rootPath, wrappedStore);
- dataService.registerCommitHandler(rootPath, wrappedStore);
- dataService.registerOperationalReader(rootPath, wrappedStore);
- return dataService;
- }
-
private SchemaService getSchemaServiceImpl() {
final SchemaService schemaService;
if(getRootSchemaService() != null) {
*/
private static final AtomicReferenceFieldUpdater<PingPongTransactionChain, PingPongTransaction> READY_UPDATER =
AtomicReferenceFieldUpdater.newUpdater(PingPongTransactionChain.class, PingPongTransaction.class, "readyTx");
- @SuppressWarnings("unused") // Accessed via READY_UPDATER
private volatile PingPongTransaction readyTx;
/**
return oldTx;
}
- // This forces allocateTransaction() on a slow path
+ /*
+ * This forces allocateTransaction() on a slow path, which has to happen after
+ * this method has completed executing.
+ */
@GuardedBy("this")
private void processIfReady() {
final PingPongTransaction tx = READY_UPDATER.getAndSet(this, null);
}
private void readyTransaction(final @Nonnull PingPongTransaction tx) {
+ // First mark the transaction as not locked.
final boolean lockedMatch = LOCKED_UPDATER.compareAndSet(this, tx, null);
Preconditions.checkState(lockedMatch, "Attempted to submit transaction %s while we have %s", tx, lockedTx);
-
LOG.debug("Transaction {} unlocked", tx);
+ /*
+ * The transaction is ready. It will then be picked up by either next allocation,
+ * or a background transaction completion callback.
+ */
+ final boolean success = READY_UPDATER.compareAndSet(this, null, tx);
+ Preconditions.checkState(success, "Transaction %s collided on ready state", tx, readyTx);
+ LOG.debug("Transaction {} readied");
+
+ /*
+ * We do not see a transaction being in-flight, so we need to take care of dispatching
+ * the transaction to the backend. We are in the ready case, we cannot short-cut
+ * the checking of readyTx, as an in-flight transaction may have completed between us
+ * setting the field above and us checking.
+ */
if (inflightTx == null) {
synchronized (this) {
- processTransaction(tx);
+ processIfReady();
}
}
}
+++ /dev/null
-/*
- * Copyright (c) 2014 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.sal.dom.broker.impl;
-
-import java.util.concurrent.atomic.AtomicLong;
-
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.controller.sal.core.api.data.DataStore;
-import org.opendaylight.yangtools.concepts.Delegator;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-
-@Deprecated
-public class DataStoreStatsWrapper implements Delegator<DataStore>, DataStore {
-
- private final DataStore delegate;
-
- private AtomicLong cfgReadCount = new AtomicLong();
- private AtomicLong cfgReadTimeTotal = new AtomicLong();
-
- private AtomicLong operReadCount = new AtomicLong();
- private AtomicLong operReadTimeTotal = new AtomicLong();
-
- private AtomicLong requestCommitCount = new AtomicLong();
- private AtomicLong requestCommitTimeTotal = new AtomicLong();
-
- public DataStoreStatsWrapper(DataStore store) {
- delegate = store;
- }
-
- @Override
- public DataStore getDelegate() {
- return delegate;
- }
-
- @Override
- public CompositeNode readConfigurationData(YangInstanceIdentifier path) {
- cfgReadCount.incrementAndGet();
- final long startTime = System.nanoTime();
- try {
- return delegate.readConfigurationData(path);
- } finally {
- final long endTime = System.nanoTime();
- final long runTime = endTime - startTime;
- cfgReadTimeTotal.addAndGet(runTime);
- }
- }
-
- @Override
- public CompositeNode readOperationalData(YangInstanceIdentifier path) {
- operReadCount.incrementAndGet();
- final long startTime = System.nanoTime();
- try {
- return delegate.readOperationalData(path);
- } finally {
- final long endTime = System.nanoTime();
- final long runTime = endTime - startTime;
- operReadTimeTotal.addAndGet(runTime);
- }
- }
-
- public DataCommitTransaction<YangInstanceIdentifier, CompositeNode> requestCommit(
- DataModification<YangInstanceIdentifier, CompositeNode> modification) {
- requestCommitCount.incrementAndGet();
- final long startTime = System.nanoTime();
- try {
- return delegate.requestCommit(modification);
- } finally {
- final long endTime = System.nanoTime();
- final long runTime = endTime - startTime;
- requestCommitTimeTotal.addAndGet(runTime);
- }
- };
-
- @Override
- public boolean containsConfigurationPath(YangInstanceIdentifier path) {
- return delegate.containsConfigurationPath(path);
- }
-
- public Iterable<YangInstanceIdentifier> getStoredConfigurationPaths() {
- return delegate.getStoredConfigurationPaths();
- }
-
- public Iterable<YangInstanceIdentifier> getStoredOperationalPaths() {
- return delegate.getStoredOperationalPaths();
- }
-
- public boolean containsOperationalPath(YangInstanceIdentifier path) {
- return delegate.containsOperationalPath(path);
- }
-
- public final long getConfigurationReadCount() {
- return cfgReadCount.get();
- }
-
- public final long getOperationalReadCount() {
- return operReadCount.get();
- }
-
- public final long getRequestCommitCount() {
- return requestCommitCount.get();
- }
-
- public final double getConfigurationReadTotalTime() {
- return cfgReadTimeTotal.get() / 1000.0d;
- }
-
- public final double getOperationalReadTotalTime() {
- return operReadTimeTotal.get() / 1000.0d;
- }
-
- public final double getRequestCommitTotalTime() {
- return requestCommitTimeTotal.get() / 1000.0d;
- }
-
- public final double getConfigurationReadAverageTime() {
- long readCount = cfgReadCount.get();
- if(readCount == 0) {
- return 0;
- }
- return getConfigurationReadTotalTime() / readCount;
- }
-
- public final double getOperationalReadAverageTime() {
- long readCount = operReadCount.get();
- if(readCount == 0) {
- return 0;
- }
- return getOperationalReadTotalTime() / readCount;
- }
-
- public final double getRequestCommitAverageTime() {
- long count = requestCommitCount.get();
- if(count == 0) {
- return 0;
- }
- return getRequestCommitTotalTime() / count;
- }
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 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.sal.dom.broker.impl;
-
-import static com.google.common.base.Preconditions.checkState;
-import com.google.common.base.Predicate;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.concurrent.Future;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.controller.md.sal.common.api.data.DataReader;
-import org.opendaylight.controller.md.sal.common.impl.AbstractDataModification;
-import org.opendaylight.controller.md.sal.common.impl.util.AbstractLockableDelegator;
-import org.opendaylight.controller.sal.core.api.data.DataStore;
-import org.opendaylight.controller.sal.dom.broker.util.YangDataOperations;
-import org.opendaylight.controller.sal.dom.broker.util.YangSchemaUtils;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Deprecated
-public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataStore> implements DataStore, SchemaContextListener, AutoCloseable {
-
- private final static Logger LOG = LoggerFactory.getLogger(SchemaAwareDataStoreAdapter.class);
-
- private SchemaContext schema = null;
- private boolean validationEnabled = false;
- private final DataReader<YangInstanceIdentifier, CompositeNode> reader = new MergeFirstLevelReader();
-
- @Override
- public boolean containsConfigurationPath(final YangInstanceIdentifier path) {
- try {
- getDelegateReadLock().lock();
- return getDelegate().containsConfigurationPath(path);
-
- } finally {
- getDelegateReadLock().unlock();
- }
- }
-
- @Override
- public boolean containsOperationalPath(final YangInstanceIdentifier path) {
- try {
- getDelegateReadLock().lock();
- return getDelegate().containsOperationalPath(path);
-
- } finally {
- getDelegateReadLock().unlock();
- }
- }
-
- @Override
- public Iterable<YangInstanceIdentifier> getStoredConfigurationPaths() {
- try {
- getDelegateReadLock().lock();
- return getDelegate().getStoredConfigurationPaths();
-
- } finally {
- getDelegateReadLock().unlock();
- }
- }
-
- @Override
- public Iterable<YangInstanceIdentifier> getStoredOperationalPaths() {
- try {
- getDelegateReadLock().lock();
- return getDelegate().getStoredOperationalPaths();
-
- } finally {
- getDelegateReadLock().unlock();
- }
- }
-
- @Override
- public CompositeNode readConfigurationData(final YangInstanceIdentifier path) {
- return reader.readConfigurationData(path);
- }
-
- @Override
- public CompositeNode readOperationalData(final YangInstanceIdentifier path) {
- return reader.readOperationalData(path);
- }
-
- @Override
- public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<YangInstanceIdentifier, CompositeNode> requestCommit(
- final DataModification<YangInstanceIdentifier, CompositeNode> modification) {
- validateAgainstSchema(modification);
- NormalizedDataModification cleanedUp = prepareMergedTransaction(modification);
- cleanedUp.status = TransactionStatus.SUBMITED;
- return retrieveDelegate().requestCommit(cleanedUp);
- }
-
- public boolean isValidationEnabled() {
- return validationEnabled;
- }
-
- public void setValidationEnabled(final boolean validationEnabled) {
- this.validationEnabled = validationEnabled;
- }
-
- private void validateAgainstSchema(final DataModification<YangInstanceIdentifier, CompositeNode> modification) {
- if (!validationEnabled) {
- return;
- }
-
- if (schema == null) {
- LOG.warn("Validation not performed for {}. Reason: YANG Schema not present.", modification.getIdentifier());
- return;
- }
- }
-
- @Override
- protected void onDelegateChanged(final DataStore oldDelegate, final DataStore newDelegate) {
- // NOOP
- }
-
- @Override
- public void onGlobalContextUpdated(final SchemaContext context) {
- this.schema = context;
- }
-
- @Override
- public void close() throws Exception {
- this.schema = null;
- }
-
- protected CompositeNode mergeData(final YangInstanceIdentifier path, final CompositeNode stored, final CompositeNode modified,
- final boolean config) {
- // long startTime = System.nanoTime();
- try {
- DataSchemaNode node = schemaNodeFor(path);
- return YangDataOperations.merge(node, stored, modified, config);
- } finally {
- // System.out.println("Merge time: " + ((System.nanoTime() -
- // startTime) / 1000.0d));
- }
- }
-
- private DataSchemaNode schemaNodeFor(final YangInstanceIdentifier path) {
- checkState(schema != null, "YANG Schema is not available");
- return YangSchemaUtils.getSchemaNode(schema, path);
- }
-
- private NormalizedDataModification prepareMergedTransaction(
- final DataModification<YangInstanceIdentifier, CompositeNode> original) {
- NormalizedDataModification normalized = new NormalizedDataModification(original);
- LOG.trace("Transaction: {} Removed Configuration {}, Removed Operational {}", original.getIdentifier(),
- original.getRemovedConfigurationData(), original.getRemovedConfigurationData());
- LOG.trace("Transaction: {} Created Configuration {}, Created Operational {}", original.getIdentifier(),
- original.getCreatedConfigurationData().entrySet(), original.getCreatedOperationalData().entrySet());
- LOG.trace("Transaction: {} Updated Configuration {}, Updated Operational {}", original.getIdentifier(),
- original.getUpdatedConfigurationData().entrySet(), original.getUpdatedOperationalData().entrySet());
-
- for (YangInstanceIdentifier entry : original.getRemovedConfigurationData()) {
- normalized.deepRemoveConfigurationData(entry);
- }
- for (YangInstanceIdentifier entry : original.getRemovedOperationalData()) {
- normalized.deepRemoveOperationalData(entry);
- }
- for (Entry<YangInstanceIdentifier, CompositeNode> entry : original.getUpdatedConfigurationData().entrySet()) {
- normalized.putDeepConfigurationData(entry.getKey(), entry.getValue());
- }
- for (Entry<YangInstanceIdentifier, CompositeNode> entry : original.getUpdatedOperationalData().entrySet()) {
- normalized.putDeepOperationalData(entry.getKey(), entry.getValue());
- }
- return normalized;
- }
-
- private Iterable<YangInstanceIdentifier> getConfigurationSubpaths(final YangInstanceIdentifier entry) {
- // FIXME: This should be replaced by index
- Iterable<YangInstanceIdentifier> paths = getStoredConfigurationPaths();
-
- return getChildrenPaths(entry, paths);
-
- }
-
- public Iterable<YangInstanceIdentifier> getOperationalSubpaths(final YangInstanceIdentifier entry) {
- // FIXME: This should be indexed
- Iterable<YangInstanceIdentifier> paths = getStoredOperationalPaths();
-
- return getChildrenPaths(entry, paths);
- }
-
- private static final Iterable<YangInstanceIdentifier> getChildrenPaths(final YangInstanceIdentifier entry,
- final Iterable<YangInstanceIdentifier> paths) {
- ImmutableSet.Builder<YangInstanceIdentifier> children = ImmutableSet.builder();
- for (YangInstanceIdentifier potential : paths) {
- if (entry.contains(potential)) {
- children.add(entry);
- }
- }
- return children.build();
- }
-
- private final Comparator<Entry<YangInstanceIdentifier, CompositeNode>> preparationComparator = new Comparator<Entry<YangInstanceIdentifier, CompositeNode>>() {
- @Override
- public int compare(final Entry<YangInstanceIdentifier, CompositeNode> o1, final Entry<YangInstanceIdentifier, CompositeNode> o2) {
- YangInstanceIdentifier o1Key = o1.getKey();
- YangInstanceIdentifier o2Key = o2.getKey();
- return Integer.compare(Iterables.size(o1Key.getPathArguments()), Iterables.size(o2Key.getPathArguments()));
- }
- };
-
- private class MergeFirstLevelReader implements DataReader<YangInstanceIdentifier, CompositeNode> {
-
- @Override
- public CompositeNode readConfigurationData(final YangInstanceIdentifier path) {
- getDelegateReadLock().lock();
- try {
- if (Iterables.isEmpty(path.getPathArguments())) {
- return null;
- }
- QName qname = null;
- CompositeNode original = getDelegate().readConfigurationData(path);
- ArrayList<Node<?>> childNodes = new ArrayList<Node<?>>();
- if (original != null) {
- childNodes.addAll(original.getValue());
- qname = original.getNodeType();
- } else {
- qname = path.getLastPathArgument().getNodeType();
- }
-
- FluentIterable<YangInstanceIdentifier> directChildren = FluentIterable.from(getStoredConfigurationPaths())
- .filter(new Predicate<YangInstanceIdentifier>() {
- @Override
- public boolean apply(final YangInstanceIdentifier input) {
- if (path.contains(input)) {
- int nesting = Iterables.size(input.getPathArguments()) - Iterables.size(path.getPathArguments());
- if (nesting == 1) {
- return true;
- }
- }
- return false;
- }
- });
- for (YangInstanceIdentifier instanceIdentifier : directChildren) {
- childNodes.add(getDelegate().readConfigurationData(instanceIdentifier));
- }
- if (original == null && childNodes.isEmpty()) {
- return null;
- }
-
- return new CompositeNodeTOImpl(qname, null, childNodes);
- } finally {
- getDelegateReadLock().unlock();
- }
- }
-
- @Override
- public CompositeNode readOperationalData(final YangInstanceIdentifier path) {
- getDelegateReadLock().lock();
- try {
- if (Iterables.isEmpty(path.getPathArguments())) {
- return null;
- }
- QName qname = null;
- CompositeNode original = getDelegate().readOperationalData(path);
- ArrayList<Node<?>> childNodes = new ArrayList<Node<?>>();
- if (original != null) {
- childNodes.addAll(original.getValue());
- qname = original.getNodeType();
- } else {
- qname = path.getLastPathArgument().getNodeType();
- }
-
- FluentIterable<YangInstanceIdentifier> directChildren = FluentIterable.from(getStoredOperationalPaths())
- .filter(new Predicate<YangInstanceIdentifier>() {
- @Override
- public boolean apply(final YangInstanceIdentifier input) {
- if (path.contains(input)) {
- int nesting = Iterables.size(input.getPathArguments()) - Iterables.size(path.getPathArguments());
- if (nesting == 1) {
- return true;
- }
- }
- return false;
- }
- });
-
- for (YangInstanceIdentifier instanceIdentifier : directChildren) {
- childNodes.add(getDelegate().readOperationalData(instanceIdentifier));
- }
- if (original == null && childNodes.isEmpty()) {
- return null;
- }
-
- return new CompositeNodeTOImpl(qname, null, childNodes);
- } finally {
- getDelegateReadLock().unlock();
- }
- }
- }
-
- private class NormalizedDataModification extends AbstractDataModification<YangInstanceIdentifier, CompositeNode> {
-
- private final String CONFIGURATIONAL_DATA_STORE_MARKER = "configurational";
- private final String OPERATIONAL_DATA_STORE_MARKER = "operational";
- private final Object identifier;
- private TransactionStatus status;
-
- public NormalizedDataModification(final DataModification<YangInstanceIdentifier, CompositeNode> original) {
- super(getDelegate());
- identifier = original;
- status = TransactionStatus.NEW;
- }
-
- /**
- *
- * Ensures all subpaths are removed - this currently does slow lookup in
- * all keys.
- *
- * @param entry
- */
- public void deepRemoveOperationalData(final YangInstanceIdentifier entry) {
- Iterable<YangInstanceIdentifier> paths = getOperationalSubpaths(entry);
- removeOperationalData(entry);
- for (YangInstanceIdentifier potential : paths) {
- removeOperationalData(potential);
- }
- }
-
- public void deepRemoveConfigurationData(final YangInstanceIdentifier entry) {
- Iterable<YangInstanceIdentifier> paths = getConfigurationSubpaths(entry);
- removeConfigurationData(entry);
- for (YangInstanceIdentifier potential : paths) {
- removeConfigurationData(potential);
- }
- }
-
- public void putDeepConfigurationData(final YangInstanceIdentifier entryKey, final CompositeNode entryData) {
- this.putCompositeNodeData(entryKey, entryData, CONFIGURATIONAL_DATA_STORE_MARKER);
- }
-
- public void putDeepOperationalData(final YangInstanceIdentifier entryKey, final CompositeNode entryData) {
- this.putCompositeNodeData(entryKey, entryData, OPERATIONAL_DATA_STORE_MARKER);
- }
-
- @Override
- public Object getIdentifier() {
- return this.identifier;
- }
-
- @Override
- public TransactionStatus getStatus() {
- return status;
- }
-
- @Override
- public Future<RpcResult<TransactionStatus>> commit() {
- throw new UnsupportedOperationException("Commit should not be invoked on this");
- }
-
- @Override
- protected CompositeNode mergeConfigurationData(final YangInstanceIdentifier path, final CompositeNode stored,
- final CompositeNode modified) {
- return mergeData(path, stored, modified, true);
- }
-
- @Override
- protected CompositeNode mergeOperationalData(final YangInstanceIdentifier path, final CompositeNode stored,
- final CompositeNode modified) {
- return mergeData(path, stored, modified, false);
- }
-
- private void putData(final YangInstanceIdentifier entryKey, final CompositeNode entryData, final String dataStoreIdentifier) {
- if (dataStoreIdentifier != null && entryKey != null && entryData != null) {
- switch (dataStoreIdentifier) {
- case (CONFIGURATIONAL_DATA_STORE_MARKER):
- this.putConfigurationData(entryKey, entryData);
- break;
- case (OPERATIONAL_DATA_STORE_MARKER):
- this.putOperationalData(entryKey, entryData);
- break;
-
- default:
- LOG.error(dataStoreIdentifier + " is NOT valid DataStore switch marker");
- throw new RuntimeException(dataStoreIdentifier + " is NOT valid DataStore switch marker");
- }
- }
- }
-
- private void putCompositeNodeData(final YangInstanceIdentifier entryKey, final CompositeNode entryData,
- final String dataStoreIdentifier) {
- this.putData(entryKey, entryData, dataStoreIdentifier);
-
- for (Node<?> child : entryData.getValue()) {
- YangInstanceIdentifier subEntryId = YangInstanceIdentifier.builder(entryKey).node(child.getNodeType())
- .toInstance();
- if (child instanceof CompositeNode) {
- DataSchemaNode subSchema = schemaNodeFor(subEntryId);
- CompositeNode compNode = (CompositeNode) child;
- YangInstanceIdentifier instanceId = null;
-
- if (subSchema instanceof ListSchemaNode) {
- ListSchemaNode listSubSchema = (ListSchemaNode) subSchema;
- Map<QName, Object> mapOfSubValues = this.getValuesFromListSchema(listSubSchema,
- (CompositeNode) child);
- if (mapOfSubValues != null) {
- instanceId = YangInstanceIdentifier.builder(entryKey)
- .nodeWithKey(listSubSchema.getQName(), mapOfSubValues).toInstance();
- }
- } else if (subSchema instanceof ContainerSchemaNode) {
- ContainerSchemaNode containerSchema = (ContainerSchemaNode) subSchema;
- instanceId = YangInstanceIdentifier.builder(entryKey).node(subSchema.getQName()).toInstance();
- }
- if (instanceId != null) {
- this.putCompositeNodeData(instanceId, compNode, dataStoreIdentifier);
- }
- }
- }
- }
-
- private Map<QName, Object> getValuesFromListSchema(final ListSchemaNode listSchema, final CompositeNode entryData) {
- List<QName> keyDef = listSchema.getKeyDefinition();
- if (keyDef != null && !keyDef.isEmpty()) {
- Map<QName, Object> map = new HashMap<QName, Object>();
- for (QName key : keyDef) {
- List<Node<?>> data = entryData.get(key);
- if (data != null && !data.isEmpty()) {
- for (Node<?> nodeData : data) {
- if (nodeData instanceof SimpleNode<?>) {
- map.put(key, data.get(0).getValue());
- }
- }
- }
- }
- return map;
- }
- return 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.sal.dom.broker.impl;
-
-/**
- * @deprecated Use org.opendaylight.yangtools.yang.model.api.SchemaContextProvider instead
- */
-@Deprecated
-public interface SchemaContextProvider extends org.opendaylight.yangtools.yang.model.api.SchemaContextProvider{
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 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.sal.dom.broker.util;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Iterables;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-
-@Deprecated
-public class YangDataOperations {
-
- public static CompositeNode merge(final DataSchemaNode schema,
- final CompositeNode stored, final CompositeNode modified,
- final boolean config) {
- if (stored == null) {
- return modified;
- }
-
- Preconditions.checkArgument(schema instanceof ListSchemaNode
- || schema instanceof ContainerSchemaNode,
- "Supplied node is not data node container.");
-
- return YangDataOperations.mergeContainer((DataNodeContainer) schema,
- stored, modified, config);
- }
-
- private static Iterable<? extends Node<?>> _mergeMultiple(
- final LeafSchemaNode node, final List<Node<?>> original,
- final List<Node<?>> modified, final boolean configurational) {
- checkArgument(original.size() == 1);
- checkArgument(modified.size() == 1);
-
- return modified;
- }
-
- private static Iterable<? extends Node<?>> _mergeMultiple(
- final LeafListSchemaNode node, final List<Node<?>> original,
- final List<Node<?>> modified, final boolean configurational) {
- return modified;
- }
-
- private static Iterable<? extends Node<?>> _mergeMultiple(
- final ContainerSchemaNode node, final List<Node<?>> original,
- final List<Node<?>> modified, final boolean configurational) {
- checkArgument(original.size() == 1);
- checkArgument(modified.size() == 1);
- return Collections.singletonList(merge(node,
- (CompositeNode) original.get(0),
- (CompositeNode) modified.get(0), configurational));
- }
-
- private static Iterable<? extends Node<?>> _mergeMultiple(
- final ListSchemaNode node, final List<Node<?>> original,
- final List<Node<?>> modified, final boolean configurational) {
-
- if (node.getKeyDefinition() == null
- || node.getKeyDefinition().isEmpty()) {
- return modified;
- }
- @SuppressWarnings({ "unchecked", "rawtypes" })
- final Map<Map<QName, Object>, CompositeNode> originalMap = YangDataUtils
- .toIndexMap((List) original, node.getKeyDefinition());
- @SuppressWarnings({ "unchecked", "rawtypes" })
- final Map<Map<QName, Object>, CompositeNode> modifiedMap = YangDataUtils
- .toIndexMap((List) modified, node.getKeyDefinition());
-
- final List<Node<?>> mergedNodes = new ArrayList<Node<?>>(
- original.size() + modified.size());
- for (final Map.Entry<Map<QName, Object>, CompositeNode> entry : modifiedMap
- .entrySet()) {
- final CompositeNode originalEntry = originalMap.get(entry.getKey());
- if (originalEntry != null) {
- originalMap.remove(entry.getKey());
- mergedNodes.add(merge(node, originalEntry, entry.getValue(),
- configurational));
- } else {
- mergedNodes.add(entry.getValue());
- }
- }
- mergedNodes.addAll(originalMap.values());
- return mergedNodes;
- }
-
- private static Iterable<? extends Node<?>> mergeMultiple(
- final DataSchemaNode node, final List<Node<?>> original,
- final List<Node<?>> modified, final boolean configurational) {
- if (node instanceof ContainerSchemaNode) {
- return _mergeMultiple((ContainerSchemaNode) node, original,
- modified, configurational);
- } else if (node instanceof LeafListSchemaNode) {
- return _mergeMultiple((LeafListSchemaNode) node, original,
- modified, configurational);
- } else if (node instanceof LeafSchemaNode) {
- return _mergeMultiple((LeafSchemaNode) node, original, modified,
- configurational);
- } else if (node instanceof ListSchemaNode) {
- return _mergeMultiple((ListSchemaNode) node, original, modified,
- configurational);
- } else {
- throw new IllegalArgumentException("Unhandled parameter types: "
- + Arrays.<Object> asList(node, original, modified,
- configurational).toString());
- }
- }
-
- private static CompositeNode mergeContainer(final DataNodeContainer schema,
- final CompositeNode stored, final CompositeNode modified,
- final boolean config) {
- if (stored == null) {
- return modified;
- }
- Preconditions.checkNotNull(stored);
- Preconditions.checkNotNull(modified);
- Preconditions.checkArgument(Objects.equals(stored.getNodeType(),
- modified.getNodeType()));
-
- final List<Node<?>> mergedChildNodes = new ArrayList<Node<?>>(stored
- .getValue().size() + modified.getValue().size());
- final Set<QName> toProcess = new HashSet<QName>(stored.keySet());
- toProcess.addAll(modified.keySet());
-
- for (QName qname : toProcess) {
- final DataSchemaNode schemaChild = schema.getDataChildByName(qname);
- final List<Node<?>> storedChildren = stored.get(qname);
- final List<Node<?>> modifiedChildren = modified.get(qname);
-
- if (modifiedChildren != null && !modifiedChildren.isEmpty()) {
- if (storedChildren == null || storedChildren.isEmpty()
- || schemaChild == null) {
- mergedChildNodes.addAll(modifiedChildren);
- } else {
- final Iterable<? extends Node<?>> _mergeMultiple = mergeMultiple(
- schemaChild, storedChildren, modifiedChildren,
- config);
- Iterables.addAll(mergedChildNodes, _mergeMultiple);
- }
- } else if (storedChildren != null && !storedChildren.isEmpty()) {
- mergedChildNodes.addAll(storedChildren);
- }
- }
- return new CompositeNodeTOImpl(stored.getNodeType(), null,
- mergedChildNodes);
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 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.sal.dom.broker.util;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-
-@Deprecated
-public final class YangDataUtils {
-
- private YangDataUtils() {
- throw new UnsupportedOperationException("Utility class");
- }
-
- public static Map<Map<QName,Object>,CompositeNode> toIndexMap(final List<CompositeNode> nodes,final List<QName> keys) {
- ConcurrentHashMap<Map<QName,Object>,CompositeNode> ret = new ConcurrentHashMap<>();
- for(CompositeNode node : nodes) {
- Map<QName, Object> key = getKeyMap(node,keys);
- ret.put(key, node);
- }
- return ret;
- }
-
- public static Map<QName,Object> getKeyMap(final CompositeNode node, final List<QName> keys) {
- Map<QName,Object> map = new HashMap<>();
- for(QName key : keys) {
- SimpleNode<?> keyNode = node.getFirstSimpleByName(QName.create(node.getNodeType(), key.getLocalName()));
- checkArgument(keyNode != null,"Node must contains all keys.");
- Object value = keyNode.getValue();
- map.put(key, value);
-
- }
- return map;
- }
-}
getSchemaServiceDependency().registerSchemaContextListener(xsqlAdapter);
xsqlAdapter.setDataBroker(getAsyncDataBrokerDependency());
XSQLProvider p = new XSQLProvider();
- p.buildXSQL(getDataBrokerDependency());
+ //p.buildXSQL(getDataBrokerDependency());
return p;
}
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
final NetconfSessionCapabilities netconfSessionPreferences, final RpcImplementation deviceRpc) {
// TODO move SchemaAwareRpcBroker from sal-broker-impl, now we have depend on the whole sal-broker-impl
- final RpcProvisionRegistry rpcRegistry = new SchemaAwareRpcBroker(id.getPath().toString(), new org.opendaylight.controller.sal.dom.broker.impl.SchemaContextProvider() {
+ final RpcProvisionRegistry rpcRegistry = new SchemaAwareRpcBroker(id.getPath().toString(), new SchemaContextProvider() {
@Override
public SchemaContext getSchemaContext() {
return schemaContext;
import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
import org.opendaylight.yangtools.concepts.ObjectRegistration;
-import org.opendaylight.yangtools.yang.binding.RpcService;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.slf4j.Logger;
return Collections.emptySet();
}
- @Override
- public Collection<? extends RpcService> getImplementations() {
- return Collections.emptySet();
- }
-
- @Override
- public Collection<? extends BindingAwareProvider.ProviderFunctionality> getFunctionality() {
- return Collections.emptySet();
- }
-
@Override
public void onSessionInitiated(final BindingAwareBroker.ProviderContext session) {
logger.debug("{}: Session with sal established {}", id, session);
datastoreAdapter = new NetconfDeviceDatastoreAdapter(id, dataBroker);
}
- @Override
- public void onSessionInitialized(final BindingAwareBroker.ConsumerContext session) {}
-
public void close() throws Exception {
mountInstance.close();
datastoreAdapter.close();
if (optionalDatastoreData.isPresent() && payload.equals(optionalDatastoreData.get())) {
String errMsg = "Post Configuration via Restconf was not executed because data already exists";
LOG.trace(errMsg + ":{}", path);
+ rWTransaction.cancel();
throw new RestconfDocumentedException("Data already exists for path: " + path, ErrorType.PROTOCOL,
ErrorTag.DATA_EXISTS);
}
try {
currentOp = currentOp.getChild(currentArg);
} catch (DataNormalizationException e) {
+ rwTx.cancel();
throw new IllegalArgumentException(
String.format("Invalid child encountered in path %s", normalizedPath), e);
}
exists = future.checkedGet();
} catch (ReadFailedException e) {
LOG.error("Failed to read pre-existing data from store {} path {}", store, currentPath, e);
+ rwTx.cancel();
throw new IllegalStateException("Failed to read pre-existing data", e);
}
final DataNodeContainer parentSchema = (DataNodeContainer) incompleteInstIdWithData.getSchemaNode();
DOMMountPoint mountPoint = incompleteInstIdWithData.getMountPoint();
final Module module = findModule(mountPoint, payload);
- if (module == null) {
- throw new RestconfDocumentedException("Module was not found for \"" + payloadNS + "\"",
- ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT);
- }
String payloadName = this.getName(payload);
final DataSchemaNode schemaNode = ControllerContext.findInstanceDataChildByNameAndNamespace(
}
final Module module = this.findModule(null, payload);
- if (module == null) {
- throw new RestconfDocumentedException(
- "Data has bad format. Root element node has incorrect namespace (XML format) or module name(JSON format)",
- ErrorType.PROTOCOL, ErrorTag.UNKNOWN_NAMESPACE);
- }
String payloadName = this.getName(payload);
final DataSchemaNode schemaNode = ControllerContext.findInstanceDataChildByNameAndNamespace(module,
}
private Module findModule(final DOMMountPoint mountPoint, final Node<?> data) {
+ Module module = null;
if (data instanceof NodeWrapper) {
- return findModule(mountPoint, (NodeWrapper<?>) data);
+ module = findModule(mountPoint, (NodeWrapper<?>) data);
} else if (data != null) {
URI namespace = data.getNodeType().getNamespace();
if (mountPoint != null) {
- return this.controllerContext.findModuleByNamespace(mountPoint, namespace);
+ module = this.controllerContext.findModuleByNamespace(mountPoint, namespace);
} else {
- return this.controllerContext.findModuleByNamespace(namespace);
+ module = this.controllerContext.findModuleByNamespace(namespace);
}
- } else {
- throw new IllegalArgumentException("Unhandled parameter types: "
- + Arrays.<Object> asList(mountPoint, data).toString());
}
+ if (module != null) {
+ return module;
+ }
+ throw new RestconfDocumentedException(
+ "Data has bad format. Root element node has incorrect namespace (XML format) or module name(JSON format)",
+ ErrorType.PROTOCOL, ErrorTag.UNKNOWN_NAMESPACE);
}
private Module findModule(final DOMMountPoint mountPoint, final NodeWrapper<?> data) {
.put(RpcConsumerRegistry.class,servicesFactory.getRpcConsumerRegistry() ).build();
}
- public ProviderContext registerProvider(BindingAwareProvider provider, BundleContext ctx) {
+ public ProviderContext registerProvider(BindingAwareProvider provider) {
throw new UnsupportedOperationException();
}
@Override
//TODO decide if serviceFactory should close clientContext or it has to be closed by consumer
}
@Override
- public ConsumerContext registerConsumer(BindingAwareConsumer consumer, BundleContext ctx) {
+ public ConsumerContext registerConsumer(BindingAwareConsumer consumer) {
checkState(supportedConsumerServices != null, "Broker is not initialized.");
return BindingContextUtils.createConsumerContextAndInitialize(consumer, supportedConsumerServices);
}
+ @Override
+ public ConsumerContext registerConsumer(BindingAwareConsumer consumer,
+ BundleContext ctx) {
+ return registerConsumer(consumer);
+ }
+
+ @Override
+ public ProviderContext registerProvider(BindingAwareProvider provider,
+ BundleContext ctx) {
+ return registerProvider(provider);
+ }
+
}
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.Sets;
+import java.util.Collection;
+import java.util.Collections;
import java.util.HashSet;
-import java.util.List;
import java.util.Map;
import java.util.Set;
import org.opendaylight.controller.config.api.LookupRegistry;
private final Set<Capability> capabilities;
private final TransactionProvider transactionProvider;
- public NetconfOperationServiceImpl(YangStoreService yangStoreService, ConfigRegistryJMXClient jmxClient,
- String netconfSessionIdForReporting) throws YangStoreException {
+ public NetconfOperationServiceImpl(final YangStoreService yangStoreService, final ConfigRegistryJMXClient jmxClient,
+ final String netconfSessionIdForReporting) throws YangStoreException {
yangStoreSnapshot = yangStoreService.getYangStoreSnapshot();
checkConsistencyBetweenYangStoreAndConfig(jmxClient, yangStoreSnapshot);
@VisibleForTesting
- static void checkConsistencyBetweenYangStoreAndConfig(LookupRegistry jmxClient, YangStoreSnapshot yangStoreSnapshot) {
+ static void checkConsistencyBetweenYangStoreAndConfig(final LookupRegistry jmxClient, final YangStoreSnapshot yangStoreSnapshot) {
Set<String> missingModulesFromConfig = Sets.newHashSet();
Set<String> modulesSeenByConfig = jmxClient.getAvailableModuleFactoryQNames();
return operationProvider.getOperations();
}
- private static Set<Capability> setupCapabilities(YangStoreSnapshot yangStoreSnapshot) {
+ private static Set<Capability> setupCapabilities(final YangStoreSnapshot yangStoreSnapshot) {
Set<Capability> capabilities = new HashSet<>();
// [RFC6241] 8.3. Candidate Configuration Capability
capabilities.add(new BasicCapability("urn:ietf:params:netconf:capability:candidate:1.0"));
private final String capability;
- private BasicCapability(String capability) {
+ private BasicCapability(final String capability) {
this.capability = capability;
}
}
@Override
- public Optional<List<String>> getLocation() {
- return Optional.absent();
+ public Collection<String> getLocation() {
+ return Collections.emptyList();
}
@Override
private final String moduleName;
private final String moduleNamespace;
- public YangStoreCapability(Module module, String moduleContent) {
+ public YangStoreCapability(final Module module, final String moduleContent) {
super(toCapabilityURI(module));
this.content = moduleContent;
this.moduleName = module.getName();
return Optional.of(content);
}
- private static String toCapabilityURI(Module module) {
+ private static String toCapabilityURI(final Module module) {
return String.valueOf(module.getNamespace()) + "?module="
+ module.getName() + "&revision=" + Util.writeDate(module.getRevision());
}
*/
private synchronized EditAndCommitResponse pushConfigWithConflictingVersionRetries(ConfigSnapshotHolder configSnapshotHolder) throws NetconfDocumentedException {
ConflictingVersionException lastException;
- Stopwatch stopwatch = new Stopwatch().start();
+ Stopwatch stopwatch = new Stopwatch();
do {
String idForReporting = configSnapshotHolder.toString();
SortedSet<String> expectedCapabilities = checkNotNull(configSnapshotHolder.getCapabilities(),
"Expected capabilities must not be null - %s, check %s", idForReporting,
configSnapshotHolder.getClass().getName());
try (NetconfOperationService operationService = getOperationServiceWithRetries(expectedCapabilities, idForReporting)) {
+ if(!stopwatch.isRunning()) {
+ stopwatch.start();
+ }
return pushConfig(configSnapshotHolder, operationService);
} catch (ConflictingVersionException e) {
lastException = e;
- LOG.debug("Conflicting version detected, will retry after timeout");
+ LOG.info("Conflicting version detected, will retry after timeout");
sleep();
}
} while (stopwatch.elapsed(TimeUnit.MILLISECONDS) < conflictingVersionTimeoutMillis);
public static final String MAX_WAIT_FOR_CAPABILITIES_MILLIS_PROPERTY = "maxWaitForCapabilitiesMillis";
private static final long MAX_WAIT_FOR_CAPABILITIES_MILLIS_DEFAULT = TimeUnit.MINUTES.toMillis(2);
public static final String CONFLICTING_VERSION_TIMEOUT_MILLIS_PROPERTY = "conflictingVersionTimeoutMillis";
- private static final long CONFLICTING_VERSION_TIMEOUT_MILLIS_DEFAULT = TimeUnit.SECONDS.toMillis(30);
+ private static final long CONFLICTING_VERSION_TIMEOUT_MILLIS_DEFAULT = TimeUnit.MINUTES.toMillis(1);
public static final String NETCONF_CONFIG_PERSISTER = "netconf.config.persister";
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
- <Import-Package>com.google.common.collect,
- org.opendaylight.yangtools.yang.binding,
- org.opendaylight.yangtools.yang.common,
- org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004,</Import-Package>
<Export-Package>org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210,</Export-Package>
</instructions>
</configuration>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
- <Import-Package>com.google.common.collect,
- org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924,
- org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924,
- org.opendaylight.yangtools.yang.binding,
- org.opendaylight.yangtools.yang.common,</Import-Package>
<Export-Package>org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.*</Export-Package>
</instructions>
</configuration>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
- <Private-Package></Private-Package>
<Export-Package>org.opendaylight.controller.netconf.api,
org.opendaylight.controller.netconf.api.jmx,
org.opendaylight.controller.netconf.api.xml,
<configuration>
<instructions>
<Export-Package>org.opendaylight.controller.netconf.client.*,</Export-Package>
- <Import-Package>com.google.common.base,
- com.google.common.collect,
- io.netty.channel,
- io.netty.channel.socket,
- io.netty.util,
- io.netty.util.concurrent,
- javax.annotation,
- javax.net.ssl,
- javax.xml.namespace,
- javax.xml.parsers,
- javax.xml.xpath,
- org.opendaylight.controller.netconf.api,
- org.opendaylight.controller.netconf.util.*,
- org.opendaylight.controller.netconf.nettyutil.*,
- org.opendaylight.protocol.framework,
- org.openexi.*,
- org.slf4j,
- org.w3c.dom,
- org.xml.sax,
- io.netty.handler.codec</Import-Package>
</instructions>
</configuration>
</plugin>
<configuration>
<instructions>
<Bundle-Activator>org.opendaylight.controller.netconf.impl.osgi.NetconfImplActivator</Bundle-Activator>
- <Import-Package>com.google.common.base,
- com.google.common.collect,
- io.netty.channel,
- io.netty.channel.socket,
- io.netty.util,
- io.netty.util.concurrent,
- io.netty.buffer,
- io.netty.handler.codec,
- io.netty.channel.nio,
- io.netty.channel.local,
- javax.annotation,
- javax.management,
- javax.net.ssl,
- javax.xml.namespace,
- javax.xml.xpath,
- org.opendaylight.controller.netconf.api,
- org.opendaylight.controller.netconf.api.jmx,
- org.opendaylight.controller.netconf.mapping.api,
- org.opendaylight.controller.netconf.util.*,
- org.opendaylight.protocol.framework,
- org.osgi.framework,
- org.osgi.util.tracker,
- org.slf4j,
- org.w3c.dom,
- org.xml.sax,
- io.netty.util.internal,
- org.opendaylight.controller.netconf.api.monitoring,
- org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924,
- org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924,
- org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004,
- org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state,
- org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.sessions,
- org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas,
- org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210,
- org.opendaylight.yangtools.yang.binding,
- org.openexi.*,
- org.opendaylight.controller.netconf.nettyutil.*</Import-Package>
</instructions>
</configuration>
</plugin>
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.Collections2;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableList.Builder;
import io.netty.util.internal.ConcurrentSet;
-import java.util.Collections;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.Nonnull;
import org.slf4j.LoggerFactory;
public class NetconfMonitoringServiceImpl implements NetconfMonitoringService, SessionMonitoringService {
-
+ private static final Schema.Location NETCONF_LOCATION = new Schema.Location(Schema.Location.Enumeration.NETCONF);
+ private static final List<Schema.Location> NETCONF_LOCATIONS = ImmutableList.of(NETCONF_LOCATION);
private static final Logger LOG = LoggerFactory.getLogger(NetconfMonitoringServiceImpl.class);
+ private static final Function<NetconfManagementSession, Session> SESSION_FUNCTION = new Function<NetconfManagementSession, Session>() {
+ @Override
+ public Session apply(@Nonnull final NetconfManagementSession input) {
+ return input.toManagementSession();
+ }
+ };
private final Set<NetconfManagementSession> sessions = new ConcurrentSet<>();
private final NetconfOperationProvider netconfOperationProvider;
- public NetconfMonitoringServiceImpl(NetconfOperationProvider netconfOperationProvider) {
+ public NetconfMonitoringServiceImpl(final NetconfOperationProvider netconfOperationProvider) {
this.netconfOperationProvider = netconfOperationProvider;
}
@Override
- public void onSessionUp(NetconfManagementSession session) {
+ public void onSessionUp(final NetconfManagementSession session) {
LOG.debug("Session {} up", session);
Preconditions.checkState(!sessions.contains(session), "Session %s was already added", session);
sessions.add(session);
}
@Override
- public void onSessionDown(NetconfManagementSession session) {
+ public void onSessionDown(final NetconfManagementSession session) {
LOG.debug("Session {} down", session);
Preconditions.checkState(sessions.contains(session), "Session %s not present", session);
sessions.remove(session);
@Override
public Sessions getSessions() {
- return new SessionsBuilder().setSession(transformSessions(sessions)).build();
+ return new SessionsBuilder().setSession(ImmutableList.copyOf(Collections2.transform(sessions, SESSION_FUNCTION))).build();
}
@Override
}
}
- private Schemas transformSchemas(Set<NetconfOperationService> services) {
- Set<Capability> caps = Sets.newHashSet();
-
- List<Schema> schemas = Lists.newArrayList();
-
-
+ private static Schemas transformSchemas(final Set<NetconfOperationService> services) {
+ // FIXME: Capability implementations do not have hashcode/equals!
+ final Set<Capability> caps = new HashSet<>();
for (NetconfOperationService netconfOperationService : services) {
// TODO check for duplicates ? move capability merging to snapshot
// Split capabilities from operations first and delete this duplicate code
caps.addAll(netconfOperationService.getCapabilities());
}
+ final List<Schema> schemas = new ArrayList<>(caps.size());
for (Capability cap : caps) {
- SchemaBuilder builder = new SchemaBuilder();
-
- if (cap.getCapabilitySchema().isPresent() == false) {
- continue;
- }
+ if (cap.getCapabilitySchema().isPresent()) {
+ SchemaBuilder builder = new SchemaBuilder();
+ Preconditions.checkState(cap.getModuleNamespace().isPresent());
+ builder.setNamespace(new Uri(cap.getModuleNamespace().get()));
- Preconditions.checkState(cap.getModuleNamespace().isPresent());
- builder.setNamespace(new Uri(cap.getModuleNamespace().get()));
+ Preconditions.checkState(cap.getRevision().isPresent());
+ String version = cap.getRevision().get();
+ builder.setVersion(version);
- Preconditions.checkState(cap.getRevision().isPresent());
- String version = cap.getRevision().get();
- builder.setVersion(version);
+ Preconditions.checkState(cap.getModuleName().isPresent());
+ String identifier = cap.getModuleName().get();
+ builder.setIdentifier(identifier);
- Preconditions.checkState(cap.getModuleName().isPresent());
- String identifier = cap.getModuleName().get();
- builder.setIdentifier(identifier);
+ builder.setFormat(Yang.class);
- builder.setFormat(Yang.class);
+ builder.setLocation(transformLocations(cap.getLocation()));
- builder.setLocation(transformLocations(cap.getLocation().or(Collections.<String>emptyList())));
+ builder.setKey(new SchemaKey(Yang.class, identifier, version));
- builder.setKey(new SchemaKey(Yang.class, identifier, version));
-
- schemas.add(builder.build());
+ schemas.add(builder.build());
+ }
}
return new SchemasBuilder().setSchema(schemas).build();
}
- private List<Schema.Location> transformLocations(List<String> locations) {
- List<Schema.Location> monitoringLocations = Lists.newArrayList();
- monitoringLocations.add(new Schema.Location(Schema.Location.Enumeration.NETCONF));
+ private static List<Schema.Location> transformLocations(final Collection<String> locations) {
+ if (locations.isEmpty()) {
+ return NETCONF_LOCATIONS;
+ }
+
+ final Builder<Schema.Location> b = ImmutableList.builder();
+ b.add(NETCONF_LOCATION);
for (String location : locations) {
- monitoringLocations.add(new Schema.Location(new Uri(location)));
+ b.add(new Schema.Location(new Uri(location)));
}
- return monitoringLocations;
- }
-
- private List<Session> transformSessions(Set<NetconfManagementSession> sessions) {
- return Lists.newArrayList(Collections2.transform(sessions, new Function<NetconfManagementSession, Session>() {
- @Override
- public Session apply(@Nonnull NetconfManagementSession input) {
- return input.toManagementSession();
- }
- }));
+ return b.build();
}
}
Optional<String> optRev = Optional.of("rev");
doReturn(optRev).when(cap).getRevision();
doReturn(Optional.of("modName")).when(cap).getModuleName();
- doReturn(Optional.of(Lists.newArrayList("loc"))).when(cap).getLocation();
+ doReturn(Lists.newArrayList("loc")).when(cap).getLocation();
doNothing().when(snapshot).close();
assertNotNull(service.getSchemas());
}
@Override
- public Optional<List<String>> getLocation() {
- return Optional.absent();
+ public List<String> getLocation() {
+ return Collections.emptyList();
}
}
}
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
- <Private-Package></Private-Package>
- <Import-Package>com.google.common.base,
- org.opendaylight.controller.netconf.api,
- org.w3c.dom</Import-Package>
<Export-Package>org.opendaylight.controller.netconf.mapping.api,</Export-Package>
</instructions>
</configuration>
package org.opendaylight.controller.netconf.mapping.api;
import com.google.common.base.Optional;
-import java.util.List;
+import java.util.Collection;
/**
* Contains capability URI announced by server hello message and optionally its
public Optional<String> getCapabilitySchema();
- public Optional<List<String>> getLocation();
+ public Collection<String> getLocation();
}
<configuration>
<instructions>
<Bundle-Activator>org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringActivator</Bundle-Activator>
- <Import-Package>com.google.common.base,
- com.google.common.collect,
- com.google.common.io,
- org.opendaylight.controller.netconf.api,
- org.opendaylight.controller.netconf.mapping.api,
- org.opendaylight.controller.netconf.util.mapping,
- org.opendaylight.controller.netconf.util.exception,
- org.osgi.framework,
- org.slf4j,
- org.w3c.dom,
- javax.xml.bind,
- javax.xml.bind.annotation,
- javax.xml.transform,
- javax.xml.transform.dom,
- org.opendaylight.controller.netconf.util.xml,
- io.netty.util.internal,
- javax.annotation,
- org.opendaylight.controller.netconf.api.monitoring,
- org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924,
- org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924,
- org.osgi.util.tracker,
- org.opendaylight.yangtools.yang.common,
- org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state,
- org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.sessions,
- org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004,
- org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas,
- org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210,
- org.opendaylight.yangtools.yang.binding,</Import-Package>
</instructions>
</configuration>
</plugin>
import com.google.common.base.Optional;
import com.google.common.collect.Sets;
-import java.util.List;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Set;
import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
import org.opendaylight.controller.netconf.mapping.api.Capability;
}
@Override
- public Optional<List<String>> getLocation() {
- return Optional.absent();
+ public Collection<String> getLocation() {
+ return Collections.emptyList();
}
});
private final NetconfMonitoringService monitor;
- public NetconfMonitoringOperationService(NetconfMonitoringService monitor) {
+ public NetconfMonitoringOperationService(final NetconfMonitoringService monitor) {
this.monitor = monitor;
}
import static org.mockito.Mockito.mock;
import com.google.common.base.Optional;
+import java.util.Collections;
import org.junit.Test;
import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
import org.opendaylight.controller.netconf.monitoring.MonitoringConstants;
assertEquals(1, service.getNetconfOperations().size());
- assertEquals(Optional.absent(), service.getCapabilities().iterator().next().getCapabilitySchema());
- assertEquals(Optional.absent(), service.getCapabilities().iterator().next().getLocation());
+ assertEquals(Optional.<String>absent(), service.getCapabilities().iterator().next().getCapabilitySchema());
+ assertEquals(Collections.<String>emptyList(), service.getCapabilities().iterator().next().getLocation());
assertEquals(Optional.of(MonitoringConstants.MODULE_REVISION), service.getCapabilities().iterator().next().getRevision());
assertEquals(Optional.of(MonitoringConstants.MODULE_NAME), service.getCapabilities().iterator().next().getModuleName());
assertEquals(Optional.of(MonitoringConstants.NAMESPACE), service.getCapabilities().iterator().next().getModuleNamespace());
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
- <Import-Package>org.apache.sshd.*, com.google.common.base, com.google.common.collect, io.netty.buffer,
- io.netty.channel, io.netty.channel.socket, io.netty.handler.codec, io.netty.handler.ssl, io.netty.util,
- io.netty.util.concurrent, javax.xml.transform, javax.xml.transform.dom, javax.xml.transform.sax,
- javax.xml.transform.stream, org.opendaylight.controller.netconf.api,
- org.opendaylight.controller.netconf.util.messages, org.opendaylight.controller.netconf.util.xml,
- org.opendaylight.protocol.framework, org.openexi.proc, org.openexi.proc.common, org.openexi.proc.grammars,
- org.openexi.sax, org.openexi.schema, org.slf4j, org.w3c.dom, org.xml.sax</Import-Package>
<Export-Package>org.opendaylight.controller.netconf.nettyutil,
org.opendaylight.controller.netconf.nettyutil.handler,
org.opendaylight.controller.netconf.nettyutil.handler.exi,
<configuration>
<instructions>
<Bundle-Activator>org.opendaylight.controller.netconf.ssh.osgi.NetconfSSHActivator</Bundle-Activator>
- <Import-Package>*</Import-Package>
</instructions>
</configuration>
</plugin>
<configuration>
<instructions>
<Bundle-Activator>org.opendaylight.controller.netconf.tcp.osgi.NetconfTCPActivator</Bundle-Activator>
- <Import-Package>com.google.common.base, io.netty.bootstrap, io.netty.channel, io.netty.channel.local,
- io.netty.channel.nio, io.netty.channel.socket, io.netty.channel.socket.nio, io.netty.handler.logging,
- io.netty.util.concurrent, org.opendaylight.controller.netconf.util.osgi, org.osgi.framework, org.slf4j</Import-Package>
</instructions>
</configuration>
</plugin>
package org.opendaylight.controller.netconf.test.tool;
import com.google.common.base.Optional;
+import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
}
@Override
- public Optional<List<String>> getLocation() {
- return Optional.absent();
+ public List<String> getLocation() {
+ return Collections.emptyList();
}
}
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
- <Import-Package>com.google.common.base, com.google.common.collect, io.netty.channel,
- io.netty.util.concurrent, javax.annotation, javax.xml.namespace, javax.xml.parsers, javax.xml.transform,
- javax.xml.transform.dom, javax.xml.transform.stream, javax.xml.validation, javax.xml.xpath,
- org.opendaylight.controller.netconf.api, org.opendaylight.controller.netconf.api.xml,
- org.opendaylight.controller.netconf.mapping.api,
- org.osgi.framework, org.slf4j, org.w3c.dom, org.xml.sax,io.netty.channel.local</Import-Package>
<Export-Package>org.opendaylight.controller.netconf.util.*</Export-Package>
</instructions>
</configuration>