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";
<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>
<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>
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.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);
+ }
+
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.config.yang.protocol.framework;
+
+/**
+*
+*/
+public class NeverReconnectStrategyFactoryModuleFactory extends org.opendaylight.controller.config.yang.protocol.framework.AbstractNeverReconnectStrategyFactoryModuleFactory
+{
+
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.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);
+ }
+
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.config.yang.protocol.framework;
+
+/**
+*
+*/
+public class ReconnectImmediatelyStrategyFactoryModuleFactory extends org.opendaylight.controller.config.yang.protocol.framework.AbstractReconnectImmediatelyStrategyFactoryModuleFactory
+{
+
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.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);
+ }
+
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.config.yang.protocol.framework;
+
+/**
+*
+*/
+public class TimedReconnectStrategyFactoryModuleFactory extends org.opendaylight.controller.config.yang.protocol.framework.AbstractTimedReconnectStrategyFactoryModuleFactory
+{
+
+
+}
--- /dev/null
+// 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
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.config.yang.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);
+ }
+ }
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.config.yang.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;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.config.yang.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;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.config.yang.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;
+ }
+
+}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <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>
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.config.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;
- }
-
-}
-
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.config.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);
- }
-
-}
+++ /dev/null
- </services>
-</data>
+++ /dev/null
-<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
- <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+++ /dev/null
- </modules>
- <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.config.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);
- }
-
-}
+++ /dev/null
-//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
+++ /dev/null
-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
+++ /dev/null
-<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>
+++ /dev/null
-//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
+++ /dev/null
-//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
+++ /dev/null
-urn:opendaylight:l2:types?module=opendaylight-l2-types&revision=2013-08-27
+++ /dev/null
-<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>
+++ /dev/null
-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
+++ /dev/null
-<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>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <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>
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.config.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();
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.config.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);
- }
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.config.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;
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.config.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"));
- }
- }
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.config.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);
- }
-
-}
+++ /dev/null
-<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
+++ /dev/null
-//MODULES START
- <config>txt</config>
-//SERVICES START
- <service>txt</service>
-//CAPABILITIES START
-cap1&rev
-cap2
-capa a
\ No newline at end of file
+++ /dev/null
-<snapshot>
- <required-capabilities>
- <capability>cap1&rev</capability>
- <capability>cap2</capability>
- <capability>capa a</capability>
- </required-capabilities>
- <configuration>
- <config>xml</config>
- </configuration>
-</snapshot>
\ No newline at end of file
+++ /dev/null
-//MODULES START
-configuration
\ No newline at end of file
+++ /dev/null
-
-<snapshot>
\ No newline at end of file
+++ /dev/null
-unknown
-file type
\ No newline at end of file
*/
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;
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;
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
@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();
}
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 {
};
}
+ 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() {
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;
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
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
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));
}
}
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;
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");
@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;
}
@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");
}
}
--- /dev/null
+<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
--- /dev/null
+<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
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <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>
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.config.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 + "]";
- }
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.config.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>";
- }
-
-}
<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>
<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>
<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>
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
-<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>
<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&revision=2013-11-12</capability>
<capability>urn:opendaylight:params:xml:ns:yang:controller:threadpool?module=threadpool&revision=2013-04-09</capability>
<capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&revision=2013-10-28</capability>
<capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&revision=2013-10-28</capability>
</required-capabilities>
-
</snapshot>
-
</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>
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();
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();
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();
}
- 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);
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;
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;
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;
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);
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();
}
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();
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
--- /dev/null
+/**
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.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);
+ }
+
+ }
+}
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
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.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();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.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;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.binding.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
+ }
+
+
+
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.binding.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");
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.binding.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);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.binding.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;
+ }
+
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.binding.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);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.binding.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 + "]";
+ }
+
+ }
+
+}
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;
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);
}
}
@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);
}
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)) {
}
@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);
}
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()) {
}
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()) {
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;
}
return baDataService;
}
- protected void setBindingDataService(DataProviderService baDataService) {
+ protected void setBindingDataService(final DataProviderService baDataService) {
this.baDataService = baDataService;
}
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);
}
}
- protected void setMappingService(BindingIndependentMappingService mappingService) {
+ protected void setMappingService(final BindingIndependentMappingService mappingService) {
this.mappingService = mappingService;
}
}
@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;
}
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;
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);
@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
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());
}
@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();
/**
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) {
}
}
- 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;
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 {
* @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
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)) {
@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;
}
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)) {
}
@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);
}
}
- private RpcInvocationStrategy resolveInvocationStrategy(QName rpc) {
+ private RpcInvocationStrategy resolveInvocationStrategy(final QName rpc) {
return strategiesByQName.get(rpc);
}
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;
}
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);
}
}
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);
@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) {
}
@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));
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();
}
@Override
- public Future<RpcResult<?>> forwardToDomBroker(DataObject input) {
+ public Future<RpcResult<?>> forwardToDomBroker(final DataObject input) {
return Futures.immediateFuture(null);
}
}
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) {
}
@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));
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;
}
}
@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) {
}
@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,
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();
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";
description
"Service definition for Binding Aware MD-SAL.";
-
+
revision "2013-10-28" {
description
"Initial revision";
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;
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 {
}
}
}*/
-
+
container data-broker {
uses config:service-ref {
refine type {
}
}
}
-
+
container notification-service {
uses config:service-ref {
refine type {
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 {
uses common:notification-state;
}
}
-}
\ No newline at end of file
+}
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;
private final List<SchemaContextListener> schemaListeners = new ArrayList<>();
+ private DataProviderService baData;
+
+ private DOMDataBroker newDOMDataBroker;
+
@Override
public SchemaContext getSchemaContext() {
return schemaContext;
.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);
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.");
}
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());
}
public DataProviderService getBindingDataBroker() {
- return baDataImpl;
+ return baData;
}
public org.opendaylight.controller.sal.core.api.data.DataProviderService getDomDataBroker() {
*/
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;
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");
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();
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);
return (Nodes) baDataService.readOperationalData(NODES_INSTANCE_ID_BA);
}
-
+
@Override
protected boolean getStartWithSchema() {
return false;
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;
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");
.node(SUPPORTED_ACTIONS_QNAME) //
.toInstance();
- private DataChangeEvent<InstanceIdentifier<?>, DataObject> receivedChangeEvent;
+ private final SettableFuture<DataChangeEvent<InstanceIdentifier<?>, DataObject>> receivedChangeEvent = SettableFuture.create();
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);
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());
}
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);
}
}
@Override
- public void onDataChanged(DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
- receivedChangeEvent = change;
+ public void onDataChanged(final DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+ receivedChangeEvent.set(change);
}
}
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;
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");
.augmentation(FlowCapableNode.class) //
.build();
- private DataChangeEvent<InstanceIdentifier<?>, DataObject> lastReceivedChangeEvent;
+ private SettableFuture<DataChangeEvent<InstanceIdentifier<?>, DataObject>> lastReceivedChangeEvent;
/**
* Test for Bug 148
* @throws Exception
*/
@Test
+ @Ignore
public void putNodeAndAugmentation() throws Exception {
-
+ lastReceivedChangeEvent = SettableFuture.create();
baDataService.registerDataChangeListener(ALL_FLOW_CAPABLE_NODES, this);
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);
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();
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
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 {
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());
}
- 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);
}
}
@Override
- public void onDataChanged(DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
- lastReceivedChangeEvent = change;
+ public void onDataChanged(final DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+ lastReceivedChangeEvent.set(change);
}
}
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;
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");
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);
.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() {
// 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
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(), //
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(), //
return false;
}
+
+ public boolean isKeyedEntry() {
+ return false;
+ }
+
protected Set<QName> getQNameIdentifiers() {
return Collections.singleton(identifier.getNodeType());
}
return Builders.leafSetEntryBuilder().withNodeIdentifier(nodeId).withValue(node.getValue()).build();
}
+
+ @Override
+ public boolean isKeyedEntry() {
+ return true;
+ }
}
private static abstract class CompositeNodeNormalizationOpertation<T extends PathArgument> extends
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());
}
}
return builder.build();
}
+
+
+ @Override
+ public boolean isKeyedEntry() {
+ return true;
+ }
}
private static final class ContainerNormalization extends DataContainerNormalizationOperation<NodeIdentifier> {
import java.util.AbstractMap;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.Map;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
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;
public class DataNormalizer {
- private final SchemaContext schemaContext;
-
private final DataNormalizationOperation<?> operation;
public DataNormalizer(final SchemaContext ctx) {
- schemaContext = ctx;
operation = DataNormalizationOperation.from(ctx);
}
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());
}
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));
}
}
@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) {
}
}
@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);
}
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) {
} 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() {
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;
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;
return removedPaths;
}
+ @Override
+ public String toString() {
+ return "DOMImmutableDataChangeEvent [created=" + createdData.keySet() + ", updated=" + updatedData.keySet()
+ + ", removed=" + removedPaths + "]";
+ }
+
public static class Builder {
private NormalizedNode<?, ?> after;
private final ImmutableMap.Builder<InstanceIdentifier, NormalizedNode<?, ?>> updated = ImmutableMap.builder();
private final ImmutableSet.Builder<InstanceIdentifier> removed = ImmutableSet.builder();
-
private Builder() {
}
}
}
-
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;
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;
}
public Iterable<ChangeListenerNotifyTask> resolve() {
+ LOG.trace("Resolving events for {}" ,modificationRoot);
resolveAnyChangeEvent(rootPath, Optional.of(listenerRoot), modificationRoot, beforeRoot, afterRoot);
return tasks.build();
}
InstanceIdentifier childPath = StoreUtils.append(path, childId);
builder.merge(resolveCreateEvent(childPath, childListeners, child));
}
+
DOMImmutableDataChangeEvent event = builder.build();
if (listeners.isPresent()) {
addNotifyTask(listeners.get().getListeners(), event);
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();
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() {
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;
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;
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
@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(
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 {
@Override
public ListenableFuture<Boolean> canCommit() {
- final DataAndMetadataSnapshot snapshotCapture = snapshot;
+ final DataAndMetadataSnapshot snapshotCapture = snapshot.get();
final ModificationApplyOperation snapshotOperation = operationTree;
return executor.submit(new Callable<Boolean>() {
@Override
public ListenableFuture<Void> preCommit() {
- storeSnapshot = snapshot;
+ storeSnapshot = snapshot.get();
if(modification.getModificationType() == ModificationType.UNMODIFIED) {
return Futures.immediateFuture(null);
}
proposedSubtree = operationTree.apply(modification, Optional.of(metadataTree),
increase(metadataTree.getSubtreeVersion()));
-
listenerTasks = DataChangeEventResolver.create() //
.setRootPath(PUBLIC_ROOT_PATH) //
.setBeforeRoot(Optional.of(metadataTree)) //
}
- private class AllwaysFailOperation implements ModificationApplyOperation {
+ private static final class AlwaysFailOperation implements ModificationApplyOperation {
@Override
public Optional<StoreMetadataNode> apply(final NodeModification modification,
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<?, ?>> {
}
- @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 {
}
private static String toStringTree(final PathArgument identifier) {
- if( identifier instanceof NodeIdentifierWithPredicates) {
+ if (identifier instanceof NodeIdentifierWithPredicates) {
StringBuilder builder = new StringBuilder();
builder.append(identifier.getNodeType().getLocalName());
builder.append(((NodeIdentifierWithPredicates) identifier).getKeyValues().values());
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;
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;
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<>();
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;
}
removeThisIfUnused();
}
-
private void removeThisIfUnused() {
- if(parent != null && listeners.isEmpty() && children.isEmpty()) {
+ if (parent != null && listeners.isEmpty() && children.isEmpty()) {
parent.removeChildIfUnused(this);
}
}
}
private boolean areChildrenUnused() {
- for(ListenerRegistrationNode child : children.values()) {
- if(!child.isUnused()) {
+ for (ListenerRegistrationNode child : children.values()) {
+ if (!child.isUnused()) {
return false;
}
}
// 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;
}
node.removeListener(this);
node = null;
}
+
+ @Override
+ public InstanceIdentifier getPath() {
+ return path;
+ }
}
}
</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>
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
}
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);
}
</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>
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)
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(),
}
private static class NotEnoughCapabilitiesException extends Exception {
+ private NotEnoughCapabilitiesException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
private NotEnoughCapabilitiesException(String message) {
super(message);
}
* @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()
);
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
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>
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 {
@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 **");
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;
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;
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));
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;
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"));
}
}
<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>
/*
- * 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,
@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.
*/
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.
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;
}
+ ", 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 + "]";
}
}
/*
- * 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,
@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,
(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 {
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 {
*/
if (type == UpdateType.ADDED) {
prodMap.put(dst, edge);
- } else {
+ } else if (type == UpdateType.REMOVED) {
prodMap.remove(dst);
}
}
list.add(SwPath.class);
list.add(HwPath.class);
list.add(Drop.class);
+ list.add(Flood.class);
+ list.add(FloodAll.class);
return list;
}