BUG-7033: Fix commit exception due to pipe-lining
[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 akka.actor.Props;
11 import akka.japi.Creator;
12 import com.google.common.base.Preconditions;
13 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
14 import org.opendaylight.controller.cluster.common.actor.AbstractUntypedActor;
15 import org.opendaylight.controller.cluster.datastore.messages.DataTreeChanged;
16 import org.opendaylight.controller.cluster.datastore.messages.DataTreeChangedReply;
17 import org.opendaylight.controller.cluster.datastore.messages.EnableNotification;
18 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeListener;
19
20 /**
21  * Proxy actor which acts as a facade to the user-provided listener. Responsible for decapsulating
22  * DataTreeChanged messages and dispatching their context to the user.
23  */
24 final class DataTreeChangeListenerActor extends AbstractUntypedActor {
25     private final DOMDataTreeChangeListener listener;
26     private boolean notificationsEnabled = false;
27
28     private DataTreeChangeListenerActor(final DOMDataTreeChangeListener listener) {
29         this.listener = Preconditions.checkNotNull(listener);
30     }
31
32     @Override
33     protected void handleReceive(final Object message) {
34         if (message instanceof DataTreeChanged) {
35             dataChanged((DataTreeChanged)message);
36         } else if (message instanceof EnableNotification) {
37             enableNotification((EnableNotification) message);
38         } else {
39             unknownMessage(message);
40         }
41     }
42
43     @SuppressWarnings("checkstyle:IllegalCatch")
44     private void dataChanged(final DataTreeChanged message) {
45         // Do nothing if notifications are not enabled
46         if (!notificationsEnabled) {
47             LOG.debug("Notifications not enabled for listener {} - dropping change notification", listener);
48             return;
49         }
50
51         LOG.debug("Sending change notification {} to listener {}", message.getChanges(), listener);
52
53         try {
54             this.listener.onDataTreeChanged(message.getChanges());
55         } catch (Exception e) {
56             LOG.error("Error notifying listener {}", this.listener, e);
57         }
58
59         // TODO: do we really need this?
60         // It seems the sender is never null but it doesn't hurt to check. If the caller passes in
61         // a null sender (ActorRef.noSender()), akka translates that to the deadLetters actor.
62         if (getSender() != null && !getContext().system().deadLetters().equals(getSender())) {
63             getSender().tell(DataTreeChangedReply.getInstance(), getSelf());
64         }
65     }
66
67     private void enableNotification(final EnableNotification message) {
68         notificationsEnabled = message.isEnabled();
69         LOG.debug("{} notifications for listener {}", notificationsEnabled ? "Enabled" : "Disabled",
70                 listener);
71     }
72
73     public static Props props(final DOMDataTreeChangeListener listener) {
74         return Props.create(new DataTreeChangeListenerCreator(listener));
75     }
76
77     private static final class DataTreeChangeListenerCreator implements Creator<DataTreeChangeListenerActor> {
78         private static final long serialVersionUID = 1L;
79
80         @SuppressFBWarnings(value = "SE_BAD_FIELD", justification = "This field is not Serializable but we don't "
81                 + "create remote instances of this actor and thus don't need it to be Serializable.")
82         private final DOMDataTreeChangeListener listener;
83
84         DataTreeChangeListenerCreator(final DOMDataTreeChangeListener listener) {
85             this.listener = Preconditions.checkNotNull(listener);
86         }
87
88         @Override
89         public DataTreeChangeListenerActor create() {
90             return new DataTreeChangeListenerActor(listener);
91         }
92     }
93 }