Merge "524 bug - %2F slashes translation behind mount point (unit test)"
authorTony Tkacik <ttkacik@cisco.com>
Tue, 8 Apr 2014 09:44:35 +0000 (09:44 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 8 Apr 2014 09:44:35 +0000 (09:44 +0000)
100 files changed:
opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/ArpHandler.java
opendaylight/commons/opendaylight/pom.xml
opendaylight/commons/protocol-framework/pom.xml
opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyFactoryModule.java [new file with mode: 0644]
opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyFactoryModuleFactory.java [new file with mode: 0644]
opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyFactoryModule.java [new file with mode: 0644]
opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyFactoryModuleFactory.java [new file with mode: 0644]
opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyFactoryModule.java [new file with mode: 0644]
opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyFactoryModuleFactory.java [new file with mode: 0644]
opendaylight/commons/protocol-framework/src/main/yang/odl-protocol-framework-cfg.yang [new file with mode: 0644]
opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/GlobalEventExecutorUtil.java [new file with mode: 0644]
opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyModuleTest.java [new file with mode: 0644]
opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyModuleTest.java [new file with mode: 0644]
opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyModuleTest.java [new file with mode: 0644]
opendaylight/config/config-persister-directory-adapter/pom.xml [deleted file]
opendaylight/config/config-persister-directory-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/directory/DirectoryPersister.java [deleted file]
opendaylight/config/config-persister-directory-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/directory/DirectoryStorageAdapter.java [deleted file]
opendaylight/config/config-persister-directory-adapter/src/main/resources/footer.txt [deleted file]
opendaylight/config/config-persister-directory-adapter/src/main/resources/header.txt [deleted file]
opendaylight/config/config-persister-directory-adapter/src/main/resources/middle.txt [deleted file]
opendaylight/config/config-persister-directory-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/directory/DirectoryStorageAdapterTest.java [deleted file]
opendaylight/config/config-persister-directory-adapter/src/test/resources/oneFile/controller.config.txt [deleted file]
opendaylight/config/config-persister-directory-adapter/src/test/resources/oneFileExpected/expectedCapabilities.txt [deleted file]
opendaylight/config/config-persister-directory-adapter/src/test/resources/oneFileExpected/expectedSnapshot.xml [deleted file]
opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFiles/controller.config1.txt [deleted file]
opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFiles/controller.config2.txt [deleted file]
opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected1/expectedCapabilities.txt [deleted file]
opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected1/expectedSnapshot.xml [deleted file]
opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected2/expectedCapabilities.txt [deleted file]
opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected2/expectedSnapshot.xml [deleted file]
opendaylight/config/config-persister-directory-autodetect-adapter/pom.xml [deleted file]
opendaylight/config/config-persister-directory-autodetect-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/directory/autodetect/AutodetectDirectoryPersister.java [deleted file]
opendaylight/config/config-persister-directory-autodetect-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/directory/autodetect/AutodetectDirectoryStorageAdapter.java [deleted file]
opendaylight/config/config-persister-directory-autodetect-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/directory/autodetect/FileType.java [deleted file]
opendaylight/config/config-persister-directory-autodetect-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/directory/autodetect/AutodetectDirectoryPersisterTest.java [deleted file]
opendaylight/config/config-persister-directory-autodetect-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/directory/autodetect/FileTypeTest.java [deleted file]
opendaylight/config/config-persister-directory-autodetect-adapter/src/test/resources/bad_controller.xml.config [deleted file]
opendaylight/config/config-persister-directory-autodetect-adapter/src/test/resources/combined/1controller.txt.config [deleted file]
opendaylight/config/config-persister-directory-autodetect-adapter/src/test/resources/combined/2controller.xml.config [deleted file]
opendaylight/config/config-persister-directory-autodetect-adapter/src/test/resources/test.txt.config [deleted file]
opendaylight/config/config-persister-directory-autodetect-adapter/src/test/resources/test.xml.config [deleted file]
opendaylight/config/config-persister-directory-autodetect-adapter/src/test/resources/unknown.config [deleted file]
opendaylight/config/config-persister-directory-xml-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/directory/xml/XmlDirectoryPersister.java
opendaylight/config/config-persister-directory-xml-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/directory/xml/XmlDirectoryStorageAdapter.java
opendaylight/config/config-persister-directory-xml-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/directory/xml/DirectoryStorageAdapterTest.java
opendaylight/config/config-persister-directory-xml-adapter/src/test/resources/twoFiles/controller.config2.xml2 [moved from opendaylight/config/config-persister-directory-xml-adapter/src/test/resources/twoFiles/controller.config2.xml with 100% similarity]
opendaylight/config/config-persister-directory-xml-adapter/src/test/resources/twoFiles_corrupt/controller.config1.xml [new file with mode: 0644]
opendaylight/config/config-persister-directory-xml-adapter/src/test/resources/twoFiles_corrupt/controller.config2.xml [new file with mode: 0644]
opendaylight/config/config-persister-file-adapter/pom.xml [deleted file]
opendaylight/config/config-persister-file-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/file/FileStorageAdapter.java [deleted file]
opendaylight/config/config-persister-file-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/file/FileStorageAdapterTest.java [deleted file]
opendaylight/config/pom.xml
opendaylight/distribution/opendaylight/pom.xml
opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini
opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.xml
opendaylight/md-sal/clustered-data-store/integrationtest/pom.xml
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/MDFlowMapping.xtend
opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/FlowCapableInventoryProvider.xtend
opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/NodeChangeCommiter.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/pom.xml
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/ForwardedCompatibleDataBrokerImplModule.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/ForwardedCompatibleDataBrokerImplModuleFactory.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractForwardedDataBroker.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractForwardedTransaction.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/BindingToNormalizedNodeCodec.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/ForwardedBackwardsCompatibleDataBroker.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/ForwardedBindingDataBroker.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/LegacyDataChangeEvent.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentConnector.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/forward/DomForwardedBroker.java
opendaylight/md-sal/sal-binding-broker/src/main/yang/opendaylight-binding-broker-impl.yang
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug02Test.java
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/PutAugmentationTest.java
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java
opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/util/compat/DataNormalizationOperation.java
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/util/compat/DataNormalizer.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMDataBrokerImpl.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ChangeListenerNotifyTask.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DOMImmutableDataChangeEvent.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataChangeEventResolver.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStore.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/StoreUtils.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/ListenerRegistrationNode.java
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/pom.xml
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend
opendaylight/md-sal/test/sal-rest-connector-it/pom.xml
opendaylight/md-sal/test/sal-rest-connector-it/src/test/java/org/opendaylight/controller/test/restconf/it/ServiceProviderController.java
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusher.java
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/PersisterAggregator.java
opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterTest.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/NetconfUtil.java
opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/NetconfUtilTest.java
opendaylight/netconf/pom.xml
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSubnet.java
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSubnetsNorthbound.java
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/DiscoveryService.java
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowConverter.java

index 083e2ed0e9784d31355ceaac1a995bde2c386278..e5491824397c1678b26b819b4e2691d0295f95a6 100644 (file)
@@ -64,6 +64,31 @@ import org.opendaylight.controller.topologymanager.ITopologyManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+/**
+ * The ArpHandler offers services to react on ARP requests and replies
+ * sent by network hosts. Moreover it allows for creating ARP messages
+ * by the controller itself.
+ *
+ * The ARP Handler on ODL doesn't use the requester MAC address in
+ * order to avoid to have to build a spanning tree where to forward
+ * ARP Requests. The ARP requests are broadcast packets so in order to
+ * reach everywhere need to be flooded, when you flood in a network
+ * that is not a tree (all the networks has some level of redundancy)
+ * that would create forwarding loops without a spanning tree. Given
+ * the need is only to send out the ARP requests toward all the hosts
+ * we actually don't need to implement a flooding mechanism in software
+ * (which would be expensive) we just send out the ARP request toward
+ * all the ports that are suspected to be host ports on all the
+ * switches (from the controller). Now the condition for which a port
+ * is marked as host port could potentially be incorrect so when the
+ * controller sends out the ARP Request that could come back to the
+ * controller and could cause another request not needed. So changing
+ * the source MAC address of the request to be the one of the controller,
+ * controller can protect itself from honoring twice the same request.
+ * This enables an ARP handler resolution, without the need of spanning
+ * tree and limiting software flooding to the minimum required.
+ */
+
 public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateAware<ARPEvent, Boolean> {
     private static final Logger log = LoggerFactory.getLogger(ArpHandler.class);
     static final String ARP_EVENT_CACHE_NAME = "arphandler.arpRequestReplyEvent";
index e7c7bbe6370c1750d88d454c8faffdd4ac2eadae..1e06679a3b9e929dc77ba5061db02c6aa3dcda11 100644 (file)
           <artifactId>config-persister-api</artifactId>
           <version>${config.version}</version>
         </dependency>
-        <dependency>
-          <groupId>org.opendaylight.controller</groupId>
-          <artifactId>config-persister-file-adapter</artifactId>
-          <version>${config.version}</version>
-        </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>config-persister-file-xml-adapter</artifactId>
           <version>${config.version}</version>
         </dependency>
-        <dependency>
-          <groupId>org.opendaylight.controller</groupId>
-          <artifactId>config-persister-directory-adapter</artifactId>
-          <version>${config.version}</version>
-        </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>config-persister-directory-xml-adapter</artifactId>
           <version>${config.version}</version>
         </dependency>
-        <dependency>
-          <groupId>org.opendaylight.controller</groupId>
-          <artifactId>config-persister-directory-autodetect-adapter</artifactId>
-          <version>${config.version}</version>
-        </dependency>
 
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
index a03518235b6521ba1c297a7b04ab8db87e0ed872..650d2dd35bb22586bcd064bc583402a90787b457 100644 (file)
         <maven>3.0.4</maven>
     </prerequisites>
 
+    <properties>
+        <jmxGeneratorPath>${project.build.directory}/generated-sources/config</jmxGeneratorPath>
+        <salGeneratorPath>${project.build.directory}/generated-sources/sal</salGeneratorPath>
+    </properties>
+
     <dependencies>
         <dependency>
             <groupId>io.netty</groupId>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>netty-config-api</artifactId>
+        </dependency>
 
         <!-- Testing dependencies -->
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-manager</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-manager</artifactId>
+            <version>${config.version}</version>
+            <scope>test</scope>
+            <type>test-jar</type>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-util</artifactId>
+            <version>${config.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>netty-event-executor-config</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
                     </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.controller.config.yangjmxgenerator.plugin.JMXGenerator
+                                  </codeGeneratorClass>
+                                  <outputBaseDir>${jmxGeneratorPath}</outputBaseDir>
+                                  <additionalConfiguration>
+                                      <namespaceToPackage1>
+                                          urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang
+                                      </namespaceToPackage1>
+                                  </additionalConfiguration>
+                              </generator>
+                              <generator>
+                                  <codeGeneratorClass>
+                                      org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl
+                                  </codeGeneratorClass>
+                                  <outputBaseDir>
+                                     ${salGeneratorPath}
+                                  </outputBaseDir>
+                              </generator>
+                          </codeGenerators>
+                          <inspectDependencies>true</inspectDependencies>
+                      </configuration>
+                  </execution>
+              </executions>
+              <dependencies>
+                  <dependency>
+                      <groupId>org.opendaylight.controller</groupId>
+                      <artifactId>yang-jmx-generator-plugin</artifactId>
+                      <version>${config.version}</version>
+                  </dependency>
+                  <dependency>
+                      <groupId>org.opendaylight.yangtools</groupId>
+                      <artifactId>maven-sal-api-gen-plugin</artifactId>
+                      <version>${yangtools.version}</version>
+                  </dependency>
+              </dependencies>
+          </plugin>
+          <plugin>
+              <groupId>org.codehaus.mojo</groupId>
+              <artifactId>build-helper-maven-plugin</artifactId>
+              <executions>
+                  <execution>
+                      <id>add-source</id>
+                      <phase>generate-sources</phase>
+                      <goals>
+                          <goal>add-source</goal>
+                      </goals>
+                      <configuration>
+                          <sources>
+                              <source>${jmxGeneratorPath}</source>
+                              <source>${salGeneratorPath}</source>
+                          </sources>
+                      </configuration>
+                  </execution>
+              </executions>
+          </plugin>
         </plugins>
     </build>
 </project>
diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyFactoryModule.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyFactoryModule.java
new file mode 100644 (file)
index 0000000..a97f65e
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * 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.config.yang.protocol.framework;
+
+import io.netty.util.concurrent.EventExecutor;
+
+import org.opendaylight.controller.config.api.JmxAttributeValidationException;
+import org.opendaylight.protocol.framework.NeverReconnectStrategy;
+import org.opendaylight.protocol.framework.ReconnectStrategy;
+import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
+
+/**
+*
+*/
+public final class NeverReconnectStrategyFactoryModule extends org.opendaylight.controller.config.yang.protocol.framework.AbstractNeverReconnectStrategyFactoryModule
+ {
+
+    public NeverReconnectStrategyFactoryModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public NeverReconnectStrategyFactoryModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+            NeverReconnectStrategyFactoryModule oldModule, java.lang.AutoCloseable oldInstance) {
+
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    protected void customValidation(){
+        JmxAttributeValidationException.checkNotNull(getTimeout(), "value is not set.", timeoutJmxAttribute);
+        JmxAttributeValidationException.checkCondition(getTimeout() >= 0, "value " + getTimeout() + " is less than 0",
+                timeoutJmxAttribute);
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        return new NeverReconnectStrategyFactoryCloseable(getExecutorDependency(), getTimeout());
+    }
+
+    private static final class NeverReconnectStrategyFactoryCloseable implements ReconnectStrategyFactory, AutoCloseable {
+
+        private final EventExecutor executor;
+        private final int timeout;
+
+        public NeverReconnectStrategyFactoryCloseable(final EventExecutor executor, final int timeout) {
+            this.executor = executor;
+            this.timeout = timeout;
+        }
+
+        @Override
+        public void close() throws Exception {
+            // no-op
+        }
+
+        @Override
+        public ReconnectStrategy createReconnectStrategy() {
+            return new NeverReconnectStrategy(this.executor, this.timeout);
+        }
+
+    }
+}
diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyFactoryModuleFactory.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyFactoryModuleFactory.java
new file mode 100644 (file)
index 0000000..bbdc939
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * 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.config.yang.protocol.framework;
+
+/**
+*
+*/
+public class NeverReconnectStrategyFactoryModuleFactory extends org.opendaylight.controller.config.yang.protocol.framework.AbstractNeverReconnectStrategyFactoryModuleFactory
+{
+
+
+}
diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyFactoryModule.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyFactoryModule.java
new file mode 100644 (file)
index 0000000..580a53b
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * 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.config.yang.protocol.framework;
+
+import io.netty.util.concurrent.EventExecutor;
+
+import org.opendaylight.controller.config.api.JmxAttributeValidationException;
+import org.opendaylight.protocol.framework.ReconnectImmediatelyStrategy;
+import org.opendaylight.protocol.framework.ReconnectStrategy;
+import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
+
+/**
+*
+*/
+public final class ReconnectImmediatelyStrategyFactoryModule extends org.opendaylight.controller.config.yang.protocol.framework.AbstractReconnectImmediatelyStrategyFactoryModule
+ {
+
+    public ReconnectImmediatelyStrategyFactoryModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public ReconnectImmediatelyStrategyFactoryModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+            ReconnectImmediatelyStrategyFactoryModule oldModule, java.lang.AutoCloseable oldInstance) {
+
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    protected void customValidation(){
+        JmxAttributeValidationException.checkNotNull(getTimeout(), "value is not set.", timeoutJmxAttribute);
+        JmxAttributeValidationException.checkCondition(getTimeout() >= 0, "value " + getTimeout() + " is less than 0",
+                timeoutJmxAttribute);
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        return new ReconnectImmediatelyStrategyFactoryCloseable(getExecutorDependency(), getTimeout());
+    }
+
+    private static final class ReconnectImmediatelyStrategyFactoryCloseable implements ReconnectStrategyFactory, AutoCloseable {
+
+        private final EventExecutor executor;
+        private final int timeout;
+
+        public ReconnectImmediatelyStrategyFactoryCloseable(final EventExecutor executor, final int timeout) {
+            this.executor = executor;
+            this.timeout = timeout;
+        }
+
+        @Override
+        public void close() throws Exception {
+            // no-op
+        }
+
+        @Override
+        public ReconnectStrategy createReconnectStrategy() {
+            return new ReconnectImmediatelyStrategy(this.executor, this.timeout);
+        }
+
+    }
+}
diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyFactoryModuleFactory.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyFactoryModuleFactory.java
new file mode 100644 (file)
index 0000000..6e72458
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * 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.config.yang.protocol.framework;
+
+/**
+*
+*/
+public class ReconnectImmediatelyStrategyFactoryModuleFactory extends org.opendaylight.controller.config.yang.protocol.framework.AbstractReconnectImmediatelyStrategyFactoryModuleFactory
+{
+
+
+}
diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyFactoryModule.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyFactoryModule.java
new file mode 100644 (file)
index 0000000..b8849c7
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * 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.config.yang.protocol.framework;
+
+import io.netty.util.concurrent.EventExecutor;
+
+import org.opendaylight.controller.config.api.JmxAttributeValidationException;
+import org.opendaylight.protocol.framework.ReconnectStrategy;
+import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
+import org.opendaylight.protocol.framework.TimedReconnectStrategy;
+
+import com.google.common.base.Preconditions;
+
+/**
+*
+*/
+public final class TimedReconnectStrategyFactoryModule extends org.opendaylight.controller.config.yang.protocol.framework.AbstractTimedReconnectStrategyFactoryModule
+ {
+
+    public TimedReconnectStrategyFactoryModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public TimedReconnectStrategyFactoryModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+            TimedReconnectStrategyFactoryModule oldModule, java.lang.AutoCloseable oldInstance) {
+
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    protected void customValidation(){
+        JmxAttributeValidationException.checkNotNull(getSleepFactor(), "value is not set.", sleepFactorJmxAttribute);
+        JmxAttributeValidationException.checkCondition(getSleepFactor().doubleValue() >= 1, "value " + getSleepFactor()
+                + " is less than 1", sleepFactorJmxAttribute);
+
+        JmxAttributeValidationException.checkNotNull(getConnectTime(), "value is not set.", connectTimeJmxAttribute);
+        JmxAttributeValidationException.checkCondition(getConnectTime() >= 0, "value " + getConnectTime()
+                + " is less than 0", connectTimeJmxAttribute);
+
+        JmxAttributeValidationException.checkNotNull(getMinSleep(), "value is not set.", minSleepJmxAttribute);
+        JmxAttributeValidationException.checkCondition(getMaxSleep() == null || getMinSleep() <= getMaxSleep(),
+                "value " + getMinSleep() + " is greter than MaxSleep " + getMaxSleep(), minSleepJmxAttribute);
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        return new TimedReconnectStrategyFactoryCloseable(getExecutorDependency(),
+                getConnectTime(), getMinSleep(), getSleepFactor().doubleValue(), getMaxSleep(), getMaxAttempts(),
+                getDeadline());
+    }
+
+    private static final class TimedReconnectStrategyFactoryCloseable implements ReconnectStrategyFactory, AutoCloseable {
+
+        private final EventExecutor executor;
+        private final Long deadline, maxAttempts, maxSleep;
+        private final double sleepFactor;
+        private final int connectTime;
+        private final long minSleep;
+
+        public TimedReconnectStrategyFactoryCloseable(final EventExecutor executor, final int connectTime, final long minSleep, final double sleepFactor,
+                final Long maxSleep, final Long maxAttempts, final Long deadline) {
+            Preconditions.checkArgument(maxSleep == null || minSleep <= maxSleep);
+            Preconditions.checkArgument(sleepFactor >= 1);
+            Preconditions.checkArgument(connectTime >= 0);
+            this.executor = Preconditions.checkNotNull(executor);
+            this.deadline = deadline;
+            this.maxAttempts = maxAttempts;
+            this.minSleep = minSleep;
+            this.maxSleep = maxSleep;
+            this.sleepFactor = sleepFactor;
+            this.connectTime = connectTime;
+        }
+
+        @Override
+        public void close() throws Exception {
+            // no-op
+        }
+
+        @Override
+        public ReconnectStrategy createReconnectStrategy() {
+            return new TimedReconnectStrategy(this.executor,
+                    this.connectTime, this.minSleep, this.sleepFactor, this.maxSleep, this.maxAttempts,
+                    this.deadline);
+        }
+
+    }
+}
diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyFactoryModuleFactory.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyFactoryModuleFactory.java
new file mode 100644 (file)
index 0000000..7f92e3a
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * 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.config.yang.protocol.framework;
+
+/**
+*
+*/
+public class TimedReconnectStrategyFactoryModuleFactory extends org.opendaylight.controller.config.yang.protocol.framework.AbstractTimedReconnectStrategyFactoryModuleFactory
+{
+
+
+}
diff --git a/opendaylight/commons/protocol-framework/src/main/yang/odl-protocol-framework-cfg.yang b/opendaylight/commons/protocol-framework/src/main/yang/odl-protocol-framework-cfg.yang
new file mode 100644 (file)
index 0000000..1856369
--- /dev/null
@@ -0,0 +1,151 @@
+// vi: set smarttab et sw=4 tabstop=4:
+module protocol-framework {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:protocol:framework";
+    prefix "pf";
+
+    import config { prefix config; revision-date 2013-04-05; }
+    import netty { prefix netty; revision-date 2013-11-19; }
+
+    organization "Cisco Systems, Inc.";
+
+    contact "Milos Fabian <milfabia@cisco.com>";
+
+    description
+        "This module contains the base YANG definitions for
+         protocol framework.
+
+        Copyright (c)2013 Cisco Systems, Inc. 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";
+
+    revision "2014-03-13" {
+        description
+            "Changed reconnect-strategy to reconnect-strategy-factory - represents ReconnectStrategyFactory.
+            reconnect-strategy-factory modules provides reconnect-strategy-factory service.";
+    }
+
+    revision "2013-11-09" {
+        description
+            "Initial revision";
+    }
+
+    identity reconnect-strategy-factory {
+        description
+            "Service representing a reconnect strategy factory.";
+
+        base "config:service-type";
+        config:java-class "org.opendaylight.protocol.framework.ReconnectStrategyFactory";
+    }
+
+    identity never-reconnect-strategy-factory {
+        base config:module-type;
+        config:provided-service reconnect-strategy-factory;
+        config:java-name-prefix NeverReconnectStrategyFactory;
+    }
+
+    augment "/config:modules/config:module/config:configuration" {
+        case never-reconnect-strategy-factory {
+            when "/config:modules/config:module/config:type = 'never-reconnect-strategy-factory'";
+
+            leaf timeout {
+                mandatory true;
+                type int32;
+            }
+
+            container executor {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity netty:netty-event-executor;
+                    }
+                }
+            }
+        }
+    }
+
+    identity reconnect-immediately-strategy-factory {
+        base config:module-type;
+        config:provided-service reconnect-strategy-factory;
+        config:java-name-prefix ReconnectImmediatelyStrategyFactory;
+    }
+
+    augment "/config:modules/config:module/config:configuration" {
+        case reconnect-immediately-strategy-factory {
+            when "/config:modules/config:module/config:type = 'reconnect-immediately-strategy-factory'";
+
+            leaf timeout {
+                mandatory true;
+                type int32;
+            }
+
+            container executor {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity netty:netty-event-executor;
+                    }
+                }
+            }
+        }
+    }
+
+    identity timed-reconnect-strategy-factory {
+        base config:module-type;
+        config:provided-service reconnect-strategy-factory;
+        config:java-name-prefix TimedReconnectStrategyFactory;
+    }
+
+    augment "/config:modules/config:module/config:configuration" {
+        case timed-reconnect-strategy-factory {
+            when "/config:modules/config:module/config:type = 'timed-reconnect-strategy-factory'";
+
+            leaf deadline {
+                type int64;
+                units "epoch nanoseconds";
+            }
+
+            leaf max-attempts {
+                mandatory true;
+                type int64;
+            }
+
+            leaf max-sleep {
+                mandatory true;
+                type int64;
+                units "milliseconds";
+            }
+
+            leaf min-sleep {
+                mandatory true;
+                type int64;
+                units "milliseconds";
+            }
+
+            leaf sleep-factor {
+                mandatory true;
+                type decimal64 {
+                    fraction-digits 2;
+                }
+            }
+
+            leaf connect-time {
+                mandatory true;
+                type int32;
+                units "milliseconds";
+            }
+
+            container executor {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity netty:netty-event-executor;
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/GlobalEventExecutorUtil.java b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/GlobalEventExecutorUtil.java
new file mode 100644 (file)
index 0000000..695e36c
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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.protocol.framework;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
+
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+import org.opendaylight.controller.config.yang.netty.eventexecutor.GlobalEventExecutorModuleFactory;
+
+final class GlobalEventExecutorUtil {
+
+    private GlobalEventExecutorUtil() {
+        throw new UnsupportedOperationException();
+    }
+
+    public static ObjectName create(final ConfigTransactionJMXClient transaction) throws InstanceAlreadyExistsException {
+        try {
+            return transaction.lookupConfigBean(GlobalEventExecutorModuleFactory.NAME,
+                    GlobalEventExecutorModuleFactory.SINGLETON_NAME);
+        } catch (InstanceNotFoundException e) {
+            try {
+                return transaction.createModule(GlobalEventExecutorModuleFactory.NAME,
+                        GlobalEventExecutorModuleFactory.SINGLETON_NAME);
+            } catch (InstanceAlreadyExistsException e1) {
+                throw new IllegalStateException(e1);
+            }
+        }
+    }
+
+}
diff --git a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyModuleTest.java b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyModuleTest.java
new file mode 100644 (file)
index 0000000..d77c9aa
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * 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.protocol.framework;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.ObjectName;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+import org.opendaylight.controller.config.yang.netty.eventexecutor.GlobalEventExecutorModuleFactory;
+
+public class NeverReconnectStrategyModuleTest extends AbstractConfigTest {
+
+    private static final String INSTANCE_NAME = "never-reconect-strategy-factory-impl";
+    private static final String FACTORY_NAME = NeverReconnectStrategyFactoryModuleFactory.NAME;
+
+    @Before
+    public void setUp() throws Exception {
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(
+                new NeverReconnectStrategyFactoryModuleFactory(), new GlobalEventExecutorModuleFactory()));
+    }
+
+    @Test
+    public void testValidationExceptionTimeoutNotSet() throws Exception {
+        try {
+            createInstance(null);
+            fail();
+        } catch (ValidationException e) {
+            assertTrue(e.getMessage().contains("Timeout value is not set."));
+        }
+    }
+
+    @Test
+    public void testValidationExceptionTimeoutMinValue() throws Exception {
+        try {
+            createInstance(-1);
+            fail();
+        } catch (ValidationException e) {
+            assertTrue(e.getMessage().contains("is less than 0"));
+        }
+    }
+
+    @Test
+    public void testCreateBean() throws Exception {
+        final CommitStatus status = createInstance();
+        assertBeanCount(1, FACTORY_NAME);
+        assertStatus(status, 2, 0, 0);
+    }
+
+    @Test
+    public void testReusingOldInstance() throws Exception {
+        createInstance();
+        final ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+        assertBeanCount(1, FACTORY_NAME);
+        final CommitStatus status = transaction.commit();
+        assertBeanCount(1, FACTORY_NAME);
+        assertStatus(status, 0, 0, 2);
+    }
+
+    @Test
+    public void testReconfigure() throws Exception {
+        createInstance();
+        final ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+        assertBeanCount(1, FACTORY_NAME);
+        final NeverReconnectStrategyFactoryModuleMXBean mxBean = transaction.newMBeanProxy(
+                transaction.lookupConfigBean(FACTORY_NAME, INSTANCE_NAME), NeverReconnectStrategyFactoryModuleMXBean.class);
+        mxBean.setTimeout(200);
+        final CommitStatus status = transaction.commit();
+        assertBeanCount(1, FACTORY_NAME);
+        assertStatus(status, 0, 1, 1);
+    }
+
+    private CommitStatus createInstance() throws Exception {
+        return createInstance(500);
+    }
+
+    private CommitStatus createInstance(final Integer timeout) throws InstanceAlreadyExistsException,
+            ConflictingVersionException, ValidationException {
+        final ConfigTransactionJMXClient transaction = this.configRegistryClient.createTransaction();
+        createInstance(transaction, timeout);
+        return transaction.commit();
+    }
+
+    private static ObjectName createInstance(final ConfigTransactionJMXClient transaction, final Integer timeout)
+            throws InstanceAlreadyExistsException {
+        final ObjectName nameCreated = transaction.createModule(FACTORY_NAME, INSTANCE_NAME);
+        final NeverReconnectStrategyFactoryModuleMXBean mxBean = transaction.newMBeanProxy(nameCreated,
+                NeverReconnectStrategyFactoryModuleMXBean.class);
+        mxBean.setTimeout(timeout);
+        mxBean.setExecutor(GlobalEventExecutorUtil.create(transaction));
+        return nameCreated;
+    }
+
+}
diff --git a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyModuleTest.java b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyModuleTest.java
new file mode 100644 (file)
index 0000000..24a0e91
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * 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.protocol.framework;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.ObjectName;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+import org.opendaylight.controller.config.yang.netty.eventexecutor.GlobalEventExecutorModuleFactory;
+
+public class ReconnectImmediatelyStrategyModuleTest extends AbstractConfigTest {
+
+    private static final String INSTANCE_NAME = "reconnect-immediately-strategy-factory-impl";
+    private static final String FACTORY_NAME = ReconnectImmediatelyStrategyFactoryModuleFactory.NAME;
+
+    @Before
+    public void setUp() throws Exception {
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(
+                new ReconnectImmediatelyStrategyFactoryModuleFactory(), new GlobalEventExecutorModuleFactory()));
+    }
+
+    @Test
+    public void testValidationExceptionTimeoutNotSet() throws Exception {
+        try {
+            createInstance(null);
+            fail();
+        } catch (ValidationException e) {
+            assertTrue(e.getMessage().contains("Timeout value is not set."));
+        }
+    }
+
+    @Test
+    public void testValidationExceptionTimeoutMinValue() throws Exception {
+        try {
+            createInstance(-1);
+            fail();
+        } catch (ValidationException e) {
+            assertTrue(e.getMessage().contains("is less than 0"));
+        }
+    }
+
+    @Test
+    public void testCreateBean() throws Exception {
+        final CommitStatus status = createInstance();
+        assertBeanCount(1, FACTORY_NAME);
+        assertStatus(status, 2, 0, 0);
+    }
+
+    @Test
+    public void testReusingOldInstance() throws Exception {
+        createInstance();
+        final ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+        assertBeanCount(1, FACTORY_NAME);
+        final CommitStatus status = transaction.commit();
+        assertBeanCount(1, FACTORY_NAME);
+        assertStatus(status, 0, 0, 2);
+    }
+
+    @Test
+    public void testReconfigure() throws Exception {
+        createInstance();
+        final ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+        assertBeanCount(1, FACTORY_NAME);
+        final ReconnectImmediatelyStrategyFactoryModuleMXBean mxBean = transaction.newMBeanProxy(
+                transaction.lookupConfigBean(FACTORY_NAME, INSTANCE_NAME),
+                ReconnectImmediatelyStrategyFactoryModuleMXBean.class);
+        mxBean.setTimeout(200);
+        final CommitStatus status = transaction.commit();
+        assertBeanCount(1, FACTORY_NAME);
+        assertStatus(status, 0, 1, 1);
+    }
+
+    private CommitStatus createInstance() throws Exception {
+        return createInstance(500);
+    }
+
+    private CommitStatus createInstance(final Integer timeout) throws Exception {
+        final ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+        createInstance(transaction, timeout);
+        return transaction.commit();
+    }
+
+    private static ObjectName createInstance(final ConfigTransactionJMXClient transaction, final Integer timeout)
+            throws InstanceAlreadyExistsException {
+        final ObjectName nameCreated = transaction.createModule(FACTORY_NAME, INSTANCE_NAME);
+        final ReconnectImmediatelyStrategyFactoryModuleMXBean mxBean = transaction.newMBeanProxy(nameCreated,
+                ReconnectImmediatelyStrategyFactoryModuleMXBean.class);
+        mxBean.setTimeout(timeout);
+        mxBean.setExecutor(GlobalEventExecutorUtil.create(transaction));
+        return nameCreated;
+    }
+
+}
diff --git a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyModuleTest.java b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyModuleTest.java
new file mode 100644 (file)
index 0000000..d051a00
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * 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.protocol.framework;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.math.BigDecimal;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.ObjectName;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+import org.opendaylight.controller.config.yang.netty.eventexecutor.GlobalEventExecutorModuleFactory;
+
+public class TimedReconnectStrategyModuleTest extends AbstractConfigTest {
+
+    private static final String INSTANCE_NAME = "timed-reconect-stategy-facotry-impl";
+    private static final String FACTORY_NAME = TimedReconnectStrategyFactoryModuleFactory.NAME;
+
+    @Before
+    public void setUp() throws Exception {
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(
+                new TimedReconnectStrategyFactoryModuleFactory(), new GlobalEventExecutorModuleFactory()));
+    }
+
+    @Test
+    public void testValidationExceptionSleepFactorNotSet() throws Exception {
+        try {
+            createInstance(500, 100L, null, 500L, 10L, 10000L);
+            fail();
+        } catch (ValidationException e) {
+            assertTrue(e.getMessage().contains("SleepFactor value is not set."));
+        }
+    }
+
+    @Test
+    public void testValidationExceptionSleepFactorMinValue() throws Exception {
+        try {
+            createInstance(500, 100L, new BigDecimal(0.5), 500L, 10L, 10000L);
+            fail();
+        } catch (ValidationException e) {
+            assertTrue(e.getMessage().contains("is less than 1"));
+        }
+    }
+
+    @Test
+    public void testValidationExceptionConnectTimeNotSet() throws Exception {
+        try {
+            createInstance(null, 100L, new BigDecimal(1.0), 500L, 10L, 10000L);
+            fail();
+        } catch (ValidationException e) {
+            assertTrue(e.getMessage().contains("ConnectTime value is not set."));
+        }
+    }
+
+    @Test
+    public void testValidationExceptionConnectTimeMinValue() throws Exception {
+        try {
+            createInstance(-1, 100L, new BigDecimal(1.0), 500L, 10L, 10000L);
+            fail();
+        } catch (ValidationException e) {
+            assertTrue(e.getMessage().contains("is less than 0"));
+        }
+    }
+
+    @Test
+    public void testValidationExceptionMinSleepNotSet() throws Exception {
+        try {
+            createInstance(100, null, new BigDecimal(1.0), 100L, 10L, 10000L);
+            fail();
+        } catch (ValidationException e) {
+            assertTrue(e.getMessage().contains("MinSleep value is not set."));
+        }
+    }
+
+    @Test
+    public void testValidationExceptionMaxSleep() throws Exception {
+        try {
+            createInstance(100, 300L, new BigDecimal(1.0), 100L, 10L, 10000L);
+            fail();
+        } catch (ValidationException e) {
+            assertTrue(e.getMessage().contains("is greter than MaxSleep"));
+        }
+    }
+
+    @Test
+    public void testCreateBean() throws Exception {
+        final CommitStatus status = createInstance();
+        assertBeanCount(1, FACTORY_NAME);
+        assertStatus(status, 2, 0, 0);
+    }
+
+    @Test
+    public void testReusingOldInstance() throws Exception {
+        createInstance();
+        final ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+        assertBeanCount(1, FACTORY_NAME);
+        final CommitStatus status = transaction.commit();
+        assertBeanCount(1, FACTORY_NAME);
+        assertStatus(status, 0, 0, 2);
+    }
+
+    @Test
+    public void testReconfigure() throws Exception {
+        createInstance();
+        final ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+        assertBeanCount(1, FACTORY_NAME);
+        final TimedReconnectStrategyFactoryModuleMXBean mxBean = transaction.newMBeanProxy(
+                transaction.lookupConfigBean(FACTORY_NAME, INSTANCE_NAME), TimedReconnectStrategyFactoryModuleMXBean.class);
+        assertEquals(mxBean.getMinSleep(), new Long(100));
+        mxBean.setMinSleep(200L);
+        assertEquals(mxBean.getMinSleep(), new Long(200));
+        final CommitStatus status = transaction.commit();
+        assertBeanCount(1, FACTORY_NAME);
+        assertStatus(status, 0, 1, 1);
+
+    }
+
+    private CommitStatus createInstance() throws Exception {
+        return createInstance(500, 100L, new BigDecimal(1.0), 500L, 10L, 10000L);
+    }
+
+    private CommitStatus createInstance(final Integer connectTime, final Long minSleep, final BigDecimal sleepFactor,
+            final Long maxSleep, final Long maxAttempts, final Long deadline) throws ConflictingVersionException,
+            ValidationException, InstanceAlreadyExistsException {
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+        createInstance(transaction, INSTANCE_NAME, connectTime, minSleep, sleepFactor, maxSleep, maxAttempts, deadline);
+        return transaction.commit();
+    }
+
+    public static ObjectName createInstance(final ConfigTransactionJMXClient transaction, final String InstanceName)
+            throws Exception {
+        return createInstance(transaction, InstanceName, 500, 100L, new BigDecimal(1.0), 500L, 10L, 10000L);
+    }
+
+    private static ObjectName createInstance(final ConfigTransactionJMXClient transaction, final String instanceName,
+            final Integer connectTime, final Long minSleep, final BigDecimal sleepFactor, final Long maxSleep,
+            final Long maxAttempts, final Long deadline) throws InstanceAlreadyExistsException {
+        final ObjectName nameCreated = transaction.createModule(FACTORY_NAME, instanceName);
+        final TimedReconnectStrategyFactoryModuleMXBean mxBean = transaction.newMBeanProxy(nameCreated,
+                TimedReconnectStrategyFactoryModuleMXBean.class);
+        mxBean.setConnectTime(connectTime);
+        mxBean.setDeadline(deadline);
+        mxBean.setMaxAttempts(maxAttempts);
+        mxBean.setMaxSleep(maxSleep);
+        mxBean.setMinSleep(minSleep);
+        mxBean.setSleepFactor(sleepFactor);
+        mxBean.setExecutor(GlobalEventExecutorUtil.create(transaction));
+        return nameCreated;
+    }
+
+}
diff --git a/opendaylight/config/config-persister-directory-adapter/pom.xml b/opendaylight/config/config-persister-directory-adapter/pom.xml
deleted file mode 100644 (file)
index 86b8c4d..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <artifactId>config-subsystem</artifactId>
-        <groupId>org.opendaylight.controller</groupId>
-        <version>0.2.5-SNAPSHOT</version>
-        <relativePath>..</relativePath>
-    </parent>
-    <artifactId>config-persister-directory-adapter</artifactId>
-    <name>${project.artifactId}</name>
-    <packaging>bundle</packaging>
-
-    <dependencies>
-        <!-- compile dependencies -->
-        <dependency>
-            <groupId>${project.groupId}</groupId>
-            <artifactId>config-persister-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-lang3</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.google.guava</groupId>
-            <artifactId>guava</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>commons-io</groupId>
-            <artifactId>commons-io</artifactId>
-        </dependency>
-
-        <!-- test dependencies -->
-        <dependency>
-            <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>mockito-configuration</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>${project.groupId}</groupId>
-            <artifactId>config-persister-api</artifactId>
-            <type>test-jar</type>
-            <scope>test</scope>
-        </dependency>
-
-    </dependencies>
-
-    <build>
-        <plugins>
-            <!-- workaround for creating version according to OSGi specification (major.minor.micro[.qualifier] -->
-            <plugin>
-                <groupId>org.codehaus.groovy.maven</groupId>
-                <artifactId>gmaven-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <phase>generate-sources</phase>
-                        <goals>
-                            <goal>execute</goal>
-                        </goals>
-                        <configuration>
-                            <source>
-                                System.setProperty("osgiversion", "${project.version}".replace('-', '.'))
-                            </source>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Fragment-Host>${project.groupId}.config-persister-impl;bundle-version=${osgiversion}
-                        </Fragment-Host>
-                        <Provide-Capability>org.opendaylight.controller.config.persister.storage.adapter
-                        </Provide-Capability>
-                        <Import-Package>
-                            com.google.common.base,
-                            com.google.common.io,
-                            org.apache.commons.io,
-                            org.opendaylight.controller.config.persist.api,
-                            org.slf4j
-                        </Import-Package>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
diff --git a/opendaylight/config/config-persister-directory-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/directory/DirectoryPersister.java b/opendaylight/config/config-persister-directory-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/directory/DirectoryPersister.java
deleted file mode 100644 (file)
index eb8ef8c..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * 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.persist.storage.directory;
-
-import com.google.common.base.Charsets;
-import com.google.common.io.Files;
-import org.apache.commons.io.IOUtils;
-import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
-import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolderImpl;
-import org.opendaylight.controller.config.persist.api.Persister;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
-
-public class DirectoryPersister implements Persister {
-    private static final Logger logger = LoggerFactory.getLogger(DirectoryPersister.class);
-    private static final Charset ENCODING = Charsets.UTF_8;
-
-    public static final String MODULES_START = "//MODULES START";
-    static final String SERVICES_START = "//SERVICES START";
-    static final String CAPABILITIES_START = "//CAPABILITIES START";
-
-
-    private final File storage;
-    private static final String header, middle, footer;
-
-    static {
-        header = readResource("header.txt");
-        middle = readResource("middle.txt");
-        footer = readResource("footer.txt");
-    }
-
-    public DirectoryPersister(File storage) {
-        checkArgument(storage.exists() && storage.isDirectory(), "Storage directory does not exist: " + storage);
-        this.storage = storage;
-    }
-
-    private static String readResource(String resource) {
-        try {
-            return IOUtils.toString(DirectoryPersister.class.getResourceAsStream("/" + resource));
-        } catch (IOException e) {
-            throw new IllegalStateException("Cannot load " + resource, e);
-        }
-    }
-
-    @Override
-    public void persistConfig(ConfigSnapshotHolder holder) throws IOException {
-        throw new UnsupportedOperationException("This adapter is read only. Please set readonly=true on " + getClass());
-    }
-
-    @Override
-    public List<ConfigSnapshotHolder> loadLastConfigs() throws IOException {
-        File[] filesArray = storage.listFiles();
-        if (filesArray == null || filesArray.length == 0) {
-            return Collections.emptyList();
-        }
-        List<File> sortedFiles = new ArrayList<>(Arrays.asList(filesArray));
-        Collections.sort(sortedFiles);
-        // combine all found files
-        logger.debug("Reading files in following order: {}", sortedFiles);
-
-        List<ConfigSnapshotHolder> result = new ArrayList<>();
-        for (File file : sortedFiles) {
-            logger.trace("Adding file '{}' to combined result", file);
-
-            ConfigSnapshotHolder configSnapshotHolder = loadLastConfig(file);
-            result.add(configSnapshotHolder);
-        }
-        return result;
-    }
-
-    public static ConfigSnapshotHolder loadLastConfig(File file) throws IOException {
-        final MyLineProcessor lineProcessor = new MyLineProcessor(file.getAbsolutePath());
-        Files.readLines(file, ENCODING, lineProcessor);
-        return lineProcessor.getConfigSnapshotHolder(header, middle, footer);
-    }
-
-
-    @Override
-    public void close() {
-
-    }
-
-    @Override
-    public String toString() {
-        return "FileStorageAdapter [storage=" + storage + "]";
-    }
-}
-
-class MyLineProcessor implements com.google.common.io.LineProcessor<String> {
-    private final String fileNameForReporting;
-
-    private boolean inModules, inServices, inCapabilities;
-    private final StringBuffer modulesBuffer = new StringBuffer(), servicesBuilder = new StringBuffer();
-    private final SortedSet<String> caps = new TreeSet<>();
-
-    MyLineProcessor(String fileNameForReporting) {
-        this.fileNameForReporting = fileNameForReporting;
-    }
-
-    @Override
-    public String getResult() {
-        return null;
-    }
-
-    @Override
-    public boolean processLine(String line) throws IOException {
-
-        String lineWithNewLine = line + System.lineSeparator();
-        if (line.equals(DirectoryPersister.MODULES_START)) {
-            checkState(inModules == false && inServices == false && inCapabilities == false);
-            inModules = true;
-        } else if (line.equals(DirectoryPersister.SERVICES_START)) {
-            checkState(inModules == true && inServices == false && inCapabilities == false);
-            inModules = false;
-            inServices = true;
-        } else if (line.equals(DirectoryPersister.CAPABILITIES_START)) {
-            checkState(inModules == false && inServices == true && inCapabilities == false);
-            inServices = false;
-            inCapabilities = true;
-        } else if (inModules) {
-            modulesBuffer.append(lineWithNewLine);
-        } else if (inServices) {
-            servicesBuilder.append(lineWithNewLine);
-        } else {
-            caps.add(line);
-        }
-        return true;
-    }
-
-    private void checkFileConsistency(){
-        checkState(inCapabilities, "File %s is missing delimiters in this order: %s", fileNameForReporting,
-                Arrays.asList(DirectoryPersister.MODULES_START,
-                        DirectoryPersister.SERVICES_START,
-                        DirectoryPersister.CAPABILITIES_START));
-    }
-
-    String getModules() {
-        checkFileConsistency();
-        return modulesBuffer.toString();
-    }
-
-    String getServices() {
-        checkFileConsistency();
-        return servicesBuilder.toString();
-    }
-
-    SortedSet<String> getCapabilities() {
-        checkFileConsistency();
-        return caps;
-    }
-
-    ConfigSnapshotHolder getConfigSnapshotHolder(String header, String middle, String footer) {
-        String combinedSnapshot = header + getModules() + middle + getServices() + footer;
-        ConfigSnapshotHolder result = new ConfigSnapshotHolderImpl(combinedSnapshot, getCapabilities(), fileNameForReporting);
-        return result;
-    }
-
-}
-
diff --git a/opendaylight/config/config-persister-directory-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/directory/DirectoryStorageAdapter.java b/opendaylight/config/config-persister-directory-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/directory/DirectoryStorageAdapter.java
deleted file mode 100644 (file)
index 69c8fba..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.persist.storage.directory;
-
-import com.google.common.base.Preconditions;
-import org.opendaylight.controller.config.persist.api.Persister;
-import org.opendaylight.controller.config.persist.api.PropertiesProvider;
-import org.opendaylight.controller.config.persist.api.StorageAdapter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.File;
-
-/**
- * StorageAdapter that retrieves initial configuration from a directory. If multiple files are present, snapshot and
- * required capabilities will be merged together. Writing to this persister is not supported.
- */
-public class DirectoryStorageAdapter implements StorageAdapter {
-    private static final Logger logger = LoggerFactory.getLogger(DirectoryStorageAdapter.class);
-
-    public static final String DIRECTORY_STORAGE_PROP = "directoryStorage";
-
-
-    @Override
-    public Persister instantiate(PropertiesProvider propertiesProvider) {
-        String fileStorageProperty = propertiesProvider.getProperty(DIRECTORY_STORAGE_PROP);
-        Preconditions.checkNotNull(fileStorageProperty, "Unable to find " + propertiesProvider.getFullKeyForReporting(DIRECTORY_STORAGE_PROP));
-        File storage  = new File(fileStorageProperty);
-        logger.debug("Using {}", storage);
-        return new DirectoryPersister(storage);
-    }
-
-}
diff --git a/opendaylight/config/config-persister-directory-adapter/src/main/resources/footer.txt b/opendaylight/config/config-persister-directory-adapter/src/main/resources/footer.txt
deleted file mode 100644 (file)
index d4dcc62..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-    </services>
-</data>
diff --git a/opendaylight/config/config-persister-directory-adapter/src/main/resources/header.txt b/opendaylight/config/config-persister-directory-adapter/src/main/resources/header.txt
deleted file mode 100644 (file)
index 90ed41c..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
-    <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
diff --git a/opendaylight/config/config-persister-directory-adapter/src/main/resources/middle.txt b/opendaylight/config/config-persister-directory-adapter/src/main/resources/middle.txt
deleted file mode 100644 (file)
index f728cfd..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-    </modules>
-    <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
diff --git a/opendaylight/config/config-persister-directory-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/directory/DirectoryStorageAdapterTest.java b/opendaylight/config/config-persister-directory-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/directory/DirectoryStorageAdapterTest.java
deleted file mode 100644 (file)
index 278d0d2..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * 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.persist.storage.directory;
-
-import java.io.File;
-import java.util.Collections;
-import java.util.List;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import org.apache.commons.io.IOUtils;
-import org.junit.Test;
-import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
-import org.opendaylight.controller.config.persist.api.Persister;
-import org.opendaylight.controller.config.persist.test.PropertiesProviderTest;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-public class DirectoryStorageAdapterTest {
-    Persister tested;
-
-    private Persister instantiatePersisterFromAdapter(File file){
-        PropertiesProviderTest pp = new PropertiesProviderTest();
-        pp.addProperty("directoryStorage",file.getPath());
-        DirectoryStorageAdapter dsa = new DirectoryStorageAdapter();
-        return dsa.instantiate(pp);
-    }
-    @Test
-    public void testEmptyDirectory() throws Exception {
-        File folder = new File("target/emptyFolder");
-        folder.mkdir();
-
-        tested =  instantiatePersisterFromAdapter(folder);
-        assertEquals(Collections.<ConfigSnapshotHolder>emptyList(), tested.loadLastConfigs());
-
-        try {
-            tested.persistConfig(new ConfigSnapshotHolder() {
-                @Override
-                public String getConfigSnapshot() {
-                    throw new RuntimeException();
-                }
-
-                @Override
-                public SortedSet<String> getCapabilities() {
-                    throw new RuntimeException();
-                }
-            });
-            fail();
-        } catch (UnsupportedOperationException e) {
-
-        }
-    }
-
-    private File getFolder(String folderName) {
-        File result = new File(("src/test/resources/" +
-                folderName).replace("/", File.separator));
-        assertTrue(result + " is not a directory", result.isDirectory());
-        return result;
-    }
-
-    @Test
-    public void testOneFile() throws Exception {
-        File folder = getFolder("oneFile");
-
-        tested = instantiatePersisterFromAdapter(folder);
-
-        List<ConfigSnapshotHolder> results = tested.loadLastConfigs();
-        assertEquals(1, results.size());
-        ConfigSnapshotHolder result = results.get(0);
-        assertSnapshot(result, "oneFileExpected");
-    }
-
-
-    @Test
-    public void testTwoFiles() throws Exception {
-        File folder = getFolder("twoFiles");
-        tested = instantiatePersisterFromAdapter(folder);
-
-        List<ConfigSnapshotHolder> results = tested.loadLastConfigs();
-        assertEquals(2, results.size());
-        assertSnapshot(results.get(0), "twoFilesExpected1");
-        assertSnapshot(results.get(1), "twoFilesExpected2");
-    }
-
-    private void assertSnapshot(ConfigSnapshotHolder result, String directory) throws Exception {
-        SortedSet<String> expectedCapabilities = new TreeSet<>(IOUtils.readLines(getClass().getResourceAsStream("/" + directory + "/expectedCapabilities.txt")));
-        String expectedSnapshot = IOUtils.toString(getClass().getResourceAsStream("/" + directory + "/expectedSnapshot.xml"));
-        expectedSnapshot = expectedSnapshot.replaceAll("\r","");
-        String _snapshot = result.getConfigSnapshot();
-        _snapshot = _snapshot.replaceAll("\r","");
-        assertEquals(expectedCapabilities, result.getCapabilities());
-        assertEquals(expectedSnapshot, _snapshot);
-    }
-
-}
diff --git a/opendaylight/config/config-persister-directory-adapter/src/test/resources/oneFile/controller.config.txt b/opendaylight/config/config-persister-directory-adapter/src/test/resources/oneFile/controller.config.txt
deleted file mode 100644 (file)
index 99b4cb9..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-//MODULES START
-        <module>
-            <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>
-        <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>
-        <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-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>
-                <name>ref_hash-map-data-store</name>
-            </data-store>
-        </module>
-        <module>
-            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-broker-impl</type>
-            <name>binding-broker-impl</name>
-            <notification-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">binding:binding-notification-service</type>
-                <name>ref_binding-notification-broker</name>
-            </notification-service>
-            <data-broker 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">binding:binding-data-broker</type>
-                <name>ref_binding-data-broker</name>
-            </data-broker>
-        </module>
-        <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>
-        </module>
-        <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>ref_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>ref_runtime-mapping-singleton</name>
-            </mapping-service>
-        </module>
-//SERVICES START
-        <service>
-            <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
-            <instance>
-                <name>ref_yang-schema-service</name>
-                <provider>/config/modules/module[name='schema-service-singleton']/instance[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>ref_binding-notification-broker</name>
-                <provider>/config/modules/module[name='binding-notification-broker']/instance[name='binding-notification-broker']</provider>
-            </instance>
-        </service>
-        <service>
-            <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-data-store</type>
-            <instance>
-                <name>ref_hash-map-data-store</name>
-                <provider>/config/modules/module[name='hash-map-data-store']/instance[name='hash-map-data-store']</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>ref_binding-broker-impl</name>
-                <provider>/config/modules/module[name='binding-broker-impl']/instance[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>ref_runtime-mapping-singleton</name>
-                <provider>/config/modules/module[name='runtime-generated-mapping']/instance[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>ref_dom-broker</name>
-                <provider>/config/modules/module[name='dom-broker-impl']/instance[name='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>ref_binding-data-broker</name>
-                <provider>/config/modules/module[name='binding-data-broker']/instance[name='binding-data-broker']</provider>
-            </instance>
-        </service>
-//CAPABILITIES START
-urn:opendaylight:l2:types?module=opendaylight-l2-types&revision=2013-08-27
-urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28
-urn:opendaylight:params:xml:ns:yang:controller:threadpool?module=threadpool&revision=2013-04-09
-urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom?module=opendaylight-md-sal-dom&revision=2013-10-28
-urn:opendaylight:params:xml:ns:yang:controller:config?module=config&revision=2013-04-05
-urn:ietf:params:netconf:capability:candidate:1.0
-urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring?module=ietf-netconf-monitoring&revision=2010-10-04
-urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor?module=netty-event-executor&revision=2013-11-12
-urn:ietf:params:xml:ns:yang:rpc-context?module=rpc-context&revision=2013-06-17
-urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&revision=2013-10-28
-urn:ietf:params:xml:ns:yang:ietf-inet-types?module=ietf-inet-types&revision=2010-09-24
-urn:ietf:params:netconf:capability:rollback-on-error:1.0
-urn:ietf:params:xml:ns:yang:ietf-yang-types?module=ietf-yang-types&revision=2010-09-24
-urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl?module=threadpool-impl&revision=2013-04-05
-urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&revision=2013-10-28
-urn:opendaylight:params:xml:ns:yang:controller:logback:config?module=config-logging&revision=2013-07-16
-urn:opendaylight:yang:extension:yang-ext?module=yang-ext&revision=2013-07-09
-urn:opendaylight:params:xml:ns:yang:iana?module=iana&revision=2013-08-16
-urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&revision=2013-10-28
-urn:opendaylight:params:xml:ns:yang:ieee754?module=ieee754&revision=2013-08-19
diff --git a/opendaylight/config/config-persister-directory-adapter/src/test/resources/oneFileExpected/expectedCapabilities.txt b/opendaylight/config/config-persister-directory-adapter/src/test/resources/oneFileExpected/expectedCapabilities.txt
deleted file mode 100644 (file)
index 84c85b7..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-urn:opendaylight:l2:types?module=opendaylight-l2-types&revision=2013-08-27
-urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28
-urn:opendaylight:params:xml:ns:yang:controller:threadpool?module=threadpool&revision=2013-04-09
-urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom?module=opendaylight-md-sal-dom&revision=2013-10-28
-urn:opendaylight:params:xml:ns:yang:controller:config?module=config&revision=2013-04-05
-urn:ietf:params:netconf:capability:candidate:1.0
-urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring?module=ietf-netconf-monitoring&revision=2010-10-04
-urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor?module=netty-event-executor&revision=2013-11-12
-urn:ietf:params:xml:ns:yang:rpc-context?module=rpc-context&revision=2013-06-17
-urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&revision=2013-10-28
-urn:ietf:params:xml:ns:yang:ietf-inet-types?module=ietf-inet-types&revision=2010-09-24
-urn:ietf:params:netconf:capability:rollback-on-error:1.0
-urn:ietf:params:xml:ns:yang:ietf-yang-types?module=ietf-yang-types&revision=2010-09-24
-urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl?module=threadpool-impl&revision=2013-04-05
-urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&revision=2013-10-28
-urn:opendaylight:params:xml:ns:yang:controller:logback:config?module=config-logging&revision=2013-07-16
-urn:opendaylight:yang:extension:yang-ext?module=yang-ext&revision=2013-07-09
-urn:opendaylight:params:xml:ns:yang:iana?module=iana&revision=2013-08-16
-urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&revision=2013-10-28
-urn:opendaylight:params:xml:ns:yang:ieee754?module=ieee754&revision=2013-08-19
diff --git a/opendaylight/config/config-persister-directory-adapter/src/test/resources/oneFileExpected/expectedSnapshot.xml b/opendaylight/config/config-persister-directory-adapter/src/test/resources/oneFileExpected/expectedSnapshot.xml
deleted file mode 100644 (file)
index a6a57d7..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
-    <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
-        <module>
-            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:schema-service-singleton</type>
-            <name>yang-schema-service</name>
-        </module>
-        <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>
-        <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-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>
-                <name>ref_hash-map-data-store</name>
-            </data-store>
-        </module>
-        <module>
-            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-broker-impl</type>
-            <name>binding-broker-impl</name>
-            <notification-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">binding:binding-notification-service</type>
-                <name>ref_binding-notification-broker</name>
-            </notification-service>
-            <data-broker 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">binding:binding-data-broker</type>
-                <name>ref_binding-data-broker</name>
-            </data-broker>
-        </module>
-        <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>
-        </module>
-        <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>ref_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>ref_runtime-mapping-singleton</name>
-            </mapping-service>
-        </module>
-    </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>ref_yang-schema-service</name>
-                <provider>/config/modules/module[name='schema-service-singleton']/instance[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>ref_binding-notification-broker</name>
-                <provider>/config/modules/module[name='binding-notification-broker']/instance[name='binding-notification-broker']</provider>
-            </instance>
-        </service>
-        <service>
-            <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-data-store</type>
-            <instance>
-                <name>ref_hash-map-data-store</name>
-                <provider>/config/modules/module[name='hash-map-data-store']/instance[name='hash-map-data-store']</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>ref_binding-broker-impl</name>
-                <provider>/config/modules/module[name='binding-broker-impl']/instance[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>ref_runtime-mapping-singleton</name>
-                <provider>/config/modules/module[name='runtime-generated-mapping']/instance[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>ref_dom-broker</name>
-                <provider>/config/modules/module[name='dom-broker-impl']/instance[name='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>ref_binding-data-broker</name>
-                <provider>/config/modules/module[name='binding-data-broker']/instance[name='binding-data-broker']</provider>
-            </instance>
-        </service>
-    </services>
-</data>
diff --git a/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFiles/controller.config1.txt b/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFiles/controller.config1.txt
deleted file mode 100644 (file)
index 6ae48fb..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-//MODULES START
-        <module>
-            <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>
-        <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>
-        <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-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>
-                <name>ref_hash-map-data-store</name>
-            </data-store>
-        </module>
-        <module>
-            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-broker-impl</type>
-            <name>binding-broker-impl</name>
-            <notification-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">binding:binding-notification-service</type>
-                <name>ref_binding-notification-broker</name>
-            </notification-service>
-            <data-broker 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">binding:binding-data-broker</type>
-                <name>ref_binding-data-broker</name>
-            </data-broker>
-        </module>
-        <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>
-        </module>
-//SERVICES START
-        <service>
-            <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
-            <instance>
-                <name>ref_yang-schema-service</name>
-                <provider>/config/modules/module[name='schema-service-singleton']/instance[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>ref_binding-notification-broker</name>
-                <provider>/config/modules/module[name='binding-notification-broker']/instance[name='binding-notification-broker']</provider>
-            </instance>
-        </service>
-        <service>
-            <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-data-store</type>
-            <instance>
-                <name>ref_hash-map-data-store</name>
-                <provider>/config/modules/module[name='hash-map-data-store']/instance[name='hash-map-data-store']</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>ref_binding-broker-impl</name>
-                <provider>/config/modules/module[name='binding-broker-impl']/instance[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>ref_runtime-mapping-singleton</name>
-                <provider>/config/modules/module[name='runtime-generated-mapping']/instance[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>ref_dom-broker</name>
-                <provider>/config/modules/module[name='dom-broker-impl']/instance[name='dom-broker']</provider>
-            </instance>
-        </service>
-//CAPABILITIES START
-urn:opendaylight:l2:types?module=opendaylight-l2-types&revision=2013-08-27
diff --git a/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFiles/controller.config2.txt b/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFiles/controller.config2.txt
deleted file mode 100644 (file)
index ad9138f..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-//MODULES 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>ref_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>ref_runtime-mapping-singleton</name>
-            </mapping-service>
-        </module>
-//SERVICES START
-        <service>
-            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
-            <instance>
-                <name>ref_binding-data-broker</name>
-                <provider>/config/modules/module[name='binding-data-broker']/instance[name='binding-data-broker']</provider>
-            </instance>
-        </service>
-//CAPABILITIES START
-urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28
-urn:opendaylight:params:xml:ns:yang:controller:threadpool?module=threadpool&revision=2013-04-09
-urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom?module=opendaylight-md-sal-dom&revision=2013-10-28
-urn:opendaylight:params:xml:ns:yang:controller:config?module=config&revision=2013-04-05
-urn:ietf:params:netconf:capability:candidate:1.0
-urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring?module=ietf-netconf-monitoring&revision=2010-10-04
-urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor?module=netty-event-executor&revision=2013-11-12
-urn:ietf:params:xml:ns:yang:rpc-context?module=rpc-context&revision=2013-06-17
-urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&revision=2013-10-28
-urn:ietf:params:xml:ns:yang:ietf-inet-types?module=ietf-inet-types&revision=2010-09-24
-urn:ietf:params:netconf:capability:rollback-on-error:1.0
-urn:ietf:params:xml:ns:yang:ietf-yang-types?module=ietf-yang-types&revision=2010-09-24
-urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl?module=threadpool-impl&revision=2013-04-05
-urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&revision=2013-10-28
-urn:opendaylight:params:xml:ns:yang:controller:logback:config?module=config-logging&revision=2013-07-16
-urn:opendaylight:yang:extension:yang-ext?module=yang-ext&revision=2013-07-09
-urn:opendaylight:params:xml:ns:yang:iana?module=iana&revision=2013-08-16
-urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&revision=2013-10-28
-urn:opendaylight:params:xml:ns:yang:ieee754?module=ieee754&revision=2013-08-19
diff --git a/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected1/expectedCapabilities.txt b/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected1/expectedCapabilities.txt
deleted file mode 100644 (file)
index ef35fdd..0000000
+++ /dev/null
@@ -1 +0,0 @@
-urn:opendaylight:l2:types?module=opendaylight-l2-types&revision=2013-08-27
diff --git a/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected1/expectedSnapshot.xml b/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected1/expectedSnapshot.xml
deleted file mode 100644 (file)
index 2b1d06e..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
-    <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
-        <module>
-            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:schema-service-singleton</type>
-            <name>yang-schema-service</name>
-        </module>
-        <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>
-        <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-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>
-                <name>ref_hash-map-data-store</name>
-            </data-store>
-        </module>
-        <module>
-            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-broker-impl</type>
-            <name>binding-broker-impl</name>
-            <notification-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">binding:binding-notification-service</type>
-                <name>ref_binding-notification-broker</name>
-            </notification-service>
-            <data-broker 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">binding:binding-data-broker</type>
-                <name>ref_binding-data-broker</name>
-            </data-broker>
-        </module>
-        <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>
-        </module>
-    </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>ref_yang-schema-service</name>
-                <provider>/config/modules/module[name='schema-service-singleton']/instance[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>ref_binding-notification-broker</name>
-                <provider>/config/modules/module[name='binding-notification-broker']/instance[name='binding-notification-broker']</provider>
-            </instance>
-        </service>
-        <service>
-            <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-data-store</type>
-            <instance>
-                <name>ref_hash-map-data-store</name>
-                <provider>/config/modules/module[name='hash-map-data-store']/instance[name='hash-map-data-store']</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>ref_binding-broker-impl</name>
-                <provider>/config/modules/module[name='binding-broker-impl']/instance[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>ref_runtime-mapping-singleton</name>
-                <provider>/config/modules/module[name='runtime-generated-mapping']/instance[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>ref_dom-broker</name>
-                <provider>/config/modules/module[name='dom-broker-impl']/instance[name='dom-broker']</provider>
-            </instance>
-        </service>
-    </services>
-</data>
diff --git a/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected2/expectedCapabilities.txt b/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected2/expectedCapabilities.txt
deleted file mode 100644 (file)
index 9924111..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28
-urn:opendaylight:params:xml:ns:yang:controller:threadpool?module=threadpool&revision=2013-04-09
-urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom?module=opendaylight-md-sal-dom&revision=2013-10-28
-urn:opendaylight:params:xml:ns:yang:controller:config?module=config&revision=2013-04-05
-urn:ietf:params:netconf:capability:candidate:1.0
-urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring?module=ietf-netconf-monitoring&revision=2010-10-04
-urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor?module=netty-event-executor&revision=2013-11-12
-urn:ietf:params:xml:ns:yang:rpc-context?module=rpc-context&revision=2013-06-17
-urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&revision=2013-10-28
-urn:ietf:params:xml:ns:yang:ietf-inet-types?module=ietf-inet-types&revision=2010-09-24
-urn:ietf:params:netconf:capability:rollback-on-error:1.0
-urn:ietf:params:xml:ns:yang:ietf-yang-types?module=ietf-yang-types&revision=2010-09-24
-urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl?module=threadpool-impl&revision=2013-04-05
-urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&revision=2013-10-28
-urn:opendaylight:params:xml:ns:yang:controller:logback:config?module=config-logging&revision=2013-07-16
-urn:opendaylight:yang:extension:yang-ext?module=yang-ext&revision=2013-07-09
-urn:opendaylight:params:xml:ns:yang:iana?module=iana&revision=2013-08-16
-urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&revision=2013-10-28
-urn:opendaylight:params:xml:ns:yang:ieee754?module=ieee754&revision=2013-08-19
diff --git a/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected2/expectedSnapshot.xml b/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected2/expectedSnapshot.xml
deleted file mode 100644 (file)
index 887cb2c..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
-    <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
-        <module>
-            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang: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>ref_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>ref_runtime-mapping-singleton</name>
-            </mapping-service>
-        </module>
-    </modules>
-    <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
-        <service>
-            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
-            <instance>
-                <name>ref_binding-data-broker</name>
-                <provider>/config/modules/module[name='binding-data-broker']/instance[name='binding-data-broker']</provider>
-            </instance>
-        </service>
-    </services>
-</data>
diff --git a/opendaylight/config/config-persister-directory-autodetect-adapter/pom.xml b/opendaylight/config/config-persister-directory-autodetect-adapter/pom.xml
deleted file mode 100644 (file)
index 5e556c0..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <artifactId>config-subsystem</artifactId>
-        <groupId>org.opendaylight.controller</groupId>
-        <version>0.2.5-SNAPSHOT</version>
-        <relativePath>..</relativePath>
-    </parent>
-    <artifactId>config-persister-directory-autodetect-adapter</artifactId>
-    <name>${project.artifactId}</name>
-    <packaging>bundle</packaging>
-
-    <dependencies>
-        <!-- compile dependencies -->
-        <dependency>
-            <groupId>${project.groupId}</groupId>
-            <artifactId>config-persister-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-lang3</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.google.guava</groupId>
-            <artifactId>guava</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>config-persister-directory-adapter</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>config-persister-directory-xml-adapter</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>commons-io</groupId>
-            <artifactId>commons-io</artifactId>
-        </dependency>
-
-        <!-- test dependencies -->
-        <dependency>
-            <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>mockito-configuration</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>${project.groupId}</groupId>
-            <artifactId>config-persister-api</artifactId>
-            <type>test-jar</type>
-            <scope>test</scope>
-        </dependency>
-
-    </dependencies>
-
-    <build>
-        <plugins>
-            <!-- workaround for creating version according to OSGi specification (major.minor.micro[.qualifier] -->
-            <plugin>
-                <groupId>org.codehaus.groovy.maven</groupId>
-                <artifactId>gmaven-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <phase>generate-sources</phase>
-                        <goals>
-                            <goal>execute</goal>
-                        </goals>
-                        <configuration>
-                            <source>
-                                System.setProperty("osgiversion", "${project.version}".replace('-', '.'))
-                            </source>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Fragment-Host>${project.groupId}.config-persister-impl;bundle-version=${osgiversion}
-                        </Fragment-Host>
-                        <Provide-Capability>org.opendaylight.controller.config.persister.storage.adapter
-                        </Provide-Capability>
-                        <Import-Package>
-                            com.google.common.base,
-                            com.google.common.io,
-                            org.apache.commons.io,
-                            org.opendaylight.controller.config.persist.api,
-                            org.slf4j,
-                            com.google.common.collect,
-                            javax.xml.bind,
-                            javax.xml.bind.annotation,
-                            javax.xml.transform,
-                            javax.xml.transform.stream,
-                            org.eclipse.persistence.jaxb,
-                            org.apache.commons.lang3
-                        </Import-Package>
-                        <Private-Package>
-                            org.opendaylight.controller.config.persist.storage.file.xml.model,
-                            org.opendaylight.controller.config.persist.storage.directory,
-                            org.opendaylight.controller.config.persist.storage.directory.xml,
-                        </Private-Package>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
diff --git a/opendaylight/config/config-persister-directory-autodetect-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/directory/autodetect/AutodetectDirectoryPersister.java b/opendaylight/config/config-persister-directory-autodetect-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/directory/autodetect/AutodetectDirectoryPersister.java
deleted file mode 100644 (file)
index 2028d62..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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.persist.storage.directory.autodetect;
-
-import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
-import org.opendaylight.controller.config.persist.api.Persister;
-import org.opendaylight.controller.config.persist.storage.directory.DirectoryPersister;
-import org.opendaylight.controller.config.persist.storage.directory.xml.XmlDirectoryPersister;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.xml.bind.JAXBException;
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-public class AutodetectDirectoryPersister implements Persister {
-    private static final Logger logger = LoggerFactory.getLogger(AutodetectDirectoryPersister.class);
-
-    private final File storage;
-
-    public AutodetectDirectoryPersister(File storage) {
-        checkArgument(storage.exists() && storage.isDirectory(), "Storage directory does not exist: " + storage);
-        this.storage = storage;
-    }
-
-    @Override
-    public void persistConfig(ConfigSnapshotHolder holder) throws IOException {
-        throw new UnsupportedOperationException("This adapter is read only. Please set readonly=true on " + getClass());
-    }
-
-    @Override
-    public List<ConfigSnapshotHolder> loadLastConfigs() throws IOException {
-        File[] filesArray = storage.listFiles();
-        if (filesArray == null || filesArray.length == 0) {
-            return Collections.emptyList();
-        }
-        List<File> sortedFiles = new ArrayList<>(Arrays.asList(filesArray));
-        Collections.sort(sortedFiles);
-
-        // combine all found files
-        logger.debug("Reading files in following order: {}", sortedFiles);
-
-        List<ConfigSnapshotHolder> result = new ArrayList<>();
-        for (File file : sortedFiles) {
-            logger.trace("Adding file '{}' to combined result", file);
-
-            FileType fileType = FileType.getFileType(file);
-            logger.trace("File '{}' detected as {} storage", file, fileType);
-
-            ConfigSnapshotHolder snapshot = loadLastConfig(file, fileType);
-            result.add(snapshot);
-        }
-        return result;
-    }
-
-    private ConfigSnapshotHolder loadLastConfig(File file, FileType fileType) throws IOException {
-        switch (fileType) {
-        case plaintext:
-            logger.warn("Plaintext configuration files are deprecated, and will not be supported in future versions. " +
-                    "Use xml files instead");
-            return DirectoryPersister.loadLastConfig(file);
-        case xml:
-            try {
-                return XmlDirectoryPersister.loadLastConfig(file);
-            } catch (JAXBException e) {
-                logger.warn("Unable to restore configuration snapshot from {}", file, e);
-                throw new IllegalStateException("Unable to restore configuration snapshot from " + file, e);
-            }
-        default:
-            throw new IllegalStateException("Unknown storage type " + fileType);
-        }
-    }
-
-    @Override
-    public void close() {
-
-    }
-
-    @Override
-    public String toString() {
-        final StringBuffer sb = new StringBuffer("AutodetectDirectoryPersister{");
-        sb.append("storage=").append(storage);
-        sb.append('}');
-        return sb.toString();
-    }
-}
diff --git a/opendaylight/config/config-persister-directory-autodetect-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/directory/autodetect/AutodetectDirectoryStorageAdapter.java b/opendaylight/config/config-persister-directory-autodetect-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/directory/autodetect/AutodetectDirectoryStorageAdapter.java
deleted file mode 100644 (file)
index f856ddd..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.persist.storage.directory.autodetect;
-
-import com.google.common.base.Preconditions;
-import org.opendaylight.controller.config.persist.api.Persister;
-import org.opendaylight.controller.config.persist.api.PropertiesProvider;
-import org.opendaylight.controller.config.persist.api.StorageAdapter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.File;
-
-/**
- * StorageAdapter that retrieves initial configuration from a directory. If multiple files are present, snapshot and
- * required capabilities will be merged together. Writing to this persister is not supported.
- */
-public class AutodetectDirectoryStorageAdapter implements StorageAdapter {
-    private static final Logger logger = LoggerFactory.getLogger(AutodetectDirectoryStorageAdapter.class);
-
-    public static final String DIRECTORY_STORAGE_PROP = "directoryStorage";
-
-
-    @Override
-    public Persister instantiate(PropertiesProvider propertiesProvider) {
-        String fileStorageProperty = propertiesProvider.getProperty(DIRECTORY_STORAGE_PROP);
-        Preconditions.checkNotNull(fileStorageProperty, "Unable to find " + propertiesProvider.getFullKeyForReporting(DIRECTORY_STORAGE_PROP));
-        File storage  = new File(fileStorageProperty);
-        logger.debug("Using {}", storage);
-        return new AutodetectDirectoryPersister(storage);
-    }
-
-}
diff --git a/opendaylight/config/config-persister-directory-autodetect-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/directory/autodetect/FileType.java b/opendaylight/config/config-persister-directory-autodetect-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/directory/autodetect/FileType.java
deleted file mode 100644 (file)
index 779a887..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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.persist.storage.directory.autodetect;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Charsets;
-import com.google.common.io.Files;
-import org.apache.commons.lang3.StringUtils;
-import org.opendaylight.controller.config.persist.storage.directory.DirectoryPersister;
-import org.opendaylight.controller.config.persist.storage.file.xml.model.ConfigSnapshot;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Arrays;
-
-enum FileType {
-
-    plaintext, xml;
-
-    public static final String XML_STORAGE_FIRST_LINE = "<" + ConfigSnapshot.SNAPSHOT_ROOT_ELEMENT_NAME + ">";
-    private static final String XML_FILE_DEFINITION_LINE = "<?xml";
-
-    static FileType getFileType(File file) {
-        String firstLine = readFirstLine(file);
-        if(isPlaintextStorage(firstLine)) {
-            return plaintext;
-        } else if(isXmlStorage(firstLine))
-            return xml;
-
-        throw new IllegalArgumentException("File " + file + " is not of permitted storage type: " + Arrays.toString(FileType.values()));
-    }
-
-    private static boolean isXmlStorage(String firstLine) {
-        boolean isXml = false;
-        isXml |= firstLine.startsWith(XML_STORAGE_FIRST_LINE);
-        isXml |= firstLine.startsWith(XML_FILE_DEFINITION_LINE);
-        return isXml;
-    }
-
-    private static boolean isPlaintextStorage(String firstLine) {
-        return firstLine.startsWith(DirectoryPersister.MODULES_START);
-
-    }
-
-    @VisibleForTesting
-    static String readFirstLine(File file) {
-        FirstLineReadingProcessor callback = new FirstLineReadingProcessor();
-        try {
-            return Files.readLines(file, Charsets.UTF_8, callback);
-        } catch (IOException e) {
-            throw new IllegalArgumentException("Unable to detect file type of file " + file, e);
-        }
-    }
-
-
-    private static class FirstLineReadingProcessor implements com.google.common.io.LineProcessor<String> {
-        private String firstNonBlankLine;
-
-        @Override
-        public boolean processLine(String line) throws IOException {
-            if(isEmptyLine(line)) {
-                return true;
-            } else {
-                firstNonBlankLine = line.trim();
-                return false;
-            }
-        }
-
-        private boolean isEmptyLine(String line) {
-            return StringUtils.isBlank(line);
-        }
-
-        @Override
-        public String getResult() {
-            return firstNonBlankLine;
-        }
-    }
-}
diff --git a/opendaylight/config/config-persister-directory-autodetect-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/directory/autodetect/AutodetectDirectoryPersisterTest.java b/opendaylight/config/config-persister-directory-autodetect-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/directory/autodetect/AutodetectDirectoryPersisterTest.java
deleted file mode 100644 (file)
index bcade93..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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.persist.storage.directory.autodetect;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
-import junit.framework.Assert;
-import org.junit.Test;
-import org.junit.matchers.JUnitMatchers;
-import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
-import org.opendaylight.controller.config.persist.test.PropertiesProviderTest;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-
-public class AutodetectDirectoryPersisterTest {
-
-    @Test
-    public void testCombined() throws Exception {
-        File resourcePath = FileTypeTest.getResourceAsFile("/combined/1controller.txt.config");
-        File parentFile = resourcePath.getParentFile();
-
-        AutodetectDirectoryStorageAdapter adapter = new AutodetectDirectoryStorageAdapter();
-
-        PropertiesProviderTest pp = new PropertiesProviderTest();
-        pp.addProperty("directoryStorage",parentFile.getPath());
-        AutodetectDirectoryPersister persister = (AutodetectDirectoryPersister) adapter.instantiate(pp);
-        List<ConfigSnapshotHolder> configs = persister.loadLastConfigs();
-
-        Assert.assertEquals(2, configs.size());
-        String snapFromTxt = configs.get(0).getConfigSnapshot();
-        org.junit.Assert.assertThat(snapFromTxt, JUnitMatchers.containsString("<config>txt</config>"));
-        org.junit.Assert.assertThat(snapFromTxt, JUnitMatchers.containsString("<service>txt</service>"));
-
-        String snapFromXml = configs.get(1).getConfigSnapshot();
-        org.junit.Assert.assertThat(snapFromXml, JUnitMatchers.containsString("<config>xml</config>"));
-
-        Assert.assertEquals(configs.get(0).getCapabilities(), configs.get(1).getCapabilities());
-    }
-
-    @Test
-    public void testInvalidXml() throws Exception {
-        File resourcePath = FileTypeTest.getResourceAsFile("/bad_controller.xml.config");
-        File parentFile = resourcePath.getParentFile();
-
-        AutodetectDirectoryStorageAdapter adapter = new AutodetectDirectoryStorageAdapter();
-
-        PropertiesProviderTest pp = new PropertiesProviderTest();
-        pp.addProperty("directoryStorage",parentFile.getPath());
-        AutodetectDirectoryPersister persister = (AutodetectDirectoryPersister) adapter.instantiate(pp);
-        try {
-            List<ConfigSnapshotHolder> configs = persister.loadLastConfigs();
-            fail("An exception of type " + IllegalStateException.class + " was expected");
-        } catch (IllegalStateException ise){
-            String message = ise.getMessage();
-            assertThat(message, JUnitMatchers.containsString("Unable to restore configuration snapshot from "));
-        }
-
-    }
-
-    @Test
-    public void testPersistConfig() throws Exception {
-        File resourcePath = FileTypeTest.getResourceAsFile("/combined/1controller.txt.config");
-        File parentFile = resourcePath.getParentFile();
-
-        AutodetectDirectoryStorageAdapter adapter = new AutodetectDirectoryStorageAdapter();
-
-        PropertiesProviderTest pp = new PropertiesProviderTest();
-        pp.addProperty("directoryStorage",parentFile.getPath());
-        AutodetectDirectoryPersister persister = (AutodetectDirectoryPersister) adapter.instantiate(pp);
-        List<ConfigSnapshotHolder> configs = null;
-        try {
-            configs = persister.loadLastConfigs();
-        } catch (IOException e) {
-            fail("An exception of type " + UnsupportedOperationException.class + " was expected");
-        }
-        Assert.assertEquals(2, configs.size());
-        try {
-            persister.persistConfig(configs.get(0));
-        } catch (UnsupportedOperationException uoe){
-            String message = uoe.getMessage();
-            assertThat(message,JUnitMatchers.containsString("This adapter is read only. Please set readonly=true on class"));
-        }
-    }
-
-}
diff --git a/opendaylight/config/config-persister-directory-autodetect-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/directory/autodetect/FileTypeTest.java b/opendaylight/config/config-persister-directory-autodetect-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/directory/autodetect/FileTypeTest.java
deleted file mode 100644 (file)
index bbc272d..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.persist.storage.directory.autodetect;
-
-import junit.framework.Assert;
-import org.junit.Test;
-import org.junit.matchers.JUnitMatchers;
-
-import java.io.File;
-
-public class FileTypeTest {
-
-    @Test
-    public void testPlaintext() throws Exception {
-        File file = getResourceAsFile("/test.txt.config");
-
-        FileType type = FileType.getFileType(file);
-        Assert.assertEquals(FileType.plaintext, type);
-
-    }
-
-    @Test
-    public void testXml() throws Exception {
-        File file = getResourceAsFile("/test.xml.config");
-
-        FileType type = FileType.getFileType(file);
-        Assert.assertEquals(FileType.xml, type);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testUnknown() throws Exception {
-        File file = getResourceAsFile("/unknown.config");
-
-        try {
-            FileType.getFileType(file);
-        } catch (IllegalArgumentException e) {
-            org.junit.Assert.assertThat(e.getMessage(), JUnitMatchers.containsString("File " + file + " is not of permitted storage type"));
-            throw e;
-        }
-    }
-
-    static File getResourceAsFile(String resource) {
-        String f = FileTypeTest.class.getResource(resource).getFile();
-        return new File(f);
-    }
-
-}
diff --git a/opendaylight/config/config-persister-directory-autodetect-adapter/src/test/resources/bad_controller.xml.config b/opendaylight/config/config-persister-directory-autodetect-adapter/src/test/resources/bad_controller.xml.config
deleted file mode 100644 (file)
index 3f6a337..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<snapshot>
-    <required-capabilities>
-        <capability
-        <capability>cap2</capability>
-        <capability>capa a</capability>
-    </required-capabilities>
-    <configuration>
-        <config>xml</config>
-    </configuration>
-</snapshot>
\ No newline at end of file
diff --git a/opendaylight/config/config-persister-directory-autodetect-adapter/src/test/resources/combined/1controller.txt.config b/opendaylight/config/config-persister-directory-autodetect-adapter/src/test/resources/combined/1controller.txt.config
deleted file mode 100644 (file)
index f72cd1c..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-//MODULES START
-        <config>txt</config>
-//SERVICES START
-        <service>txt</service>
-//CAPABILITIES START
-cap1&rev
-cap2
-capa a
\ No newline at end of file
diff --git a/opendaylight/config/config-persister-directory-autodetect-adapter/src/test/resources/combined/2controller.xml.config b/opendaylight/config/config-persister-directory-autodetect-adapter/src/test/resources/combined/2controller.xml.config
deleted file mode 100644 (file)
index 988f866..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<snapshot>
-    <required-capabilities>
-        <capability>cap1&amp;rev</capability>
-        <capability>cap2</capability>
-        <capability>capa a</capability>
-    </required-capabilities>
-    <configuration>
-        <config>xml</config>
-    </configuration>
-</snapshot>
\ No newline at end of file
diff --git a/opendaylight/config/config-persister-directory-autodetect-adapter/src/test/resources/test.txt.config b/opendaylight/config/config-persister-directory-autodetect-adapter/src/test/resources/test.txt.config
deleted file mode 100644 (file)
index edf37ca..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-//MODULES START
-configuration
\ No newline at end of file
diff --git a/opendaylight/config/config-persister-directory-autodetect-adapter/src/test/resources/test.xml.config b/opendaylight/config/config-persister-directory-autodetect-adapter/src/test/resources/test.xml.config
deleted file mode 100644 (file)
index fe94299..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-
-<snapshot>
\ No newline at end of file
diff --git a/opendaylight/config/config-persister-directory-autodetect-adapter/src/test/resources/unknown.config b/opendaylight/config/config-persister-directory-autodetect-adapter/src/test/resources/unknown.config
deleted file mode 100644 (file)
index c4218c8..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-unknown
-file type
\ No newline at end of file
index 0ca47edf0e5540cef5db8c2bcbb8f0d8f9dde611..7f8ebd7fddf8e7ee93a665106040ef4c83c5fb96 100644 (file)
@@ -7,6 +7,8 @@
  */
 package org.opendaylight.controller.config.persist.storage.directory.xml;
 
+import com.google.common.base.Optional;
+import com.google.common.io.Files;
 import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
 import org.opendaylight.controller.config.persist.api.Persister;
 import org.opendaylight.controller.config.persist.storage.file.xml.model.ConfigSnapshot;
@@ -17,11 +19,13 @@ import javax.xml.bind.JAXBContext;
 import javax.xml.bind.JAXBException;
 import javax.xml.bind.Unmarshaller;
 import java.io.File;
+import java.io.FilenameFilter;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Set;
 import java.util.SortedSet;
 
 import static com.google.common.base.Preconditions.checkArgument;
@@ -30,10 +34,26 @@ public class XmlDirectoryPersister implements Persister {
     private static final Logger logger = LoggerFactory.getLogger(XmlDirectoryPersister.class);
 
     private final File storage;
+    private final Optional<FilenameFilter> extensionsFilter;
 
+    /**
+     * Creates XmlDirectoryPersister that picks up all files in specified folder
+     */
     public XmlDirectoryPersister(File storage) {
+        this(storage, Optional.<FilenameFilter>absent());
+    }
+
+    /**
+     * Creates XmlDirectoryPersister that picks up files only with specified file extension
+     */
+    public XmlDirectoryPersister(File storage, Set<String> fileExtensions) {
+        this(storage, Optional.of(getFilter(fileExtensions)));
+    }
+
+    private XmlDirectoryPersister(File storage, Optional<FilenameFilter> extensionsFilter) {
         checkArgument(storage.exists() && storage.isDirectory(), "Storage directory does not exist: " + storage);
         this.storage = storage;
+        this.extensionsFilter = extensionsFilter;
     }
 
     @Override
@@ -43,7 +63,7 @@ public class XmlDirectoryPersister implements Persister {
 
     @Override
     public List<ConfigSnapshotHolder> loadLastConfigs() throws IOException {
-        File[] filesArray = storage.listFiles();
+        File[] filesArray = extensionsFilter.isPresent() ? storage.listFiles(extensionsFilter.get()) : storage.listFiles();
         if (filesArray == null || filesArray.length == 0) {
             return Collections.emptyList();
         }
@@ -55,19 +75,30 @@ public class XmlDirectoryPersister implements Persister {
         List<ConfigSnapshotHolder> result = new ArrayList<>();
         for (File file : sortedFiles) {
             logger.trace("Adding file '{}' to combined result", file);
-            ConfigSnapshotHolder h = fromXmlSnapshot(file);
-            result.add(h);
+            Optional<ConfigSnapshotHolder> h = fromXmlSnapshot(file);
+            // Ignore non valid snapshot
+            if(h.isPresent() == false) {
+                continue;
+            }
+
+            result.add(h.get());
         }
         return result;
     }
 
-    private ConfigSnapshotHolder fromXmlSnapshot(File file) {
+    private Optional<ConfigSnapshotHolder> fromXmlSnapshot(File file) {
         try {
-            return loadLastConfig(file);
+            return Optional.of(loadLastConfig(file));
         } catch (JAXBException e) {
-            logger.warn("Unable to restore configuration snapshot from {}", file, e);
-            throw new IllegalStateException("Unable to restore configuration snapshot from " + file, e);
+            // In case of parse error, issue a warning, ignore and continue
+            logger.warn(
+                    "Unable to parse configuration snapshot from {}. Initial config from {} will be IGNORED in this run. " +
+                    "Note that subsequent config files may fail due to this problem. " +
+                    "Xml markup in this file needs to be fixed, for detailed information see enclosed exception.",
+                    file, file, e);
         }
+
+        return Optional.absent();
     }
 
     public static ConfigSnapshotHolder loadLastConfig(File file) throws JAXBException {
@@ -96,6 +127,17 @@ public class XmlDirectoryPersister implements Persister {
         };
     }
 
+    private static FilenameFilter getFilter(final Set<String>fileExtensions) {
+        checkArgument(fileExtensions.isEmpty() == false, "No file extension provided", fileExtensions);
+
+        return new FilenameFilter() {
+            @Override
+            public boolean accept(File dir, String name) {
+                String ext = Files.getFileExtension(name);
+                return fileExtensions.contains(ext);
+            }
+        };
+    }
 
     @Override
     public void close() {
index ab6fb1577cc49261b134b2db57ad15dd76c63938..40f8c283ddd5a8e49ff7eb2c8464bddd65178a98 100644 (file)
@@ -9,6 +9,8 @@
 package org.opendaylight.controller.config.persist.storage.directory.xml;
 
 import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Sets;
 import org.opendaylight.controller.config.persist.api.Persister;
 import org.opendaylight.controller.config.persist.api.PropertiesProvider;
 import org.opendaylight.controller.config.persist.api.StorageAdapter;
@@ -16,6 +18,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.io.File;
+import java.util.Set;
 
 /**
  * StorageAdapter that retrieves initial configuration from a directory. If multiple files are present, snapshot and
@@ -25,6 +28,8 @@ public class XmlDirectoryStorageAdapter implements StorageAdapter {
     private static final Logger logger = LoggerFactory.getLogger(XmlDirectoryStorageAdapter.class);
 
     public static final String DIRECTORY_STORAGE_PROP = "directoryStorage";
+    public static final String INCLUDE_EXT_PROP = "includeExtensions";
+    private static final char EXTENSIONS_SEPARATOR = ',';
 
 
     @Override
@@ -32,8 +37,21 @@ public class XmlDirectoryStorageAdapter implements StorageAdapter {
         String fileStorageProperty = propertiesProvider.getProperty(DIRECTORY_STORAGE_PROP);
         Preconditions.checkNotNull(fileStorageProperty, "Unable to find " + propertiesProvider.getFullKeyForReporting(DIRECTORY_STORAGE_PROP));
         File storage  = new File(fileStorageProperty);
-        logger.debug("Using {}", storage);
-        return new XmlDirectoryPersister(storage);
+        String fileExtensions = propertiesProvider.getProperty(INCLUDE_EXT_PROP);
+
+        logger.debug("Using storage: {}", storage);
+
+        if(fileExtensions != null) {
+            logger.debug("Using extensions: {}", fileExtensions);
+            return new XmlDirectoryPersister(storage, splitExtensions(fileExtensions));
+        } else {
+            return new XmlDirectoryPersister(storage);
+        }
+    }
+
+    private Set<String> splitExtensions(String fileExtensions) {
+        return Sets.newHashSet(Splitter.on(EXTENSIONS_SEPARATOR).trimResults().omitEmptyStrings()
+                .split(fileExtensions));
     }
 
 }
index 8e34bc79903bcb54c712416afa906246c2ef3a5e..da442ef4b2fb669b5b1bd0e9a389616cc6755b97 100644 (file)
@@ -12,6 +12,8 @@ import java.io.File;
 import java.util.Collections;
 import java.util.List;
 import java.util.SortedSet;
+
+import com.google.common.base.Optional;
 import org.junit.Test;
 import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
 import org.opendaylight.controller.config.persist.api.Persister;
@@ -26,13 +28,21 @@ public class DirectoryStorageAdapterTest {
     Persister tested;
     Logger logger = LoggerFactory.getLogger(DirectoryStorageAdapterTest.class.toString());
 
-    private Persister instantiatePersisterFromAdapter(File file){
+    private Persister instantiatePersisterFromAdapter(File file, Optional<String> extensions){
         PropertiesProviderTest pp = new PropertiesProviderTest();
-        pp.addProperty("directoryStorage",file.getPath());
+        pp.addProperty(XmlDirectoryStorageAdapter.DIRECTORY_STORAGE_PROP,file.getPath());
+        if(extensions.isPresent()) {
+            pp.addProperty(XmlDirectoryStorageAdapter.INCLUDE_EXT_PROP, extensions.get());
+        }
+
         XmlDirectoryStorageAdapter dsa = new XmlDirectoryStorageAdapter();
         return dsa.instantiate(pp);
     }
 
+    private Persister instantiatePersisterFromAdapter(File file){
+        return instantiatePersisterFromAdapter(file, Optional.<String>absent());
+    }
+
     @Test
     public void testEmptyDirectory() throws Exception {
         File folder = new File("target/emptyFolder");
@@ -69,15 +79,22 @@ public class DirectoryStorageAdapterTest {
     @Test
     public void testOneFile() throws Exception {
         File folder = getFolder("oneFile");
-        tested = instantiatePersisterFromAdapter(folder);
+        tested = instantiatePersisterFromAdapter(folder, Optional.of("xml"));
 
-        logger.info("Testing : "+tested.toString());
+        logger.info("Testing : " + tested.toString());
         List<ConfigSnapshotHolder> results = tested.loadLastConfigs();
         assertEquals(1, results.size());
         ConfigSnapshotHolder result = results.get(0);
         assertResult(result, "<config>1</config>", "cap1&rev", "cap2", "capa a");
     }
 
+    @Test
+    public void testOneFileWrongExtension() throws Exception {
+        File folder = getFolder("oneFile");
+        tested = instantiatePersisterFromAdapter(folder, Optional.of("aa, bb"));
+        logger.info("Testing : " + tested.toString());
+    }
+
     private void assertResult(ConfigSnapshotHolder result, String s, String... caps) {
         assertEquals(s, result.getConfigSnapshot().replaceAll("\\s", ""));
         int i = 0;
@@ -87,16 +104,45 @@ public class DirectoryStorageAdapterTest {
     }
 
     @Test
-    public void testTwoFiles() throws Exception {
+    public void testTwoFilesAllExtensions() throws Exception {
         File folder = getFolder("twoFiles");
         tested = instantiatePersisterFromAdapter(folder);
-        logger.info("Testing : "+tested.toString());
+        logger.info("Testing : " + tested.toString());
         List<ConfigSnapshotHolder> results = tested.loadLastConfigs();
         assertEquals(2, results.size());
 
         assertResult(results.get(0), "<config>1</config>", "cap1-a", "cap2-a", "capa a-a");
         assertResult(results.get(1), "<config>2</config>", "cap1-b", "cap2-b", "capa a-b");
+    }
+
+    @Test
+    public void testTwoFilesTwoExtensions() throws Exception {
+        File folder = getFolder("twoFiles");
+        tested = instantiatePersisterFromAdapter(folder, Optional.of("xml, xml2"));
+        logger.info("Testing : " + tested.toString());
+        assertEquals(2, tested.loadLastConfigs().size());
+    }
+
+    @Test
+    public void testTwoFilesOnlyOneExtension() throws Exception {
+        File folder = getFolder("twoFiles");
+        tested = instantiatePersisterFromAdapter(folder, Optional.of("xml"));
+        logger.info("Testing : " + tested.toString());
+        List<ConfigSnapshotHolder> results = tested.loadLastConfigs();
+        assertEquals(1, results.size());
 
+        assertResult(results.get(0), "<config>1</config>", "cap1-a", "cap2-a", "capa a-a");
+    }
+
+    @Test
+    public void testTwoFilesOneInvalid() throws Exception {
+        File folder = getFolder("twoFiles_corrupt");
+        tested = instantiatePersisterFromAdapter(folder, Optional.of("xml"));
+        logger.info("Testing : " + tested.toString());
+        List<ConfigSnapshotHolder> results = tested.loadLastConfigs();
+        assertEquals(1, results.size());
+
+        assertResult(results.get(0), "<config>1</config>", "cap1-a", "cap2-a", "capa a-a");
     }
 
 }
diff --git a/opendaylight/config/config-persister-directory-xml-adapter/src/test/resources/twoFiles_corrupt/controller.config1.xml b/opendaylight/config/config-persister-directory-xml-adapter/src/test/resources/twoFiles_corrupt/controller.config1.xml
new file mode 100644 (file)
index 0000000..28f112e
--- /dev/null
@@ -0,0 +1,10 @@
+<snapshot>
+    <required-capabilities>
+        <capability>cap1-a</capability>
+        <capability>cap2-a</capability>
+        <capability>capa a-a</capability>
+    </required-capabilities>
+    <configuration>
+        <config>1</config>
+    </configuration>
+</snapshot>
\ No newline at end of file
diff --git a/opendaylight/config/config-persister-directory-xml-adapter/src/test/resources/twoFiles_corrupt/controller.config2.xml b/opendaylight/config/config-persister-directory-xml-adapter/src/test/resources/twoFiles_corrupt/controller.config2.xml
new file mode 100644 (file)
index 0000000..ed781d5
--- /dev/null
@@ -0,0 +1,10 @@
+<snapshotInvalid>
+    <required-capabilities>
+        <capability>cap1-b</capability>
+        <capability>cap2-b</capability>
+        <capability>capa a-b</capability>
+    </required-capabilities>
+    <configuration>
+        <config>2</config>
+    </configuration>
+</snapshotInvalid>
\ No newline at end of file
diff --git a/opendaylight/config/config-persister-file-adapter/pom.xml b/opendaylight/config/config-persister-file-adapter/pom.xml
deleted file mode 100644 (file)
index a8ea93e..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <artifactId>config-subsystem</artifactId>
-        <groupId>org.opendaylight.controller</groupId>
-        <version>0.2.5-SNAPSHOT</version>
-        <relativePath>..</relativePath>
-    </parent>
-    <artifactId>config-persister-file-adapter</artifactId>
-    <name>${project.artifactId}</name>
-    <packaging>bundle</packaging>
-
-    <dependencies>
-        <!-- compile dependencies -->
-        <dependency>
-            <groupId>${project.groupId}</groupId>
-            <artifactId>config-persister-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-lang3</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.google.guava</groupId>
-            <artifactId>guava</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-        </dependency>
-
-        <!-- test dependencies -->
-        <dependency>
-            <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>mockito-configuration</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>${project.groupId}</groupId>
-            <artifactId>config-persister-api</artifactId>
-            <type>test-jar</type>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <plugins>
-            <!-- workaround for creating version according to OSGi specification (major.minor.micro[.qualifier] -->
-            <plugin>
-                <groupId>org.codehaus.groovy.maven</groupId>
-                <artifactId>gmaven-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <phase>generate-sources</phase>
-                        <goals>
-                            <goal>execute</goal>
-                        </goals>
-                        <configuration>
-                            <source>
-                                System.setProperty("osgiversion", "${project.version}".replace('-', '.'))
-                            </source>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Fragment-Host>${project.groupId}.config-persister-impl;bundle-version=${osgiversion}
-                        </Fragment-Host>
-                        <Provide-Capability>org.opendaylight.controller.config.persister.storage.adapter
-                        </Provide-Capability>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
diff --git a/opendaylight/config/config-persister-file-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/file/FileStorageAdapter.java b/opendaylight/config/config-persister-file-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/file/FileStorageAdapter.java
deleted file mode 100644 (file)
index 1b9948b..0000000
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * 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.persist.storage.file;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Charsets;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.io.Files;
-import java.io.File;
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import org.apache.commons.lang3.StringUtils;
-import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
-import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolderImpl;
-import org.opendaylight.controller.config.persist.api.Persister;
-import org.opendaylight.controller.config.persist.api.PropertiesProvider;
-import org.opendaylight.controller.config.persist.api.StorageAdapter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * StorageAdapter that stores configuration in a plain file.
- */
-public class FileStorageAdapter implements StorageAdapter, Persister {
-    private static final Logger logger = LoggerFactory.getLogger(FileStorageAdapter.class);
-
-
-    private static final Charset ENCODING = Charsets.UTF_8;
-
-    public static final String FILE_STORAGE_PROP = "fileStorage";
-    public static final String NUMBER_OF_BACKUPS = "numberOfBackups";
-
-
-    private static final String SEPARATOR_E_PURE = "//END OF CONFIG";
-    private static final String SEPARATOR_E = newLine(SEPARATOR_E_PURE);
-
-    private static final String SEPARATOR_M_PURE = "//END OF SNAPSHOT";
-    private static final String SEPARATOR_M = newLine(SEPARATOR_M_PURE);
-
-    private static final String SEPARATOR_S = newLine("//START OF CONFIG");
-
-    private static final String SEPARATOR_SL_PURE = "//START OF CONFIG-LAST";
-    private static final String SEPARATOR_SL = newLine(SEPARATOR_SL_PURE);
-
-    private static Integer numberOfStoredBackups;
-    private File storage;
-
-    @Override
-    public Persister instantiate(PropertiesProvider propertiesProvider) {
-        File storage = extractStorageFileFromProperties(propertiesProvider);
-        logger.debug("Using file {}", storage.getAbsolutePath());
-        // Create file if it does not exist
-        File parentFile = storage.getAbsoluteFile().getParentFile();
-        if (parentFile.exists() == false) {
-            logger.debug("Creating parent folders {}", parentFile);
-            parentFile.mkdirs();
-        }
-        if (storage.exists() == false) {
-            logger.debug("Storage file does not exist, creating empty file");
-            try {
-                boolean result = storage.createNewFile();
-                if (result == false)
-                    throw new RuntimeException("Unable to create storage file " + storage);
-            } catch (IOException e) {
-                throw new RuntimeException("Unable to create storage file " + storage, e);
-            }
-        }
-        if (numberOfStoredBackups == 0) {
-            throw new RuntimeException(NUMBER_OF_BACKUPS
-                    + " property should be either set to positive value, or ommited. Can not be set to 0.");
-        }
-        setFileStorage(storage);
-        return this;
-    }
-
-    @VisibleForTesting
-    void setFileStorage(File storage) {
-        this.storage = storage;
-    }
-
-    @VisibleForTesting
-    void setNumberOfBackups(Integer numberOfBackups) {
-        numberOfStoredBackups = numberOfBackups;
-    }
-
-    private static File extractStorageFileFromProperties(PropertiesProvider propertiesProvider) {
-        String fileStorageProperty = propertiesProvider.getProperty(FILE_STORAGE_PROP);
-        Preconditions.checkNotNull(fileStorageProperty, "Unable to find " + propertiesProvider.getFullKeyForReporting(FILE_STORAGE_PROP));
-        File result = new File(fileStorageProperty);
-        String numberOfBAckupsAsString = propertiesProvider.getProperty(NUMBER_OF_BACKUPS);
-        if (numberOfBAckupsAsString != null) {
-            numberOfStoredBackups = Integer.valueOf(numberOfBAckupsAsString);
-        } else {
-            numberOfStoredBackups = Integer.MAX_VALUE;
-        }
-        logger.trace("Property {} set to {}", NUMBER_OF_BACKUPS, numberOfStoredBackups);
-        return result;
-    }
-
-    private static String newLine(String string) {
-        return string + "\n";
-    }
-
-    @Override
-    public void persistConfig(ConfigSnapshotHolder holder) throws IOException {
-        Preconditions.checkNotNull(storage, "Storage file is null");
-
-        String content = Files.toString(storage, ENCODING);
-        if (numberOfStoredBackups == Integer.MAX_VALUE) {
-            resetLastConfig(content);
-            persistLastConfig(holder);
-        } else {
-            if (numberOfStoredBackups == 1) {
-                Files.write("", storage, ENCODING);
-                persistLastConfig(holder);
-            } else {
-                int count = StringUtils.countMatches(content, SEPARATOR_S);
-                if ((count + 1) < numberOfStoredBackups) {
-                    resetLastConfig(content);
-                    persistLastConfig(holder);
-                } else {
-                    String contentSubString = StringUtils.substringBefore(content, SEPARATOR_E);
-                    contentSubString = contentSubString.concat(SEPARATOR_E_PURE);
-                    content = StringUtils.substringAfter(content, contentSubString);
-                    resetLastConfig(content);
-                    persistLastConfig(holder);
-                }
-            }
-        }
-    }
-
-    private void resetLastConfig(String content) throws IOException {
-        content = content.replaceFirst(SEPARATOR_SL, SEPARATOR_S);
-        Files.write(content, storage, ENCODING);
-    }
-
-    private void persistLastConfig(ConfigSnapshotHolder holder) throws IOException {
-        Files.append(SEPARATOR_SL, storage, ENCODING);
-        String snapshotAsString = holder.getConfigSnapshot();
-        Files.append(newLine(snapshotAsString), storage, ENCODING);
-        Files.append(SEPARATOR_M, storage, ENCODING);
-        Files.append(toStringCaps(holder.getCapabilities()), storage, ENCODING);
-        Files.append(SEPARATOR_E, storage, ENCODING);
-    }
-
-    private CharSequence toStringCaps(Set<String> capabilities) {
-        StringBuilder b = new StringBuilder();
-        for (String capability : capabilities) {
-            b.append(newLine(capability));
-        }
-        return b.toString();
-    }
-
-    @Override
-    public List<ConfigSnapshotHolder> loadLastConfigs() throws IOException {
-        Preconditions.checkNotNull(storage, "Storage file is null");
-
-        if (!storage.exists()) {
-            return Collections.emptyList();
-        }
-
-        final LineProcessor lineProcessor = new LineProcessor();
-        Files.readLines(storage, ENCODING, lineProcessor);
-
-        if (lineProcessor.getConfigSnapshot().isPresent() == false) {
-            return Collections.emptyList();
-        } else {
-            return Arrays.<ConfigSnapshotHolder>asList(new ConfigSnapshotHolderImpl(lineProcessor.getConfigSnapshot().get(),
-                    lineProcessor.getCapabilities(), storage.getAbsolutePath()));
-        }
-
-    }
-
-    private static final class LineProcessor implements com.google.common.io.LineProcessor<String> {
-
-        private boolean inLastConfig, inLastSnapshot;
-        private final StringBuffer snapshotBuffer = new StringBuffer();
-        private final SortedSet<String> caps = new TreeSet<>();
-
-        @Override
-        public String getResult() {
-            return null;
-        }
-
-        @Override
-        public boolean processLine(String line) throws IOException {
-            if (inLastConfig && line.equals(SEPARATOR_E_PURE)) {
-                inLastConfig = false;
-                return false;
-            }
-
-            if (inLastConfig && line.equals(SEPARATOR_M_PURE)) {
-                inLastSnapshot = false;
-                return true;
-            }
-
-            if (inLastConfig) {
-                if (inLastSnapshot) {
-                    snapshotBuffer.append(line);
-                    snapshotBuffer.append(System.lineSeparator());
-                } else {
-                    caps.add(line);
-                }
-            }
-
-            if (line.equals(SEPARATOR_SL_PURE)) {
-                inLastConfig = true;
-                inLastSnapshot = true;
-            }
-
-            return true;
-        }
-
-        Optional<String> getConfigSnapshot() {
-            final String xmlContent = snapshotBuffer.toString();
-            if (xmlContent.equals("")) {
-                return Optional.absent();
-            } else {
-                return Optional.of(xmlContent);
-            }
-        }
-
-        SortedSet<String> getCapabilities() {
-            return caps;
-        }
-
-    }
-
-    @Override
-    public void close() {
-
-    }
-
-    @Override
-    public String toString() {
-        return "FileStorageAdapter [storage=" + storage + "]";
-    }
-
-}
diff --git a/opendaylight/config/config-persister-file-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/file/FileStorageAdapterTest.java b/opendaylight/config/config-persister-file-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/file/FileStorageAdapterTest.java
deleted file mode 100644 (file)
index 0366dbc..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * 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.persist.storage.file;
-
-import com.google.common.base.Charsets;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Collections2;
-import java.io.File;
-import java.nio.file.Files;
-import java.util.Collection;
-import java.util.List;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mockito;
-import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
-import org.opendaylight.controller.config.persist.api.Persister;
-import org.opendaylight.controller.config.persist.test.PropertiesProviderTest;
-import static junit.framework.Assert.assertFalse;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-
-public class FileStorageAdapterTest {
-
-    private static int i;
-    private File file;
-
-    @Before
-    public void setUp() throws Exception {
-        file = Files.createTempFile("testFilePersist", ".txt").toFile();
-        if (!file.exists())
-            return;
-        com.google.common.io.Files.write("", file, Charsets.UTF_8);
-        i = 1;
-    }
-
-
-    @Test
-    public void testFileAdapterAsPersister() throws Exception {
-        FileStorageAdapter storage = new FileStorageAdapter();
-        PropertiesProviderTest pp = new PropertiesProviderTest();
-        pp.addProperty("fileStorage",file.getPath());
-        pp.addProperty("numberOfBackups",Integer.toString(Integer.MAX_VALUE));
-
-        Persister configPersister = storage.instantiate(pp);
-        final ConfigSnapshotHolder holder = new ConfigSnapshotHolder() {
-            @Override
-            public String getConfigSnapshot() {
-                return createConfig();
-            }
-
-            @Override
-            public SortedSet<String> getCapabilities() {
-                return createCaps();
-            }
-        };
-        configPersister.persistConfig(holder);
-
-        configPersister.persistConfig(holder);
-
-        Collection<String> readLines = Collections2.filter(com.google.common.io.Files.readLines(file, Charsets.UTF_8),
-                new Predicate<String>() {
-
-                    @Override
-                    public boolean apply(String input) {
-                        if (input.equals(""))
-                            return false;
-                        return true;
-                    }
-                });
-        assertEquals(14, readLines.size());
-
-        List<ConfigSnapshotHolder> lastConf = storage.loadLastConfigs();
-        assertEquals(1, lastConf.size());
-        ConfigSnapshotHolder configSnapshotHolder = lastConf.get(0);
-        assertEquals("<config>2</config>",
-                configSnapshotHolder.getConfigSnapshot().replaceAll("\\s", ""));
-        assertEquals(createCaps(), configSnapshotHolder.getCapabilities());
-    }
-    @Test
-    public void testFileAdapter() throws Exception {
-        FileStorageAdapter storage = new FileStorageAdapter();
-        storage.setFileStorage(file);
-        storage.setNumberOfBackups(Integer.MAX_VALUE);
-        final ConfigSnapshotHolder holder = new ConfigSnapshotHolder() {
-            @Override
-            public String getConfigSnapshot() {
-                return createConfig();
-            }
-
-            @Override
-            public SortedSet<String> getCapabilities() {
-                return createCaps();
-            }
-        };
-        storage.persistConfig(holder);
-
-        storage.persistConfig(holder);
-
-        Collection<String> readLines = Collections2.filter(com.google.common.io.Files.readLines(file, Charsets.UTF_8),
-                new Predicate<String>() {
-
-                    @Override
-                    public boolean apply(String input) {
-                        if (input.equals(""))
-                            return false;
-                        return true;
-                    }
-                });
-        assertEquals(14, readLines.size());
-
-        List<ConfigSnapshotHolder> lastConf = storage.loadLastConfigs();
-        assertEquals(1, lastConf.size());
-        ConfigSnapshotHolder configSnapshotHolder = lastConf.get(0);
-        assertEquals("<config>2</config>",
-                configSnapshotHolder.getConfigSnapshot().replaceAll("\\s", ""));
-        assertEquals(createCaps(), configSnapshotHolder.getCapabilities());
-    }
-
-    private SortedSet<String> createCaps() {
-        SortedSet<String> caps = new TreeSet<>();
-
-        caps.add("cap1");
-        caps.add("cap2");
-        caps.add("capaaaa as dasfasdf s2");
-        return caps;
-    }
-
-    @Test
-    public void testFileAdapterOneBackup() throws Exception {
-        FileStorageAdapter storage = new FileStorageAdapter();
-        storage.setFileStorage(file);
-        storage.setNumberOfBackups(1);
-        final ConfigSnapshotHolder holder = new ConfigSnapshotHolder() {
-            @Override
-            public String getConfigSnapshot() {
-                return createConfig();
-            }
-
-            @Override
-            public SortedSet<String> getCapabilities() {
-                return createCaps();
-            }
-        };
-        storage.persistConfig(holder);
-
-        storage.persistConfig(holder);
-
-        Collection<String> readLines = Collections2.filter(com.google.common.io.Files.readLines(file, Charsets.UTF_8),
-                new Predicate<String>() {
-
-                    @Override
-                    public boolean apply(String input) {
-                        if (input.equals(""))
-                            return false;
-                        return true;
-                    }
-                });
-        assertEquals(7, readLines.size());
-
-        List<ConfigSnapshotHolder> lastConf = storage.loadLastConfigs();
-        assertEquals(1, lastConf.size());
-        ConfigSnapshotHolder configSnapshotHolder = lastConf.get(0);
-        assertEquals("<config>2</config>",
-                configSnapshotHolder.getConfigSnapshot().replaceAll("\\s", ""));
-    }
-
-    @Test
-    public void testFileAdapterOnlyTwoBackups() throws Exception {
-        FileStorageAdapter storage = new FileStorageAdapter();
-        storage.setFileStorage(file);
-        storage.setNumberOfBackups(2);
-        final ConfigSnapshotHolder holder = new ConfigSnapshotHolder() {
-            @Override
-            public String getConfigSnapshot() {
-                return createConfig();
-            }
-
-            @Override
-            public SortedSet<String> getCapabilities() {
-                return createCaps();
-            }
-        };
-        storage.persistConfig(holder);
-
-        storage.persistConfig(holder);
-        storage.persistConfig(holder);
-
-        Collection<String> readLines = Collections2.filter(com.google.common.io.Files.readLines(file, Charsets.UTF_8),
-                new Predicate<String>() {
-
-                    @Override
-                    public boolean apply(String input) {
-                        if (input.equals(""))
-                            return false;
-                        return true;
-                    }
-                });
-
-        assertEquals(14, readLines.size());
-
-        List<ConfigSnapshotHolder> lastConf = storage.loadLastConfigs();
-        assertEquals(1, lastConf.size());
-        ConfigSnapshotHolder configSnapshotHolder = lastConf.get(0);
-        assertEquals("<config>3</config>",
-                configSnapshotHolder.getConfigSnapshot().replaceAll("\\s", ""));
-        assertFalse(readLines.contains(holder.getConfigSnapshot()));
-    }
-
-    @Test
-    public void testNoLastConfig() throws Exception {
-        File file = Files.createTempFile("testFilePersist", ".txt").toFile();
-        if (!file.exists())
-            return;
-        FileStorageAdapter storage = new FileStorageAdapter();
-        storage.setFileStorage(file);
-
-        List<ConfigSnapshotHolder> elementOptional = storage.loadLastConfigs();
-        assertThat(elementOptional.size(), is(0));
-    }
-
-    @Test(expected = NullPointerException.class)
-    public void testNoProperties() throws Exception {
-        FileStorageAdapter storage = new FileStorageAdapter();
-        storage.loadLastConfigs();
-    }
-
-    @Test(expected = NullPointerException.class)
-    public void testNoProperties2() throws Exception {
-        FileStorageAdapter storage = new FileStorageAdapter();
-        storage.persistConfig(new ConfigSnapshotHolder() {
-            @Override
-            public String getConfigSnapshot() {
-                return Mockito.mock(String.class);
-            }
-
-            @Override
-            public SortedSet<String> getCapabilities() {
-                return new TreeSet<>();
-            }
-        } );
-    }
-
-    static String createConfig() {
-        return "<config>" + i++ + "</config>";
-    }
-
-}
index 6b55b6ad16ab85e6f15dd30eb96e2dbc9ed1ad44..d700075e950030e77856de1b84a2382878653055 100644 (file)
@@ -23,7 +23,6 @@
         <module>config-plugin-parent</module>
         <module>config-util</module>
         <module>config-persister-api</module>
-        <module>config-persister-file-adapter</module>
         <module>config-persister-file-xml-adapter</module>
         <module>yang-jmx-generator</module>
         <module>yang-jmx-generator-plugin</module>
@@ -35,9 +34,7 @@
         <module>netty-threadgroup-config</module>
         <module>netty-event-executor-config</module>
         <module>netty-timer-config</module>
-        <module>config-persister-directory-adapter</module>
         <module>config-persister-directory-xml-adapter</module>
-        <module>config-persister-directory-autodetect-adapter</module>
         <module>yang-test-plugin</module>
         <module>shutdown-api</module>
         <module>shutdown-impl</module>
index a38a9b4f935cd401428dd2c0b86f3e24024fd01c..a6d1019c42f03da052a5012047d83c201059bfa1 100644 (file)
                     <groupId>org.opendaylight.controller</groupId>
                     <artifactId>config-persister-api</artifactId>
                 </dependency>
-                <dependency>
-                    <groupId>org.opendaylight.controller</groupId>
-                    <artifactId>config-persister-file-adapter</artifactId>
-                </dependency>
                 <dependency>
                     <groupId>org.opendaylight.controller</groupId>
                     <artifactId>config-persister-file-xml-adapter</artifactId>
                 </dependency>
-                <dependency>
-                    <groupId>org.opendaylight.controller</groupId>
-                    <artifactId>config-persister-directory-adapter</artifactId>
-                </dependency>
                 <dependency>
                     <groupId>org.opendaylight.controller</groupId>
                     <artifactId>config-persister-directory-xml-adapter</artifactId>
                 </dependency>
-                <dependency>
-                    <groupId>org.opendaylight.controller</groupId>
-                    <artifactId>config-persister-directory-autodetect-adapter</artifactId>
-                </dependency>
 
                 <dependency>
                     <groupId>org.opendaylight.controller</groupId>
index 4598bac593269d026bdcf32dd295ecaf5eb2af37..e91a13b9f2dda31dc53860ea9c1563316d3f896b 100644 (file)
@@ -26,22 +26,12 @@ netconf.ssh.pk.path = ./configuration/RSA.pk
 
 netconf.config.persister.active=1,2
 # read startup configuration
-#netconf.config.persister.1.storageAdapterClass=org.opendaylight.controller.config.persist.storage.directory.DirectoryStorageAdapter
-#netconf.config.persister.1.properties.directoryStorage=configuration/initial/
-#netconf.config.persister.1.readonly=true
-
-netconf.config.persister.1.storageAdapterClass=org.opendaylight.controller.config.persist.storage.directory.autodetect.AutodetectDirectoryStorageAdapter
+netconf.config.persister.1.storageAdapterClass=org.opendaylight.controller.config.persist.storage.directory.xml.XmlDirectoryStorageAdapter
 netconf.config.persister.1.properties.directoryStorage=configuration/initial/
+# include only xml files, files with other extensions will be skipped, multiple extensions are permitted e.g. netconf.config.persister.1.properties.includeExtensions=xml,cfg,config
+netconf.config.persister.1.properties.includeExtensions=xml
 netconf.config.persister.1.readonly=true
 
-#netconf.config.persister.3.storageAdapterClass=org.opendaylight.controller.config.persist.storage.directory.xml.XmlDirectoryStorageAdapter
-#netconf.config.persister.3.properties.directoryStorage=configuration/initialXml/
-#netconf.config.persister.3.readonly=true
-
-#netconf.config.persister.4.storageAdapterClass=org.opendaylight.controller.config.persist.storage.file.FileStorageAdapter
-#netconf.config.persister.4.properties.fileStorage=configuration/current/controller.currentconfig.txt
-#netconf.config.persister.4.properties.numberOfBackups=1
-
 netconf.config.persister.2.storageAdapterClass=org.opendaylight.controller.config.persist.storage.file.xml.XmlFileStorageAdapter
 netconf.config.persister.2.properties.fileStorage=configuration/current/controller.currentconfig.xml
 netconf.config.persister.2.properties.numberOfBackups=1
index de9ac232e871a6f018839ba9c15974a34fbc29b3..619ab06d8d3c3da7ca181949b4fff7ddd7596e6e 100644 (file)
@@ -1,26 +1,62 @@
-<snapshot>
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ 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
+-->
+<snapshot>
     <configuration>
-    
         <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
             <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
                 <module>
                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang: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>
+                </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 -->
                 </module>
                 <module>
                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-broker-impl</type>
@@ -42,6 +78,7 @@
                     <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>
+                <!-- 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>
                         <name>runtime-mapping-singleton</name>
                     </mapping-service>
                 </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>
+                    <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>
+                    </dom-async-broker>
+                    <binding-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>
+                    </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>
-                       <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>
-                       <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: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-broker'][name='binding-data-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="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: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>
 
             </services>
         </data>
-
     </configuration>
-    
     <required-capabilities>
         <capability>urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor?module=netty-event-executor&amp;revision=2013-11-12</capability>
         <capability>urn:opendaylight:params:xml:ns:yang:controller:threadpool?module=threadpool&amp;revision=2013-04-09</capability>
         <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&amp;revision=2013-10-28</capability>
         <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&amp;revision=2013-10-28</capability>
     </required-capabilities>
-
 </snapshot>
-
index 74e7d1afe74910bcc55a3a1e1a3b9c52a546060c..01e5ae0372b06d6bf54138dd9bb9df948f1d551b 100644 (file)
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
-            <artifactId>config-persister-file-adapter</artifactId>
+            <artifactId>config-persister-file-xml-adapter</artifactId>
             <version>${config.version}</version>
         </dependency>
         <dependency>
             <artifactId>config-persister-impl</artifactId>
             <version>${config.version}</version>
         </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>config-persister-file-adapter</artifactId>
-            <version>${config.version}</version>
-        </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>netconf-impl</artifactId>
index fe545b09888c6153b225f8467bab4456134f4cfe..6a9712b1c6a41a093bd905996606290b4e33289e 100644 (file)
@@ -132,8 +132,10 @@ public class MDFlowMapping {
 
         val sourceActions = sourceFlow.actions;
         val targetActions = new ArrayList<Action>();
+        var int action = 0;
         for (sourceAction : sourceActions) {
-            targetActions.add(sourceAction.toAction());
+            targetActions.add(sourceAction.toAction(action));
+            action = action + 1;
         }
         instructions = targetActions.toApplyInstruction();
         match = sourceFlow.match.toMatch();
@@ -154,8 +156,10 @@ public class MDFlowMapping {
     
        val sourceActions = sourceFlow.actions;
        val targetActions = new ArrayList<Action>();
+       var int action = 0;
        for (sourceAction : sourceActions) {
-           targetActions.add(sourceAction.toAction());
+           targetActions.add(sourceAction.toAction(action));
+           action = action+ 1;
        }
        instructions = targetActions.toApplyInstruction();
        match = sourceFlow.match.toMatch();
@@ -199,44 +203,44 @@ public class MDFlowMapping {
         return it.build();
     }
 
-    public static dispatch def toAction(Controller sourceAction) {
-        val actionBuilder = new ActionBuilder();
+    public static dispatch def toAction(Controller sourceAction, int order) {
+        val actionBuilder = new ActionBuilder().setOrder(order);
         actionBuilder.action = new ControllerActionCaseBuilder().setControllerAction(new ControllerActionBuilder().build()).build();
         return actionBuilder.build();
     }
 
-    public static dispatch def toAction(Drop sourceAction) {
-        val actionBuilder = new ActionBuilder();
+    public static dispatch def toAction(Drop sourceAction, int order) {
+        val actionBuilder = new ActionBuilder().setOrder(order);
         actionBuilder.action = new DropActionCaseBuilder().setDropAction(new DropActionBuilder().build()).build();
         return actionBuilder.build();
     }
 
-    public static dispatch def toAction(Flood sourceAction) {
-        val actionBuilder = new ActionBuilder();
+    public static dispatch def toAction(Flood sourceAction, int order) {
+        val actionBuilder = new ActionBuilder().setOrder(order);
         actionBuilder.action = new FloodActionCaseBuilder().setFloodAction(new FloodActionBuilder().build).build();
         return actionBuilder.build();
     }
 
-    public static dispatch def toAction(FloodAll sourceAction) {
-        val actionBuilder = new ActionBuilder();
+    public static dispatch def toAction(FloodAll sourceAction, int order) {
+        val actionBuilder = new ActionBuilder().setOrder(order);
         actionBuilder.action = new FloodAllActionCaseBuilder().setFloodAllAction(new FloodAllActionBuilder().build()).build();
         return actionBuilder.build();
     }
 
-    public static dispatch def toAction(HwPath sourceAction) {
-        val actionBuilder = new ActionBuilder();
+    public static dispatch def toAction(HwPath sourceAction, int order) {
+        val actionBuilder = new ActionBuilder().setOrder(order);
         actionBuilder.action = new HwPathActionCaseBuilder().setHwPathAction(new HwPathActionBuilder().build()).build();
         return actionBuilder.build();
     }
 
-    public static dispatch def toAction(Loopback sourceAction) {
-        val actionBuilder = new ActionBuilder();
+    public static dispatch def toAction(Loopback sourceAction, int order) {
+        val actionBuilder = new ActionBuilder().setOrder(order);
         actionBuilder.action = new LoopbackActionCaseBuilder().setLoopbackAction(new LoopbackActionBuilder().build()).build();
         return actionBuilder.build();
     }
 
-    public static dispatch def toAction(Output sourceAction) {
-        val actionBuilder = new ActionBuilder();
+    public static dispatch def toAction(Output sourceAction, int order) {
+        val actionBuilder = new ActionBuilder().setOrder(order);
         val it = new OutputActionBuilder();
         outputNodeConnector = sourceAction.port.toUri;
         actionBuilder.action = new OutputActionCaseBuilder().setOutputAction(it.build()).build();
@@ -244,14 +248,14 @@ public class MDFlowMapping {
 
     }
 
-    public static dispatch def toAction(PopVlan sourceAction) {
-        val actionBuilder = new ActionBuilder();
+    public static dispatch def toAction(PopVlan sourceAction, int order) {
+        val actionBuilder = new ActionBuilder().setOrder(order);
         actionBuilder.action = new PopVlanActionCaseBuilder().build();
         return actionBuilder.build();
     }
 
-    public static dispatch def toAction(PushVlan sourceAction) {
-        val actionBuilder = new ActionBuilder();
+    public static dispatch def toAction(PushVlan sourceAction, int order) {
+        val actionBuilder = new ActionBuilder().setOrder(order);
         val it = new PushVlanActionBuilder();
         cfi = new VlanCfi(sourceAction.cfi);
         vlanId = new VlanId(sourceAction.vlanId);
@@ -261,32 +265,32 @@ public class MDFlowMapping {
         return actionBuilder.build();
     }
 
-    public static dispatch def toAction(SetDlDst sourceAction) {
-        val actionBuilder = new ActionBuilder();
+    public static dispatch def toAction(SetDlDst sourceAction, int order) {
+        val actionBuilder = new ActionBuilder().setOrder(order);
         val it = new SetDlDstActionBuilder();
         address = sourceAction.dlAddress.toMacAddress();
         actionBuilder.action = new SetDlDstActionCaseBuilder().setSetDlDstAction(it.build()).build;
         return actionBuilder.build();
     }
 
-    public static dispatch def toAction(SetDlSrc sourceAction) {
-        val actionBuilder = new ActionBuilder();
+    public static dispatch def toAction(SetDlSrc sourceAction, int order) {
+        val actionBuilder = new ActionBuilder().setOrder(order);
         val it = new SetDlSrcActionBuilder();
         address = sourceAction.dlAddress.toMacAddress;
         actionBuilder.action = new SetDlSrcActionCaseBuilder().setSetDlSrcAction(it.build()).build;
         return actionBuilder.build();
     }
 
-    public static dispatch def toAction(SetDlType sourceAction) {
-        val actionBuilder = new ActionBuilder();
+    public static dispatch def toAction(SetDlType sourceAction, int order) {
+        val actionBuilder = new ActionBuilder().setOrder(order);
         val it = new SetDlTypeActionBuilder();
         dlType = new EtherType(sourceAction.dlType as long);
         actionBuilder.action = new SetDlTypeActionCaseBuilder().setSetDlTypeAction(it.build()).build();
         return actionBuilder.build();
     }
 
-    public static dispatch def toAction(SetNextHop sourceAction) {
-        val actionBuilder = new ActionBuilder();
+    public static dispatch def toAction(SetNextHop sourceAction, int order) {
+        val actionBuilder = new ActionBuilder().setOrder(order);
         val it = new SetNextHopActionBuilder();
         val inetAddress = sourceAction.address;
         address = inetAddress.toInetAddress;
@@ -294,8 +298,8 @@ public class MDFlowMapping {
         return actionBuilder.build();
     }
 
-    public static dispatch def toAction(SetNwDst sourceAction) {
-        val actionBuilder = new ActionBuilder();
+    public static dispatch def toAction(SetNwDst sourceAction, int order) {
+        val actionBuilder = new ActionBuilder().setOrder(order);
         val it = new SetNwDstActionBuilder();
         val inetAddress = sourceAction.address;
         address = inetAddress.toInetAddress;
@@ -303,8 +307,8 @@ public class MDFlowMapping {
         return actionBuilder.build();
     }
 
-    public static dispatch def toAction(SetNwSrc sourceAction) {
-        val actionBuilder = new ActionBuilder();
+    public static dispatch def toAction(SetNwSrc sourceAction, int order) {
+        val actionBuilder = new ActionBuilder().setOrder(order);
         val it = new SetNwSrcActionBuilder();
         val inetAddress = sourceAction.address;
         address = inetAddress.toInetAddress;
@@ -312,40 +316,40 @@ public class MDFlowMapping {
         return actionBuilder.build();
     }
 
-    public static dispatch def toAction(SetNwTos sourceAction) {
-        val actionBuilder = new ActionBuilder();
+    public static dispatch def toAction(SetNwTos sourceAction, int order) {
+        val actionBuilder = new ActionBuilder().setOrder(order);
         val it = new SetNwTosActionBuilder();
         tos = sourceAction.nwTos;
         actionBuilder.action = new SetNwTosActionCaseBuilder().setSetNwTosAction(it.build).build;
         return actionBuilder.build();
     }
 
-    public static dispatch def toAction(SetTpDst sourceAction) {
-        val actionBuilder = new ActionBuilder();
+    public static dispatch def toAction(SetTpDst sourceAction, int order) {
+        val actionBuilder = new ActionBuilder().setOrder(order);
         val it = new SetTpDstActionBuilder();
         port = new PortNumber(sourceAction.port);
         actionBuilder.action = new SetTpDstActionCaseBuilder().setSetTpDstAction(it.build()).build();
         return actionBuilder.build();
     }
 
-    public static dispatch def toAction(SetTpSrc sourceAction) {
-        val actionBuilder = new ActionBuilder();
+    public static dispatch def toAction(SetTpSrc sourceAction, int order) {
+        val actionBuilder = new ActionBuilder().setOrder(order);
         val it = new SetTpSrcActionBuilder();
         port = new PortNumber(sourceAction.port);
         actionBuilder.action = new SetTpSrcActionCaseBuilder().setSetTpSrcAction(it.build()).build();
         return actionBuilder.build();
     }
 
-    public static dispatch def toAction(SetVlanCfi sourceAction) {
-        val actionBuilder = new ActionBuilder();
+    public static dispatch def toAction(SetVlanCfi sourceAction, int order) {
+        val actionBuilder = new ActionBuilder().setOrder(order);
         val it = new SetVlanCfiActionBuilder();
         vlanCfi = new VlanCfi(sourceAction.cfi);
         actionBuilder.action = new SetVlanCfiActionCaseBuilder().setSetVlanCfiAction(it.build()).build();
         return actionBuilder.build();
     }
 
-    public static dispatch def toAction(SetVlanId sourceAction) {
-        val actionBuilder = new ActionBuilder();
+    public static dispatch def toAction(SetVlanId sourceAction, int order) {
+        val actionBuilder = new ActionBuilder().setOrder(order);
 
         val it = new SetVlanIdActionBuilder();
         vlanId = new VlanId(sourceAction.vlanId);
@@ -353,16 +357,16 @@ public class MDFlowMapping {
         return actionBuilder.build();
     }
 
-    public static dispatch def toAction(SetVlanPcp sourceAction) {
-        val actionBuilder = new ActionBuilder();
+    public static dispatch def toAction(SetVlanPcp sourceAction, int order) {
+        val actionBuilder = new ActionBuilder().setOrder(order);
         val it = new SetVlanPcpActionBuilder();
         vlanPcp = new VlanPcp(sourceAction.pcp as short);
         actionBuilder.action = new SetVlanPcpActionCaseBuilder().setSetVlanPcpAction(it.build).build;
         return actionBuilder.build();
     }
 
-    public static dispatch def toAction(SwPath sourceAction) {
-        val actionBuilder = new ActionBuilder();
+    public static dispatch def toAction(SwPath sourceAction, int order) {
+        val actionBuilder = new ActionBuilder().setOrder(order);
         actionBuilder.action = new SwPathActionCaseBuilder().setSwPathAction(new SwPathActionBuilder().build()).build();
         return actionBuilder.build();
     }
@@ -405,8 +409,10 @@ public class MDFlowMapping {
 
         val sourceActions = sourceFlow.actions;
         val targetActions = new ArrayList<Action>();
+        var int action = 0;
         for (sourceAction : sourceActions) {
-            targetActions.add(sourceAction.toAction());
+            targetActions.add(sourceAction.toAction(action));
+            action = action + 1;
         }
         instructions = targetActions.toApplyInstruction();
         match = sourceFlow.match.toMatch();
index 43f48a50e56175a2297e78e32478f80404ff839d..ec8da8693fd5dd83379377786a6c3dc015797d34 100644 (file)
@@ -60,75 +60,4 @@ class FlowCapableInventoryProvider implements AutoCloseable {
         listenerRegistration?.close();
     }
     
-}
-
-class NodeChangeCommiter implements OpendaylightInventoryListener {
-
-    static val LOG = LoggerFactory.getLogger(NodeChangeCommiter);
-
-    @Property
-    val FlowCapableInventoryProvider manager;
-
-    new(FlowCapableInventoryProvider manager) {
-        _manager = manager;
-    }
-
-    override onNodeConnectorRemoved(NodeConnectorRemoved connector) {
-        val ref = connector.nodeConnectorRef;
-
-        // Check path
-        val it = manager.startChange()
-
-        LOG.debug("removing node connector : " + ref.value.toString());
-
-        removeOperationalData(ref.value as InstanceIdentifier<? extends DataObject>);
-        commit()
-    }
-
-    override onNodeConnectorUpdated(NodeConnectorUpdated connector) {
-        val ref = connector.nodeConnectorRef;
-
-        val flowConnector = connector.getAugmentation(FlowCapableNodeConnectorUpdated);
-
-        val it = manager.startChange()
-        val data = new NodeConnectorBuilder(connector);
-        data.key = (new NodeConnectorKey(connector.id))
-        if (flowConnector != null) {
-            val augment = flowConnector.toInventoryAugment()
-            data.addAugmentation(FlowCapableNodeConnector, augment)
-        }
-
-        LOG.debug("updating node connector : " + ref.value.toString());
-
-        putOperationalData(ref.value as InstanceIdentifier<NodeConnector>, data.build());
-        commit()
-    }
-
-    override onNodeRemoved(NodeRemoved node) {
-        val ref = node.nodeRef;
-        val it = manager.startChange()
-
-        LOG.debug("removing node : " + ref.value.toString());
-
-        removeOperationalData(ref.value as InstanceIdentifier<? extends DataObject>);
-        commit()
-    }
-
-    override onNodeUpdated(NodeUpdated node) {
-        val ref = node.nodeRef;
-        val flowNode = node.getAugmentation(FlowCapableNodeUpdated);
-
-        val it = manager.startChange()
-        val data = new NodeBuilder(node);
-        data.key = (new NodeKey(node.id))
-        if (flowNode != null) {
-            val augment = flowNode.toInventoryAugment();
-            data.addAugmentation(FlowCapableNode, augment)
-        }
-
-        LOG.debug("updating node : " + ref.value.toString());
-
-        putOperationalData(ref.value as InstanceIdentifier<Node>, data.build())
-        commit()
-    }
-}
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/NodeChangeCommiter.java b/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/NodeChangeCommiter.java
new file mode 100644 (file)
index 0000000..ebb3de7
--- /dev/null
@@ -0,0 +1,159 @@
+/**
+ * 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.md.inventory.manager;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.OpendaylightInventoryListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Objects;
+
+@SuppressWarnings("all")
+public class NodeChangeCommiter implements OpendaylightInventoryListener {
+    private final static Logger LOG = LoggerFactory.getLogger(NodeChangeCommiter.class);
+
+    private final FlowCapableInventoryProvider manager;
+
+    public NodeChangeCommiter(final FlowCapableInventoryProvider manager) {
+        this.manager = manager;
+    }
+
+    public FlowCapableInventoryProvider getManager() {
+        return this.manager;
+    }
+
+    @Override
+    public synchronized void onNodeConnectorRemoved(final NodeConnectorRemoved connector) {
+
+        final NodeConnectorRef ref = connector.getNodeConnectorRef();
+        final DataModificationTransaction it = this.getManager().startChange();
+        NodeChangeCommiter.LOG.debug("removing node connector {} ", ref.getValue());
+        it.removeOperationalData(ref.getValue());
+        Future<RpcResult<TransactionStatus>> commitResult = it.commit();
+        try {
+            commitResult.get();
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error("Node Connector {} not removed.", ref.getValue(), e);
+        }
+
+    }
+
+    @Override
+    public synchronized void onNodeConnectorUpdated(final NodeConnectorUpdated connector) {
+
+        final NodeConnectorRef ref = connector.getNodeConnectorRef();
+        final FlowCapableNodeConnectorUpdated flowConnector = connector
+                .getAugmentation(FlowCapableNodeConnectorUpdated.class);
+        final DataModificationTransaction it = this.getManager().startChange();
+        final NodeConnectorBuilder data = new NodeConnectorBuilder(connector);
+        NodeConnectorId id = connector.getId();
+        NodeConnectorKey nodeConnectorKey = new NodeConnectorKey(id);
+        data.setKey(nodeConnectorKey);
+        boolean notEquals = (!Objects.equal(flowConnector, null));
+        if (notEquals) {
+            final FlowCapableNodeConnector augment = InventoryMapping.toInventoryAugment(flowConnector);
+            data.addAugmentation(FlowCapableNodeConnector.class, augment);
+        }
+        InstanceIdentifier<? extends Object> value = ref.getValue();
+        String string = value.toString();
+        String plus = ("updating node connector : " + string);
+        NodeChangeCommiter.LOG.debug(plus);
+        InstanceIdentifier<? extends Object> value1 = ref.getValue();
+        NodeConnector build = data.build();
+        it.putOperationalData((value1), build);
+        Future<RpcResult<TransactionStatus>> commitResult = it.commit();
+        try {
+            commitResult.get();
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error("Node Connector {} not updated.", ref.getValue(), e);
+        }
+
+    }
+
+    @Override
+    public synchronized void onNodeRemoved(final NodeRemoved node) {
+
+        final NodeRef ref = node.getNodeRef();
+        FlowCapableInventoryProvider manager = this.getManager();
+        final DataModificationTransaction it = manager.startChange();
+        InstanceIdentifier<? extends Object> value = ref.getValue();
+        String string = value.toString();
+        String plus = ("removing node : " + string);
+        NodeChangeCommiter.LOG.debug(plus);
+        InstanceIdentifier<? extends Object> value1 = ref.getValue();
+        it.removeOperationalData((value1));
+        Future<RpcResult<TransactionStatus>> commitResult = it.commit();
+        try {
+            commitResult.get();
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error("Node {} not removed.", ref.getValue(), e);
+        }
+    }
+
+    @Override
+    public synchronized void onNodeUpdated(final NodeUpdated node) {
+
+        final NodeRef ref = node.getNodeRef();
+        final FlowCapableNodeUpdated flowNode = node
+                .<FlowCapableNodeUpdated> getAugmentation(FlowCapableNodeUpdated.class);
+        FlowCapableInventoryProvider manager = this.getManager();
+        final DataModificationTransaction it = manager.startChange();
+        NodeBuilder nodeBuilder = new NodeBuilder(node);
+        final NodeBuilder data = nodeBuilder;
+        NodeId id = node.getId();
+        NodeKey nodeKey = new NodeKey(id);
+        data.setKey(nodeKey);
+        boolean equals = Objects.equal(flowNode, null);
+        if (equals) {
+            return;
+        }
+        final FlowCapableNode augment = InventoryMapping.toInventoryAugment(flowNode);
+        data.addAugmentation(FlowCapableNode.class, augment);
+        InstanceIdentifier<? extends Object> value = ref.getValue();
+        InstanceIdentifierBuilder<Node> builder = InstanceIdentifier.<Node> builder(((InstanceIdentifier<Node>) value));
+        InstanceIdentifierBuilder<FlowCapableNode> augmentation = builder
+                .<FlowCapableNode> augmentation(FlowCapableNode.class);
+        final InstanceIdentifier<FlowCapableNode> path = augmentation.build();
+        NodeChangeCommiter.LOG.debug("updating node :{} ", path);
+        it.putOperationalData(path, augment);
+
+        Future<RpcResult<TransactionStatus>> commitResult = it.commit();
+        try {
+            commitResult.get();
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error("Node  {} not updated.", ref.getValue(), e);
+        }
+
+    }
+}
index dea455bfa1a53e3f7c02175c99905747098a9620..dafb3ef6343c895385ebe99aee565e7d082182cd 100644 (file)
                             org.opendaylight.controller.sal.binding.impl.*,
                             org.opendaylight.controller.sal.binding.codegen,
                             org.opendaylight.controller.sal.binding.codegen.*,
+                            org.opendaylight.controller.md.sal.binding.impl,
                             <!--org.opendaylight.controller.sal.binding.dom.*,-->
                             org.opendaylight.controller.sal.binding.osgi.*,
                             org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.binding.impl.rev131028
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/ForwardedCompatibleDataBrokerImplModule.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/ForwardedCompatibleDataBrokerImplModule.java
new file mode 100644 (file)
index 0000000..647ca85
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * 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.config.yang.md.sal.binding.impl;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.opendaylight.controller.md.sal.binding.impl.ForwardedBackwardsCompatibleDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingDomConnectorDeployer;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.Provider;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+import org.osgi.framework.BundleContext;
+
+import com.google.common.util.concurrent.ListeningExecutorService;
+
+/**
+*
+*/
+public final class ForwardedCompatibleDataBrokerImplModule extends
+        org.opendaylight.controller.config.yang.md.sal.binding.impl.AbstractForwardedCompatibleDataBrokerImplModule
+        implements Provider {
+
+    private BundleContext bundleContext;
+
+    public ForwardedCompatibleDataBrokerImplModule(
+            final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public ForwardedCompatibleDataBrokerImplModule(
+            final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+            final ForwardedCompatibleDataBrokerImplModule oldModule, final java.lang.AutoCloseable oldInstance) {
+
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    protected void customValidation() {
+        // Add custom validation for module attributes here.
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        ListeningExecutorService listeningExecutor = SingletonHolder.getDefaultCommitExecutor();
+        BindingIndependentMappingService mappingService = getBindingMappingServiceDependency();
+
+        Broker domBroker = getDomAsyncBrokerDependency();
+        ProviderSession session = domBroker.registerProvider(this, getBundleContext());
+        DOMDataBroker domDataBroker = session.getService(DOMDataBroker.class);
+        ForwardedBackwardsCompatibleDataBroker dataBroker = new ForwardedBackwardsCompatibleDataBroker(domDataBroker,
+                mappingService, listeningExecutor);
+
+        session.getService(SchemaService.class).registerSchemaServiceListener(dataBroker);
+
+        dataBroker.setConnector(BindingDomConnectorDeployer.createConnector(getBindingMappingServiceDependency()));
+        dataBroker.setDomProviderContext(session);
+        return dataBroker;
+    }
+
+    public BundleContext getBundleContext() {
+        return bundleContext;
+    }
+
+    public void setBundleContext(final BundleContext bundleContext2) {
+        this.bundleContext = bundleContext2;
+    }
+
+    @Override
+    public void onSessionInitiated(final ProviderSession session) {
+
+    }
+
+    @Override
+    public Collection<ProviderFunctionality> getProviderFunctionality() {
+        return Collections.emptySet();
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/ForwardedCompatibleDataBrokerImplModuleFactory.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/ForwardedCompatibleDataBrokerImplModuleFactory.java
new file mode 100644 (file)
index 0000000..f019775
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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.config.yang.md.sal.binding.impl;
+
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;
+import org.opendaylight.controller.config.spi.Module;
+import org.osgi.framework.BundleContext;
+
+
+/**
+*
+*/
+public class ForwardedCompatibleDataBrokerImplModuleFactory extends org.opendaylight.controller.config.yang.md.sal.binding.impl.AbstractForwardedCompatibleDataBrokerImplModuleFactory
+{
+
+
+    @Override
+    public Module createModule(final String instanceName, final DependencyResolver dependencyResolver, final BundleContext bundleContext) {
+        ForwardedCompatibleDataBrokerImplModule module = (ForwardedCompatibleDataBrokerImplModule) super.createModule(instanceName, dependencyResolver, bundleContext);
+        module.setBundleContext(bundleContext);
+        return module;
+    }
+
+    @Override
+    public Module createModule(final String instanceName, final DependencyResolver dependencyResolver,
+            final DynamicMBeanWithInstance old, final BundleContext bundleContext) throws Exception {
+        ForwardedCompatibleDataBrokerImplModule module = (ForwardedCompatibleDataBrokerImplModule)  super.createModule(instanceName, dependencyResolver, old, bundleContext);
+        module.setBundleContext(bundleContext);
+        return module;
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractForwardedDataBroker.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractForwardedDataBroker.java
new file mode 100644 (file)
index 0000000..8a32b0b
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.binding.impl;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.eclipse.xtext.xbase.lib.Exceptions;
+import org.opendaylight.controller.md.sal.binding.api.BindingDataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentConnector;
+import org.opendaylight.controller.sal.binding.impl.forward.DomForwardedBroker;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.yangtools.concepts.AbstractListenerRegistration;
+import org.opendaylight.yangtools.concepts.Delegator;
+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.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBroker>, DomForwardedBroker, SchemaContextListener {
+
+    private static final Logger LOG = LoggerFactory.getLogger(AbstractForwardedDataBroker.class);
+    // The Broker to whom we do all forwarding
+    private final DOMDataBroker domDataBroker;
+
+    // Mapper to convert from Binding Independent objects to Binding Aware
+    // objects
+    private final BindingIndependentMappingService mappingService;
+
+    private final BindingToNormalizedNodeCodec codec;
+    private BindingIndependentConnector connector;
+    private ProviderSession context;
+
+    protected AbstractForwardedDataBroker(final DOMDataBroker domDataBroker,
+            final BindingIndependentMappingService mappingService) {
+        this.domDataBroker = domDataBroker;
+        this.mappingService = mappingService;
+        this.codec = new BindingToNormalizedNodeCodec(mappingService);
+    }
+
+    protected BindingToNormalizedNodeCodec getCodec() {
+        return codec;
+    }
+
+    protected BindingIndependentMappingService getMappingService() {
+        return mappingService;
+    }
+
+    @Override
+    public DOMDataBroker getDelegate() {
+        return domDataBroker;
+    }
+
+    @Override
+    public void onGlobalContextUpdated(final SchemaContext ctx) {
+        codec.onGlobalContextUpdated(ctx);
+    }
+
+    public ListenerRegistration<BindingDataChangeListener> registerDataChangeListener(final LogicalDatastoreType store,
+            final InstanceIdentifier<?> path, final BindingDataChangeListener listener,
+            final DataChangeScope triggeringScope) {
+        DOMDataChangeListener domDataChangeListener = new TranslatingDataChangeInvoker(store, path, listener,
+                triggeringScope);
+        org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath = codec.toNormalized(path);
+        ListenerRegistration<DOMDataChangeListener> domRegistration = domDataBroker.registerDataChangeListener(store, domPath, domDataChangeListener, triggeringScope);
+        return new ListenerRegistrationImpl(listener, domRegistration);
+    }
+
+    protected Map<InstanceIdentifier<?>, DataObject> fromDOMToData(
+            final Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, ? extends NormalizedNode<?, ?>> normalized) {
+        Map<InstanceIdentifier<?>, DataObject> newMap = new HashMap<>();
+        for (Map.Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, ? extends NormalizedNode<?, ?>> entry : normalized
+                .entrySet()) {
+            try {
+                Entry<InstanceIdentifier<? extends DataObject>, DataObject> binding = getCodec().toBinding(entry);
+                newMap.put(binding.getKey(), binding.getValue());
+            } catch (DeserializationException e) {
+                LOG.debug("Ommiting {}",entry,e);
+            }
+        }
+        return newMap;
+    }
+
+    private class TranslatingDataChangeInvoker implements DOMDataChangeListener {
+        private final BindingDataChangeListener bindingDataChangeListener;
+        private final LogicalDatastoreType store;
+        private final InstanceIdentifier<?> path;
+        private final DataChangeScope triggeringScope;
+
+        public TranslatingDataChangeInvoker(final LogicalDatastoreType store, final InstanceIdentifier<?> path,
+                final BindingDataChangeListener bindingDataChangeListener, final DataChangeScope triggeringScope) {
+            this.store = store;
+            this.path = path;
+            this.bindingDataChangeListener = bindingDataChangeListener;
+            this.triggeringScope = triggeringScope;
+        }
+
+        @Override
+        public void onDataChanged(
+                final AsyncDataChangeEvent<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> change) {
+            bindingDataChangeListener.onDataChanged(new TranslatedDataChangeEvent(change,path));
+        }
+    }
+
+    private class TranslatedDataChangeEvent implements AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> {
+        private final AsyncDataChangeEvent<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> domEvent;
+        private InstanceIdentifier<?> path;
+
+        public TranslatedDataChangeEvent(
+                final AsyncDataChangeEvent<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> change) {
+            this.domEvent = change;
+        }
+
+        public TranslatedDataChangeEvent(
+                final AsyncDataChangeEvent<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> change,
+                final InstanceIdentifier<?> path) {
+            this.domEvent = change;
+            this.path = path;
+        }
+
+        @Override
+        public Map<InstanceIdentifier<?>, DataObject> getCreatedData() {
+            return fromDOMToData(domEvent.getCreatedData());
+        }
+
+        @Override
+        public Map<InstanceIdentifier<?>, DataObject> getUpdatedData() {
+            return fromDOMToData(domEvent.getUpdatedData());
+
+        }
+
+        @Override
+        public Set<InstanceIdentifier<?>> getRemovedPaths() {
+            final Set<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> removedPaths = domEvent
+                    .getRemovedPaths();
+            final Set<InstanceIdentifier<?>> output = new HashSet<>();
+            for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier instanceIdentifier : removedPaths) {
+                try {
+                    output.add(mappingService.fromDataDom(instanceIdentifier));
+                } catch (DeserializationException e) {
+                    Exceptions.sneakyThrow(e);
+                }
+            }
+
+            return output;
+        }
+
+        @Override
+        public Map<InstanceIdentifier<?>, ? extends DataObject> getOriginalData() {
+            return fromDOMToData(domEvent.getOriginalData());
+
+        }
+
+        @Override
+        public DataObject getOriginalSubtree() {
+
+            return toBindingData(path,domEvent.getOriginalSubtree());
+        }
+
+        @Override
+        public DataObject getUpdatedSubtree() {
+
+            return toBindingData(path,domEvent.getUpdatedSubtree());
+        }
+
+        @Override
+        public String toString() {
+            return "TranslatedDataChangeEvent [domEvent=" + domEvent + "]";
+        }
+    }
+
+    private static class ListenerRegistrationImpl extends AbstractListenerRegistration<BindingDataChangeListener> {
+        private final ListenerRegistration<DOMDataChangeListener> registration;
+
+        public ListenerRegistrationImpl(final BindingDataChangeListener listener,
+                final ListenerRegistration<DOMDataChangeListener> registration) {
+            super(listener);
+            this.registration = registration;
+        }
+
+        @Override
+        protected void removeRegistration() {
+            registration.close();
+        }
+    }
+
+    protected DataObject toBindingData(final InstanceIdentifier<?> path, final NormalizedNode<?, ?> data) {
+        try {
+            return getCodec().toBinding(path, data);
+        } catch (DeserializationException e) {
+            return null;
+        }
+    }
+
+
+    @Override
+    public BindingIndependentConnector getConnector() {
+        return this.connector;
+    }
+
+    @Override
+    public ProviderSession getDomProviderContext() {
+        return this.context;
+    }
+
+    @Override
+    public void setConnector(final BindingIndependentConnector connector) {
+        this.connector = connector;
+    }
+
+    @Override
+    public void setDomProviderContext(final ProviderSession domProviderContext) {
+       this.context = domProviderContext;
+    }
+
+    @Override
+    public void startForwarding() {
+        // NOOP
+    }
+
+
+
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractForwardedTransaction.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractForwardedTransaction.java
new file mode 100644 (file)
index 0000000..4f9c429
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.binding.impl;
+
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.Nullable;
+
+import org.eclipse.xtext.xbase.lib.Exceptions;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationOperation;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
+import org.opendaylight.yangtools.concepts.Delegator;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+public class AbstractForwardedTransaction<T extends AsyncTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>>>
+        implements Delegator<T> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(AbstractForwardedTransaction.class);
+    private final T delegate;
+    private final static CacheBuilder<Object, Object> CACHE_BUILDER = CacheBuilder.newBuilder()
+            .expireAfterWrite(10, TimeUnit.MILLISECONDS).maximumSize(100);
+    private final BindingToNormalizedNodeCodec codec;
+    private final EnumMap<LogicalDatastoreType, Cache<InstanceIdentifier<?>, DataObject>> cacheMap;
+
+    protected AbstractForwardedTransaction(final T delegate, final BindingToNormalizedNodeCodec codec) {
+        super();
+        this.delegate = delegate;
+        this.codec = codec;
+
+        this.cacheMap = new EnumMap<>(LogicalDatastoreType.class);
+        cacheMap.put(LogicalDatastoreType.OPERATIONAL, CACHE_BUILDER.<InstanceIdentifier<?>, DataObject> build());
+        cacheMap.put(LogicalDatastoreType.CONFIGURATION, CACHE_BUILDER.<InstanceIdentifier<?>, DataObject> build());
+
+    }
+
+    @Override
+    public T getDelegate() {
+        return delegate;
+    }
+
+    protected final BindingToNormalizedNodeCodec getCodec() {
+        return codec;
+    }
+
+    protected ListenableFuture<Optional<DataObject>> transformFuture(final LogicalDatastoreType store,
+            final InstanceIdentifier<?> path, final ListenableFuture<Optional<NormalizedNode<?, ?>>> future) {
+        return Futures.transform(future, new Function<Optional<NormalizedNode<?, ?>>, Optional<DataObject>>() {
+            @Nullable
+            @Override
+            public Optional<DataObject> apply(@Nullable final Optional<NormalizedNode<?, ?>> normalizedNode) {
+                try {
+                    final DataObject dataObject = normalizedNode.isPresent() ? codec.toBinding(path,
+                            normalizedNode.get()) : null;
+                    if(dataObject != null) {
+                        updateCache(store, path, dataObject);
+                    }
+                    return Optional.fromNullable(dataObject);
+                } catch (DeserializationException e) {
+                    Exceptions.sneakyThrow(e);
+                }
+                return null;
+            }
+        });
+    }
+
+    protected void doPut(final DOMDataWriteTransaction 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);
+        writeTransaction.put(store, normalized.getKey(), normalized.getValue());
+    }
+
+    protected void doPutWithEnsureParents(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();
+        try {
+            List<PathArgument> currentArguments = new ArrayList<>();
+            DataNormalizationOperation<?> currentOp = codec.getDataNormalizer().getRootOperation();
+            Iterator<PathArgument> iterator = normalizedPath.getPath().iterator();
+            while (iterator.hasNext()) {
+                PathArgument currentArg = iterator.next();
+                currentOp = currentOp.getChild(currentArg);
+                currentArguments.add(currentArg);
+                org.opendaylight.yangtools.yang.data.api.InstanceIdentifier currentPath = new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(
+                        currentArguments);
+                boolean isPresent = writeTransaction.read(store, currentPath).get().isPresent();
+                if (isPresent == false && iterator.hasNext()) {
+                    writeTransaction.put(store, currentPath, currentOp.createDefault(currentArg));
+                }
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            e.printStackTrace();
+        }
+        //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,
+            final InstanceIdentifier<?> path, final DataObject data) {
+        invalidateCache(store, path);
+        final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> normalized = codec
+                .toNormalizedNode(path, data);
+        writeTransaction.merge(store, normalized.getKey(), normalized.getValue());
+    }
+
+    protected void doDelete(final DOMDataWriteTransaction writeTransaction, final LogicalDatastoreType store,
+            final InstanceIdentifier<?> path) {
+        invalidateCache(store, path);
+        final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized = codec.toNormalized(path);
+        writeTransaction.delete(store, normalized);
+    }
+
+    protected ListenableFuture<RpcResult<TransactionStatus>> doCommit(final DOMDataWriteTransaction writeTransaction) {
+        return writeTransaction.commit();
+    }
+
+    protected void doCancel(final DOMDataWriteTransaction writeTransaction) {
+        writeTransaction.cancel();
+    }
+
+    protected ListenableFuture<Optional<DataObject>> doRead(final DOMDataReadTransaction readTransaction,
+            final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
+        final DataObject dataObject = getFromCache(store, path);
+        if (dataObject == null) {
+            final ListenableFuture<Optional<NormalizedNode<?, ?>>> future = readTransaction.read(store,
+                    codec.toNormalized(path));
+            return transformFuture(store, path, future);
+        } else {
+            return Futures.immediateFuture(Optional.of(dataObject));
+        }
+    }
+
+    private DataObject getFromCache(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
+        Cache<InstanceIdentifier<?>, DataObject> cache = cacheMap.get(store);
+        if (cache != null) {
+            return cache.getIfPresent(path);
+        }
+        return null;
+    }
+
+    private void updateCache(final LogicalDatastoreType store, final InstanceIdentifier<?> path,
+            final DataObject dataObject) {
+        // Check if cache exists. If not create one.
+        Cache<InstanceIdentifier<?>, DataObject> cache = cacheMap.get(store);
+        if (cache == null) {
+            cache = CacheBuilder.newBuilder().maximumSize(1000).expireAfterWrite(1, TimeUnit.MINUTES).build();
+
+        }
+
+        cache.put(path, dataObject);
+    }
+
+    private void invalidateCache(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
+        // FIXME: Optimization: invalidate only parents and children of path
+        Cache<InstanceIdentifier<?>, DataObject> cache = cacheMap.get(store);
+        cache.invalidateAll();
+        LOG.trace("Cache invalidated");
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/BindingToNormalizedNodeCodec.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/BindingToNormalizedNodeCodec.java
new file mode 100644 (file)
index 0000000..f885b32
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.binding.impl;
+
+import java.util.AbstractMap.SimpleEntry;
+import java.util.Map.Entry;
+
+import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableList;
+
+public class BindingToNormalizedNodeCodec implements SchemaContextListener {
+
+    private static final Logger LOG = LoggerFactory.getLogger(BindingToNormalizedNodeCodec.class);
+
+    private final BindingIndependentMappingService bindingToLegacy;
+    private DataNormalizer legacyToNormalized;
+
+    public BindingToNormalizedNodeCodec(final BindingIndependentMappingService mappingService) {
+        super();
+        this.bindingToLegacy = mappingService;
+    }
+
+    public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toNormalized(
+            final InstanceIdentifier<? extends DataObject> binding) {
+        return legacyToNormalized.toNormalized(bindingToLegacy.toDataDom(binding));
+    }
+
+    public Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> toNormalizedNode(
+            final InstanceIdentifier<? extends DataObject> bindingPath, final DataObject bindingObject) {
+        return toNormalizedNode(toEntry(bindingPath, bindingObject));
+
+    }
+
+    public Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> toNormalizedNode(
+            final Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject> binding) {
+        Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> normalizedEntry = legacyToNormalized.toNormalized(bindingToLegacy.toDataDom(binding));
+        if(Augmentation.class.isAssignableFrom(binding.getKey().getTargetType())) {
+
+            for(DataContainerChild<? extends PathArgument, ?> child : ((DataContainerNode<?>) normalizedEntry.getValue()).getValue()) {
+               if(child instanceof AugmentationNode) {
+                   ImmutableList<PathArgument> childArgs = ImmutableList.<PathArgument>builder()
+                           .addAll(normalizedEntry.getKey().getPath())
+                           .add(child.getIdentifier())
+                           .build();
+                   org.opendaylight.yangtools.yang.data.api.InstanceIdentifier childPath = new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(childArgs);
+                   return new SimpleEntry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>>(childPath,child);
+               }
+            }
+
+        }
+        return normalizedEntry;
+
+
+    }
+
+    public InstanceIdentifier<? extends DataObject> toBinding(
+            final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized)
+            throws DeserializationException {
+
+        org.opendaylight.yangtools.yang.data.api.InstanceIdentifier legacyPath = legacyToNormalized
+                .toLegacy(normalized);
+        return bindingToLegacy.fromDataDom(legacyPath);
+    }
+
+    private static final Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject> toEntry(
+            final org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject> key,
+            final DataObject value) {
+        return new SimpleEntry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject>(
+                key, value);
+    }
+
+    public DataObject toBinding(final InstanceIdentifier<?> path, final NormalizedNode<?, ?> normalizedNode)
+            throws DeserializationException {
+        return bindingToLegacy.dataObjectFromDataDom(path, (CompositeNode) DataNormalizer.toLegacy(normalizedNode));
+    }
+
+    public DataNormalizer getDataNormalizer() {
+        return legacyToNormalized;
+    }
+
+    public Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject> toBinding(
+            final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, ? extends NormalizedNode<?, ?>> normalized)
+            throws DeserializationException {
+        InstanceIdentifier<? extends DataObject> bindingPath = toBinding(normalized.getKey());
+        DataObject bindingData = toBinding(bindingPath, normalized.getValue());
+        return toEntry(bindingPath, bindingData);
+    }
+
+    @Override
+    public void onGlobalContextUpdated(final SchemaContext arg0) {
+        legacyToNormalized = new DataNormalizer(arg0);
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/ForwardedBackwardsCompatibleDataBroker.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/ForwardedBackwardsCompatibleDataBroker.java
new file mode 100644 (file)
index 0000000..ee76073
--- /dev/null
@@ -0,0 +1,441 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.binding.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
+
+import org.opendaylight.controller.md.sal.binding.api.BindingDataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration;
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
+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.controller.sal.common.util.Rpcs;
+import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
+import org.opendaylight.yangtools.concepts.Delegator;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.util.concurrent.AsyncFunction;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+
+public class ForwardedBackwardsCompatibleDataBroker extends AbstractForwardedDataBroker implements DataProviderService, AutoCloseable {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ForwardedBackwardsCompatibleDataBroker.class);
+
+    private final ConcurrentHashMap<InstanceIdentifier<?>, CommitHandlerRegistrationImpl> commitHandlers = new ConcurrentHashMap<>();
+    private final ListenerRegistry<DataChangeListener> fakeRegistry = ListenerRegistry.create();
+    private final ListeningExecutorService executorService;
+
+    public ForwardedBackwardsCompatibleDataBroker(final DOMDataBroker domDataBroker,
+            final BindingIndependentMappingService mappingService, final ListeningExecutorService executor) {
+        super(domDataBroker, mappingService);
+        executorService = executor;
+        LOG.info("ForwardedBackwardsCompatibleBroker started.");
+    }
+
+    @Override
+    public DataModificationTransaction beginTransaction() {
+        return new ForwardedBackwardsCompatibleTransacion(getDelegate().newReadWriteTransaction(), getCodec());
+    }
+
+    @Override
+    public DataObject readConfigurationData(final InstanceIdentifier<? extends DataObject> path) {
+        DataModificationTransaction tx = beginTransaction();
+        return tx.readConfigurationData(path);
+    }
+
+    @Override
+    public DataObject readOperationalData(final InstanceIdentifier<? extends DataObject> path) {
+        DataModificationTransaction tx = beginTransaction();
+        return tx.readOperationalData(path);
+    }
+
+    @Override
+    public Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> registerCommitHandler(
+            final InstanceIdentifier<? extends DataObject> path,
+            final DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> commitHandler) {
+
+
+        //transformingCommitHandler = new TransformingDataChangeListener
+        //fakeCommitHandler =  registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, path, listener, DataChangeScope.SUBTREE);
+
+        CommitHandlerRegistrationImpl reg = new CommitHandlerRegistrationImpl(path, commitHandler);
+        commitHandlers.put(path, reg);
+        return reg;
+    }
+
+    @Override
+    @Deprecated
+    public ListenerRegistration<RegistrationListener<DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject>>> registerCommitHandlerListener(
+            final RegistrationListener<DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject>> commitHandlerListener) {
+        throw new UnsupportedOperationException("Not supported contract.");
+    }
+
+    @Override
+    public ListenerRegistration<DataChangeListener> registerDataChangeListener(
+            final InstanceIdentifier<? extends DataObject> path, final DataChangeListener listener) {
+
+
+        BindingDataChangeListener asyncOperListener = new BackwardsCompatibleOperationalDataChangeInvoker(listener);
+        BindingDataChangeListener asyncCfgListener = new BackwardsCompatibleConfigurationDataChangeInvoker(listener);
+
+        ListenerRegistration<BindingDataChangeListener> cfgReg = registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, path, asyncCfgListener, DataChangeScope.SUBTREE);
+        ListenerRegistration<BindingDataChangeListener> operReg = registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, path, asyncOperListener, DataChangeScope.SUBTREE);
+
+        return new LegacyListenerRegistration(listener,cfgReg,operReg);
+    }
+
+    @Override
+    public Registration<DataReader<InstanceIdentifier<? extends DataObject>, DataObject>> registerDataReader(
+            final InstanceIdentifier<? extends DataObject> path,
+            final DataReader<InstanceIdentifier<? extends DataObject>, DataObject> reader) {
+        throw new UnsupportedOperationException("Data reader contract is not supported.");
+    }
+
+    @Override
+    public void close() throws Exception {
+        // TODO Auto-generated method stub
+
+    }
+
+    public ListenableFuture<RpcResult<TransactionStatus>> commit(final ForwardedBackwardsCompatibleTransacion tx) {
+
+        final List<DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject>> subTrans = new ArrayList<>();
+        LOG.debug("Tx: {} Submitted.",tx.getIdentifier());
+        ListenableFuture<Boolean> requestCommit = executorService.submit(new Callable<Boolean>() {
+
+            @Override
+            public Boolean call() throws Exception {
+                try {
+                    for (CommitHandlerRegistrationImpl handler : commitHandlers.values()) {
+
+                        DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> subTx = handler
+                                .getInstance().requestCommit(tx);
+                        subTrans.add(subTx);
+                    }
+                } catch (Exception e) {
+                    LOG.error("Tx: {} Rollback.",tx.getIdentifier(),e);
+                    for (DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> subTx : subTrans) {
+                        subTx.rollback();
+                    }
+                    return false;
+                }
+                LOG.debug("Tx: {} Can Commit True.",tx.getIdentifier());
+                return true;
+            }
+
+        });
+
+        ListenableFuture<RpcResult<TransactionStatus>> dataStoreCommit = Futures.transform(requestCommit, new AsyncFunction<Boolean, RpcResult<TransactionStatus>>() {
+
+            @Override
+            public ListenableFuture<RpcResult<TransactionStatus>> apply(final Boolean requestCommitSuccess) throws Exception {
+                if(requestCommitSuccess) {
+                    return tx.getDelegate().commit();
+                }
+                return Futures.immediateFuture(Rpcs.getRpcResult(false, TransactionStatus.FAILED, Collections.<RpcError>emptySet()));
+            }
+        });
+
+        return Futures.transform(dataStoreCommit, new Function<RpcResult<TransactionStatus>,RpcResult<TransactionStatus>>() {
+            @Override
+            public RpcResult<TransactionStatus> apply(final RpcResult<TransactionStatus> input) {
+                if(input.isSuccessful()) {
+                    for(DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> subTx : subTrans ) {
+                        subTx.finish();
+                    }
+                } else {
+                    LOG.error("Tx: {} Rollback - Datastore commit failed.",tx.getIdentifier());
+                    for(DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> subTx : subTrans ) {
+                        subTx.rollback();
+                    }
+                }
+                return input;
+            }
+        });
+    }
+
+    private class ForwardedBackwardsCompatibleTransacion extends
+            AbstractForwardedTransaction<DOMDataReadWriteTransaction> implements DataModificationTransaction {
+
+        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<>();
+        private final Map<InstanceIdentifier<? extends DataObject>, DataObject> original = new HashMap<>();
+        private TransactionStatus status = TransactionStatus.NEW;
+
+        @Override
+        public final TransactionStatus getStatus() {
+            return status;
+        }
+
+        protected ForwardedBackwardsCompatibleTransacion(final DOMDataReadWriteTransaction delegate,
+                final BindingToNormalizedNodeCodec codec) {
+            super(delegate, codec);
+            LOG.debug("Tx {} allocated.",getIdentifier());
+        }
+
+        @Override
+        public void putOperationalData(final InstanceIdentifier<? extends DataObject> path, final DataObject data) {
+
+            doPutWithEnsureParents(getDelegate(), LogicalDatastoreType.OPERATIONAL, path, data);
+        }
+
+        @Override
+        public void putConfigurationData(final InstanceIdentifier<? extends DataObject> path, final DataObject data) {
+            DataObject originalObj = readConfigurationData(path);
+            if (originalObj != null) {
+                original.put(path, originalObj);
+
+            } else {
+                created.put(path, data);
+            }
+            updated.put(path, data);
+            doPutWithEnsureParents(getDelegate(), LogicalDatastoreType.CONFIGURATION, path, data);
+        }
+
+        @Override
+        public void removeOperationalData(final InstanceIdentifier<? extends DataObject> path) {
+            doDelete(getDelegate(), LogicalDatastoreType.OPERATIONAL, path);
+
+        }
+
+        @Override
+        public void removeConfigurationData(final InstanceIdentifier<? extends DataObject> path) {
+            doDelete(getDelegate(), LogicalDatastoreType.CONFIGURATION, path);
+        }
+
+        @Override
+        public Map<InstanceIdentifier<? extends DataObject>, DataObject> getCreatedOperationalData() {
+            return Collections.emptyMap();
+        }
+
+        @Override
+        public Map<InstanceIdentifier<? extends DataObject>, DataObject> getCreatedConfigurationData() {
+            return created;
+        }
+
+        @Override
+        public Map<InstanceIdentifier<? extends DataObject>, DataObject> getUpdatedOperationalData() {
+            return Collections.emptyMap();
+        }
+
+        @Override
+        public Map<InstanceIdentifier<? extends DataObject>, DataObject> getUpdatedConfigurationData() {
+            return updated;
+        }
+
+        @Override
+        public Set<InstanceIdentifier<? extends DataObject>> getRemovedConfigurationData() {
+            return removed;
+        }
+
+        @Override
+        public Set<InstanceIdentifier<? extends DataObject>> getRemovedOperationalData() {
+            return Collections.emptySet();
+        }
+
+        @Override
+        public Map<InstanceIdentifier<? extends DataObject>, DataObject> getOriginalConfigurationData() {
+            return original;
+        }
+
+        @Override
+        public Map<InstanceIdentifier<? extends DataObject>, DataObject> getOriginalOperationalData() {
+            return Collections.emptyMap();
+        }
+
+        @Override
+        public DataObject readOperationalData(final InstanceIdentifier<? extends DataObject> path) {
+            try {
+                return doRead(getDelegate(), LogicalDatastoreType.OPERATIONAL, path).get().orNull();
+            } catch (InterruptedException | ExecutionException e) {
+                LOG.error("Read of {} failed.", path,e);
+                return null;
+            }
+        }
+
+        @Override
+        public DataObject readConfigurationData(final InstanceIdentifier<? extends DataObject> path) {
+            try {
+                return doRead(getDelegate(), LogicalDatastoreType.CONFIGURATION, path).get().orNull();
+            } catch (InterruptedException | ExecutionException e) {
+                LOG.error("Read of {} failed.", path,e);
+                return null;
+            }
+        }
+
+        @Override
+        public Object getIdentifier() {
+            return getDelegate().getIdentifier();
+        }
+
+        private void changeStatus(TransactionStatus status) {
+            LOG.trace("Transaction {} changed status to {}", getIdentifier(), status);
+            this.status = status;
+        }
+
+        @Override
+        public ListenableFuture<RpcResult<TransactionStatus>> commit() {
+            final ListenableFuture<RpcResult<TransactionStatus>> f = ForwardedBackwardsCompatibleDataBroker.this.commit(this);
+
+            changeStatus(TransactionStatus.SUBMITED);
+
+            Futures.addCallback(f, new FutureCallback<RpcResult<TransactionStatus>>() {
+                @Override
+                public void onSuccess(RpcResult<TransactionStatus> result) {
+                    changeStatus(result.getResult());
+                }
+
+                @Override
+                public void onFailure(Throwable t) {
+                    LOG.error("Transaction {} failed to complete", getIdentifier(), t);
+                    changeStatus(TransactionStatus.FAILED);
+                }
+            });
+
+            return f;
+        }
+
+        @Override
+        public ListenerRegistration<DataTransactionListener> registerListener(final DataTransactionListener listener) {
+            throw new UnsupportedOperationException();
+        }
+
+    }
+
+    private class CommitHandlerRegistrationImpl extends
+            AbstractObjectRegistration<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> {
+
+        private final InstanceIdentifier<? extends DataObject> path;
+
+        public CommitHandlerRegistrationImpl(final InstanceIdentifier<? extends DataObject> path,
+                final DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> commitHandler) {
+            super(commitHandler);
+            this.path = path;
+        }
+
+        @Override
+        protected void removeRegistration() {
+            commitHandlers.remove(path, this);
+        }
+
+    }
+
+
+    private static final class LegacyListenerRegistration implements ListenerRegistration<DataChangeListener> {
+
+        private final DataChangeListener instance;
+        private final ListenerRegistration<BindingDataChangeListener> cfgReg;
+        private final ListenerRegistration<BindingDataChangeListener> operReg;
+
+        public LegacyListenerRegistration(final DataChangeListener listener,
+                final ListenerRegistration<BindingDataChangeListener> cfgReg,
+                final ListenerRegistration<BindingDataChangeListener> operReg) {
+            this.instance = listener;
+            this.cfgReg = cfgReg;
+            this.operReg = operReg;
+        }
+
+        @Override
+        public DataChangeListener getInstance() {
+            return instance;
+        }
+
+        @Override
+        public void close() {
+            cfgReg.close();
+            operReg.close();
+        }
+
+    }
+
+    private static class BackwardsCompatibleOperationalDataChangeInvoker implements BindingDataChangeListener, Delegator<DataChangeListener> {
+
+        private final org.opendaylight.controller.md.sal.common.api.data.DataChangeListener<?,?> delegate;
+
+
+        public BackwardsCompatibleOperationalDataChangeInvoker(final DataChangeListener listener) {
+            this.delegate = listener;
+        }
+
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        @Override
+        public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+
+            DataChangeEvent legacyChange = LegacyDataChangeEvent.createOperational(change);
+            delegate.onDataChanged(legacyChange);
+
+        }
+
+        @Override
+        public DataChangeListener getDelegate() {
+            return (DataChangeListener) delegate;
+        }
+
+    }
+
+    private static class BackwardsCompatibleConfigurationDataChangeInvoker implements BindingDataChangeListener, Delegator<DataChangeListener> {
+
+
+        @SuppressWarnings("rawtypes")
+        private final org.opendaylight.controller.md.sal.common.api.data.DataChangeListener<?,?> delegate;
+
+        public BackwardsCompatibleConfigurationDataChangeInvoker(final DataChangeListener listener) {
+            this.delegate = listener;
+        }
+
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        @Override
+        public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+
+            DataChangeEvent legacyChange = LegacyDataChangeEvent.createConfiguration(change);
+
+            delegate.onDataChanged(legacyChange);
+
+        }
+
+        @Override
+        public DataChangeListener getDelegate() {
+            return (DataChangeListener) delegate;
+        }
+
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/ForwardedBindingDataBroker.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/ForwardedBindingDataBroker.java
new file mode 100644 (file)
index 0000000..fb06b13
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.binding.impl;
+
+import org.opendaylight.controller.md.sal.binding.api.BindingDataBroker;
+import org.opendaylight.controller.md.sal.binding.api.BindingDataReadTransaction;
+import org.opendaylight.controller.md.sal.binding.api.BindingDataReadWriteTransaction;
+import org.opendaylight.controller.md.sal.binding.api.BindingDataWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * The DataBrokerImpl simply defers to the DOMDataBroker for all its operations.
+ * All transactions and listener registrations are wrapped by the DataBrokerImpl
+ * to allow binding aware components to use the DataBroker transparently.
+ *
+ * Besides this the DataBrokerImpl and it's collaborators also cache data that
+ * is already transformed from the binding independent to binding aware format
+ *
+ * TODO : All references in this class to CompositeNode should be switched to
+ * NormalizedNode once the MappingService is updated
+ *
+ */
+public class ForwardedBindingDataBroker extends AbstractForwardedDataBroker implements BindingDataBroker {
+
+    public ForwardedBindingDataBroker(final DOMDataBroker domDataBroker, final BindingIndependentMappingService mappingService) {
+        super(domDataBroker, mappingService);
+    }
+
+    @Override
+    public BindingDataReadTransaction newReadOnlyTransaction() {
+        return new BindingDataReadTransactionImpl(getDelegate().newReadOnlyTransaction(),getCodec());
+    }
+
+    @Override
+    public BindingDataReadWriteTransaction newReadWriteTransaction() {
+        return new BindingDataReadWriteTransactionImpl(getDelegate().newReadWriteTransaction(),getCodec());
+    }
+
+    @Override
+    public BindingDataWriteTransaction newWriteOnlyTransaction() {
+        return new BindingDataWriteTransactionImpl<DOMDataWriteTransaction>(getDelegate().newWriteOnlyTransaction(),getCodec());
+    }
+
+    private abstract class AbstractBindingTransaction<T extends AsyncTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>>>
+            extends AbstractForwardedTransaction<T> implements AsyncTransaction<InstanceIdentifier<?>, DataObject> {
+
+        protected AbstractBindingTransaction(final T delegate, final BindingToNormalizedNodeCodec codec) {
+            super(delegate, codec);
+        }
+
+        @Override
+        public Object getIdentifier() {
+            return getDelegate().getIdentifier();
+        }
+
+        @Override
+        public void close() {
+            getDelegate().close();
+        }
+
+    }
+
+    private class BindingDataReadTransactionImpl extends AbstractBindingTransaction<DOMDataReadTransaction> implements
+            BindingDataReadTransaction {
+
+        protected BindingDataReadTransactionImpl(final DOMDataReadTransaction delegate,
+                final BindingToNormalizedNodeCodec codec) {
+            super(delegate, codec);
+        }
+
+        @Override
+        public ListenableFuture<Optional<DataObject>> read(final LogicalDatastoreType store,
+                final InstanceIdentifier<?> path) {
+            return doRead(getDelegate(), store, path);
+        }
+    }
+
+    private class BindingDataWriteTransactionImpl<T extends DOMDataWriteTransaction> extends
+            AbstractBindingTransaction<T> implements BindingDataWriteTransaction {
+
+        protected BindingDataWriteTransactionImpl(final T delegate, final BindingToNormalizedNodeCodec codec) {
+            super(delegate, codec);
+
+        }
+
+        @Override
+        public void cancel() {
+            doCancel(getDelegate());
+        }
+
+        @Override
+        public void put(final LogicalDatastoreType store, final InstanceIdentifier<?> path, final DataObject data) {
+            doPut(getDelegate(), store, path, data);
+        }
+
+        @Override
+        public void merge(final LogicalDatastoreType store, final InstanceIdentifier<?> path, final DataObject data) {
+            doMerge(getDelegate(), store, path, data);
+        }
+
+        @Override
+        public void delete(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
+            doDelete(getDelegate(), store, path);
+        }
+
+        @Override
+        public ListenableFuture<RpcResult<TransactionStatus>> commit() {
+            return doCommit(getDelegate());
+        }
+    }
+
+    private class BindingDataReadWriteTransactionImpl extends
+            BindingDataWriteTransactionImpl<DOMDataReadWriteTransaction> implements BindingDataReadWriteTransaction {
+
+        protected BindingDataReadWriteTransactionImpl(final DOMDataReadWriteTransaction delegate,
+                final BindingToNormalizedNodeCodec codec) {
+            super(delegate, codec);
+        }
+
+        @Override
+        public ListenableFuture<Optional<DataObject>> read(final LogicalDatastoreType store,
+                final InstanceIdentifier<?> path) {
+            return doRead(getDelegate(), store, path);
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/LegacyDataChangeEvent.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/LegacyDataChangeEvent.java
new file mode 100644 (file)
index 0000000..8cb4a70
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.binding.impl;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public abstract class LegacyDataChangeEvent implements
+        DataChangeEvent<InstanceIdentifier<? extends DataObject>, DataObject> {
+
+    private LegacyDataChangeEvent() {
+    }
+
+    public static final DataChangeEvent<InstanceIdentifier<?>, DataObject> createOperational(
+            final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        return new OperationalChangeEvent(change);
+    }
+
+    public static final DataChangeEvent<InstanceIdentifier<?>, DataObject> createConfiguration(
+            final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        return new ConfigurationChangeEvent(change);
+    }
+
+    @Override
+    public Map<InstanceIdentifier<?>, DataObject> getCreatedOperationalData() {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public Map<InstanceIdentifier<?>, DataObject> getCreatedConfigurationData() {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public Map<InstanceIdentifier<?>, DataObject> getUpdatedOperationalData() {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public Map<InstanceIdentifier<?>, DataObject> getUpdatedConfigurationData() {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public Set<InstanceIdentifier<?>> getRemovedConfigurationData() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public Set<InstanceIdentifier<?>> getRemovedOperationalData() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public Map<InstanceIdentifier<?>, DataObject> getOriginalConfigurationData() {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public Map<InstanceIdentifier<?>, DataObject> getOriginalOperationalData() {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public DataObject getOriginalConfigurationSubtree() {
+        return null;
+    }
+
+    @Override
+    public DataObject getOriginalOperationalSubtree() {
+        return null;
+    }
+
+    @Override
+    public DataObject getUpdatedConfigurationSubtree() {
+        return null;
+    }
+
+    @Override
+    public DataObject getUpdatedOperationalSubtree() {
+        return null;
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    private final static class OperationalChangeEvent extends LegacyDataChangeEvent {
+
+        private final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> delegate;
+
+        public OperationalChangeEvent(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+            this.delegate = change;
+        }
+
+        @Override
+        public Map<InstanceIdentifier<?>, DataObject> getCreatedOperationalData() {
+            return delegate.getCreatedData();
+        }
+
+        @Override
+        public Set<InstanceIdentifier<?>> getRemovedOperationalData() {
+            return delegate.getRemovedPaths();
+        }
+
+        @Override
+        public DataObject getOriginalOperationalSubtree() {
+            return delegate.getOriginalSubtree();
+        }
+
+        @Override
+        public DataObject getUpdatedOperationalSubtree() {
+            return delegate.getUpdatedSubtree();
+        }
+
+        @Override
+        public Map<InstanceIdentifier<?>, DataObject> getOriginalOperationalData() {
+            return (Map) delegate.getOriginalData();
+        }
+
+        @Override
+        public Map<InstanceIdentifier<?>, DataObject> getUpdatedOperationalData() {
+            return delegate.getUpdatedData();
+        }
+
+        @Override
+        public String toString() {
+            return "OperationalChangeEvent [delegate=" + delegate + "]";
+        }
+
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    private final static class ConfigurationChangeEvent extends LegacyDataChangeEvent {
+
+        private final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> delegate;
+
+        public ConfigurationChangeEvent(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+            this.delegate = change;
+        }
+
+        @Override
+        public Map<InstanceIdentifier<?>, DataObject> getCreatedConfigurationData() {
+            return delegate.getCreatedData();
+        }
+
+        @Override
+        public Set<InstanceIdentifier<?>> getRemovedConfigurationData() {
+            return delegate.getRemovedPaths();
+        }
+
+        @Override
+        public DataObject getOriginalConfigurationSubtree() {
+            return delegate.getOriginalSubtree();
+        }
+
+        @Override
+        public DataObject getUpdatedConfigurationSubtree() {
+            return delegate.getUpdatedSubtree();
+        }
+
+        @Override
+        public Map<InstanceIdentifier<?>, DataObject> getOriginalConfigurationData() {
+            return (Map) delegate.getOriginalData();
+        }
+
+        @Override
+        public Map<InstanceIdentifier<?>, DataObject> getUpdatedConfigurationData() {
+            return delegate.getUpdatedData();
+        }
+
+        @Override
+        public String toString() {
+            return "ConfigurationChangeEvent [delegate=" + delegate + "]";
+        }
+
+    }
+
+}
index e6e935c920b613c577d4b9f890092a22c13cb49d..37c0dfa60750280b9fe0963bf223a131b0e64753 100644 (file)
@@ -28,6 +28,7 @@ import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 
+import org.opendaylight.controller.md.sal.binding.impl.AbstractForwardedDataBroker;
 import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
@@ -133,7 +134,7 @@ public class BindingIndependentConnector implements //
     private final Function<InstanceIdentifier<?>, org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> toDOMInstanceIdentifier = new Function<InstanceIdentifier<?>, org.opendaylight.yangtools.yang.data.api.InstanceIdentifier>() {
 
         @Override
-        public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier apply(InstanceIdentifier<?> input) {
+        public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier apply(final InstanceIdentifier<?> input) {
             return mappingService.toDataDom(input);
         }
 
@@ -162,7 +163,7 @@ public class BindingIndependentConnector implements //
     }
 
     @Override
-    public DataObject readOperationalData(InstanceIdentifier<? extends DataObject> path) {
+    public DataObject readOperationalData(final InstanceIdentifier<? extends DataObject> path) {
         try {
             org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
             CompositeNode result = biDataService.readOperationalData(biPath);
@@ -173,7 +174,7 @@ public class BindingIndependentConnector implements //
     }
 
     private DataObject potentialAugmentationRead(InstanceIdentifier<? extends DataObject> path,
-            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath, CompositeNode result)
+            final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath, final CompositeNode result)
             throws DeserializationException {
         Class<? extends DataObject> targetType = path.getTargetType();
         if (Augmentation.class.isAssignableFrom(targetType)) {
@@ -188,7 +189,7 @@ public class BindingIndependentConnector implements //
     }
 
     @Override
-    public DataObject readConfigurationData(InstanceIdentifier<? extends DataObject> path) {
+    public DataObject readConfigurationData(final InstanceIdentifier<? extends DataObject> path) {
         try {
             org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
             CompositeNode result = biDataService.readConfigurationData(biPath);
@@ -199,7 +200,7 @@ public class BindingIndependentConnector implements //
     }
 
     private DataModificationTransaction createBindingToDomTransaction(
-            DataModification<InstanceIdentifier<? extends DataObject>, DataObject> source) {
+            final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> source) {
         DataModificationTransaction target = biDataService.beginTransaction();
         LOG.debug("Created DOM Transaction {} for {},", target.getIdentifier(),source.getIdentifier());
         for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedConfigurationData()) {
@@ -231,7 +232,7 @@ public class BindingIndependentConnector implements //
     }
 
     private org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction createDomToBindingTransaction(
-            DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> source) {
+            final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> source) {
         org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction target = baDataService
                 .beginTransaction();
         for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedConfigurationData()) {
@@ -280,7 +281,7 @@ public class BindingIndependentConnector implements //
         return biDataService;
     }
 
-    protected void setDomDataService(org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService) {
+    protected void setDomDataService(final org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService) {
         this.biDataService = biDataService;
     }
 
@@ -288,7 +289,7 @@ public class BindingIndependentConnector implements //
         return baDataService;
     }
 
-    protected void setBindingDataService(DataProviderService baDataService) {
+    protected void setBindingDataService(final DataProviderService baDataService) {
         this.baDataService = baDataService;
     }
 
@@ -296,11 +297,15 @@ public class BindingIndependentConnector implements //
         return baRpcRegistry;
     }
 
-    protected void setBindingRpcRegistry(RpcProviderRegistry rpcRegistry) {
+    protected void setBindingRpcRegistry(final RpcProviderRegistry rpcRegistry) {
         this.baRpcRegistry = rpcRegistry;
     }
 
     public void startDataForwarding() {
+        if(baDataService instanceof AbstractForwardedDataBroker) {
+            dataForwarding = true;
+            return;
+        }
         checkState(!dataForwarding, "Connector is already forwarding data.");
         baDataReaderRegistration = baDataService.registerDataReader(ROOT, this);
         baCommitHandlerRegistration = baDataService.registerCommitHandler(ROOT, bindingToDomCommitHandler);
@@ -331,7 +336,7 @@ public class BindingIndependentConnector implements //
         }
     }
 
-    protected void setMappingService(BindingIndependentMappingService mappingService) {
+    protected void setMappingService(final BindingIndependentMappingService mappingService) {
         this.mappingService = mappingService;
     }
 
@@ -341,17 +346,17 @@ public class BindingIndependentConnector implements //
     }
 
     @Override
-    public void onSessionInitiated(ProviderSession session) {
+    public void onSessionInitiated(final ProviderSession session) {
         setDomDataService(session.getService(org.opendaylight.controller.sal.core.api.data.DataProviderService.class));
         setDomRpcRegistry(session.getService(RpcProvisionRegistry.class));
 
     }
 
-    public <T extends RpcService> void onRpcRouterCreated(Class<T> serviceType, RpcRouter<T> router) {
+    public <T extends RpcService> void onRpcRouterCreated(final Class<T> serviceType, final RpcRouter<T> router) {
 
     }
 
-    public void setDomRpcRegistry(RpcProvisionRegistry registry) {
+    public void setDomRpcRegistry(final RpcProvisionRegistry registry) {
         biRpcRegistry = registry;
     }
 
@@ -373,8 +378,8 @@ public class BindingIndependentConnector implements //
         private final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> modification;
 
         public DomToBindingTransaction(
-                org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing,
-                DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> modification) {
+                final org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing,
+                final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> modification) {
             super();
             this.backing = backing;
             this.modification = modification;
@@ -412,8 +417,8 @@ public class BindingIndependentConnector implements //
         private final DataModificationTransaction backing;
         private final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
 
-        public BindingToDomTransaction(DataModificationTransaction backing,
-                DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
+        public BindingToDomTransaction(final DataModificationTransaction backing,
+                final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
             this.backing = backing;
             this.modification = modification;
             domOpenedTransactions.put(backing.getIdentifier(), this);
@@ -451,7 +456,7 @@ public class BindingIndependentConnector implements //
 
         @Override
         public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> requestCommit(
-                DataModification<InstanceIdentifier<? extends DataObject>, DataObject> bindingTransaction) {
+                final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> bindingTransaction) {
 
             /**
              * Transaction was created as DOM transaction, in that case we do
@@ -474,7 +479,7 @@ public class BindingIndependentConnector implements //
             DataCommitHandler<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
 
         @Override
-        public void onRegister(DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
+        public void onRegister(final DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
 
             org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath = mappingService.toDataDom(registration
                     .getPath());
@@ -482,14 +487,14 @@ public class BindingIndependentConnector implements //
         }
 
         @Override
-        public void onUnregister(DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
+        public void onUnregister(final DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
             // NOOP for now
             // FIXME: do registration based on only active commit handlers.
         }
 
         @Override
         public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> requestCommit(
-                DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> domTransaction) {
+                final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> domTransaction) {
             Object identifier = domTransaction.getIdentifier();
 
             /**
@@ -527,34 +532,34 @@ public class BindingIndependentConnector implements //
             return registryImpl;
         }
 
-        public void setRegistryImpl(RpcProviderRegistryImpl registryImpl) {
+        public void setRegistryImpl(final RpcProviderRegistryImpl registryImpl) {
             this.registryImpl = registryImpl;
         }
 
         @Override
-        public void onGlobalRpcRegistered(Class<? extends RpcService> cls) {
+        public void onGlobalRpcRegistered(final Class<? extends RpcService> cls) {
             getRpcForwarder(cls, null);
         }
 
         @Override
-        public void onGlobalRpcUnregistered(Class<? extends RpcService> cls) {
+        public void onGlobalRpcUnregistered(final Class<? extends RpcService> cls) {
             // NOOP
         }
 
         @Override
-        public void onRpcRouterCreated(RpcRouter<?> router) {
+        public void onRpcRouterCreated(final RpcRouter<?> router) {
             Class<? extends BaseIdentity> ctx = router.getContexts().iterator().next();
             getRpcForwarder(router.getServiceType(), ctx);
         }
 
         @Override
-        public void onRouteChange(RouteChange<RpcContextIdentifier, InstanceIdentifier<?>> change) {
+        public void onRouteChange(final RouteChange<RpcContextIdentifier, InstanceIdentifier<?>> change) {
             for (Entry<RpcContextIdentifier, Set<InstanceIdentifier<?>>> entry : change.getAnnouncements().entrySet()) {
                 bindingRoutesAdded(entry);
             }
         }
 
-        private void bindingRoutesAdded(Entry<RpcContextIdentifier, Set<InstanceIdentifier<?>>> entry) {
+        private void bindingRoutesAdded(final Entry<RpcContextIdentifier, Set<InstanceIdentifier<?>>> entry) {
             Class<? extends BaseIdentity> context = entry.getKey().getRoutingContext();
             Class<? extends RpcService> service = entry.getKey().getRpcService();
             if (context != null) {
@@ -562,8 +567,8 @@ public class BindingIndependentConnector implements //
             }
         }
 
-        private DomToBindingRpcForwarder getRpcForwarder(Class<? extends RpcService> service,
-                Class<? extends BaseIdentity> context) {
+        private DomToBindingRpcForwarder getRpcForwarder(final Class<? extends RpcService> service,
+                final Class<? extends BaseIdentity> context) {
             DomToBindingRpcForwarder potential = forwarders.get(service);
             if (potential != null) {
                 return potential;
@@ -588,7 +593,7 @@ public class BindingIndependentConnector implements //
         private final Map<QName, RpcInvocationStrategy> strategiesByQName = new HashMap<>();
         private final WeakHashMap<Method, RpcInvocationStrategy> strategiesByMethod = new WeakHashMap<>();
 
-        public DomToBindingRpcForwarder(Class<? extends RpcService> service) {
+        public DomToBindingRpcForwarder(final Class<? extends RpcService> service) {
             this.rpcServiceType = new WeakReference<Class<? extends RpcService>>(service);
             this.supportedRpcs = mappingService.getRpcQNamesFor(service);
             try {
@@ -611,7 +616,7 @@ public class BindingIndependentConnector implements //
          * @param service
          * @param context
          */
-        public DomToBindingRpcForwarder(Class<? extends RpcService> service, Class<? extends BaseIdentity> context) {
+        public DomToBindingRpcForwarder(final Class<? extends RpcService> service, final Class<? extends BaseIdentity> context) {
             this.rpcServiceType = new WeakReference<Class<? extends RpcService>>(service);
             this.supportedRpcs = mappingService.getRpcQNamesFor(service);
             Builder<RoutedRpcRegistration> registrationsBuilder = ImmutableSet
@@ -630,8 +635,8 @@ public class BindingIndependentConnector implements //
             registrations = registrationsBuilder.build();
         }
 
-        public void registerPaths(Class<? extends BaseIdentity> context, Class<? extends RpcService> service,
-                Set<InstanceIdentifier<?>> set) {
+        public void registerPaths(final Class<? extends BaseIdentity> context, final Class<? extends RpcService> service,
+                final Set<InstanceIdentifier<?>> set) {
             QName ctx = BindingReflections.findQName(context);
             for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier path : FluentIterable.from(set).transform(
                     toDOMInstanceIdentifier)) {
@@ -643,7 +648,7 @@ public class BindingIndependentConnector implements //
 
 
         @Override
-        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+        public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
             if (EQUALS_METHOD.equals(method)) {
                 return false;
             }
@@ -657,8 +662,8 @@ public class BindingIndependentConnector implements //
             return strategy.forwardToDomBroker(null);
         }
 
-        public void removePaths(Class<? extends BaseIdentity> context, Class<? extends RpcService> service,
-                Set<InstanceIdentifier<?>> set) {
+        public void removePaths(final Class<? extends BaseIdentity> context, final Class<? extends RpcService> service,
+                final Set<InstanceIdentifier<?>> set) {
             QName ctx = BindingReflections.findQName(context);
             for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier path : FluentIterable.from(set).transform(
                     toDOMInstanceIdentifier)) {
@@ -686,7 +691,7 @@ public class BindingIndependentConnector implements //
         }
 
         @Override
-        public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode domInput) {
+        public RpcResult<CompositeNode> invokeRpc(final QName rpc, final CompositeNode domInput) {
             checkArgument(rpc != null);
             checkArgument(domInput != null);
 
@@ -702,7 +707,7 @@ public class BindingIndependentConnector implements //
             }
         }
 
-        private RpcInvocationStrategy resolveInvocationStrategy(QName rpc) {
+        private RpcInvocationStrategy resolveInvocationStrategy(final QName rpc) {
             return strategiesByQName.get(rpc);
         }
 
@@ -750,7 +755,7 @@ public class BindingIndependentConnector implements //
         protected final Method targetMethod;
         protected final QName rpc;
 
-        public RpcInvocationStrategy(QName rpc, Method targetMethod) {
+        public RpcInvocationStrategy(final QName rpc, final Method targetMethod) {
             this.targetMethod = targetMethod;
             this.rpc = rpc;
         }
@@ -760,7 +765,7 @@ public class BindingIndependentConnector implements //
         public abstract RpcResult<CompositeNode> uncheckedInvoke(RpcService rpcService, CompositeNode domInput)
                 throws Exception;
 
-        public RpcResult<CompositeNode> invokeOn(RpcService rpcService, CompositeNode domInput) throws Exception {
+        public RpcResult<CompositeNode> invokeOn(final RpcService rpcService, final CompositeNode domInput) throws Exception {
             return uncheckedInvoke(rpcService, domInput);
         }
     }
@@ -774,8 +779,8 @@ public class BindingIndependentConnector implements //
         private final WeakReference<Class> outputClass;
 
         @SuppressWarnings({ "rawtypes", "unchecked" })
-        public DefaultInvocationStrategy(QName rpc, Method targetMethod, Class<?> outputClass,
-                Class<? extends DataContainer> inputClass) {
+        public DefaultInvocationStrategy(final QName rpc, final Method targetMethod, final Class<?> outputClass,
+                final Class<? extends DataContainer> inputClass) {
             super(rpc, targetMethod);
             this.outputClass = new WeakReference(outputClass);
             this.inputClass = new WeakReference(inputClass);
@@ -783,7 +788,7 @@ public class BindingIndependentConnector implements //
 
         @SuppressWarnings("unchecked")
         @Override
-        public RpcResult<CompositeNode> uncheckedInvoke(RpcService rpcService, CompositeNode domInput) throws Exception {
+        public RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput) throws Exception {
             DataContainer bindingInput = mappingService.dataObjectFromDataDom(inputClass.get(), domInput);
             Future<RpcResult<?>> futureResult = (Future<RpcResult<?>>) targetMethod.invoke(rpcService, bindingInput);
             if (futureResult == null) {
@@ -799,7 +804,7 @@ public class BindingIndependentConnector implements //
         }
 
         @Override
-        public Future<RpcResult<?>> forwardToDomBroker(DataObject input) {
+        public Future<RpcResult<?>> forwardToDomBroker(final DataObject input) {
             if(biRpcRegistry != null) {
                 CompositeNode xml = mappingService.toDataDom(input);
                 CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc, ImmutableList.<Node<?>> of(xml));
@@ -818,12 +823,12 @@ public class BindingIndependentConnector implements //
 
     private class NoInputNoOutputInvocationStrategy extends RpcInvocationStrategy {
 
-        public NoInputNoOutputInvocationStrategy(QName rpc, Method targetMethod) {
+        public NoInputNoOutputInvocationStrategy(final QName rpc, final Method targetMethod) {
             super(rpc, targetMethod);
         }
 
         @Override
-        public RpcResult<CompositeNode> uncheckedInvoke(RpcService rpcService, CompositeNode domInput) throws Exception {
+        public RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput) throws Exception {
             @SuppressWarnings("unchecked")
             Future<RpcResult<Void>> result = (Future<RpcResult<Void>>) targetMethod.invoke(rpcService);
             RpcResult<Void> bindingResult = result.get();
@@ -831,7 +836,7 @@ public class BindingIndependentConnector implements //
         }
 
         @Override
-        public Future<RpcResult<?>> forwardToDomBroker(DataObject input) {
+        public Future<RpcResult<?>> forwardToDomBroker(final DataObject input) {
             return Futures.immediateFuture(null);
         }
     }
@@ -843,15 +848,15 @@ public class BindingIndependentConnector implements //
         private final WeakReference<Class> inputClass;
 
         @SuppressWarnings({ "rawtypes", "unchecked" })
-        public NoOutputInvocationStrategy(QName rpc, Method targetMethod,
-                Class<? extends DataContainer> inputClass) {
+        public NoOutputInvocationStrategy(final QName rpc, final Method targetMethod,
+                final Class<? extends DataContainer> inputClass) {
             super(rpc,targetMethod);
             this.inputClass = new WeakReference(inputClass);
         }
 
 
         @Override
-        public RpcResult<CompositeNode> uncheckedInvoke(RpcService rpcService, CompositeNode domInput) throws Exception {
+        public RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput) throws Exception {
             DataContainer bindingInput = mappingService.dataObjectFromDataDom(inputClass.get(), domInput);
             Future<RpcResult<?>> result = (Future<RpcResult<?>>) targetMethod.invoke(rpcService, bindingInput);
             if (result == null) {
@@ -862,7 +867,7 @@ public class BindingIndependentConnector implements //
         }
 
         @Override
-        public Future<RpcResult<?>> forwardToDomBroker(DataObject input) {
+        public Future<RpcResult<?>> forwardToDomBroker(final DataObject input) {
             if(biRpcRegistry != null) {
                 CompositeNode xml = mappingService.toDataDom(input);
                 CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc,ImmutableList.<Node<?>>of(xml));
@@ -892,12 +897,12 @@ public class BindingIndependentConnector implements //
         return mappingService;
     }
 
-    public void setBindingNotificationService(NotificationProviderService baService) {
+    public void setBindingNotificationService(final NotificationProviderService baService) {
         this.baNotifyService = baService;
 
     }
 
-    public void setDomNotificationService(NotificationPublishService domService) {
+    public void setDomNotificationService(final NotificationPublishService domService) {
         this.domNotificationService = domService;
     }
 
@@ -912,7 +917,7 @@ public class BindingIndependentConnector implements //
         }
 
         @Override
-        public void onNotification(CompositeNode notification) {
+        public void onNotification(final CompositeNode notification) {
             QName qname = notification.getNodeType();
             WeakReference<Class<? extends Notification>> potential = notifications.get(qname);
             if (potential != null) {
@@ -929,7 +934,7 @@ public class BindingIndependentConnector implements //
         }
 
         @Override
-        public void onNotificationSubscribtion(Class<? extends Notification> notificationType) {
+        public void onNotificationSubscribtion(final Class<? extends Notification> notificationType) {
             QName qname = BindingReflections.findQName(notificationType);
             if (qname != null) {
                 WeakReference<Class<? extends Notification>> already = notifications.putIfAbsent(qname,
index 8d6f3314520d3fc31f21b60a004915c1cc938263..db98b456f05c9060f04f8154eecf1e6fc5cf35ad 100644 (file)
@@ -10,12 +10,12 @@ package org.opendaylight.controller.sal.binding.impl.forward;
 import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentConnector;
 import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
 
-interface DomForwardedBroker {
+public interface DomForwardedBroker {
 
     public BindingIndependentConnector getConnector();
-    
+
     public void setConnector(BindingIndependentConnector connector);
-    
+
     public void setDomProviderContext(ProviderSession domProviderContext);
 
     public ProviderSession getDomProviderContext();
index b95cb73f1c793fa04491093b226707b3756a375c..428025a58df58180085c4811f441f7f5a0e5d702 100644 (file)
@@ -1,5 +1,5 @@
 module opendaylight-sal-binding-broker-impl {
-       yang-version 1;
+    yang-version 1;
     namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl";
     prefix "binding-impl";
 
@@ -10,7 +10,7 @@ module opendaylight-sal-binding-broker-impl {
 
     description
         "Service definition for Binding Aware MD-SAL.";
+
     revision "2013-10-28" {
         description
             "Initial revision";
@@ -28,20 +28,27 @@ module opendaylight-sal-binding-broker-impl {
         config:provided-service sal:binding-rpc-registry;
         config:java-name-prefix BindingBrokerImpl;
     }
-    
+
     identity binding-data-broker {
         base config:module-type;
         config:provided-service sal:binding-data-broker;
         config:provided-service sal:binding-data-consumer-broker;
         config:java-name-prefix DataBrokerImpl;
     }
-    
+
+    identity binding-data-compatible-broker {
+        base config:module-type;
+        config:provided-service sal:binding-data-broker;
+        config:provided-service sal:binding-data-consumer-broker;
+        config:java-name-prefix ForwardedCompatibleDataBrokerImpl;
+    }
+
     identity binding-rpc-broker {
         base config:module-type;
         config:provided-service sal:binding-rpc-registry;
         config:java-name-prefix RpcBrokerImpl;
     }
-    
+
     identity binding-notification-broker {
         base config:module-type;
         config:provided-service sal:binding-notification-service;
@@ -58,7 +65,7 @@ module opendaylight-sal-binding-broker-impl {
     augment "/config:modules/config:module/config:configuration" {
         case binding-broker-impl {
             when "/config:modules/config:module/config:type = 'binding-broker-impl'";
-            
+
             /*
             container rpc-registry {
                 uses config:service-ref {
@@ -68,7 +75,7 @@ module opendaylight-sal-binding-broker-impl {
                     }
                 }
             }*/
-            
+
             container data-broker {
                 uses config:service-ref {
                     refine type {
@@ -77,7 +84,7 @@ module opendaylight-sal-binding-broker-impl {
                     }
                 }
             }
-            
+
             container notification-service {
                 uses config:service-ref {
                     refine type {
@@ -108,10 +115,34 @@ module opendaylight-sal-binding-broker-impl {
                         config:required-identity binding-dom-mapping-service;
                     }
                 }
-            } 
+            }
+        }
+    }
+
+    augment "/config:modules/config:module/config:configuration" {
+        case binding-data-compatible-broker {
+            when "/config:modules/config:module/config:type = 'binding-data-compatible-broker'";
+
+            container dom-async-broker {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity dom:dom-broker-osgi-registry;
+                    }
+                }
+            }
+
+            container binding-mapping-service {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity binding-dom-mapping-service;
+                    }
+                }
+            }
         }
     }
-    
+
 
     augment "/config:modules/config:module/config:state" {
         case runtime-generated-mapping {
@@ -139,4 +170,4 @@ module opendaylight-sal-binding-broker-impl {
             uses common:notification-state;
         }
     }
-}
\ No newline at end of file
+}
index 2e43b885531b40f1f302bb4fb67d1d0e7be721c4..4bad2bbb86140a5f04ac6a704b84e0b314cad76b 100644 (file)
@@ -17,7 +17,9 @@ import java.util.concurrent.Future;
 
 import javassist.ClassPool;
 
+import org.opendaylight.controller.md.sal.binding.impl.ForwardedBackwardsCompatibleDataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
 import org.opendaylight.controller.md.sal.dom.broker.impl.DOMDataBrokerImpl;
 import org.opendaylight.controller.md.sal.dom.broker.impl.compat.BackwardsCompatibleDataBroker;
 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
@@ -107,6 +109,10 @@ public class BindingTestContext implements AutoCloseable, SchemaContextProvider
 
     private final List<SchemaContextListener> schemaListeners = new ArrayList<>();
 
+    private DataProviderService baData;
+
+    private DOMDataBroker newDOMDataBroker;
+
     @Override
     public SchemaContext getSchemaContext() {
         return schemaContext;
@@ -152,9 +158,9 @@ public class BindingTestContext implements AutoCloseable, SchemaContextProvider
                 .put(LogicalDatastoreType.CONFIGURATION, configStore)
                 .build();
 
-        DOMDataBrokerImpl newBiDataImpl = new DOMDataBrokerImpl(newDatastores, executor);
+        newDOMDataBroker = new DOMDataBrokerImpl(newDatastores, executor);
 
-        biCompatibleBroker = new BackwardsCompatibleDataBroker(newBiDataImpl);
+        biCompatibleBroker = new BackwardsCompatibleDataBroker(newDOMDataBroker);
 
         schemaListeners.add(configStore);
         schemaListeners.add(operStore);
@@ -166,24 +172,25 @@ public class BindingTestContext implements AutoCloseable, SchemaContextProvider
         checkState(executor != null, "Executor needs to be set");
         baDataImpl = new DataBrokerImpl();
         baDataImpl.setExecutor(executor);
+        baData = baDataImpl;
     }
 
     public void startBindingBroker() {
         checkState(executor != null, "Executor needs to be set");
-        checkState(baDataImpl != null, "Binding Data Broker must be started");
+        checkState(baData != null, "Binding Data Broker must be started");
         checkState(baNotifyImpl != null, "Notification Service must be started");
         baBrokerImpl = new DomForwardedBindingBrokerImpl("test");
 
         baBrokerImpl.getMountManager().setDataCommitExecutor(executor);
         baBrokerImpl.getMountManager().setNotificationExecutor(executor);
         baBrokerImpl.setRpcBroker(new RpcProviderRegistryImpl("test"));
-        baBrokerImpl.setDataBroker(baDataImpl);
+        baBrokerImpl.setDataBroker(baData);
         baBrokerImpl.setNotificationBroker(baNotifyImpl);
         baBrokerImpl.start();
     }
 
     public void startForwarding() {
-        checkState(baDataImpl != null, "Binding Data Broker needs to be started");
+        checkState(baData != null, "Binding Data Broker needs to be started");
         checkState(biDataLegacyBroker != null, "DOM Data Broker needs to be started.");
         checkState(mappingServiceImpl != null, "DOM Mapping Service needs to be started.");
 
@@ -315,19 +322,27 @@ public class BindingTestContext implements AutoCloseable, SchemaContextProvider
     }
 
     public void start() {
-        startBindingDataBroker();
-        startBindingNotificationBroker();
-        startBindingBroker();
         startNewDomDataBroker();
         startDomBroker();
         startDomMountPoint();
         startBindingToDomMappingService();
+        startNewBindingDataBroker();
+
+        startBindingNotificationBroker();
+        startBindingBroker();
+
         startForwarding();
         if (startWithSchema) {
             loadYangSchemaFromClasspath();
         }
     }
 
+    public void startNewBindingDataBroker() {
+        ForwardedBackwardsCompatibleDataBroker forwarded = new ForwardedBackwardsCompatibleDataBroker(newDOMDataBroker, mappingServiceImpl, executor);
+        schemaListeners.add(forwarded);
+        baData = forwarded;
+    }
+
     private void startDomMountPoint() {
         biMountImpl = new MountPointManagerImpl();
         biMountImpl.setDataBroker(getDomDataBroker());
@@ -353,7 +368,7 @@ public class BindingTestContext implements AutoCloseable, SchemaContextProvider
     }
 
     public DataProviderService getBindingDataBroker() {
-        return baDataImpl;
+        return baData;
     }
 
     public org.opendaylight.controller.sal.core.api.data.DataProviderService getDomDataBroker() {
index 929eb66350115f025135dc77b5ce1aaf4d103149..6784c0cc919ae1f637a1b7c14e0addebcfc3400e 100644 (file)
@@ -7,6 +7,9 @@
  */
 package org.opendaylight.controller.sal.binding.test.bugfix;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
 import java.util.Collections;
 import java.util.Map;
 import java.util.concurrent.Callable;
@@ -16,29 +19,24 @@ import java.util.concurrent.Future;
 
 import javassist.ClassPool;
 
-import org.junit.Ignore;
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
 import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
 import org.opendaylight.controller.sal.binding.test.util.BindingBrokerTestFactory;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
 
-import static org.junit.Assert.*;
-
 public class DOMCodecBug02Test extends AbstractDataServiceTest {
 
     private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
@@ -68,12 +66,13 @@ public class DOMCodecBug02Test extends AbstractDataServiceTest {
     private static final NodeRef NODE_REF = new NodeRef(NODE_INSTANCE_ID_BA);
 
     /**
-     * This test is ignored, till found out better way to test generation
-     * of classes without leaking of instances from previous run
-     * 
+     * This test is ignored, till found out better way to test generation of
+     * classes without leaking of instances from previous run
+     *
      * @throws Exception
      */
-    
+
+    @Override
     public void setUp() {
         ListeningExecutorService executor = MoreExecutors.sameThreadExecutor();
         BindingBrokerTestFactory factory = new BindingBrokerTestFactory();
@@ -82,33 +81,33 @@ public class DOMCodecBug02Test extends AbstractDataServiceTest {
         factory.setStartWithParsedSchema(getStartWithSchema());
         testContext = factory.getTestContext();
         testContext.start();
-        
+
         baDataService = testContext.getBindingDataBroker();
         biDataService = testContext.getDomDataBroker();
         dataStore = testContext.getDomDataStore();
         mappingService = testContext.getBindingToDomMappingService();
     };
-    
+
     @Test
     public void testSchemaContextNotAvailable() throws Exception {
 
         ExecutorService testExecutor = Executors.newFixedThreadPool(1);
         testContext.loadYangSchemaFromClasspath();
-        Future<Future<RpcResult<TransactionStatus>>> future = testExecutor.submit(new Callable<Future<RpcResult<TransactionStatus>>>() {
-            @Override
-            public Future<RpcResult<TransactionStatus>> call() throws Exception {
-                NodesBuilder nodesBuilder = new NodesBuilder();
-                nodesBuilder.setNode(Collections.<Node> emptyList());
-                DataModificationTransaction transaction = baDataService.beginTransaction();
-                transaction.putOperationalData(NODES_INSTANCE_ID_BA, nodesBuilder.build());
-                return transaction.commit();
-            }
-        });
-        
-        
+        Future<Future<RpcResult<TransactionStatus>>> future = testExecutor
+                .submit(new Callable<Future<RpcResult<TransactionStatus>>>() {
+                    @Override
+                    public Future<RpcResult<TransactionStatus>> call() throws Exception {
+                        NodesBuilder nodesBuilder = new NodesBuilder();
+                        nodesBuilder.setNode(Collections.<Node> emptyList());
+                        DataModificationTransaction transaction = baDataService.beginTransaction();
+                        transaction.putOperationalData(NODES_INSTANCE_ID_BA, nodesBuilder.build());
+                        return transaction.commit();
+                    }
+                });
+
         RpcResult<TransactionStatus> result = future.get().get();
         assertEquals(TransactionStatus.COMMITED, result.getResult());
-        
+
         Nodes nodes = checkForNodes();
         assertNotNull(nodes);
 
@@ -118,7 +117,7 @@ public class DOMCodecBug02Test extends AbstractDataServiceTest {
         return (Nodes) baDataService.readOperationalData(NODES_INSTANCE_ID_BA);
 
     }
-    
+
     @Override
     protected boolean getStartWithSchema() {
         return false;
index 6a050efb35679af9ef283bbef313a09cc92b24d9..e89371337e0a27af96679ca91437862c2cd2f2ef 100644 (file)
@@ -14,6 +14,7 @@ import static org.junit.Assert.assertNull;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.TimeUnit;
 
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
@@ -43,6 +44,8 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 
+import com.google.common.util.concurrent.SettableFuture;
+
 public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataChangeListener {
 
     private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
@@ -85,7 +88,7 @@ public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataCh
                     .node(SUPPORTED_ACTIONS_QNAME) //
                     .toInstance();
 
-    private DataChangeEvent<InstanceIdentifier<?>, DataObject> receivedChangeEvent;
+    private final SettableFuture<DataChangeEvent<InstanceIdentifier<?>, DataObject>> receivedChangeEvent = SettableFuture.create();
 
 
 
@@ -120,9 +123,10 @@ public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataCh
         RpcResult<TransactionStatus> result = transaction.commit().get();
         assertEquals(TransactionStatus.COMMITED, result.getResult());
 
-        assertNotNull(receivedChangeEvent);
+        DataChangeEvent<InstanceIdentifier<?>, DataObject> potential = receivedChangeEvent.get(1000,TimeUnit.MILLISECONDS);
+        assertNotNull(potential);
 
-        verifyNodes((Nodes) receivedChangeEvent.getUpdatedOperationalSubtree(),original);
+        verifyNodes((Nodes) potential.getUpdatedOperationalSubtree(),original);
         assertBindingIndependentVersion(NODE_INSTANCE_ID_BI);
         Nodes nodes = checkForNodes();
         verifyNodes(nodes,original);
@@ -186,7 +190,7 @@ public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataCh
         assertNull(node);
     }
 
-    private void verifyNodes(Nodes nodes,Node original) {
+    private void verifyNodes(final Nodes nodes,final Node original) {
         assertNotNull(nodes);
         assertNotNull(nodes.getNode());
         assertEquals(1, nodes.getNode().size());
@@ -203,7 +207,7 @@ public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataCh
     }
 
     private void assertBindingIndependentVersion(
-            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier nodeId) {
+            final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier nodeId) {
         CompositeNode node = biDataService.readOperationalData(nodeId);
         assertNotNull(node);
     }
@@ -213,8 +217,8 @@ public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataCh
     }
 
     @Override
-    public void onDataChanged(DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
-        receivedChangeEvent = change;
+    public void onDataChanged(final DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        receivedChangeEvent.set(change);
     }
 
 }
index 90fa2be21103a7bf89ec8191a2a4d9fad4b301f4..027a8eeb9f103005c7fbf2140c7aa842e0471de3 100644 (file)
@@ -14,7 +14,9 @@ import static org.junit.Assert.assertTrue;
 
 import java.util.Collections;
 import java.util.Map;
+import java.util.concurrent.TimeUnit;
 
+import org.junit.Ignore;
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
@@ -41,6 +43,8 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 
+import com.google.common.util.concurrent.SettableFuture;
+
 public class PutAugmentationTest extends AbstractDataServiceTest implements DataChangeListener {
 
     private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
@@ -89,7 +93,7 @@ public class PutAugmentationTest extends AbstractDataServiceTest implements Data
             .augmentation(FlowCapableNode.class) //
             .build();
 
-    private DataChangeEvent<InstanceIdentifier<?>, DataObject> lastReceivedChangeEvent;
+    private SettableFuture<DataChangeEvent<InstanceIdentifier<?>, DataObject>> lastReceivedChangeEvent;
 
     /**
      * Test for Bug 148
@@ -97,8 +101,9 @@ public class PutAugmentationTest extends AbstractDataServiceTest implements Data
      * @throws Exception
      */
     @Test
+    @Ignore
     public void putNodeAndAugmentation() throws Exception {
-
+        lastReceivedChangeEvent = SettableFuture.create();
         baDataService.registerDataChangeListener(ALL_FLOW_CAPABLE_NODES, this);
 
 
@@ -126,11 +131,16 @@ public class PutAugmentationTest extends AbstractDataServiceTest implements Data
         DataModificationTransaction augmentedTransaction = baDataService.beginTransaction();
         augmentedTransaction.putOperationalData(augmentIdentifier, fnu);
 
+
+        lastReceivedChangeEvent = SettableFuture.create();
         result = augmentedTransaction.commit().get();
         assertEquals(TransactionStatus.COMMITED, result.getResult());
 
-        assertNotNull(lastReceivedChangeEvent);
-        assertTrue(lastReceivedChangeEvent.getCreatedOperationalData().containsKey(FLOW_AUGMENTATION_PATH));
+        DataChangeEvent<InstanceIdentifier<?>, DataObject> potential = lastReceivedChangeEvent.get(1000,TimeUnit.MILLISECONDS);
+        assertNotNull(potential);
+        assertTrue(potential.getCreatedOperationalData().containsKey(FLOW_AUGMENTATION_PATH));
+
+        lastReceivedChangeEvent = SettableFuture.create();
 
         Node augmentedNode = (Node) baDataService.readOperationalData(NODE_INSTANCE_ID_BA);
         assertNotNull(node);
@@ -141,12 +151,13 @@ public class PutAugmentationTest extends AbstractDataServiceTest implements Data
         assertEquals(fnu.getDescription(), readedAugmentation.getDescription());
         assertBindingIndependentVersion(NODE_INSTANCE_ID_BI);
         testNodeRemove();
-        assertTrue(lastReceivedChangeEvent.getRemovedOperationalData().contains(FLOW_AUGMENTATION_PATH));
+        assertTrue(lastReceivedChangeEvent.get(1000,TimeUnit.MILLISECONDS).getRemovedOperationalData().contains(FLOW_AUGMENTATION_PATH));
     }
 
     @Test
+    @Ignore
     public void putNodeWithAugmentation() throws Exception {
-
+        lastReceivedChangeEvent = SettableFuture.create();
         baDataService.registerDataChangeListener(ALL_FLOW_CAPABLE_NODES, this);
 
         NodeBuilder nodeBuilder = new NodeBuilder();
@@ -165,9 +176,11 @@ public class PutAugmentationTest extends AbstractDataServiceTest implements Data
         baseTransaction.putOperationalData(NODE_INSTANCE_ID_BA, nodeBuilder.build());
         RpcResult<TransactionStatus> result = baseTransaction.commit().get();
 
-        assertNotNull(lastReceivedChangeEvent);
-        assertTrue(lastReceivedChangeEvent.getCreatedOperationalData().containsKey(FLOW_AUGMENTATION_PATH));
-        lastReceivedChangeEvent = null;
+
+        DataChangeEvent<InstanceIdentifier<?>, DataObject> potential = lastReceivedChangeEvent.get(1000,TimeUnit.MILLISECONDS);
+        assertNotNull(potential);
+        assertTrue(potential.getCreatedOperationalData().containsKey(FLOW_AUGMENTATION_PATH));
+        lastReceivedChangeEvent = SettableFuture.create();
         assertEquals(TransactionStatus.COMMITED, result.getResult());
 
         FlowCapableNode readedAugmentation = (FlowCapableNode) baDataService.readOperationalData(InstanceIdentifier
@@ -177,10 +190,10 @@ public class PutAugmentationTest extends AbstractDataServiceTest implements Data
         assertEquals(fnu.getHardware(), readedAugmentation.getHardware());
 
         testPutNodeConnectorWithAugmentation();
-        lastReceivedChangeEvent = null;
+        lastReceivedChangeEvent = SettableFuture.create();
         testNodeRemove();
 
-        assertTrue(lastReceivedChangeEvent.getRemovedOperationalData().contains(FLOW_AUGMENTATION_PATH));
+        assertTrue(lastReceivedChangeEvent.get(1000,TimeUnit.MILLISECONDS).getRemovedOperationalData().contains(FLOW_AUGMENTATION_PATH));
     }
 
     private void testPutNodeConnectorWithAugmentation() throws Exception {
@@ -218,7 +231,7 @@ public class PutAugmentationTest extends AbstractDataServiceTest implements Data
         assertNull(node);
     }
 
-    private void verifyNodes(Nodes nodes, Node original) {
+    private void verifyNodes(final Nodes nodes, final Node original) {
         assertNotNull(nodes);
         assertNotNull(nodes.getNode());
         assertEquals(1, nodes.getNode().size());
@@ -234,7 +247,7 @@ public class PutAugmentationTest extends AbstractDataServiceTest implements Data
 
     }
 
-    private void assertBindingIndependentVersion(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier nodeId) {
+    private void assertBindingIndependentVersion(final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier nodeId) {
         CompositeNode node = biDataService.readOperationalData(nodeId);
         assertNotNull(node);
     }
@@ -244,8 +257,8 @@ public class PutAugmentationTest extends AbstractDataServiceTest implements Data
     }
 
     @Override
-    public void onDataChanged(DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
-        lastReceivedChangeEvent = change;
+    public void onDataChanged(final DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        lastReceivedChangeEvent.set(change);
     }
 
 }
index 6f938b15ed19391ad0de52e941bb0cd2311ec8f7..1661ff230d133fc1b2145070fd420fe98bc3dbbd 100644 (file)
@@ -15,14 +15,13 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.TimeUnit;
 
-import org.junit.Ignore;
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
 import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
-import org.opendaylight.controller.sal.common.util.CommitHandlerTransactions;
 import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpVersion;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
@@ -53,17 +52,21 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
-import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.SettableFuture;
 
 public class ChangeOriginatedInDomBrokerTest extends AbstractDataServiceTest {
 
+    private static final Logger LOG = LoggerFactory.getLogger(ChangeOriginatedInDomBrokerTest.class);
+
     private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
     private static final QName FLOW_ID_QNAME = QName.create(Flow.QNAME, "id");
     private static final QName FLOW_NODE_QNAME = QName.create(Flow.QNAME, "node");
@@ -76,7 +79,7 @@ public class ChangeOriginatedInDomBrokerTest extends AbstractDataServiceTest {
     private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID));
     private static final FlowKey FLOW_KEY = new FlowKey(FLOW_ID);
 
-    private DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modificationCapture;
+    private final SettableFuture<DataChangeEvent<InstanceIdentifier<?>, DataObject>> modificationCapture = SettableFuture.create();
 
     private static final Map<QName, Object> NODE_KEY_BI = Collections.<QName, Object> singletonMap(NODE_ID_QNAME,
             NODE_ID);
@@ -119,40 +122,36 @@ public class ChangeOriginatedInDomBrokerTest extends AbstractDataServiceTest {
             .toInstance();
 
     @Test
-    @Ignore
     public void simpleModifyOperation() throws Exception {
 
         assertNull(biDataService.readConfigurationData(FLOW_INSTANCE_ID_BI));
 
-        registerCommitHandler();
+        registerChangeListener();
 
         CompositeNode domflow = createTestFlow();
         DataModificationTransaction biTransaction = biDataService.beginTransaction();
         biTransaction.putConfigurationData(FLOW_INSTANCE_ID_BI, domflow);
         RpcResult<TransactionStatus> biResult = biTransaction.commit().get();
         assertEquals(TransactionStatus.COMMITED, biResult.getResult());
-        assertNotNull(modificationCapture);
-        Flow flow = (Flow) modificationCapture.getCreatedConfigurationData().get(FLOW_INSTANCE_ID_BA);
+        DataChangeEvent<InstanceIdentifier<?>, DataObject> event = modificationCapture.get(1000,TimeUnit.MILLISECONDS);
+        assertNotNull(event);
+        LOG.info("Created Configuration :{}",event.getCreatedConfigurationData());
+        Flow flow = (Flow) event.getCreatedConfigurationData().get(FLOW_INSTANCE_ID_BA);
         assertNotNull(flow);
         assertNotNull(flow.getMatch());
         assertEquals(TransactionStatus.COMMITED, biResult.getResult());
 
     }
 
-    private void registerCommitHandler() {
-        DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> flowTestCommitHandler = new DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>() {
+    private void registerChangeListener() {
+        baDataService.registerDataChangeListener(FLOWS_PATH_BA, new DataChangeListener() {
 
             @Override
-            public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> requestCommit(
-                    final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
-                modificationCapture = modification;
-                return CommitHandlerTransactions.allwaysSuccessfulTransaction(modification);
+            public void onDataChanged(final DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+                LOG.info("Data Change listener invoked.");
+                modificationCapture.set(change);
             }
-
-        };
-        Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> registration = baDataService
-                .registerCommitHandler(FLOWS_PATH_BA, flowTestCommitHandler);
-        assertNotNull(registration);
+        });
     }
 
     private CompositeNode createTestFlow() {
@@ -195,6 +194,7 @@ public class ChangeOriginatedInDomBrokerTest extends AbstractDataServiceTest {
 
         // Wrap our Apply Action in an Instruction
         InstructionBuilder ib = new InstructionBuilder();
+        ib.setOrder(0);
         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
 
         // Put our Instruction in a list of Instructions
index ba639ad7c24e4e704a15234949a13431a137f9fc..5b97da368e8634dca3bb86278e8f767c3eecd208 100644 (file)
@@ -52,7 +52,6 @@ public class TestHelper {
                 mavenBundle("io.netty", "netty-codec").versionAsInProject(), //
                 mavenBundle("io.netty", "netty-transport").versionAsInProject(), //
 
-                mavenBundle(CONTROLLER, "protocol-framework").versionAsInProject(), //
                 mavenBundle(CONTROLLER, "config-manager").versionAsInProject(), // //
                 mavenBundle("commons-io", "commons-io").versionAsInProject(), //
                 mavenBundle(CONTROLLER, "config-manager").versionAsInProject(), //
@@ -64,6 +63,9 @@ public class TestHelper {
                 mavenBundle(CONTROLLER, "ietf-netconf-monitoring-extension").versionAsInProject(), //
                 mavenBundle(CONTROLLER, "netconf-monitoring").versionAsInProject(), //
 
+                mavenBundle(CONTROLLER, "netty-config-api").versionAsInProject(), //
+                mavenBundle(CONTROLLER, "protocol-framework").versionAsInProject(), //
+
                 mavenBundle(CONTROLLER, "netconf-client").versionAsInProject(), //
                 mavenBundle(CONTROLLER, "netconf-util").versionAsInProject(), //
                 mavenBundle(CONTROLLER + ".thirdparty", "ganymed").versionAsInProject(), //
index de90f48b35d7506351afb26373a60b9a4c773442..941f2fdb39059950a5d3ae910848a282c7c3311a 100644 (file)
@@ -61,6 +61,11 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
         return false;
     }
 
+
+    public boolean isKeyedEntry() {
+        return false;
+    }
+
     protected Set<QName> getQNameIdentifiers() {
         return Collections.singleton(identifier.getNodeType());
     }
@@ -129,6 +134,11 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
             return Builders.leafSetEntryBuilder().withNodeIdentifier(nodeId).withValue(node.getValue()).build();
         }
 
+
+        @Override
+        public boolean isKeyedEntry() {
+            return true;
+        }
     }
 
     private static abstract class CompositeNodeNormalizationOpertation<T extends PathArgument> extends
@@ -243,7 +253,9 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
         protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
             ImmutableMap.Builder<QName, Object> keys = ImmutableMap.builder();
             for (QName key : keyDefinition) {
-                SimpleNode<?> valueNode = checkNotNull(compositeNode.getFirstSimpleByName(key),"List node %s MUST contain leaf %s with value.",getIdentifier().getNodeType(),key);
+
+                SimpleNode<?> valueNode = checkNotNull(compositeNode.getFirstSimpleByName(key),
+                        "List node %s MUST contain leaf %s with value.", getIdentifier().getNodeType(), key);
                 keys.put(key, valueNode.getValue());
             }
 
@@ -263,6 +275,12 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
             }
             return builder.build();
         }
+
+
+        @Override
+        public boolean isKeyedEntry() {
+            return true;
+        }
     }
 
     private static final class ContainerNormalization extends DataContainerNormalizationOperation<NodeIdentifier> {
index 9487f2159011132cd71e935a757b432dd324270a..28b2bde26d31e4558b5f716666147983446811cc 100644 (file)
@@ -4,6 +4,7 @@ import static com.google.common.base.Preconditions.checkArgument;
 
 import java.util.AbstractMap;
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.Map;
 
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
@@ -11,6 +12,7 @@ import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
@@ -31,12 +33,9 @@ import com.google.common.collect.Iterables;
 
 public class DataNormalizer {
 
-    private final SchemaContext schemaContext;
-
     private final DataNormalizationOperation<?> operation;
 
     public DataNormalizer(final SchemaContext ctx) {
-        schemaContext = ctx;
         operation = DataNormalizationOperation.from(ctx);
     }
 
@@ -44,14 +43,18 @@ public class DataNormalizer {
         ImmutableList.Builder<PathArgument> normalizedArgs = ImmutableList.builder();
 
         DataNormalizationOperation<?> currentOp = operation;
-        for (PathArgument legacyArg : legacy.getPath()) {
+        Iterator<PathArgument> arguments = legacy.getPath().iterator();
+        while ( arguments.hasNext() ) {
+            PathArgument legacyArg = arguments.next();
             currentOp = currentOp.getChild(legacyArg);
             checkArgument(currentOp != null, "Legacy Instance Identifier %s is not correct. Normalized Instance Identifier so far %s",legacy,normalizedArgs.build());
             while (currentOp.isMixin()) {
                 normalizedArgs.add(currentOp.getIdentifier());
                 currentOp = currentOp.getChild(legacyArg.getNodeType());
             }
-            normalizedArgs.add(legacyArg);
+            if(arguments.hasNext() || (!currentOp.isKeyedEntry() || legacyArg instanceof NodeIdentifierWithPredicates || legacyArg instanceof NodeWithValue)) {
+                normalizedArgs.add(legacyArg);
+            }
         }
         return new InstanceIdentifier(normalizedArgs.build());
     }
index fcf8b40efe52106fb8477897d028dc153c956eee..fc87a9110576054eb75571167d01f60c1c95c98e 100644 (file)
@@ -120,7 +120,7 @@ public class DOMDataBrokerImpl implements DOMDataBroker, AutoCloseable {
 
     private ListenableFuture<RpcResult<TransactionStatus>> submit(
             final WriteTransactionImpl<? extends DOMStoreWriteTransaction> transaction) {
-        LOG.debug("Tx: {} is submitted for execution.",transaction.getIdentifier());
+        LOG.debug("Tx: {} is submitted for execution.", transaction.getIdentifier());
         return executor.submit(new CommitCoordination(transaction));
     }
 
@@ -253,7 +253,8 @@ public class DOMDataBrokerImpl implements DOMDataBroker, AutoCloseable {
         }
 
         @Override
-        public void merge(final LogicalDatastoreType store, final InstanceIdentifier path, final NormalizedNode<?, ?> data) {
+        public void merge(final LogicalDatastoreType store, final InstanceIdentifier path,
+                final NormalizedNode<?, ?> data) {
 
         }
     }
@@ -269,15 +270,18 @@ public class DOMDataBrokerImpl implements DOMDataBroker, AutoCloseable {
         @Override
         public RpcResult<TransactionStatus> call() throws Exception {
 
-            Boolean canCommit = canCommit().get();
             try {
+                Boolean canCommit = canCommit().get();
+
                 if (canCommit) {
                     try {
                         preCommit().get();
                         try {
                             commit().get();
-                            COORDINATOR_LOG.debug("Tx: {} Is commited.",transaction.getIdentifier());
-                            return Rpcs.getRpcResult(true, TransactionStatus.COMMITED, Collections.<RpcError>emptySet());
+                            COORDINATOR_LOG.debug("Tx: {} Is commited.", transaction.getIdentifier());
+                            return Rpcs.getRpcResult(true, TransactionStatus.COMMITED,
+                                    Collections.<RpcError> emptySet());
+
                         } catch (InterruptedException | ExecutionException e) {
                             COORDINATOR_LOG.error("Tx: {} Error during commit", transaction.getIdentifier(), e);
                         }
@@ -287,7 +291,7 @@ public class DOMDataBrokerImpl implements DOMDataBroker, AutoCloseable {
                                 transaction.getIdentifier(), e);
                     }
                 } else {
-                    COORDINATOR_LOG.info("Tx: {} Did not pass canCommit phase.");
+                    COORDINATOR_LOG.info("Tx: {} Did not pass canCommit phase.", transaction.getIdentifier());
                     abort().get();
                 }
             } catch (InterruptedException | ExecutionException e) {
@@ -299,7 +303,7 @@ public class DOMDataBrokerImpl implements DOMDataBroker, AutoCloseable {
             } catch (InterruptedException | ExecutionException e) {
                 COORDINATOR_LOG.error("Tx: {} Error during abort", transaction.getIdentifier(), e);
             }
-            return Rpcs.getRpcResult(false, TransactionStatus.FAILED, Collections.<RpcError>emptySet());
+            return Rpcs.getRpcResult(false, TransactionStatus.FAILED, Collections.<RpcError> emptySet());
         }
 
         public ListenableFuture<Void> preCommit() {
index ff0fbf98cf270a30128b4b0ed780fa3b0319e2b2..306dc2390b9a4381067baa62506112ad42d071c7 100644 (file)
@@ -1,7 +1,6 @@
 package org.opendaylight.controller.md.sal.dom.store.impl;
 
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerRegistrationNode.DataChangeListenerRegistration;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.slf4j.Logger;
@@ -10,10 +9,10 @@ import org.slf4j.LoggerFactory;
 class ChangeListenerNotifyTask implements Runnable {
 
     private static final Logger LOG = LoggerFactory.getLogger(ChangeListenerNotifyTask.class);
-    private final Iterable<DataChangeListenerRegistration<?>> listeners;
+    private final Iterable<? extends DataChangeListenerRegistration<?>> listeners;
     private final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> event;
 
-    public ChangeListenerNotifyTask(final Iterable<DataChangeListenerRegistration<?>> listeners,
+    public ChangeListenerNotifyTask(final Iterable<? extends DataChangeListenerRegistration<?>> listeners,
             final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> event) {
         this.listeners = listeners;
         this.event = event;
index d0ebcf5d4c77543b91352246d1d3331731294228..3c6a3d60d859e4c503c7bc9ed6d3b0045d58a68e 100644 (file)
@@ -63,6 +63,12 @@ public final class DOMImmutableDataChangeEvent implements
         return removedPaths;
     }
 
+    @Override
+    public String toString() {
+        return "DOMImmutableDataChangeEvent [created=" + createdData.keySet() + ", updated=" + updatedData.keySet()
+                + ", removed=" + removedPaths + "]";
+    }
+
     public static class Builder {
 
         private NormalizedNode<?, ?> after;
@@ -73,7 +79,6 @@ public final class DOMImmutableDataChangeEvent implements
         private final ImmutableMap.Builder<InstanceIdentifier, NormalizedNode<?, ?>> updated = ImmutableMap.builder();
         private final ImmutableSet.Builder<InstanceIdentifier> removed = ImmutableSet.builder();
 
-
         private Builder() {
 
         }
@@ -122,4 +127,3 @@ public final class DOMImmutableDataChangeEvent implements
     }
 
 }
-
index c2faf86bce73427c11217fd2ef7c2bfdb905a864..0948f6d3e56f9bd285240c39dc9a6b2f80039b6f 100644 (file)
@@ -4,15 +4,19 @@ import static org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableData
 import static org.opendaylight.controller.md.sal.dom.store.impl.StoreUtils.append;
 import static org.opendaylight.controller.md.sal.dom.store.impl.tree.TreeNodeUtils.getChild;
 
+import java.util.ArrayList;
+import java.util.Collection;
+
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.Builder;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerRegistrationNode;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerRegistrationNode.DataChangeListenerRegistration;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableList;
@@ -20,6 +24,9 @@ import com.google.common.collect.ImmutableSet;
 
 public class DataChangeEventResolver {
 
+
+    private  static final Logger LOG = LoggerFactory.getLogger(DataChangeEventResolver.class);
+
     private static final DOMImmutableDataChangeEvent NO_CHANGE = builder().build();
     private InstanceIdentifier rootPath;
     private ListenerRegistrationNode listenerRoot;
@@ -74,6 +81,7 @@ public class DataChangeEventResolver {
     }
 
     public Iterable<ChangeListenerNotifyTask> resolve() {
+        LOG.trace("Resolving events for {}" ,modificationRoot);
         resolveAnyChangeEvent(rootPath, Optional.of(listenerRoot), modificationRoot, beforeRoot, afterRoot);
         return tasks.build();
     }
@@ -124,6 +132,7 @@ public class DataChangeEventResolver {
             InstanceIdentifier childPath = StoreUtils.append(path, childId);
             builder.merge(resolveCreateEvent(childPath, childListeners, child));
         }
+
         DOMImmutableDataChangeEvent event = builder.build();
         if (listeners.isPresent()) {
             addNotifyTask(listeners.get().getListeners(), event);
@@ -169,12 +178,15 @@ public class DataChangeEventResolver {
             switch (childMod.getModificationType()) {
             case WRITE:
             case DELETE:
-                one.merge(resolveAnyChangeEvent(childPath, childListen, childMod, childBefore, childBefore));
+                one.merge(resolveAnyChangeEvent(childPath, childListen, childMod, childBefore, childAfter));
                 break;
             case SUBTREE_MODIFIED:
                 subtree.merge(resolveSubtreeChangeEvent(childPath, childListen, childMod, childBefore.get(),
                         childAfter.get()));
                 break;
+            case UNMODIFIED:
+                // no-op
+                break;
             }
         }
         DOMImmutableDataChangeEvent oneChangeEvent = one.build();
@@ -194,16 +206,27 @@ public class DataChangeEventResolver {
         return builder().build();
     }
 
-    private void addNotifyTask(final ListenerRegistrationNode listenerRegistrationNode, final DataChangeScope one,
+    private void addNotifyTask(final ListenerRegistrationNode listenerRegistrationNode, final DataChangeScope scope,
             final DOMImmutableDataChangeEvent event) {
-
-
+        Collection<DataChangeListenerRegistration<?>> potential = listenerRegistrationNode.getListeners();
+        if(potential.isEmpty()) {
+            return;
+        }
+        ArrayList<DataChangeListenerRegistration<?>> toNotify = new ArrayList<>(potential.size());
+        for(DataChangeListenerRegistration<?> listener : potential) {
+            if(scope.equals(listener.getScope())) {
+                toNotify.add(listener);
+            }
+        }
+        addNotifyTask(toNotify, event);
 
     }
 
-    private void addNotifyTask(final Iterable<DataChangeListenerRegistration<?>> listeners,
+    private void addNotifyTask(final Collection<DataChangeListenerRegistration<?>> listeners,
             final DOMImmutableDataChangeEvent event) {
-        tasks .add(new ChangeListenerNotifyTask(ImmutableSet.copyOf(listeners),event));
+        if(!listeners.isEmpty()) {
+            tasks.add(new ChangeListenerNotifyTask(ImmutableSet.copyOf(listeners),event));
+        }
     }
 
     public static DataChangeEventResolver create() {
index 0944c2efaebdbf4d328ec94e7a4b3996a1c66239..2091913f24949106aae128e07083a4354b992b70 100644 (file)
@@ -11,16 +11,18 @@ import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
 import static org.opendaylight.controller.md.sal.dom.store.impl.StoreUtils.increase;
 
+import java.util.Collections;
 import java.util.concurrent.Callable;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
 
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerRegistrationNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerRegistrationNode.DataChangeListenerRegistration;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.TreeNodeUtils;
 import org.opendaylight.controller.sal.core.spi.data.DOMStore;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
@@ -38,6 +40,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 import com.google.common.primitives.UnsignedLong;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
@@ -52,41 +55,39 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
     private final ListeningExecutorService executor;
     private final String name;
     private final AtomicLong txCounter = new AtomicLong(0);
-
-    private DataAndMetadataSnapshot snapshot;
-    private ModificationApplyOperation operationTree;
     private final ListenerRegistrationNode listenerTree;
+    private final AtomicReference<DataAndMetadataSnapshot> snapshot;
 
-
+    private ModificationApplyOperation operationTree;
 
     private SchemaContext schemaContext;
 
     public InMemoryDOMDataStore(final String name, final ListeningExecutorService executor) {
-        this.executor = executor;
-        this.name = name;
-        this.operationTree = new AllwaysFailOperation();
-        this.snapshot = DataAndMetadataSnapshot.createEmpty();
+        this.name = Preconditions.checkNotNull(name);
+        this.executor = Preconditions.checkNotNull(executor);
         this.listenerTree = ListenerRegistrationNode.createRoot();
+        this.snapshot = new AtomicReference<DataAndMetadataSnapshot>(DataAndMetadataSnapshot.createEmpty());
+        this.operationTree = new AlwaysFailOperation();
     }
 
     @Override
-    public String getIdentifier() {
+    public final String getIdentifier() {
         return name;
     }
 
     @Override
     public DOMStoreReadTransaction newReadOnlyTransaction() {
-        return new SnapshotBackedReadTransaction(nextIdentifier(), snapshot);
+        return new SnapshotBackedReadTransaction(nextIdentifier(), snapshot.get());
     }
 
     @Override
     public DOMStoreReadWriteTransaction newReadWriteTransaction() {
-        return new SnapshotBackedReadWriteTransaction(nextIdentifier(), snapshot, this, operationTree);
+        return new SnapshotBackedReadWriteTransaction(nextIdentifier(), snapshot.get(), this, operationTree);
     }
 
     @Override
     public DOMStoreWriteTransaction newWriteOnlyTransaction() {
-        return new SnaphostBackedWriteTransaction(nextIdentifier(), snapshot, this, operationTree);
+        return new SnaphostBackedWriteTransaction(nextIdentifier(), snapshot.get(), this, operationTree);
     }
 
     @Override
@@ -98,31 +99,36 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
     @Override
     public <L extends AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>> ListenerRegistration<L> registerChangeListener(
             final InstanceIdentifier path, final L listener, final DataChangeScope scope) {
-
-        Optional<ListenerRegistrationNode> listenerNode = TreeNodeUtils.findNode(listenerTree, path);
-        checkState(listenerNode.isPresent());
-        synchronized (listener) {
-            notifyInitialState(path, listener);
+        LOG.debug("{}: Registering data change listener {} for {}",name,listener,path);
+        ListenerRegistrationNode listenerNode = listenerTree;
+        for(PathArgument arg : path.getPath()) {
+            listenerNode = listenerNode.ensureChild(arg);
         }
-        return listenerNode.get().registerDataChangeListener(listener, scope);
-    }
 
-    private void notifyInitialState(final InstanceIdentifier path,
-            final AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>> listener) {
-        Optional<StoreMetadataNode> currentState = snapshot.read(path);
-        try {
+        /*
+         * Make sure commit is not occurring right now. Listener has to be registered and its
+         * state capture enqueued at a consistent point.
+         *
+         * FIXME: improve this to read-write lock, such that multiple listener registrations
+         *        can occur simultaneously
+         */
+        final DataChangeListenerRegistration<L> reg;
+        synchronized (this) {
+            reg = listenerNode.registerDataChangeListener(path, listener, scope);
+
+            Optional<StoreMetadataNode> currentState = snapshot.get().read(path);
             if (currentState.isPresent()) {
-                NormalizedNode<?, ?> data = currentState.get().getData();
-                listener.onDataChanged(DOMImmutableDataChangeEvent.builder() //
+                final NormalizedNode<?, ?> data = currentState.get().getData();
+
+                final DOMImmutableDataChangeEvent event = DOMImmutableDataChangeEvent.builder() //
                         .setAfter(data) //
                         .addCreated(path, data) //
-                        .build() //
-                );
+                        .build();
+                executor.submit(new ChangeListenerNotifyTask(Collections.singletonList(reg), event));
             }
-        } catch (Exception e) {
-            LOG.error("Unhandled exception encountered when invoking listener {}", listener, e);
         }
 
+        return reg;
     }
 
     private synchronized DOMStoreThreePhaseCommitCohort submit(
@@ -135,22 +141,30 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
         return name + "-" + txCounter.getAndIncrement();
     }
 
-    private synchronized void commit(final DataAndMetadataSnapshot currentSnapshot,
+    private void commit(final DataAndMetadataSnapshot currentSnapshot,
             final StoreMetadataNode newDataTree, final Iterable<ChangeListenerNotifyTask> listenerTasks) {
         LOG.debug("Updating Store snaphot version: {} with version:{}",currentSnapshot.getMetadataTree().getSubtreeVersion(),newDataTree.getSubtreeVersion());
+
         if(LOG.isTraceEnabled()) {
             LOG.trace("Data Tree is {}",StoreUtils.toStringTree(newDataTree));
         }
-        checkState(snapshot == currentSnapshot, "Store snapshot and transaction snapshot differs");
-        snapshot = DataAndMetadataSnapshot.builder() //
+
+        final DataAndMetadataSnapshot newSnapshot = DataAndMetadataSnapshot.builder() //
                 .setMetadataTree(newDataTree) //
                 .setSchemaContext(schemaContext) //
                 .build();
 
-        for(ChangeListenerNotifyTask task : listenerTasks) {
-            executor.submit(task);
-        }
+        /*
+         * The commit has to occur atomically with regard to listener registrations.
+         */
+        synchronized (this) {
+            final boolean success = snapshot.compareAndSet(currentSnapshot, newSnapshot);
+            checkState(success, "Store snapshot and transaction snapshot differ. This should never happen.");
 
+            for (ChangeListenerNotifyTask task : listenerTasks) {
+                executor.submit(task);
+            }
+        }
     }
 
     private static class SnapshotBackedReadTransaction implements DOMStoreReadTransaction {
@@ -291,7 +305,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
 
         @Override
         public ListenableFuture<Boolean> canCommit() {
-            final DataAndMetadataSnapshot snapshotCapture = snapshot;
+            final DataAndMetadataSnapshot snapshotCapture = snapshot.get();
             final ModificationApplyOperation snapshotOperation = operationTree;
 
             return executor.submit(new Callable<Boolean>() {
@@ -308,7 +322,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
 
         @Override
         public ListenableFuture<Void> preCommit() {
-            storeSnapshot = snapshot;
+            storeSnapshot = snapshot.get();
             if(modification.getModificationType() == ModificationType.UNMODIFIED) {
                 return Futures.immediateFuture(null);
             }
@@ -323,7 +337,6 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
                     proposedSubtree = operationTree.apply(modification, Optional.of(metadataTree),
                             increase(metadataTree.getSubtreeVersion()));
 
-
                     listenerTasks = DataChangeEventResolver.create() //
                             .setRootPath(PUBLIC_ROOT_PATH) //
                             .setBeforeRoot(Optional.of(metadataTree)) //
@@ -359,7 +372,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
 
     }
 
-    private class AllwaysFailOperation implements ModificationApplyOperation {
+    private static final class AlwaysFailOperation implements ModificationApplyOperation {
 
         @Override
         public Optional<StoreMetadataNode> apply(final NodeModification modification,
index df58d62dd47662a7da382f2232b8067a337c7118..02c2a4fa06042e2984745183262a7d053411157a 100644 (file)
@@ -45,6 +45,11 @@ public final class StoreUtils {
         return new InitialDataChangeEvent(path, data.getData());
     }
 
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public static <V> Function<Identifiable<V>, V> identifierExtractor() {
+        return (Function) EXTRACT_IDENTIFIER;
+    }
+
     private static final class InitialDataChangeEvent implements
             AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> {
 
@@ -88,30 +93,25 @@ public final class StoreUtils {
 
     }
 
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    public static <V> Function<Identifiable<V>,V> identifierExtractor() {
-        return (Function) EXTRACT_IDENTIFIER;
-    }
-
     public static <V> Set<V> toIdentifierSet(final Iterable<? extends Identifiable<V>> children) {
-        return FluentIterable.from(children).transform(StoreUtils.<V>identifierExtractor()).toSet();
+        return FluentIterable.from(children).transform(StoreUtils.<V> identifierExtractor()).toSet();
     }
 
     public static String toStringTree(final StoreMetadataNode metaNode) {
         StringBuilder builder = new StringBuilder();
-        toStringTree(builder, metaNode,0);
+        toStringTree(builder, metaNode, 0);
         return builder.toString();
 
     }
 
-    private static void toStringTree(final StringBuilder builder, final StoreMetadataNode metaNode,final int offset) {
+    private static void toStringTree(final StringBuilder builder, final StoreMetadataNode metaNode, final int offset) {
         String prefix = Strings.repeat(" ", offset);
         builder.append(prefix).append(toStringTree(metaNode.getIdentifier()));
         NormalizedNode<?, ?> dataNode = metaNode.getData();
-        if(dataNode instanceof NormalizedNodeContainer<?,?,?>)  {
+        if (dataNode instanceof NormalizedNodeContainer<?, ?, ?>) {
             builder.append(" {").append("\n");
-            for(StoreMetadataNode child : metaNode.getChildren()) {
-                toStringTree(builder, child, offset+4);
+            for (StoreMetadataNode child : metaNode.getChildren()) {
+                toStringTree(builder, child, offset + 4);
             }
             builder.append(prefix).append("}");
         } else {
@@ -121,7 +121,7 @@ public final class StoreUtils {
     }
 
     private static String toStringTree(final PathArgument identifier) {
-        ifidentifier instanceof NodeIdentifierWithPredicates) {
+        if (identifier instanceof NodeIdentifierWithPredicates) {
             StringBuilder builder = new StringBuilder();
             builder.append(identifier.getNodeType().getLocalName());
             builder.append(((NodeIdentifierWithPredicates) identifier).getKeyValues().values());
index ee49effd31002e88c8f89924f7b41eb977f7b3e2..2528d383b95a0c9f6534ad0f01627f56dbc26c5c 100644 (file)
@@ -1,5 +1,6 @@
 package org.opendaylight.controller.md.sal.dom.store.impl.tree;
 
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -8,14 +9,17 @@ import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataCh
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
 import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
 import org.opendaylight.yangtools.concepts.Identifiable;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
 
-public class ListenerRegistrationNode implements StoreTreeNode<ListenerRegistrationNode>,Identifiable<PathArgument> {
+public class ListenerRegistrationNode implements StoreTreeNode<ListenerRegistrationNode>, Identifiable<PathArgument> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ListenerRegistrationNode.class);
 
     private final ListenerRegistrationNode parent;
     private final Map<PathArgument, ListenerRegistrationNode> children;
@@ -23,10 +27,10 @@ public class ListenerRegistrationNode implements StoreTreeNode<ListenerRegistrat
     private final HashSet<DataChangeListenerRegistration<?>> listeners;
 
     private ListenerRegistrationNode(final PathArgument identifier) {
-        this(null,identifier);
+        this(null, identifier);
     }
 
-    private ListenerRegistrationNode(final ListenerRegistrationNode parent,final PathArgument identifier) {
+    private ListenerRegistrationNode(final ListenerRegistrationNode parent, final PathArgument identifier) {
         this.parent = parent;
         this.identifier = identifier;
         children = new HashMap<>();
@@ -42,23 +46,39 @@ public class ListenerRegistrationNode implements StoreTreeNode<ListenerRegistrat
         return identifier;
     }
 
-    public Iterable<DataChangeListenerRegistration<?>> getListeners() {
-        return listeners;
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    public Collection<org.opendaylight.controller.md.sal.dom.store.impl.DataChangeListenerRegistration<?>> getListeners() {
+        // FIXME: this is not thread-safe and races with listener (un)registration!
+        return (Collection) listeners;
     }
 
     @Override
     public synchronized Optional<ListenerRegistrationNode> getChild(final PathArgument child) {
+        return Optional.fromNullable(children.get(child));
+    }
+
+    public synchronized ListenerRegistrationNode ensureChild(final PathArgument child) {
         ListenerRegistrationNode potential = (children.get(child));
-        if(potential == null) {
+        if (potential == null) {
             potential = new ListenerRegistrationNode(this, child);
             children.put(child, potential);
         }
-        return Optional.of(potential);
+        return potential;
     }
 
-    public <L extends AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>> ListenerRegistration<L> registerDataChangeListener(
+    /**
+     *
+     * Registers listener on this node.
+     *
+     * @param path Full path on which listener is registered.
+     * @param listener Listener
+     * @param scope Scope of triggering event.
+     * @return
+     */
+    public <L extends AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>> DataChangeListenerRegistration<L> registerDataChangeListener(final InstanceIdentifier path,
             final L listener, final DataChangeScope scope) {
-        DataChangeListenerRegistration<L> listenerReg = new DataChangeListenerRegistration<L>(listener, scope,this);
+
+        DataChangeListenerRegistration<L> listenerReg = new DataChangeListenerRegistration<L>(path,listener, scope, this);
         listeners.add(listenerReg);
         return listenerReg;
     }
@@ -68,9 +88,8 @@ public class ListenerRegistrationNode implements StoreTreeNode<ListenerRegistrat
         removeThisIfUnused();
     }
 
-
     private void removeThisIfUnused() {
-        if(parent != null && listeners.isEmpty() && children.isEmpty()) {
+        if (parent != null && listeners.isEmpty() && children.isEmpty()) {
             parent.removeChildIfUnused(this);
         }
     }
@@ -80,8 +99,8 @@ public class ListenerRegistrationNode implements StoreTreeNode<ListenerRegistrat
     }
 
     private boolean areChildrenUnused() {
-        for(ListenerRegistrationNode child :  children.values()) {
-            if(!child.isUnused()) {
+        for (ListenerRegistrationNode child : children.values()) {
+            if (!child.isUnused()) {
                 return false;
             }
         }
@@ -92,23 +111,24 @@ public class ListenerRegistrationNode implements StoreTreeNode<ListenerRegistrat
         // FIXME Remove unnecessary
     }
 
-
-
-
-    public static class DataChangeListenerRegistration<T extends AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>> extends AbstractObjectRegistration<T>
-            implements ListenerRegistration<T> {
+    public static class DataChangeListenerRegistration<T extends AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>>
+            extends AbstractObjectRegistration<T> implements
+            org.opendaylight.controller.md.sal.dom.store.impl.DataChangeListenerRegistration<T> {
 
         private final DataChangeScope scope;
         private ListenerRegistrationNode node;
+        private final InstanceIdentifier path;
 
-        public DataChangeListenerRegistration(final T listener, final DataChangeScope scope, final ListenerRegistrationNode node) {
+        public DataChangeListenerRegistration(final InstanceIdentifier path,final T listener, final DataChangeScope scope,
+                final ListenerRegistrationNode node) {
             super(listener);
-
+            this.path = path;
             this.scope = scope;
             this.node = node;
         }
 
-        protected DataChangeScope getScope() {
+        @Override
+        public DataChangeScope getScope() {
             return scope;
         }
 
@@ -117,5 +137,10 @@ public class ListenerRegistrationNode implements StoreTreeNode<ListenerRegistrat
             node.removeListener(this);
             node = null;
         }
+
+        @Override
+        public InstanceIdentifier getPath() {
+            return path;
+        }
     }
 }
index 3e73f161c28df060f33e9f658b8eb4d60d30f5ac..ffdcda31eb7b4916bc96b3ceca017da177648ab3 100644 (file)
@@ -50,7 +50,7 @@
         </plugins>
         <pluginManagement>
             <plugins>
-                <!--This plugin's configuration is used to store Eclipse 
+                <!--This plugin's configuration is used to store Eclipse
                     m2e settings only. It has no influence on the Maven build itself. -->
                 <plugin>
                     <groupId>org.eclipse.m2e</groupId>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-data-api</artifactId>
         </dependency>
-        <!--dependency> <groupId>org.opendaylight.yangtools</groupId> <artifactId>yang-data-impl</artifactId> 
+        <!--dependency> <groupId>org.opendaylight.yangtools</groupId> <artifactId>yang-data-impl</artifactId>
             <version>${yangtools.version}</version> </dependency -->
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
-            <artifactId>config-persister-file-adapter</artifactId>
+            <artifactId>config-persister-file-xml-adapter</artifactId>
             <version>${config.version}</version>
         </dependency>
         <dependency>
             <groupId>org.ops4j.pax.exam</groupId>
             <artifactId>pax-exam</artifactId>
             <version>${exam.version}</version>
-            <!-- Compile scope here is intentional, it is used in TestHelper 
-                class which could be downloaded via nexus and reused in other integration 
+            <!-- Compile scope here is intentional, it is used in TestHelper
+                class which could be downloaded via nexus and reused in other integration
                 tests. -->
             <scope>compile</scope>
         </dependency>
index 8ebf28f35f1771ec778fc6e1a5b16088f6aafe16..fa478ac72e398ae928c619004023b8aae6cc68fe 100644 (file)
@@ -305,7 +305,7 @@ class RestconfImpl implements RestconfService {
         return callRpc(rpc, null)
     }
 
-    def resolveIdentifierInInvokeRpc(String identifier) {
+    private def resolveIdentifierInInvokeRpc(String identifier) {
         if (identifier.indexOf("/") === -1) {
             val identifierDecoded = identifier.urlPathArgDecode
             val rpc = identifierDecoded.rpcDefinition
@@ -314,8 +314,8 @@ class RestconfImpl implements RestconfService {
             }
             throw new ResponseException(NOT_FOUND, "RPC does not exist.");
         }
-        val slashErrorMsg  = String.format("Identifier %n%s%ncan't contain slash character (/). +
-            If slash is part of identifier name then use %2F placeholder.",identifier)
+        val slashErrorMsg = String.format(
+            "Identifier %n%s%ncan't contain slash character (/).%nIf slash is part of identifier name then use %%2F placeholder.", identifier)
         throw new ResponseException(NOT_FOUND, slashErrorMsg);
     }
 
index a9fc739456b95740c3ab9c00313c31711e7ebba9..f0a8584730955a76514824494d02de82f66ded54 100644 (file)
@@ -43,7 +43,7 @@
         </plugins>
         <pluginManagement>
             <plugins>
-                <!--This plugin's configuration is used to store Eclipse 
+                <!--This plugin's configuration is used to store Eclipse
                     m2e settings only. It has no influence on the Maven build itself. -->
                 <plugin>
                     <groupId>org.eclipse.m2e</groupId>
             <artifactId>jersey-core</artifactId>
             <version>${jersey.version}</version>
         </dependency>
-        <!-- <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-servlet</artifactId> 
+        <!-- <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-servlet</artifactId>
             <version>${jersey.version}</version> </dependency> -->
         <dependency>
             <groupId>com.sun.jersey</groupId>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
-            <artifactId>config-persister-file-adapter</artifactId>
+            <artifactId>config-persister-file-xml-adapter</artifactId>
             <version>${config.version}</version>
         </dependency>
         <dependency>
index 8400bc18353fc765da09cf6f84831085875fbb44..4a43e0cf8266c1ae5c56dbb6a77c9bdc7018bb73 100644 (file)
@@ -75,9 +75,9 @@ public class ServiceProviderController {
         InstanceIdentifier path = InstanceIdentifier.builder(InventoryUtils.INVENTORY_PATH)
                 .nodeWithKey(InventoryUtils.INVENTORY_NODE, InventoryUtils.INVENTORY_ID, "foo").toInstance();
 
-        
+
         InstanceIdentifier mountPointPath = path;
-        
+
         /** We retrive a mountpoint **/
         MountProvisionInstance mountPoint = mountService.getMountPoint(mountPointPath);
         CompositeNode data = mountPoint.readOperationalData(InstanceIdentifier.builder().node(CONFIG_MODULES)
@@ -215,7 +215,7 @@ public class ServiceProviderController {
                 mavenBundle(ODL, "yang-jmx-generator").versionAsInProject(),
                 mavenBundle(ODL, "logback-config").versionAsInProject(),
                 mavenBundle(ODL, "config-persister-api").versionAsInProject(),
-                // mavenBundle(ODL,"config-persister-file-adapter").versionAsInProject(),
+                // mavenBundle(ODL,"config-persister-file-xml-adapter").versionAsInProject(),
                 mavenBundle(ODL, "protocol-framework").versionAsInProject(),
                 mavenBundle(ODL, "netconf-api").versionAsInProject(),
                 mavenBundle(ODL, "netconf-impl").versionAsInProject(),
index 6dba9ac64e22e1e5d5f528aa6b8c830aa78d9f17..ed5a3a97a4c67809e75857ba77409eb695e00535 100644 (file)
@@ -110,6 +110,10 @@ public class ConfigPusher {
     }
 
     private static class NotEnoughCapabilitiesException extends Exception {
+        private NotEnoughCapabilitiesException(String message, Throwable cause) {
+            super(message, cause);
+        }
+
         private NotEnoughCapabilitiesException(String message) {
             super(message);
         }
@@ -123,13 +127,18 @@ public class ConfigPusher {
      * @return service if capabilities are present, otherwise absent value
      */
     private NetconfOperationService getOperationService(Set<String> expectedCapabilities, String idForReporting) throws NotEnoughCapabilitiesException {
-        NetconfOperationService serviceCandidate = configNetconfConnector.createService(idForReporting);
+        NetconfOperationService serviceCandidate;
+        try {
+            serviceCandidate = configNetconfConnector.createService(idForReporting);
+        } catch(RuntimeException e) {
+            throw new NotEnoughCapabilitiesException("Netconf service not stable for " + idForReporting, e);
+        }
         Set<String> notFoundDiff = computeNotFoundCapabilities(expectedCapabilities, serviceCandidate);
         if (notFoundDiff.isEmpty()) {
             return serviceCandidate;
         } else {
             serviceCandidate.close();
-            logger.debug("Netconf server did not provide required capabilities for {} " +
+            logger.trace("Netconf server did not provide required capabilities for {} " +
                             "Expected but not found: {}, all expected {}, current {}",
                     idForReporting, notFoundDiff, expectedCapabilities, serviceCandidate.getCapabilities()
             );
@@ -226,15 +235,13 @@ public class ConfigPusher {
         try {
             response = operation.handle(request.getDocument(), NetconfOperationChainedExecution.EXECUTION_TERMINATION_POINT);
         } catch (NetconfDocumentedException | RuntimeException e) {
+            if (e instanceof NetconfDocumentedException && e.getCause() instanceof ConflictingVersionException) {
+                throw (ConflictingVersionException) e.getCause();
+            }
             throw new IllegalStateException("Failed to send " + operationNameForReporting +
                     " for configuration " + configIdForReporting, e);
         }
-        try {
-            return NetconfUtil.checkIsMessageOk(response);
-        } catch (ConflictingVersionException e) {
-            logger.trace("conflicting version detected: {} while committing {}", e.toString(), configIdForReporting);
-            throw e;
-        }
+        return NetconfUtil.checkIsMessageOk(response);
     }
 
     // load editConfig.xml template, populate /rpc/edit-config/config with parameter
index c1cad4a8ddaba3750b70c3530d7f8324afde8a95..31a4f080368515c075872173e9ba066c830f5e0e 100644 (file)
@@ -37,12 +37,12 @@ import java.util.ListIterator;
  netconf.config.persister.1.storageAdapterClass=org.opendaylight.controller.config.persist.storage.directory.xml.XmlDirectoryStorageAdapter
  netconf.config.persister.1.properties.fileStorage=configuration/initial/
 
- netconf.config.persister.2.storageAdapterClass=org.opendaylight.controller.config.persist.storage.file.FileStorageAdapter
+ netconf.config.persister.2.storageAdapterClass=org.opendaylight.controller.config.persist.storage.file.xml.XmlFileStorageAdapter
  netconf.config.persister.2.readonly=true
- netconf.config.persister.2.properties.fileStorage=configuration/current/controller.config.1.txt
+ netconf.config.persister.2.properties.fileStorage=configuration/current/controller.config.1.xml
 
- netconf.config.persister.3.storageAdapterClass=org.opendaylight.controller.config.persist.storage.file.FileStorageAdapter
- netconf.config.persister.3.properties.fileStorage=configuration/current/controller.config.2.txt
+ netconf.config.persister.3.storageAdapterClass=org.opendaylight.controller.config.persist.storage.file.xml.XmlFileStorageAdapter
+ netconf.config.persister.3.properties.fileStorage=configuration/current/controller.config.2.xml
  netconf.config.persister.3.properties.numberOfBackups=3
 
  </pre>
index b722496142e4f2014b82e776317488e02ddb4527..493ecd9250262959e78523c4ed1dc49c7d177474 100644 (file)
@@ -33,6 +33,7 @@ import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
 
 public class ConfigPersisterTest {
@@ -113,26 +114,29 @@ public class ConfigPersisterTest {
     @Test
     public void testPersisterConflictingVersionException() throws Exception {
         setUpContextAndStartPersister("cap1");
-        NetconfOperationService service = getWorkingService(getConflictVersionDocument());
-        doReturn(service).when(ctx.serviceFactory).createService(anyString());
+
+        doReturn(getConflictingService()).when(ctx.serviceFactory).createService(anyString());
         Thread.sleep(2000);
         handler.assertException(IllegalStateException.class, "Max wait for conflicting version stabilization timeout");
     }
 
-    private Document getConflictVersionDocument() throws SAXException, IOException {
-        return XmlUtil.readXmlToDocument(
-                "<rpc-reply message-id=\"1\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n" +
-                        "<rpc-error><error-info><error>" +
-                        ConflictingVersionException.class.getCanonicalName() +
-                        "</error></error-info></rpc-error>\n" +
-                        "</rpc-reply>"
-        );
+    private NetconfOperationService getConflictingService() throws Exception {
+        NetconfOperationService service =  getWorkingService(getOKDocument());
+        ConflictingVersionException cve = new ConflictingVersionException("");
+        try {
+            NetconfDocumentedException.wrap(cve);
+            throw new AssertionError("Should throw an exception");
+        }catch(NetconfDocumentedException e) {
+            NetconfOperation mockedOperation = service.getNetconfOperations().iterator().next();
+            doThrow(e).when(mockedOperation).handle(any(Document.class), any(NetconfOperationChainedExecution.class));
+            return service;
+        }
     }
 
     @Test
     public void testSuccessConflictingVersionException() throws Exception {
         setUpContextAndStartPersister("cap1");
-        doReturn(getWorkingService(getConflictVersionDocument())).when(ctx.serviceFactory).createService(anyString());
+        doReturn(getConflictingService()).when(ctx.serviceFactory).createService(anyString());
         Thread.sleep(500);
         // working service:
         logger.info("Switching to working service **");
index b0884ca2fb4bc648183841241967660c3f9fc9f3..29f40ce6242e7fcada70574b774a56ff1a5fab99 100644 (file)
@@ -8,9 +8,7 @@
 package org.opendaylight.controller.netconf.util;
 
 import com.google.common.base.Preconditions;
-import org.opendaylight.controller.config.api.ConflictingVersionException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.util.xml.XMLNetconfUtil;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
@@ -19,8 +17,6 @@ import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.xml.sax.SAXException;
 
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathExpression;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -56,31 +52,17 @@ public final class NetconfUtil {
         return (doc == null) ? null : new NetconfMessage(doc);
     }
 
-    public static Document checkIsMessageOk(NetconfMessage responseMessage) throws ConflictingVersionException {
+    public static Document checkIsMessageOk(NetconfMessage responseMessage) {
         return checkIsMessageOk(responseMessage.getDocument());
     }
 
-    public static Document checkIsMessageOk(Document response) throws ConflictingVersionException {
+    public static Document checkIsMessageOk(Document response) {
         XmlElement element = XmlElement.fromDomDocument(response);
         Preconditions.checkState(element.getName().equals(XmlNetconfConstants.RPC_REPLY_KEY));
         element = element.getOnlyChildElement();
-
         if (element.getName().equals(XmlNetconfConstants.OK)) {
             return response;
         }
-
-        if (element.getName().equals(XmlNetconfConstants.RPC_ERROR)) {
-            logger.warn("Can not load last configuration, operation failed");
-            // is it ConflictingVersionException ?
-            XPathExpression xPathExpression = XMLNetconfUtil.compileXPath("/netconf:rpc-reply/netconf:rpc-error/netconf:error-info/netconf:error");
-            String error = (String) XmlUtil.evaluateXPath(xPathExpression, element.getDomElement(), XPathConstants.STRING);
-            if (error!=null && error.contains(ConflictingVersionException.class.getCanonicalName())) {
-                throw new ConflictingVersionException(error);
-            }
-            throw new IllegalStateException("Can not load last configuration, operation failed: "
-                    + XmlUtil.toString(response));
-        }
-
         logger.warn("Can not load last configuration. Operation failed.");
         throw new IllegalStateException("Can not load last configuration. Operation failed: "
                 + XmlUtil.toString(response));
index b4b8aba81fc0513e5d7debf0aca749f1a592129b..85eeb30a07339c3b379bd756328f7ed96926fbc2 100644 (file)
@@ -8,7 +8,6 @@
 package org.opendaylight.controller.netconf.util;
 
 import org.junit.Test;
-import org.opendaylight.controller.config.api.ConflictingVersionException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.w3c.dom.Document;
@@ -25,7 +24,7 @@ public class NetconfUtilTest {
         try{
             NetconfUtil.checkIsMessageOk(new NetconfMessage(document));
             fail();
-        }catch(ConflictingVersionException e){
+        }catch(IllegalStateException e){
             assertThat(e.getMessage(), containsString("Optimistic lock failed. Expected parent version 21, was 18"));
         }
     }
index 586366f41a63659bc8b75fd8ccbf12df97ae34bd..2be64a8a9873f138ae29876a2ac1c1d1998213e4 100644 (file)
                 <artifactId>config-persister-api</artifactId>
                 <version>${config.version}</version>
             </dependency>
-            <dependency>
-                <groupId>org.opendaylight.controller</groupId>
-                <artifactId>config-persister-file-adapter</artifactId>
-                <version>${config.version}</version>
-            </dependency>
             <dependency>
                 <groupId>${project.groupId}</groupId>
                 <artifactId>netconf-client</artifactId>
index 6582d8c021d5f61de10ae6b221f1217fdd1d668f..ae84a72bbac84ddda56c102972c894e21873a603 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright IBM Corporation, 2013.  All rights reserved.
+ * Copyright IBM Corporation and others, 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,
@@ -64,6 +64,12 @@ public class NeutronSubnet extends ConfigurationObject implements Serializable {
     @XmlElement (name="tenant_id")
     String tenantID;
 
+    @XmlElement (name="ipv6_address_mode", nillable=true)
+    String ipV6AddressMode;
+
+    @XmlElement (name="ipv6_ra_mode", nillable=true)
+    String ipV6RaMode;
+
     /* stores the OpenStackPorts associated with an instance
      * used to determine if that instance can be deleted.
      */
@@ -170,6 +176,14 @@ public class NeutronSubnet extends ConfigurationObject implements Serializable {
         this.tenantID = tenantID;
     }
 
+    public String getIpV6AddressMode() { return ipV6AddressMode; }
+
+    public void setIpV6AddressMode(String ipV6AddressMode) { this.ipV6AddressMode = ipV6AddressMode; }
+
+    public String getIpV6RaMode() { return ipV6RaMode; }
+
+    public void setIpV6RaMode(String ipV6RaMode) { this.ipV6RaMode = ipV6RaMode; }
+
     /**
      * This method copies selected fields from the object and returns them
      * as a new object, suitable for marshaling.
@@ -224,6 +238,12 @@ public class NeutronSubnet extends ConfigurationObject implements Serializable {
             if (s.equals("tenant_id")) {
                 ans.setTenantID(this.getTenantID());
             }
+            if (s.equals("ipv6_address_mode")) {
+                ans.setIpV6AddressMode(this.getIpV6AddressMode());
+            }
+            if (s.equals("ipv6_ra_mode")) {
+                ans.setIpV6RaMode(this.getIpV6RaMode());
+            }
         }
         return ans;
     }
@@ -444,6 +464,7 @@ public class NeutronSubnet extends ConfigurationObject implements Serializable {
                 + ", ipVersion=" + ipVersion + ", cidr=" + cidr + ", gatewayIP=" + gatewayIP + ", dnsNameservers="
                 + dnsNameservers + ", allocationPools=" + allocationPools + ", hostRoutes=" + hostRoutes
                 + ", enableDHCP=" + enableDHCP + ", tenantID=" + tenantID + ", myPorts=" + myPorts
-                + ", gatewayIPAssigned=" + gatewayIPAssigned + "]";
+                + ", gatewayIPAssigned=" + gatewayIPAssigned + ", ipv6AddressMode=" + ipV6AddressMode
+                + ", ipv6RaMode=" + ipV6RaMode + "]";
     }
 }
index 224fcb5f01ceaaaa662d2c9bbe0655892da463a2..f397eb3a97b0630002b3fc1b70901a1a25cf0609 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright IBM Corporation, 2013.  All rights reserved.
+ * Copyright IBM Corporation and others, 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,
@@ -87,6 +87,8 @@ public class NeutronSubnetsNorthbound {
             @QueryParam("gateway_ip") String queryGatewayIP,
             @QueryParam("enable_dhcp") String queryEnableDHCP,
             @QueryParam("tenant_id") String queryTenantID,
+            @QueryParam("ipv6_address_mode") String queryIpV6AddressMode,
+            @QueryParam("ipv6_ra_mode") String queryIpV6RaMode,
             // pagination
             @QueryParam("limit") String limit,
             @QueryParam("marker") String marker,
@@ -110,7 +112,9 @@ public class NeutronSubnetsNorthbound {
                     (queryCIDR == null || queryCIDR.equals(oSS.getCidr())) &&
                     (queryGatewayIP == null || queryGatewayIP.equals(oSS.getGatewayIP())) &&
                     (queryEnableDHCP == null || queryEnableDHCP.equals(oSS.getEnableDHCP())) &&
-                    (queryTenantID == null || queryTenantID.equals(oSS.getTenantID()))) {
+                    (queryTenantID == null || queryTenantID.equals(oSS.getTenantID())) &&
+                    (queryIpV6AddressMode == null || queryIpV6AddressMode.equals(oSS.getIpV6AddressMode())) &&
+                    (queryIpV6RaMode == null || queryIpV6RaMode.equals(oSS.getIpV6RaMode()))){
                 if (fields.size() > 0) {
                     ans.add(extractFields(oSS,fields));
                 } else {
index 548bfb1f9fb26eb93ab4ca5bcd456d9bdc4082c3..fc668b3f4d0f1a1f01bb3a9b096b6bc7440515c0 100644 (file)
@@ -945,7 +945,7 @@ public class DiscoveryService implements IInventoryShimExternalListener, IDataPa
         if (!src.getType().equals(NodeConnector.NodeConnectorIDType.PRODUCTION)) {
             if (type == UpdateType.ADDED) {
                 edgeMap.put(dst, edge);
-            } else {
+            } else if (type == UpdateType.REMOVED) {
                 edgeMap.remove(dst);
             }
         } else {
@@ -954,7 +954,7 @@ public class DiscoveryService implements IInventoryShimExternalListener, IDataPa
              */
             if (type == UpdateType.ADDED) {
                 prodMap.put(dst, edge);
-            } else {
+            } else if (type == UpdateType.REMOVED) {
                 prodMap.remove(dst);
             }
         }
index 6d1c563aa44729581b5eb46b5e61f8cb0543b47a..8893762c3ca41f52fbc0fcfeb8905c66a1d9eb02 100644 (file)
@@ -806,6 +806,8 @@ public class FlowConverter {
         list.add(SwPath.class);
         list.add(HwPath.class);
         list.add(Drop.class);
+        list.add(Flood.class);
+        list.add(FloodAll.class);
 
         return list;
     }