From: Tony Tkacik Date: Tue, 29 Jul 2014 09:29:39 +0000 (+0000) Subject: Merge changes Ifd28301d,I38220acb,I9bad24df X-Git-Tag: release/helium~402 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=35ac0155c164ead34628292057008bd6e3a1ffb5;hp=d8c12d0919fc0ce038afdad96c5ab6bb531736aa Merge changes Ifd28301d,I38220acb,I9bad24df * changes: WIP: Backwards compatible MountPointService Fix children element lookup in XmlElement Fix config attributes with same names for different modules. --- diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyFactoryModule.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyFactoryModule.java index 580a53be94..12b771df80 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyFactoryModule.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyFactoryModule.java @@ -32,14 +32,14 @@ public final class ReconnectImmediatelyStrategyFactoryModule extends org.openday @Override protected void customValidation(){ - JmxAttributeValidationException.checkNotNull(getTimeout(), "value is not set.", timeoutJmxAttribute); - JmxAttributeValidationException.checkCondition(getTimeout() >= 0, "value " + getTimeout() + " is less than 0", - timeoutJmxAttribute); + JmxAttributeValidationException.checkNotNull(getReconnectTimeout(), "value is not set.", reconnectTimeoutJmxAttribute); + JmxAttributeValidationException.checkCondition(getReconnectTimeout() >= 0, "value " + getReconnectTimeout() + " is less than 0", + reconnectTimeoutJmxAttribute); } @Override public java.lang.AutoCloseable createInstance() { - return new ReconnectImmediatelyStrategyFactoryCloseable(getExecutorDependency(), getTimeout()); + return new ReconnectImmediatelyStrategyFactoryCloseable(getReconnectExecutorDependency(), getReconnectTimeout()); } private static final class ReconnectImmediatelyStrategyFactoryCloseable implements ReconnectStrategyFactory, AutoCloseable { diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyFactoryModule.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyFactoryModule.java index b8849c7a1d..0b4a7baf6f 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyFactoryModule.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyFactoryModule.java @@ -49,7 +49,7 @@ public final class TimedReconnectStrategyFactoryModule extends org.opendaylight. @Override public java.lang.AutoCloseable createInstance() { - return new TimedReconnectStrategyFactoryCloseable(getExecutorDependency(), + return new TimedReconnectStrategyFactoryCloseable(getTimedReconnectExecutorDependency(), getConnectTime(), getMinSleep(), getSleepFactor().doubleValue(), getMaxSleep(), getMaxAttempts(), getDeadline()); } diff --git a/opendaylight/commons/protocol-framework/src/main/yang/odl-protocol-framework-cfg.yang b/opendaylight/commons/protocol-framework/src/main/yang/odl-protocol-framework-cfg.yang index 1856369178..cd84d4a95e 100644 --- a/opendaylight/commons/protocol-framework/src/main/yang/odl-protocol-framework-cfg.yang +++ b/opendaylight/commons/protocol-framework/src/main/yang/odl-protocol-framework-cfg.yang @@ -77,12 +77,12 @@ module protocol-framework { case reconnect-immediately-strategy-factory { when "/config:modules/config:module/config:type = 'reconnect-immediately-strategy-factory'"; - leaf timeout { + leaf reconnect-timeout { mandatory true; type int32; } - container executor { + container reconnect-executor { uses config:service-ref { refine type { mandatory true; @@ -138,7 +138,7 @@ module protocol-framework { units "milliseconds"; } - container executor { + container timed-reconnect-executor { uses config:service-ref { refine type { mandatory true; diff --git a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyModuleTest.java b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyModuleTest.java index 9beadc4dbb..cfdf3bff28 100644 --- a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyModuleTest.java +++ b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyModuleTest.java @@ -78,7 +78,7 @@ public class ReconnectImmediatelyStrategyModuleTest extends AbstractConfigTest { final ReconnectImmediatelyStrategyFactoryModuleMXBean mxBean = transaction.newMBeanProxy( transaction.lookupConfigBean(FACTORY_NAME, INSTANCE_NAME), ReconnectImmediatelyStrategyFactoryModuleMXBean.class); - mxBean.setTimeout(200); + mxBean.setReconnectTimeout(200); final CommitStatus status = transaction.commit(); assertBeanCount(1, FACTORY_NAME); assertStatus(status, 0, 1, 1); @@ -99,8 +99,8 @@ public class ReconnectImmediatelyStrategyModuleTest extends AbstractConfigTest { 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)); + mxBean.setReconnectTimeout(timeout); + mxBean.setReconnectExecutor(GlobalEventExecutorUtil.create(transaction)); return nameCreated; } diff --git a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyModuleTest.java b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyModuleTest.java index a8cdff7119..1c068a98e7 100644 --- a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyModuleTest.java +++ b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyModuleTest.java @@ -7,6 +7,13 @@ */ 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; @@ -17,14 +24,6 @@ import org.opendaylight.controller.config.manager.impl.factoriesresolver.Hardcod import org.opendaylight.controller.config.util.ConfigTransactionJMXClient; import org.opendaylight.controller.config.yang.netty.eventexecutor.GlobalEventExecutorModuleFactory; -import javax.management.InstanceAlreadyExistsException; -import javax.management.ObjectName; -import java.math.BigDecimal; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - public class TimedReconnectStrategyModuleTest extends AbstractConfigTest { private static final String INSTANCE_NAME = "timed-reconect-stategy-facotry-impl"; @@ -158,7 +157,7 @@ public class TimedReconnectStrategyModuleTest extends AbstractConfigTest { mxBean.setMaxSleep(maxSleep); mxBean.setMinSleep(minSleep); mxBean.setSleepFactor(sleepFactor); - mxBean.setExecutor(GlobalEventExecutorUtil.create(transaction)); + mxBean.setTimedReconnectExecutor(GlobalEventExecutorUtil.create(transaction)); return nameCreated; } diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.xml b/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.xml index 9534094fa8..03da7f0ccd 100644 --- a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.xml +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.xml @@ -86,10 +86,10 @@ prefix:inmemory-operational-datastore-provider operational-store-service - + dom:schema-service yang-schema-service - + + org.opendaylight.controller.sal.dom.broker.impl, org.opendaylight.controller.sal.dom.broker.impl.*, + + org.opendaylight.controller.sal.dom.broker, org.opendaylight.controller.sal.dom.broker.osgi, org.opendaylight.controller.sal.dom.broker.util, org.opendaylight.controller.config.yang.md.sal.dom.impl, - org.opendaylight.controller.config.yang.md.sal.dom.statistics, + org.opendaylight.controller.config.yang.md.sal.dom.statistics,\ org.opendaylight.controller.md.sal.dom.broker.impl, org.opendaylight.controller.md.sal.dom.broker.impl.*, org.opendaylight.yangtools.yang.util, diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModule.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModule.java index 998d884b0c..34d231cf2a 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModule.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModule.java @@ -7,8 +7,12 @@ */ package org.opendaylight.controller.config.yang.md.sal.dom.impl; +import com.google.common.collect.ClassToInstanceMap; +import com.google.common.collect.MutableClassToInstanceMap; import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; +import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService; import org.opendaylight.controller.md.sal.dom.broker.impl.compat.BackwardsCompatibleDataBroker; +import org.opendaylight.controller.md.sal.dom.broker.impl.mount.DOMMountPointServiceImpl; import org.opendaylight.controller.sal.core.api.BrokerService; import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry; import org.opendaylight.controller.sal.core.api.data.DataBrokerService; @@ -17,18 +21,15 @@ import org.opendaylight.controller.sal.core.api.data.DataStore; import org.opendaylight.controller.sal.core.api.model.SchemaService; import org.opendaylight.controller.sal.core.api.mount.MountProvisionService; import org.opendaylight.controller.sal.core.api.mount.MountService; +import org.opendaylight.controller.sal.dom.broker.BackwardsCompatibleMountPointManager; import org.opendaylight.controller.sal.dom.broker.BrokerImpl; import org.opendaylight.controller.sal.dom.broker.DataBrokerImpl; import org.opendaylight.controller.sal.dom.broker.GlobalBundleScanningSchemaServiceImpl; -import org.opendaylight.controller.sal.dom.broker.MountPointManagerImpl; import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter; import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareRpcBroker; import org.opendaylight.controller.sal.dom.broker.impl.SchemaContextProviders; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; -import com.google.common.collect.ClassToInstanceMap; -import com.google.common.collect.MutableClassToInstanceMap; - /** * */ @@ -72,10 +73,13 @@ public final class DomBrokerImplModule extends org.opendaylight.controller.confi services.putInstance(DataProviderService.class,legacyData); services.putInstance(DataBrokerService.class, legacyData); + final DOMMountPointService mountService = new DOMMountPointServiceImpl(); + services.putInstance(DOMMountPointService.class, mountService); - MountPointManagerImpl mountService = new MountPointManagerImpl(); - services.putInstance(MountService.class, mountService); - services.putInstance(MountProvisionService.class, mountService); + // TODO remove backwards service, use only new DOMMountPointService + final MountProvisionService backwardsMountService = new BackwardsCompatibleMountPointManager(mountService); + services.putInstance(MountService.class, backwardsMountService); + services.putInstance(MountProvisionService.class, backwardsMountService); return new BrokerImpl(router, services); } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/mount/DOMMountPointServiceImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/mount/DOMMountPointServiceImpl.java index cdb78fc592..9dd180866a 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/mount/DOMMountPointServiceImpl.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/mount/DOMMountPointServiceImpl.java @@ -8,9 +8,12 @@ package org.opendaylight.controller.md.sal.dom.broker.impl.mount; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.collect.ClassToInstanceMap; +import com.google.common.collect.MutableClassToInstanceMap; import java.util.HashMap; import java.util.Map; - import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint; import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService; import org.opendaylight.controller.md.sal.dom.api.DOMService; @@ -22,20 +25,15 @@ import org.opendaylight.yangtools.concepts.util.ListenerRegistry; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; import org.opendaylight.yangtools.yang.model.api.SchemaContext; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; -import com.google.common.collect.ClassToInstanceMap; -import com.google.common.collect.MutableClassToInstanceMap; - public class DOMMountPointServiceImpl implements DOMMountPointService { - private final Map mountPoints = new HashMap<>(); + private final Map mountPoints = new HashMap<>(); private final ListenerRegistry listeners = ListenerRegistry.create(); @Override public Optional getMountPoint(final InstanceIdentifier path) { - return Optional.fromNullable(mountPoints.get(path)); + return Optional.fromNullable(mountPoints.get(path)); } @Override @@ -51,21 +49,35 @@ public class DOMMountPointServiceImpl implements DOMMountPointService { } } + public void notifyMountRemoved(final InstanceIdentifier identifier) { + for (final ListenerRegistration listener : listeners + .getListeners()) { + listener.getInstance().onMountPointRemoved(identifier); + } + } + @Override public ListenerRegistration registerProvisionListener( final MountProvisionListener listener) { return listeners.register(listener); } - public ObjectRegistration registerMountPoint(final SimpleDOMMountPoint mountPoint) { + public ObjectRegistration registerMountPoint(final DOMMountPoint mountPoint) { synchronized (mountPoints) { Preconditions.checkState(!mountPoints.containsKey(mountPoint.getIdentifier()), "Mount point already exists"); mountPoints.put(mountPoint.getIdentifier(), mountPoint); } notifyMountCreated(mountPoint.getIdentifier()); - // FIXME this shouldnt be null - return null; + return new MountRegistration(mountPoint); + } + + public void unregisterMountPoint(final InstanceIdentifier mountPointId) { + synchronized (mountPoints) { + Preconditions.checkState(mountPoints.containsKey(mountPointId), "Mount point does not exist"); + mountPoints.remove(mountPointId); + } + notifyMountRemoved(mountPointId); } public class DOMMountPointBuilderImpl implements DOMMountPointBuilder { @@ -98,4 +110,22 @@ public class DOMMountPointServiceImpl implements DOMMountPointService { return registerMountPoint(mountPoint); } } + + private final class MountRegistration implements ObjectRegistration { + private final DOMMountPoint mountPoint; + + public MountRegistration(final DOMMountPoint mountPoint) { + this.mountPoint = mountPoint; + } + + @Override + public DOMMountPoint getInstance() { + return mountPoint; + } + + @Override + public void close() throws Exception { + unregisterMountPoint(mountPoint.getIdentifier()); + } + } } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BackwardsCompatibleMountPoint.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BackwardsCompatibleMountPoint.java new file mode 100644 index 0000000000..1a1ca00b39 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BackwardsCompatibleMountPoint.java @@ -0,0 +1,561 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html. + */ +package org.opendaylight.controller.sal.dom.broker; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.JdkFutureAdapters; +import com.google.common.util.concurrent.ListenableFuture; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; +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; +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.common.api.data.TransactionChainListener; +import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; +import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener; +import org.opendaylight.controller.md.sal.common.impl.ListenerRegistry; +import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException; +import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer; +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; +import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener; +import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction; +import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction; +import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction; +import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint; +import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService; +import org.opendaylight.controller.md.sal.dom.api.DOMService; +import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain; +import org.opendaylight.controller.md.sal.dom.broker.impl.compat.BackwardsCompatibleDataBroker; +import org.opendaylight.controller.sal.common.DataStoreIdentifier; +import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration; +import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration; +import org.opendaylight.controller.sal.core.api.RoutedRpcDefaultImplementation; +import org.opendaylight.controller.sal.core.api.RpcImplementation; +import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry; +import org.opendaylight.controller.sal.core.api.RpcRegistrationListener; +import org.opendaylight.controller.sal.core.api.RpcRoutingContext; +import org.opendaylight.controller.sal.core.api.data.DataChangeListener; +import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction; +import org.opendaylight.controller.sal.core.api.data.DataProviderService; +import org.opendaylight.controller.sal.core.api.data.DataValidator; +import org.opendaylight.controller.sal.core.api.model.SchemaService; +import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance; +import org.opendaylight.controller.sal.core.api.notify.NotificationListener; +import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService; +import org.opendaylight.controller.sal.dom.broker.impl.NotificationRouterImpl; +import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareRpcBroker; +import org.opendaylight.controller.sal.dom.broker.impl.SchemaContextProvider; +import org.opendaylight.controller.sal.dom.broker.spi.NotificationRouter; +import org.opendaylight.controller.sal.dom.broker.util.ProxySchemaContext; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.concepts.Registration; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener; + +public class BackwardsCompatibleMountPoint implements MountProvisionInstance, SchemaContextProvider, SchemaService { + + private final DataProviderService dataReader; + private final DataReader readWrapper; + + private final InstanceIdentifier mountPath; + private final NotificationPublishService notificationPublishService; + private final RpcProvisionRegistry rpcs; + + private final ListenerRegistry schemaListenerRegistry = new ListenerRegistry<>(); + + private SchemaContext schemaContext; + + public BackwardsCompatibleMountPoint(final InstanceIdentifier path, final DOMMountPointService.DOMMountPointBuilder mountPointBuilder) { + this.mountPath = Preconditions.checkNotNull(path); + Preconditions.checkNotNull(mountPointBuilder); + + dataReader = new DataBrokerImpl(); + readWrapper = new ReadWrapper(); + notificationPublishService = new DelgatingNotificationPublishService(); + rpcs = new SchemaAwareRpcBroker(path.toString(), this); + + mountPointBuilder.addService(DOMDataBroker.class, new BackwardsCompatibleDomStore(dataReader, this)); + mountPointBuilder.addService(NotificationPublishService.class, notificationPublishService); + mountPointBuilder.addService(RpcProvisionRegistry.class, rpcs); + + mountPointBuilder.addInitialSchemaContext(new ProxySchemaContext(this)); + + mountPointBuilder.register(); + } + + public BackwardsCompatibleMountPoint(final InstanceIdentifier path, final DOMMountPoint mount) { + this.mountPath = Preconditions.checkNotNull(path); + Preconditions.checkNotNull(mount); + + final DOMDataBroker domBroker = getServiceWithCheck(mount, DOMDataBroker.class); + + this.schemaContext = mount.getSchemaContext(); + dataReader = new BackwardsCompatibleDataBroker(domBroker, this); + readWrapper = new ReadWrapper(); + + notificationPublishService = getServiceWithCheck(mount, NotificationPublishService.class); + rpcs = getServiceWithCheck(mount, RpcProvisionRegistry.class); + } + + private T getServiceWithCheck(final DOMMountPoint mount, final Class type) { + final Optional serviceOptional = mount.getService(type); + Preconditions.checkArgument(serviceOptional.isPresent(), "Service {} has to be set in {}. " + + "Cannot construct backwards compatible mount wrapper without it", type, mount); + return serviceOptional.get(); + } + + @Override + public void addModule(final Module module) { + throw new UnsupportedOperationException(); + } + + @Override + public void removeModule(final Module module) { + throw new UnsupportedOperationException(); + } + + @Override + public SchemaContext getSessionContext() { + return getSchemaContext(); + } + + @Override + public SchemaContext getGlobalContext() { + return getSchemaContext(); + } + + @Override + public ListenerRegistration registerSchemaServiceListener(final SchemaServiceListener listener) { + return schemaListenerRegistry.register(listener); + } + + @Override + public void publish(final CompositeNode notification) { + notificationPublishService.publish(notification); + } + + @Override + public ListenerRegistration addNotificationListener(final QName notification, final NotificationListener listener) { + return notificationPublishService.addNotificationListener(notification, listener); + } + + // TODO Read wrapper is never used ... same in org.opendaylight.controller.sal.dom.broker.MountPointImpl + public DataReader getReadWrapper() { + return readWrapper; + } + + @Override + public CompositeNode readConfigurationData(final InstanceIdentifier path) { + return dataReader.readConfigurationData(path); + } + + @Override + public CompositeNode readOperationalData(final InstanceIdentifier path) { + return dataReader.readOperationalData(path); + } + + @Override + public Registration registerOperationalReader( + final InstanceIdentifier path, final DataReader reader) { + return dataReader.registerOperationalReader(path, reader); + } + + @Override + public Registration registerConfigurationReader( + final InstanceIdentifier path, final DataReader reader) { + return dataReader.registerConfigurationReader(path, reader); + } + + @Override + public RoutedRpcRegistration addRoutedRpcImplementation(final QName rpcType, final RpcImplementation implementation) { + return rpcs.addRoutedRpcImplementation(rpcType, implementation); + } + + @Override + public void setRoutedRpcDefaultDelegate(final RoutedRpcDefaultImplementation defaultImplementation) { + rpcs.setRoutedRpcDefaultDelegate(defaultImplementation); + } + + @Override + public RpcRegistration addRpcImplementation(final QName rpcType, final RpcImplementation implementation) + throws IllegalArgumentException { + return rpcs.addRpcImplementation(rpcType, implementation); + } + + @Override + public Set getSupportedRpcs() { + return rpcs.getSupportedRpcs(); + } + + @Override + public ListenableFuture> invokeRpc(final QName rpc, final CompositeNode input) { + return rpcs.invokeRpc(rpc, input); + } + + @Override + public ListenerRegistration addRpcRegistrationListener(final RpcRegistrationListener listener) { + return rpcs.addRpcRegistrationListener(listener); + } + + @Override + public ListenableFuture> rpc(final QName type, final CompositeNode input) { + return rpcs.invokeRpc(type, input); + } + + @Override + public DataModificationTransaction beginTransaction() { + return dataReader.beginTransaction(); + } + + @Override + public ListenerRegistration registerDataChangeListener(final InstanceIdentifier path, + final DataChangeListener listener) { + return dataReader.registerDataChangeListener(path, listener); + } + + @Override + public Registration registerCommitHandler( + final InstanceIdentifier path, final DataCommitHandler commitHandler) { + return dataReader.registerCommitHandler(path, commitHandler); + } + + @Override + public void removeRefresher(final DataStoreIdentifier store, final DataRefresher refresher) { + // NOOP + } + + @Override + public void addRefresher(final DataStoreIdentifier store, final DataRefresher refresher) { + // NOOP + } + + @Override + public void addValidator(final DataStoreIdentifier store, final DataValidator validator) { + // NOOP + } + @Override + public void removeValidator(final DataStoreIdentifier store, final DataValidator validator) { + // NOOP + } + + @Override + public SchemaContext getSchemaContext() { + return schemaContext; + } + + @Override + public void setSchemaContext(final SchemaContext schemaContext) { + this.schemaContext = schemaContext; + for (ListenerRegistration schemaServiceListenerListenerRegistration : schemaListenerRegistry.getListeners()) { + schemaServiceListenerListenerRegistration.getInstance().onGlobalContextUpdated(schemaContext); + } + } + + class ReadWrapper implements DataReader { + private InstanceIdentifier shortenPath(final InstanceIdentifier path) { + InstanceIdentifier ret = null; + if(mountPath.contains(path)) { + final List newArgs = path.getPath().subList(mountPath.getPath().size(), path.getPath().size()); + ret = InstanceIdentifier.create(newArgs); + } + return ret; + } + + @Override + public CompositeNode readConfigurationData(final InstanceIdentifier path) { + final InstanceIdentifier newPath = shortenPath(path); + if(newPath == null) { + return null; + } + return BackwardsCompatibleMountPoint.this.readConfigurationData(newPath); + } + + @Override + public CompositeNode readOperationalData(final InstanceIdentifier path) { + final InstanceIdentifier newPath = shortenPath(path); + if(newPath == null) { + return null; + } + return BackwardsCompatibleMountPoint.this.readOperationalData(newPath); + } + } + + @Override + public ListenerRegistration>> registerCommitHandlerListener( + final RegistrationListener> commitHandlerListener) { + return dataReader.registerCommitHandlerListener(commitHandlerListener); + } + + @Override + public > ListenerRegistration registerRouteChangeListener( + final L listener) { + return rpcs.registerRouteChangeListener(listener); + } + + @VisibleForTesting + static final class BackwardsCompatibleDomStore implements DOMDataBroker { + private final DataProviderService dataReader; + private final SchemaContextProvider schemaContextProvider; + + public BackwardsCompatibleDomStore(final DataProviderService dataReader, final SchemaContextProvider schemaContextProvider) { + this.dataReader = dataReader; + this.schemaContextProvider = schemaContextProvider; + } + + @Override + public DOMDataReadOnlyTransaction newReadOnlyTransaction() { + final DataNormalizer dataNormalizer = new DataNormalizer(schemaContextProvider.getSchemaContext()); + return new BackwardsCompatibleReadTransaction(dataReader, dataNormalizer); + } + + @Override + public DOMDataWriteTransaction newWriteOnlyTransaction() { + final DataNormalizer dataNormalizer = new DataNormalizer(schemaContextProvider.getSchemaContext()); + return new BackwardsCompatibleWriteTransaction(dataReader, dataNormalizer); + } + + @Override + public ListenerRegistration registerDataChangeListener(final LogicalDatastoreType store, final InstanceIdentifier path, final DOMDataChangeListener listener, final DataChangeScope triggeringScope) { + throw new UnsupportedOperationException("Register data listener not supported for mount point"); + } + + @Override + public DOMTransactionChain createTransactionChain(final TransactionChainListener listener) { + throw new UnsupportedOperationException("Transaction chain not supported for mount point"); + } + + @Override + public DOMDataReadWriteTransaction newReadWriteTransaction() { + final DataNormalizer dataNormalizer = new DataNormalizer(schemaContextProvider.getSchemaContext()); + return new BackwardsCompatibleReadWriteTransaction(dataReader, dataNormalizer); + } + + @VisibleForTesting + static final class BackwardsCompatibleReadTransaction implements DOMDataReadOnlyTransaction { + private final DataProviderService dataReader; + private final DataNormalizer normalizer; + + public BackwardsCompatibleReadTransaction(final DataProviderService dataReader, final DataNormalizer normalizer) { + this.dataReader = dataReader; + this.normalizer = normalizer; + } + + @Override + public Object getIdentifier() { + return this; + } + + @Override + public void close() { + // NOOP + } + + @Override + public ListenableFuture>> read(final LogicalDatastoreType store, final InstanceIdentifier path) { + + CompositeNode rawData = null; + + switch (store) { + case CONFIGURATION: { + rawData = dataReader.readConfigurationData(path); + break; + } + case OPERATIONAL: { + rawData = dataReader.readOperationalData(path); + break; + } + } + Preconditions.checkNotNull(rawData, "Unable to read %s data on path %s", store, path); + + final Map.Entry> normalized = normalizer.toNormalized(path, rawData); + final Optional> normalizedNodeOptional = Optional.>fromNullable(normalized.getValue()); + return com.google.common.util.concurrent.Futures.immediateFuture(normalizedNodeOptional); + } + } + + @VisibleForTesting + static final class BackwardsCompatibleWriteTransaction implements DOMDataWriteTransaction { + private DataModificationTransaction oldTx; + private final DataNormalizer dataNormalizer; + + public BackwardsCompatibleWriteTransaction(final DataProviderService dataReader, final DataNormalizer dataNormalizer) { + this.oldTx = dataReader.beginTransaction(); + this.dataNormalizer = dataNormalizer; + } + + @Override + public Object getIdentifier() { + return this; + } + + @Override + public boolean cancel() { + oldTx = null; + return true; + } + + @Override + public void put(final LogicalDatastoreType store, final InstanceIdentifier path, final NormalizedNode data) { + final CompositeNode legacyData = dataNormalizer.toLegacy(path, data); + try { + final InstanceIdentifier legacyPath = dataNormalizer.toLegacy(path); + + switch (store) { + case CONFIGURATION: { + oldTx.putConfigurationData(legacyPath, legacyData); + return; + } + } + + throw new IllegalArgumentException("Cannot put data " + path + " to datastore " + store); + } catch (final DataNormalizationException e) { + throw new IllegalArgumentException(String.format("Cannot transform path %s to legacy format", path), e); + } + } + + @Override + public void merge(final LogicalDatastoreType store, final InstanceIdentifier path, final NormalizedNode data) { + // TODO not supported + throw new UnsupportedOperationException("Merge not supported for mount point"); + } + + @Override + public void delete(final LogicalDatastoreType store, final InstanceIdentifier path) { + try { + final InstanceIdentifier legacyPath = dataNormalizer.toLegacy(path); + + switch (store) { + case CONFIGURATION: { + oldTx.removeConfigurationData(legacyPath); + return; + } + } + throw new IllegalArgumentException("Cannot delete data " + path + " from datastore " + store); + } catch (final DataNormalizationException e) { + throw new IllegalArgumentException(String.format("Cannot transform path %s to legacy format", path), e); + } + } + + @Override + public CheckedFuture submit() { + final ListenableFuture commitAsVoid = Futures.transform(commit(), new Function, Void>() { + @Override + public Void apply(@Nullable final RpcResult input) { + return null; + } + }); + + return Futures.makeChecked(commitAsVoid, new Function() { + @Override + public TransactionCommitFailedException apply(@Nullable final Exception input) { + return new TransactionCommitFailedException("Commit failed", input); + } + }); + } + + @Override + public ListenableFuture> commit() { + return JdkFutureAdapters.listenInPoolThread(oldTx.commit()); + } + } + + + @VisibleForTesting + static class BackwardsCompatibleReadWriteTransaction implements DOMDataReadWriteTransaction { + + private final DataProviderService dataReader; + private final DataNormalizer dataNormalizer; + private final BackwardsCompatibleWriteTransaction delegateWriteTx; + + public BackwardsCompatibleReadWriteTransaction(final DataProviderService dataReader, final DataNormalizer dataNormalizer) { + this.dataReader = dataReader; + this.dataNormalizer = dataNormalizer; + this.delegateWriteTx = new BackwardsCompatibleWriteTransaction(dataReader, dataNormalizer); + } + + @Override + public Object getIdentifier() { + return this; + } + + @Override + public ListenableFuture>> read(final LogicalDatastoreType store, final InstanceIdentifier path) { + return new BackwardsCompatibleReadTransaction(dataReader, dataNormalizer).read(store, path); + } + + @Override + public boolean cancel() { + return delegateWriteTx.cancel(); + } + + @Override + public void put(final LogicalDatastoreType store, final InstanceIdentifier path, final NormalizedNode data) { + delegateWriteTx.put(store, path, data); + } + + @Override + public void merge(final LogicalDatastoreType store, final InstanceIdentifier path, final NormalizedNode data) { + delegateWriteTx.merge(store, path, data); + } + + @Override + public void delete(final LogicalDatastoreType store, final InstanceIdentifier path) { + delegateWriteTx.delete(store, path); + } + + @Override + public CheckedFuture submit() { + return delegateWriteTx.submit(); + } + + @Override + public ListenableFuture> commit() { + return delegateWriteTx.commit(); + } + } + } + + private class DelgatingNotificationPublishService implements NotificationPublishService { + private final NotificationRouter notificationRouter; + + public DelgatingNotificationPublishService(final NotificationRouter notificationRouter) { + this.notificationRouter = notificationRouter; + } + + private DelgatingNotificationPublishService() { + this(new NotificationRouterImpl()); + } + + @Override + public void publish(final CompositeNode notification) { + notificationRouter.publish(notification); + } + + @Override + public ListenerRegistration addNotificationListener(final QName notification, final NotificationListener listener) { + return notificationRouter.addNotificationListener(notification, listener); + } + } +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BackwardsCompatibleMountPointManager.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BackwardsCompatibleMountPointManager.java new file mode 100644 index 0000000000..5c2a8e0725 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BackwardsCompatibleMountPointManager.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html. + */ +package org.opendaylight.controller.sal.dom.broker; + +import static com.google.common.base.Preconditions.checkState; + +import com.google.common.base.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint; +import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService; +import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance; +import org.opendaylight.controller.sal.core.api.mount.MountProvisionListener; +import org.opendaylight.controller.sal.core.api.mount.MountProvisionService; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.concepts.util.ListenerRegistry; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; + +public class BackwardsCompatibleMountPointManager implements MountProvisionService, MountProvisionListener { + + private final ListenerRegistry listeners = ListenerRegistry.create(); + private final ConcurrentMap mounts = new ConcurrentHashMap<>(); + + private final DOMMountPointService domMountPointService; + + public BackwardsCompatibleMountPointManager(final DOMMountPointService domMountPointService) { + this.domMountPointService = domMountPointService; + } + + @Override + public MountProvisionInstance createMountPoint(final InstanceIdentifier path) { + checkState(!mounts.containsKey(path), "Mount already created"); + // Create mount point instance, wrap instance of new API with BackwardsCompatibleMountPoint to preserve backwards comatibility + final BackwardsCompatibleMountPoint mount = new BackwardsCompatibleMountPoint(path, domMountPointService.createMountPoint(path)); + mounts.put(path, mount); + return mount; + } + + public void notifyMountCreated(final InstanceIdentifier identifier) { + for (final ListenerRegistration listener : listeners.getListeners()) { + listener.getInstance().onMountPointCreated(identifier); + } + } + + public void notifyMountRemoved(final InstanceIdentifier identifier) { + for (final ListenerRegistration listener : listeners.getListeners()) { + listener.getInstance().onMountPointRemoved(identifier); + } + } + + @Override + public MountProvisionInstance createOrGetMountPoint( + final InstanceIdentifier path) { + final MountProvisionInstance mount = getMountPoint(path); + if (mount == null) { + return createMountPoint(path); + } + return mount; + } + + @Override + public MountProvisionInstance getMountPoint(final InstanceIdentifier path) { + // If the mount point was created here, return directly + if(mounts.containsKey(path)) { + return mounts.get(path); + } + + // If mount was created in underlying DOMMountService, wrap as MountProvisionInstance + final Optional mount = domMountPointService.getMountPoint(path); + if(mount.isPresent()) { + return new BackwardsCompatibleMountPoint(path, mount.get()); + } else { + return null; + } + } + + @Override + public ListenerRegistration registerProvisionListener( + final MountProvisionListener listener) { + return domMountPointService.registerProvisionListener(listener); + } + + @Override + public void onMountPointCreated(final InstanceIdentifier path) { + notifyMountCreated(path); + } + + @Override + public void onMountPointRemoved(final InstanceIdentifier path) { + notifyMountRemoved(path); + } +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/DOMMountPointServiceProxy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/DOMMountPointServiceProxy.java new file mode 100644 index 0000000000..4c73e0b70a --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/DOMMountPointServiceProxy.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html. + */ +package org.opendaylight.controller.sal.dom.broker.osgi; + +import com.google.common.base.Optional; +import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint; +import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService; +import org.opendaylight.controller.sal.core.api.mount.MountProvisionListener; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.osgi.framework.ServiceReference; + +public class DOMMountPointServiceProxy extends AbstractBrokerServiceProxy implements DOMMountPointService{ + + + public DOMMountPointServiceProxy(final ServiceReference ref, final DOMMountPointService delegate) { + super(ref, delegate); + } + + @Override + public Optional getMountPoint(final InstanceIdentifier path) { + return getDelegate().getMountPoint(path); + } + + @Override + public DOMMountPointBuilder createMountPoint(final InstanceIdentifier path) { + return getDelegate().createMountPoint(path); + } + + public ListenerRegistration registerProvisionListener(final MountProvisionListener listener) { + return getDelegate().registerProvisionListener(listener); + } +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/ProxyFactory.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/ProxyFactory.java index c2d6add17a..2ce2bac862 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/ProxyFactory.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/ProxyFactory.java @@ -9,6 +9,7 @@ package org.opendaylight.controller.sal.dom.broker.osgi; import java.util.Arrays; +import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService; import org.opendaylight.controller.sal.core.api.BrokerService; import org.osgi.framework.ServiceReference; import org.opendaylight.controller.sal.core.api.data.DataBrokerService; @@ -66,6 +67,13 @@ public class ProxyFactory { ((ServiceReference) ref), service); } + private static Object _createProxyImpl(final ServiceReference ref, + final DOMMountPointService service) { + + return new DOMMountPointServiceProxy( + ((ServiceReference) ref), service); + } + private static Object _createProxyImpl(final ServiceReference ref, final SchemaService service) { @@ -113,6 +121,8 @@ public class ProxyFactory { return _createProxyImpl(ref, (SchemaService) service); } else if (service instanceof NotificationService) { return _createProxyImpl(ref, (NotificationService) service); + } else if (service instanceof DOMMountPointService) { + return _createProxyImpl(ref, (DOMMountPointService) service); } else if (service != null) { return _createProxyImpl(ref, service); } else { diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/util/ProxySchemaContext.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/util/ProxySchemaContext.java new file mode 100644 index 0000000000..311055f4b4 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/util/ProxySchemaContext.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html. + */ + +package org.opendaylight.controller.sal.dom.broker.util; + +import java.net.URI; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.Set; + +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; +import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition; +import org.opendaylight.yangtools.yang.model.api.GroupingDefinition; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier; +import org.opendaylight.yangtools.yang.model.api.NotificationDefinition; +import org.opendaylight.yangtools.yang.model.api.RpcDefinition; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider; +import org.opendaylight.yangtools.yang.model.api.SchemaPath; +import org.opendaylight.yangtools.yang.model.api.Status; +import org.opendaylight.yangtools.yang.model.api.TypeDefinition; +import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode; +import org.opendaylight.yangtools.yang.model.api.UsesNode; + +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; + +/** + * ProxySchema Context for SchemaContextProviders + */ +public class ProxySchemaContext implements SchemaContext { + + private final SchemaContextProvider schemaProvider; + + public ProxySchemaContext(final SchemaContextProvider schemaProvider) { + this.schemaProvider = schemaProvider; + } + + private SchemaContext getCurrentSchema() { + Preconditions.checkState(schemaProvider.getSchemaContext() != null, "Schema context unavailable from %s", schemaProvider); + return schemaProvider.getSchemaContext(); + } + + @Override + public Set getDataDefinitions() { + return getCurrentSchema().getDataDefinitions(); + } + + @Override + public Set getModules() { + return getCurrentSchema().getModules(); + } + + @Override + public Set getNotifications() { + return getCurrentSchema().getNotifications(); + } + + @Override + public Set getOperations() { + return getCurrentSchema().getOperations(); + } + + @Override + public Set getExtensions() { + return getCurrentSchema().getExtensions(); + } + + @Override + public Module findModuleByName(final String s, final Date date) { + return getCurrentSchema().findModuleByName(s, date); + } + + @Override + public Set findModuleByNamespace(final URI uri) { + return getCurrentSchema().findModuleByNamespace(uri); + } + + @Override + public Module findModuleByNamespaceAndRevision(final URI uri, final Date date) { + return getCurrentSchema().findModuleByNamespaceAndRevision(uri, date); + } + + @Override + public Optional getModuleSource(final ModuleIdentifier moduleIdentifier) { + return getCurrentSchema().getModuleSource(moduleIdentifier); + } + + @Override + public Set getAllModuleIdentifiers() { + return getCurrentSchema().getAllModuleIdentifiers(); + } + + @Override + public boolean isPresenceContainer() { + return getCurrentSchema().isPresenceContainer(); + } + + @Override + public Set> getTypeDefinitions() { + return getCurrentSchema().getTypeDefinitions(); + } + + @Override + public Collection getChildNodes() { + return getCurrentSchema().getChildNodes(); + } + + @Override + public Set getGroupings() { + return getCurrentSchema().getGroupings(); + } + + @Override + public DataSchemaNode getDataChildByName(final QName qName) { + return getCurrentSchema().getDataChildByName(qName); + } + + @Override + public DataSchemaNode getDataChildByName(final String s) { + return getCurrentSchema().getDataChildByName(s); + } + + @Override + public Set getUses() { + return getCurrentSchema().getUses(); + } + + @Override + public Set getAvailableAugmentations() { + return getCurrentSchema().getAvailableAugmentations(); + } + + @Override + public boolean isAugmenting() { + return getCurrentSchema().isAugmenting(); + } + + @Override + public boolean isAddedByUses() { + return getCurrentSchema().isAddedByUses(); + } + + @Override + public boolean isConfiguration() { + return getCurrentSchema().isConfiguration(); + } + + @Override + public ConstraintDefinition getConstraints() { + return getCurrentSchema().getConstraints(); + } + + @Override + public QName getQName() { + return getCurrentSchema().getQName(); + } + + @Override + public SchemaPath getPath() { + return getCurrentSchema().getPath(); + } + + @Override + public List getUnknownSchemaNodes() { + return getCurrentSchema().getUnknownSchemaNodes(); + } + + @Override + public String getDescription() { + return getCurrentSchema().getDescription(); + } + + @Override + public String getReference() { + return getCurrentSchema().getReference(); + } + + @Override + public Status getStatus() { + return getCurrentSchema().getStatus(); + } +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/sal/dom/broker/BackwardsCompatibleMountPointManagerTest.java b/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/sal/dom/broker/BackwardsCompatibleMountPointManagerTest.java new file mode 100644 index 0000000000..3b11ed0566 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/sal/dom/broker/BackwardsCompatibleMountPointManagerTest.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html. + */ + +package org.opendaylight.controller.sal.dom.broker; + +import static junit.framework.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint; +import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService; +import org.opendaylight.controller.md.sal.dom.api.DOMService; +import org.opendaylight.controller.md.sal.dom.broker.impl.mount.DOMMountPointServiceImpl; +import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance; +import org.opendaylight.controller.sal.core.api.mount.MountProvisionListener; +import org.opendaylight.yangtools.concepts.ObjectRegistration; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Optional; + +public class BackwardsCompatibleMountPointManagerTest { + private static final Logger log = LoggerFactory.getLogger(BackwardsCompatibleMountPointManagerTest.class); + + @Mock + private DOMMountPointServiceImpl domMountPointService; + @Mock + private DOMMountPointService.DOMMountPointBuilder mountBuilder; + + private BackwardsCompatibleMountPointManager compatibleMountPointManager; + static final QName qName = QName.create("namespace", "12-12-1212", "mount"); + static final InstanceIdentifier id = InstanceIdentifier.builder(qName).build(); + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + stubMountService(); + compatibleMountPointManager = new BackwardsCompatibleMountPointManager(domMountPointService); + } + + @Test + public void testCreateMountpointAlreadyCreated() throws Exception { + compatibleMountPointManager.createMountPoint(id); + verify(domMountPointService).createMountPoint(id); + verify(mountBuilder, times(3)).addService(any(Class.class), any(DOMService.class)); + verify(mountBuilder).addInitialSchemaContext(any(SchemaContext.class)); + + try { + compatibleMountPointManager.createMountPoint(id); + } catch (final IllegalStateException e) { + log.debug("", e); + return; + } + fail("Should fail to create duplicate mount"); + } + + @Test + public void testCreateMountpointGetOrCreate() throws Exception { + compatibleMountPointManager = new BackwardsCompatibleMountPointManager(new DOMMountPointServiceImpl()); + + final MountProvisionListener listener = new MountProvisionListener() { + public int createdMounts = 0; + + @Override + public void onMountPointCreated(final InstanceIdentifier path) { + if(createdMounts++ > 1 ) { + fail("Only one mount point should have been created"); + } + } + + @Override + public void onMountPointRemoved(final InstanceIdentifier path) {} + }; + + compatibleMountPointManager.registerProvisionListener(listener); + + final MountProvisionInstance m1 = compatibleMountPointManager.createOrGetMountPoint(id); + m1.setSchemaContext(mockSchemaContext()); + compatibleMountPointManager.createOrGetMountPoint(id); + compatibleMountPointManager.createOrGetMountPoint(id); + } + + private void stubMountService() { + doReturn(mockMountPointBuilder()).when(domMountPointService).createMountPoint(any(InstanceIdentifier.class)); + doReturn(Optional.of(mockMountPoint())).when(domMountPointService).getMountPoint(any(InstanceIdentifier.class)); + } + + private DOMMountPoint mockMountPoint() { + final DOMMountPoint mock = mock(DOMMountPoint.class); + doAnswer(new Answer() { + @Override + public Object answer(final InvocationOnMock invocation) throws Throwable { + return Optional.of(mock(((Class) invocation.getArguments()[0]))); + } + }).when(mock).getService(any(Class.class)); + doReturn(mockSchemaContext()).when(mock).getSchemaContext(); + return mock; + } + + static SchemaContext mockSchemaContext() { + final SchemaContext mock = mock(SchemaContext.class); + doReturn(qName).when(mock).getQName(); + doReturn("schema").when(mock).toString(); + doReturn(mock(DataSchemaNode.class)).when(mock).getDataChildByName(any(QName.class)); + return mock; + } + + private DOMMountPointService.DOMMountPointBuilder mockMountPointBuilder() { + doReturn(mountBuilder).when(mountBuilder).addService(any(Class.class), any(DOMService.class)); + doReturn(mockObjectRegistration()).when(mountBuilder).register(); + doReturn(mountBuilder).when(mountBuilder).addInitialSchemaContext(any(SchemaContext.class)); + return mountBuilder; + } + + private ObjectRegistration mockObjectRegistration() { + return mock(ObjectRegistration.class); + } + +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/sal/dom/broker/BackwardsCompatibleMountPointTest.java b/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/sal/dom/broker/BackwardsCompatibleMountPointTest.java new file mode 100644 index 0000000000..5a36f710ff --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/sal/dom/broker/BackwardsCompatibleMountPointTest.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html. + */ + +package org.opendaylight.controller.sal.dom.broker; + +import static junit.framework.Assert.fail; +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import com.google.common.base.Optional; +import com.google.common.util.concurrent.ListenableFuture; +import java.util.AbstractMap; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.opendaylight.controller.md.sal.common.api.TransactionStatus; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException; +import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer; +import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction; +import org.opendaylight.controller.sal.core.api.data.DataProviderService; +import org.opendaylight.controller.sal.dom.broker.impl.SchemaContextProvider; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class BackwardsCompatibleMountPointTest { + private static final Logger log = LoggerFactory.getLogger(BackwardsCompatibleMountPointManagerTest.class); + + private static final InstanceIdentifier id = BackwardsCompatibleMountPointManagerTest.id; + private final NormalizedNode normalizedNode = mockNormalizedNode(); + private final CompositeNode compositeNode = mockCompositeNode(); + + @Mock + private DataProviderService oldBroker; + @Mock + private SchemaContextProvider schemaContextProvider; + @Mock + private DataModificationTransaction mockTx; + + private BackwardsCompatibleMountPoint.BackwardsCompatibleDomStore backwardsCompatibleDomStore; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + stubSchemaProvider(); + stubOldBroker(); + backwardsCompatibleDomStore = new BackwardsCompatibleMountPoint.BackwardsCompatibleDomStore(oldBroker, schemaContextProvider); + } + + private void stubOldBroker() { + doReturn(compositeNode).when(oldBroker).readConfigurationData(id); + doReturn(compositeNode).when(oldBroker).readOperationalData(id); + doReturn(mockTx).when(oldBroker).beginTransaction(); + doNothing().when(mockTx).putConfigurationData(id, compositeNode); + doNothing().when(mockTx).putOperationalData(id, compositeNode); + doReturn(com.google.common.util.concurrent.Futures.immediateFuture(RpcResultBuilder.success(TransactionStatus.COMMITED))).when(mockTx).commit(); + } + + private CompositeNode mockCompositeNode() { + final CompositeNode mock = mock(CompositeNode.class); + doReturn("node").when(mock).toString(); + return mock; + } + + private void stubSchemaProvider() { + doReturn(BackwardsCompatibleMountPointManagerTest.mockSchemaContext()).when(schemaContextProvider).getSchemaContext(); + } + + @Test + public void testBackwardsCompatibleBroker() throws Exception { + backwardsCompatibleDomStore.newReadOnlyTransaction(); + backwardsCompatibleDomStore.newWriteOnlyTransaction(); + backwardsCompatibleDomStore.newReadWriteTransaction(); + } + + @Test + public void testReadTransaction() throws Exception { + final BackwardsCompatibleMountPoint.BackwardsCompatibleDomStore.BackwardsCompatibleReadTransaction tx = + new BackwardsCompatibleMountPoint.BackwardsCompatibleDomStore.BackwardsCompatibleReadTransaction(oldBroker, mockNormalizer()); + + ListenableFuture>> read = tx.read(LogicalDatastoreType.CONFIGURATION, id); + assertEquals(normalizedNode, read.get().get()); + verify(oldBroker).readConfigurationData(id); + + read = tx.read(LogicalDatastoreType.OPERATIONAL, id); + assertEquals(normalizedNode, read.get().get()); + + verify(oldBroker).readOperationalData(id); + } + + @Test + public void testReadWriteTransactionOperational() throws Exception { + final BackwardsCompatibleMountPoint.BackwardsCompatibleDomStore.BackwardsCompatibleWriteTransaction tx = + new BackwardsCompatibleMountPoint.BackwardsCompatibleDomStore.BackwardsCompatibleWriteTransaction(oldBroker, mockNormalizer()); + + verify(oldBroker).beginTransaction(); + + tx.put(LogicalDatastoreType.CONFIGURATION, id, normalizedNode); + verify(mockTx).putConfigurationData(id, compositeNode); + + tx.put(LogicalDatastoreType.CONFIGURATION, id, normalizedNode); + verify(mockTx, times(2)).putConfigurationData(id, compositeNode); + + tx.commit(); + verify(mockTx).commit(); + } + + + @Test + public void testCannotPutOperational() throws Exception { + final BackwardsCompatibleMountPoint.BackwardsCompatibleDomStore.BackwardsCompatibleWriteTransaction tx = + new BackwardsCompatibleMountPoint.BackwardsCompatibleDomStore.BackwardsCompatibleWriteTransaction(oldBroker, mockNormalizer()); + + try { + tx.put(LogicalDatastoreType.OPERATIONAL, id, normalizedNode); + } catch (IllegalArgumentException e) { + // Cannot put operational data + log.debug("", e); + return; + } + + fail("Should fail when putting operational data"); + } + + private DataNormalizer mockNormalizer() throws DataNormalizationException { + final DataNormalizer mock = mock(DataNormalizer.class); + doReturn(new AbstractMap.SimpleEntry>(id, normalizedNode) {}) + .when(mock).toNormalized(any(InstanceIdentifier.class), any(CompositeNode.class)); + doReturn(compositeNode).when(mock).toLegacy(any(InstanceIdentifier.class), any(NormalizedNode.class)); + doReturn(id).when(mock).toLegacy(any(InstanceIdentifier.class)); + return mock; + } + + private NormalizedNode mockNormalizedNode() { + final NormalizedNode mock = mock(NormalizedNode.class); + doReturn("mockNormalizedNode").when(mock).toString(); + return mock; + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryOperationalDataStoreProviderModule.java b/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryOperationalDataStoreProviderModule.java index 172b0dbc01..b39c9bbbd8 100644 --- a/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryOperationalDataStoreProviderModule.java +++ b/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryOperationalDataStoreProviderModule.java @@ -23,7 +23,7 @@ public class InMemoryOperationalDataStoreProviderModule extends org.opendaylight @Override public java.lang.AutoCloseable createInstance() { InMemoryDOMDataStore ids = new InMemoryDOMDataStore("DOM-OPER", MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor())); - getSchemaServiceDependency().registerSchemaServiceListener(ids); + getOperationalSchemaServiceDependency().registerSchemaServiceListener(ids); return ids; } diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/main/yang/opendaylight-inmemory-datastore-provider.yang b/opendaylight/md-sal/sal-inmemory-datastore/src/main/yang/opendaylight-inmemory-datastore-provider.yang index 03220a3e5d..d4f57b53fe 100644 --- a/opendaylight/md-sal/sal-inmemory-datastore/src/main/yang/opendaylight-inmemory-datastore-provider.yang +++ b/opendaylight/md-sal/sal-inmemory-datastore/src/main/yang/opendaylight-inmemory-datastore-provider.yang @@ -58,7 +58,10 @@ module opendaylight-inmemory-datastore-provider { case inmemory-operational-datastore-provider { when "/config:modules/config:module/config:type = 'inmemory-operational-datastore-provider'"; - container schema-service { + // Yang does not allow two cases from same namespaces with same children + // Schema-service dependency renamed to operational-schema-service + // to prevent conflict with schema-service container from inmemory-config-datastore-provider + container operational-schema-service { uses config:service-ref { refine type { mandatory false; diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java index 8780925eb1..4e3a66b7ec 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java @@ -224,11 +224,17 @@ public final class XmlElement { }); } + /** + * + * @param tagName tag name without prefix + * @return + */ public List getChildElements(final String tagName) { return getChildElementsInternal(new ElementFilteringStrategy() { @Override public boolean accept(Element e) { - return e.getTagName().equals(tagName); + // localName returns pure localName without prefix + return e.getLocalName().equals(tagName); } }); }