Define DataStoreVersions.MAGNESIUM_VERSION
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / datastore / DataTreeChangeListenerActor.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.controller.cluster.datastore;
9
10 import static java.util.Objects.requireNonNull;
11
12 import akka.actor.Props;
13 import org.opendaylight.controller.cluster.common.actor.AbstractUntypedActor;
14 import org.opendaylight.controller.cluster.datastore.messages.DataTreeChanged;
15 import org.opendaylight.controller.cluster.datastore.messages.DataTreeChangedReply;
16 import org.opendaylight.controller.cluster.datastore.messages.DataTreeListenerInfo;
17 import org.opendaylight.controller.cluster.datastore.messages.EnableNotification;
18 import org.opendaylight.controller.cluster.datastore.messages.GetInfo;
19 import org.opendaylight.controller.cluster.datastore.messages.OnInitialData;
20 import org.opendaylight.mdsal.dom.api.DOMDataTreeChangeListener;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
22
23 /**
24  * Proxy actor which acts as a facade to the user-provided listener. Responsible for decapsulating
25  * DataTreeChanged messages and dispatching their context to the user.
26  */
27 final class DataTreeChangeListenerActor extends AbstractUntypedActor {
28     private final DOMDataTreeChangeListener listener;
29     private final YangInstanceIdentifier registeredPath;
30     private boolean notificationsEnabled = false;
31     private long notificationCount;
32     private String logContext = "";
33
34     private DataTreeChangeListenerActor(final DOMDataTreeChangeListener listener,
35             final YangInstanceIdentifier registeredPath) {
36         this.listener = requireNonNull(listener);
37         this.registeredPath = requireNonNull(registeredPath);
38     }
39
40     @Override
41     protected void handleReceive(final Object message) {
42         if (message instanceof DataTreeChanged) {
43             dataChanged((DataTreeChanged)message);
44         } else if (message instanceof OnInitialData) {
45             onInitialData();
46         } else if (message instanceof EnableNotification) {
47             enableNotification((EnableNotification) message);
48         } else if (message instanceof GetInfo) {
49             getSender().tell(new DataTreeListenerInfo(listener.toString(), registeredPath.toString(),
50                     notificationsEnabled, notificationCount), getSelf());
51         } else {
52             unknownMessage(message);
53         }
54     }
55
56     @SuppressWarnings("checkstyle:IllegalCatch")
57     private void onInitialData() {
58         LOG.debug("{}: Notifying onInitialData to listener {}", logContext, listener);
59
60         try {
61             this.listener.onInitialData();
62         } catch (Exception e) {
63             LOG.error("{}: Error notifying listener {}", logContext, this.listener, e);
64         }
65     }
66
67     @SuppressWarnings("checkstyle:IllegalCatch")
68     private void dataChanged(final DataTreeChanged message) {
69         // Do nothing if notifications are not enabled
70         if (!notificationsEnabled) {
71             LOG.debug("{}: Notifications not enabled for listener {} - dropping change notification",
72                     logContext, listener);
73             return;
74         }
75
76         LOG.debug("{}: Sending {} change notification(s) {} to listener {}", logContext, message.getChanges().size(),
77                 message.getChanges(), listener);
78
79         notificationCount++;
80
81         try {
82             this.listener.onDataTreeChanged(message.getChanges());
83         } catch (Exception e) {
84             LOG.error("{}: Error notifying listener {}", logContext, this.listener, e);
85         }
86
87         // TODO: do we really need this?
88         // It seems the sender is never null but it doesn't hurt to check. If the caller passes in
89         // a null sender (ActorRef.noSender()), akka translates that to the deadLetters actor.
90         if (getSender() != null && !getContext().system().deadLetters().equals(getSender())) {
91             getSender().tell(DataTreeChangedReply.getInstance(), getSelf());
92         }
93     }
94
95     private void enableNotification(final EnableNotification message) {
96         logContext = message.getLogContext();
97         notificationsEnabled = message.isEnabled();
98         LOG.debug("{}: {} notifications for listener {}", logContext, notificationsEnabled ? "Enabled" : "Disabled",
99                 listener);
100     }
101
102     public static Props props(final DOMDataTreeChangeListener listener, final YangInstanceIdentifier registeredPath) {
103         return Props.create(DataTreeChangeListenerActor.class, listener, registeredPath);
104     }
105 }