From: Robert Varga Date: Fri, 28 Mar 2014 21:23:07 +0000 (+0100) Subject: Bug 510: Implementation of Forwarded Binding Data Broker X-Git-Tag: autorelease-tag-v20140601202136_82eb3f9~280^2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=743b4bf3f8b1b8ff1ffffbd8151cbd4c1842330d Bug 510: Implementation of Forwarded Binding Data Broker Initial implementation of Forwarded Binding Data Broker and Forwarded Backwards Compatible Data Broker, which provides access to new data broker via original API. Added sample configuration which enables new DOM Data Broker, In-memory Data Broker and ForwardedCompatibleDataBroker. Change-Id: I3569da20a9873edf352a54622be7a01fd329aa9b Signed-off-by: Moiz Raja Signed-off-by: Tony Tkacik Signed-off-by: Robert Varga --- diff --git a/opendaylight/md-sal/sal-binding-broker/pom.xml b/opendaylight/md-sal/sal-binding-broker/pom.xml index dea455bfa1..dafb3ef634 100644 --- a/opendaylight/md-sal/sal-binding-broker/pom.xml +++ b/opendaylight/md-sal/sal-binding-broker/pom.xml @@ -110,6 +110,7 @@ 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.osgi.*, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.binding.impl.rev131028 diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/ForwardedCompatibleDataBrokerImplModule.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/ForwardedCompatibleDataBrokerImplModule.java new file mode 100644 index 0000000000..647ca85671 --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/ForwardedCompatibleDataBrokerImplModule.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.config.yang.md.sal.binding.impl; + +import java.util.Collection; +import java.util.Collections; + +import org.opendaylight.controller.md.sal.binding.impl.ForwardedBackwardsCompatibleDataBroker; +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; +import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder; +import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingDomConnectorDeployer; +import org.opendaylight.controller.sal.core.api.Broker; +import org.opendaylight.controller.sal.core.api.Broker.ProviderSession; +import org.opendaylight.controller.sal.core.api.Provider; +import org.opendaylight.controller.sal.core.api.model.SchemaService; +import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService; +import org.osgi.framework.BundleContext; + +import com.google.common.util.concurrent.ListeningExecutorService; + +/** +* +*/ +public final class ForwardedCompatibleDataBrokerImplModule extends + org.opendaylight.controller.config.yang.md.sal.binding.impl.AbstractForwardedCompatibleDataBrokerImplModule + implements Provider { + + private BundleContext bundleContext; + + public ForwardedCompatibleDataBrokerImplModule( + final org.opendaylight.controller.config.api.ModuleIdentifier identifier, + final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { + super(identifier, dependencyResolver); + } + + public ForwardedCompatibleDataBrokerImplModule( + final org.opendaylight.controller.config.api.ModuleIdentifier identifier, + final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, + final ForwardedCompatibleDataBrokerImplModule oldModule, final java.lang.AutoCloseable oldInstance) { + + super(identifier, dependencyResolver, oldModule, oldInstance); + } + + @Override + protected void customValidation() { + // Add custom validation for module attributes here. + } + + @Override + public java.lang.AutoCloseable createInstance() { + ListeningExecutorService listeningExecutor = SingletonHolder.getDefaultCommitExecutor(); + BindingIndependentMappingService mappingService = getBindingMappingServiceDependency(); + + Broker domBroker = getDomAsyncBrokerDependency(); + ProviderSession session = domBroker.registerProvider(this, getBundleContext()); + DOMDataBroker domDataBroker = session.getService(DOMDataBroker.class); + ForwardedBackwardsCompatibleDataBroker dataBroker = new ForwardedBackwardsCompatibleDataBroker(domDataBroker, + mappingService, listeningExecutor); + + session.getService(SchemaService.class).registerSchemaServiceListener(dataBroker); + + dataBroker.setConnector(BindingDomConnectorDeployer.createConnector(getBindingMappingServiceDependency())); + dataBroker.setDomProviderContext(session); + return dataBroker; + } + + public BundleContext getBundleContext() { + return bundleContext; + } + + public void setBundleContext(final BundleContext bundleContext2) { + this.bundleContext = bundleContext2; + } + + @Override + public void onSessionInitiated(final ProviderSession session) { + + } + + @Override + public Collection getProviderFunctionality() { + return Collections.emptySet(); + } +} diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/ForwardedCompatibleDataBrokerImplModuleFactory.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/ForwardedCompatibleDataBrokerImplModuleFactory.java new file mode 100644 index 0000000000..f01977503e --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/ForwardedCompatibleDataBrokerImplModuleFactory.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.config.yang.md.sal.binding.impl; + +import org.opendaylight.controller.config.api.DependencyResolver; +import org.opendaylight.controller.config.api.DynamicMBeanWithInstance; +import org.opendaylight.controller.config.spi.Module; +import org.osgi.framework.BundleContext; + + +/** +* +*/ +public class ForwardedCompatibleDataBrokerImplModuleFactory extends org.opendaylight.controller.config.yang.md.sal.binding.impl.AbstractForwardedCompatibleDataBrokerImplModuleFactory +{ + + + @Override + public Module createModule(final String instanceName, final DependencyResolver dependencyResolver, final BundleContext bundleContext) { + ForwardedCompatibleDataBrokerImplModule module = (ForwardedCompatibleDataBrokerImplModule) super.createModule(instanceName, dependencyResolver, bundleContext); + module.setBundleContext(bundleContext); + return module; + } + + @Override + public Module createModule(final String instanceName, final DependencyResolver dependencyResolver, + final DynamicMBeanWithInstance old, final BundleContext bundleContext) throws Exception { + ForwardedCompatibleDataBrokerImplModule module = (ForwardedCompatibleDataBrokerImplModule) super.createModule(instanceName, dependencyResolver, old, bundleContext); + module.setBundleContext(bundleContext); + return module; + } + +} diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractForwardedDataBroker.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractForwardedDataBroker.java new file mode 100644 index 0000000000..8a32b0b302 --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractForwardedDataBroker.java @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.binding.impl; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.eclipse.xtext.xbase.lib.Exceptions; +import org.opendaylight.controller.md.sal.binding.api.BindingDataChangeListener; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; +import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener; +import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentConnector; +import org.opendaylight.controller.sal.binding.impl.forward.DomForwardedBroker; +import org.opendaylight.controller.sal.core.api.Broker.ProviderSession; +import org.opendaylight.yangtools.concepts.AbstractListenerRegistration; +import org.opendaylight.yangtools.concepts.Delegator; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService; +import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.api.SchemaContextListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class AbstractForwardedDataBroker implements Delegator, 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 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 domRegistration = domDataBroker.registerDataChangeListener(store, domPath, domDataChangeListener, triggeringScope); + return new ListenerRegistrationImpl(listener, domRegistration); + } + + protected Map, DataObject> fromDOMToData( + final Map> normalized) { + Map, DataObject> newMap = new HashMap<>(); + for (Map.Entry> entry : normalized + .entrySet()) { + try { + Entry, 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> change) { + bindingDataChangeListener.onDataChanged(new TranslatedDataChangeEvent(change,path)); + } + } + + private class TranslatedDataChangeEvent implements AsyncDataChangeEvent, DataObject> { + private final AsyncDataChangeEvent> domEvent; + private InstanceIdentifier path; + + public TranslatedDataChangeEvent( + final AsyncDataChangeEvent> change) { + this.domEvent = change; + } + + public TranslatedDataChangeEvent( + final AsyncDataChangeEvent> change, + final InstanceIdentifier path) { + this.domEvent = change; + this.path = path; + } + + @Override + public Map, DataObject> getCreatedData() { + return fromDOMToData(domEvent.getCreatedData()); + } + + @Override + public Map, DataObject> getUpdatedData() { + return fromDOMToData(domEvent.getUpdatedData()); + + } + + @Override + public Set> getRemovedPaths() { + final Set removedPaths = domEvent + .getRemovedPaths(); + final Set> 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, ? 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 { + private final ListenerRegistration registration; + + public ListenerRegistrationImpl(final BindingDataChangeListener listener, + final ListenerRegistration registration) { + super(listener); + this.registration = registration; + } + + @Override + protected void removeRegistration() { + registration.close(); + } + } + + protected DataObject toBindingData(final InstanceIdentifier path, final NormalizedNode data) { + try { + return getCodec().toBinding(path, data); + } catch (DeserializationException e) { + return null; + } + } + + + @Override + public BindingIndependentConnector getConnector() { + return this.connector; + } + + @Override + public ProviderSession getDomProviderContext() { + return this.context; + } + + @Override + public void setConnector(final BindingIndependentConnector connector) { + this.connector = connector; + } + + @Override + public void setDomProviderContext(final ProviderSession domProviderContext) { + this.context = domProviderContext; + } + + @Override + public void startForwarding() { + // NOOP + } + + + + +} diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractForwardedTransaction.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractForwardedTransaction.java new file mode 100644 index 0000000000..4f9c429e50 --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractForwardedTransaction.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.binding.impl; + +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map.Entry; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; + +import javax.annotation.Nullable; + +import org.eclipse.xtext.xbase.lib.Exceptions; +import org.opendaylight.controller.md.sal.common.api.TransactionStatus; +import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationOperation; +import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction; +import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction; +import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction; +import org.opendaylight.yangtools.concepts.Delegator; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; + +public class AbstractForwardedTransaction>> + implements Delegator { + + private static final Logger LOG = LoggerFactory.getLogger(AbstractForwardedTransaction.class); + private final T delegate; + private final static CacheBuilder CACHE_BUILDER = CacheBuilder.newBuilder() + .expireAfterWrite(10, TimeUnit.MILLISECONDS).maximumSize(100); + private final BindingToNormalizedNodeCodec codec; + private final EnumMap, 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., DataObject> build()); + cacheMap.put(LogicalDatastoreType.CONFIGURATION, CACHE_BUILDER., DataObject> build()); + + } + + @Override + public T getDelegate() { + return delegate; + } + + protected final BindingToNormalizedNodeCodec getCodec() { + return codec; + } + + protected ListenableFuture> transformFuture(final LogicalDatastoreType store, + final InstanceIdentifier path, final ListenableFuture>> future) { + return Futures.transform(future, new Function>, Optional>() { + @Nullable + @Override + public Optional apply(@Nullable final Optional> 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> 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> normalized = codec + .toNormalizedNode(path, data); + + org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath = normalized.getKey(); + try { + List currentArguments = new ArrayList<>(); + DataNormalizationOperation currentOp = codec.getDataNormalizer().getRootOperation(); + Iterator 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> 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> doCommit(final DOMDataWriteTransaction writeTransaction) { + return writeTransaction.commit(); + } + + protected void doCancel(final DOMDataWriteTransaction writeTransaction) { + writeTransaction.cancel(); + } + + protected ListenableFuture> doRead(final DOMDataReadTransaction readTransaction, + final LogicalDatastoreType store, final InstanceIdentifier path) { + final DataObject dataObject = getFromCache(store, path); + if (dataObject == null) { + final ListenableFuture>> 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, 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, 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, DataObject> cache = cacheMap.get(store); + cache.invalidateAll(); + LOG.trace("Cache invalidated"); + } + +} diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/BindingToNormalizedNodeCodec.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/BindingToNormalizedNodeCodec.java new file mode 100644 index 0000000000..f885b323e6 --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/BindingToNormalizedNodeCodec.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.binding.impl; + +import java.util.AbstractMap.SimpleEntry; +import java.util.Map.Entry; + +import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer; +import org.opendaylight.yangtools.yang.binding.Augmentation; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode; +import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild; +import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService; +import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.api.SchemaContextListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.ImmutableList; + +public class BindingToNormalizedNodeCodec implements SchemaContextListener { + + private static final Logger LOG = LoggerFactory.getLogger(BindingToNormalizedNodeCodec.class); + + private final BindingIndependentMappingService bindingToLegacy; + private DataNormalizer legacyToNormalized; + + public BindingToNormalizedNodeCodec(final BindingIndependentMappingService mappingService) { + super(); + this.bindingToLegacy = mappingService; + } + + public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toNormalized( + final InstanceIdentifier binding) { + return legacyToNormalized.toNormalized(bindingToLegacy.toDataDom(binding)); + } + + public Entry> toNormalizedNode( + final InstanceIdentifier bindingPath, final DataObject bindingObject) { + return toNormalizedNode(toEntry(bindingPath, bindingObject)); + + } + + public Entry> toNormalizedNode( + final Entry, DataObject> binding) { + Entry> normalizedEntry = legacyToNormalized.toNormalized(bindingToLegacy.toDataDom(binding)); + if(Augmentation.class.isAssignableFrom(binding.getKey().getTargetType())) { + + for(DataContainerChild child : ((DataContainerNode) normalizedEntry.getValue()).getValue()) { + if(child instanceof AugmentationNode) { + ImmutableList childArgs = ImmutableList.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>(childPath,child); + } + } + + } + return normalizedEntry; + + + } + + public InstanceIdentifier 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, DataObject> toEntry( + final org.opendaylight.yangtools.yang.binding.InstanceIdentifier key, + final DataObject value) { + return new SimpleEntry, 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, DataObject> toBinding( + final Entry> normalized) + throws DeserializationException { + InstanceIdentifier bindingPath = toBinding(normalized.getKey()); + DataObject bindingData = toBinding(bindingPath, normalized.getValue()); + return toEntry(bindingPath, bindingData); + } + + @Override + public void onGlobalContextUpdated(final SchemaContext arg0) { + legacyToNormalized = new DataNormalizer(arg0); + } + +} diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/ForwardedBackwardsCompatibleDataBroker.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/ForwardedBackwardsCompatibleDataBroker.java new file mode 100644 index 0000000000..ee7607306a --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/ForwardedBackwardsCompatibleDataBroker.java @@ -0,0 +1,441 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.binding.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; + +import org.opendaylight.controller.md.sal.binding.api.BindingDataChangeListener; +import org.opendaylight.controller.md.sal.common.api.RegistrationListener; +import org.opendaylight.controller.md.sal.common.api.TransactionStatus; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; +import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent; +import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler; +import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction; +import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration; +import org.opendaylight.controller.md.sal.common.api.data.DataReader; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; +import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction; +import org.opendaylight.controller.sal.binding.api.data.DataChangeListener; +import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; +import org.opendaylight.controller.sal.binding.api.data.DataProviderService; +import org.opendaylight.controller.sal.common.util.Rpcs; +import org.opendaylight.yangtools.concepts.AbstractObjectRegistration; +import org.opendaylight.yangtools.concepts.Delegator; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.concepts.Registration; +import org.opendaylight.yangtools.concepts.util.ListenerRegistry; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcError; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Function; +import com.google.common.util.concurrent.AsyncFunction; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; + +public class ForwardedBackwardsCompatibleDataBroker extends AbstractForwardedDataBroker implements DataProviderService, AutoCloseable { + + private static final Logger LOG = LoggerFactory.getLogger(ForwardedBackwardsCompatibleDataBroker.class); + + private final ConcurrentHashMap, CommitHandlerRegistrationImpl> commitHandlers = new ConcurrentHashMap<>(); + private final ListenerRegistry 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 path) { + DataModificationTransaction tx = beginTransaction(); + return tx.readConfigurationData(path); + } + + @Override + public DataObject readOperationalData(final InstanceIdentifier path) { + DataModificationTransaction tx = beginTransaction(); + return tx.readOperationalData(path); + } + + @Override + public Registration, DataObject>> registerCommitHandler( + final InstanceIdentifier path, + final DataCommitHandler, 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, DataObject>>> registerCommitHandlerListener( + final RegistrationListener, DataObject>> commitHandlerListener) { + throw new UnsupportedOperationException("Not supported contract."); + } + + @Override + public ListenerRegistration registerDataChangeListener( + final InstanceIdentifier path, final DataChangeListener listener) { + + + BindingDataChangeListener asyncOperListener = new BackwardsCompatibleOperationalDataChangeInvoker(listener); + BindingDataChangeListener asyncCfgListener = new BackwardsCompatibleConfigurationDataChangeInvoker(listener); + + ListenerRegistration cfgReg = registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, path, asyncCfgListener, DataChangeScope.SUBTREE); + ListenerRegistration operReg = registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, path, asyncOperListener, DataChangeScope.SUBTREE); + + return new LegacyListenerRegistration(listener,cfgReg,operReg); + } + + @Override + public Registration, DataObject>> registerDataReader( + final InstanceIdentifier path, + final DataReader, DataObject> reader) { + throw new UnsupportedOperationException("Data reader contract is not supported."); + } + + @Override + public void close() throws Exception { + // TODO Auto-generated method stub + + } + + public ListenableFuture> commit(final ForwardedBackwardsCompatibleTransacion tx) { + + final List, DataObject>> subTrans = new ArrayList<>(); + LOG.debug("Tx: {} Submitted.",tx.getIdentifier()); + ListenableFuture requestCommit = executorService.submit(new Callable() { + + @Override + public Boolean call() throws Exception { + try { + for (CommitHandlerRegistrationImpl handler : commitHandlers.values()) { + + DataCommitTransaction, DataObject> subTx = handler + .getInstance().requestCommit(tx); + subTrans.add(subTx); + } + } catch (Exception e) { + LOG.error("Tx: {} Rollback.",tx.getIdentifier(),e); + for (DataCommitTransaction, DataObject> subTx : subTrans) { + subTx.rollback(); + } + return false; + } + LOG.debug("Tx: {} Can Commit True.",tx.getIdentifier()); + return true; + } + + }); + + ListenableFuture> dataStoreCommit = Futures.transform(requestCommit, new AsyncFunction>() { + + @Override + public ListenableFuture> apply(final Boolean requestCommitSuccess) throws Exception { + if(requestCommitSuccess) { + return tx.getDelegate().commit(); + } + return Futures.immediateFuture(Rpcs.getRpcResult(false, TransactionStatus.FAILED, Collections.emptySet())); + } + }); + + return Futures.transform(dataStoreCommit, new Function,RpcResult>() { + @Override + public RpcResult apply(final RpcResult input) { + if(input.isSuccessful()) { + for(DataCommitTransaction, DataObject> subTx : subTrans ) { + subTx.finish(); + } + } else { + LOG.error("Tx: {} Rollback - Datastore commit failed.",tx.getIdentifier()); + for(DataCommitTransaction, DataObject> subTx : subTrans ) { + subTx.rollback(); + } + } + return input; + } + }); + } + + private class ForwardedBackwardsCompatibleTransacion extends + AbstractForwardedTransaction implements DataModificationTransaction { + + private final Map, DataObject> updated = new HashMap<>(); + private final Map, DataObject> created = new HashMap<>(); + private final Set> removed = new HashSet<>(); + private final Map, 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 path, final DataObject data) { + + doPutWithEnsureParents(getDelegate(), LogicalDatastoreType.OPERATIONAL, path, data); + } + + @Override + public void putConfigurationData(final InstanceIdentifier 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 path) { + doDelete(getDelegate(), LogicalDatastoreType.OPERATIONAL, path); + + } + + @Override + public void removeConfigurationData(final InstanceIdentifier path) { + doDelete(getDelegate(), LogicalDatastoreType.CONFIGURATION, path); + } + + @Override + public Map, DataObject> getCreatedOperationalData() { + return Collections.emptyMap(); + } + + @Override + public Map, DataObject> getCreatedConfigurationData() { + return created; + } + + @Override + public Map, DataObject> getUpdatedOperationalData() { + return Collections.emptyMap(); + } + + @Override + public Map, DataObject> getUpdatedConfigurationData() { + return updated; + } + + @Override + public Set> getRemovedConfigurationData() { + return removed; + } + + @Override + public Set> getRemovedOperationalData() { + return Collections.emptySet(); + } + + @Override + public Map, DataObject> getOriginalConfigurationData() { + return original; + } + + @Override + public Map, DataObject> getOriginalOperationalData() { + return Collections.emptyMap(); + } + + @Override + public DataObject readOperationalData(final InstanceIdentifier 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 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> commit() { + final ListenableFuture> f = ForwardedBackwardsCompatibleDataBroker.this.commit(this); + + changeStatus(TransactionStatus.SUBMITED); + + Futures.addCallback(f, new FutureCallback>() { + @Override + public void onSuccess(RpcResult 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 registerListener(final DataTransactionListener listener) { + throw new UnsupportedOperationException(); + } + + } + + private class CommitHandlerRegistrationImpl extends + AbstractObjectRegistration, DataObject>> { + + private final InstanceIdentifier path; + + public CommitHandlerRegistrationImpl(final InstanceIdentifier path, + final DataCommitHandler, DataObject> commitHandler) { + super(commitHandler); + this.path = path; + } + + @Override + protected void removeRegistration() { + commitHandlers.remove(path, this); + } + + } + + + private static final class LegacyListenerRegistration implements ListenerRegistration { + + private final DataChangeListener instance; + private final ListenerRegistration cfgReg; + private final ListenerRegistration operReg; + + public LegacyListenerRegistration(final DataChangeListener listener, + final ListenerRegistration cfgReg, + final ListenerRegistration 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 { + + 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, DataObject> change) { + + DataChangeEvent legacyChange = LegacyDataChangeEvent.createOperational(change); + delegate.onDataChanged(legacyChange); + + } + + @Override + public DataChangeListener getDelegate() { + return (DataChangeListener) delegate; + } + + } + + private static class BackwardsCompatibleConfigurationDataChangeInvoker implements BindingDataChangeListener, Delegator { + + + @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, DataObject> change) { + + DataChangeEvent legacyChange = LegacyDataChangeEvent.createConfiguration(change); + + delegate.onDataChanged(legacyChange); + + } + + @Override + public DataChangeListener getDelegate() { + return (DataChangeListener) delegate; + } + + } +} diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/ForwardedBindingDataBroker.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/ForwardedBindingDataBroker.java new file mode 100644 index 0000000000..fb06b130ce --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/ForwardedBindingDataBroker.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.binding.impl; + +import org.opendaylight.controller.md.sal.binding.api.BindingDataBroker; +import org.opendaylight.controller.md.sal.binding.api.BindingDataReadTransaction; +import org.opendaylight.controller.md.sal.binding.api.BindingDataReadWriteTransaction; +import org.opendaylight.controller.md.sal.binding.api.BindingDataWriteTransaction; +import org.opendaylight.controller.md.sal.common.api.TransactionStatus; +import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; +import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction; +import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction; +import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService; + +import com.google.common.base.Optional; +import com.google.common.util.concurrent.ListenableFuture; + +/** + * The DataBrokerImpl simply defers to the DOMDataBroker for all its operations. + * All transactions and listener registrations are wrapped by the DataBrokerImpl + * to allow binding aware components to use the DataBroker transparently. + * + * Besides this the DataBrokerImpl and it's collaborators also cache data that + * is already transformed from the binding independent to binding aware format + * + * TODO : All references in this class to CompositeNode should be switched to + * NormalizedNode once the MappingService is updated + * + */ +public class ForwardedBindingDataBroker extends AbstractForwardedDataBroker implements BindingDataBroker { + + public ForwardedBindingDataBroker(final DOMDataBroker domDataBroker, final BindingIndependentMappingService mappingService) { + super(domDataBroker, mappingService); + } + + @Override + public BindingDataReadTransaction newReadOnlyTransaction() { + return new BindingDataReadTransactionImpl(getDelegate().newReadOnlyTransaction(),getCodec()); + } + + @Override + public BindingDataReadWriteTransaction newReadWriteTransaction() { + return new BindingDataReadWriteTransactionImpl(getDelegate().newReadWriteTransaction(),getCodec()); + } + + @Override + public BindingDataWriteTransaction newWriteOnlyTransaction() { + return new BindingDataWriteTransactionImpl(getDelegate().newWriteOnlyTransaction(),getCodec()); + } + + private abstract class AbstractBindingTransaction>> + extends AbstractForwardedTransaction implements AsyncTransaction, 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 implements + BindingDataReadTransaction { + + protected BindingDataReadTransactionImpl(final DOMDataReadTransaction delegate, + final BindingToNormalizedNodeCodec codec) { + super(delegate, codec); + } + + @Override + public ListenableFuture> read(final LogicalDatastoreType store, + final InstanceIdentifier path) { + return doRead(getDelegate(), store, path); + } + } + + private class BindingDataWriteTransactionImpl extends + AbstractBindingTransaction 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> commit() { + return doCommit(getDelegate()); + } + } + + private class BindingDataReadWriteTransactionImpl extends + BindingDataWriteTransactionImpl implements BindingDataReadWriteTransaction { + + protected BindingDataReadWriteTransactionImpl(final DOMDataReadWriteTransaction delegate, + final BindingToNormalizedNodeCodec codec) { + super(delegate, codec); + } + + @Override + public ListenableFuture> read(final LogicalDatastoreType store, + final InstanceIdentifier path) { + return doRead(getDelegate(), store, path); + } + } +} diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/LegacyDataChangeEvent.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/LegacyDataChangeEvent.java new file mode 100644 index 0000000000..8cb4a70f9c --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/LegacyDataChangeEvent.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.binding.impl; + +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; +import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public abstract class LegacyDataChangeEvent implements + DataChangeEvent, DataObject> { + + private LegacyDataChangeEvent() { + } + + public static final DataChangeEvent, DataObject> createOperational( + final AsyncDataChangeEvent, DataObject> change) { + return new OperationalChangeEvent(change); + } + + public static final DataChangeEvent, DataObject> createConfiguration( + final AsyncDataChangeEvent, DataObject> change) { + return new ConfigurationChangeEvent(change); + } + + @Override + public Map, DataObject> getCreatedOperationalData() { + return Collections.emptyMap(); + } + + @Override + public Map, DataObject> getCreatedConfigurationData() { + return Collections.emptyMap(); + } + + @Override + public Map, DataObject> getUpdatedOperationalData() { + return Collections.emptyMap(); + } + + @Override + public Map, DataObject> getUpdatedConfigurationData() { + return Collections.emptyMap(); + } + + @Override + public Set> getRemovedConfigurationData() { + return Collections.emptySet(); + } + + @Override + public Set> getRemovedOperationalData() { + return Collections.emptySet(); + } + + @Override + public Map, DataObject> getOriginalConfigurationData() { + return Collections.emptyMap(); + } + + @Override + public Map, 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, DataObject> delegate; + + public OperationalChangeEvent(final AsyncDataChangeEvent, DataObject> change) { + this.delegate = change; + } + + @Override + public Map, DataObject> getCreatedOperationalData() { + return delegate.getCreatedData(); + } + + @Override + public Set> getRemovedOperationalData() { + return delegate.getRemovedPaths(); + } + + @Override + public DataObject getOriginalOperationalSubtree() { + return delegate.getOriginalSubtree(); + } + + @Override + public DataObject getUpdatedOperationalSubtree() { + return delegate.getUpdatedSubtree(); + } + + @Override + public Map, DataObject> getOriginalOperationalData() { + return (Map) delegate.getOriginalData(); + } + + @Override + public Map, 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, DataObject> delegate; + + public ConfigurationChangeEvent(final AsyncDataChangeEvent, DataObject> change) { + this.delegate = change; + } + + @Override + public Map, DataObject> getCreatedConfigurationData() { + return delegate.getCreatedData(); + } + + @Override + public Set> getRemovedConfigurationData() { + return delegate.getRemovedPaths(); + } + + @Override + public DataObject getOriginalConfigurationSubtree() { + return delegate.getOriginalSubtree(); + } + + @Override + public DataObject getUpdatedConfigurationSubtree() { + return delegate.getUpdatedSubtree(); + } + + @Override + public Map, DataObject> getOriginalConfigurationData() { + return (Map) delegate.getOriginalData(); + } + + @Override + public Map, DataObject> getUpdatedConfigurationData() { + return delegate.getUpdatedData(); + } + + @Override + public String toString() { + return "ConfigurationChangeEvent [delegate=" + delegate + "]"; + } + + } + +} diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentConnector.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentConnector.java index e6e935c920..37c0dfa607 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentConnector.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentConnector.java @@ -28,6 +28,7 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; +import org.opendaylight.controller.md.sal.binding.impl.AbstractForwardedDataBroker; import org.opendaylight.controller.md.sal.common.api.RegistrationListener; import org.opendaylight.controller.md.sal.common.api.TransactionStatus; import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler; @@ -133,7 +134,7 @@ public class BindingIndependentConnector implements // private final Function, org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> toDOMInstanceIdentifier = new Function, org.opendaylight.yangtools.yang.data.api.InstanceIdentifier>() { @Override - public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier apply(InstanceIdentifier input) { + public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier apply(final InstanceIdentifier input) { return mappingService.toDataDom(input); } @@ -162,7 +163,7 @@ public class BindingIndependentConnector implements // } @Override - public DataObject readOperationalData(InstanceIdentifier path) { + public DataObject readOperationalData(final InstanceIdentifier path) { try { org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path); CompositeNode result = biDataService.readOperationalData(biPath); @@ -173,7 +174,7 @@ public class BindingIndependentConnector implements // } private DataObject potentialAugmentationRead(InstanceIdentifier 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 targetType = path.getTargetType(); if (Augmentation.class.isAssignableFrom(targetType)) { @@ -188,7 +189,7 @@ public class BindingIndependentConnector implements // } @Override - public DataObject readConfigurationData(InstanceIdentifier path) { + public DataObject readConfigurationData(final InstanceIdentifier path) { try { org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path); CompositeNode result = biDataService.readConfigurationData(biPath); @@ -199,7 +200,7 @@ public class BindingIndependentConnector implements // } private DataModificationTransaction createBindingToDomTransaction( - DataModification, DataObject> source) { + final DataModification, DataObject> source) { DataModificationTransaction target = biDataService.beginTransaction(); LOG.debug("Created DOM Transaction {} for {},", target.getIdentifier(),source.getIdentifier()); for (InstanceIdentifier entry : source.getRemovedConfigurationData()) { @@ -231,7 +232,7 @@ public class BindingIndependentConnector implements // } private org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction createDomToBindingTransaction( - DataModification source) { + final DataModification source) { org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction target = baDataService .beginTransaction(); for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedConfigurationData()) { @@ -280,7 +281,7 @@ public class BindingIndependentConnector implements // return biDataService; } - protected void setDomDataService(org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService) { + protected void setDomDataService(final org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService) { this.biDataService = biDataService; } @@ -288,7 +289,7 @@ public class BindingIndependentConnector implements // return baDataService; } - protected void setBindingDataService(DataProviderService baDataService) { + protected void setBindingDataService(final DataProviderService baDataService) { this.baDataService = baDataService; } @@ -296,11 +297,15 @@ public class BindingIndependentConnector implements // return baRpcRegistry; } - protected void setBindingRpcRegistry(RpcProviderRegistry rpcRegistry) { + protected void setBindingRpcRegistry(final RpcProviderRegistry rpcRegistry) { this.baRpcRegistry = rpcRegistry; } public void startDataForwarding() { + if(baDataService instanceof AbstractForwardedDataBroker) { + dataForwarding = true; + return; + } checkState(!dataForwarding, "Connector is already forwarding data."); baDataReaderRegistration = baDataService.registerDataReader(ROOT, this); baCommitHandlerRegistration = baDataService.registerCommitHandler(ROOT, bindingToDomCommitHandler); @@ -331,7 +336,7 @@ public class BindingIndependentConnector implements // } } - protected void setMappingService(BindingIndependentMappingService mappingService) { + protected void setMappingService(final BindingIndependentMappingService mappingService) { this.mappingService = mappingService; } @@ -341,17 +346,17 @@ public class BindingIndependentConnector implements // } @Override - public void onSessionInitiated(ProviderSession session) { + public void onSessionInitiated(final ProviderSession session) { setDomDataService(session.getService(org.opendaylight.controller.sal.core.api.data.DataProviderService.class)); setDomRpcRegistry(session.getService(RpcProvisionRegistry.class)); } - public void onRpcRouterCreated(Class serviceType, RpcRouter router) { + public void onRpcRouterCreated(final Class serviceType, final RpcRouter router) { } - public void setDomRpcRegistry(RpcProvisionRegistry registry) { + public void setDomRpcRegistry(final RpcProvisionRegistry registry) { biRpcRegistry = registry; } @@ -373,8 +378,8 @@ public class BindingIndependentConnector implements // private final DataModification modification; public DomToBindingTransaction( - org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing, - DataModification modification) { + final org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing, + final DataModification modification) { super(); this.backing = backing; this.modification = modification; @@ -412,8 +417,8 @@ public class BindingIndependentConnector implements // private final DataModificationTransaction backing; private final DataModification, DataObject> modification; - public BindingToDomTransaction(DataModificationTransaction backing, - DataModification, DataObject> modification) { + public BindingToDomTransaction(final DataModificationTransaction backing, + final DataModification, DataObject> modification) { this.backing = backing; this.modification = modification; domOpenedTransactions.put(backing.getIdentifier(), this); @@ -451,7 +456,7 @@ public class BindingIndependentConnector implements // @Override public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction, DataObject> requestCommit( - DataModification, DataObject> bindingTransaction) { + final DataModification, DataObject> bindingTransaction) { /** * Transaction was created as DOM transaction, in that case we do @@ -474,7 +479,7 @@ public class BindingIndependentConnector implements // DataCommitHandler { @Override - public void onRegister(DataCommitHandlerRegistration, DataObject> registration) { + public void onRegister(final DataCommitHandlerRegistration, DataObject> registration) { org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath = mappingService.toDataDom(registration .getPath()); @@ -482,14 +487,14 @@ public class BindingIndependentConnector implements // } @Override - public void onUnregister(DataCommitHandlerRegistration, DataObject> registration) { + public void onUnregister(final DataCommitHandlerRegistration, 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 requestCommit( - DataModification domTransaction) { + final DataModification domTransaction) { Object identifier = domTransaction.getIdentifier(); /** @@ -527,34 +532,34 @@ public class BindingIndependentConnector implements // return registryImpl; } - public void setRegistryImpl(RpcProviderRegistryImpl registryImpl) { + public void setRegistryImpl(final RpcProviderRegistryImpl registryImpl) { this.registryImpl = registryImpl; } @Override - public void onGlobalRpcRegistered(Class cls) { + public void onGlobalRpcRegistered(final Class cls) { getRpcForwarder(cls, null); } @Override - public void onGlobalRpcUnregistered(Class cls) { + public void onGlobalRpcUnregistered(final Class cls) { // NOOP } @Override - public void onRpcRouterCreated(RpcRouter router) { + public void onRpcRouterCreated(final RpcRouter router) { Class ctx = router.getContexts().iterator().next(); getRpcForwarder(router.getServiceType(), ctx); } @Override - public void onRouteChange(RouteChange> change) { + public void onRouteChange(final RouteChange> change) { for (Entry>> entry : change.getAnnouncements().entrySet()) { bindingRoutesAdded(entry); } } - private void bindingRoutesAdded(Entry>> entry) { + private void bindingRoutesAdded(final Entry>> entry) { Class context = entry.getKey().getRoutingContext(); Class service = entry.getKey().getRpcService(); if (context != null) { @@ -562,8 +567,8 @@ public class BindingIndependentConnector implements // } } - private DomToBindingRpcForwarder getRpcForwarder(Class service, - Class context) { + private DomToBindingRpcForwarder getRpcForwarder(final Class service, + final Class context) { DomToBindingRpcForwarder potential = forwarders.get(service); if (potential != null) { return potential; @@ -588,7 +593,7 @@ public class BindingIndependentConnector implements // private final Map strategiesByQName = new HashMap<>(); private final WeakHashMap strategiesByMethod = new WeakHashMap<>(); - public DomToBindingRpcForwarder(Class service) { + public DomToBindingRpcForwarder(final Class service) { this.rpcServiceType = new WeakReference>(service); this.supportedRpcs = mappingService.getRpcQNamesFor(service); try { @@ -611,7 +616,7 @@ public class BindingIndependentConnector implements // * @param service * @param context */ - public DomToBindingRpcForwarder(Class service, Class context) { + public DomToBindingRpcForwarder(final Class service, final Class context) { this.rpcServiceType = new WeakReference>(service); this.supportedRpcs = mappingService.getRpcQNamesFor(service); Builder registrationsBuilder = ImmutableSet @@ -630,8 +635,8 @@ public class BindingIndependentConnector implements // registrations = registrationsBuilder.build(); } - public void registerPaths(Class context, Class service, - Set> set) { + public void registerPaths(final Class context, final Class service, + final Set> set) { QName ctx = BindingReflections.findQName(context); for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier path : FluentIterable.from(set).transform( toDOMInstanceIdentifier)) { @@ -643,7 +648,7 @@ public class BindingIndependentConnector implements // @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { if (EQUALS_METHOD.equals(method)) { return false; } @@ -657,8 +662,8 @@ public class BindingIndependentConnector implements // return strategy.forwardToDomBroker(null); } - public void removePaths(Class context, Class service, - Set> set) { + public void removePaths(final Class context, final Class service, + final Set> set) { QName ctx = BindingReflections.findQName(context); for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier path : FluentIterable.from(set).transform( toDOMInstanceIdentifier)) { @@ -686,7 +691,7 @@ public class BindingIndependentConnector implements // } @Override - public RpcResult invokeRpc(QName rpc, CompositeNode domInput) { + public RpcResult invokeRpc(final QName rpc, final CompositeNode domInput) { checkArgument(rpc != null); checkArgument(domInput != null); @@ -702,7 +707,7 @@ public class BindingIndependentConnector implements // } } - private RpcInvocationStrategy resolveInvocationStrategy(QName rpc) { + private RpcInvocationStrategy resolveInvocationStrategy(final QName rpc) { return strategiesByQName.get(rpc); } @@ -750,7 +755,7 @@ public class BindingIndependentConnector implements // protected final Method targetMethod; protected final QName rpc; - public RpcInvocationStrategy(QName rpc, Method targetMethod) { + public RpcInvocationStrategy(final QName rpc, final Method targetMethod) { this.targetMethod = targetMethod; this.rpc = rpc; } @@ -760,7 +765,7 @@ public class BindingIndependentConnector implements // public abstract RpcResult uncheckedInvoke(RpcService rpcService, CompositeNode domInput) throws Exception; - public RpcResult invokeOn(RpcService rpcService, CompositeNode domInput) throws Exception { + public RpcResult invokeOn(final RpcService rpcService, final CompositeNode domInput) throws Exception { return uncheckedInvoke(rpcService, domInput); } } @@ -774,8 +779,8 @@ public class BindingIndependentConnector implements // private final WeakReference outputClass; @SuppressWarnings({ "rawtypes", "unchecked" }) - public DefaultInvocationStrategy(QName rpc, Method targetMethod, Class outputClass, - Class inputClass) { + public DefaultInvocationStrategy(final QName rpc, final Method targetMethod, final Class outputClass, + final Class inputClass) { super(rpc, targetMethod); this.outputClass = new WeakReference(outputClass); this.inputClass = new WeakReference(inputClass); @@ -783,7 +788,7 @@ public class BindingIndependentConnector implements // @SuppressWarnings("unchecked") @Override - public RpcResult uncheckedInvoke(RpcService rpcService, CompositeNode domInput) throws Exception { + public RpcResult uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput) throws Exception { DataContainer bindingInput = mappingService.dataObjectFromDataDom(inputClass.get(), domInput); Future> futureResult = (Future>) targetMethod.invoke(rpcService, bindingInput); if (futureResult == null) { @@ -799,7 +804,7 @@ public class BindingIndependentConnector implements // } @Override - public Future> forwardToDomBroker(DataObject input) { + public Future> forwardToDomBroker(final DataObject input) { if(biRpcRegistry != null) { CompositeNode xml = mappingService.toDataDom(input); CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc, ImmutableList.> of(xml)); @@ -818,12 +823,12 @@ public class BindingIndependentConnector implements // private class NoInputNoOutputInvocationStrategy extends RpcInvocationStrategy { - public NoInputNoOutputInvocationStrategy(QName rpc, Method targetMethod) { + public NoInputNoOutputInvocationStrategy(final QName rpc, final Method targetMethod) { super(rpc, targetMethod); } @Override - public RpcResult uncheckedInvoke(RpcService rpcService, CompositeNode domInput) throws Exception { + public RpcResult uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput) throws Exception { @SuppressWarnings("unchecked") Future> result = (Future>) targetMethod.invoke(rpcService); RpcResult bindingResult = result.get(); @@ -831,7 +836,7 @@ public class BindingIndependentConnector implements // } @Override - public Future> forwardToDomBroker(DataObject input) { + public Future> forwardToDomBroker(final DataObject input) { return Futures.immediateFuture(null); } } @@ -843,15 +848,15 @@ public class BindingIndependentConnector implements // private final WeakReference inputClass; @SuppressWarnings({ "rawtypes", "unchecked" }) - public NoOutputInvocationStrategy(QName rpc, Method targetMethod, - Class inputClass) { + public NoOutputInvocationStrategy(final QName rpc, final Method targetMethod, + final Class inputClass) { super(rpc,targetMethod); this.inputClass = new WeakReference(inputClass); } @Override - public RpcResult uncheckedInvoke(RpcService rpcService, CompositeNode domInput) throws Exception { + public RpcResult uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput) throws Exception { DataContainer bindingInput = mappingService.dataObjectFromDataDom(inputClass.get(), domInput); Future> result = (Future>) targetMethod.invoke(rpcService, bindingInput); if (result == null) { @@ -862,7 +867,7 @@ public class BindingIndependentConnector implements // } @Override - public Future> forwardToDomBroker(DataObject input) { + public Future> forwardToDomBroker(final DataObject input) { if(biRpcRegistry != null) { CompositeNode xml = mappingService.toDataDom(input); CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc,ImmutableList.>of(xml)); @@ -892,12 +897,12 @@ public class BindingIndependentConnector implements // return mappingService; } - public void setBindingNotificationService(NotificationProviderService baService) { + public void setBindingNotificationService(final NotificationProviderService baService) { this.baNotifyService = baService; } - public void setDomNotificationService(NotificationPublishService domService) { + public void setDomNotificationService(final NotificationPublishService domService) { this.domNotificationService = domService; } @@ -912,7 +917,7 @@ public class BindingIndependentConnector implements // } @Override - public void onNotification(CompositeNode notification) { + public void onNotification(final CompositeNode notification) { QName qname = notification.getNodeType(); WeakReference> potential = notifications.get(qname); if (potential != null) { @@ -929,7 +934,7 @@ public class BindingIndependentConnector implements // } @Override - public void onNotificationSubscribtion(Class notificationType) { + public void onNotificationSubscribtion(final Class notificationType) { QName qname = BindingReflections.findQName(notificationType); if (qname != null) { WeakReference> already = notifications.putIfAbsent(qname, diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/forward/DomForwardedBroker.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/forward/DomForwardedBroker.java index 8d6f331452..db98b456f0 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/forward/DomForwardedBroker.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/forward/DomForwardedBroker.java @@ -10,12 +10,12 @@ package org.opendaylight.controller.sal.binding.impl.forward; import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentConnector; import org.opendaylight.controller.sal.core.api.Broker.ProviderSession; -interface DomForwardedBroker { +public interface DomForwardedBroker { public BindingIndependentConnector getConnector(); - + public void setConnector(BindingIndependentConnector connector); - + public void setDomProviderContext(ProviderSession domProviderContext); public ProviderSession getDomProviderContext(); diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/yang/opendaylight-binding-broker-impl.yang b/opendaylight/md-sal/sal-binding-broker/src/main/yang/opendaylight-binding-broker-impl.yang index b95cb73f1c..428025a58d 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/yang/opendaylight-binding-broker-impl.yang +++ b/opendaylight/md-sal/sal-binding-broker/src/main/yang/opendaylight-binding-broker-impl.yang @@ -1,5 +1,5 @@ module opendaylight-sal-binding-broker-impl { - yang-version 1; + yang-version 1; namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl"; prefix "binding-impl"; @@ -10,7 +10,7 @@ module opendaylight-sal-binding-broker-impl { description "Service definition for Binding Aware MD-SAL."; - + revision "2013-10-28" { description "Initial revision"; @@ -28,20 +28,27 @@ module opendaylight-sal-binding-broker-impl { config:provided-service sal:binding-rpc-registry; config:java-name-prefix BindingBrokerImpl; } - + identity binding-data-broker { base config:module-type; config:provided-service sal:binding-data-broker; config:provided-service sal:binding-data-consumer-broker; config:java-name-prefix DataBrokerImpl; } - + + identity binding-data-compatible-broker { + base config:module-type; + config:provided-service sal:binding-data-broker; + config:provided-service sal:binding-data-consumer-broker; + config:java-name-prefix ForwardedCompatibleDataBrokerImpl; + } + identity binding-rpc-broker { base config:module-type; config:provided-service sal:binding-rpc-registry; config:java-name-prefix RpcBrokerImpl; } - + identity binding-notification-broker { base config:module-type; config:provided-service sal:binding-notification-service; @@ -58,7 +65,7 @@ module opendaylight-sal-binding-broker-impl { augment "/config:modules/config:module/config:configuration" { case binding-broker-impl { when "/config:modules/config:module/config:type = 'binding-broker-impl'"; - + /* container rpc-registry { uses config:service-ref { @@ -68,7 +75,7 @@ module opendaylight-sal-binding-broker-impl { } } }*/ - + container data-broker { uses config:service-ref { refine type { @@ -77,7 +84,7 @@ module opendaylight-sal-binding-broker-impl { } } } - + container notification-service { uses config:service-ref { refine type { @@ -108,10 +115,34 @@ module opendaylight-sal-binding-broker-impl { config:required-identity binding-dom-mapping-service; } } - } + } + } + } + + augment "/config:modules/config:module/config:configuration" { + case binding-data-compatible-broker { + when "/config:modules/config:module/config:type = 'binding-data-compatible-broker'"; + + container dom-async-broker { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity dom:dom-broker-osgi-registry; + } + } + } + + container binding-mapping-service { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity binding-dom-mapping-service; + } + } + } } } - + augment "/config:modules/config:module/config:state" { case runtime-generated-mapping { @@ -139,4 +170,4 @@ module opendaylight-sal-binding-broker-impl { uses common:notification-state; } } -} \ No newline at end of file +} diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java index 2e43b88553..4bad2bbb86 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java @@ -17,7 +17,9 @@ import java.util.concurrent.Future; import javassist.ClassPool; +import org.opendaylight.controller.md.sal.binding.impl.ForwardedBackwardsCompatibleDataBroker; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; import org.opendaylight.controller.md.sal.dom.broker.impl.DOMDataBrokerImpl; import org.opendaylight.controller.md.sal.dom.broker.impl.compat.BackwardsCompatibleDataBroker; import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore; @@ -107,6 +109,10 @@ public class BindingTestContext implements AutoCloseable, SchemaContextProvider private final List schemaListeners = new ArrayList<>(); + private DataProviderService baData; + + private DOMDataBroker newDOMDataBroker; + @Override public SchemaContext getSchemaContext() { return schemaContext; @@ -152,9 +158,9 @@ public class BindingTestContext implements AutoCloseable, SchemaContextProvider .put(LogicalDatastoreType.CONFIGURATION, configStore) .build(); - DOMDataBrokerImpl newBiDataImpl = new DOMDataBrokerImpl(newDatastores, executor); + newDOMDataBroker = new DOMDataBrokerImpl(newDatastores, executor); - biCompatibleBroker = new BackwardsCompatibleDataBroker(newBiDataImpl); + biCompatibleBroker = new BackwardsCompatibleDataBroker(newDOMDataBroker); schemaListeners.add(configStore); schemaListeners.add(operStore); @@ -166,24 +172,25 @@ public class BindingTestContext implements AutoCloseable, SchemaContextProvider checkState(executor != null, "Executor needs to be set"); baDataImpl = new DataBrokerImpl(); baDataImpl.setExecutor(executor); + baData = baDataImpl; } public void startBindingBroker() { checkState(executor != null, "Executor needs to be set"); - checkState(baDataImpl != null, "Binding Data Broker must be started"); + checkState(baData != null, "Binding Data Broker must be started"); checkState(baNotifyImpl != null, "Notification Service must be started"); baBrokerImpl = new DomForwardedBindingBrokerImpl("test"); baBrokerImpl.getMountManager().setDataCommitExecutor(executor); baBrokerImpl.getMountManager().setNotificationExecutor(executor); baBrokerImpl.setRpcBroker(new RpcProviderRegistryImpl("test")); - baBrokerImpl.setDataBroker(baDataImpl); + baBrokerImpl.setDataBroker(baData); baBrokerImpl.setNotificationBroker(baNotifyImpl); baBrokerImpl.start(); } public void startForwarding() { - checkState(baDataImpl != null, "Binding Data Broker needs to be started"); + checkState(baData != null, "Binding Data Broker needs to be started"); checkState(biDataLegacyBroker != null, "DOM Data Broker needs to be started."); checkState(mappingServiceImpl != null, "DOM Mapping Service needs to be started."); @@ -315,19 +322,27 @@ public class BindingTestContext implements AutoCloseable, SchemaContextProvider } public void start() { - startBindingDataBroker(); - startBindingNotificationBroker(); - startBindingBroker(); startNewDomDataBroker(); startDomBroker(); startDomMountPoint(); startBindingToDomMappingService(); + startNewBindingDataBroker(); + + startBindingNotificationBroker(); + startBindingBroker(); + startForwarding(); if (startWithSchema) { loadYangSchemaFromClasspath(); } } + public void startNewBindingDataBroker() { + ForwardedBackwardsCompatibleDataBroker forwarded = new ForwardedBackwardsCompatibleDataBroker(newDOMDataBroker, mappingServiceImpl, executor); + schemaListeners.add(forwarded); + baData = forwarded; + } + private void startDomMountPoint() { biMountImpl = new MountPointManagerImpl(); biMountImpl.setDataBroker(getDomDataBroker()); @@ -353,7 +368,7 @@ public class BindingTestContext implements AutoCloseable, SchemaContextProvider } public DataProviderService getBindingDataBroker() { - return baDataImpl; + return baData; } public org.opendaylight.controller.sal.core.api.data.DataProviderService getDomDataBroker() { diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug02Test.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug02Test.java index 929eb66350..6784c0cc91 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug02Test.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug02Test.java @@ -7,6 +7,9 @@ */ package org.opendaylight.controller.sal.binding.test.bugfix; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + import java.util.Collections; import java.util.Map; import java.util.concurrent.Callable; @@ -16,29 +19,24 @@ import java.util.concurrent.Future; import javassist.ClassPool; -import org.junit.Ignore; import org.junit.Test; import org.opendaylight.controller.md.sal.common.api.TransactionStatus; +import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest; import org.opendaylight.controller.sal.binding.test.util.BindingBrokerTestFactory; -import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.RpcResult; -import org.opendaylight.yangtools.yang.model.api.SchemaContext; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; -import static org.junit.Assert.*; - public class DOMCodecBug02Test extends AbstractDataServiceTest { private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id"); @@ -68,12 +66,13 @@ public class DOMCodecBug02Test extends AbstractDataServiceTest { private static final NodeRef NODE_REF = new NodeRef(NODE_INSTANCE_ID_BA); /** - * This test is ignored, till found out better way to test generation - * of classes without leaking of instances from previous run - * + * This test is ignored, till found out better way to test generation of + * classes without leaking of instances from previous run + * * @throws Exception */ - + + @Override public void setUp() { ListeningExecutorService executor = MoreExecutors.sameThreadExecutor(); BindingBrokerTestFactory factory = new BindingBrokerTestFactory(); @@ -82,33 +81,33 @@ public class DOMCodecBug02Test extends AbstractDataServiceTest { factory.setStartWithParsedSchema(getStartWithSchema()); testContext = factory.getTestContext(); testContext.start(); - + baDataService = testContext.getBindingDataBroker(); biDataService = testContext.getDomDataBroker(); dataStore = testContext.getDomDataStore(); mappingService = testContext.getBindingToDomMappingService(); }; - + @Test public void testSchemaContextNotAvailable() throws Exception { ExecutorService testExecutor = Executors.newFixedThreadPool(1); testContext.loadYangSchemaFromClasspath(); - Future>> future = testExecutor.submit(new Callable>>() { - @Override - public Future> call() throws Exception { - NodesBuilder nodesBuilder = new NodesBuilder(); - nodesBuilder.setNode(Collections. emptyList()); - DataModificationTransaction transaction = baDataService.beginTransaction(); - transaction.putOperationalData(NODES_INSTANCE_ID_BA, nodesBuilder.build()); - return transaction.commit(); - } - }); - - + Future>> future = testExecutor + .submit(new Callable>>() { + @Override + public Future> call() throws Exception { + NodesBuilder nodesBuilder = new NodesBuilder(); + nodesBuilder.setNode(Collections. emptyList()); + DataModificationTransaction transaction = baDataService.beginTransaction(); + transaction.putOperationalData(NODES_INSTANCE_ID_BA, nodesBuilder.build()); + return transaction.commit(); + } + }); + RpcResult result = future.get().get(); assertEquals(TransactionStatus.COMMITED, result.getResult()); - + Nodes nodes = checkForNodes(); assertNotNull(nodes); @@ -118,7 +117,7 @@ public class DOMCodecBug02Test extends AbstractDataServiceTest { return (Nodes) baDataService.readOperationalData(NODES_INSTANCE_ID_BA); } - + @Override protected boolean getStartWithSchema() { return false; diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java index 6a050efb35..e89371337e 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java @@ -14,6 +14,7 @@ import static org.junit.Assert.assertNull; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.concurrent.TimeUnit; import org.junit.Test; import org.opendaylight.controller.md.sal.common.api.TransactionStatus; @@ -43,6 +44,8 @@ import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import com.google.common.util.concurrent.SettableFuture; + public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataChangeListener { private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id"); @@ -85,7 +88,7 @@ public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataCh .node(SUPPORTED_ACTIONS_QNAME) // .toInstance(); - private DataChangeEvent, DataObject> receivedChangeEvent; + private final SettableFuture, DataObject>> receivedChangeEvent = SettableFuture.create(); @@ -120,9 +123,10 @@ public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataCh RpcResult result = transaction.commit().get(); assertEquals(TransactionStatus.COMMITED, result.getResult()); - assertNotNull(receivedChangeEvent); + DataChangeEvent, DataObject> potential = receivedChangeEvent.get(1000,TimeUnit.MILLISECONDS); + assertNotNull(potential); - verifyNodes((Nodes) receivedChangeEvent.getUpdatedOperationalSubtree(),original); + verifyNodes((Nodes) potential.getUpdatedOperationalSubtree(),original); assertBindingIndependentVersion(NODE_INSTANCE_ID_BI); Nodes nodes = checkForNodes(); verifyNodes(nodes,original); @@ -186,7 +190,7 @@ public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataCh assertNull(node); } - private void verifyNodes(Nodes nodes,Node original) { + private void verifyNodes(final Nodes nodes,final Node original) { assertNotNull(nodes); assertNotNull(nodes.getNode()); assertEquals(1, nodes.getNode().size()); @@ -203,7 +207,7 @@ public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataCh } private void assertBindingIndependentVersion( - org.opendaylight.yangtools.yang.data.api.InstanceIdentifier nodeId) { + final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier nodeId) { CompositeNode node = biDataService.readOperationalData(nodeId); assertNotNull(node); } @@ -213,8 +217,8 @@ public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataCh } @Override - public void onDataChanged(DataChangeEvent, DataObject> change) { - receivedChangeEvent = change; + public void onDataChanged(final DataChangeEvent, DataObject> change) { + receivedChangeEvent.set(change); } } diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/PutAugmentationTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/PutAugmentationTest.java index 90fa2be211..027a8eeb9f 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/PutAugmentationTest.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/PutAugmentationTest.java @@ -14,7 +14,9 @@ import static org.junit.Assert.assertTrue; import java.util.Collections; import java.util.Map; +import java.util.concurrent.TimeUnit; +import org.junit.Ignore; import org.junit.Test; import org.opendaylight.controller.md.sal.common.api.TransactionStatus; import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent; @@ -41,6 +43,8 @@ import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import com.google.common.util.concurrent.SettableFuture; + public class PutAugmentationTest extends AbstractDataServiceTest implements DataChangeListener { private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id"); @@ -89,7 +93,7 @@ public class PutAugmentationTest extends AbstractDataServiceTest implements Data .augmentation(FlowCapableNode.class) // .build(); - private DataChangeEvent, DataObject> lastReceivedChangeEvent; + private SettableFuture, DataObject>> lastReceivedChangeEvent; /** * Test for Bug 148 @@ -97,8 +101,9 @@ public class PutAugmentationTest extends AbstractDataServiceTest implements Data * @throws Exception */ @Test + @Ignore public void putNodeAndAugmentation() throws Exception { - + lastReceivedChangeEvent = SettableFuture.create(); baDataService.registerDataChangeListener(ALL_FLOW_CAPABLE_NODES, this); @@ -126,11 +131,16 @@ public class PutAugmentationTest extends AbstractDataServiceTest implements Data DataModificationTransaction augmentedTransaction = baDataService.beginTransaction(); augmentedTransaction.putOperationalData(augmentIdentifier, fnu); + + lastReceivedChangeEvent = SettableFuture.create(); result = augmentedTransaction.commit().get(); assertEquals(TransactionStatus.COMMITED, result.getResult()); - assertNotNull(lastReceivedChangeEvent); - assertTrue(lastReceivedChangeEvent.getCreatedOperationalData().containsKey(FLOW_AUGMENTATION_PATH)); + DataChangeEvent, DataObject> potential = lastReceivedChangeEvent.get(1000,TimeUnit.MILLISECONDS); + assertNotNull(potential); + assertTrue(potential.getCreatedOperationalData().containsKey(FLOW_AUGMENTATION_PATH)); + + lastReceivedChangeEvent = SettableFuture.create(); Node augmentedNode = (Node) baDataService.readOperationalData(NODE_INSTANCE_ID_BA); assertNotNull(node); @@ -141,12 +151,13 @@ public class PutAugmentationTest extends AbstractDataServiceTest implements Data assertEquals(fnu.getDescription(), readedAugmentation.getDescription()); assertBindingIndependentVersion(NODE_INSTANCE_ID_BI); testNodeRemove(); - assertTrue(lastReceivedChangeEvent.getRemovedOperationalData().contains(FLOW_AUGMENTATION_PATH)); + assertTrue(lastReceivedChangeEvent.get(1000,TimeUnit.MILLISECONDS).getRemovedOperationalData().contains(FLOW_AUGMENTATION_PATH)); } @Test + @Ignore public void putNodeWithAugmentation() throws Exception { - + lastReceivedChangeEvent = SettableFuture.create(); baDataService.registerDataChangeListener(ALL_FLOW_CAPABLE_NODES, this); NodeBuilder nodeBuilder = new NodeBuilder(); @@ -165,9 +176,11 @@ public class PutAugmentationTest extends AbstractDataServiceTest implements Data baseTransaction.putOperationalData(NODE_INSTANCE_ID_BA, nodeBuilder.build()); RpcResult result = baseTransaction.commit().get(); - assertNotNull(lastReceivedChangeEvent); - assertTrue(lastReceivedChangeEvent.getCreatedOperationalData().containsKey(FLOW_AUGMENTATION_PATH)); - lastReceivedChangeEvent = null; + + DataChangeEvent, DataObject> potential = lastReceivedChangeEvent.get(1000,TimeUnit.MILLISECONDS); + assertNotNull(potential); + assertTrue(potential.getCreatedOperationalData().containsKey(FLOW_AUGMENTATION_PATH)); + lastReceivedChangeEvent = SettableFuture.create(); assertEquals(TransactionStatus.COMMITED, result.getResult()); FlowCapableNode readedAugmentation = (FlowCapableNode) baDataService.readOperationalData(InstanceIdentifier @@ -177,10 +190,10 @@ public class PutAugmentationTest extends AbstractDataServiceTest implements Data assertEquals(fnu.getHardware(), readedAugmentation.getHardware()); testPutNodeConnectorWithAugmentation(); - lastReceivedChangeEvent = null; + lastReceivedChangeEvent = SettableFuture.create(); testNodeRemove(); - assertTrue(lastReceivedChangeEvent.getRemovedOperationalData().contains(FLOW_AUGMENTATION_PATH)); + assertTrue(lastReceivedChangeEvent.get(1000,TimeUnit.MILLISECONDS).getRemovedOperationalData().contains(FLOW_AUGMENTATION_PATH)); } private void testPutNodeConnectorWithAugmentation() throws Exception { @@ -218,7 +231,7 @@ public class PutAugmentationTest extends AbstractDataServiceTest implements Data assertNull(node); } - private void verifyNodes(Nodes nodes, Node original) { + private void verifyNodes(final Nodes nodes, final Node original) { assertNotNull(nodes); assertNotNull(nodes.getNode()); assertEquals(1, nodes.getNode().size()); @@ -234,7 +247,7 @@ public class PutAugmentationTest extends AbstractDataServiceTest implements Data } - private void assertBindingIndependentVersion(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier nodeId) { + private void assertBindingIndependentVersion(final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier nodeId) { CompositeNode node = biDataService.readOperationalData(nodeId); assertNotNull(node); } @@ -244,8 +257,8 @@ public class PutAugmentationTest extends AbstractDataServiceTest implements Data } @Override - public void onDataChanged(DataChangeEvent, DataObject> change) { - lastReceivedChangeEvent = change; + public void onDataChanged(final DataChangeEvent, DataObject> change) { + lastReceivedChangeEvent.set(change); } } diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java index 6f938b15ed..1661ff230d 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java @@ -15,14 +15,13 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.concurrent.TimeUnit; -import org.junit.Ignore; import org.junit.Test; import org.opendaylight.controller.md.sal.common.api.TransactionStatus; -import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler; -import org.opendaylight.controller.md.sal.common.api.data.DataModification; +import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent; +import org.opendaylight.controller.sal.binding.api.data.DataChangeListener; import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest; -import org.opendaylight.controller.sal.common.util.CommitHandlerTransactions; import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpVersion; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix; @@ -53,17 +52,21 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder; -import org.opendaylight.yangtools.concepts.Registration; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.common.collect.ImmutableMap; +import com.google.common.util.concurrent.SettableFuture; public class ChangeOriginatedInDomBrokerTest extends AbstractDataServiceTest { + private static final Logger LOG = LoggerFactory.getLogger(ChangeOriginatedInDomBrokerTest.class); + private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id"); private static final QName FLOW_ID_QNAME = QName.create(Flow.QNAME, "id"); private static final QName FLOW_NODE_QNAME = QName.create(Flow.QNAME, "node"); @@ -76,7 +79,7 @@ public class ChangeOriginatedInDomBrokerTest extends AbstractDataServiceTest { private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID)); private static final FlowKey FLOW_KEY = new FlowKey(FLOW_ID); - private DataModification, DataObject> modificationCapture; + private final SettableFuture, DataObject>> modificationCapture = SettableFuture.create(); private static final Map NODE_KEY_BI = Collections. singletonMap(NODE_ID_QNAME, NODE_ID); @@ -119,40 +122,36 @@ public class ChangeOriginatedInDomBrokerTest extends AbstractDataServiceTest { .toInstance(); @Test - @Ignore public void simpleModifyOperation() throws Exception { assertNull(biDataService.readConfigurationData(FLOW_INSTANCE_ID_BI)); - registerCommitHandler(); + registerChangeListener(); CompositeNode domflow = createTestFlow(); DataModificationTransaction biTransaction = biDataService.beginTransaction(); biTransaction.putConfigurationData(FLOW_INSTANCE_ID_BI, domflow); RpcResult biResult = biTransaction.commit().get(); assertEquals(TransactionStatus.COMMITED, biResult.getResult()); - assertNotNull(modificationCapture); - Flow flow = (Flow) modificationCapture.getCreatedConfigurationData().get(FLOW_INSTANCE_ID_BA); + DataChangeEvent, 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, DataObject> flowTestCommitHandler = new DataCommitHandler, DataObject>() { + private void registerChangeListener() { + baDataService.registerDataChangeListener(FLOWS_PATH_BA, new DataChangeListener() { @Override - public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction, DataObject> requestCommit( - final DataModification, DataObject> modification) { - modificationCapture = modification; - return CommitHandlerTransactions.allwaysSuccessfulTransaction(modification); + public void onDataChanged(final DataChangeEvent, DataObject> change) { + LOG.info("Data Change listener invoked."); + modificationCapture.set(change); } - - }; - Registration, DataObject>> registration = baDataService - .registerCommitHandler(FLOWS_PATH_BA, flowTestCommitHandler); - assertNotNull(registration); + }); } private CompositeNode createTestFlow() { @@ -195,6 +194,7 @@ public class ChangeOriginatedInDomBrokerTest extends AbstractDataServiceTest { // Wrap our Apply Action in an Instruction InstructionBuilder ib = new InstructionBuilder(); + ib.setOrder(0); ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build()); // Put our Instruction in a list of Instructions