Add MXBean to report shard registered DTCL/DCL info
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / datastore / DataChangeListener.java
index fd4f9f75b5bd801aaa1fd9484c3e0b01a8d522ae..f0c6595ac4cbbb8d2bdfea00503728b09c21d326 100644 (file)
@@ -9,44 +9,86 @@
 package org.opendaylight.controller.cluster.datastore;
 
 import akka.actor.Props;
-import akka.japi.Creator;
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.cluster.common.actor.AbstractUntypedActor;
 import org.opendaylight.controller.cluster.datastore.messages.DataChanged;
 import org.opendaylight.controller.cluster.datastore.messages.DataChangedReply;
+import org.opendaylight.controller.cluster.datastore.messages.DataTreeListenerInfo;
+import org.opendaylight.controller.cluster.datastore.messages.EnableNotification;
+import org.opendaylight.controller.cluster.datastore.messages.GetInfo;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 
+/**
+ * Actor for a DataChangeListener.
+ *
+ * @deprecated Replaced by {@link DataTreeChangeListener}
+ */
+@Deprecated
 public class DataChangeListener extends AbstractUntypedActor {
-    private final AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>> listener;
+    private final AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>> listener;
+    private final YangInstanceIdentifier registeredPath;
+    private boolean notificationsEnabled = false;
+    private long notificationCount;
 
-    public DataChangeListener(
-        AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>> listener) {
-        this.listener = listener;
+    public DataChangeListener(AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>> listener,
+            final YangInstanceIdentifier registeredPath) {
+        this.listener = Preconditions.checkNotNull(listener, "listener should not be null");
+        this.registeredPath = Preconditions.checkNotNull(registeredPath);
     }
 
-    @Override public void handleReceive(Object message) throws Exception {
-        if(message instanceof DataChanged){
-            DataChanged reply = (DataChanged) message;
-            AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>>
-                change = reply.getChange();
-            this.listener.onDataChanged(change);
+    @Override
+    public void handleReceive(Object message) {
+        if (message instanceof DataChanged) {
+            dataChanged(message);
+        } else if (message instanceof EnableNotification) {
+            enableNotification((EnableNotification) message);
+        } else if (message instanceof GetInfo) {
+            getSender().tell(new DataTreeListenerInfo(listener.toString(), registeredPath.toString(),
+                    notificationsEnabled, notificationCount), getSelf());
+        } else {
+            unknownMessage(message);
+        }
+    }
+
+    private void enableNotification(EnableNotification message) {
+        notificationsEnabled = message.isEnabled();
+        LOG.debug("{} notifications for listener {}", notificationsEnabled ? "Enabled" : "Disabled",
+                listener);
+    }
 
-            if(getSender() != null){
-                getSender().tell(new DataChangedReply(), getSelf());
-            }
+    @SuppressWarnings("checkstyle:IllegalCatch")
+    private void dataChanged(Object message) {
 
+        // Do nothing if notifications are not enabled
+        if (!notificationsEnabled) {
+            LOG.debug("Notifications not enabled for listener {} - dropping change notification", listener);
+            return;
         }
-    }
 
-    public static Props props(final AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>> listener) {
-        return Props.create(new Creator<DataChangeListener>() {
-            @Override
-            public DataChangeListener create() throws Exception {
-                return new DataChangeListener(listener);
-            }
+        DataChanged reply = (DataChanged) message;
+        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change = reply.getChange();
 
-        });
+        LOG.debug("Sending change notification {} to listener {}", change, listener);
+
+        notificationCount++;
+
+        try {
+            this.listener.onDataChanged(change);
+        } catch (RuntimeException e) {
+            LOG.error(String.format("Error notifying listener %s", this.listener), e);
+        }
+
+        if (isValidSender(getSender())) {
+            getSender().tell(DataChangedReply.INSTANCE, getSelf());
+        }
+    }
 
+    public static Props props(final AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>> listener,
+            final YangInstanceIdentifier registeredPath) {
+        return Props.create(DataChangeListener.class, listener, registeredPath);
     }
 }