<artifactId>jersey-core</artifactId>
<version>${jersey.version}</version>
</dependency>
- <dependency>
- <groupId>javax.ws.rs</groupId>
- <artifactId>jsr311-api</artifactId>
- <version>${jsr311.api.version}</version>
- </dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<artifactId>netty-transport</artifactId>
<version>${netty.version}</version>
</dependency>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>jsr311-api</artifactId>
+ <version>${jsr311.api.version}</version>
+ </dependency>
<dependency>
<groupId>orbit</groupId>
<artifactId>javax.activation</artifactId>
File[] sourceFiles = sourceDirectory.listFiles();
for (File sourceFile: sourceFiles) {
- if(sourceFile.getName().endsWith("Module.java") || sourceFile.getName().endsWith("ModuleFactory.java")) {
- File stubFile = new File(sourceFile.getPath().replace(".java", "Stub.txt"));
- if (stubFile.exists()) {
- try {
- rewrite(sourceFile, FileUtils.readFileToString(stubFile));
- } catch (IOException e) {
- getLog().error("Error while reading/writing to files.", e);
+ if (sourceFile.getName().endsWith(".java")) {
+ String sourceContent;
+ try {
+ sourceContent = FileUtils.readFileToString(sourceFile);
+ } catch (IOException e) {
+ getLog().error("Cannot read " + sourceFile.getAbsolutePath(), e);
+ continue;
+ }
+ if (sourceFile.getName().endsWith("Module.java") || sourceFile.getName().endsWith("ModuleFactory.java")) {
+ File stubFile = new File(sourceFile.getPath().replace(".java", "Stub.txt"));
+ if (stubFile.exists()) {
+ String stubContent = null;
+ try {
+ stubContent = FileUtils.readFileToString(stubFile);
+ } catch (IOException e) {
+ getLog().error("Cannot read " + stubFile.getAbsolutePath(), e);
+ }
+ if (stubContent != null) {
+ sourceContent = rewriteStub(sourceContent, stubContent);
+ }
}
}
+ // remove copyright headers as they can contain timestamp
+ sourceContent = removeCopyrights(sourceContent);
+
+ // replace the file content
+ try {
+ FileUtils.write(sourceFile, sourceContent);
+ } catch (IOException e) {
+ getLog().error("Cannot write " + sourceFile.getAbsolutePath(), e);
+ }
}
+
}
}
- private static void rewrite(File sourceFile, String replaceTODOWith) throws IOException {
- String source = FileUtils.readFileToString(sourceFile);
- String target = Pattern.compile("^.*TODO.*\n.*throw new java.lang.UnsupportedOperationException.*$", Pattern.MULTILINE).matcher(source).replaceFirst(replaceTODOWith);
- FileUtils.write(sourceFile, target);
+ private static Pattern MULTILINE_COMMENT_PATTERN = Pattern.compile("/\\*.*\\*/", Pattern.MULTILINE | Pattern.DOTALL);
+ private static String removeCopyrights(String source) {
+ String target = MULTILINE_COMMENT_PATTERN.matcher(source).replaceAll("\n");
+ //FileUtils.write(sourceFile, target);
+ return target;
+ }
+
+ private static Pattern UNSUPPORTED_OP_PATTERN = Pattern.compile("^.*TODO.*\n.*throw new java.lang.UnsupportedOperationException.*$", Pattern.MULTILINE);
+
+ private static String rewriteStub(String source, String replaceTODOWith) {
+ String target = UNSUPPORTED_OP_PATTERN.matcher(source).replaceFirst(replaceTODOWith);
+ return target;
}
}
-/*
-* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
-*
-* This program and the accompanying materials are made available under the
-* terms of the Eclipse Public License v1.0 which accompanies this distribution,
-* and is available at http://www.eclipse.org/legal/epl-v10.html
-*/
+
+
package org.opendaylight.controller.config.yang.test.impl;
public class DepTestImplModule extends org.opendaylight.controller.config.yang.test.impl.AbstractDepTestImplModule {
public DepTestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
-/*
-* 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
-*/
-/*
-* Generated file
-*
-* Generated from: yang module name: config-test-impl yang module local name: impl-dep
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Fri Apr 25 11:50:32 CEST 2014
-*
-* Do not modify this file unless it is present under src/main directory
-*/
+
+
package org.opendaylight.controller.config.yang.test.impl;
public class DepTestImplModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractDepTestImplModuleFactory {
-/*
-* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
-*
-* This program and the accompanying materials are made available under the
-* terms of the Eclipse Public License v1.0 which accompanies this distribution,
-* and is available at http://www.eclipse.org/legal/epl-v10.html
-*/
+
+
package org.opendaylight.controller.config.yang.test.impl;
public class IdentityTestModule extends org.opendaylight.controller.config.yang.test.impl.AbstractIdentityTestModule {
public IdentityTestModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
-/*
-* 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
-*/
-/*
-* Generated file
-*
-* Generated from: yang module name: config-test-impl yang module local name: impl-identity-test
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Fri Apr 25 11:50:32 CEST 2014
-*
-* Do not modify this file unless it is present under src/main directory
-*/
+
+
package org.opendaylight.controller.config.yang.test.impl;
public class IdentityTestModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractIdentityTestModuleFactory {
-/*
-* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
-*
-* This program and the accompanying materials are made available under the
-* terms of the Eclipse Public License v1.0 which accompanies this distribution,
-* and is available at http://www.eclipse.org/legal/epl-v10.html
-*/
+
+
package org.opendaylight.controller.config.yang.test.impl;
public class NetconfTestImplModule extends org.opendaylight.controller.config.yang.test.impl.AbstractNetconfTestImplModule {
public NetconfTestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
-/*
-* 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
-*/
-/*
-* Generated file
-*
-* Generated from: yang module name: config-test-impl yang module local name: impl-netconf
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Fri Apr 25 11:50:32 CEST 2014
-*
-* Do not modify this file unless it is present under src/main directory
-*/
+
+
package org.opendaylight.controller.config.yang.test.impl;
public class NetconfTestImplModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractNetconfTestImplModuleFactory {
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
+
+
package org.opendaylight.controller.config.yang.test.impl;
import com.google.common.collect.Lists;
-/*
-* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
-*
-* This program and the accompanying materials are made available under the
-* terms of the Eclipse Public License v1.0 which accompanies this distribution,
-* and is available at http://www.eclipse.org/legal/epl-v10.html
-*/
+
+
package org.opendaylight.controller.config.yang.test.impl;
public class TestImplModule extends org.opendaylight.controller.config.yang.test.impl.AbstractTestImplModule {
public TestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
-/*
-* 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
-*/
-/*
-* Generated file
-*
-* Generated from: yang module name: config-test-impl yang module local name: impl
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Fri Apr 25 11:50:32 CEST 2014
-*
-* Do not modify this file unless it is present under src/main directory
-*/
+
+
package org.opendaylight.controller.config.yang.test.impl;
public class TestImplModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractTestImplModuleFactory {
netconf.ssh.address=0.0.0.0
netconf.ssh.port=1830
netconf.ssh.pk.path = ./configuration/RSA.pk
+netconf.ssh.default.user = netconf
+netconf.ssh.default.password = netconf
netconf.config.persister.active=1,2
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:schema-service-singleton</type>
<name>yang-schema-service</name>
</module>
- <!-- To enable use of new in-memory datastore and new implementations
- of data brokers, comment out all parts of this
- xml which are marked with DATA-BROKER and uncomment all parts
- of this xml which are marked with NEW-DATA-BROKER
- -->
- <!-- DATA-BROKER start-->
- <module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:hash-map-data-store</type>
- <name>hash-map-data-store</name>
- </module>
- <!-- DATA BROKER end -->
- <!-- NEW-DATA-BROKER start -->
- <!--
<module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-inmemory-data-broker</type>
- <name>async-data-broker</name>
- <schema-service>
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
- <name>yang-schema-service</name>
- </schema-service>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:runtime-generated-mapping</type>
+ <name>runtime-mapping-singleton</name>
</module>
- -->
- <!-- NEW-DATA-BROKER end -->
<module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-broker-impl</type>
- <name>dom-broker</name>
- <!-- DATA-BROKER start -->
- <data-store xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-data-store</type>
- <!-- to switch to the clustered data store, comment out the hash-map-data-store <name> and uncomment the cluster-data-store one -->
- <name>hash-map-data-store</name>
- <!-- <name>cluster-data-store</name> -->
- </data-store>
- <!-- DATA-BROKER end -->
- <!-- NEW-DATA-BROKER start -->
- <!--
- <async-data-broker>
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-async-data-broker</type>
- <name>async-data-broker</name>
- </async-data-broker>
- -->
- <!-- NEW-DATA-BROKER end -->
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-notification-broker</type>
+ <name>binding-notification-broker</name>
</module>
<module>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-broker-impl</type>
<name>binding-data-broker</name>
</data-broker>
</module>
+
+ <!--
+ Tree-based in-memory data store. This is the data store which is currently
+ recommended for single-node deployments.
+ -->
<module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:runtime-generated-mapping</type>
- <name>runtime-mapping-singleton</name>
- </module>
- <module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-notification-broker</type>
- <name>binding-notification-broker</name>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-inmemory-data-broker</type>
+ <name>inmemory-data-broker</name>
+ <schema-service>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
+ <name>yang-schema-service</name>
+ </schema-service>
</module>
- <!-- DATA-BROKER start -->
<module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-data-broker</type>
- <name>binding-data-broker</name>
- <dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
- <name>dom-broker</name>
- </dom-broker>
- <mapping-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding:binding-dom-mapping-service</type>
- <name>runtime-mapping-singleton</name>
- </mapping-service>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-broker-impl</type>
+ <name>inmemory-dom-broker</name>
+ <async-data-broker>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-async-data-broker</type>
+ <name>inmemory-data-broker</name>
+ </async-data-broker>
</module>
- <!-- DATA-BROKER end -->
- <!-- NEW-DATA-BROKER start -->
- <!--
<module>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-data-compatible-broker</type>
- <name>binding-data-broker</name>
+ <name>inmemory-binding-data-broker</name>
<dom-async-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
<type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
<name>dom-broker</name>
<name>runtime-mapping-singleton</name>
</binding-mapping-service>
</module>
- -->
- <!-- NEW-DATA-BROKER end -->
</modules>
<services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
- <service>
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
- <instance>
- <name>yang-schema-service</name>
- <provider>/modules/module[type='schema-service-singleton'][name='yang-schema-service']</provider>
- </instance>
- </service>
- <service>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
- <instance>
- <name>binding-notification-broker</name>
- <provider>/modules/module[type='binding-notification-broker'][name='binding-notification-broker']</provider>
- </instance>
- </service>
- <!-- DATA-BROKER start -->
- <service>
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-data-store</type>
- <instance>
- <name>hash-map-data-store</name>
- <provider>/modules/module[type='hash-map-data-store'][name='hash-map-data-store']</provider>
- </instance>
- </service>
- <!-- DATA-BROKER end -->
- <!-- NEW-DATA-BROKER start -->
- <!--
- <service>
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-async-data-broker</type>
- <instance>
- <name>async-data-broker</name>
- <provider>/modules/module[type='dom-inmemory-data-broker'][name='async-data-broker']</provider>
- </instance>
- </service>
- -->
- <!-- NEW-DATA-BROKER end -->
- <service>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
- <instance>
- <name>binding-osgi-broker</name>
- <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
- </instance>
- </service>
- <service>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
- <instance>
- <name>binding-rpc-broker</name>
- <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
- </instance>
- </service>
- <service>
- <type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding-impl:binding-dom-mapping-service</type>
- <instance>
- <name>runtime-mapping-singleton</name>
- <provider>/modules/module[type='runtime-generated-mapping'][name='runtime-mapping-singleton']</provider>
- </instance>
- </service>
- <service>
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
- <instance>
- <name>dom-broker</name>
- <provider>/modules/module[type='dom-broker-impl'][name='dom-broker']</provider>
- </instance>
- </service>
+ <service>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
+ <instance>
+ <name>yang-schema-service</name>
+ <provider>/modules/module[type='schema-service-singleton'][name='yang-schema-service']</provider>
+ </instance>
+ </service>
+ <service>
+ <type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding-impl:binding-dom-mapping-service</type>
+ <instance>
+ <name>runtime-mapping-singleton</name>
+ <provider>/modules/module[type='runtime-generated-mapping'][name='runtime-mapping-singleton']</provider>
+ </instance>
+ </service>
+ <service>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
+ <instance>
+ <name>binding-notification-broker</name>
+ <provider>/modules/module[type='binding-notification-broker'][name='binding-notification-broker']</provider>
+ </instance>
+ </service>
+ <service>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
+ <instance>
+ <name>binding-osgi-broker</name>
+ <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
+ </instance>
+ </service>
+ <service>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+ <instance>
+ <name>binding-rpc-broker</name>
+ <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
+ </instance>
+ </service>
- <service>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
- <instance>
- <name>binding-data-broker</name>
- <!-- DATA-BROKER start -->
- <provider>/modules/module[type='binding-data-broker'][name='binding-data-broker']</provider>
- <!-- DATA-BROKER end -->
- <!-- NEW-DATA-BROKER start -->
- <!--
- <provider>/modules/module[type='binding-data-compatible-broker'][name='binding-data-broker']</provider>
- -->
- <!-- NEW-DATA-BROKER end -->
- </instance>
- </service>
+ <service>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
+ <instance>
+ <name>dom-broker</name>
+ <provider>/modules/module[type='dom-broker-impl'][name='inmemory-dom-broker']</provider>
+ </instance>
+ </service>
+ <service>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
+ <instance>
+ <name>binding-data-broker</name>
+ <provider>/modules/module[type='binding-data-compatible-broker'][name='inmemory-binding-data-broker']</provider>
+ </instance>
+ </service>
+
+ <service>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-async-data-broker</type>
+ <instance>
+ <name>inmemory-data-broker</name>
+ <provider>/modules/module[type='dom-inmemory-data-broker'][name='inmemory-data-broker']</provider>
+ </instance>
+ </service>
</services>
</data>
</configuration>
</instructions>
</configuration>
</plugin>
- <plugin>
- <groupId>org.eclipse.xtend</groupId>
- <artifactId>xtend-maven-plugin</artifactId>
- </plugin>
</plugins>
</build>
--- /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.frm;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ */
+public abstract class AbstractChangeListener implements DataChangeListener {
+
+ private final AtomicLong txNum = new AtomicLong();
+ private String transactionId;
+
+ @Override
+ public void onDataChanged(DataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvent) {
+ this.transactionId = this.newTransactionIdentifier().toString();
+
+ final Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> createdEntries =
+ changeEvent.getCreatedConfigurationData().entrySet();
+ final Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> updatedEntries =
+ new HashSet<Entry<InstanceIdentifier<? extends DataObject>, DataObject>>();
+
+ Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> updateConfigEntrySet =
+ changeEvent.getUpdatedConfigurationData().entrySet();
+ updatedEntries.addAll(updateConfigEntrySet);
+ updatedEntries.removeAll(createdEntries);
+
+ final Set<InstanceIdentifier<? extends DataObject>> removeEntriesInstanceIdentifiers =
+ changeEvent.getRemovedConfigurationData();
+
+ for (final Entry<InstanceIdentifier<? extends DataObject>, DataObject> createdEntry : createdEntries) {
+ InstanceIdentifier<? extends DataObject> c_key = createdEntry.getKey();
+ DataObject c_value = createdEntry.getValue();
+ this.add(c_key, c_value);
+ }
+
+ for (final Entry<InstanceIdentifier<?>, DataObject> updatedEntrie : updatedEntries) {
+ Map<InstanceIdentifier<? extends DataObject>, DataObject> origConfigData =
+ changeEvent.getOriginalConfigurationData();
+
+ InstanceIdentifier<? extends Object> u_key = updatedEntrie.getKey();
+ final DataObject originalFlow = origConfigData.get(u_key);
+ final DataObject updatedFlow = updatedEntrie.getValue();
+ this.update(u_key, originalFlow, updatedFlow);
+ }
+
+ for (final InstanceIdentifier<?> instanceId : removeEntriesInstanceIdentifiers) {
+ Map<InstanceIdentifier<? extends DataObject>, DataObject> origConfigData =
+ changeEvent.getOriginalConfigurationData();
+
+ final DataObject removeValue = origConfigData.get(instanceId);
+ this.remove(instanceId, removeValue);
+ }
+ }
+
+ public String getTransactionId() {
+ return this.transactionId;
+ }
+
+ private Object newTransactionIdentifier() {
+ return "DOM-" + txNum.getAndIncrement();
+ }
+
+ protected abstract void validate() throws IllegalStateException;
+
+ protected abstract void remove(
+ final InstanceIdentifier<? extends DataObject> identifier,
+ final DataObject remove);
+
+ protected abstract void update(
+ final InstanceIdentifier<? extends DataObject> identifier,
+ final DataObject original, final DataObject update);
+
+ protected abstract void add(
+ final InstanceIdentifier<? extends DataObject> identifier,
+ final DataObject add);
+}
+++ /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.frm
-
-import java.util.Collections
-import java.util.HashSet
-import java.util.Map.Entry
-import java.util.Set
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction
-import org.opendaylight.controller.md.sal.common.api.data.DataModification
-import org.opendaylight.controller.sal.common.util.Rpcs
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yangtools.yang.common.RpcError
-
-abstract class AbstractTransaction implements DataCommitTransaction<InstanceIdentifier<?extends DataObject>, DataObject> {
-
- @Property
- val DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
-
- new(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
- _modification = modification;
- }
-
- def void validate() throws IllegalStateException
-
- override finish() throws IllegalStateException {
- validate()
- callRpcs();
- return Rpcs.getRpcResult(true, null, Collections.<RpcError>emptySet());
- }
-
- override getModification() {
- return _modification;
- }
-
- override rollback() throws IllegalStateException {
- rollbackRpcs();
- return Rpcs.getRpcResult(true, null, Collections.<RpcError>emptySet());
- }
-
- def private callRpcs() {
- val Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> createdEntries = _modification.getCreatedConfigurationData().entrySet();
-
- /*
- * This little dance is because updatedEntries contains both created and modified entries
- * The reason I created a new HashSet is because the collections we are returned are immutable.
- */
- val Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> updatedEntries = new HashSet<Entry<InstanceIdentifier<? extends DataObject>, DataObject>>();
- updatedEntries.addAll(_modification.getUpdatedConfigurationData().entrySet());
- updatedEntries.removeAll(createdEntries);
-
- val Set<InstanceIdentifier<? extends DataObject>> removeEntriesInstanceIdentifiers = _modification.getRemovedConfigurationData();
- for (Entry<InstanceIdentifier<? extends DataObject >, DataObject> entry : createdEntries) {
- add(entry.key,entry.value);
- }
- for (Entry<InstanceIdentifier<?>, DataObject> entry : updatedEntries) {
- val originalFlow = _modification.originalConfigurationData.get(entry.key);
- val updatedFlow = entry.value
- update(entry.key, originalFlow ,updatedFlow);
- }
-
- for (InstanceIdentifier<?> instanceId : removeEntriesInstanceIdentifiers ) {
- val removeValue = _modification.getOriginalConfigurationData.get(instanceId);
- remove(instanceId,removeValue);
- }
- }
-
- def void remove(InstanceIdentifier<?> identifier, DataObject remove)
-
- def void update(InstanceIdentifier<?> identifier, DataObject original, DataObject update)
-
- def void add(InstanceIdentifier<?> identifier, DataObject add)
-
- def private rollbackRpcs() {
- val Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> createdEntries = _modification.getCreatedConfigurationData().entrySet();
-
- /*
- * This little dance is because updatedEntries contains both created and modified entries
- * The reason I created a new HashSet is because the collections we are returned are immutable.
- */
- val Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> updatedEntries = new HashSet<Entry<InstanceIdentifier<? extends DataObject>, DataObject>>();
- updatedEntries.addAll(_modification.getUpdatedConfigurationData().entrySet());
- updatedEntries.removeAll(createdEntries);
-
- val Set<InstanceIdentifier<? >> removeEntriesInstanceIdentifiers = _modification.getRemovedConfigurationData();
- for (Entry<InstanceIdentifier<?>, DataObject> entry : createdEntries) {
- remove(entry.key,entry.value); // because we are rolling back, remove what we would have added.
- }
- for (Entry<InstanceIdentifier<?>, DataObject> entry : updatedEntries) {
- val originalFlow = _modification.originalConfigurationData.get(entry.key);
- val updatedFlow = entry.value
- update(entry.key, updatedFlow ,originalFlow);// because we are rolling back, replace the updated with the original
- }
-
- for (InstanceIdentifier<?> instanceId : removeEntriesInstanceIdentifiers ) {
- val removeValue = _modification.getOriginalConfigurationData.get(instanceId);
- add(instanceId,removeValue);// because we are rolling back, add what we would have removed.
- }
- }
-}
--- /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.frm;
+
+import org.opendaylight.controller.frm.flow.FlowProvider;
+import org.opendaylight.controller.frm.group.GroupProvider;
+import org.opendaylight.controller.frm.meter.MeterProvider;
+import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
+import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FRMActivator extends AbstractBindingAwareProvider {
+
+ private final static Logger LOG = LoggerFactory.getLogger(FRMActivator.class);
+
+ private static FlowProvider flowProvider = new FlowProvider();
+ private static GroupProvider groupProvider = new GroupProvider();
+ private static MeterProvider meterProvider = new MeterProvider();
+
+ @Override
+ public void onSessionInitiated(final ProviderContext session) {
+ DataProviderService flowSalService = session.<DataProviderService>getSALService(DataProviderService.class);
+ FRMActivator.flowProvider.setDataService(flowSalService);
+ SalFlowService rpcFlowSalService = session.<SalFlowService>getRpcService(SalFlowService.class);
+ FRMActivator.flowProvider.setSalFlowService(rpcFlowSalService);
+ FRMActivator.flowProvider.start();
+ DataProviderService groupSalService = session.<DataProviderService>getSALService(DataProviderService.class);
+ FRMActivator.groupProvider.setDataService(groupSalService);
+ SalGroupService rpcGroupSalService = session.<SalGroupService>getRpcService(SalGroupService.class);
+ FRMActivator.groupProvider.setSalGroupService(rpcGroupSalService);
+ FRMActivator.groupProvider.start();
+ DataProviderService meterSalService = session.<DataProviderService>getSALService(DataProviderService.class);
+ FRMActivator.meterProvider.setDataService(meterSalService);
+ SalMeterService rpcMeterSalService = session.<SalMeterService>getRpcService(SalMeterService.class);
+ FRMActivator.meterProvider.setSalMeterService(rpcMeterSalService);
+ FRMActivator.meterProvider.start();
+ }
+
+ @Override
+ protected void stopImpl(final BundleContext context) {
+ try {
+ FRMActivator.flowProvider.close();
+ FRMActivator.groupProvider.close();
+ FRMActivator.meterProvider.close();
+ } catch (Throwable e) {
+ LOG.error("Unexpected error by stopping FRMActivator", e);
+ throw new RuntimeException(e);
+ }
+ }
+ }
\ 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.frm
-
-import org.opendaylight.controller.frm.flow.FlowProvider
-import org.opendaylight.controller.frm.group.GroupProvider
-import org.opendaylight.controller.frm.meter.MeterProvider
-import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService
-import org.osgi.framework.BundleContext
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService
-
-class FRMActivator extends AbstractBindingAwareProvider {
-
- static var FlowProvider provider = new FlowProvider();
- static var GroupProvider groupProvider = new GroupProvider();
- static var MeterProvider meterProvider = new MeterProvider();
-
- override onSessionInitiated(ProviderContext session) {
- provider.dataService = session.getSALService(DataProviderService)
- provider.salFlowService = session.getRpcService(SalFlowService);
- provider.start();
-
- groupProvider.dataService = session.getSALService(DataProviderService)
- groupProvider.salGroupService = session.getRpcService(SalGroupService)
- groupProvider.start();
-
- meterProvider.dataService = session.getSALService(DataProviderService)
- meterProvider.salMeterService = session.getRpcService(SalMeterService)
- meterProvider.start();
- }
-
- override protected stopImpl(BundleContext context) {
- provider.close();
- groupProvider.close();
- meterProvider.close();
- }
-
-}
--- /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.frm.flow;
+
+import org.opendaylight.controller.frm.AbstractChangeListener;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ */
+public class FlowChangeListener extends AbstractChangeListener {
+
+ private final static Logger LOG = LoggerFactory.getLogger(FlowChangeListener.class);
+
+ private final SalFlowService salFlowService;
+
+ public SalFlowService getSalFlowService() {
+ return this.salFlowService;
+ }
+
+ public FlowChangeListener(final SalFlowService manager) {
+ this.salFlowService = manager;
+ }
+
+ @Override
+ protected void validate() throws IllegalStateException {
+ FlowTransactionValidator.validate(this);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<? extends DataObject> identifier, DataObject removeDataObj) {
+ if ((removeDataObj instanceof Flow)) {
+
+ final Flow flow = ((Flow) removeDataObj);
+ final InstanceIdentifier<Table> tableInstanceId = identifier.<Table> firstIdentifierOf(Table.class);
+ final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
+ final RemoveFlowInputBuilder builder = new RemoveFlowInputBuilder(flow);
+
+ builder.setFlowRef(new FlowRef(identifier));
+ builder.setNode(new NodeRef(nodeInstanceId));
+ builder.setFlowTable(new FlowTableRef(tableInstanceId));
+
+ Uri uri = new Uri(this.getTransactionId());
+ builder.setTransactionUri(uri);
+ this.salFlowService.removeFlow((RemoveFlowInput) builder.build());
+ LOG.debug("Transaction {} - Removed Flow has removed flow: {}", new Object[]{uri, removeDataObj});
+ }
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<? extends DataObject> identifier, DataObject original, DataObject update) {
+ if (original instanceof Flow && update instanceof Flow) {
+
+ final Flow originalFlow = ((Flow) original);
+ final Flow updatedFlow = ((Flow) update);
+ final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node>firstIdentifierOf(Node.class);
+ final UpdateFlowInputBuilder builder = new UpdateFlowInputBuilder();
+
+ builder.setNode(new NodeRef(nodeInstanceId));
+ builder.setFlowRef(new FlowRef(identifier));
+
+ Uri uri = new Uri(this.getTransactionId());
+ builder.setTransactionUri(uri);
+
+ builder.setUpdatedFlow((UpdatedFlow) (new UpdatedFlowBuilder(updatedFlow)).build());
+ builder.setOriginalFlow((OriginalFlow) (new OriginalFlowBuilder(originalFlow)).build());
+
+ this.salFlowService.updateFlow((UpdateFlowInput) builder.build());
+ LOG.debug("Transaction {} - Update Flow has updated flow {} with {}", new Object[]{uri, original, update});
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<? extends DataObject> identifier, DataObject addDataObj) {
+ if ((addDataObj instanceof Flow)) {
+
+ final Flow flow = ((Flow) addDataObj);
+ final InstanceIdentifier<Table> tableInstanceId = identifier.<Table> firstIdentifierOf(Table.class);
+ final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
+ final AddFlowInputBuilder builder = new AddFlowInputBuilder(flow);
+
+ builder.setNode(new NodeRef(nodeInstanceId));
+ builder.setFlowRef(new FlowRef(identifier));
+ builder.setFlowTable(new FlowTableRef(tableInstanceId));
+
+ Uri uri = new Uri(this.getTransactionId());
+ builder.setTransactionUri(uri);
+ this.salFlowService.addFlow((AddFlowInput) builder.build());
+ LOG.debug("Transaction {} - Add Flow has added flow: {}", new Object[]{uri, addDataObj});
+ }
+ }
+}
+++ /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.frm.flow
-
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
-import org.opendaylight.controller.md.sal.common.api.data.DataModification
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
-
-class FlowCommitHandler implements DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
-
- @Property
- val SalFlowService salFlowService;
-
- new(SalFlowService manager) {
- _salFlowService = manager;
- }
-
- override requestCommit(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
- return new FlowTransaction(modification,salFlowService);
- }
-
-}
--- /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.frm.flow;
+
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FlowProvider implements AutoCloseable {
+
+ private final static Logger LOG = LoggerFactory.getLogger(FlowProvider.class);
+
+ private SalFlowService salFlowService;
+ private DataProviderService dataService;
+
+ /* DataChangeListener */
+ private FlowChangeListener flowDataChangeListener;
+ ListenerRegistration<DataChangeListener> flowDataChangeListenerRegistration;
+
+ public void start() {
+ /* Build Path */
+ InstanceIdentifierBuilder<Nodes> nodesBuilder = InstanceIdentifier.<Nodes> builder(Nodes.class);
+ InstanceIdentifierBuilder<Node> nodeChild = nodesBuilder.<Node> child(Node.class);
+ InstanceIdentifierBuilder<FlowCapableNode> augmentFlowCapNode = nodeChild.<FlowCapableNode> augmentation(FlowCapableNode.class);
+ InstanceIdentifierBuilder<Table> tableChild = augmentFlowCapNode.<Table> child(Table.class);
+ InstanceIdentifierBuilder<Flow> flowChild = tableChild.<Flow> child(Flow.class);
+ final InstanceIdentifier<? extends DataObject> flowDataObjectPath = flowChild.toInstance();
+
+ /* DataChangeListener registration */
+ this.flowDataChangeListener = new FlowChangeListener(this.salFlowService);
+ this.flowDataChangeListenerRegistration = this.dataService.registerDataChangeListener(flowDataObjectPath, flowDataChangeListener);
+ LOG.info("Flow Config Provider started.");
+ }
+
+ protected DataModificationTransaction startChange() {
+ return this.dataService.beginTransaction();
+ }
+
+ @Override
+ public void close() throws Exception {
+ if(flowDataChangeListenerRegistration != null){
+ flowDataChangeListenerRegistration.close();
+ }
+ }
+
+ public void setDataService(final DataProviderService dataService) {
+ this.dataService = dataService;
+ }
+
+ public void setSalFlowService(final SalFlowService salFlowService) {
+ this.salFlowService = salFlowService;
+ }
+}
+++ /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.frm.flow
-
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
-import org.opendaylight.yangtools.concepts.Registration
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.slf4j.LoggerFactory
-
-class FlowProvider implements AutoCloseable {
-
- @Property
- DataProviderService dataService;
-
- @Property
- SalFlowService salFlowService;
-
- FlowCommitHandler commitHandler
-
- Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>,DataObject>> commitHandlerRegistration;
-
- static val LOG = LoggerFactory.getLogger(FlowProvider);
-
- def void start() {
- commitHandler = new FlowCommitHandler(salFlowService)
- val InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder(Nodes)
- .child(Node)
- .augmentation(FlowCapableNode)
- .child(Table)
- .child(Flow)
- .toInstance();
- commitHandlerRegistration = dataService.registerCommitHandler(path,commitHandler);
- LOG.info("Flow Config Provider started.");
- }
-
- protected def startChange() {
- return dataService.beginTransaction;
- }
-
- override close() throws Exception {
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
- }
-
-}
+++ /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.frm.flow
-
-import org.opendaylight.controller.frm.AbstractTransaction
-import org.opendaylight.controller.md.sal.common.api.data.DataModification
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInputBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlowBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri
-
-class FlowTransaction extends AbstractTransaction {
-
- @Property
- val SalFlowService salFlowService;
-
-
- new(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification,SalFlowService salFlowService) {
- super(modification)
- _salFlowService = salFlowService;
- }
-
- override remove(InstanceIdentifier<?> instanceId, DataObject obj) {
- if(obj instanceof Flow) {
- val flow = (obj as Flow)
- val tableInstanceId = instanceId.firstIdentifierOf(Table);
- val nodeInstanceId = instanceId.firstIdentifierOf(Node);
- val builder = new RemoveFlowInputBuilder(flow);
- builder.setFlowRef(new FlowRef(instanceId));
- builder.setNode(new NodeRef(nodeInstanceId));
- builder.setFlowTable(new FlowTableRef(tableInstanceId));
- builder.setTransactionUri(new Uri(modification.getIdentifier() as String));
- _salFlowService.removeFlow(builder.build());
- }
- }
-
- override update(InstanceIdentifier<?> instanceId, DataObject originalObj, DataObject updatedObj) {
- if(originalObj instanceof Flow && updatedObj instanceof Flow) {
- val originalFlow = (originalObj as Flow)
- val updatedFlow = (updatedObj as Flow)
- val nodeInstanceId = instanceId.firstIdentifierOf(Node);
- val builder = new UpdateFlowInputBuilder();
- builder.setNode(new NodeRef(nodeInstanceId));
- builder.setFlowRef(new FlowRef(instanceId));
- val ufb = new UpdatedFlowBuilder(updatedFlow);
- builder.setUpdatedFlow((ufb.build()));
- builder.setTransactionUri(new Uri(modification.getIdentifier() as String));
- val ofb = new OriginalFlowBuilder(originalFlow);
- builder.setOriginalFlow(ofb.build());
- _salFlowService.updateFlow(builder.build());
-
- }
- }
-
- override add(InstanceIdentifier<?> instanceId, DataObject obj) {
- if(obj instanceof Flow) {
- val flow = (obj as Flow)
- val tableInstanceId = instanceId.firstIdentifierOf(Table);
- val nodeInstanceId = instanceId.firstIdentifierOf(Node);
- val builder = new AddFlowInputBuilder(flow);
- builder.setNode(new NodeRef(nodeInstanceId));
- builder.setTransactionUri(new Uri(modification.getIdentifier() as String));
- builder.setFlowRef(new FlowRef(instanceId));
- builder.setFlowTable(new FlowTableRef(tableInstanceId));
- _salFlowService.addFlow(builder.build());
- }
- }
-
- override validate() throws IllegalStateException {
- FlowTransactionValidator.validate(this)
- }
-}
-/*
+/**
* 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
public class FlowTransactionValidator {
- public static void validate(FlowTransaction transaction) throws IllegalStateException {
+ public static void validate(FlowChangeListener transaction) throws IllegalStateException {
// NOOP
}
-
}
--- /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.frm.group;
+
+import org.opendaylight.controller.frm.AbstractChangeListener;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.OriginalGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.OriginalGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ */
+public class GroupChangeListener extends AbstractChangeListener {
+
+ private final static Logger LOG = LoggerFactory.getLogger(GroupChangeListener.class);
+
+ private final SalGroupService salGroupService;
+
+ public SalGroupService getSalGroupService() {
+ return this.salGroupService;
+ }
+
+ public GroupChangeListener(final SalGroupService manager) {
+ this.salGroupService = manager;
+ }
+
+ @Override
+ protected void validate() throws IllegalStateException {
+ GroupTransactionValidator.validate(this);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<? extends DataObject> identifier, DataObject removeDataObj) {
+ if ((removeDataObj instanceof Group)) {
+
+ final Group group = ((Group) removeDataObj);
+ final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
+ final RemoveGroupInputBuilder builder = new RemoveGroupInputBuilder(group);
+
+ builder.setNode(new NodeRef(nodeInstanceId));
+ builder.setGroupRef(new GroupRef(identifier));
+
+ Uri uri = new Uri(this.getTransactionId());
+ builder.setTransactionUri(uri);
+ this.salGroupService.removeGroup((RemoveGroupInput) builder.build());
+ LOG.debug("Transaction {} - Remove Group has removed group: {}", new Object[]{uri, removeDataObj});
+ }
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<? extends DataObject> identifier, DataObject original, DataObject update) {
+ if (original instanceof Group && update instanceof Group) {
+
+ final Group originalGroup = ((Group) original);
+ final Group updatedGroup = ((Group) update);
+ final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
+ final UpdateGroupInputBuilder builder = new UpdateGroupInputBuilder();
+
+ builder.setNode(new NodeRef(nodeInstanceId));
+ builder.setGroupRef(new GroupRef(identifier));
+
+ Uri uri = new Uri(this.getTransactionId());
+ builder.setTransactionUri(uri);
+
+ builder.setUpdatedGroup((UpdatedGroup) (new UpdatedGroupBuilder(updatedGroup)).build());
+ builder.setOriginalGroup((OriginalGroup) (new OriginalGroupBuilder(originalGroup)).build());
+
+ this.salGroupService.updateGroup((UpdateGroupInput) builder.build());
+ LOG.debug("Transaction {} - Update Group has updated group {} with group {}", new Object[]{uri, original, update});
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<? extends DataObject> identifier, DataObject addDataObj) {
+ if ((addDataObj instanceof Group)) {
+ final Group group = ((Group) addDataObj);
+ final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
+ final AddGroupInputBuilder builder = new AddGroupInputBuilder(group);
+
+ builder.setNode(new NodeRef(nodeInstanceId));
+ builder.setGroupRef(new GroupRef(identifier));
+
+ Uri uri = new Uri(this.getTransactionId());
+ builder.setTransactionUri(uri);
+ this.salGroupService.addGroup((AddGroupInput) builder.build());
+ LOG.debug("Transaction {} - Add Group has added group: {}", new Object[]{uri, addDataObj});
+ }
+ }
+}
+++ /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.frm.group
-
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
-import org.opendaylight.controller.md.sal.common.api.data.DataModification
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-
-class GroupCommitHandler implements DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
-
- @Property
- val SalGroupService groupService;
-
- new(SalGroupService groupService) {
- _groupService = groupService;
- }
-
- override requestCommit(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
- return new GroupTransaction(modification,groupService);
- }
-
-}
--- /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.frm.group;
+
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class GroupProvider implements AutoCloseable {
+
+ private final static Logger LOG = LoggerFactory.getLogger(GroupProvider.class);
+
+ private SalGroupService salGroupService;
+ private DataProviderService dataService;
+
+ /* DataChangeListener */
+ private GroupChangeListener groupDataChangeListener;
+ ListenerRegistration<DataChangeListener> groupDataChangeListenerRegistration;
+
+ public void start() {
+ /* Build Path */
+ InstanceIdentifierBuilder<Nodes> nodesBuilder = InstanceIdentifier.<Nodes> builder(Nodes.class);
+ InstanceIdentifierBuilder<Node> nodeChild = nodesBuilder.<Node> child(Node.class);
+ InstanceIdentifierBuilder<FlowCapableNode> augmentFlowCapNode = nodeChild.<FlowCapableNode> augmentation(FlowCapableNode.class);
+ InstanceIdentifierBuilder<Group> groupChild = augmentFlowCapNode.<Group> child(Group.class);
+ final InstanceIdentifier<? extends DataObject> groupDataObjectPath = groupChild.toInstance();
+
+ /* DataChangeListener registration */
+ this.groupDataChangeListener = new GroupChangeListener(this.salGroupService);
+ this.groupDataChangeListenerRegistration = this.dataService.registerDataChangeListener(groupDataObjectPath, groupDataChangeListener);
+ LOG.info("Group Config Provider started.");
+ }
+
+ protected DataModificationTransaction startChange() {
+ return this.dataService.beginTransaction();
+ }
+
+ public void close() throws Exception {
+ if(groupDataChangeListenerRegistration != null){
+ groupDataChangeListenerRegistration.close();
+ }
+ }
+
+ public void setDataService(final DataProviderService dataService) {
+ this.dataService = dataService;
+ }
+
+ public void setSalGroupService(final SalGroupService salGroupService) {
+ this.salGroupService = salGroupService;
+ }
+}
+++ /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.frm.group
-
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
-import org.opendaylight.yangtools.concepts.Registration
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.slf4j.LoggerFactory
-
-class GroupProvider implements AutoCloseable {
-
- @Property
- DataProviderService dataService;
-
- @Property
- SalGroupService salGroupService;
-
- GroupCommitHandler commitHandler
-
- Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>,DataObject>> commitHandlerRegistration;
-
- static val LOG = LoggerFactory.getLogger(GroupProvider);
-
- def void start() {
- commitHandler = new GroupCommitHandler(salGroupService)
- val InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder(Nodes)
- .child(Node)
- .augmentation(FlowCapableNode)
- .child(Group)
- .toInstance();
- commitHandlerRegistration = dataService.registerCommitHandler(path,commitHandler);
- LOG.info("Group Config Provider started.");
- }
-
- protected def startChange() {
- return dataService.beginTransaction;
- }
-
- override close() throws Exception {
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
- }
-
-}
+++ /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.frm.group
-
-import org.opendaylight.controller.frm.AbstractTransaction
-import org.opendaylight.controller.md.sal.common.api.data.DataModification
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInputBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInputBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.OriginalGroupBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroupBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupRef
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri
-
-class GroupTransaction extends AbstractTransaction {
-
- @Property
- val SalGroupService groupService;
-
- new(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification,SalGroupService groupService) {
- super(modification)
- _groupService = groupService;
- }
-
- override remove(InstanceIdentifier<?> instanceId, DataObject obj) {
- if(obj instanceof Group) {
- val group = (obj as Group)
- val nodeInstanceId = instanceId.firstIdentifierOf(Node);
- val builder = new RemoveGroupInputBuilder(group);
- builder.setNode(new NodeRef(nodeInstanceId));
- builder.setTransactionUri(new Uri(modification.getIdentifier() as String));
- builder.setGroupRef(new GroupRef(instanceId));
- _groupService.removeGroup(builder.build());
- }
- }
-
- override update(InstanceIdentifier<?> instanceId, DataObject originalObj, DataObject updatedObj) {
- if(originalObj instanceof Group && updatedObj instanceof Group) {
- val originalGroup = (originalObj as Group)
- val updatedGroup = (updatedObj as Group)
- val nodeInstanceId = instanceId.firstIdentifierOf(Node);
- val builder = new UpdateGroupInputBuilder();
- builder.setNode(new NodeRef(nodeInstanceId));
- builder.setGroupRef(new GroupRef(instanceId));
- val ufb = new UpdatedGroupBuilder(updatedGroup);
- builder.setUpdatedGroup((ufb.build()));
- builder.setTransactionUri(new Uri(modification.getIdentifier() as String));
- val ofb = new OriginalGroupBuilder(originalGroup);
- builder.setOriginalGroup(ofb.build());
- _groupService.updateGroup(builder.build());
-
- }
- }
-
- override add(InstanceIdentifier<?> instanceId, DataObject obj) {
- if(obj instanceof Group) {
- val group = (obj as Group)
- val nodeInstanceId = instanceId.firstIdentifierOf(Node);
- val builder = new AddGroupInputBuilder(group);
- builder.setNode(new NodeRef(nodeInstanceId));
- builder.setGroupRef(new GroupRef(instanceId));
- builder.setTransactionUri(new Uri(modification.getIdentifier() as String));
- _groupService.addGroup(builder.build());
- }
- }
-
- override validate() throws IllegalStateException {
- GroupTransactionValidator.validate(this)
- }
-}
-/*
+/**
* Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
public class GroupTransactionValidator {
- public static void validate(GroupTransaction transaction) throws IllegalStateException {
+ public static void validate(GroupChangeListener transaction) throws IllegalStateException {
// NOOP
}
-
}
--- /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.frm.meter;
+
+import org.opendaylight.controller.frm.AbstractChangeListener;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.OriginalMeter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.OriginalMeterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.UpdatedMeter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.UpdatedMeterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterRef;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ */
+public class MeterChangeListener extends AbstractChangeListener {
+
+ private final static Logger LOG = LoggerFactory.getLogger(MeterChangeListener.class);
+
+ private final SalMeterService salMeterService;
+
+ public SalMeterService getSalMeterService() {
+ return this.salMeterService;
+ }
+
+ public MeterChangeListener(final SalMeterService manager) {
+ this.salMeterService = manager;
+ }
+
+ @Override
+ protected void validate() throws IllegalStateException {
+ MeterTransactionValidator.validate(this);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<? extends DataObject> identifier, DataObject removeDataObj) {
+ if ((removeDataObj instanceof Meter)) {
+
+ final Meter meter = ((Meter) removeDataObj);
+ final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
+ final RemoveMeterInputBuilder builder = new RemoveMeterInputBuilder(meter);
+
+ builder.setNode(new NodeRef(nodeInstanceId));
+ builder.setMeterRef(new MeterRef(identifier));
+
+ Uri uri = new Uri(this.getTransactionId());
+ builder.setTransactionUri(uri);
+ this.salMeterService.removeMeter((RemoveMeterInput) builder.build());
+ LOG.debug("Transaction {} - Remove Meter has removed meter: {}", new Object[]{uri, removeDataObj});
+ }
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<? extends DataObject> identifier, DataObject original, DataObject update) {
+ if (original instanceof Meter && update instanceof Meter) {
+
+ final Meter originalMeter = ((Meter) original);
+ final Meter updatedMeter = ((Meter) update);
+ final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
+ final UpdateMeterInputBuilder builder = new UpdateMeterInputBuilder();
+
+ builder.setNode(new NodeRef(nodeInstanceId));
+ builder.setMeterRef(new MeterRef(identifier));
+
+ Uri uri = new Uri(this.getTransactionId());
+ builder.setTransactionUri(uri);
+
+ builder.setUpdatedMeter((UpdatedMeter) (new UpdatedMeterBuilder(updatedMeter)).build());
+ builder.setOriginalMeter((OriginalMeter) (new OriginalMeterBuilder(originalMeter)).build());
+
+ this.salMeterService.updateMeter((UpdateMeterInput) builder.build());
+ LOG.debug("Transaction {} - Update Meter has updated meter {} with {}", new Object[]{uri, original, update});
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<? extends DataObject> identifier, DataObject addDataObj) {
+ if ((addDataObj instanceof Meter)) {
+
+ final Meter meter = ((Meter) addDataObj);
+ final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
+ final AddMeterInputBuilder builder = new AddMeterInputBuilder(meter);
+
+ builder.setNode(new NodeRef(nodeInstanceId));
+ builder.setMeterRef(new MeterRef(identifier));
+
+ Uri uri = new Uri(this.getTransactionId());
+ builder.setTransactionUri(uri);
+ this.salMeterService.addMeter((AddMeterInput) builder.build());
+ LOG.debug("Transaction {} - Add Meter has added meter: {}", new Object[]{uri, addDataObj});
+ }
+ }
+}
\ No newline at end of file
+++ /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.frm.meter
-
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
-import org.opendaylight.controller.md.sal.common.api.data.DataModification
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-
-class FlowCommitHandler implements DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
-
- @Property
- val SalMeterService salMeterService;
-
- new(SalMeterService manager) {
- _salMeterService = manager;
- }
-
- override requestCommit(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
- return new MeterTransaction(modification,salMeterService);
- }
-
-}
--- /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.frm.meter;
+
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MeterProvider implements AutoCloseable {
+
+ private final static Logger LOG = LoggerFactory.getLogger(MeterProvider.class);
+
+ private DataProviderService dataService;
+ private SalMeterService salMeterService;
+
+ /* DataChangeListener */
+ private MeterChangeListener meterDataChangeListener;
+ ListenerRegistration<DataChangeListener> meterDataChangeListenerRegistration;
+
+ public void start() {
+ /* Build Path */
+ InstanceIdentifierBuilder<Nodes> nodesBuilder = InstanceIdentifier.<Nodes> builder(Nodes.class);
+ InstanceIdentifierBuilder<Node> nodeChild = nodesBuilder.<Node> child(Node.class);
+ InstanceIdentifierBuilder<FlowCapableNode> augmentFlowCapNode = nodeChild.<FlowCapableNode> augmentation(FlowCapableNode.class);
+ InstanceIdentifierBuilder<Meter> meterChild = augmentFlowCapNode.<Meter> child(Meter.class);
+ final InstanceIdentifier<? extends DataObject> meterDataObjectPath = meterChild.toInstance();
+
+ /* DataChangeListener registration */
+ this.meterDataChangeListener = new MeterChangeListener(this.salMeterService);
+ this.meterDataChangeListenerRegistration = this.dataService.registerDataChangeListener(meterDataObjectPath, meterDataChangeListener);
+ LOG.info("Meter Config Provider started.");
+ }
+
+ protected DataModificationTransaction startChange() {
+ return this.dataService.beginTransaction();
+ }
+
+ public void close() throws Exception {
+ if(meterDataChangeListenerRegistration != null){
+ meterDataChangeListenerRegistration.close();
+ }
+ }
+
+ public void setDataService(final DataProviderService dataService) {
+ this.dataService = dataService;
+ }
+
+ public void setSalMeterService(final SalMeterService salMeterService) {
+ this.salMeterService = salMeterService;
+ }
+}
\ No newline at end of file
+++ /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.frm.meter
-
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService
-import org.opendaylight.yangtools.concepts.Registration
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.slf4j.LoggerFactory
-
-class MeterProvider implements AutoCloseable {
-
- @Property
- DataProviderService dataService;
-
- @Property
- SalMeterService salMeterService;
-
- FlowCommitHandler commitHandler
-
- Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>,DataObject>> commitHandlerRegistration;
-
- static val LOG = LoggerFactory.getLogger(MeterProvider);
-
- def void start() {
- commitHandler = new FlowCommitHandler(salMeterService)
- val InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder(Nodes)
- .child(Node)
- .augmentation(FlowCapableNode)
- .child(Meter)
- .toInstance();
- commitHandlerRegistration = dataService.registerCommitHandler(path,commitHandler);
- LOG.info("Meter Config Provider started.");
- }
-
- protected def startChange() {
- return dataService.beginTransaction;
- }
-
- override close() throws Exception {
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
- }
-
-}
+++ /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.frm.meter
-
-import org.opendaylight.controller.frm.AbstractTransaction
-import org.opendaylight.controller.md.sal.common.api.data.DataModification
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInputBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInputBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterInputBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.OriginalMeterBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.UpdatedMeterBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.Meter
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterRef
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri
-
-class MeterTransaction extends AbstractTransaction {
-
- @Property
- val SalMeterService salMeterService;
-
- new(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification,SalMeterService salMeterService) {
- super(modification)
- _salMeterService = salMeterService;
- }
-
- override remove(InstanceIdentifier<?> instanceId, DataObject obj) {
- if(obj instanceof Meter) {
- val meter = (obj as Meter)
- val nodeInstanceId = instanceId.firstIdentifierOf(Node);
- val builder = new RemoveMeterInputBuilder(meter);
- builder.setNode(new NodeRef(nodeInstanceId));
- builder.setMeterRef(new MeterRef(instanceId));
- builder.setTransactionUri(new Uri(modification.getIdentifier() as String));
- _salMeterService.removeMeter(builder.build());
- }
- }
-
- override update(InstanceIdentifier<?> instanceId, DataObject originalObj, DataObject updatedObj) {
- if(originalObj instanceof Meter && updatedObj instanceof Meter) {
- val originalMeter = (originalObj as Meter)
- val updatedMeter = (updatedObj as Meter)
- val nodeInstanceId = instanceId.firstIdentifierOf(Node);
- val builder = new UpdateMeterInputBuilder();
- builder.setNode(new NodeRef(nodeInstanceId));
- builder.setMeterRef(new MeterRef(instanceId));
- val ufb = new UpdatedMeterBuilder(updatedMeter);
- builder.setUpdatedMeter((ufb.build()));
- builder.setTransactionUri(new Uri(modification.getIdentifier() as String));
- val ofb = new OriginalMeterBuilder(originalMeter);
- builder.setOriginalMeter(ofb.build());
- _salMeterService.updateMeter(builder.build());
-
- }
- }
-
- override add(InstanceIdentifier<?> instanceId, DataObject obj) {
- if(obj instanceof Meter) {
- val meter = (obj as Meter)
- val nodeInstanceId = instanceId.firstIdentifierOf(Node);
- val builder = new AddMeterInputBuilder(meter);
- builder.setNode(new NodeRef(nodeInstanceId));
- builder.setMeterRef(new MeterRef(instanceId));
- builder.setTransactionUri(new Uri(modification.getIdentifier() as String));
- _salMeterService.addMeter(builder.build());
- }
- }
-
- override validate() throws IllegalStateException {
- MeterTransactionValidator.validate(this)
- }
-}
-/*
+/**
* Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
public class MeterTransactionValidator {
- public static void validate(MeterTransaction transaction) throws IllegalStateException {
+ public static void validate(MeterChangeListener transaction) throws IllegalStateException {
// NOOP
}
-
}
try {
final DataObject dataObject = normalizedNode.isPresent() ? codec.toBinding(path,
normalizedNode.get()) : null;
- if(dataObject != null) {
+ if (dataObject != null) {
updateCache(store, path, dataObject);
}
return Optional.fromNullable(dataObject);
.toNormalizedNode(path, data);
org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath = normalized.getKey();
+ ensureParentsByMerge(writeTransaction, store, normalized.getKey(), path);
+ LOG.debug("Tx: {} : Putting data {}",getDelegate().getIdentifier(),normalized.getKey());
+ writeTransaction.put(store, normalized.getKey(), normalized.getValue());
+ }
+
+ protected void doMergeWithEnsureParents(final DOMDataReadWriteTransaction writeTransaction,
+ final LogicalDatastoreType store, final InstanceIdentifier<?> path, final DataObject data) {
+ invalidateCache(store, path);
+ final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> normalized = codec
+ .toNormalizedNode(path, data);
+
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath = normalized.getKey();
+ ensureParentsByMerge(writeTransaction, store, normalized.getKey(), path);
+ LOG.debug("Tx: {} : Merge data {}",getDelegate().getIdentifier(),normalized.getKey());
+ writeTransaction.merge(store, normalized.getKey(), normalized.getValue());
+ }
+
+ private void ensureParentsByMerge(final DOMDataReadWriteTransaction writeTransaction,
+ final LogicalDatastoreType store,
+ final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath,
+ final InstanceIdentifier<?> path) {
List<PathArgument> currentArguments = new ArrayList<>();
DataNormalizationOperation<?> currentOp = codec.getDataNormalizer().getRootOperation();
Iterator<PathArgument> iterator = normalizedPath.getPath().iterator();
writeTransaction.merge(store, currentPath, currentOp.createDefault(currentArg));
}
}
- //LOG .info("Tx: {} : Putting data {}",getDelegate().getIdentifier(),normalized.getKey());
- writeTransaction.put(store, normalized.getKey(), normalized.getValue());
}
protected void doMerge(final DOMDataWriteTransaction writeTransaction, final LogicalDatastoreType store,
private class ForwardedBackwardsCompatibleTransacion extends
AbstractForwardedTransaction<DOMDataReadWriteTransaction> implements DataModificationTransaction {
+ private final ListenerRegistry<DataTransactionListener> listeners = ListenerRegistry.create();
private final Map<InstanceIdentifier<? extends DataObject>, DataObject> updated = new HashMap<>();
private final Map<InstanceIdentifier<? extends DataObject>, DataObject> created = new HashMap<>();
private final Set<InstanceIdentifier<? extends DataObject>> removed = new HashSet<>();
@Override
public void putOperationalData(final InstanceIdentifier<? extends DataObject> path, final DataObject data) {
- posponedRemovedOperational.remove(path);
- doPutWithEnsureParents(getDelegate(), LogicalDatastoreType.OPERATIONAL, path, data);
+ boolean previouslyRemoved = posponedRemovedOperational.remove(path);
+ if(previouslyRemoved) {
+ doPutWithEnsureParents(getDelegate(), LogicalDatastoreType.OPERATIONAL, path, data);
+ } else {
+ doMergeWithEnsureParents(getDelegate(), LogicalDatastoreType.OPERATIONAL, path, data);
+ }
}
@Override
public void putConfigurationData(final InstanceIdentifier<? extends DataObject> path, final DataObject data) {
- posponedRemovedConfiguration.remove(path);
+ boolean previouslyRemoved = posponedRemovedConfiguration.remove(path);
DataObject originalObj = readConfigurationData(path);
if (originalObj != null) {
original.put(path, originalObj);
created.put(path, data);
}
updated.put(path, data);
- doPutWithEnsureParents(getDelegate(), LogicalDatastoreType.CONFIGURATION, path, data);
+ if(previouslyRemoved) {
+ doPutWithEnsureParents(getDelegate(), LogicalDatastoreType.CONFIGURATION, path, data);
+ } else {
+ doMergeWithEnsureParents(getDelegate(), LogicalDatastoreType.CONFIGURATION, path, data);
+ }
}
@Override
private void changeStatus(final TransactionStatus status) {
LOG.trace("Transaction {} changed status to {}", getIdentifier(), status);
this.status = status;
+
+ for(ListenerRegistration<DataTransactionListener> listener : listeners) {
+ try {
+ listener.getInstance().onStatusUpdated(this, status);
+ } catch (Exception e) {
+ LOG.error("Error during invoking transaction listener {}",listener.getInstance(),e);
+ }
+ }
}
@Override
doDelete(getDelegate(), LogicalDatastoreType.OPERATIONAL, path);
}
- final ListenableFuture<RpcResult<TransactionStatus>> f = ForwardedBackwardsCompatibleDataBroker.this.commit(this);
-
changeStatus(TransactionStatus.SUBMITED);
+ final ListenableFuture<RpcResult<TransactionStatus>> f = ForwardedBackwardsCompatibleDataBroker.this.commit(this);
+
Futures.addCallback(f, new FutureCallback<RpcResult<TransactionStatus>>() {
@Override
public void onSuccess(final RpcResult<TransactionStatus> result) {
@Override
public ListenerRegistration<DataTransactionListener> registerListener(final DataTransactionListener listener) {
- throw new UnsupportedOperationException();
+ return listeners.register(listener);
}
}
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-binding-broker-impl</artifactId>
<type>test-jar</type>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-binding</artifactId>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller.model</groupId>
<artifactId>model-flow-management</artifactId>
</dependencies>
<build>
<plugins>
- <plugin>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-maven-plugin</artifactId>
- <executions>
- <execution>
- <goals>
- <goal>generate-sources</goal>
- </goals>
- <configuration>
- <codeGenerators>
- <generator>
- <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>
- <outputBaseDir>${salGeneratorPath}</outputBaseDir>
- </generator>
- </codeGenerators>
- <inspectDependencies>true</inspectDependencies>
- </configuration>
- </execution>
- </executions>
- </plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</execution>
</executions>
</plugin>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>
+ <outputBaseDir>${salGeneratorPath}</outputBaseDir>
+ </generator>
+ </codeGenerators>
+ <inspectDependencies>true</inspectDependencies>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
</plugins>
</build>
<scm>
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
public final class ImmutableDataChangeEvent<P extends Path<P>, D> implements DataChangeEvent<P,D> {
originalOperational.putAll(Maps.filterKeys(data.getOriginalOperationalData(), keyFilter));
createdOperational.putAll(Maps.filterKeys(data.getCreatedOperationalData(), keyFilter));
createdConfiguration.putAll(Maps.filterKeys(data.getCreatedConfigurationData(), keyFilter));
+ removedOperational.addAll(Sets.filter(data.getRemovedOperationalData(), keyFilter));
+ removedConfiguration.addAll(Sets.filter(data.getRemovedConfigurationData(), keyFilter));
return this;
}
Builder eventBuilder = builder(potentialScope) //
.setBefore(beforeCont) //
- .setAfter(afterCont);
+ .setAfter(afterCont)
+ .addUpdated(path, beforeCont, afterCont);
for (DOMImmutableDataChangeEvent childChange : childChanges) {
eventBuilder.merge(childChange);
}
final Collection<Node> listeners, final NormalizedNode<PathArgument, ?> node,
final SimpleEventFactory eventFactory) {
- DOMImmutableDataChangeEvent event = eventFactory.create(path, node);
-
- if (!listeners.isEmpty()) {
+ final DOMImmutableDataChangeEvent event = eventFactory.create(path, node);
+ DOMImmutableDataChangeEvent propagateEvent = event;
// We have listeners for this node or it's children, so we will try
// to do additional processing
- if (node instanceof NormalizedNodeContainer<?, ?, ?>) {
- // Node has children, so we will try to resolve it's children
- // changes.
- @SuppressWarnings("unchecked")
- NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> container = (NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>>) node;
- for (NormalizedNode<PathArgument, ?> child : container.getValue()) {
- PathArgument childId = child.getIdentifier();
- Collection<Node> childListeners = getListenerChildrenWildcarded(listeners, childId);
- if (!childListeners.isEmpty()) {
- resolveSameEventRecursivelly(append(path, childId), childListeners, child, eventFactory);
- }
- }
+ if (node instanceof NormalizedNodeContainer<?, ?, ?>) {
+ Builder eventBuilder = builder(DataChangeScope.BASE);
+ eventBuilder.merge(event);
+ eventBuilder.setBefore(event.getOriginalSubtree());
+ eventBuilder.setAfter(event.getUpdatedSubtree());
+
+ // Node has children, so we will try to resolve it's children
+ // changes.
+ @SuppressWarnings("unchecked")
+ NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> container = (NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>>) node;
+ for (NormalizedNode<PathArgument, ?> child : container.getValue()) {
+ PathArgument childId = child.getIdentifier();
+ Collection<Node> childListeners = getListenerChildrenWildcarded(listeners, childId);
+ eventBuilder.merge(resolveSameEventRecursivelly(append(path, childId), childListeners, child, eventFactory));
}
+ propagateEvent = eventBuilder.build();
+ } else {
+ // We do not dispatch leaf events since Binding Aware components do not support them.
+ propagateEvent = builder(DataChangeScope.BASE).build();
+ }
+ if (!listeners.isEmpty()) {
addPartialTask(listeners, event);
}
- return event;
+ return propagateEvent;
}
private DOMImmutableDataChangeEvent resolveSubtreeChangeEvent(final InstanceIdentifier path,
Builder one = builder(DataChangeScope.ONE).setBefore(before.getData()).setAfter(after.getData());
- Builder subtree = builder(DataChangeScope.SUBTREE);
+ Builder subtree = builder(DataChangeScope.SUBTREE).setBefore(before.getData()).setAfter(after.getData());
for (NodeModification childMod : modification.getModifications()) {
PathArgument childId = childMod.getIdentifier();
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedLeafSetNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder;
import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
} else if (schemaNode instanceof ChoiceNode) {
return new ChoiceModificationStrategy((ChoiceNode) schemaNode);
} else if (schemaNode instanceof LeafListSchemaNode) {
- return new LeafSetEntryModificationStrategy((LeafListSchemaNode) schemaNode);
+ return fromLeafListSchemaNode((LeafListSchemaNode) schemaNode);
} else if (schemaNode instanceof LeafSchemaNode) {
return new LeafModificationStrategy((LeafSchemaNode) schemaNode);
}
return new UnorderedMapModificationStrategy(schemaNode);
}
+ private static SchemaAwareApplyOperation fromLeafListSchemaNode(final LeafListSchemaNode schemaNode) {
+ if(schemaNode.isUserOrdered()) {
+ return new OrderedLeafSetModificationStrategy(schemaNode);
+ } else {
+ return new UnorderedLeafSetModificationStrategy(schemaNode);
+ }
+ }
+
+
public static SchemaAwareApplyOperation from(final DataNodeContainer resolvedTree,
final AugmentationTarget augSchemas, final AugmentationIdentifier identifier) {
AugmentationSchema augSchema = null;
}
- public static class LeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
+ public static class UnorderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
private final Optional<ModificationApplyOperation> entryStrategy;
@SuppressWarnings({ "unchecked", "rawtypes" })
- protected LeafSetModificationStrategy(final LeafListSchemaNode schema) {
+ protected UnorderedLeafSetModificationStrategy(final LeafListSchemaNode schema) {
super((Class) LeafSetNode.class);
entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
}
}
+ public static class OrderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
+
+ private final Optional<ModificationApplyOperation> entryStrategy;
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ protected OrderedLeafSetModificationStrategy(final LeafListSchemaNode schema) {
+ super((Class) LeafSetNode.class);
+ entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ protected NormalizedNodeContainerBuilder createBuilder(final PathArgument identifier) {
+ return ImmutableOrderedLeafSetNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
+ }
+
+ @Override
+ public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
+ if (identifier instanceof NodeWithValue) {
+ return entryStrategy;
+ }
+ return Optional.absent();
+ }
+
+ }
+
public static class UnkeyedListModificationStrategy extends SchemaAwareApplyOperation {
private final Optional<ModificationApplyOperation> entryStrategy;
private static final Logger logger = LoggerFactory.getLogger(AbstractListeningStatsTracker.class);
private ListenerRegistration<?> reg;
- protected AbstractListeningStatsTracker(FlowCapableContext context, long lifetimeNanos) {
- super(context, lifetimeNanos);
+ protected AbstractListeningStatsTracker(FlowCapableContext context) {
+ super(context);
}
protected abstract InstanceIdentifier<?> listenPath();
abstract class AbstractStatsTracker<I, K> {
private static final Logger logger = LoggerFactory.getLogger(AbstractStatsTracker.class);
+
+ private static final int WAIT_FOR_REQUEST_CYCLE = 2;
+
private final FutureCallback<RpcResult<? extends TransactionAware>> callback =
new FutureCallback<RpcResult<? extends TransactionAware>>() {
@Override
private final Map<K, Long> trackedItems = new HashMap<>();
private final FlowCapableContext context;
- private final long lifetimeNanos;
+ private long requestCounter;
- protected AbstractStatsTracker(final FlowCapableContext context, final long lifetimeNanos) {
+ protected AbstractStatsTracker(final FlowCapableContext context) {
this.context = Preconditions.checkNotNull(context);
- this.lifetimeNanos = lifetimeNanos;
+ this.requestCounter = 0;
}
protected final InstanceIdentifierBuilder<Node> getNodeIdentifierBuilder() {
return context.startDataModification();
}
+ public final synchronized void increaseRequestCounter(){
+ this.requestCounter++;
+ }
protected abstract void cleanupSingleStat(DataModificationTransaction trans, K item);
protected abstract K updateSingleStat(DataModificationTransaction trans, I item);
+ public abstract void request();
public final synchronized void updateStats(List<I> list) {
- final Long expiryTime = System.nanoTime() + lifetimeNanos;
+
final DataModificationTransaction trans = startTransaction();
for (final I item : list) {
- trackedItems.put(updateSingleStat(trans, item), expiryTime);
+ trackedItems.put(updateSingleStat(trans, item), requestCounter);
}
trans.commit();
}
- public final synchronized void cleanup(final DataModificationTransaction trans, long now) {
+ /**
+ * Statistics will be cleaned up if not update in last two request cycles.
+ * @param trans
+ */
+ public final synchronized void cleanup(final DataModificationTransaction trans) {
for (Iterator<Entry<K, Long>> it = trackedItems.entrySet().iterator();it.hasNext();){
Entry<K, Long> e = it.next();
- if (now > e.getValue()) {
+ if (requestCounter >= e.getValue()+WAIT_FOR_REQUEST_CYCLE) {
cleanupSingleStat(trans, e.getKey());
it.remove();
}
*/
package org.opendaylight.controller.md.statistics.manager;
+import java.util.Collection;
import java.util.Map.Entry;
import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
final class FlowStatsTracker extends AbstractListeningStatsTracker<FlowAndStatisticsMapList, FlowStatsEntry> {
private static final Logger logger = LoggerFactory.getLogger(FlowStatsTracker.class);
private final OpendaylightFlowStatisticsService flowStatsService;
+ private FlowTableStatsTracker flowTableStats;
private int unaccountedFlowsCounter = 1;
- FlowStatsTracker(OpendaylightFlowStatisticsService flowStatsService, final FlowCapableContext context, long lifetimeNanos) {
- super(context, lifetimeNanos);
+ FlowStatsTracker(OpendaylightFlowStatisticsService flowStatsService, final FlowCapableContext context) {
+ super(context);
this.flowStatsService = flowStatsService;
}
+ FlowStatsTracker(OpendaylightFlowStatisticsService flowStatsService, final FlowCapableContext context, FlowTableStatsTracker flowTableStats) {
+ this(flowStatsService, context);
+ this.flowTableStats = flowTableStats;
+ }
@Override
protected void cleanupSingleStat(DataModificationTransaction trans, FlowStatsEntry item) {
return "Flow";
}
+ @Override
+ public void request() {
+ // FIXME: it does not make sense to trigger this before sendAllFlowTablesStatisticsRequest()
+ // comes back -- we do not have any tables anyway.
+ final Collection<TableKey> tables = flowTableStats.getTables();
+ logger.debug("Node {} supports {} table(s)", this.getNodeRef(), tables.size());
+ for (final TableKey key : tables) {
+ logger.debug("Send aggregate stats request for flow table {} to node {}", key.getId(), this.getNodeRef());
+ this.requestAggregateFlows(key);
+ }
+
+ this.requestAllFlowsAllTables();
+
+ }
public void requestAllFlowsAllTables() {
if (flowStatsService != null) {
final GetAllFlowsStatisticsFromAllFlowTablesInputBuilder input = new GetAllFlowsStatisticsFromAllFlowTablesInputBuilder();
private final Set<TableKey> tables = Collections.unmodifiableSet(privateTables);
private final OpendaylightFlowTableStatisticsService flowTableStatsService;
- FlowTableStatsTracker(OpendaylightFlowTableStatisticsService flowTableStatsService, final FlowCapableContext context, long lifetimeNanos) {
- super(context, lifetimeNanos);
+ FlowTableStatsTracker(OpendaylightFlowTableStatisticsService flowTableStatsService, final FlowCapableContext context) {
+ super(context);
this.flowTableStatsService = flowTableStatsService;
}
return item;
}
+ @Override
public void request() {
if (flowTableStatsService != null) {
final GetFlowTablesStatisticsInputBuilder input = new GetFlowTablesStatisticsInputBuilder();
private static final Logger logger = LoggerFactory.getLogger(GroupDescStatsTracker.class);
private final OpendaylightGroupStatisticsService groupStatsService;
- public GroupDescStatsTracker(OpendaylightGroupStatisticsService groupStatsService, final FlowCapableContext context, final long lifetimeNanos) {
- super(context, lifetimeNanos);
+ public GroupDescStatsTracker(OpendaylightGroupStatisticsService groupStatsService, final FlowCapableContext context) {
+ super(context);
this.groupStatsService = groupStatsService;
}
return "Group Descriptor";
}
+ @Override
public void request() {
if (groupStatsService != null) {
final GetGroupDescriptionInputBuilder input = new GetGroupDescriptionInputBuilder();
private static final Logger logger = LoggerFactory.getLogger(GroupStatsTracker.class);
private final OpendaylightGroupStatisticsService groupStatsService;
- GroupStatsTracker(OpendaylightGroupStatisticsService groupStatsService, FlowCapableContext context, long lifetimeNanos) {
- super(context, lifetimeNanos);
+ GroupStatsTracker(OpendaylightGroupStatisticsService groupStatsService, FlowCapableContext context) {
+ super(context);
this.groupStatsService = Preconditions.checkNotNull(groupStatsService);
}
return "Group";
}
+ @Override
public void request() {
final GetAllGroupStatisticsInputBuilder input = new GetAllGroupStatisticsInputBuilder();
input.setNode(getNodeRef());
private static final Logger logger = LoggerFactory.getLogger(MeterConfigStatsTracker.class);
private final OpendaylightMeterStatisticsService meterStatsService;
- protected MeterConfigStatsTracker(OpendaylightMeterStatisticsService meterStatsService, final FlowCapableContext context, long lifetimeNanos) {
- super(context, lifetimeNanos);
+ protected MeterConfigStatsTracker(OpendaylightMeterStatisticsService meterStatsService, final FlowCapableContext context) {
+ super(context);
this.meterStatsService = meterStatsService;
}
return item;
}
+ @Override
public void request() {
if (meterStatsService != null) {
GetAllMeterConfigStatisticsInputBuilder input = new GetAllMeterConfigStatisticsInputBuilder();
private static final Logger logger = LoggerFactory.getLogger(MeterStatsTracker.class);
private final OpendaylightMeterStatisticsService meterStatsService;
- MeterStatsTracker(OpendaylightMeterStatisticsService meterStatsService, final FlowCapableContext context, long lifetimeNanos) {
- super(context, lifetimeNanos);
+ MeterStatsTracker(OpendaylightMeterStatisticsService meterStatsService, final FlowCapableContext context) {
+ super(context);
this.meterStatsService = meterStatsService;
}
return item;
}
+ @Override
public void request() {
if (meterStatsService != null) {
GetAllMeterStatisticsInputBuilder input = new GetAllMeterStatisticsInputBuilder();
private static final Logger logger = LoggerFactory.getLogger(NodeConnectorStatsTracker.class);
private final OpendaylightPortStatisticsService portStatsService;
- NodeConnectorStatsTracker(final OpendaylightPortStatisticsService portStatsService, final FlowCapableContext context, long lifetimeNanos) {
- super(context, lifetimeNanos);
+ NodeConnectorStatsTracker(final OpendaylightPortStatisticsService portStatsService, final FlowCapableContext context) {
+ super(context);
this.portStatsService = portStatsService;
}
return item;
}
+ @Override
public void request() {
if (portStatsService != null) {
final GetAllNodeConnectorsStatisticsInputBuilder input = new GetAllNodeConnectorsStatisticsInputBuilder();
*/
package org.opendaylight.controller.md.statistics.manager;
-import java.util.Collection;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
private static final int NUMBER_OF_WAIT_CYCLES = 2;
private final MultipartMessageManager msgManager;
+ private final StatisticsRequestScheduler srScheduler;
private final InstanceIdentifier<Node> targetNodeIdentifier;
private final FlowStatsTracker flowStats;
private final FlowTableStatsTracker flowTableStats;
final OpendaylightGroupStatisticsService groupStatsService,
final OpendaylightMeterStatisticsService meterStatsService,
final OpendaylightPortStatisticsService portStatsService,
- final OpendaylightQueueStatisticsService queueStatsService) {
+ final OpendaylightQueueStatisticsService queueStatsService,
+ final StatisticsRequestScheduler srScheduler) {
this.dps = Preconditions.checkNotNull(dps);
this.targetNodeKey = Preconditions.checkNotNull(nodeKey);
+ this.srScheduler = Preconditions.checkNotNull(srScheduler);
this.targetNodeIdentifier = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey).build();
this.targetNodeRef = new NodeRef(targetNodeIdentifier);
final long lifetimeNanos = TimeUnit.MILLISECONDS.toNanos(STATS_COLLECTION_MILLIS * NUMBER_OF_WAIT_CYCLES);
msgManager = new MultipartMessageManager(lifetimeNanos);
- flowStats = new FlowStatsTracker(flowStatsService, this, lifetimeNanos);
- flowTableStats = new FlowTableStatsTracker(flowTableStatsService, this, lifetimeNanos);
- groupDescStats = new GroupDescStatsTracker(groupStatsService, this, lifetimeNanos);
- groupStats = new GroupStatsTracker(groupStatsService, this, lifetimeNanos);
- meterConfigStats = new MeterConfigStatsTracker(meterStatsService, this, lifetimeNanos);
- meterStats = new MeterStatsTracker(meterStatsService, this, lifetimeNanos);
- nodeConnectorStats = new NodeConnectorStatsTracker(portStatsService, this, lifetimeNanos);
- queueStats = new QueueStatsTracker(queueStatsService, this, lifetimeNanos);
+ flowTableStats = new FlowTableStatsTracker(flowTableStatsService, this);
+ flowStats = new FlowStatsTracker(flowStatsService, this, flowTableStats);
+ groupDescStats = new GroupDescStatsTracker(groupStatsService, this);
+ groupStats = new GroupStatsTracker(groupStatsService, this);
+ meterConfigStats = new MeterConfigStatsTracker(meterStatsService, this);
+ meterStats = new MeterStatsTracker(meterStatsService, this);
+ nodeConnectorStats = new NodeConnectorStatsTracker(portStatsService, this);
+ queueStats = new QueueStatsTracker(queueStatsService, this);
}
public NodeKey getTargetNodeKey() {
@Override
public DataModificationTransaction startDataModification() {
- return dps.beginTransaction();
+ DataModificationTransaction dmt = dps.beginTransaction();
+ dmt.registerListener(this.srScheduler);
+ return dmt;
}
public synchronized void updateGroupDescStats(TransactionAware transaction, List<GroupDescStats> list) {
public synchronized void updateAggregateFlowStats(TransactionAware transaction, AggregateFlowStatistics flowStats) {
final Short tableId = msgManager.isExpectedTableTransaction(transaction);
if (tableId != null) {
- final DataModificationTransaction trans = dps.beginTransaction();
+ final DataModificationTransaction trans = this.startDataModification();
InstanceIdentifier<Table> tableRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey)
.augmentation(FlowCapableNode.class).child(Table.class, new TableKey(tableId)).toInstance();
}
public synchronized void updateGroupFeatures(GroupFeatures notification) {
- final DataModificationTransaction trans = dps.beginTransaction();
+ final DataModificationTransaction trans = this.startDataModification();
final NodeBuilder nodeData = new NodeBuilder();
nodeData.setKey(targetNodeKey);
}
public synchronized void updateMeterFeatures(MeterFeatures features) {
- final DataModificationTransaction trans = dps.beginTransaction();
+ final DataModificationTransaction trans = this.startDataModification();
final NodeBuilder nodeData = new NodeBuilder();
nodeData.setKey(targetNodeKey);
}
public synchronized void cleanStaleStatistics() {
- final DataModificationTransaction trans = dps.beginTransaction();
- final long now = System.nanoTime();
-
- flowStats.cleanup(trans, now);
- groupDescStats.cleanup(trans, now);
- groupStats.cleanup(trans, now);
- meterConfigStats.cleanup(trans, now);
- meterStats.cleanup(trans, now);
- nodeConnectorStats.cleanup(trans, now);
- queueStats.cleanup(trans, now);
+ final DataModificationTransaction trans = this.startDataModification();
+
+ flowStats.cleanup(trans);
+ groupDescStats.cleanup(trans);
+ groupStats.cleanup(trans);
+ meterConfigStats.cleanup(trans);
+ meterStats.cleanup(trans);
+ nodeConnectorStats.cleanup(trans);
+ queueStats.cleanup(trans);
msgManager.cleanStaleTransactionIds();
trans.commit();
public synchronized void requestPeriodicStatistics() {
logger.debug("Send requests for statistics collection to node : {}", targetNodeKey);
- flowTableStats.request();
-
- // FIXME: it does not make sense to trigger this before sendAllFlowTablesStatisticsRequest()
- // comes back -- we do not have any tables anyway.
- final Collection<TableKey> tables = flowTableStats.getTables();
- logger.debug("Node {} supports {} table(s)", targetNodeKey, tables.size());
- for (final TableKey key : tables) {
- logger.debug("Send aggregate stats request for flow table {} to node {}", key.getId(), targetNodeKey);
- flowStats.requestAggregateFlows(key);
- }
-
- flowStats.requestAllFlowsAllTables();
- nodeConnectorStats.request();
- groupStats.request();
- groupDescStats.request();
- meterStats.request();
- meterConfigStats.request();
- queueStats.request();
+ this.srScheduler.addRequestToSchedulerQueue(flowTableStats);
+
+ this.srScheduler.addRequestToSchedulerQueue(flowStats);
+
+ this.srScheduler.addRequestToSchedulerQueue(nodeConnectorStats);
+
+ this.srScheduler.addRequestToSchedulerQueue(groupStats);
+
+ this.srScheduler.addRequestToSchedulerQueue(groupDescStats);
+
+ this.srScheduler.addRequestToSchedulerQueue(meterStats);
+
+ this.srScheduler.addRequestToSchedulerQueue(meterConfigStats);
+
+ this.srScheduler.addRequestToSchedulerQueue(queueStats);
}
-
+
public synchronized void start(final Timer timer) {
flowStats.start(dps);
groupDescStats.start(dps);
private static final Logger logger = LoggerFactory.getLogger(QueueStatsTracker.class);
private final OpendaylightQueueStatisticsService queueStatsService;
- QueueStatsTracker(OpendaylightQueueStatisticsService queueStatsService, final FlowCapableContext context, long lifetimeNanos) {
- super(context, lifetimeNanos);
+ QueueStatsTracker(OpendaylightQueueStatisticsService queueStatsService, final FlowCapableContext context) {
+ super(context);
this.queueStatsService = queueStatsService;
}
return queueEntry;
}
+ @Override
public void request() {
if (queueStatsService != null) {
GetAllQueuesStatisticsFromAllPortsInputBuilder input = new GetAllQueuesStatisticsFromAllPortsInputBuilder();
private OpendaylightFlowTableStatisticsService flowTableStatsService;
private OpendaylightQueueStatisticsService queueStatsService;
+
+ private final StatisticsRequestScheduler srScheduler;
public StatisticsProvider(final DataProviderService dataService) {
this.dps = Preconditions.checkNotNull(dataService);
+ this.srScheduler = new StatisticsRequestScheduler();
}
private final StatisticsListener updateCommiter = new StatisticsListener(StatisticsProvider.this);
portStatsService = rpcRegistry.getRpcService(OpendaylightPortStatisticsService.class);
flowTableStatsService = rpcRegistry.getRpcService(OpendaylightFlowTableStatisticsService.class);
queueStatsService = rpcRegistry.getRpcService(OpendaylightQueueStatisticsService.class);
-
+ this.srScheduler.start();
+
// Start receiving notifications
this.listenerRegistration = nps.registerNotificationListener(this.updateCommiter);
final NodeStatisticsHandler h = new NodeStatisticsHandler(dps, key,
flowStatsService, flowTableStatsService, groupStatsService,
- meterStatsService, portStatsService, queueStatsService);
+ meterStatsService, portStatsService, queueStatsService,srScheduler);
final NodeStatisticsHandler old = handlers.putIfAbsent(key.getId(), h);
if (old == null) {
spLogger.debug("Started node handler for {}", key.getId());
--- /dev/null
+/*
+ * Copyright IBM Corporation, 2013. 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.statistics.manager;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.TimeUnit;
+
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction.DataTransactionListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Main responsibility of the class is to check the MD-SAL data store read/write
+ * transaction accumulation level and send statistics request if number of pending
+ * read/write transactions are zero.
+ * @author avishnoi@in.ibm.com
+ *
+ */
+@SuppressWarnings("rawtypes")
+public class StatisticsRequestScheduler implements DataTransactionListener {
+
+ private static final Logger srsLogger = LoggerFactory.getLogger(StatisticsRequestScheduler.class);
+ private final Timer timer = new Timer("request-monitor", true);
+
+ // We need ordered retrieval, and O(1) contains operation
+ private final Map<AbstractStatsTracker,Integer> requestQueue =
+ Collections.synchronizedMap(new LinkedHashMap<AbstractStatsTracker,Integer>());
+
+ private Long PendingTransactions;
+
+ private long lastRequestTime = System.nanoTime();
+
+ private static final long REQUEST_MONITOR_INTERVAL = 1000;
+
+ private final TimerTask task = new TimerTask() {
+ @Override
+ public void run() {
+ long now = System.nanoTime();
+ if(now > lastRequestTime+TimeUnit.MILLISECONDS.toNanos(REQUEST_MONITOR_INTERVAL)){
+ requestStatistics();
+ }
+ }
+ };
+
+ public StatisticsRequestScheduler(){
+ PendingTransactions = (long) 0;
+ }
+
+ public void addRequestToSchedulerQueue(AbstractStatsTracker statsRequest){
+ requestQueue.put(statsRequest, null);
+ }
+
+ public AbstractStatsTracker getNextRequestFromSchedulerQueue(){
+ //Remove first element
+ AbstractStatsTracker stats = null;
+ synchronized(requestQueue){
+ Iterator<Map.Entry<AbstractStatsTracker, Integer>> nodesItr = requestQueue.entrySet().iterator();
+ if(nodesItr.hasNext()){
+ stats = nodesItr.next().getKey();
+ srsLogger.debug("{} chosen up for execution",stats.getNodeRef());
+ nodesItr.remove();
+ return stats;
+ }
+ }
+ return stats;
+ }
+
+ private void requestStatistics(){
+ AbstractStatsTracker stats = this.getNextRequestFromSchedulerQueue();
+ if(stats != null) {
+ stats.request();
+ stats.increaseRequestCounter();
+ }
+ }
+ @Override
+ public void onStatusUpdated(DataModificationTransaction transaction, TransactionStatus status) {
+
+ AbstractStatsTracker stats = null;
+ synchronized(PendingTransactions){
+ switch(status){
+ case SUBMITED:
+ this.PendingTransactions++;
+ break;
+ case COMMITED:
+ case FAILED:
+ this.PendingTransactions--;
+ if(PendingTransactions == 0){
+ lastRequestTime = System.nanoTime();
+ stats = this.getNextRequestFromSchedulerQueue();
+ }
+ srsLogger.debug("Pending MD-SAL transactions : {} & Scheduler queue size : {}",this.PendingTransactions,this.requestQueue.size());
+ break;
+ default:
+ break;
+ }
+ }
+ if(stats != null){
+ stats.request();
+ stats.increaseRequestCounter();
+ }
+ }
+
+ public void start(){
+ timer.schedule(task, 0, REQUEST_MONITOR_INTERVAL);
+ }
+}
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import io.netty.channel.ChannelFuture;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.management.ManagementFactory;
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+import javax.management.ObjectName;
+import javax.xml.parsers.ParserConfigurationException;
import junit.framework.Assert;
import org.apache.commons.io.IOUtils;
import org.junit.After;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
-
-import javax.management.ObjectName;
-import javax.xml.parsers.ParserConfigurationException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.management.ManagementFactory;
-import java.net.InetSocketAddress;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeoutException;
-
import static java.util.Collections.emptyList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
try {
c = sess.getStdout().read(bytes);
} catch (IOException e) {
- e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
+ throw new IllegalStateException("IO exception while reading data on ssh bridge.");
}
logger.info("got data:" + bytes);
if (c == 0) {
*/
package org.opendaylight.controller.netconf.ssh.authentication;
+import java.io.IOException;
import org.opendaylight.controller.sal.authorization.AuthResultEnum;
-import org.opendaylight.controller.sal.authorization.UserLevel;
import org.opendaylight.controller.usermanager.IUserManager;
-import org.opendaylight.controller.usermanager.UserConfig;
-
-import java.util.ArrayList;
-import java.util.List;
-
import static com.google.common.base.Preconditions.checkNotNull;
public class AuthProvider implements AuthProviderInterface {
- private static IUserManager um; //FIXME static mutable state, no locks
- private static final String DEFAULT_USER = "netconf";
- private static final String DEFAULT_PASSWORD = "netconf";
+ private IUserManager um;
private final String pem;
- public AuthProvider(IUserManager ium, String pemCertificate) throws Exception {
+ public AuthProvider(IUserManager ium, String pemCertificate) throws IllegalArgumentException, IOException {
checkNotNull(pemCertificate, "Parameter 'pemCertificate' is null");
- AuthProvider.um = ium;
- if (AuthProvider.um == null) {
- throw new Exception("No usermanager service available.");
- }
-
- List<String> roles = new ArrayList<String>(1);
- roles.add(UserLevel.SYSTEMADMIN.toString());
- AuthProvider.um.addLocalUser(new UserConfig(DEFAULT_USER, DEFAULT_PASSWORD, roles)); //FIXME hardcoded auth
+ checkNotNull(ium, "No user manager service available.");
+ this.um = ium;
pem = pemCertificate;
}
@Override
public boolean authenticated(String username, String password) {
- if (AuthProvider.um == null) {
- throw new IllegalStateException("No usermanager service available.");
- }
- AuthResultEnum authResult = AuthProvider.um.authenticate(username, password);
+ AuthResultEnum authResult = this.um.authenticate(username, password);
return authResult.equals(AuthResultEnum.AUTH_ACCEPT) || authResult.equals(AuthResultEnum.AUTH_ACCEPT_LOC);
}
@Override
public void removeUserManagerService() {
- AuthProvider.um = null;
+ this.um = null;
}
@Override
public void addUserManagerService(IUserManager userManagerService) {
- AuthProvider.um = userManagerService;
+ this.um = userManagerService;
}
}
package org.opendaylight.controller.netconf.ssh.osgi;
import com.google.common.base.Optional;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.opendaylight.controller.netconf.ssh.NetconfSSHServer;
import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
import org.opendaylight.controller.netconf.ssh.authentication.PEMGenerator;
import org.opendaylight.controller.netconf.util.osgi.NetconfConfigUtil;
+import org.opendaylight.controller.sal.authorization.UserLevel;
import org.opendaylight.controller.usermanager.IUserManager;
+import org.opendaylight.controller.usermanager.UserConfig;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.net.InetSocketAddress;
+import static com.google.common.base.Preconditions.checkNotNull;
/**
* Activator for netconf SSH bundle which creates SSH bridge between netconf client and netconf server. Activator
* starts SSH Server in its own thread. This thread is closed when activator calls stop() method. Server opens socket
- * and listen for client connections. Each client connection creation is handled in separate
+ * and listens for client connections. Each client connection creation is handled in separate
* {@link org.opendaylight.controller.netconf.ssh.threads.SocketThread} thread.
* This thread creates two additional threads {@link org.opendaylight.controller.netconf.ssh.threads.IOThread}
* forwarding data from/to client.IOThread closes servers session and server connection when it gets -1 on input stream.
private static final String EXCEPTION_MESSAGE = "Netconf ssh bridge is not available.";
private IUserManager iUserManager;
private BundleContext context = null;
+ private Optional<String> defaultPassword;
+ private Optional<String> defaultUser;
private ServiceTrackerCustomizer<IUserManager, IUserManager> customizer = new ServiceTrackerCustomizer<IUserManager, IUserManager>(){
@Override
@Override
public void stop(BundleContext context) throws IOException {
+ if (this.defaultUser.isPresent()){
+ this.iUserManager.removeLocalUser(this.defaultUser.get());
+ }
if (server != null){
server.stop();
logger.trace("Netconf SSH bridge is down ...");
}
}
private void startSSHServer() throws IllegalStateException, IOException {
+ checkNotNull(this.iUserManager, "No user manager service available.");
logger.trace("Starting netconf SSH bridge.");
Optional<InetSocketAddress> sshSocketAddressOptional = NetconfConfigUtil.extractSSHNetconfAddress(context, EXCEPTION_MESSAGE);
InetSocketAddress tcpSocketAddress = NetconfConfigUtil.extractTCPNetconfAddress(context,
EXCEPTION_MESSAGE, true);
if (sshSocketAddressOptional.isPresent()){
- String path = NetconfConfigUtil.getPrivateKeyPath(context);
- path = path.replace("\\", "/"); // FIXME: shouldn't this convert lines to system dependent path separator?
+ String path = FilenameUtils.separatorsToSystem(NetconfConfigUtil.getPrivateKeyPath(context));
if (path.equals("")){
throw new IllegalStateException("Missing netconf.ssh.pk.path key in configuration file.");
}
File privateKeyFile = new File(path);
String privateKeyPEMString = null;
if (privateKeyFile.exists() == false) {
- // generate & save to file
try {
privateKeyPEMString = PEMGenerator.generateTo(privateKeyFile);
} catch (Exception e) {
- logger.error("Exception occured while generating PEM string {}",e);
+ logger.error("Exception occurred while generating PEM string {}",e);
}
} else {
// read from file
}
AuthProvider authProvider = null;
try {
+ this.defaultPassword = NetconfConfigUtil.getSSHDefaultPassword(context);
+ this.defaultUser = NetconfConfigUtil.getSSHDefaultUser(context);
+ // Since there is no user data store yet (ldap, ...) this adds default user/password to UserManager
+ // if these parameters are set in netconf configuration file.
+ if (defaultUser.isPresent() &&
+ defaultPassword.isPresent()){
+ logger.trace(String.format("Default username and password for netconf ssh bridge found. Adding user %s to user manager.",defaultUser.get()));
+ List<String> roles = new ArrayList<String>(1);
+ roles.add(UserLevel.SYSTEMADMIN.toString());
+ iUserManager.addLocalUser(new UserConfig(defaultUser.get(), defaultPassword.get(), roles));
+ }
authProvider = new AuthProvider(iUserManager, privateKeyPEMString);
} catch (Exception e) {
logger.error("Error instantiating AuthProvider {}",e);
package org.opendaylight.controller.netconf.util.osgi;
import com.google.common.base.Optional;
+import com.google.common.base.Strings;
+import java.net.InetSocketAddress;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
-import java.net.InetSocketAddress;
-
import static com.google.common.base.Preconditions.checkNotNull;
public final class NetconfConfigUtil {
private static final String ADDRESS_SUFFIX_PROP = ".address";
private static final String CLIENT_PROP = ".client";
private static final String PRIVATE_KEY_PATH_PROP = ".pk.path";
+ private static final String SSH_DEFAULT_USER = ".default.user";
+ private static final String SSH_DEFAULT_PASSWORD = ".default.password";
private static final String CONNECTION_TIMEOUT_MILLIS_PROP = "connectionTimeoutMillis";
private static final long DEFAULT_TIMEOUT_MILLIS = 5000;
public static String getPrivateKeyPath(BundleContext context){
return getPropertyValue(context,PREFIX_PROP + InfixProp.ssh +PRIVATE_KEY_PATH_PROP);
}
+ public static Optional<String> getSSHDefaultUser(BundleContext context){
+ return getOptionalPropertyValue(context,PREFIX_PROP + InfixProp.ssh +SSH_DEFAULT_USER);
+ }
+ public static Optional<String> getSSHDefaultPassword(BundleContext context){
+ return getOptionalPropertyValue(context,PREFIX_PROP + InfixProp.ssh +SSH_DEFAULT_PASSWORD);
+ }
+
private static String getPropertyValue(BundleContext context, String propertyName){
String propertyValue = context.getProperty(propertyName);
if (propertyValue == null){
}
return propertyValue;
}
+ private static Optional<String> getOptionalPropertyValue(BundleContext context, String propertyName){
+ String propertyValue = context.getProperty(propertyName);
+ if (Strings.isNullOrEmpty(propertyValue)){
+ return Optional.absent();
+ }
+ return Optional.fromNullable(propertyValue);
+ }
/**
* @param context
* from which properties are being read.