<groupId>org.opendaylight.openflowplugin.model</groupId>
<artifactId>model-flow-statistics</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>openflowplugin-common</artifactId>
+ </dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
package org.opendaylight.openflowplugin.applications.statistics.manager;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
* org.opendaylight.openflowplugin.applications.statistics.manager
*
* StatListeningCommiter
- * Definition Interface for {@link DataChangeListener} implementer class rule.
+ * Definition Interface for {@link DataTreeChangeListener} implementer class rule.
* Interface represent a contract between Config/DataStore changes and
* Operational/DataStore commits. All Operational/DataStore commit have
* to by represent as RPC Device response Notification processing. So
*
* Created: Aug 27, 2014
*/
-public interface StatListeningCommiter<T extends DataObject, N extends NotificationListener> extends DataChangeListener, StatNotifyCommiter<N> {
+public interface StatListeningCommiter<T extends DataObject, N extends NotificationListener> extends DataTreeChangeListener<T>, StatNotifyCommiter<N> {
/**
*
* StatNodeRegistration
* Class represents {@link org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode}
- * {@link org.opendaylight.controller.md.sal.binding.api.DataChangeListener} in Operational/DataStore for ADD / REMOVE
+ * {@link org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener} in Operational/DataStore for ADD / REMOVE
* actions which are represented connect / disconnect OF actions. Connect functionality are expecting
*
* @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+
+import java.util.Collection;
import java.util.Map;
+import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-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.binding.api.*;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
import org.opendaylight.openflowplugin.applications.statistics.manager.StatListeningCommiter;
import org.opendaylight.openflowplugin.applications.statistics.manager.StatNodeRegistration;
import org.opendaylight.openflowplugin.applications.statistics.manager.StatisticsManager;
+import org.opendaylight.openflowplugin.common.wait.SimpleTaskRetryLooper;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
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.binding.NotificationListener;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger LOG = LoggerFactory.getLogger(StatAbstractListenCommit.class);
- private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private ListenerRegistration<StatAbstractListenCommit<T, N>> listenerRegistration;
protected final Map<InstanceIdentifier<Node>, Map<InstanceIdentifier<T>, Integer>> mapNodesForDelete = new ConcurrentHashMap<>();
protected final Map<InstanceIdentifier<Node>, Integer> mapNodeFeautureRepeater = new ConcurrentHashMap<>();
private ReadOnlyTransaction currentReadTx;
private volatile boolean currentReadTxStale;
+ private static final int STARTUP_LOOP_TICK = 500;
+ private static final int STARTUP_LOOP_MAX_RETRIES = 8;
+
+ private final DataTreeIdentifier<T> treeId =
+ new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, getWildCardedRegistrationPath());
+
/* Constructor has to make a registration */
public StatAbstractListenCommit(final StatisticsManager manager, final DataBroker db,
final NotificationProviderService nps, final Class<T> clazz, final StatNodeRegistration nodeRegistrationManager) {
super(manager,nps, nodeRegistrationManager);
this.clazz = Preconditions.checkNotNull(clazz, "Referenced Class can not be null");
Preconditions.checkArgument(db != null, "DataBroker can not be null!");
- listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
- getWildCardedRegistrationPath(), this, DataChangeScope.BASE);
this.dataBroker = db;
this.nodeRegistrationManager = nodeRegistrationManager;
+
+ SimpleTaskRetryLooper looper = new SimpleTaskRetryLooper(STARTUP_LOOP_TICK, STARTUP_LOOP_MAX_RETRIES);
+ try{
+ listenerRegistration = looper.loopUntilNoException(new Callable<ListenerRegistration<StatAbstractListenCommit<T, N>>>() {
+ @Override
+ public ListenerRegistration<StatAbstractListenCommit<T, N>> call() throws Exception {
+ return db.registerDataTreeChangeListener(treeId,StatAbstractListenCommit.this);
+ }
+ });
+ }catch(final Exception ex){
+ LOG.debug(" StatAbstractListenCommit DataChange listener registration failed {}", ex.getMessage());
+ throw new IllegalStateException("Notification supplier startup fail! System needs restart.", ex);
+ }
}
/**
* Method returns WildCarded Path which is used for registration as a listening path changes in
- * {@link org.opendaylight.controller.md.sal.binding.api.DataChangeListener}
+ * {@link org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener}
* @return
*/
protected abstract InstanceIdentifier<T> getWildCardedRegistrationPath();
@Override
- public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvent) {
- Preconditions.checkNotNull(changeEvent,"Async ChangeEvent can not be null!");
-
+ public void onDataTreeChanged(Collection<DataTreeModification<T>> changes) {
+ Preconditions.checkNotNull(changes, "Changes must not be null!");
/*
* If we have opened read transaction for configuration data store, we need to mark it as stale.
*
* org.opendaylight.openflowplugin.applications.statistics.manager.impl
*
* StatListenCommitFlow
- * Class is a NotifyListener for FlowStatistics and DataChangeListener for Config/DataStore for Flow node.
+ * Class is a NotifyListener for FlowStatistics and DataTreeChangeListener for Config/DataStore for Flow node.
* All expected (registered) FlowStatistics will be builded and commit to Operational/DataStore.
* DataChangeEven should call create/delete Flow in Operational/DS create process needs to pair
* Device Flow HashCode and FlowId from Config/DS
* org.opendaylight.openflowplugin.applications.statistics.manager.impl
*
* StatListenCommitGroup
- * Class is a NotifyListener for GroupStatistics and DataChangeListener for Config/DataStore for Group node.
+ * Class is a NotifyListener for GroupStatistics and DataTreeChangeListener for Config/DataStore for Group node.
* All expected (registered) GroupStatistics will be builded and commit to Operational/DataStore.
* DataChangeEven should call create/delete Group in Operational/DS
*
* org.opendaylight.openflowplugin.applications.statistics.manager.impl
*
* StatListenCommitMeter
- * Class is a NotifyListener for MeterStatistics and DataChangeListener for Config/DataStore for Meter node.
+ * Class is a NotifyListener for MeterStatistics and DataTreeChangeListener for Config/DataStore for Meter node.
* All expected (registered) MeterStatistics will be builded and commit to Operational/DataStore.
* DataChangeEven should call create/delete Meter in Operational/DS
*
import org.mockito.stubbing.Answer;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-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.common.api.data.ReadFailedException;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.NotificationListener;
+import java.util.ArrayList;
+
+
/**
* Unit tests for StatAbstractListenCommit.
*
@Override
public CheckedFuture<Optional<DataObject>, ReadFailedException> answer(
InvocationOnMock unused) {
- statCommit.onDataChanged(mock(AsyncDataChangeEvent.class));
+ statCommit.onDataTreeChanged(new ArrayList<>());
return Futures.immediateCheckedFuture(expected1);
}
};
import static org.junit.Assert.assertTrue;
import com.google.common.base.Optional;
+
+import java.util.Collection;
import java.util.concurrent.ExecutionException;
import org.junit.Test;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.binding.api.*;
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.common.api.data.ReadFailedException;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
final InstanceIdentifier<Table> tableII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
.augmentation(FlowCapableNode.class).child(Table.class, new TableKey(flow.getTableId()));
- getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
- tableII.child(Flow.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
+ getDataBroker().registerDataTreeChangeListener( new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
+ tableII.child(Flow.class)), new ChangeListener());
synchronized (waitObject) {
waitObject.wait();
final InstanceIdentifier<Group> groupII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
.augmentation(FlowCapableNode.class).child(Group.class, getGroup().getKey());
- getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
- groupII.augmentation(NodeGroupStatistics.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
+ getDataBroker().registerDataTreeChangeListener( new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
+ groupII.augmentation(NodeGroupStatistics.class)), new ChangeListener());
synchronized (waitObject) {
waitObject.wait();
final InstanceIdentifier<Group> groupII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
.augmentation(FlowCapableNode.class).child(Group.class, getGroup().getKey());
- getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
- groupII.augmentation(NodeGroupStatistics.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
+ getDataBroker().registerDataTreeChangeListener( new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
+ groupII.augmentation(NodeGroupStatistics.class)), new ChangeListener());
synchronized (waitObject) {
waitObject.wait();
final InstanceIdentifier<Meter> meterII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
.augmentation(FlowCapableNode.class).child(Meter.class, getMeter().getKey());
- getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
- meterII.augmentation(NodeMeterStatistics.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
+ getDataBroker().registerDataTreeChangeListener( new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
+ meterII.augmentation(NodeMeterStatistics.class)), new ChangeListener());
synchronized (waitObject) {
waitObject.wait();
writeTx.put(LogicalDatastoreType.OPERATIONAL, queueII, qBuilder.build());
assertCommit(writeTx.submit());
- getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
- queueII.augmentation(FlowCapableNodeConnectorQueueStatisticsData.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
+ getDataBroker().registerDataTreeChangeListener( new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
+ queueII.augmentation(FlowCapableNodeConnectorQueueStatisticsData.class)), new ChangeListener());
synchronized (waitObject) {
waitObject.wait();
writeTx.put(LogicalDatastoreType.OPERATIONAL, nodeConnectorII, ncBuilder.build());
assertCommit(writeTx.submit());
- getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
- nodeConnectorII.augmentation(FlowCapableNodeConnectorStatisticsData.class),
- new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
+ getDataBroker().registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
+ nodeConnectorII.augmentation(FlowCapableNodeConnectorStatisticsData.class)), new ChangeListener());
synchronized (waitObject) {
waitObject.wait();
final InstanceIdentifier<Table> tableII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
.augmentation(FlowCapableNode.class).child(Table.class, new TableKey(tableId.getValue()));
- getDataBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
- tableII.augmentation(FlowTableStatisticsData.class), new ChangeListener(), AsyncDataBroker.DataChangeScope.BASE);
+ getDataBroker().registerDataTreeChangeListener( new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
+ tableII.augmentation(FlowTableStatisticsData.class)), new ChangeListener());
synchronized (waitObject) {
waitObject.wait();
flowTableStatisticsDataOptional.get().getFlowTableStatistics().getPacketsLookedUp());
}
- public class ChangeListener implements DataChangeListener {
+ public class ChangeListener<T extends DataObject> implements DataTreeChangeListener<T> {
@Override
- public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+ public void onDataTreeChanged(final Collection<DataTreeModification<T>> changes){
synchronized (waitObject) {
waitObject.notify();
}
}
+
}
}