From: Harman Singh Date: Fri, 24 Jul 2015 01:32:46 +0000 (-0700) Subject: Enabling Data Change Notifications for all nodes in cluster. X-Git-Tag: release/beryllium~149^2~6 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=a0c515cd53c82031ca63c195fd2eea1f17ee5ac1;p=mdsal.git Enabling Data Change Notifications for all nodes in cluster. Two new interfaces are introduced ClusteredDataChangeListener and ClusteredDOMDataChangeListener and external applications will have to implement any of that interface, if those applications want to listen to remote data change notifications. Datastore registers listeners, which are instance of that interface, even on followers. Change-Id: I0e29cdf2a08a2051de5fc8ce73b9ec8ac408e45b Signed-off-by: Harman Singh --- diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/ClusteredDataChangeListener.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/ClusteredDataChangeListener.java new file mode 100644 index 0000000000..511910de62 --- /dev/null +++ b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/ClusteredDataChangeListener.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015 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.api; + +/** + *

+ * ClusteredDataChangeListener is a marker interface to enable data change notifications on all instances in a cluster, + * where this listener is registered. + *

+ * + *

Applications should implement ClusteredDataChangeListener instead of DataChangeListener, if they want to listen + * to data change notifications on any node of clustered datastore. DataChangeListener enables data change notifications + * only at leader of the datastore shard.

+ * + */ + +public interface ClusteredDataChangeListener extends DataChangeListener{ +} diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/DataChangeListener.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/DataChangeListener.java index 65257a328a..2833f41f67 100644 --- a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/DataChangeListener.java +++ b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/DataChangeListener.java @@ -12,6 +12,10 @@ import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListene import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +/* + * DataChangeListener enables data change notifications only at leader of the datastore shard + */ + public interface DataChangeListener extends AsyncDataChangeListener, DataObject> { @Override void onDataChanged(AsyncDataChangeEvent, DataObject> change); 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 index 4bbeaebf55..ad52557b47 100644 --- 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 @@ -15,12 +15,15 @@ import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set; + +import org.opendaylight.controller.md.sal.binding.api.ClusteredDataChangeListener; import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; 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.md.sal.dom.api.ClusteredDOMDataChangeListener; import org.opendaylight.controller.sal.core.api.model.SchemaService; import org.opendaylight.yangtools.concepts.AbstractListenerRegistration; import org.opendaylight.yangtools.concepts.Delegator; @@ -63,8 +66,14 @@ public abstract class AbstractForwardedDataBroker implements Delegator registerDataChangeListener(final LogicalDatastoreType store, final InstanceIdentifier path, final DataChangeListener listener, final DataChangeScope triggeringScope) { - final DOMDataChangeListener domDataChangeListener = new TranslatingDataChangeInvoker(store, path, listener, + final DOMDataChangeListener domDataChangeListener; + + if(listener instanceof ClusteredDataChangeListener) { + domDataChangeListener = new TranslatingClusteredDataChangeInvoker(store, path, listener, triggeringScope); + } else { + domDataChangeListener = new TranslatingDataChangeInvoker(store, path, listener, triggeringScope); + } final YangInstanceIdentifier domPath = codec.toYangInstanceIdentifierBlocking(path); final ListenerRegistration domRegistration = domDataBroker.registerDataChangeListener(store, domPath, domDataChangeListener, triggeringScope); @@ -140,6 +149,20 @@ public abstract class AbstractForwardedDataBroker implements Delegator path, + DataChangeListener bindingDataChangeListener, + DataChangeScope triggeringScope) { + super(store, path, bindingDataChangeListener, triggeringScope); + } + } + private class TranslatedDataChangeEvent implements AsyncDataChangeEvent, DataObject> { private final AsyncDataChangeEvent> domEvent; private final InstanceIdentifier path; diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/BindingDOMDataBrokerAdapterTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/BindingDOMDataBrokerAdapterTest.java new file mode 100644 index 0000000000..e2fcebaac1 --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/BindingDOMDataBrokerAdapterTest.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2015 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.test; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.opendaylight.controller.md.sal.binding.api.ClusteredDataChangeListener; +import org.opendaylight.controller.md.sal.binding.impl.BindingDOMDataBrokerAdapter; +import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker; +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.ClusteredDOMDataChangeListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top; +import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry; +import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; + + +public class BindingDOMDataBrokerAdapterTest { + + @Mock + DOMDataBroker dataBroker; + + @Mock + GeneratedClassLoadingStrategy classLoadingStrategy; + @Mock + BindingNormalizedNodeCodecRegistry codecRegistry; + + @Mock + YangInstanceIdentifier yangInstanceIdentifier; + + + private static final InstanceIdentifier TOP_PATH = InstanceIdentifier + .create(Top.class); + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testClusteredDataChangeListernerRegisteration() { + + BindingToNormalizedNodeCodec codec = new BindingToNormalizedNodeCodec(classLoadingStrategy, codecRegistry); + + BindingDOMDataBrokerAdapter bindingDOMDataBrokerAdapter = new BindingDOMDataBrokerAdapter(dataBroker, codec); + Mockito.when(codecRegistry.toYangInstanceIdentifier(TOP_PATH)).thenReturn(yangInstanceIdentifier); + + ArgumentCaptor clusteredDOMListener = ArgumentCaptor. + forClass(ClusteredDOMDataChangeListener.class); + ArgumentCaptor logicalDatastoreType = ArgumentCaptor.forClass(LogicalDatastoreType.class); + ArgumentCaptor dataChangeScope = ArgumentCaptor. + forClass(AsyncDataBroker.DataChangeScope.class); + ArgumentCaptor yangInstanceIdentifier = ArgumentCaptor. + forClass(YangInstanceIdentifier.class); + + TestListener listener = new TestListener(); + + bindingDOMDataBrokerAdapter.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, TOP_PATH, listener, + AsyncDataBroker.DataChangeScope.BASE); + Mockito.verify(dataBroker).registerDataChangeListener(logicalDatastoreType.capture(), yangInstanceIdentifier.capture(), + clusteredDOMListener.capture(), dataChangeScope.capture()); + + } + + private class TestListener implements ClusteredDataChangeListener { + + @Override + public void onDataChanged(AsyncDataChangeEvent, DataObject> change) { + + } + } +} diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/ClusteredDOMDataChangeListener.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/ClusteredDOMDataChangeListener.java new file mode 100644 index 0000000000..e5dbc545e5 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/ClusteredDOMDataChangeListener.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2015 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.dom.api; + +/** + *

ClusteredDOMDataChangeListener is a marker interface to enable data change notifications on all instances in a cluster, + * where this listener is registered.

+ * + * + *

Applications should implement ClusteredDOMDataChangeListener instead of DOMDataChangeListener, if they want to listen + * to data change notifications on any node of clustered datastore. DOMDataChangeListener enables data change notifications + * only at leader of the datastore shard.

+ * + */ + +public interface ClusteredDOMDataChangeListener extends DOMDataChangeListener{ + +} diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataChangeListener.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataChangeListener.java index 393d1eaafe..c46529bd02 100644 --- a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataChangeListener.java +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataChangeListener.java @@ -11,6 +11,10 @@ import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListene import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +/** + * DOMDataChangeListener enables data change notifications only at leader of the datastore shard. + */ + public interface DOMDataChangeListener extends AsyncDataChangeListener> { }