Fix warnings/javadocs in sal-distributed-datastore
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / datastore / entityownership / EntityOwnershipListenerSupport.java
1 /*
2  * Copyright (c) 2015 Brocade Communications 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.entityownership;
9
10 import akka.actor.ActorContext;
11 import akka.actor.ActorRef;
12 import akka.actor.PoisonPill;
13 import com.google.common.collect.HashMultimap;
14 import com.google.common.collect.Multimap;
15 import java.util.Collection;
16 import java.util.Collections;
17 import java.util.HashSet;
18 import java.util.IdentityHashMap;
19 import java.util.Map;
20 import java.util.Set;
21 import org.opendaylight.mdsal.eos.common.api.EntityOwnershipChangeState;
22 import org.opendaylight.mdsal.eos.dom.api.DOMEntity;
23 import org.opendaylight.mdsal.eos.dom.api.DOMEntityOwnershipChange;
24 import org.opendaylight.mdsal.eos.dom.api.DOMEntityOwnershipListener;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 /**
29  * Manages EntityOwnershipListener registrations and notifications for the EntityOwnershipShard.
30  *
31  * @author Thomas Pantelis
32  */
33 class EntityOwnershipListenerSupport {
34     private static final Logger LOG = LoggerFactory.getLogger(EntityOwnershipListenerSupport.class);
35
36     private final String logId;
37     private final ActorContext actorContext;
38     private final Map<DOMEntityOwnershipListener, ListenerActorRefEntry> listenerActorMap = new IdentityHashMap<>();
39     private final Set<DOMEntity> entitiesWithCandidateSet = new HashSet<>();
40     private final Multimap<String, DOMEntityOwnershipListener> entityTypeListenerMap = HashMultimap.create();
41     private volatile boolean inJeopardy = false;
42
43     EntityOwnershipListenerSupport(ActorContext actorContext, String logId) {
44         this.actorContext = actorContext;
45         this.logId = logId;
46     }
47
48     String getLogId() {
49         return logId;
50     }
51
52     /**
53      * Set the in-jeopardy flag and indicate its previous state.
54      *
55      * @param inJeopardy new value of the in-jeopardy flag
56      * @return Previous value of the flag.
57      */
58     boolean setInJeopardy(final boolean inJeopardy) {
59         final boolean wasInJeopardy = this.inJeopardy;
60         this.inJeopardy = inJeopardy;
61         return wasInJeopardy;
62     }
63
64     boolean hasCandidateForEntity(DOMEntity entity) {
65         return entitiesWithCandidateSet.contains(entity);
66     }
67
68     void setHasCandidateForEntity(DOMEntity entity) {
69         entitiesWithCandidateSet.add(entity);
70     }
71
72     void unsetHasCandidateForEntity(DOMEntity entity) {
73         entitiesWithCandidateSet.remove(entity);
74     }
75
76     void addEntityOwnershipListener(String entityType, DOMEntityOwnershipListener listener) {
77         LOG.debug("{}: Adding EntityOwnershipListener {} for entity type {}", logId, listener, entityType);
78
79         addListener(listener, entityType);
80     }
81
82     void removeEntityOwnershipListener(String entityType, DOMEntityOwnershipListener listener) {
83         LOG.debug("{}: Removing EntityOwnershipListener {} for entity type {}", logId, listener, entityType);
84
85         removeListener(listener, entityType);
86     }
87
88     void notifyEntityOwnershipListeners(DOMEntity entity, boolean wasOwner, boolean isOwner, boolean hasOwner) {
89         notifyListeners(entity, entity.getType(), wasOwner, isOwner, hasOwner);
90     }
91
92     void notifyEntityOwnershipListener(DOMEntity entity, boolean wasOwner, boolean isOwner, boolean hasOwner,
93             DOMEntityOwnershipListener listener) {
94         notifyListeners(entity, wasOwner, isOwner, hasOwner, Collections.singleton(listener));
95     }
96
97     private void notifyListeners(DOMEntity entity, String mapKey, boolean wasOwner, boolean isOwner, boolean hasOwner) {
98         Collection<DOMEntityOwnershipListener> listeners = entityTypeListenerMap.get(mapKey);
99         if (!listeners.isEmpty()) {
100             notifyListeners(entity, wasOwner, isOwner, hasOwner, listeners);
101         }
102     }
103
104     private void notifyListeners(DOMEntity entity, boolean wasOwner, boolean isOwner, boolean hasOwner,
105             Collection<DOMEntityOwnershipListener> listeners) {
106         DOMEntityOwnershipChange changed = new DOMEntityOwnershipChange(entity,
107                 EntityOwnershipChangeState.from(wasOwner, isOwner, hasOwner), inJeopardy);
108         for (DOMEntityOwnershipListener listener: listeners) {
109             ActorRef listenerActor = listenerActorFor(listener);
110
111             LOG.debug("{}: Notifying EntityOwnershipListenerActor {} with {}", logId, listenerActor, changed);
112
113             listenerActor.tell(changed, ActorRef.noSender());
114         }
115     }
116
117     private void addListener(DOMEntityOwnershipListener listener, String mapKey) {
118         if (entityTypeListenerMap.put(mapKey, listener)) {
119             ListenerActorRefEntry listenerEntry = listenerActorMap.get(listener);
120             if (listenerEntry == null) {
121                 listenerActorMap.put(listener, new ListenerActorRefEntry());
122             } else {
123                 listenerEntry.referenceCount++;
124             }
125         }
126     }
127
128     private void removeListener(DOMEntityOwnershipListener listener, String mapKey) {
129         if (entityTypeListenerMap.remove(mapKey, listener)) {
130             ListenerActorRefEntry listenerEntry = listenerActorMap.get(listener);
131
132             LOG.debug("{}: Found {}", logId, listenerEntry);
133
134             listenerEntry.referenceCount--;
135             if (listenerEntry.referenceCount <= 0) {
136                 listenerActorMap.remove(listener);
137
138                 if (listenerEntry.actorRef != null) {
139                     LOG.debug("Killing EntityOwnershipListenerActor {}", listenerEntry.actorRef);
140                     listenerEntry.actorRef.tell(PoisonPill.getInstance(), ActorRef.noSender());
141                 }
142             }
143         }
144     }
145
146     private ActorRef listenerActorFor(DOMEntityOwnershipListener listener) {
147         return listenerActorMap.get(listener).actorFor(listener);
148     }
149
150     private class ListenerActorRefEntry {
151         ActorRef actorRef;
152         int referenceCount = 1;
153
154         ActorRef actorFor(DOMEntityOwnershipListener listener) {
155             if (actorRef == null) {
156                 actorRef = actorContext.actorOf(EntityOwnershipListenerActor.props(listener));
157
158                 LOG.debug("{}: Created EntityOwnershipListenerActor {} for listener {}", logId, actorRef, listener);
159             }
160
161             return actorRef;
162         }
163
164         @Override
165         public String toString() {
166             return "ListenerActorRefEntry [actorRef=" + actorRef + ", referenceCount=" + referenceCount + "]";
167         }
168     }
169 }