2 * Copyright (c) 2015 Brocade Communications Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.controller.cluster.datastore.entityownership;
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.IdentityHashMap;
18 import org.opendaylight.controller.cluster.datastore.entityownership.messages.EntityOwnershipChanged;
19 import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
20 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListener;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
25 * Manages EntityOwnershipListener registrations and notifications for the EntityOwnershipShard.
27 * @author Thomas Pantelis
29 class EntityOwnershipListenerSupport {
30 private static final Logger LOG = LoggerFactory.getLogger(EntityOwnershipListenerSupport.class);
32 private final ActorContext actorContext;
33 private final Map<EntityOwnershipListener, ListenerActorRefEntry> listenerActorMap = new IdentityHashMap<>();
34 private final Multimap<Entity, EntityOwnershipListener> entityListenerMap = HashMultimap.create();
36 EntityOwnershipListenerSupport(ActorContext actorContext) {
37 this.actorContext = actorContext;
40 void addEntityOwnershipListener(Entity entity, EntityOwnershipListener listener) {
41 LOG.debug("Adding EntityOwnershipListener {} for {}", listener, entity);
43 if(entityListenerMap.put(entity, listener)) {
44 ListenerActorRefEntry listenerEntry = listenerActorMap.get(listener);
45 if(listenerEntry == null) {
46 listenerActorMap.put(listener, new ListenerActorRefEntry());
48 listenerEntry.referenceCount++;
53 void removeEntityOwnershipListener(Entity entity, EntityOwnershipListener listener) {
54 LOG.debug("Removing EntityOwnershipListener {} for {}", listener, entity);
56 if(entityListenerMap.remove(entity, listener)) {
57 ListenerActorRefEntry listenerEntry = listenerActorMap.get(listener);
59 LOG.debug("Found {}", listenerEntry);
61 listenerEntry.referenceCount--;
62 if(listenerEntry.referenceCount <= 0) {
63 listenerActorMap.remove(listener);
65 if(listenerEntry.actorRef != null) {
66 LOG.debug("Killing EntityOwnershipListenerActor {}", listenerEntry.actorRef);
67 listenerEntry.actorRef.tell(PoisonPill.getInstance(), ActorRef.noSender());
73 void notifyEntityOwnershipListeners(Entity entity, boolean wasOwner, boolean isOwner) {
74 Collection<EntityOwnershipListener> listeners = entityListenerMap.get(entity);
75 if(listeners.isEmpty()) {
79 EntityOwnershipChanged changed = new EntityOwnershipChanged(entity, wasOwner, isOwner);
80 for(EntityOwnershipListener listener: listeners) {
81 ActorRef listenerActor = listenerActorFor(listener);
83 LOG.debug("Notifying EntityOwnershipListenerActor {} with {}", listenerActor,changed);
85 listenerActor.tell(changed, ActorRef.noSender());
89 private ActorRef listenerActorFor(EntityOwnershipListener listener) {
90 return listenerActorMap.get(listener).actorFor(listener);
93 private class ListenerActorRefEntry {
95 int referenceCount = 1;
97 ActorRef actorFor(EntityOwnershipListener listener) {
98 if(actorRef == null) {
99 actorRef = actorContext.actorOf(EntityOwnershipListenerActor.props(listener));
101 LOG.debug("Created EntityOwnershipListenerActor {} for listener {}", actorRef, listener);
108 public String toString() {
109 return "ListenerActorRefEntry [actorRef=" + actorRef + ", referenceCount=" + referenceCount + "]";