From c19766901dce1994ef2432f356b32d539b6c43cc Mon Sep 17 00:00:00 2001 From: Tony Tkacik Date: Sun, 3 Nov 2013 20:37:46 +0100 Subject: [PATCH] Unification of broker concepts implementations - Introduced AbstractDataReadRouter into sal-common-impl which deals with data read routing. - AbstractDataReadRouter is then used inside sal-binding-broker to route reads between binding aware components and inside sal-dom-broker to route reads inside a mount point or between binding independent components. Extracted Rpc Routing logic from BrokerImpl.xtend and moved it to separate class, which is used in the broker (global context) and also in the mount-points (nested subsystems). Change-Id: I7eaaddafe9f4dcb2ca6d25090246dfd51940b2d7 Signed-off-by: Tony Tkacik --- opendaylight/md-sal/sal-binding-api/pom.xml | 1 + .../md-sal/sal-binding-broker/pom.xml | 6 +- .../sal/binding/impl/DataBrokerImpl.xtend | 95 ++------- .../binding/impl/DataProviderContext.xtend | 19 -- .../util/BindingAwareDataReaderRouter.xtend | 13 ++ .../md/sal/common/api/data/DataChange.java | 95 ++++++++- .../common/api/data/DataCommitHandler.java | 2 +- .../md/sal/common/api/data/DataStore.java | 16 ++ .../md/sal/common/api/routing/Route.java | 10 + .../api/routing/RouteChangeListener.java | 8 + .../api/routing/RouteChangePublisher.java | 8 + .../md/sal/common/api/routing/Router.java | 10 + opendaylight/md-sal/sal-common-impl/pom.xml | 5 +- .../impl/routing/AbstractDataReadRouter.java | 187 ++++++++++++++++++ .../sal/core/api/RpcConsumptionRegistry.java | 22 +++ .../sal/core/api/RpcProvisionRegistry.java | 33 ++++ .../core/api/data/DataProviderService.java | 7 + .../api/mount/MountProvisionInstance.java | 8 + .../core/api/mount/MountProvisionService.java | 13 ++ opendaylight/md-sal/sal-dom-broker/pom.xml | 7 +- .../sal/dom/broker/BrokerImpl.xtend | 94 +++------ .../sal/dom/broker/MountPointImpl.java | 118 +++++++++++ .../dom/broker/MountPointManagerImpl.xtend | 35 ++++ .../sal/dom/broker/ProviderContextImpl.xtend | 79 +++----- .../dom/broker/impl/DataReaderRouter.xtend | 13 ++ .../broker/impl/NotificationRouterImpl.java | 89 +++++++++ .../sal/dom/broker/impl/RpcRouterImpl.xtend | 106 ++++++++++ .../dom/broker/spi/NotificationRouter.java | 21 ++ .../dom/broker/spi/RoutedRpcProcessor.java | 27 +++ .../sal/dom/broker/spi/RpcRouter.java | 31 +++ .../md-sal/sal-netconf-connector/pom.xml | 147 ++++++++++++++ 31 files changed, 1096 insertions(+), 229 deletions(-) delete mode 100644 opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataProviderContext.xtend create mode 100644 opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/BindingAwareDataReaderRouter.xtend create mode 100644 opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataStore.java create mode 100644 opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/Route.java create mode 100644 opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RouteChangeListener.java create mode 100644 opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RouteChangePublisher.java create mode 100644 opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/Router.java create mode 100644 opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/AbstractDataReadRouter.java create mode 100644 opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcConsumptionRegistry.java create mode 100644 opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcProvisionRegistry.java create mode 100644 opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/mount/MountProvisionInstance.java create mode 100644 opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/mount/MountProvisionService.java create mode 100644 opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointImpl.java create mode 100644 opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointManagerImpl.xtend create mode 100644 opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataReaderRouter.xtend create mode 100644 opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/NotificationRouterImpl.java create mode 100644 opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RpcRouterImpl.xtend create mode 100644 opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/NotificationRouter.java create mode 100644 opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/RoutedRpcProcessor.java create mode 100644 opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/RpcRouter.java diff --git a/opendaylight/md-sal/sal-binding-api/pom.xml b/opendaylight/md-sal/sal-binding-api/pom.xml index c1dccdf532..cfbd4f7b71 100644 --- a/opendaylight/md-sal/sal-binding-api/pom.xml +++ b/opendaylight/md-sal/sal-binding-api/pom.xml @@ -38,6 +38,7 @@ org.osgi org.osgi.core ${osgi.core.version} + provided diff --git a/opendaylight/md-sal/sal-binding-broker/pom.xml b/opendaylight/md-sal/sal-binding-broker/pom.xml index b8b37af58e..9ca025b393 100644 --- a/opendaylight/md-sal/sal-binding-broker/pom.xml +++ b/opendaylight/md-sal/sal-binding-broker/pom.xml @@ -77,12 +77,14 @@ ${project.groupId}.${project.artifactId} + + org.opendaylight.controller.sal.binding.spi.*, + org.opendaylight.controller.config.yang.md.sal.binding.impl, - org.opendaylight.controller.sal.binding.spi, - org.opendaylight.controller.sal.binding.spi.*, org.opendaylight.controller.sal.binding.impl, org.opendaylight.controller.sal.binding.impl.*, + org.opendaylight.controller.sal.binding.codegen, org.opendaylight.controller.sal.binding.codegen.*, diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.xtend index 9356ecda88..6ed63b21dd 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.xtend +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.xtend @@ -5,23 +5,13 @@ import org.opendaylight.controller.sal.binding.api.data.DataChangeListener import org.opendaylight.controller.sal.binding.api.data.DataProviderService import org.opendaylight.yangtools.yang.binding.DataObject import org.opendaylight.yangtools.yang.binding.InstanceIdentifier -import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction -import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction.DataTransactionListener import org.opendaylight.controller.md.sal.common.api.TransactionStatus -import org.opendaylight.controller.md.sal.common.impl.AbstractDataModification import org.opendaylight.controller.md.sal.common.api.data.DataReader import org.opendaylight.yangtools.concepts.AbstractObjectRegistration import org.opendaylight.yangtools.concepts.ListenerRegistration -import static extension org.opendaylight.controller.sal.binding.impl.util.MapUtils.*; -import java.util.Collection -import java.util.Map.Entry -import java.util.HashSet -import java.util.Set import com.google.common.collect.Multimap import static com.google.common.base.Preconditions.*; import java.util.List -import java.util.LinkedList -import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider import com.google.common.collect.HashMultimap import java.util.concurrent.ExecutorService import java.util.concurrent.Callable @@ -30,15 +20,17 @@ import org.opendaylight.controller.sal.common.util.Rpcs import java.util.Collections import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction import java.util.ArrayList -import org.opendaylight.controller.sal.common.util.RpcErrors +import org.opendaylight.controller.sal.binding.impl.util.BindingAwareDataReaderRouter +import org.opendaylight.yangtools.concepts.CompositeObjectRegistration +import java.util.Arrays class DataBrokerImpl extends DeprecatedDataAPISupport implements DataProviderService { @Property var ExecutorService executor; - Multimap configReaders = HashMultimap.create(); - Multimap operationalReaders = HashMultimap.create(); + val dataReadRouter = new BindingAwareDataReaderRouter; + Multimap listeners = HashMultimap.create(); Multimap commitHandlers = HashMultimap.create(); @@ -47,13 +39,11 @@ class DataBrokerImpl extends DeprecatedDataAPISupport implements DataProviderSer } override readConfigurationData(InstanceIdentifier path) { - val readers = configReaders.getAllChildren(path); - return readers.readConfiguration(path); + return dataReadRouter.readConfigurationData(path); } override readOperationalData(InstanceIdentifier path) { - val readers = operationalReaders.getAllChildren(path); - return readers.readOperational(path); + return dataReadRouter.readOperationalData(path); } override registerCommitHandler(InstanceIdentifier path, @@ -69,20 +59,12 @@ class DataBrokerImpl extends DeprecatedDataAPISupport implements DataProviderSer return reg; } - override registerDataReader(InstanceIdentifier path, - DataReader, DataObject> provider) { - val ret = new DataReaderRegistration(provider, this); - ret.paths.add(path); - configReaders.put(path, ret); - operationalReaders.put(path, ret); - return ret; - } - - protected def removeReader(DataReaderRegistration reader) { - for (path : reader.paths) { - operationalReaders.remove(path, reader); - configReaders.remove(path, reader); - } + override registerDataReader(InstanceIdentifier path,DataReader,DataObject> reader) { + + val confReg = dataReadRouter.registerConfigurationReader(path,reader); + val dataReg = dataReadRouter.registerOperationalReader(path,reader); + + return new CompositeObjectRegistration(reader,Arrays.asList(confReg,dataReg)); } protected def removeListener(DataChangeListenerRegistration registration) { @@ -92,39 +74,8 @@ class DataBrokerImpl extends DeprecatedDataAPISupport implements DataProviderSer protected def removeCommitHandler(DataCommitHandlerRegistration registration) { commitHandlers.remove(registration.path, registration); } - - protected def DataObject readConfiguration( - Collection> entries, - InstanceIdentifier path) { - - val List partialResults = new LinkedList(); - for (entry : entries) { - partialResults.add(entry.value.instance.readConfigurationData(path)) - } - return merge(path, partialResults); - } - - protected def DataObject readOperational( - Collection> entries, - InstanceIdentifier path) { - - val List partialResults = new LinkedList(); - for (entry : entries) { - partialResults.add(entry.value.instance.readOperationalData(path)) - } - return merge(path, partialResults); - } - - protected def DataObject merge(InstanceIdentifier identifier, List objects) { - - // FIXME: implement real merge - if (objects.size > 0) { - return objects.get(0); - } - } protected def getActiveCommitHandlers() { - return commitHandlers.entries.map[ value.instance].toSet } @@ -137,26 +88,6 @@ class DataBrokerImpl extends DeprecatedDataAPISupport implements DataProviderSer } -package class DataReaderRegistration extends // -AbstractObjectRegistration, DataObject>> { - - DataBrokerImpl dataBroker; - - @Property - val Set> paths; - - new(DataReader, DataObject> instance, DataBrokerImpl broker) { - super(instance) - dataBroker = broker; - _paths = new HashSet(); - } - - override protected removeRegistration() { - dataBroker.removeReader(this); - } - -} - package class DataChangeListenerRegistration extends AbstractObjectRegistration implements ListenerRegistration { DataBrokerImpl dataBroker; diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataProviderContext.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataProviderContext.xtend deleted file mode 100644 index 398a2196c6..0000000000 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataProviderContext.xtend +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.controller.sal.binding.impl - -import org.opendaylight.controller.sal.common.DataStoreIdentifier -import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider - -class DataProviderContext { - - @Property - var DataStoreIdentifier identifier; - @Property - var RuntimeDataProvider provider; -} diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/BindingAwareDataReaderRouter.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/BindingAwareDataReaderRouter.xtend new file mode 100644 index 0000000000..f586a8b4c5 --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/BindingAwareDataReaderRouter.xtend @@ -0,0 +1,13 @@ +package org.opendaylight.controller.sal.binding.impl.util + +import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRouter +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier +import org.opendaylight.yangtools.yang.binding.DataObject + +class BindingAwareDataReaderRouter extends AbstractDataReadRouter, DataObject> { + + override protected merge(InstanceIdentifier path, Iterable data) { + return data.iterator.next; + } + +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChange.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChange.java index 0fea50b777..55565252a2 100644 --- a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChange.java +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChange.java @@ -13,19 +13,102 @@ import java.util.Set; // FIXME: After 0.6 Release of YANGTools refactor to use Path marker interface for arguments. // import org.opendaylight.yangtools.concepts.Path; +public interface DataChange

*/, D> { -public interface DataChange

*/,D> { + /** + * Returns a map of paths and newly created objects + * + * @return map of paths and newly created objects + */ + Map getCreatedOperationalData(); - Map getCreatedOperationalData(); + /** + * Returns a map of paths and newly created objects + * + * @return map of paths and newly created objects + */ + Map getCreatedConfigurationData(); - Map getUpdatedOperationalData(); + /** + * Returns a map of paths and respective updated objects after update. + * + * Original state of the object is in + * {@link #getOriginalOperationalData()} + * + * @return map of paths and newly created objects + */ + Map getUpdatedOperationalData(); + /** + * Returns a map of paths and respective updated objects after update. + * + * Original state of the object is in + * {@link #getOriginalConfigurationData()} + * + * @return map of paths and newly created objects + */ + Map getUpdatedConfigurationData(); + + /** + * Returns a set of paths of removed objects. + * + * Original state of the object is in + * {@link #getOriginalConfigurationData()} + * + * @return map of paths and newly created objects + */ + Set

getRemovedConfigurationData(); + + /** + * Returns a set of paths of removed objects. + * + * Original state of the object is in + * {@link #getOriginalOperationalData()} + * + * @return map of paths and newly created objects + */ Set

getRemovedOperationalData(); - Map getCreatedConfigurationData(); + /** + * Return a map of paths and original state of updated and removed objectd. + * + * @return map of paths and original state of updated and removed objectd. + */ + Map getOriginalConfigurationData(); - Map getUpdatedConfigurationData(); + /** + * Return a map of paths and original state of updated and removed objectd. + * + * @return map of paths and original state of updated and removed objectd. + */ + Map getOriginalOperationalData(); - Set

getRemovedConfigurationData(); + /** + * Returns a original subtree of data, which starts at the path + * where listener was registered. + * + */ + D getOriginalConfigurationSubtree(); + + /** + * Returns a original subtree of data, which starts at the path + * where listener was registered. + * + */ + D getOriginalOperationalSubtree(); + + /** + * Returns a new subtree of data, which starts at the path + * where listener was registered. + * + */ + D getUpdatedConfigurationSubtree(); + + /** + * Returns a new subtree of data, which starts at the path + * where listener was registered. + * + */ + D getUpdatedOperationalSubtree(); } diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataCommitHandler.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataCommitHandler.java index 85e3d8f57c..90de13d15e 100644 --- a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataCommitHandler.java +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataCommitHandler.java @@ -84,7 +84,7 @@ import org.opendaylight.yangtools.yang.common.RpcResult; */ public interface DataCommitHandler

*/,D> { - + DataCommitTransaction requestCommit(DataModification modification); public interface DataCommitTransaction

*/,D> { diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataStore.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataStore.java new file mode 100644 index 0000000000..f448d4e2ee --- /dev/null +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataStore.java @@ -0,0 +1,16 @@ +package org.opendaylight.controller.md.sal.common.api.data; + +public interface DataStore extends // + DataReader, // + DataModificationTransactionFactory { + + @Override + public DataModification beginTransaction(); + + @Override + public D readConfigurationData(P path); + + @Override + public D readOperationalData(P path); + +} diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/Route.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/Route.java new file mode 100644 index 0000000000..afe9e9921e --- /dev/null +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/Route.java @@ -0,0 +1,10 @@ +package org.opendaylight.controller.md.sal.common.api.routing; + +import org.opendaylight.yangtools.concepts.Immutable; + +public interface Route extends Immutable { + + C getType(); + + P getPath(); +} diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RouteChangeListener.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RouteChangeListener.java new file mode 100644 index 0000000000..994f65b960 --- /dev/null +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RouteChangeListener.java @@ -0,0 +1,8 @@ +package org.opendaylight.controller.md.sal.common.api.routing; + +import java.util.EventListener; + +public interface RouteChangeListener extends EventListener { + + void onRouteChange(RouteChange change); +} diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RouteChangePublisher.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RouteChangePublisher.java new file mode 100644 index 0000000000..89851c9393 --- /dev/null +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RouteChangePublisher.java @@ -0,0 +1,8 @@ +package org.opendaylight.controller.md.sal.common.api.routing; + +import org.opendaylight.yangtools.concepts.ListenerRegistration; + +public interface RouteChangePublisher { + + ListenerRegistration> registerRouteChangeListener(RouteChangeListener listener); +} diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/Router.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/Router.java new file mode 100644 index 0000000000..8d0a90c50b --- /dev/null +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/Router.java @@ -0,0 +1,10 @@ +package org.opendaylight.controller.md.sal.common.api.routing; + +import java.util.Map; +import java.util.Set; + +public interface Router extends // + RouteChangePublisher { + + Map> getAnnouncedPaths(); +} diff --git a/opendaylight/md-sal/sal-common-impl/pom.xml b/opendaylight/md-sal/sal-common-impl/pom.xml index 0c2344a23e..3bd51ec7d8 100644 --- a/opendaylight/md-sal/sal-common-impl/pom.xml +++ b/opendaylight/md-sal/sal-common-impl/pom.xml @@ -37,7 +37,10 @@ maven-bundle-plugin - org.opendaylight.controller.md.sal.common.impl + + org.opendaylight.controller.md.sal.common.impl, + org.opendaylight.controller.md.sal.common.impl.* + diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/AbstractDataReadRouter.java b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/AbstractDataReadRouter.java new file mode 100644 index 0000000000..f83c61f804 --- /dev/null +++ b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/AbstractDataReadRouter.java @@ -0,0 +1,187 @@ +package org.opendaylight.controller.md.sal.common.impl.routing; + +import java.util.Map.Entry; + +import org.opendaylight.controller.md.sal.common.api.data.DataReader; +import org.opendaylight.yangtools.concepts.AbstractObjectRegistration; +import org.opendaylight.yangtools.concepts.Path; +import org.opendaylight.yangtools.concepts.Registration; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; + +/** + * Base abstract implementation of DataReadRouter, which performs + * a read operation on multiple data readers and then merges result. + * + * @param

+ * @param + */ +public abstract class AbstractDataReadRouter

, D> implements DataReader { + + Multimap> configReaders = HashMultimap.create(); + Multimap> operationalReaders = HashMultimap.create(); + + @Override + public D readConfigurationData(P path) { + FluentIterable dataBits = FluentIterable // + .from(getReaders(configReaders, path)).transform(configurationRead(path)); + return merge(path,dataBits); + } + + @Override + public D readOperationalData(P path) { + FluentIterable dataBits = FluentIterable // + .from(getReaders(configReaders, path)).transform(operationalRead(path)); + return merge(path,dataBits); + + } + + /** + * Merges data readed by reader instances from specified path + * + * @param path Path on which read was performed + * @param data Data which was returned by read operation. + * @return Merged result. + */ + protected abstract D merge(P path,Iterable data); + + /** + * Returns a function which performs configuration read for supplied path + * + * @param path + * @return function which performs configuration read for supplied path + */ + + private Function, D> configurationRead(final P path) { + return new Function, D>() { + @Override + public D apply(DataReader input) { + return input.readConfigurationData(path); + } + }; + } + + /** + * Returns a function which performs operational read for supplied path + * + * @param path + * @return function which performs operational read for supplied path + */ + private Function, D> operationalRead(final P path) { + return new Function, D>() { + @Override + public D apply(DataReader input) { + return input.readConfigurationData(path); + } + }; + } + + // Registrations + + /** + * Register's a reader for operational data. + * + * @param path Path which is served by this reader + * @param reader Reader instance which is responsible for reading particular subpath. + * @return + */ + public Registration> registerOperationalReader(P path, DataReader reader) { + OperationalDataReaderRegistration ret = new OperationalDataReaderRegistration<>(path, reader); + operationalReaders.put(path, ret); + return ret; + } + + public Registration> registerConfigurationReader(P path, DataReader reader) { + ConfigurationDataReaderRegistration ret = new ConfigurationDataReaderRegistration<>(path, reader); + configReaders.put(path, ret); + return ret; + } + + Iterable> getOperationalReaders(P path) { + return getReaders(operationalReaders, path); + } + + Iterable> getConfigurationReaders(P path) { + return getReaders(configReaders, path); + } + + private Iterable> getReaders(Multimap> readerMap, P path) { + return FluentIterable + .from(readerMap.entries()) // + .filter(affects(path)) // + .transform(retrieveInstance()); + } + + private void removeRegistration(OperationalDataReaderRegistration registration) { + operationalReaders.remove(registration.getKey(), registration); + } + + private void removeRegistration(ConfigurationDataReaderRegistration registration) { + configReaders.remove(registration.getKey(), registration); + } + + private Function>, DataReader> retrieveInstance() { + return new Function>, DataReader>() { + @Override + public DataReader apply(Entry> input) { + return input.getValue().getInstance(); + } + }; + } + + private Predicate>> affects(final P path) { + + return new Predicate>>() { + + @Override + public boolean apply(Entry> input) { + final Path key = input.getKey(); + return key.contains(path) || ((Path) path).contains(key); + } + + }; + } + + private class ConfigurationDataReaderRegistration

, D> extends DataReaderRegistration { + + public ConfigurationDataReaderRegistration(P key, DataReader instance) { + super(key, instance); + } + + @Override + protected void removeRegistration() { + AbstractDataReadRouter.this.removeRegistration(this); + } + } + + private class OperationalDataReaderRegistration

, D> extends DataReaderRegistration { + + public OperationalDataReaderRegistration(P key, DataReader instance) { + super(key, instance); + } + + @Override + protected void removeRegistration() { + AbstractDataReadRouter.this.removeRegistration(this); + } + } + + private abstract static class DataReaderRegistration

, D> extends + AbstractObjectRegistration> { + + private final P key; + + public P getKey() { + return this.key; + } + + public DataReaderRegistration(P key, DataReader instance) { + super(instance); + this.key = key; + } + } +} diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcConsumptionRegistry.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcConsumptionRegistry.java new file mode 100644 index 0000000000..c19ee1a7cb --- /dev/null +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcConsumptionRegistry.java @@ -0,0 +1,22 @@ +package org.opendaylight.controller.sal.core.api; + +import java.util.concurrent.Future; + +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; + +public interface RpcConsumptionRegistry { + /** + * Sends an RPC to other components registered to the broker. + * + * @see RpcImplementation + * @param rpc + * Name of RPC + * @param input + * Input data to the RPC + * @return Result of the RPC call + */ + Future> rpc(QName rpc, CompositeNode input); + +} diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcProvisionRegistry.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcProvisionRegistry.java new file mode 100644 index 0000000000..c326bab7a4 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcProvisionRegistry.java @@ -0,0 +1,33 @@ +package org.opendaylight.controller.sal.core.api; + +import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration; +import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration; +import org.opendaylight.yangtools.yang.common.QName; + +public interface RpcProvisionRegistry { + + /** + * Registers an implementation of the rpc. + * + *

+ * The registered rpc functionality will be available to all other + * consumers and providers registered to the broker, which are aware of + * the {@link QName} assigned to the rpc. + * + *

+ * There is no assumption that rpc type is in the set returned by + * invoking {@link RpcImplementation#getSupportedRpcs()}. This allows + * for dynamic rpc implementations. + * + * @param rpcType + * Name of Rpc + * @param implementation + * Provider's Implementation of the RPC functionality + * @throws IllegalArgumentException + * If the name of RPC is invalid + */ + RpcRegistration addRpcImplementation(QName rpcType, RpcImplementation implementation) + throws IllegalArgumentException; + + RoutedRpcRegistration addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation); +} diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataProviderService.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataProviderService.java index 3024c89d61..20fa29dceb 100644 --- a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataProviderService.java +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataProviderService.java @@ -10,8 +10,10 @@ package org.opendaylight.controller.sal.core.api.data; import org.opendaylight.controller.md.sal.common.api.data.DataProvisionService; import org.opendaylight.controller.sal.common.DataStoreIdentifier; import org.opendaylight.controller.sal.core.api.Provider; +import org.opendaylight.yangtools.concepts.Registration; import org.opendaylight.yangtools.yang.data.api.CompositeNode; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.controller.md.sal.common.api.data.DataReader;; public interface DataProviderService extends DataBrokerService, // @@ -54,6 +56,11 @@ public interface DataProviderService extends */ void removeRefresher(DataStoreIdentifier store, DataRefresher refresher); + + Registration> registerConfigurationReader(InstanceIdentifier path, DataReader reader); + + Registration> registerOperationalReader(InstanceIdentifier path, DataReader reader); + public interface DataRefresher extends Provider.ProviderFunctionality { /** diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/mount/MountProvisionInstance.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/mount/MountProvisionInstance.java new file mode 100644 index 0000000000..8f6a5d0a90 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/mount/MountProvisionInstance.java @@ -0,0 +1,8 @@ +package org.opendaylight.controller.sal.core.api.mount; + +import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry; +import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService; + +public interface MountProvisionInstance extends MountInstance, NotificationPublishService, RpcProvisionRegistry { + +} diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/mount/MountProvisionService.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/mount/MountProvisionService.java new file mode 100644 index 0000000000..fade7d341b --- /dev/null +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/mount/MountProvisionService.java @@ -0,0 +1,13 @@ +package org.opendaylight.controller.sal.core.api.mount; + +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; + +public interface MountProvisionService extends MountService { + + @Override + public MountProvisionInstance getMountPoint(InstanceIdentifier path); + + MountProvisionInstance createMountPoint(InstanceIdentifier path); + + MountProvisionInstance createOrGetMountPoint(InstanceIdentifier path); +} diff --git a/opendaylight/md-sal/sal-dom-broker/pom.xml b/opendaylight/md-sal/sal-dom-broker/pom.xml index 678728ab3b..9383a9e2ff 100644 --- a/opendaylight/md-sal/sal-dom-broker/pom.xml +++ b/opendaylight/md-sal/sal-dom-broker/pom.xml @@ -24,6 +24,11 @@ org.opendaylight.controller sal-common-util 1.0-SNAPSHOT + + + org.opendaylight.controller + sal-common-impl + 1.0-SNAPSHOT org.opendaylight.controller @@ -60,7 +65,7 @@ ${project.groupId}.${project.artifactId} org.opendaylight.controller.sal.dom.broker.BrokerActivator - org.opendaylight.controller.sal.dom.broker, + org.opendaylight.controller.sal.dom.broker.* diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.xtend index 83dda5902d..855ad9bd32 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.xtend +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.xtend @@ -7,29 +7,28 @@ */ package org.opendaylight.controller.sal.dom.broker; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import org.opendaylight.controller.sal.core.api.Broker; -import org.opendaylight.controller.sal.core.api.BrokerService; -import org.opendaylight.controller.sal.core.api.Consumer; -import org.opendaylight.controller.sal.core.api.Provider; -import org.opendaylight.controller.sal.core.api.RpcImplementation; -import org.opendaylight.controller.sal.core.spi.BrokerModule; -import org.opendaylight.yangtools.yang.common.QName; -import org.opendaylight.yangtools.yang.common.RpcResult; -import org.opendaylight.yangtools.yang.data.api.CompositeNode; -import org.osgi.framework.BundleContext; -import org.slf4j.LoggerFactory; +import java.util.Collections +import java.util.HashMap +import java.util.HashSet +import java.util.Map +import java.util.Set +import java.util.concurrent.Callable +import java.util.concurrent.ExecutorService +import java.util.concurrent.Executors +import java.util.concurrent.Future +import org.opendaylight.controller.sal.core.api.Broker +import org.opendaylight.controller.sal.core.api.BrokerService +import org.opendaylight.controller.sal.core.api.Consumer +import org.opendaylight.controller.sal.core.api.Provider +import org.opendaylight.controller.sal.core.spi.BrokerModule +import org.opendaylight.yangtools.yang.common.QName +import org.opendaylight.yangtools.yang.common.RpcResult +import org.opendaylight.yangtools.yang.data.api.CompositeNode +import org.osgi.framework.BundleContext +import org.slf4j.LoggerFactory +import org.opendaylight.controller.sal.dom.broker.spi.RpcRouter import org.opendaylight.yangtools.concepts.ListenerRegistration import org.opendaylight.controller.sal.core.api.RpcRegistrationListener -import org.opendaylight.controller.md.sal.common.impl.ListenerRegistry public class BrokerImpl implements Broker { private static val log = LoggerFactory.getLogger(BrokerImpl); @@ -42,17 +41,14 @@ public class BrokerImpl implements Broker { private val Map, BrokerModule> serviceProviders = Collections. synchronizedMap(new HashMap, BrokerModule>()); - - private val rpcRegistrationListeners = new ListenerRegistry(); - // RPC Context - private val Map rpcImpls = Collections.synchronizedMap( - new HashMap()); - // Implementation specific @Property private var ExecutorService executor = Executors.newFixedThreadPool(5); @Property private var BundleContext bundleContext; + + @Property + private var RpcRouter router; override registerConsumer(Consumer consumer, BundleContext ctx) { checkPredicates(consumer); @@ -95,42 +91,8 @@ public class BrokerImpl implements Broker { return prov.getServiceForSession(service, session); } - // RPC Functionality - protected def void addRpcImplementation(QName rpcType, RpcImplementation implementation) { - if(rpcImpls.get(rpcType) != null) { - throw new IllegalStateException("Implementation for rpc " + rpcType + " is already registered."); - } - - - rpcImpls.put(rpcType, implementation); - - - for(listener : rpcRegistrationListeners.listeners) { - try { - listener.instance.onRpcImplementationAdded(rpcType); - } catch (Exception e){ - log.error("Unhandled exception during invoking listener",e); - } - } - } - - protected def void removeRpcImplementation(QName rpcType, RpcImplementation implToRemove) { - if(implToRemove == rpcImpls.get(rpcType)) { - rpcImpls.remove(rpcType); - } - - for(listener : rpcRegistrationListeners.listeners) { - try { - listener.instance.onRpcImplementationRemoved(rpcType); - } catch (Exception e){ - log.error("Unhandled exception during invoking listener",e); - } - } - } - protected def Future> invokeRpc(QName rpc, CompositeNode input) { - val impl = rpcImpls.get(rpc); - val result = executor.submit([|impl.invokeRpc(rpc, input)] as Callable>); + val result = executor.submit([|router.invokeRpc(rpc, input)] as Callable>); return result; } @@ -171,12 +133,4 @@ public class BrokerImpl implements Broker { sessions.remove(consumerContextImpl); providerSessions.remove(consumerContextImpl); } - - protected def getSupportedRpcs() { - rpcImpls.keySet; - } - - def ListenerRegistration addRpcRegistrationListener(RpcRegistrationListener listener) { - rpcRegistrationListeners.register(listener); - } } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointImpl.java new file mode 100644 index 0000000000..7037b46ce9 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointImpl.java @@ -0,0 +1,118 @@ +package org.opendaylight.controller.sal.dom.broker; + +import java.util.Set; +import java.util.concurrent.Future; + +import org.opendaylight.controller.md.sal.common.api.data.DataReader; +import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration; +import org.opendaylight.controller.sal.core.api.RpcImplementation; +import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration; +import org.opendaylight.controller.sal.core.api.RpcRegistrationListener; +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.mount.MountProvisionInstance; +import org.opendaylight.controller.sal.core.api.notify.NotificationListener; +import org.opendaylight.controller.sal.dom.broker.impl.DataReaderRouter; +import org.opendaylight.controller.sal.dom.broker.impl.NotificationRouterImpl; +import org.opendaylight.controller.sal.dom.broker.impl.RpcRouterImpl; +import org.opendaylight.controller.sal.dom.broker.spi.NotificationRouter; +import org.opendaylight.controller.sal.dom.broker.spi.RpcRouter; +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; + +public class MountPointImpl implements MountProvisionInstance { + + final RpcRouter rpcs; + final DataReaderRouter dataReader; + final NotificationRouter notificationRouter; + + public MountPointImpl(InstanceIdentifier path) { + rpcs = new RpcRouterImpl(""); + dataReader = new DataReaderRouter(); + notificationRouter = new NotificationRouterImpl(); + } + + @Override + public void publish(CompositeNode notification) { + notificationRouter.publish(notification); + } + + @Override + public Registration addNotificationListener(QName notification, NotificationListener listener) { + return notificationRouter.addNotificationListener(notification, listener); + } + + @Override + public CompositeNode readConfigurationData(InstanceIdentifier path) { + return dataReader.readConfigurationData(path); + } + + @Override + public CompositeNode readOperationalData(InstanceIdentifier path) { + return dataReader.readOperationalData(path); + } + + public Registration> registerOperationalReader( + InstanceIdentifier path, DataReader reader) { + return dataReader.registerOperationalReader(path, reader); + } + + public Registration> registerConfigurationReader( + InstanceIdentifier path, DataReader reader) { + return dataReader.registerConfigurationReader(path, reader); + } + + @Override + public RoutedRpcRegistration addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation) { + return rpcs.addRoutedRpcImplementation(rpcType, implementation); + } + + @Override + public RpcRegistration addRpcImplementation(QName rpcType, RpcImplementation implementation) + throws IllegalArgumentException { + return rpcs.addRpcImplementation(rpcType, implementation); + } + + public Set getSupportedRpcs() { + return rpcs.getSupportedRpcs(); + } + + + public RpcResult invokeRpc(QName rpc, CompositeNode input) { + return rpcs.invokeRpc(rpc, input); + } + + public ListenerRegistration addRpcRegistrationListener(RpcRegistrationListener listener) { + return rpcs.addRpcRegistrationListener(listener); + } + + + @Override + public Future> rpc(QName type, CompositeNode input) { + // TODO Auto-generated method stub + return null; + } + + @Override + public DataModificationTransaction beginTransaction() { + // TODO Auto-generated method stub + return null; + } + + @Override + public ListenerRegistration registerDataChangeListener(InstanceIdentifier path, + DataChangeListener listener) { + // TODO Auto-generated method stub + return null; + } + + @Override + public void sendNotification(CompositeNode notification) { + publish(notification); + + } +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointManagerImpl.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointManagerImpl.xtend new file mode 100644 index 0000000000..c64d1e56dd --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointManagerImpl.xtend @@ -0,0 +1,35 @@ +package org.opendaylight.controller.sal.dom.broker + + +import org.opendaylight.controller.sal.core.api.mount.MountProvisionService +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier +import java.util.concurrent.ConcurrentMap +import java.util.concurrent.ConcurrentHashMap +import static com.google.common.base.Preconditions.*; + +class MountPointManagerImpl implements MountProvisionService { + + ConcurrentMap mounts = new ConcurrentHashMap(); + + override createMountPoint(InstanceIdentifier path) { + checkState(!mounts.containsKey(path),"Mount already created"); + val mount = new MountPointImpl(path); + mounts.put(path,mount); + } + + + override createOrGetMountPoint(InstanceIdentifier path) { + val mount = mounts.get(path); + if(mount === null) { + return createMountPoint(path) + } + return mount; + } + + + override getMountPoint(InstanceIdentifier path) { + mounts.get(path); + } + + +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ProviderContextImpl.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ProviderContextImpl.xtend index bffc570596..cf5d220943 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ProviderContextImpl.xtend +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ProviderContextImpl.xtend @@ -1,25 +1,23 @@ package org.opendaylight.controller.sal.dom.broker -import java.util.Collections -import java.util.HashMap import org.opendaylight.controller.sal.core.api.Broker.ProviderSession import org.opendaylight.controller.sal.core.api.Provider import org.opendaylight.controller.sal.core.api.RpcImplementation import org.opendaylight.yangtools.yang.common.QName import org.osgi.framework.BundleContext -import org.opendaylight.yangtools.concepts.AbstractObjectRegistration import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration -import static java.util.Collections.* -import java.util.Collections -import java.util.HashMap import org.opendaylight.controller.sal.core.api.RpcRegistrationListener +import org.opendaylight.yangtools.concepts.Registration + +import java.util.Set +import java.util.HashSet class ProviderContextImpl extends ConsumerContextImpl implements ProviderSession { @Property private val Provider provider; - private val rpcImpls = Collections.synchronizedMap(new HashMap()); + private val Set> registrations = new HashSet(); new(Provider provider, BundleContext ctx) { super(null, ctx); @@ -27,39 +25,22 @@ class ProviderContextImpl extends ConsumerContextImpl implements ProviderSession } override addRpcImplementation(QName rpcType, RpcImplementation implementation) throws IllegalArgumentException { - if (rpcType == null) { - throw new IllegalArgumentException("rpcType must not be null"); - } - if (implementation == null) { - throw new IllegalArgumentException("Implementation must not be null"); - } - broker.addRpcImplementation(rpcType, implementation); - rpcImpls.put(rpcType, implementation); - - return new RpcRegistrationImpl(rpcType, implementation, this); + val origReg = broker.router.addRpcImplementation(rpcType, implementation); + val newReg = new RpcRegistrationWrapper(origReg); + registrations.add(newReg); + return newReg; } - def removeRpcImplementation(RpcRegistrationImpl implToRemove) throws IllegalArgumentException { - val localImpl = rpcImpls.get(implToRemove.type); - if (localImpl !== implToRemove.instance) { - throw new IllegalStateException("Implementation was not registered in this session"); - } - broker.removeRpcImplementation(implToRemove.type, localImpl); - rpcImpls.remove(implToRemove.type); + protected def removeRpcImplementation(RpcRegistrationWrapper implToRemove) throws IllegalArgumentException { + registrations.remove(implToRemove); } - + override close() { - removeAllRpcImlementations - super.close - } - - private def removeAllRpcImlementations() { - if (!rpcImpls.empty) { - for (entry : rpcImpls.entrySet) { - broker.removeRpcImplementation(entry.key, entry.value); - } - rpcImpls.clear + + for (reg : registrations) { + reg.close() } + super.close } override addMountedRpcImplementation(QName rpcType, RpcImplementation implementation) { @@ -71,30 +52,34 @@ class ProviderContextImpl extends ConsumerContextImpl implements ProviderSession } override getSupportedRpcs() { - broker.getSupportedRpcs(); + broker.router.supportedRpcs; } override addRpcRegistrationListener(RpcRegistrationListener listener) { - broker.addRpcRegistrationListener(listener); + broker.router.addRpcRegistrationListener(listener); } } -class RpcRegistrationImpl extends AbstractObjectRegistration implements RpcRegistration { +class RpcRegistrationWrapper implements RpcRegistration { + @Property - val QName type + val RpcRegistration delegate - private var ProviderContextImpl context + new(RpcRegistration delegate) { + _delegate = delegate + } - new(QName type, RpcImplementation instance, ProviderContextImpl ctx) { - super(instance) - _type = type - context = ctx + override getInstance() { + delegate.instance } - override protected removeRegistration() { - context.removeRpcImplementation(this) - context = null + override close() { + delegate.close } + override getType() { + delegate.type + } } + diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataReaderRouter.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataReaderRouter.xtend new file mode 100644 index 0000000000..1e0f3385cc --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataReaderRouter.xtend @@ -0,0 +1,13 @@ +package org.opendaylight.controller.sal.dom.broker.impl + +import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRouter +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier +import org.opendaylight.yangtools.yang.data.api.CompositeNode + +class DataReaderRouter extends AbstractDataReadRouter { + + override protected merge(InstanceIdentifier path, Iterable data) { + return data.iterator.next + } + +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/NotificationRouterImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/NotificationRouterImpl.java new file mode 100644 index 0000000000..6d7b600dbc --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/NotificationRouterImpl.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.sal.dom.broker.impl; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.opendaylight.controller.sal.core.api.BrokerService; +import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession; +import org.opendaylight.controller.sal.core.api.Broker.ProviderSession; +import org.opendaylight.controller.sal.core.api.Consumer.ConsumerFunctionality; +import org.opendaylight.controller.sal.core.api.Provider.ProviderFunctionality; +import org.opendaylight.controller.sal.core.api.notify.NotificationListener; +import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService; +import org.opendaylight.controller.sal.core.api.notify.NotificationService; +import org.opendaylight.controller.sal.core.spi.BrokerModule; +import org.opendaylight.controller.sal.dom.broker.spi.NotificationRouter; +import org.opendaylight.yangtools.concepts.AbstractObjectRegistration; +import org.opendaylight.yangtools.concepts.Registration; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Multimap; + +public class NotificationRouterImpl implements NotificationRouter { + private static Logger log = LoggerFactory.getLogger(NotificationRouterImpl.class); + + private Multimap> listeners = HashMultimap.create(); + + private void sendNotification(CompositeNode notification) { + QName type = notification.getNodeType(); + Collection> toNotify = listeners.get(type); + log.info("Publishing notification " + type); + + if (toNotify == null) { + // No listeners were registered - returns. + return; + } + + for (Registration listener : toNotify) { + try { + // FIXME: ensure that notification is immutable + listener.getInstance().onNotification(notification); + } catch (Exception e) { + log.error("Uncaught exception in NotificationListener", e); + } + } + + } + + @Override + public void publish(CompositeNode notification) { + sendNotification(notification); + } + + @Override + public Registration addNotificationListener(QName notification, NotificationListener listener) { + ListenerRegistration ret = new ListenerRegistration(notification, listener); + return ret; + } + + private class ListenerRegistration extends AbstractObjectRegistration { + + final QName type; + + public ListenerRegistration(QName type, NotificationListener instance) { + super(instance); + this.type = type; + } + + @Override + protected void removeRegistration() { + listeners.remove(type, this); + } + } +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RpcRouterImpl.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RpcRouterImpl.xtend new file mode 100644 index 0000000000..d67697f849 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RpcRouterImpl.xtend @@ -0,0 +1,106 @@ +package org.opendaylight.controller.sal.dom.broker.impl + +import org.opendaylight.controller.sal.dom.broker.spi.RpcRouter +import org.opendaylight.yangtools.concepts.Identifiable +import org.opendaylight.yangtools.yang.common.QName +import org.opendaylight.controller.sal.core.api.RpcImplementation +import org.opendaylight.yangtools.yang.data.api.CompositeNode +import static com.google.common.base.Preconditions.*; +import java.util.Map +import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration +import java.util.concurrent.ConcurrentHashMap +import java.util.Set +import java.util.Collections +import org.opendaylight.yangtools.concepts.AbstractObjectRegistration +import org.opendaylight.controller.md.sal.common.impl.ListenerRegistry +import org.opendaylight.controller.sal.core.api.RpcRegistrationListener +import org.slf4j.LoggerFactory + +class RpcRouterImpl implements RpcRouter, Identifiable { + + static val log = LoggerFactory.getLogger(RpcRouterImpl) + + Map implementations = new ConcurrentHashMap(); + + @Property + val Set supportedRpcs = Collections.unmodifiableSet(implementations.keySet); + + private val rpcRegistrationListeners = new ListenerRegistry(); + + @Property + val String identifier; + + new(String name) { + _identifier = name; + } + + override addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation) { + } + + override addRpcImplementation(QName rpcType, RpcImplementation implementation) throws IllegalArgumentException { + checkNotNull(rpcType, "Rpc Type should not be null"); + checkNotNull(implementation, "Implementation should not be null."); + checkState(!implementations.containsKey(rpcType), "Provider for supplied rpc is already registered."); + val reg = new RpcRegistrationImpl(rpcType, implementation, this); + implementations.put(rpcType, reg) + + for (listener : rpcRegistrationListeners.listeners) { + try { + listener.instance.onRpcImplementationAdded(rpcType); + } catch (Exception e) { + log.error("Unhandled exception during invoking listener", e); + } + } + + return reg; + + } + + override invokeRpc(QName rpc, CompositeNode input) { + checkNotNull(rpc, "Rpc Type should not be null"); + + val impl = implementations.get(rpc); + checkState(impl !== null, "Provider for supplied rpc is not registered."); + + return impl.instance.invokeRpc(rpc, input); + } + + def remove(RpcRegistrationImpl impl) { + val existing = implementations.get(impl.type); + if (existing == impl) { + implementations.remove(impl.type); + } + for (listener : rpcRegistrationListeners.listeners) { + try { + listener.instance.onRpcImplementationRemoved(impl.type); + } catch (Exception e) { + log.error("Unhandled exception during invoking listener", e); + } + } + } + + override addRpcRegistrationListener(RpcRegistrationListener listener) { + rpcRegistrationListeners.register(listener); + } + +} + +class RpcRegistrationImpl extends AbstractObjectRegistration implements RpcRegistration { + + @Property + val QName type; + + @Property + var RpcRouterImpl router; + + new(QName type, RpcImplementation instance, RpcRouterImpl router) { + super(instance) + _type = type + _router = router + } + + override protected removeRegistration() { + router.remove(this); + } + +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/NotificationRouter.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/NotificationRouter.java new file mode 100644 index 0000000000..fc42d2ceb9 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/NotificationRouter.java @@ -0,0 +1,21 @@ +package org.opendaylight.controller.sal.dom.broker.spi; + +import org.opendaylight.controller.sal.core.api.notify.NotificationListener; +import org.opendaylight.yangtools.concepts.Registration; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; + +public interface NotificationRouter { + + void publish(CompositeNode notification); + + /** + * Registers a notification listener for supplied notification type. + * + * @param notification + * @param listener + */ + Registration addNotificationListener(QName notification, + NotificationListener listener); + +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/RoutedRpcProcessor.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/RoutedRpcProcessor.java new file mode 100644 index 0000000000..97c2a151ce --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/RoutedRpcProcessor.java @@ -0,0 +1,27 @@ +package org.opendaylight.controller.sal.dom.broker.spi; + +import java.util.Map; +import java.util.Set; + +import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration; +import org.opendaylight.controller.sal.core.api.RpcImplementation; +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; + +public interface RoutedRpcProcessor extends RpcImplementation { + + public RoutedRpcRegistration addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation); + + public Set getSupportedRpcs(); + + public QName getRpcType(); + + public RpcResult invokeRpc(QName rpc, CompositeNode input); + + Map getRoutes(); + + RpcImplementation getDefaultRoute(); + +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/RpcRouter.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/RpcRouter.java new file mode 100644 index 0000000000..6886f892c6 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/RpcRouter.java @@ -0,0 +1,31 @@ +package org.opendaylight.controller.sal.dom.broker.spi; + +import java.util.Set; + +import org.opendaylight.controller.sal.core.api.RpcImplementation; +import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry; +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.RpcRegistrationListener; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; + +public interface RpcRouter extends RpcProvisionRegistry, RpcImplementation { + + @Override + public RoutedRpcRegistration addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation); + + @Override + public RpcRegistration addRpcImplementation(QName rpcType, RpcImplementation implementation) + throws IllegalArgumentException; + + @Override + public Set getSupportedRpcs(); + + @Override + public RpcResult invokeRpc(QName rpc, CompositeNode input); + + ListenerRegistration addRpcRegistrationListener(RpcRegistrationListener listener); +} diff --git a/opendaylight/md-sal/sal-netconf-connector/pom.xml b/opendaylight/md-sal/sal-netconf-connector/pom.xml index c8bc71577d..57e4d858c1 100644 --- a/opendaylight/md-sal/sal-netconf-connector/pom.xml +++ b/opendaylight/md-sal/sal-netconf-connector/pom.xml @@ -6,6 +6,9 @@ sal-parent 1.0-SNAPSHOT + + 0.2.2-SNAPSHOT + sal-netconf-connector scm:git:ssh://git.opendaylight.org:29418/controller.git @@ -18,6 +21,150 @@ ${project.groupId} sal-connector-api + + ${project.groupId} + sal-common-util + 1.0-SNAPSHOT + + + org.eclipse.xtend + org.eclipse.xtend.lib + + + org.opendaylight.controller + netconf-client + 0.2.2-SNAPSHOT + + + org.opendaylight.yangtools + yang-data-impl + 0.5.9-SNAPSHOT + + + junit + junit + test + + + ${project.groupId} + yang-test + ${netconf.version} + test + + + ${project.groupId} + config-api + ${netconf.version} + test + + + ${project.groupId} + config-util + ${netconf.version} + test + + + ${project.groupId} + yang-store-api + ${netconf.version} + test + + + ${project.groupId} + netconf-api + ${netconf.version} + test + + + org.opendaylight.bgpcep + util + test + 0.3.0-SNAPSHOT + + + ${project.groupId} + netconf-client + test + ${netconf.version} + + + ${project.groupId} + config-netconf-connector + test + ${netconf.version} + + + ${project.groupId} + yang-test + test + ${netconf.version} + + + ${project.groupId} + config-manager + test + ${netconf.version} + + + ${project.groupId} + config-persister-impl + test + ${netconf.version} + + + ${project.groupId} + config-manager + test + test-jar + ${netconf.version} + + + ${project.groupId} + netconf-impl + test + ${netconf.version} + + + ${project.groupId} + netconf-mapping-api + test + ${netconf.version} + + + ${project.groupId} + netconf-util + test + test-jar + ${netconf.version} + + + ${project.groupId} + yang-store-impl + test + ${netconf.version} + + + ${project.groupId} + yang-store-impl + test + test-jar + ${netconf.version} + + + org.opendaylight.controller + logback-config + test + ${netconf.version} + + + org.mockito + mockito-all + test + + + org.slf4j + slf4j-api + bundle -- 2.36.6