-<snapshot>
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<snapshot>
<configuration>
-
<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
<module>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:schema-service-singleton</type>
<name>yang-schema-service</name>
</module>
+ <!-- To enable use of new in-memory datastore and new implementations
+ of data brokers, comment out all parts of this
+ xml which are marked with DATA-BROKER and uncomment all parts
+ of this xml which are marked with NEW-DATA-BROKER
+ -->
+ <!-- DATA-BROKER start-->
<module>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:hash-map-data-store</type>
<name>hash-map-data-store</name>
</module>
+ <!-- DATA BROKER end -->
+ <!-- NEW-DATA-BROKER start -->
+ <!--
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-inmemory-data-broker</type>
+ <name>async-data-broker</name>
+ <schema-service>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
+ <name>yang-schema-service</name>
+ </schema-service>
+ </module>
+ -->
+ <!-- NEW-DATA-BROKER end -->
<module>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-broker-impl</type>
<name>dom-broker</name>
+ <!-- DATA-BROKER start -->
<data-store xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
<type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-data-store</type>
<!-- to switch to the clustered data store, comment out the hash-map-data-store <name> and uncomment the cluster-data-store one -->
<name>hash-map-data-store</name>
<!-- <name>cluster-data-store</name> -->
</data-store>
+ <!-- DATA-BROKER end -->
+ <!-- NEW-DATA-BROKER start -->
+ <!--
+ <async-data-broker>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-async-data-broker</type>
+ <name>async-data-broker</name>
+ </async-data-broker>
+ -->
+ <!-- NEW-DATA-BROKER end -->
</module>
<module>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-broker-impl</type>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-notification-broker</type>
<name>binding-notification-broker</name>
</module>
+ <!-- DATA-BROKER start -->
<module>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-data-broker</type>
<name>binding-data-broker</name>
<name>runtime-mapping-singleton</name>
</mapping-service>
</module>
-
+ <!-- DATA-BROKER end -->
+ <!-- NEW-DATA-BROKER start -->
+ <!--
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-data-compatible-broker</type>
+ <name>binding-data-broker</name>
+ <dom-async-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
+ <name>dom-broker</name>
+ </dom-async-broker>
+ <binding-mapping-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding:binding-dom-mapping-service</type>
+ <name>runtime-mapping-singleton</name>
+ </binding-mapping-service>
+ </module>
+ -->
+ <!-- NEW-DATA-BROKER end -->
</modules>
-
<services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
- <service>
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
- <instance>
- <name>yang-schema-service</name>
- <provider>/modules/module[type='schema-service-singleton'][name='yang-schema-service']</provider>
- </instance>
- </service>
- <service>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
- <instance>
- <name>binding-notification-broker</name>
- <provider>/modules/module[type='binding-notification-broker'][name='binding-notification-broker']</provider>
- </instance>
- </service>
- <service>
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-data-store</type>
- <instance>
- <name>hash-map-data-store</name>
- <provider>/modules/module[type='hash-map-data-store'][name='hash-map-data-store']</provider>
- </instance>
- </service>
- <service>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
- <instance>
- <name>binding-osgi-broker</name>
- <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
- </instance>
- </service>
- <service>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
- <instance>
- <name>binding-rpc-broker</name>
- <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
- </instance>
- </service>
- <service>
- <type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding-impl:binding-dom-mapping-service</type>
- <instance>
- <name>runtime-mapping-singleton</name>
- <provider>/modules/module[type='runtime-generated-mapping'][name='runtime-mapping-singleton']</provider>
- </instance>
- </service>
- <service>
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
- <instance>
- <name>dom-broker</name>
- <provider>/modules/module[type='dom-broker-impl'][name='dom-broker']</provider>
- </instance>
- </service>
- <service>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
- <instance>
- <name>binding-data-broker</name>
- <provider>/modules/module[type='binding-data-broker'][name='binding-data-broker']</provider>
- </instance>
- </service>
+ <service>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
+ <instance>
+ <name>yang-schema-service</name>
+ <provider>/modules/module[type='schema-service-singleton'][name='yang-schema-service']</provider>
+ </instance>
+ </service>
+ <service>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
+ <instance>
+ <name>binding-notification-broker</name>
+ <provider>/modules/module[type='binding-notification-broker'][name='binding-notification-broker']</provider>
+ </instance>
+ </service>
+ <!-- DATA-BROKER start -->
+ <service>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-data-store</type>
+ <instance>
+ <name>hash-map-data-store</name>
+ <provider>/modules/module[type='hash-map-data-store'][name='hash-map-data-store']</provider>
+ </instance>
+ </service>
+ <!-- DATA-BROKER end -->
+ <!-- NEW-DATA-BROKER start -->
+ <!--
+ <service>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-async-data-broker</type>
+ <instance>
+ <name>async-data-broker</name>
+ <provider>/modules/module[type='dom-inmemory-data-broker'][name='async-data-broker']</provider>
+ </instance>
+ </service>
+ -->
+ <!-- NEW-DATA-BROKER end -->
+ <service>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
+ <instance>
+ <name>binding-osgi-broker</name>
+ <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
+ </instance>
+ </service>
+ <service>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+ <instance>
+ <name>binding-rpc-broker</name>
+ <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
+ </instance>
+ </service>
+ <service>
+ <type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding-impl:binding-dom-mapping-service</type>
+ <instance>
+ <name>runtime-mapping-singleton</name>
+ <provider>/modules/module[type='runtime-generated-mapping'][name='runtime-mapping-singleton']</provider>
+ </instance>
+ </service>
+ <service>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
+ <instance>
+ <name>dom-broker</name>
+ <provider>/modules/module[type='dom-broker-impl'][name='dom-broker']</provider>
+ </instance>
+ </service>
+
+ <service>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
+ <instance>
+ <name>binding-data-broker</name>
+ <!-- DATA-BROKER start -->
+ <provider>/modules/module[type='binding-data-broker'][name='binding-data-broker']</provider>
+ <!-- DATA-BROKER end -->
+ <!-- NEW-DATA-BROKER start -->
+ <!--
+ <provider>/modules/module[type='binding-data-compatible-broker'][name='binding-data-broker']</provider>
+ -->
+ <!-- NEW-DATA-BROKER end -->
+ </instance>
+ </service>
</services>
</data>
-
</configuration>
-
<required-capabilities>
<capability>urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor?module=netty-event-executor&revision=2013-11-12</capability>
<capability>urn:opendaylight:params:xml:ns:yang:controller:threadpool?module=threadpool&revision=2013-04-09</capability>
<capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&revision=2013-10-28</capability>
<capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&revision=2013-10-28</capability>
</required-capabilities>
-
</snapshot>
-
org.opendaylight.controller.sal.binding.impl.*,
org.opendaylight.controller.sal.binding.codegen,
org.opendaylight.controller.sal.binding.codegen.*,
+ org.opendaylight.controller.md.sal.binding.impl,
<!--org.opendaylight.controller.sal.binding.dom.*,-->
org.opendaylight.controller.sal.binding.osgi.*,
org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.binding.impl.rev131028
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.config.yang.md.sal.binding.impl;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.opendaylight.controller.md.sal.binding.impl.ForwardedBackwardsCompatibleDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingDomConnectorDeployer;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.Provider;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+import org.osgi.framework.BundleContext;
+
+import com.google.common.util.concurrent.ListeningExecutorService;
+
+/**
+*
+*/
+public final class ForwardedCompatibleDataBrokerImplModule extends
+ org.opendaylight.controller.config.yang.md.sal.binding.impl.AbstractForwardedCompatibleDataBrokerImplModule
+ implements Provider {
+
+ private BundleContext bundleContext;
+
+ public ForwardedCompatibleDataBrokerImplModule(
+ final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+ final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public ForwardedCompatibleDataBrokerImplModule(
+ final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+ final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+ final ForwardedCompatibleDataBrokerImplModule oldModule, final java.lang.AutoCloseable oldInstance) {
+
+ super(identifier, dependencyResolver, oldModule, oldInstance);
+ }
+
+ @Override
+ protected void customValidation() {
+ // Add custom validation for module attributes here.
+ }
+
+ @Override
+ public java.lang.AutoCloseable createInstance() {
+ ListeningExecutorService listeningExecutor = SingletonHolder.getDefaultCommitExecutor();
+ BindingIndependentMappingService mappingService = getBindingMappingServiceDependency();
+
+ Broker domBroker = getDomAsyncBrokerDependency();
+ ProviderSession session = domBroker.registerProvider(this, getBundleContext());
+ DOMDataBroker domDataBroker = session.getService(DOMDataBroker.class);
+ ForwardedBackwardsCompatibleDataBroker dataBroker = new ForwardedBackwardsCompatibleDataBroker(domDataBroker,
+ mappingService, listeningExecutor);
+
+ session.getService(SchemaService.class).registerSchemaServiceListener(dataBroker);
+
+ dataBroker.setConnector(BindingDomConnectorDeployer.createConnector(getBindingMappingServiceDependency()));
+ dataBroker.setDomProviderContext(session);
+ return dataBroker;
+ }
+
+ public BundleContext getBundleContext() {
+ return bundleContext;
+ }
+
+ public void setBundleContext(final BundleContext bundleContext2) {
+ this.bundleContext = bundleContext2;
+ }
+
+ @Override
+ public void onSessionInitiated(final ProviderSession session) {
+
+ }
+
+ @Override
+ public Collection<ProviderFunctionality> getProviderFunctionality() {
+ return Collections.emptySet();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.config.yang.md.sal.binding.impl;
+
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;
+import org.opendaylight.controller.config.spi.Module;
+import org.osgi.framework.BundleContext;
+
+
+/**
+*
+*/
+public class ForwardedCompatibleDataBrokerImplModuleFactory extends org.opendaylight.controller.config.yang.md.sal.binding.impl.AbstractForwardedCompatibleDataBrokerImplModuleFactory
+{
+
+
+ @Override
+ public Module createModule(final String instanceName, final DependencyResolver dependencyResolver, final BundleContext bundleContext) {
+ ForwardedCompatibleDataBrokerImplModule module = (ForwardedCompatibleDataBrokerImplModule) super.createModule(instanceName, dependencyResolver, bundleContext);
+ module.setBundleContext(bundleContext);
+ return module;
+ }
+
+ @Override
+ public Module createModule(final String instanceName, final DependencyResolver dependencyResolver,
+ final DynamicMBeanWithInstance old, final BundleContext bundleContext) throws Exception {
+ ForwardedCompatibleDataBrokerImplModule module = (ForwardedCompatibleDataBrokerImplModule) super.createModule(instanceName, dependencyResolver, old, bundleContext);
+ module.setBundleContext(bundleContext);
+ return module;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.binding.impl;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.eclipse.xtext.xbase.lib.Exceptions;
+import org.opendaylight.controller.md.sal.binding.api.BindingDataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentConnector;
+import org.opendaylight.controller.sal.binding.impl.forward.DomForwardedBroker;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.yangtools.concepts.AbstractListenerRegistration;
+import org.opendaylight.yangtools.concepts.Delegator;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBroker>, DomForwardedBroker, SchemaContextListener {
+
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractForwardedDataBroker.class);
+ // The Broker to whom we do all forwarding
+ private final DOMDataBroker domDataBroker;
+
+ // Mapper to convert from Binding Independent objects to Binding Aware
+ // objects
+ private final BindingIndependentMappingService mappingService;
+
+ private final BindingToNormalizedNodeCodec codec;
+ private BindingIndependentConnector connector;
+ private ProviderSession context;
+
+ protected AbstractForwardedDataBroker(final DOMDataBroker domDataBroker,
+ final BindingIndependentMappingService mappingService) {
+ this.domDataBroker = domDataBroker;
+ this.mappingService = mappingService;
+ this.codec = new BindingToNormalizedNodeCodec(mappingService);
+ }
+
+ protected BindingToNormalizedNodeCodec getCodec() {
+ return codec;
+ }
+
+ protected BindingIndependentMappingService getMappingService() {
+ return mappingService;
+ }
+
+ @Override
+ public DOMDataBroker getDelegate() {
+ return domDataBroker;
+ }
+
+ @Override
+ public void onGlobalContextUpdated(final SchemaContext ctx) {
+ codec.onGlobalContextUpdated(ctx);
+ }
+
+ public ListenerRegistration<BindingDataChangeListener> registerDataChangeListener(final LogicalDatastoreType store,
+ final InstanceIdentifier<?> path, final BindingDataChangeListener listener,
+ final DataChangeScope triggeringScope) {
+ DOMDataChangeListener domDataChangeListener = new TranslatingDataChangeInvoker(store, path, listener,
+ triggeringScope);
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath = codec.toNormalized(path);
+ ListenerRegistration<DOMDataChangeListener> domRegistration = domDataBroker.registerDataChangeListener(store, domPath, domDataChangeListener, triggeringScope);
+ return new ListenerRegistrationImpl(listener, domRegistration);
+ }
+
+ protected Map<InstanceIdentifier<?>, DataObject> fromDOMToData(
+ final Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, ? extends NormalizedNode<?, ?>> normalized) {
+ Map<InstanceIdentifier<?>, DataObject> newMap = new HashMap<>();
+ for (Map.Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, ? extends NormalizedNode<?, ?>> entry : normalized
+ .entrySet()) {
+ try {
+ Entry<InstanceIdentifier<? extends DataObject>, DataObject> binding = getCodec().toBinding(entry);
+ newMap.put(binding.getKey(), binding.getValue());
+ } catch (DeserializationException e) {
+ LOG.debug("Ommiting {}",entry,e);
+ }
+ }
+ return newMap;
+ }
+
+ private class TranslatingDataChangeInvoker implements DOMDataChangeListener {
+ private final BindingDataChangeListener bindingDataChangeListener;
+ private final LogicalDatastoreType store;
+ private final InstanceIdentifier<?> path;
+ private final DataChangeScope triggeringScope;
+
+ public TranslatingDataChangeInvoker(final LogicalDatastoreType store, final InstanceIdentifier<?> path,
+ final BindingDataChangeListener bindingDataChangeListener, final DataChangeScope triggeringScope) {
+ this.store = store;
+ this.path = path;
+ this.bindingDataChangeListener = bindingDataChangeListener;
+ this.triggeringScope = triggeringScope;
+ }
+
+ @Override
+ public void onDataChanged(
+ final AsyncDataChangeEvent<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> change) {
+ bindingDataChangeListener.onDataChanged(new TranslatedDataChangeEvent(change,path));
+ }
+ }
+
+ private class TranslatedDataChangeEvent implements AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> {
+ private final AsyncDataChangeEvent<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> domEvent;
+ private InstanceIdentifier<?> path;
+
+ public TranslatedDataChangeEvent(
+ final AsyncDataChangeEvent<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> change) {
+ this.domEvent = change;
+ }
+
+ public TranslatedDataChangeEvent(
+ final AsyncDataChangeEvent<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> change,
+ final InstanceIdentifier<?> path) {
+ this.domEvent = change;
+ this.path = path;
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getCreatedData() {
+ return fromDOMToData(domEvent.getCreatedData());
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getUpdatedData() {
+ return fromDOMToData(domEvent.getUpdatedData());
+
+ }
+
+ @Override
+ public Set<InstanceIdentifier<?>> getRemovedPaths() {
+ final Set<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> removedPaths = domEvent
+ .getRemovedPaths();
+ final Set<InstanceIdentifier<?>> output = new HashSet<>();
+ for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier instanceIdentifier : removedPaths) {
+ try {
+ output.add(mappingService.fromDataDom(instanceIdentifier));
+ } catch (DeserializationException e) {
+ Exceptions.sneakyThrow(e);
+ }
+ }
+
+ return output;
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, ? extends DataObject> getOriginalData() {
+ return fromDOMToData(domEvent.getOriginalData());
+
+ }
+
+ @Override
+ public DataObject getOriginalSubtree() {
+
+ return toBindingData(path,domEvent.getOriginalSubtree());
+ }
+
+ @Override
+ public DataObject getUpdatedSubtree() {
+
+ return toBindingData(path,domEvent.getUpdatedSubtree());
+ }
+
+ @Override
+ public String toString() {
+ return "TranslatedDataChangeEvent [domEvent=" + domEvent + "]";
+ }
+ }
+
+ private static class ListenerRegistrationImpl extends AbstractListenerRegistration<BindingDataChangeListener> {
+ private final ListenerRegistration<DOMDataChangeListener> registration;
+
+ public ListenerRegistrationImpl(final BindingDataChangeListener listener,
+ final ListenerRegistration<DOMDataChangeListener> registration) {
+ super(listener);
+ this.registration = registration;
+ }
+
+ @Override
+ protected void removeRegistration() {
+ registration.close();
+ }
+ }
+
+ protected DataObject toBindingData(final InstanceIdentifier<?> path, final NormalizedNode<?, ?> data) {
+ try {
+ return getCodec().toBinding(path, data);
+ } catch (DeserializationException e) {
+ return null;
+ }
+ }
+
+
+ @Override
+ public BindingIndependentConnector getConnector() {
+ return this.connector;
+ }
+
+ @Override
+ public ProviderSession getDomProviderContext() {
+ return this.context;
+ }
+
+ @Override
+ public void setConnector(final BindingIndependentConnector connector) {
+ this.connector = connector;
+ }
+
+ @Override
+ public void setDomProviderContext(final ProviderSession domProviderContext) {
+ this.context = domProviderContext;
+ }
+
+ @Override
+ public void startForwarding() {
+ // NOOP
+ }
+
+
+
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.binding.impl;
+
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.Nullable;
+
+import org.eclipse.xtext.xbase.lib.Exceptions;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationOperation;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
+import org.opendaylight.yangtools.concepts.Delegator;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+public class AbstractForwardedTransaction<T extends AsyncTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>>>
+ implements Delegator<T> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractForwardedTransaction.class);
+ private final T delegate;
+ private final static CacheBuilder<Object, Object> CACHE_BUILDER = CacheBuilder.newBuilder()
+ .expireAfterWrite(10, TimeUnit.MILLISECONDS).maximumSize(100);
+ private final BindingToNormalizedNodeCodec codec;
+ private final EnumMap<LogicalDatastoreType, Cache<InstanceIdentifier<?>, DataObject>> cacheMap;
+
+ protected AbstractForwardedTransaction(final T delegate, final BindingToNormalizedNodeCodec codec) {
+ super();
+ this.delegate = delegate;
+ this.codec = codec;
+
+ this.cacheMap = new EnumMap<>(LogicalDatastoreType.class);
+ cacheMap.put(LogicalDatastoreType.OPERATIONAL, CACHE_BUILDER.<InstanceIdentifier<?>, DataObject> build());
+ cacheMap.put(LogicalDatastoreType.CONFIGURATION, CACHE_BUILDER.<InstanceIdentifier<?>, DataObject> build());
+
+ }
+
+ @Override
+ public T getDelegate() {
+ return delegate;
+ }
+
+ protected final BindingToNormalizedNodeCodec getCodec() {
+ return codec;
+ }
+
+ protected ListenableFuture<Optional<DataObject>> transformFuture(final LogicalDatastoreType store,
+ final InstanceIdentifier<?> path, final ListenableFuture<Optional<NormalizedNode<?, ?>>> future) {
+ return Futures.transform(future, new Function<Optional<NormalizedNode<?, ?>>, Optional<DataObject>>() {
+ @Nullable
+ @Override
+ public Optional<DataObject> apply(@Nullable final Optional<NormalizedNode<?, ?>> normalizedNode) {
+ try {
+ final DataObject dataObject = normalizedNode.isPresent() ? codec.toBinding(path,
+ normalizedNode.get()) : null;
+ if(dataObject != null) {
+ updateCache(store, path, dataObject);
+ }
+ return Optional.fromNullable(dataObject);
+ } catch (DeserializationException e) {
+ Exceptions.sneakyThrow(e);
+ }
+ return null;
+ }
+ });
+ }
+
+ protected void doPut(final DOMDataWriteTransaction writeTransaction, final LogicalDatastoreType store,
+ final InstanceIdentifier<?> path, final DataObject data) {
+ invalidateCache(store, path);
+ final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> normalized = codec
+ .toNormalizedNode(path, data);
+ writeTransaction.put(store, normalized.getKey(), normalized.getValue());
+ }
+
+ protected void doPutWithEnsureParents(final DOMDataReadWriteTransaction writeTransaction,
+ final LogicalDatastoreType store, final InstanceIdentifier<?> path, final DataObject data) {
+ invalidateCache(store, path);
+ final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> normalized = codec
+ .toNormalizedNode(path, data);
+
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath = normalized.getKey();
+ try {
+ List<PathArgument> currentArguments = new ArrayList<>();
+ DataNormalizationOperation<?> currentOp = codec.getDataNormalizer().getRootOperation();
+ Iterator<PathArgument> iterator = normalizedPath.getPath().iterator();
+ while (iterator.hasNext()) {
+ PathArgument currentArg = iterator.next();
+ currentOp = currentOp.getChild(currentArg);
+ currentArguments.add(currentArg);
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier currentPath = new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(
+ currentArguments);
+ boolean isPresent = writeTransaction.read(store, currentPath).get().isPresent();
+ if (isPresent == false && iterator.hasNext()) {
+ writeTransaction.put(store, currentPath, currentOp.createDefault(currentArg));
+ }
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ e.printStackTrace();
+ }
+ //LOG .info("Tx: {} : Putting data {}",getDelegate().getIdentifier(),normalized.getKey());
+ writeTransaction.put(store, normalized.getKey(), normalized.getValue());
+
+ }
+
+ protected void doMerge(final DOMDataWriteTransaction writeTransaction, final LogicalDatastoreType store,
+ final InstanceIdentifier<?> path, final DataObject data) {
+ invalidateCache(store, path);
+ final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> normalized = codec
+ .toNormalizedNode(path, data);
+ writeTransaction.merge(store, normalized.getKey(), normalized.getValue());
+ }
+
+ protected void doDelete(final DOMDataWriteTransaction writeTransaction, final LogicalDatastoreType store,
+ final InstanceIdentifier<?> path) {
+ invalidateCache(store, path);
+ final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized = codec.toNormalized(path);
+ writeTransaction.delete(store, normalized);
+ }
+
+ protected ListenableFuture<RpcResult<TransactionStatus>> doCommit(final DOMDataWriteTransaction writeTransaction) {
+ return writeTransaction.commit();
+ }
+
+ protected void doCancel(final DOMDataWriteTransaction writeTransaction) {
+ writeTransaction.cancel();
+ }
+
+ protected ListenableFuture<Optional<DataObject>> doRead(final DOMDataReadTransaction readTransaction,
+ final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
+ final DataObject dataObject = getFromCache(store, path);
+ if (dataObject == null) {
+ final ListenableFuture<Optional<NormalizedNode<?, ?>>> future = readTransaction.read(store,
+ codec.toNormalized(path));
+ return transformFuture(store, path, future);
+ } else {
+ return Futures.immediateFuture(Optional.of(dataObject));
+ }
+ }
+
+ private DataObject getFromCache(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
+ Cache<InstanceIdentifier<?>, DataObject> cache = cacheMap.get(store);
+ if (cache != null) {
+ return cache.getIfPresent(path);
+ }
+ return null;
+ }
+
+ private void updateCache(final LogicalDatastoreType store, final InstanceIdentifier<?> path,
+ final DataObject dataObject) {
+ // Check if cache exists. If not create one.
+ Cache<InstanceIdentifier<?>, DataObject> cache = cacheMap.get(store);
+ if (cache == null) {
+ cache = CacheBuilder.newBuilder().maximumSize(1000).expireAfterWrite(1, TimeUnit.MINUTES).build();
+
+ }
+
+ cache.put(path, dataObject);
+ }
+
+ private void invalidateCache(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
+ // FIXME: Optimization: invalidate only parents and children of path
+ Cache<InstanceIdentifier<?>, DataObject> cache = cacheMap.get(store);
+ cache.invalidateAll();
+ LOG.trace("Cache invalidated");
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.binding.impl;
+
+import java.util.AbstractMap.SimpleEntry;
+import java.util.Map.Entry;
+
+import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableList;
+
+public class BindingToNormalizedNodeCodec implements SchemaContextListener {
+
+ private static final Logger LOG = LoggerFactory.getLogger(BindingToNormalizedNodeCodec.class);
+
+ private final BindingIndependentMappingService bindingToLegacy;
+ private DataNormalizer legacyToNormalized;
+
+ public BindingToNormalizedNodeCodec(final BindingIndependentMappingService mappingService) {
+ super();
+ this.bindingToLegacy = mappingService;
+ }
+
+ public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toNormalized(
+ final InstanceIdentifier<? extends DataObject> binding) {
+ return legacyToNormalized.toNormalized(bindingToLegacy.toDataDom(binding));
+ }
+
+ public Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> toNormalizedNode(
+ final InstanceIdentifier<? extends DataObject> bindingPath, final DataObject bindingObject) {
+ return toNormalizedNode(toEntry(bindingPath, bindingObject));
+
+ }
+
+ public Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> toNormalizedNode(
+ final Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject> binding) {
+ Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> normalizedEntry = legacyToNormalized.toNormalized(bindingToLegacy.toDataDom(binding));
+ if(Augmentation.class.isAssignableFrom(binding.getKey().getTargetType())) {
+
+ for(DataContainerChild<? extends PathArgument, ?> child : ((DataContainerNode<?>) normalizedEntry.getValue()).getValue()) {
+ if(child instanceof AugmentationNode) {
+ ImmutableList<PathArgument> childArgs = ImmutableList.<PathArgument>builder()
+ .addAll(normalizedEntry.getKey().getPath())
+ .add(child.getIdentifier())
+ .build();
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier childPath = new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(childArgs);
+ return new SimpleEntry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>>(childPath,child);
+ }
+ }
+
+ }
+ return normalizedEntry;
+
+
+ }
+
+ public InstanceIdentifier<? extends DataObject> toBinding(
+ final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized)
+ throws DeserializationException {
+
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier legacyPath = legacyToNormalized
+ .toLegacy(normalized);
+ return bindingToLegacy.fromDataDom(legacyPath);
+ }
+
+ private static final Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject> toEntry(
+ final org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject> key,
+ final DataObject value) {
+ return new SimpleEntry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject>(
+ key, value);
+ }
+
+ public DataObject toBinding(final InstanceIdentifier<?> path, final NormalizedNode<?, ?> normalizedNode)
+ throws DeserializationException {
+ return bindingToLegacy.dataObjectFromDataDom(path, (CompositeNode) DataNormalizer.toLegacy(normalizedNode));
+ }
+
+ public DataNormalizer getDataNormalizer() {
+ return legacyToNormalized;
+ }
+
+ public Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject> toBinding(
+ final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, ? extends NormalizedNode<?, ?>> normalized)
+ throws DeserializationException {
+ InstanceIdentifier<? extends DataObject> bindingPath = toBinding(normalized.getKey());
+ DataObject bindingData = toBinding(bindingPath, normalized.getValue());
+ return toEntry(bindingPath, bindingData);
+ }
+
+ @Override
+ public void onGlobalContextUpdated(final SchemaContext arg0) {
+ legacyToNormalized = new DataNormalizer(arg0);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.binding.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
+
+import org.opendaylight.controller.md.sal.binding.api.BindingDataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration;
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
+import org.opendaylight.yangtools.concepts.Delegator;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.util.concurrent.AsyncFunction;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+
+public class ForwardedBackwardsCompatibleDataBroker extends AbstractForwardedDataBroker implements DataProviderService, AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ForwardedBackwardsCompatibleDataBroker.class);
+
+ private final ConcurrentHashMap<InstanceIdentifier<?>, CommitHandlerRegistrationImpl> commitHandlers = new ConcurrentHashMap<>();
+ private final ListenerRegistry<DataChangeListener> fakeRegistry = ListenerRegistry.create();
+ private final ListeningExecutorService executorService;
+
+ public ForwardedBackwardsCompatibleDataBroker(final DOMDataBroker domDataBroker,
+ final BindingIndependentMappingService mappingService, final ListeningExecutorService executor) {
+ super(domDataBroker, mappingService);
+ executorService = executor;
+ LOG.info("ForwardedBackwardsCompatibleBroker started.");
+ }
+
+ @Override
+ public DataModificationTransaction beginTransaction() {
+ return new ForwardedBackwardsCompatibleTransacion(getDelegate().newReadWriteTransaction(), getCodec());
+ }
+
+ @Override
+ public DataObject readConfigurationData(final InstanceIdentifier<? extends DataObject> path) {
+ DataModificationTransaction tx = beginTransaction();
+ return tx.readConfigurationData(path);
+ }
+
+ @Override
+ public DataObject readOperationalData(final InstanceIdentifier<? extends DataObject> path) {
+ DataModificationTransaction tx = beginTransaction();
+ return tx.readOperationalData(path);
+ }
+
+ @Override
+ public Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> registerCommitHandler(
+ final InstanceIdentifier<? extends DataObject> path,
+ final DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> commitHandler) {
+
+
+ //transformingCommitHandler = new TransformingDataChangeListener
+ //fakeCommitHandler = registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, path, listener, DataChangeScope.SUBTREE);
+
+ CommitHandlerRegistrationImpl reg = new CommitHandlerRegistrationImpl(path, commitHandler);
+ commitHandlers.put(path, reg);
+ return reg;
+ }
+
+ @Override
+ @Deprecated
+ public ListenerRegistration<RegistrationListener<DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject>>> registerCommitHandlerListener(
+ final RegistrationListener<DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject>> commitHandlerListener) {
+ throw new UnsupportedOperationException("Not supported contract.");
+ }
+
+ @Override
+ public ListenerRegistration<DataChangeListener> registerDataChangeListener(
+ final InstanceIdentifier<? extends DataObject> path, final DataChangeListener listener) {
+
+
+ BindingDataChangeListener asyncOperListener = new BackwardsCompatibleOperationalDataChangeInvoker(listener);
+ BindingDataChangeListener asyncCfgListener = new BackwardsCompatibleConfigurationDataChangeInvoker(listener);
+
+ ListenerRegistration<BindingDataChangeListener> cfgReg = registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, path, asyncCfgListener, DataChangeScope.SUBTREE);
+ ListenerRegistration<BindingDataChangeListener> operReg = registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, path, asyncOperListener, DataChangeScope.SUBTREE);
+
+ return new LegacyListenerRegistration(listener,cfgReg,operReg);
+ }
+
+ @Override
+ public Registration<DataReader<InstanceIdentifier<? extends DataObject>, DataObject>> registerDataReader(
+ final InstanceIdentifier<? extends DataObject> path,
+ final DataReader<InstanceIdentifier<? extends DataObject>, DataObject> reader) {
+ throw new UnsupportedOperationException("Data reader contract is not supported.");
+ }
+
+ @Override
+ public void close() throws Exception {
+ // TODO Auto-generated method stub
+
+ }
+
+ public ListenableFuture<RpcResult<TransactionStatus>> commit(final ForwardedBackwardsCompatibleTransacion tx) {
+
+ final List<DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject>> subTrans = new ArrayList<>();
+ LOG.debug("Tx: {} Submitted.",tx.getIdentifier());
+ ListenableFuture<Boolean> requestCommit = executorService.submit(new Callable<Boolean>() {
+
+ @Override
+ public Boolean call() throws Exception {
+ try {
+ for (CommitHandlerRegistrationImpl handler : commitHandlers.values()) {
+
+ DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> subTx = handler
+ .getInstance().requestCommit(tx);
+ subTrans.add(subTx);
+ }
+ } catch (Exception e) {
+ LOG.error("Tx: {} Rollback.",tx.getIdentifier(),e);
+ for (DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> subTx : subTrans) {
+ subTx.rollback();
+ }
+ return false;
+ }
+ LOG.debug("Tx: {} Can Commit True.",tx.getIdentifier());
+ return true;
+ }
+
+ });
+
+ ListenableFuture<RpcResult<TransactionStatus>> dataStoreCommit = Futures.transform(requestCommit, new AsyncFunction<Boolean, RpcResult<TransactionStatus>>() {
+
+ @Override
+ public ListenableFuture<RpcResult<TransactionStatus>> apply(final Boolean requestCommitSuccess) throws Exception {
+ if(requestCommitSuccess) {
+ return tx.getDelegate().commit();
+ }
+ return Futures.immediateFuture(Rpcs.getRpcResult(false, TransactionStatus.FAILED, Collections.<RpcError>emptySet()));
+ }
+ });
+
+ return Futures.transform(dataStoreCommit, new Function<RpcResult<TransactionStatus>,RpcResult<TransactionStatus>>() {
+ @Override
+ public RpcResult<TransactionStatus> apply(final RpcResult<TransactionStatus> input) {
+ if(input.isSuccessful()) {
+ for(DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> subTx : subTrans ) {
+ subTx.finish();
+ }
+ } else {
+ LOG.error("Tx: {} Rollback - Datastore commit failed.",tx.getIdentifier());
+ for(DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> subTx : subTrans ) {
+ subTx.rollback();
+ }
+ }
+ return input;
+ }
+ });
+ }
+
+ private class ForwardedBackwardsCompatibleTransacion extends
+ AbstractForwardedTransaction<DOMDataReadWriteTransaction> implements DataModificationTransaction {
+
+ private final Map<InstanceIdentifier<? extends DataObject>, DataObject> updated = new HashMap<>();
+ private final Map<InstanceIdentifier<? extends DataObject>, DataObject> created = new HashMap<>();
+ private final Set<InstanceIdentifier<? extends DataObject>> removed = new HashSet<>();
+ private final Map<InstanceIdentifier<? extends DataObject>, DataObject> original = new HashMap<>();
+ private TransactionStatus status = TransactionStatus.NEW;
+
+ @Override
+ public final TransactionStatus getStatus() {
+ return status;
+ }
+
+ protected ForwardedBackwardsCompatibleTransacion(final DOMDataReadWriteTransaction delegate,
+ final BindingToNormalizedNodeCodec codec) {
+ super(delegate, codec);
+ LOG.debug("Tx {} allocated.",getIdentifier());
+ }
+
+ @Override
+ public void putOperationalData(final InstanceIdentifier<? extends DataObject> path, final DataObject data) {
+
+ doPutWithEnsureParents(getDelegate(), LogicalDatastoreType.OPERATIONAL, path, data);
+ }
+
+ @Override
+ public void putConfigurationData(final InstanceIdentifier<? extends DataObject> path, final DataObject data) {
+ DataObject originalObj = readConfigurationData(path);
+ if (originalObj != null) {
+ original.put(path, originalObj);
+
+ } else {
+ created.put(path, data);
+ }
+ updated.put(path, data);
+ doPutWithEnsureParents(getDelegate(), LogicalDatastoreType.CONFIGURATION, path, data);
+ }
+
+ @Override
+ public void removeOperationalData(final InstanceIdentifier<? extends DataObject> path) {
+ doDelete(getDelegate(), LogicalDatastoreType.OPERATIONAL, path);
+
+ }
+
+ @Override
+ public void removeConfigurationData(final InstanceIdentifier<? extends DataObject> path) {
+ doDelete(getDelegate(), LogicalDatastoreType.CONFIGURATION, path);
+ }
+
+ @Override
+ public Map<InstanceIdentifier<? extends DataObject>, DataObject> getCreatedOperationalData() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Map<InstanceIdentifier<? extends DataObject>, DataObject> getCreatedConfigurationData() {
+ return created;
+ }
+
+ @Override
+ public Map<InstanceIdentifier<? extends DataObject>, DataObject> getUpdatedOperationalData() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Map<InstanceIdentifier<? extends DataObject>, DataObject> getUpdatedConfigurationData() {
+ return updated;
+ }
+
+ @Override
+ public Set<InstanceIdentifier<? extends DataObject>> getRemovedConfigurationData() {
+ return removed;
+ }
+
+ @Override
+ public Set<InstanceIdentifier<? extends DataObject>> getRemovedOperationalData() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Map<InstanceIdentifier<? extends DataObject>, DataObject> getOriginalConfigurationData() {
+ return original;
+ }
+
+ @Override
+ public Map<InstanceIdentifier<? extends DataObject>, DataObject> getOriginalOperationalData() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public DataObject readOperationalData(final InstanceIdentifier<? extends DataObject> path) {
+ try {
+ return doRead(getDelegate(), LogicalDatastoreType.OPERATIONAL, path).get().orNull();
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("Read of {} failed.", path,e);
+ return null;
+ }
+ }
+
+ @Override
+ public DataObject readConfigurationData(final InstanceIdentifier<? extends DataObject> path) {
+ try {
+ return doRead(getDelegate(), LogicalDatastoreType.CONFIGURATION, path).get().orNull();
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("Read of {} failed.", path,e);
+ return null;
+ }
+ }
+
+ @Override
+ public Object getIdentifier() {
+ return getDelegate().getIdentifier();
+ }
+
+ private void changeStatus(TransactionStatus status) {
+ LOG.trace("Transaction {} changed status to {}", getIdentifier(), status);
+ this.status = status;
+ }
+
+ @Override
+ public ListenableFuture<RpcResult<TransactionStatus>> commit() {
+ final ListenableFuture<RpcResult<TransactionStatus>> f = ForwardedBackwardsCompatibleDataBroker.this.commit(this);
+
+ changeStatus(TransactionStatus.SUBMITED);
+
+ Futures.addCallback(f, new FutureCallback<RpcResult<TransactionStatus>>() {
+ @Override
+ public void onSuccess(RpcResult<TransactionStatus> result) {
+ changeStatus(result.getResult());
+ }
+
+ @Override
+ public void onFailure(Throwable t) {
+ LOG.error("Transaction {} failed to complete", getIdentifier(), t);
+ changeStatus(TransactionStatus.FAILED);
+ }
+ });
+
+ return f;
+ }
+
+ @Override
+ public ListenerRegistration<DataTransactionListener> registerListener(final DataTransactionListener listener) {
+ throw new UnsupportedOperationException();
+ }
+
+ }
+
+ private class CommitHandlerRegistrationImpl extends
+ AbstractObjectRegistration<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> {
+
+ private final InstanceIdentifier<? extends DataObject> path;
+
+ public CommitHandlerRegistrationImpl(final InstanceIdentifier<? extends DataObject> path,
+ final DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> commitHandler) {
+ super(commitHandler);
+ this.path = path;
+ }
+
+ @Override
+ protected void removeRegistration() {
+ commitHandlers.remove(path, this);
+ }
+
+ }
+
+
+ private static final class LegacyListenerRegistration implements ListenerRegistration<DataChangeListener> {
+
+ private final DataChangeListener instance;
+ private final ListenerRegistration<BindingDataChangeListener> cfgReg;
+ private final ListenerRegistration<BindingDataChangeListener> operReg;
+
+ public LegacyListenerRegistration(final DataChangeListener listener,
+ final ListenerRegistration<BindingDataChangeListener> cfgReg,
+ final ListenerRegistration<BindingDataChangeListener> operReg) {
+ this.instance = listener;
+ this.cfgReg = cfgReg;
+ this.operReg = operReg;
+ }
+
+ @Override
+ public DataChangeListener getInstance() {
+ return instance;
+ }
+
+ @Override
+ public void close() {
+ cfgReg.close();
+ operReg.close();
+ }
+
+ }
+
+ private static class BackwardsCompatibleOperationalDataChangeInvoker implements BindingDataChangeListener, Delegator<DataChangeListener> {
+
+ private final org.opendaylight.controller.md.sal.common.api.data.DataChangeListener<?,?> delegate;
+
+
+ public BackwardsCompatibleOperationalDataChangeInvoker(final DataChangeListener listener) {
+ this.delegate = listener;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Override
+ public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+
+ DataChangeEvent legacyChange = LegacyDataChangeEvent.createOperational(change);
+ delegate.onDataChanged(legacyChange);
+
+ }
+
+ @Override
+ public DataChangeListener getDelegate() {
+ return (DataChangeListener) delegate;
+ }
+
+ }
+
+ private static class BackwardsCompatibleConfigurationDataChangeInvoker implements BindingDataChangeListener, Delegator<DataChangeListener> {
+
+
+ @SuppressWarnings("rawtypes")
+ private final org.opendaylight.controller.md.sal.common.api.data.DataChangeListener<?,?> delegate;
+
+ public BackwardsCompatibleConfigurationDataChangeInvoker(final DataChangeListener listener) {
+ this.delegate = listener;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Override
+ public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+
+ DataChangeEvent legacyChange = LegacyDataChangeEvent.createConfiguration(change);
+
+ delegate.onDataChanged(legacyChange);
+
+ }
+
+ @Override
+ public DataChangeListener getDelegate() {
+ return (DataChangeListener) delegate;
+ }
+
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.binding.impl;
+
+import org.opendaylight.controller.md.sal.binding.api.BindingDataBroker;
+import org.opendaylight.controller.md.sal.binding.api.BindingDataReadTransaction;
+import org.opendaylight.controller.md.sal.binding.api.BindingDataReadWriteTransaction;
+import org.opendaylight.controller.md.sal.binding.api.BindingDataWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * The DataBrokerImpl simply defers to the DOMDataBroker for all its operations.
+ * All transactions and listener registrations are wrapped by the DataBrokerImpl
+ * to allow binding aware components to use the DataBroker transparently.
+ *
+ * Besides this the DataBrokerImpl and it's collaborators also cache data that
+ * is already transformed from the binding independent to binding aware format
+ *
+ * TODO : All references in this class to CompositeNode should be switched to
+ * NormalizedNode once the MappingService is updated
+ *
+ */
+public class ForwardedBindingDataBroker extends AbstractForwardedDataBroker implements BindingDataBroker {
+
+ public ForwardedBindingDataBroker(final DOMDataBroker domDataBroker, final BindingIndependentMappingService mappingService) {
+ super(domDataBroker, mappingService);
+ }
+
+ @Override
+ public BindingDataReadTransaction newReadOnlyTransaction() {
+ return new BindingDataReadTransactionImpl(getDelegate().newReadOnlyTransaction(),getCodec());
+ }
+
+ @Override
+ public BindingDataReadWriteTransaction newReadWriteTransaction() {
+ return new BindingDataReadWriteTransactionImpl(getDelegate().newReadWriteTransaction(),getCodec());
+ }
+
+ @Override
+ public BindingDataWriteTransaction newWriteOnlyTransaction() {
+ return new BindingDataWriteTransactionImpl<DOMDataWriteTransaction>(getDelegate().newWriteOnlyTransaction(),getCodec());
+ }
+
+ private abstract class AbstractBindingTransaction<T extends AsyncTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>>>
+ extends AbstractForwardedTransaction<T> implements AsyncTransaction<InstanceIdentifier<?>, DataObject> {
+
+ protected AbstractBindingTransaction(final T delegate, final BindingToNormalizedNodeCodec codec) {
+ super(delegate, codec);
+ }
+
+ @Override
+ public Object getIdentifier() {
+ return getDelegate().getIdentifier();
+ }
+
+ @Override
+ public void close() {
+ getDelegate().close();
+ }
+
+ }
+
+ private class BindingDataReadTransactionImpl extends AbstractBindingTransaction<DOMDataReadTransaction> implements
+ BindingDataReadTransaction {
+
+ protected BindingDataReadTransactionImpl(final DOMDataReadTransaction delegate,
+ final BindingToNormalizedNodeCodec codec) {
+ super(delegate, codec);
+ }
+
+ @Override
+ public ListenableFuture<Optional<DataObject>> read(final LogicalDatastoreType store,
+ final InstanceIdentifier<?> path) {
+ return doRead(getDelegate(), store, path);
+ }
+ }
+
+ private class BindingDataWriteTransactionImpl<T extends DOMDataWriteTransaction> extends
+ AbstractBindingTransaction<T> implements BindingDataWriteTransaction {
+
+ protected BindingDataWriteTransactionImpl(final T delegate, final BindingToNormalizedNodeCodec codec) {
+ super(delegate, codec);
+
+ }
+
+ @Override
+ public void cancel() {
+ doCancel(getDelegate());
+ }
+
+ @Override
+ public void put(final LogicalDatastoreType store, final InstanceIdentifier<?> path, final DataObject data) {
+ doPut(getDelegate(), store, path, data);
+ }
+
+ @Override
+ public void merge(final LogicalDatastoreType store, final InstanceIdentifier<?> path, final DataObject data) {
+ doMerge(getDelegate(), store, path, data);
+ }
+
+ @Override
+ public void delete(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
+ doDelete(getDelegate(), store, path);
+ }
+
+ @Override
+ public ListenableFuture<RpcResult<TransactionStatus>> commit() {
+ return doCommit(getDelegate());
+ }
+ }
+
+ private class BindingDataReadWriteTransactionImpl extends
+ BindingDataWriteTransactionImpl<DOMDataReadWriteTransaction> implements BindingDataReadWriteTransaction {
+
+ protected BindingDataReadWriteTransactionImpl(final DOMDataReadWriteTransaction delegate,
+ final BindingToNormalizedNodeCodec codec) {
+ super(delegate, codec);
+ }
+
+ @Override
+ public ListenableFuture<Optional<DataObject>> read(final LogicalDatastoreType store,
+ final InstanceIdentifier<?> path) {
+ return doRead(getDelegate(), store, path);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.binding.impl;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public abstract class LegacyDataChangeEvent implements
+ DataChangeEvent<InstanceIdentifier<? extends DataObject>, DataObject> {
+
+ private LegacyDataChangeEvent() {
+ }
+
+ public static final DataChangeEvent<InstanceIdentifier<?>, DataObject> createOperational(
+ final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+ return new OperationalChangeEvent(change);
+ }
+
+ public static final DataChangeEvent<InstanceIdentifier<?>, DataObject> createConfiguration(
+ final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+ return new ConfigurationChangeEvent(change);
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getCreatedOperationalData() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getCreatedConfigurationData() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getUpdatedOperationalData() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getUpdatedConfigurationData() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Set<InstanceIdentifier<?>> getRemovedConfigurationData() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Set<InstanceIdentifier<?>> getRemovedOperationalData() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getOriginalConfigurationData() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getOriginalOperationalData() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public DataObject getOriginalConfigurationSubtree() {
+ return null;
+ }
+
+ @Override
+ public DataObject getOriginalOperationalSubtree() {
+ return null;
+ }
+
+ @Override
+ public DataObject getUpdatedConfigurationSubtree() {
+ return null;
+ }
+
+ @Override
+ public DataObject getUpdatedOperationalSubtree() {
+ return null;
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ private final static class OperationalChangeEvent extends LegacyDataChangeEvent {
+
+ private final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> delegate;
+
+ public OperationalChangeEvent(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+ this.delegate = change;
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getCreatedOperationalData() {
+ return delegate.getCreatedData();
+ }
+
+ @Override
+ public Set<InstanceIdentifier<?>> getRemovedOperationalData() {
+ return delegate.getRemovedPaths();
+ }
+
+ @Override
+ public DataObject getOriginalOperationalSubtree() {
+ return delegate.getOriginalSubtree();
+ }
+
+ @Override
+ public DataObject getUpdatedOperationalSubtree() {
+ return delegate.getUpdatedSubtree();
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getOriginalOperationalData() {
+ return (Map) delegate.getOriginalData();
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getUpdatedOperationalData() {
+ return delegate.getUpdatedData();
+ }
+
+ @Override
+ public String toString() {
+ return "OperationalChangeEvent [delegate=" + delegate + "]";
+ }
+
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ private final static class ConfigurationChangeEvent extends LegacyDataChangeEvent {
+
+ private final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> delegate;
+
+ public ConfigurationChangeEvent(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+ this.delegate = change;
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getCreatedConfigurationData() {
+ return delegate.getCreatedData();
+ }
+
+ @Override
+ public Set<InstanceIdentifier<?>> getRemovedConfigurationData() {
+ return delegate.getRemovedPaths();
+ }
+
+ @Override
+ public DataObject getOriginalConfigurationSubtree() {
+ return delegate.getOriginalSubtree();
+ }
+
+ @Override
+ public DataObject getUpdatedConfigurationSubtree() {
+ return delegate.getUpdatedSubtree();
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getOriginalConfigurationData() {
+ return (Map) delegate.getOriginalData();
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getUpdatedConfigurationData() {
+ return delegate.getUpdatedData();
+ }
+
+ @Override
+ public String toString() {
+ return "ConfigurationChangeEvent [delegate=" + delegate + "]";
+ }
+
+ }
+
+}
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
+import org.opendaylight.controller.md.sal.binding.impl.AbstractForwardedDataBroker;
import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
private final Function<InstanceIdentifier<?>, org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> toDOMInstanceIdentifier = new Function<InstanceIdentifier<?>, org.opendaylight.yangtools.yang.data.api.InstanceIdentifier>() {
@Override
- public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier apply(InstanceIdentifier<?> input) {
+ public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier apply(final InstanceIdentifier<?> input) {
return mappingService.toDataDom(input);
}
}
@Override
- public DataObject readOperationalData(InstanceIdentifier<? extends DataObject> path) {
+ public DataObject readOperationalData(final InstanceIdentifier<? extends DataObject> path) {
try {
org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
CompositeNode result = biDataService.readOperationalData(biPath);
}
private DataObject potentialAugmentationRead(InstanceIdentifier<? extends DataObject> path,
- org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath, CompositeNode result)
+ final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath, final CompositeNode result)
throws DeserializationException {
Class<? extends DataObject> targetType = path.getTargetType();
if (Augmentation.class.isAssignableFrom(targetType)) {
}
@Override
- public DataObject readConfigurationData(InstanceIdentifier<? extends DataObject> path) {
+ public DataObject readConfigurationData(final InstanceIdentifier<? extends DataObject> path) {
try {
org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
CompositeNode result = biDataService.readConfigurationData(biPath);
}
private DataModificationTransaction createBindingToDomTransaction(
- DataModification<InstanceIdentifier<? extends DataObject>, DataObject> source) {
+ final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> source) {
DataModificationTransaction target = biDataService.beginTransaction();
LOG.debug("Created DOM Transaction {} for {},", target.getIdentifier(),source.getIdentifier());
for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedConfigurationData()) {
}
private org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction createDomToBindingTransaction(
- DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> source) {
+ final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> source) {
org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction target = baDataService
.beginTransaction();
for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedConfigurationData()) {
return biDataService;
}
- protected void setDomDataService(org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService) {
+ protected void setDomDataService(final org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService) {
this.biDataService = biDataService;
}
return baDataService;
}
- protected void setBindingDataService(DataProviderService baDataService) {
+ protected void setBindingDataService(final DataProviderService baDataService) {
this.baDataService = baDataService;
}
return baRpcRegistry;
}
- protected void setBindingRpcRegistry(RpcProviderRegistry rpcRegistry) {
+ protected void setBindingRpcRegistry(final RpcProviderRegistry rpcRegistry) {
this.baRpcRegistry = rpcRegistry;
}
public void startDataForwarding() {
+ if(baDataService instanceof AbstractForwardedDataBroker) {
+ dataForwarding = true;
+ return;
+ }
checkState(!dataForwarding, "Connector is already forwarding data.");
baDataReaderRegistration = baDataService.registerDataReader(ROOT, this);
baCommitHandlerRegistration = baDataService.registerCommitHandler(ROOT, bindingToDomCommitHandler);
}
}
- protected void setMappingService(BindingIndependentMappingService mappingService) {
+ protected void setMappingService(final BindingIndependentMappingService mappingService) {
this.mappingService = mappingService;
}
}
@Override
- public void onSessionInitiated(ProviderSession session) {
+ public void onSessionInitiated(final ProviderSession session) {
setDomDataService(session.getService(org.opendaylight.controller.sal.core.api.data.DataProviderService.class));
setDomRpcRegistry(session.getService(RpcProvisionRegistry.class));
}
- public <T extends RpcService> void onRpcRouterCreated(Class<T> serviceType, RpcRouter<T> router) {
+ public <T extends RpcService> void onRpcRouterCreated(final Class<T> serviceType, final RpcRouter<T> router) {
}
- public void setDomRpcRegistry(RpcProvisionRegistry registry) {
+ public void setDomRpcRegistry(final RpcProvisionRegistry registry) {
biRpcRegistry = registry;
}
private final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> modification;
public DomToBindingTransaction(
- org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing,
- DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> modification) {
+ final org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing,
+ final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> modification) {
super();
this.backing = backing;
this.modification = modification;
private final DataModificationTransaction backing;
private final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
- public BindingToDomTransaction(DataModificationTransaction backing,
- DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
+ public BindingToDomTransaction(final DataModificationTransaction backing,
+ final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
this.backing = backing;
this.modification = modification;
domOpenedTransactions.put(backing.getIdentifier(), this);
@Override
public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> requestCommit(
- DataModification<InstanceIdentifier<? extends DataObject>, DataObject> bindingTransaction) {
+ final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> bindingTransaction) {
/**
* Transaction was created as DOM transaction, in that case we do
DataCommitHandler<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
@Override
- public void onRegister(DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
+ public void onRegister(final DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath = mappingService.toDataDom(registration
.getPath());
}
@Override
- public void onUnregister(DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
+ public void onUnregister(final DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
// NOOP for now
// FIXME: do registration based on only active commit handlers.
}
@Override
public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> requestCommit(
- DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> domTransaction) {
+ final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> domTransaction) {
Object identifier = domTransaction.getIdentifier();
/**
return registryImpl;
}
- public void setRegistryImpl(RpcProviderRegistryImpl registryImpl) {
+ public void setRegistryImpl(final RpcProviderRegistryImpl registryImpl) {
this.registryImpl = registryImpl;
}
@Override
- public void onGlobalRpcRegistered(Class<? extends RpcService> cls) {
+ public void onGlobalRpcRegistered(final Class<? extends RpcService> cls) {
getRpcForwarder(cls, null);
}
@Override
- public void onGlobalRpcUnregistered(Class<? extends RpcService> cls) {
+ public void onGlobalRpcUnregistered(final Class<? extends RpcService> cls) {
// NOOP
}
@Override
- public void onRpcRouterCreated(RpcRouter<?> router) {
+ public void onRpcRouterCreated(final RpcRouter<?> router) {
Class<? extends BaseIdentity> ctx = router.getContexts().iterator().next();
getRpcForwarder(router.getServiceType(), ctx);
}
@Override
- public void onRouteChange(RouteChange<RpcContextIdentifier, InstanceIdentifier<?>> change) {
+ public void onRouteChange(final RouteChange<RpcContextIdentifier, InstanceIdentifier<?>> change) {
for (Entry<RpcContextIdentifier, Set<InstanceIdentifier<?>>> entry : change.getAnnouncements().entrySet()) {
bindingRoutesAdded(entry);
}
}
- private void bindingRoutesAdded(Entry<RpcContextIdentifier, Set<InstanceIdentifier<?>>> entry) {
+ private void bindingRoutesAdded(final Entry<RpcContextIdentifier, Set<InstanceIdentifier<?>>> entry) {
Class<? extends BaseIdentity> context = entry.getKey().getRoutingContext();
Class<? extends RpcService> service = entry.getKey().getRpcService();
if (context != null) {
}
}
- private DomToBindingRpcForwarder getRpcForwarder(Class<? extends RpcService> service,
- Class<? extends BaseIdentity> context) {
+ private DomToBindingRpcForwarder getRpcForwarder(final Class<? extends RpcService> service,
+ final Class<? extends BaseIdentity> context) {
DomToBindingRpcForwarder potential = forwarders.get(service);
if (potential != null) {
return potential;
private final Map<QName, RpcInvocationStrategy> strategiesByQName = new HashMap<>();
private final WeakHashMap<Method, RpcInvocationStrategy> strategiesByMethod = new WeakHashMap<>();
- public DomToBindingRpcForwarder(Class<? extends RpcService> service) {
+ public DomToBindingRpcForwarder(final Class<? extends RpcService> service) {
this.rpcServiceType = new WeakReference<Class<? extends RpcService>>(service);
this.supportedRpcs = mappingService.getRpcQNamesFor(service);
try {
* @param service
* @param context
*/
- public DomToBindingRpcForwarder(Class<? extends RpcService> service, Class<? extends BaseIdentity> context) {
+ public DomToBindingRpcForwarder(final Class<? extends RpcService> service, final Class<? extends BaseIdentity> context) {
this.rpcServiceType = new WeakReference<Class<? extends RpcService>>(service);
this.supportedRpcs = mappingService.getRpcQNamesFor(service);
Builder<RoutedRpcRegistration> registrationsBuilder = ImmutableSet
registrations = registrationsBuilder.build();
}
- public void registerPaths(Class<? extends BaseIdentity> context, Class<? extends RpcService> service,
- Set<InstanceIdentifier<?>> set) {
+ public void registerPaths(final Class<? extends BaseIdentity> context, final Class<? extends RpcService> service,
+ final Set<InstanceIdentifier<?>> set) {
QName ctx = BindingReflections.findQName(context);
for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier path : FluentIterable.from(set).transform(
toDOMInstanceIdentifier)) {
@Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
if (EQUALS_METHOD.equals(method)) {
return false;
}
return strategy.forwardToDomBroker(null);
}
- public void removePaths(Class<? extends BaseIdentity> context, Class<? extends RpcService> service,
- Set<InstanceIdentifier<?>> set) {
+ public void removePaths(final Class<? extends BaseIdentity> context, final Class<? extends RpcService> service,
+ final Set<InstanceIdentifier<?>> set) {
QName ctx = BindingReflections.findQName(context);
for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier path : FluentIterable.from(set).transform(
toDOMInstanceIdentifier)) {
}
@Override
- public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode domInput) {
+ public RpcResult<CompositeNode> invokeRpc(final QName rpc, final CompositeNode domInput) {
checkArgument(rpc != null);
checkArgument(domInput != null);
}
}
- private RpcInvocationStrategy resolveInvocationStrategy(QName rpc) {
+ private RpcInvocationStrategy resolveInvocationStrategy(final QName rpc) {
return strategiesByQName.get(rpc);
}
protected final Method targetMethod;
protected final QName rpc;
- public RpcInvocationStrategy(QName rpc, Method targetMethod) {
+ public RpcInvocationStrategy(final QName rpc, final Method targetMethod) {
this.targetMethod = targetMethod;
this.rpc = rpc;
}
public abstract RpcResult<CompositeNode> uncheckedInvoke(RpcService rpcService, CompositeNode domInput)
throws Exception;
- public RpcResult<CompositeNode> invokeOn(RpcService rpcService, CompositeNode domInput) throws Exception {
+ public RpcResult<CompositeNode> invokeOn(final RpcService rpcService, final CompositeNode domInput) throws Exception {
return uncheckedInvoke(rpcService, domInput);
}
}
private final WeakReference<Class> outputClass;
@SuppressWarnings({ "rawtypes", "unchecked" })
- public DefaultInvocationStrategy(QName rpc, Method targetMethod, Class<?> outputClass,
- Class<? extends DataContainer> inputClass) {
+ public DefaultInvocationStrategy(final QName rpc, final Method targetMethod, final Class<?> outputClass,
+ final Class<? extends DataContainer> inputClass) {
super(rpc, targetMethod);
this.outputClass = new WeakReference(outputClass);
this.inputClass = new WeakReference(inputClass);
@SuppressWarnings("unchecked")
@Override
- public RpcResult<CompositeNode> uncheckedInvoke(RpcService rpcService, CompositeNode domInput) throws Exception {
+ public RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput) throws Exception {
DataContainer bindingInput = mappingService.dataObjectFromDataDom(inputClass.get(), domInput);
Future<RpcResult<?>> futureResult = (Future<RpcResult<?>>) targetMethod.invoke(rpcService, bindingInput);
if (futureResult == null) {
}
@Override
- public Future<RpcResult<?>> forwardToDomBroker(DataObject input) {
+ public Future<RpcResult<?>> forwardToDomBroker(final DataObject input) {
if(biRpcRegistry != null) {
CompositeNode xml = mappingService.toDataDom(input);
CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc, ImmutableList.<Node<?>> of(xml));
private class NoInputNoOutputInvocationStrategy extends RpcInvocationStrategy {
- public NoInputNoOutputInvocationStrategy(QName rpc, Method targetMethod) {
+ public NoInputNoOutputInvocationStrategy(final QName rpc, final Method targetMethod) {
super(rpc, targetMethod);
}
@Override
- public RpcResult<CompositeNode> uncheckedInvoke(RpcService rpcService, CompositeNode domInput) throws Exception {
+ public RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput) throws Exception {
@SuppressWarnings("unchecked")
Future<RpcResult<Void>> result = (Future<RpcResult<Void>>) targetMethod.invoke(rpcService);
RpcResult<Void> bindingResult = result.get();
}
@Override
- public Future<RpcResult<?>> forwardToDomBroker(DataObject input) {
+ public Future<RpcResult<?>> forwardToDomBroker(final DataObject input) {
return Futures.immediateFuture(null);
}
}
private final WeakReference<Class> inputClass;
@SuppressWarnings({ "rawtypes", "unchecked" })
- public NoOutputInvocationStrategy(QName rpc, Method targetMethod,
- Class<? extends DataContainer> inputClass) {
+ public NoOutputInvocationStrategy(final QName rpc, final Method targetMethod,
+ final Class<? extends DataContainer> inputClass) {
super(rpc,targetMethod);
this.inputClass = new WeakReference(inputClass);
}
@Override
- public RpcResult<CompositeNode> uncheckedInvoke(RpcService rpcService, CompositeNode domInput) throws Exception {
+ public RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput) throws Exception {
DataContainer bindingInput = mappingService.dataObjectFromDataDom(inputClass.get(), domInput);
Future<RpcResult<?>> result = (Future<RpcResult<?>>) targetMethod.invoke(rpcService, bindingInput);
if (result == null) {
}
@Override
- public Future<RpcResult<?>> forwardToDomBroker(DataObject input) {
+ public Future<RpcResult<?>> forwardToDomBroker(final DataObject input) {
if(biRpcRegistry != null) {
CompositeNode xml = mappingService.toDataDom(input);
CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc,ImmutableList.<Node<?>>of(xml));
return mappingService;
}
- public void setBindingNotificationService(NotificationProviderService baService) {
+ public void setBindingNotificationService(final NotificationProviderService baService) {
this.baNotifyService = baService;
}
- public void setDomNotificationService(NotificationPublishService domService) {
+ public void setDomNotificationService(final NotificationPublishService domService) {
this.domNotificationService = domService;
}
}
@Override
- public void onNotification(CompositeNode notification) {
+ public void onNotification(final CompositeNode notification) {
QName qname = notification.getNodeType();
WeakReference<Class<? extends Notification>> potential = notifications.get(qname);
if (potential != null) {
}
@Override
- public void onNotificationSubscribtion(Class<? extends Notification> notificationType) {
+ public void onNotificationSubscribtion(final Class<? extends Notification> notificationType) {
QName qname = BindingReflections.findQName(notificationType);
if (qname != null) {
WeakReference<Class<? extends Notification>> already = notifications.putIfAbsent(qname,
import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentConnector;
import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
-interface DomForwardedBroker {
+public interface DomForwardedBroker {
public BindingIndependentConnector getConnector();
-
+
public void setConnector(BindingIndependentConnector connector);
-
+
public void setDomProviderContext(ProviderSession domProviderContext);
public ProviderSession getDomProviderContext();
module opendaylight-sal-binding-broker-impl {
- yang-version 1;
+ yang-version 1;
namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl";
prefix "binding-impl";
description
"Service definition for Binding Aware MD-SAL.";
-
+
revision "2013-10-28" {
description
"Initial revision";
config:provided-service sal:binding-rpc-registry;
config:java-name-prefix BindingBrokerImpl;
}
-
+
identity binding-data-broker {
base config:module-type;
config:provided-service sal:binding-data-broker;
config:provided-service sal:binding-data-consumer-broker;
config:java-name-prefix DataBrokerImpl;
}
-
+
+ identity binding-data-compatible-broker {
+ base config:module-type;
+ config:provided-service sal:binding-data-broker;
+ config:provided-service sal:binding-data-consumer-broker;
+ config:java-name-prefix ForwardedCompatibleDataBrokerImpl;
+ }
+
identity binding-rpc-broker {
base config:module-type;
config:provided-service sal:binding-rpc-registry;
config:java-name-prefix RpcBrokerImpl;
}
-
+
identity binding-notification-broker {
base config:module-type;
config:provided-service sal:binding-notification-service;
augment "/config:modules/config:module/config:configuration" {
case binding-broker-impl {
when "/config:modules/config:module/config:type = 'binding-broker-impl'";
-
+
/*
container rpc-registry {
uses config:service-ref {
}
}
}*/
-
+
container data-broker {
uses config:service-ref {
refine type {
}
}
}
-
+
container notification-service {
uses config:service-ref {
refine type {
config:required-identity binding-dom-mapping-service;
}
}
- }
+ }
+ }
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case binding-data-compatible-broker {
+ when "/config:modules/config:module/config:type = 'binding-data-compatible-broker'";
+
+ container dom-async-broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity dom:dom-broker-osgi-registry;
+ }
+ }
+ }
+
+ container binding-mapping-service {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity binding-dom-mapping-service;
+ }
+ }
+ }
}
}
-
+
augment "/config:modules/config:module/config:state" {
case runtime-generated-mapping {
uses common:notification-state;
}
}
-}
\ No newline at end of file
+}
import javassist.ClassPool;
+import org.opendaylight.controller.md.sal.binding.impl.ForwardedBackwardsCompatibleDataBroker;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
import org.opendaylight.controller.md.sal.dom.broker.impl.DOMDataBrokerImpl;
import org.opendaylight.controller.md.sal.dom.broker.impl.compat.BackwardsCompatibleDataBroker;
import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
private final List<SchemaContextListener> schemaListeners = new ArrayList<>();
+ private DataProviderService baData;
+
+ private DOMDataBroker newDOMDataBroker;
+
@Override
public SchemaContext getSchemaContext() {
return schemaContext;
.put(LogicalDatastoreType.CONFIGURATION, configStore)
.build();
- DOMDataBrokerImpl newBiDataImpl = new DOMDataBrokerImpl(newDatastores, executor);
+ newDOMDataBroker = new DOMDataBrokerImpl(newDatastores, executor);
- biCompatibleBroker = new BackwardsCompatibleDataBroker(newBiDataImpl);
+ biCompatibleBroker = new BackwardsCompatibleDataBroker(newDOMDataBroker);
schemaListeners.add(configStore);
schemaListeners.add(operStore);
checkState(executor != null, "Executor needs to be set");
baDataImpl = new DataBrokerImpl();
baDataImpl.setExecutor(executor);
+ baData = baDataImpl;
}
public void startBindingBroker() {
checkState(executor != null, "Executor needs to be set");
- checkState(baDataImpl != null, "Binding Data Broker must be started");
+ checkState(baData != null, "Binding Data Broker must be started");
checkState(baNotifyImpl != null, "Notification Service must be started");
baBrokerImpl = new DomForwardedBindingBrokerImpl("test");
baBrokerImpl.getMountManager().setDataCommitExecutor(executor);
baBrokerImpl.getMountManager().setNotificationExecutor(executor);
baBrokerImpl.setRpcBroker(new RpcProviderRegistryImpl("test"));
- baBrokerImpl.setDataBroker(baDataImpl);
+ baBrokerImpl.setDataBroker(baData);
baBrokerImpl.setNotificationBroker(baNotifyImpl);
baBrokerImpl.start();
}
public void startForwarding() {
- checkState(baDataImpl != null, "Binding Data Broker needs to be started");
+ checkState(baData != null, "Binding Data Broker needs to be started");
checkState(biDataLegacyBroker != null, "DOM Data Broker needs to be started.");
checkState(mappingServiceImpl != null, "DOM Mapping Service needs to be started.");
}
public void start() {
- startBindingDataBroker();
- startBindingNotificationBroker();
- startBindingBroker();
startNewDomDataBroker();
startDomBroker();
startDomMountPoint();
startBindingToDomMappingService();
+ startNewBindingDataBroker();
+
+ startBindingNotificationBroker();
+ startBindingBroker();
+
startForwarding();
if (startWithSchema) {
loadYangSchemaFromClasspath();
}
}
+ public void startNewBindingDataBroker() {
+ ForwardedBackwardsCompatibleDataBroker forwarded = new ForwardedBackwardsCompatibleDataBroker(newDOMDataBroker, mappingServiceImpl, executor);
+ schemaListeners.add(forwarded);
+ baData = forwarded;
+ }
+
private void startDomMountPoint() {
biMountImpl = new MountPointManagerImpl();
biMountImpl.setDataBroker(getDomDataBroker());
}
public DataProviderService getBindingDataBroker() {
- return baDataImpl;
+ return baData;
}
public org.opendaylight.controller.sal.core.api.data.DataProviderService getDomDataBroker() {
*/
package org.opendaylight.controller.sal.binding.test.bugfix;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.Callable;
import javassist.ClassPool;
-import org.junit.Ignore;
import org.junit.Test;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
import org.opendaylight.controller.sal.binding.test.util.BindingBrokerTestFactory;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
-import static org.junit.Assert.*;
-
public class DOMCodecBug02Test extends AbstractDataServiceTest {
private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
private static final NodeRef NODE_REF = new NodeRef(NODE_INSTANCE_ID_BA);
/**
- * This test is ignored, till found out better way to test generation
- * of classes without leaking of instances from previous run
- *
+ * This test is ignored, till found out better way to test generation of
+ * classes without leaking of instances from previous run
+ *
* @throws Exception
*/
-
+
+ @Override
public void setUp() {
ListeningExecutorService executor = MoreExecutors.sameThreadExecutor();
BindingBrokerTestFactory factory = new BindingBrokerTestFactory();
factory.setStartWithParsedSchema(getStartWithSchema());
testContext = factory.getTestContext();
testContext.start();
-
+
baDataService = testContext.getBindingDataBroker();
biDataService = testContext.getDomDataBroker();
dataStore = testContext.getDomDataStore();
mappingService = testContext.getBindingToDomMappingService();
};
-
+
@Test
public void testSchemaContextNotAvailable() throws Exception {
ExecutorService testExecutor = Executors.newFixedThreadPool(1);
testContext.loadYangSchemaFromClasspath();
- Future<Future<RpcResult<TransactionStatus>>> future = testExecutor.submit(new Callable<Future<RpcResult<TransactionStatus>>>() {
- @Override
- public Future<RpcResult<TransactionStatus>> call() throws Exception {
- NodesBuilder nodesBuilder = new NodesBuilder();
- nodesBuilder.setNode(Collections.<Node> emptyList());
- DataModificationTransaction transaction = baDataService.beginTransaction();
- transaction.putOperationalData(NODES_INSTANCE_ID_BA, nodesBuilder.build());
- return transaction.commit();
- }
- });
-
-
+ Future<Future<RpcResult<TransactionStatus>>> future = testExecutor
+ .submit(new Callable<Future<RpcResult<TransactionStatus>>>() {
+ @Override
+ public Future<RpcResult<TransactionStatus>> call() throws Exception {
+ NodesBuilder nodesBuilder = new NodesBuilder();
+ nodesBuilder.setNode(Collections.<Node> emptyList());
+ DataModificationTransaction transaction = baDataService.beginTransaction();
+ transaction.putOperationalData(NODES_INSTANCE_ID_BA, nodesBuilder.build());
+ return transaction.commit();
+ }
+ });
+
RpcResult<TransactionStatus> result = future.get().get();
assertEquals(TransactionStatus.COMMITED, result.getResult());
-
+
Nodes nodes = checkForNodes();
assertNotNull(nodes);
return (Nodes) baDataService.readOperationalData(NODES_INSTANCE_ID_BA);
}
-
+
@Override
protected boolean getStartWithSchema() {
return false;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import com.google.common.util.concurrent.SettableFuture;
+
public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataChangeListener {
private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
.node(SUPPORTED_ACTIONS_QNAME) //
.toInstance();
- private DataChangeEvent<InstanceIdentifier<?>, DataObject> receivedChangeEvent;
+ private final SettableFuture<DataChangeEvent<InstanceIdentifier<?>, DataObject>> receivedChangeEvent = SettableFuture.create();
RpcResult<TransactionStatus> result = transaction.commit().get();
assertEquals(TransactionStatus.COMMITED, result.getResult());
- assertNotNull(receivedChangeEvent);
+ DataChangeEvent<InstanceIdentifier<?>, DataObject> potential = receivedChangeEvent.get(1000,TimeUnit.MILLISECONDS);
+ assertNotNull(potential);
- verifyNodes((Nodes) receivedChangeEvent.getUpdatedOperationalSubtree(),original);
+ verifyNodes((Nodes) potential.getUpdatedOperationalSubtree(),original);
assertBindingIndependentVersion(NODE_INSTANCE_ID_BI);
Nodes nodes = checkForNodes();
verifyNodes(nodes,original);
assertNull(node);
}
- private void verifyNodes(Nodes nodes,Node original) {
+ private void verifyNodes(final Nodes nodes,final Node original) {
assertNotNull(nodes);
assertNotNull(nodes.getNode());
assertEquals(1, nodes.getNode().size());
}
private void assertBindingIndependentVersion(
- org.opendaylight.yangtools.yang.data.api.InstanceIdentifier nodeId) {
+ final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier nodeId) {
CompositeNode node = biDataService.readOperationalData(nodeId);
assertNotNull(node);
}
}
@Override
- public void onDataChanged(DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
- receivedChangeEvent = change;
+ public void onDataChanged(final DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+ receivedChangeEvent.set(change);
}
}
import java.util.Collections;
import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import org.junit.Ignore;
import org.junit.Test;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import com.google.common.util.concurrent.SettableFuture;
+
public class PutAugmentationTest extends AbstractDataServiceTest implements DataChangeListener {
private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
.augmentation(FlowCapableNode.class) //
.build();
- private DataChangeEvent<InstanceIdentifier<?>, DataObject> lastReceivedChangeEvent;
+ private SettableFuture<DataChangeEvent<InstanceIdentifier<?>, DataObject>> lastReceivedChangeEvent;
/**
* Test for Bug 148
* @throws Exception
*/
@Test
+ @Ignore
public void putNodeAndAugmentation() throws Exception {
-
+ lastReceivedChangeEvent = SettableFuture.create();
baDataService.registerDataChangeListener(ALL_FLOW_CAPABLE_NODES, this);
DataModificationTransaction augmentedTransaction = baDataService.beginTransaction();
augmentedTransaction.putOperationalData(augmentIdentifier, fnu);
+
+ lastReceivedChangeEvent = SettableFuture.create();
result = augmentedTransaction.commit().get();
assertEquals(TransactionStatus.COMMITED, result.getResult());
- assertNotNull(lastReceivedChangeEvent);
- assertTrue(lastReceivedChangeEvent.getCreatedOperationalData().containsKey(FLOW_AUGMENTATION_PATH));
+ DataChangeEvent<InstanceIdentifier<?>, DataObject> potential = lastReceivedChangeEvent.get(1000,TimeUnit.MILLISECONDS);
+ assertNotNull(potential);
+ assertTrue(potential.getCreatedOperationalData().containsKey(FLOW_AUGMENTATION_PATH));
+
+ lastReceivedChangeEvent = SettableFuture.create();
Node augmentedNode = (Node) baDataService.readOperationalData(NODE_INSTANCE_ID_BA);
assertNotNull(node);
assertEquals(fnu.getDescription(), readedAugmentation.getDescription());
assertBindingIndependentVersion(NODE_INSTANCE_ID_BI);
testNodeRemove();
- assertTrue(lastReceivedChangeEvent.getRemovedOperationalData().contains(FLOW_AUGMENTATION_PATH));
+ assertTrue(lastReceivedChangeEvent.get(1000,TimeUnit.MILLISECONDS).getRemovedOperationalData().contains(FLOW_AUGMENTATION_PATH));
}
@Test
+ @Ignore
public void putNodeWithAugmentation() throws Exception {
-
+ lastReceivedChangeEvent = SettableFuture.create();
baDataService.registerDataChangeListener(ALL_FLOW_CAPABLE_NODES, this);
NodeBuilder nodeBuilder = new NodeBuilder();
baseTransaction.putOperationalData(NODE_INSTANCE_ID_BA, nodeBuilder.build());
RpcResult<TransactionStatus> result = baseTransaction.commit().get();
- assertNotNull(lastReceivedChangeEvent);
- assertTrue(lastReceivedChangeEvent.getCreatedOperationalData().containsKey(FLOW_AUGMENTATION_PATH));
- lastReceivedChangeEvent = null;
+
+ DataChangeEvent<InstanceIdentifier<?>, DataObject> potential = lastReceivedChangeEvent.get(1000,TimeUnit.MILLISECONDS);
+ assertNotNull(potential);
+ assertTrue(potential.getCreatedOperationalData().containsKey(FLOW_AUGMENTATION_PATH));
+ lastReceivedChangeEvent = SettableFuture.create();
assertEquals(TransactionStatus.COMMITED, result.getResult());
FlowCapableNode readedAugmentation = (FlowCapableNode) baDataService.readOperationalData(InstanceIdentifier
assertEquals(fnu.getHardware(), readedAugmentation.getHardware());
testPutNodeConnectorWithAugmentation();
- lastReceivedChangeEvent = null;
+ lastReceivedChangeEvent = SettableFuture.create();
testNodeRemove();
- assertTrue(lastReceivedChangeEvent.getRemovedOperationalData().contains(FLOW_AUGMENTATION_PATH));
+ assertTrue(lastReceivedChangeEvent.get(1000,TimeUnit.MILLISECONDS).getRemovedOperationalData().contains(FLOW_AUGMENTATION_PATH));
}
private void testPutNodeConnectorWithAugmentation() throws Exception {
assertNull(node);
}
- private void verifyNodes(Nodes nodes, Node original) {
+ private void verifyNodes(final Nodes nodes, final Node original) {
assertNotNull(nodes);
assertNotNull(nodes.getNode());
assertEquals(1, nodes.getNode().size());
}
- private void assertBindingIndependentVersion(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier nodeId) {
+ private void assertBindingIndependentVersion(final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier nodeId) {
CompositeNode node = biDataService.readOperationalData(nodeId);
assertNotNull(node);
}
}
@Override
- public void onDataChanged(DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
- lastReceivedChangeEvent = change;
+ public void onDataChanged(final DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+ lastReceivedChangeEvent.set(change);
}
}
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.TimeUnit;
-import org.junit.Ignore;
import org.junit.Test;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
-import org.opendaylight.controller.sal.common.util.CommitHandlerTransactions;
import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpVersion;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
-import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.SettableFuture;
public class ChangeOriginatedInDomBrokerTest extends AbstractDataServiceTest {
+ private static final Logger LOG = LoggerFactory.getLogger(ChangeOriginatedInDomBrokerTest.class);
+
private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
private static final QName FLOW_ID_QNAME = QName.create(Flow.QNAME, "id");
private static final QName FLOW_NODE_QNAME = QName.create(Flow.QNAME, "node");
private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID));
private static final FlowKey FLOW_KEY = new FlowKey(FLOW_ID);
- private DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modificationCapture;
+ private final SettableFuture<DataChangeEvent<InstanceIdentifier<?>, DataObject>> modificationCapture = SettableFuture.create();
private static final Map<QName, Object> NODE_KEY_BI = Collections.<QName, Object> singletonMap(NODE_ID_QNAME,
NODE_ID);
.toInstance();
@Test
- @Ignore
public void simpleModifyOperation() throws Exception {
assertNull(biDataService.readConfigurationData(FLOW_INSTANCE_ID_BI));
- registerCommitHandler();
+ registerChangeListener();
CompositeNode domflow = createTestFlow();
DataModificationTransaction biTransaction = biDataService.beginTransaction();
biTransaction.putConfigurationData(FLOW_INSTANCE_ID_BI, domflow);
RpcResult<TransactionStatus> biResult = biTransaction.commit().get();
assertEquals(TransactionStatus.COMMITED, biResult.getResult());
- assertNotNull(modificationCapture);
- Flow flow = (Flow) modificationCapture.getCreatedConfigurationData().get(FLOW_INSTANCE_ID_BA);
+ DataChangeEvent<InstanceIdentifier<?>, DataObject> event = modificationCapture.get(1000,TimeUnit.MILLISECONDS);
+ assertNotNull(event);
+ LOG.info("Created Configuration :{}",event.getCreatedConfigurationData());
+ Flow flow = (Flow) event.getCreatedConfigurationData().get(FLOW_INSTANCE_ID_BA);
assertNotNull(flow);
assertNotNull(flow.getMatch());
assertEquals(TransactionStatus.COMMITED, biResult.getResult());
}
- private void registerCommitHandler() {
- DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> flowTestCommitHandler = new DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>() {
+ private void registerChangeListener() {
+ baDataService.registerDataChangeListener(FLOWS_PATH_BA, new DataChangeListener() {
@Override
- public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> requestCommit(
- final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
- modificationCapture = modification;
- return CommitHandlerTransactions.allwaysSuccessfulTransaction(modification);
+ public void onDataChanged(final DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+ LOG.info("Data Change listener invoked.");
+ modificationCapture.set(change);
}
-
- };
- Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> registration = baDataService
- .registerCommitHandler(FLOWS_PATH_BA, flowTestCommitHandler);
- assertNotNull(registration);
+ });
}
private CompositeNode createTestFlow() {
// Wrap our Apply Action in an Instruction
InstructionBuilder ib = new InstructionBuilder();
+ ib.setOrder(0);
ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
// Put our Instruction in a list of Instructions
mavenBundle(CONTROLLER, "ietf-netconf-monitoring-extension").versionAsInProject(), //
mavenBundle(CONTROLLER, "netconf-monitoring").versionAsInProject(), //
- mavenBundle(CONTROLLER, "netty-config-api"), //
+ mavenBundle(CONTROLLER, "netty-config-api").versionAsInProject(), //
mavenBundle(CONTROLLER, "protocol-framework").versionAsInProject(), //
mavenBundle(CONTROLLER, "netconf-client").versionAsInProject(), //
return false;
}
+
+ public boolean isKeyedEntry() {
+ return false;
+ }
+
protected Set<QName> getQNameIdentifiers() {
return Collections.singleton(identifier.getNodeType());
}
return Builders.leafSetEntryBuilder().withNodeIdentifier(nodeId).withValue(node.getValue()).build();
}
+
+ @Override
+ public boolean isKeyedEntry() {
+ return true;
+ }
}
private static abstract class CompositeNodeNormalizationOpertation<T extends PathArgument> extends
protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
ImmutableMap.Builder<QName, Object> keys = ImmutableMap.builder();
for (QName key : keyDefinition) {
- SimpleNode<?> valueNode = checkNotNull(compositeNode.getFirstSimpleByName(key),"List node %s MUST contain leaf %s with value.",getIdentifier().getNodeType(),key);
+
+ SimpleNode<?> valueNode = checkNotNull(compositeNode.getFirstSimpleByName(key),
+ "List node %s MUST contain leaf %s with value.", getIdentifier().getNodeType(), key);
keys.put(key, valueNode.getValue());
}
}
return builder.build();
}
+
+
+ @Override
+ public boolean isKeyedEntry() {
+ return true;
+ }
}
private static final class ContainerNormalization extends DataContainerNormalizationOperation<NodeIdentifier> {
import java.util.AbstractMap;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.Map;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.Node;
import org.opendaylight.yangtools.yang.data.api.SimpleNode;
public class DataNormalizer {
- private final SchemaContext schemaContext;
-
private final DataNormalizationOperation<?> operation;
public DataNormalizer(final SchemaContext ctx) {
- schemaContext = ctx;
operation = DataNormalizationOperation.from(ctx);
}
ImmutableList.Builder<PathArgument> normalizedArgs = ImmutableList.builder();
DataNormalizationOperation<?> currentOp = operation;
- for (PathArgument legacyArg : legacy.getPath()) {
+ Iterator<PathArgument> arguments = legacy.getPath().iterator();
+ while ( arguments.hasNext() ) {
+ PathArgument legacyArg = arguments.next();
currentOp = currentOp.getChild(legacyArg);
checkArgument(currentOp != null, "Legacy Instance Identifier %s is not correct. Normalized Instance Identifier so far %s",legacy,normalizedArgs.build());
while (currentOp.isMixin()) {
normalizedArgs.add(currentOp.getIdentifier());
currentOp = currentOp.getChild(legacyArg.getNodeType());
}
- normalizedArgs.add(legacyArg);
+ if(arguments.hasNext() || (!currentOp.isKeyedEntry() || legacyArg instanceof NodeIdentifierWithPredicates || legacyArg instanceof NodeWithValue)) {
+ normalizedArgs.add(legacyArg);
+ }
}
return new InstanceIdentifier(normalizedArgs.build());
}
private ListenableFuture<RpcResult<TransactionStatus>> submit(
final WriteTransactionImpl<? extends DOMStoreWriteTransaction> transaction) {
- LOG.debug("Tx: {} is submitted for execution.",transaction.getIdentifier());
+ LOG.debug("Tx: {} is submitted for execution.", transaction.getIdentifier());
return executor.submit(new CommitCoordination(transaction));
}
}
@Override
- public void merge(final LogicalDatastoreType store, final InstanceIdentifier path, final NormalizedNode<?, ?> data) {
+ public void merge(final LogicalDatastoreType store, final InstanceIdentifier path,
+ final NormalizedNode<?, ?> data) {
}
}
@Override
public RpcResult<TransactionStatus> call() throws Exception {
- Boolean canCommit = canCommit().get();
try {
+ Boolean canCommit = canCommit().get();
+
if (canCommit) {
try {
preCommit().get();
try {
commit().get();
- COORDINATOR_LOG.debug("Tx: {} Is commited.",transaction.getIdentifier());
- return Rpcs.getRpcResult(true, TransactionStatus.COMMITED, Collections.<RpcError>emptySet());
+ COORDINATOR_LOG.debug("Tx: {} Is commited.", transaction.getIdentifier());
+ return Rpcs.getRpcResult(true, TransactionStatus.COMMITED,
+ Collections.<RpcError> emptySet());
+
} catch (InterruptedException | ExecutionException e) {
COORDINATOR_LOG.error("Tx: {} Error during commit", transaction.getIdentifier(), e);
}
transaction.getIdentifier(), e);
}
} else {
- COORDINATOR_LOG.info("Tx: {} Did not pass canCommit phase.");
+ COORDINATOR_LOG.info("Tx: {} Did not pass canCommit phase.", transaction.getIdentifier());
abort().get();
}
} catch (InterruptedException | ExecutionException e) {
} catch (InterruptedException | ExecutionException e) {
COORDINATOR_LOG.error("Tx: {} Error during abort", transaction.getIdentifier(), e);
}
- return Rpcs.getRpcResult(false, TransactionStatus.FAILED, Collections.<RpcError>emptySet());
+ return Rpcs.getRpcResult(false, TransactionStatus.FAILED, Collections.<RpcError> emptySet());
}
public ListenableFuture<Void> preCommit() {
package org.opendaylight.controller.md.sal.dom.store.impl;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerRegistrationNode.DataChangeListenerRegistration;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.slf4j.Logger;
return removedPaths;
}
+ @Override
+ public String toString() {
+ return "DOMImmutableDataChangeEvent [created=" + createdData.keySet() + ", updated=" + updatedData.keySet()
+ + ", removed=" + removedPaths + "]";
+ }
+
public static class Builder {
private NormalizedNode<?, ?> after;
private final ImmutableMap.Builder<InstanceIdentifier, NormalizedNode<?, ?>> updated = ImmutableMap.builder();
private final ImmutableSet.Builder<InstanceIdentifier> removed = ImmutableSet.builder();
-
private Builder() {
}
}
}
-
import static org.opendaylight.controller.md.sal.dom.store.impl.StoreUtils.append;
import static org.opendaylight.controller.md.sal.dom.store.impl.tree.TreeNodeUtils.getChild;
+import java.util.ArrayList;
+import java.util.Collection;
+
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
import org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.Builder;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerRegistrationNode;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerRegistrationNode.DataChangeListenerRegistration;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
public class DataChangeEventResolver {
+
+ private static final Logger LOG = LoggerFactory.getLogger(DataChangeEventResolver.class);
+
private static final DOMImmutableDataChangeEvent NO_CHANGE = builder().build();
private InstanceIdentifier rootPath;
private ListenerRegistrationNode listenerRoot;
}
public Iterable<ChangeListenerNotifyTask> resolve() {
+ LOG.trace("Resolving events for {}" ,modificationRoot);
resolveAnyChangeEvent(rootPath, Optional.of(listenerRoot), modificationRoot, beforeRoot, afterRoot);
return tasks.build();
}
InstanceIdentifier childPath = StoreUtils.append(path, childId);
builder.merge(resolveCreateEvent(childPath, childListeners, child));
}
+
DOMImmutableDataChangeEvent event = builder.build();
if (listeners.isPresent()) {
addNotifyTask(listeners.get().getListeners(), event);
switch (childMod.getModificationType()) {
case WRITE:
case DELETE:
- one.merge(resolveAnyChangeEvent(childPath, childListen, childMod, childBefore, childBefore));
+ one.merge(resolveAnyChangeEvent(childPath, childListen, childMod, childBefore, childAfter));
break;
case SUBTREE_MODIFIED:
subtree.merge(resolveSubtreeChangeEvent(childPath, childListen, childMod, childBefore.get(),
childAfter.get()));
break;
+ case UNMODIFIED:
+ // no-op
+ break;
}
}
DOMImmutableDataChangeEvent oneChangeEvent = one.build();
return builder().build();
}
- private void addNotifyTask(final ListenerRegistrationNode listenerRegistrationNode, final DataChangeScope one,
+ private void addNotifyTask(final ListenerRegistrationNode listenerRegistrationNode, final DataChangeScope scope,
final DOMImmutableDataChangeEvent event) {
-
-
+ Collection<DataChangeListenerRegistration<?>> potential = listenerRegistrationNode.getListeners();
+ if(potential.isEmpty()) {
+ return;
+ }
+ ArrayList<DataChangeListenerRegistration<?>> toNotify = new ArrayList<>(potential.size());
+ for(DataChangeListenerRegistration<?> listener : potential) {
+ if(scope.equals(listener.getScope())) {
+ toNotify.add(listener);
+ }
+ }
+ addNotifyTask(toNotify, event);
}
- private void addNotifyTask(final Iterable<DataChangeListenerRegistration<?>> listeners,
+ private void addNotifyTask(final Collection<DataChangeListenerRegistration<?>> listeners,
final DOMImmutableDataChangeEvent event) {
- tasks .add(new ChangeListenerNotifyTask(ImmutableSet.copyOf(listeners),event));
+ if(!listeners.isEmpty()) {
+ tasks.add(new ChangeListenerNotifyTask(ImmutableSet.copyOf(listeners),event));
+ }
}
public static DataChangeEventResolver create() {
import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.TreeNodeUtils;
import org.opendaylight.controller.sal.core.spi.data.DOMStore;
import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
import org.slf4j.LoggerFactory;
import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
import com.google.common.primitives.UnsignedLong;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
private SchemaContext schemaContext;
public InMemoryDOMDataStore(final String name, final ListeningExecutorService executor) {
- this.executor = executor;
- this.name = name;
- this.operationTree = new AllwaysFailOperation();
+ this.name = Preconditions.checkNotNull(name);
+ this.executor = Preconditions.checkNotNull(executor);
+ this.operationTree = new AlwaysFailOperation();
this.snapshot = DataAndMetadataSnapshot.createEmpty();
this.listenerTree = ListenerRegistrationNode.createRoot();
}
@Override
- public String getIdentifier() {
+ public final String getIdentifier() {
return name;
}
@Override
public <L extends AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>> ListenerRegistration<L> registerChangeListener(
final InstanceIdentifier path, final L listener, final DataChangeScope scope) {
-
- Optional<ListenerRegistrationNode> listenerNode = TreeNodeUtils.findNode(listenerTree, path);
- checkState(listenerNode.isPresent());
+ LOG.debug("{}: Registering data change listener {} for {}",name,listener,path);
+ ListenerRegistrationNode listenerNode = listenerTree;
+ for(PathArgument arg :path.getPath()) {
+ listenerNode = listenerNode.ensureChild(arg);
+ }
synchronized (listener) {
notifyInitialState(path, listener);
}
- return listenerNode.get().registerDataChangeListener(listener, scope);
+ return listenerNode.registerDataChangeListener(path,listener, scope);
}
private void notifyInitialState(final InstanceIdentifier path,
private synchronized void commit(final DataAndMetadataSnapshot currentSnapshot,
final StoreMetadataNode newDataTree, final Iterable<ChangeListenerNotifyTask> listenerTasks) {
LOG.debug("Updating Store snaphot version: {} with version:{}",currentSnapshot.getMetadataTree().getSubtreeVersion(),newDataTree.getSubtreeVersion());
+
if(LOG.isTraceEnabled()) {
LOG.trace("Data Tree is {}",StoreUtils.toStringTree(newDataTree));
}
proposedSubtree = operationTree.apply(modification, Optional.of(metadataTree),
increase(metadataTree.getSubtreeVersion()));
-
listenerTasks = DataChangeEventResolver.create() //
.setRootPath(PUBLIC_ROOT_PATH) //
.setBeforeRoot(Optional.of(metadataTree)) //
}
- private class AllwaysFailOperation implements ModificationApplyOperation {
+ private static final class AlwaysFailOperation implements ModificationApplyOperation {
@Override
public Optional<StoreMetadataNode> apply(final NodeModification modification,
return new InitialDataChangeEvent(path, data.getData());
}
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public static <V> Function<Identifiable<V>, V> identifierExtractor() {
+ return (Function) EXTRACT_IDENTIFIER;
+ }
+
private static final class InitialDataChangeEvent implements
AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> {
}
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public static <V> Function<Identifiable<V>,V> identifierExtractor() {
- return (Function) EXTRACT_IDENTIFIER;
- }
-
public static <V> Set<V> toIdentifierSet(final Iterable<? extends Identifiable<V>> children) {
- return FluentIterable.from(children).transform(StoreUtils.<V>identifierExtractor()).toSet();
+ return FluentIterable.from(children).transform(StoreUtils.<V> identifierExtractor()).toSet();
}
public static String toStringTree(final StoreMetadataNode metaNode) {
StringBuilder builder = new StringBuilder();
- toStringTree(builder, metaNode,0);
+ toStringTree(builder, metaNode, 0);
return builder.toString();
}
- private static void toStringTree(final StringBuilder builder, final StoreMetadataNode metaNode,final int offset) {
+ private static void toStringTree(final StringBuilder builder, final StoreMetadataNode metaNode, final int offset) {
String prefix = Strings.repeat(" ", offset);
builder.append(prefix).append(toStringTree(metaNode.getIdentifier()));
NormalizedNode<?, ?> dataNode = metaNode.getData();
- if(dataNode instanceof NormalizedNodeContainer<?,?,?>) {
+ if (dataNode instanceof NormalizedNodeContainer<?, ?, ?>) {
builder.append(" {").append("\n");
- for(StoreMetadataNode child : metaNode.getChildren()) {
- toStringTree(builder, child, offset+4);
+ for (StoreMetadataNode child : metaNode.getChildren()) {
+ toStringTree(builder, child, offset + 4);
}
builder.append(prefix).append("}");
} else {
}
private static String toStringTree(final PathArgument identifier) {
- if( identifier instanceof NodeIdentifierWithPredicates) {
+ if (identifier instanceof NodeIdentifierWithPredicates) {
StringBuilder builder = new StringBuilder();
builder.append(identifier.getNodeType().getLocalName());
builder.append(((NodeIdentifierWithPredicates) identifier).getKeyValues().values());
package org.opendaylight.controller.md.sal.dom.store.impl.tree;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.google.common.base.Optional;
-public class ListenerRegistrationNode implements StoreTreeNode<ListenerRegistrationNode>,Identifiable<PathArgument> {
+public class ListenerRegistrationNode implements StoreTreeNode<ListenerRegistrationNode>, Identifiable<PathArgument> {
+
+ private final Logger LOG = LoggerFactory.getLogger(ListenerRegistrationNode.class);
private final ListenerRegistrationNode parent;
private final Map<PathArgument, ListenerRegistrationNode> children;
private final HashSet<DataChangeListenerRegistration<?>> listeners;
private ListenerRegistrationNode(final PathArgument identifier) {
- this(null,identifier);
+ this(null, identifier);
}
- private ListenerRegistrationNode(final ListenerRegistrationNode parent,final PathArgument identifier) {
+ private ListenerRegistrationNode(final ListenerRegistrationNode parent, final PathArgument identifier) {
this.parent = parent;
this.identifier = identifier;
children = new HashMap<>();
return identifier;
}
- public Iterable<DataChangeListenerRegistration<?>> getListeners() {
- return listeners;
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ public Collection<org.opendaylight.controller.md.sal.dom.store.impl.DataChangeListenerRegistration<?>> getListeners() {
+ return (Collection) listeners;
}
@Override
public synchronized Optional<ListenerRegistrationNode> getChild(final PathArgument child) {
+ return Optional.fromNullable(children.get(child));
+ }
+
+ public synchronized ListenerRegistrationNode ensureChild(final PathArgument child) {
ListenerRegistrationNode potential = (children.get(child));
- if(potential == null) {
+ if (potential == null) {
potential = new ListenerRegistrationNode(this, child);
children.put(child, potential);
}
- return Optional.of(potential);
+ return potential;
}
- public <L extends AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>> ListenerRegistration<L> registerDataChangeListener(
+ /**
+ *
+ * Registers listener on this node.
+ *
+ * @param path Full path on which listener is registered.
+ * @param listener Listener
+ * @param scope Scope of triggering event.
+ * @return
+ */
+ public <L extends AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>> ListenerRegistration<L> registerDataChangeListener(final InstanceIdentifier path,
final L listener, final DataChangeScope scope) {
- DataChangeListenerRegistration<L> listenerReg = new DataChangeListenerRegistration<L>(listener, scope,this);
+
+ DataChangeListenerRegistration<L> listenerReg = new DataChangeListenerRegistration<L>(path,listener, scope, this);
listeners.add(listenerReg);
return listenerReg;
}
removeThisIfUnused();
}
-
private void removeThisIfUnused() {
- if(parent != null && listeners.isEmpty() && children.isEmpty()) {
+ if (parent != null && listeners.isEmpty() && children.isEmpty()) {
parent.removeChildIfUnused(this);
}
}
}
private boolean areChildrenUnused() {
- for(ListenerRegistrationNode child : children.values()) {
- if(!child.isUnused()) {
+ for (ListenerRegistrationNode child : children.values()) {
+ if (!child.isUnused()) {
return false;
}
}
// FIXME Remove unnecessary
}
-
-
-
- public static class DataChangeListenerRegistration<T extends AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>> extends AbstractObjectRegistration<T>
- implements ListenerRegistration<T> {
+ public static class DataChangeListenerRegistration<T extends AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>>
+ extends AbstractObjectRegistration<T> implements
+ org.opendaylight.controller.md.sal.dom.store.impl.DataChangeListenerRegistration<T> {
private final DataChangeScope scope;
private ListenerRegistrationNode node;
+ private final InstanceIdentifier path;
- public DataChangeListenerRegistration(final T listener, final DataChangeScope scope, final ListenerRegistrationNode node) {
+ public DataChangeListenerRegistration(final InstanceIdentifier path,final T listener, final DataChangeScope scope,
+ final ListenerRegistrationNode node) {
super(listener);
-
+ this.path = path;
this.scope = scope;
this.node = node;
}
- protected DataChangeScope getScope() {
+ @Override
+ public DataChangeScope getScope() {
return scope;
}
node.removeListener(this);
node = null;
}
+
+ @Override
+ public InstanceIdentifier getPath() {
+ return path;
+ }
}
}
}
private static class NotEnoughCapabilitiesException extends Exception {
+ private NotEnoughCapabilitiesException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
private NotEnoughCapabilitiesException(String message) {
super(message);
}
* @return service if capabilities are present, otherwise absent value
*/
private NetconfOperationService getOperationService(Set<String> expectedCapabilities, String idForReporting) throws NotEnoughCapabilitiesException {
- NetconfOperationService serviceCandidate = configNetconfConnector.createService(idForReporting);
+ NetconfOperationService serviceCandidate;
+ try {
+ serviceCandidate = configNetconfConnector.createService(idForReporting);
+ } catch(RuntimeException e) {
+ throw new NotEnoughCapabilitiesException("Netconf service not stable for " + idForReporting, e);
+ }
Set<String> notFoundDiff = computeNotFoundCapabilities(expectedCapabilities, serviceCandidate);
if (notFoundDiff.isEmpty()) {
return serviceCandidate;
} else {
serviceCandidate.close();
- logger.debug("Netconf server did not provide required capabilities for {} " +
+ logger.trace("Netconf server did not provide required capabilities for {} " +
"Expected but not found: {}, all expected {}, current {}",
idForReporting, notFoundDiff, expectedCapabilities, serviceCandidate.getCapabilities()
);
try {
response = operation.handle(request.getDocument(), NetconfOperationChainedExecution.EXECUTION_TERMINATION_POINT);
} catch (NetconfDocumentedException | RuntimeException e) {
+ if (e instanceof NetconfDocumentedException && e.getCause() instanceof ConflictingVersionException) {
+ throw (ConflictingVersionException) e.getCause();
+ }
throw new IllegalStateException("Failed to send " + operationNameForReporting +
" for configuration " + configIdForReporting, e);
}
- try {
- return NetconfUtil.checkIsMessageOk(response);
- } catch (ConflictingVersionException e) {
- logger.trace("conflicting version detected: {} while committing {}", e.toString(), configIdForReporting);
- throw e;
- }
+ return NetconfUtil.checkIsMessageOk(response);
}
// load editConfig.xml template, populate /rpc/edit-config/config with parameter
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
public class ConfigPersisterTest {
@Test
public void testPersisterConflictingVersionException() throws Exception {
setUpContextAndStartPersister("cap1");
- NetconfOperationService service = getWorkingService(getConflictVersionDocument());
- doReturn(service).when(ctx.serviceFactory).createService(anyString());
+
+ doReturn(getConflictingService()).when(ctx.serviceFactory).createService(anyString());
Thread.sleep(2000);
handler.assertException(IllegalStateException.class, "Max wait for conflicting version stabilization timeout");
}
- private Document getConflictVersionDocument() throws SAXException, IOException {
- return XmlUtil.readXmlToDocument(
- "<rpc-reply message-id=\"1\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n" +
- "<rpc-error><error-info><error>" +
- ConflictingVersionException.class.getCanonicalName() +
- "</error></error-info></rpc-error>\n" +
- "</rpc-reply>"
- );
+ private NetconfOperationService getConflictingService() throws Exception {
+ NetconfOperationService service = getWorkingService(getOKDocument());
+ ConflictingVersionException cve = new ConflictingVersionException("");
+ try {
+ NetconfDocumentedException.wrap(cve);
+ throw new AssertionError("Should throw an exception");
+ }catch(NetconfDocumentedException e) {
+ NetconfOperation mockedOperation = service.getNetconfOperations().iterator().next();
+ doThrow(e).when(mockedOperation).handle(any(Document.class), any(NetconfOperationChainedExecution.class));
+ return service;
+ }
}
@Test
public void testSuccessConflictingVersionException() throws Exception {
setUpContextAndStartPersister("cap1");
- doReturn(getWorkingService(getConflictVersionDocument())).when(ctx.serviceFactory).createService(anyString());
+ doReturn(getConflictingService()).when(ctx.serviceFactory).createService(anyString());
Thread.sleep(500);
// working service:
logger.info("Switching to working service **");
package org.opendaylight.controller.netconf.util;
import com.google.common.base.Preconditions;
-import org.opendaylight.controller.config.api.ConflictingVersionException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.util.xml.XMLNetconfUtil;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathExpression;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
return (doc == null) ? null : new NetconfMessage(doc);
}
- public static Document checkIsMessageOk(NetconfMessage responseMessage) throws ConflictingVersionException {
+ public static Document checkIsMessageOk(NetconfMessage responseMessage) {
return checkIsMessageOk(responseMessage.getDocument());
}
- public static Document checkIsMessageOk(Document response) throws ConflictingVersionException {
+ public static Document checkIsMessageOk(Document response) {
XmlElement element = XmlElement.fromDomDocument(response);
Preconditions.checkState(element.getName().equals(XmlNetconfConstants.RPC_REPLY_KEY));
element = element.getOnlyChildElement();
-
if (element.getName().equals(XmlNetconfConstants.OK)) {
return response;
}
-
- if (element.getName().equals(XmlNetconfConstants.RPC_ERROR)) {
- logger.warn("Can not load last configuration, operation failed");
- // is it ConflictingVersionException ?
- XPathExpression xPathExpression = XMLNetconfUtil.compileXPath("/netconf:rpc-reply/netconf:rpc-error/netconf:error-info/netconf:error");
- String error = (String) XmlUtil.evaluateXPath(xPathExpression, element.getDomElement(), XPathConstants.STRING);
- if (error!=null && error.contains(ConflictingVersionException.class.getCanonicalName())) {
- throw new ConflictingVersionException(error);
- }
- throw new IllegalStateException("Can not load last configuration, operation failed: "
- + XmlUtil.toString(response));
- }
-
logger.warn("Can not load last configuration. Operation failed.");
throw new IllegalStateException("Can not load last configuration. Operation failed: "
+ XmlUtil.toString(response));
package org.opendaylight.controller.netconf.util;
import org.junit.Test;
-import org.opendaylight.controller.config.api.ConflictingVersionException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.w3c.dom.Document;
try{
NetconfUtil.checkIsMessageOk(new NetconfMessage(document));
fail();
- }catch(ConflictingVersionException e){
+ }catch(IllegalStateException e){
assertThat(e.getMessage(), containsString("Optimistic lock failed. Expected parent version 21, was 18"));
}
}
list.add(SwPath.class);
list.add(HwPath.class);
list.add(Drop.class);
+ list.add(Flood.class);
+ list.add(FloodAll.class);
return list;
}