X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-distributed-datastore%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fcluster%2Fdatastore%2FAbstractDataListenerSupport.java;h=5a09b87da19f1e5b360761b1e64d05f00d793737;hp=a253b794db15871f69117f291be14ef4d1193a23;hb=e78622411319748472b5d9edab14eb6dc92cf6b1;hpb=6050fd28f2def659abb5bc9d7127eb748b5fb32a diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/AbstractDataListenerSupport.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/AbstractDataListenerSupport.java index a253b794db..5a09b87da1 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/AbstractDataListenerSupport.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/AbstractDataListenerSupport.java @@ -9,101 +9,121 @@ package org.opendaylight.controller.cluster.datastore; import akka.actor.ActorRef; import akka.actor.ActorSelection; -import com.google.common.base.Optional; import java.util.ArrayList; import java.util.Collection; import java.util.EventListener; -import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; +import org.opendaylight.controller.cluster.datastore.actors.DataTreeNotificationListenerRegistrationActor; import org.opendaylight.controller.cluster.datastore.messages.EnableNotification; import org.opendaylight.controller.cluster.datastore.messages.ListenerRegistrationMessage; -import org.opendaylight.yangtools.concepts.ListenerRegistration; -import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate; +import org.opendaylight.controller.cluster.datastore.messages.RegisterDataTreeNotificationListenerReply; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -abstract class AbstractDataListenerSupport, LR extends ListenerRegistration> - extends LeaderLocalDelegateFactory> { +abstract class AbstractDataListenerSupport + extends LeaderLocalDelegateFactory { private final Logger log = LoggerFactory.getLogger(getClass()); - private final ArrayList delayedListenerRegistrations = new ArrayList<>(); - private final ArrayList delayedListenerOnAllRegistrations = new ArrayList<>(); - private final Collection actors = new ArrayList<>(); + private final Collection> delayedListenerRegistrations = + ConcurrentHashMap.newKeySet(); + private final Collection> delayedListenerOnAllRegistrations = + ConcurrentHashMap.newKeySet(); + private final Collection leaderOnlyListenerActors = ConcurrentHashMap.newKeySet(); + private final Collection allListenerActors = ConcurrentHashMap.newKeySet(); protected AbstractDataListenerSupport(Shard shard) { super(shard); } + Collection getListenerActors() { + return new ArrayList<>(allListenerActors); + } + @Override void onLeadershipChange(boolean isLeader, boolean hasLeader) { log.debug("{}: onLeadershipChange, isLeader: {}, hasLeader : {}", persistenceId(), isLeader, hasLeader); - final EnableNotification msg = new EnableNotification(isLeader); - for(ActorSelection dataChangeListener : actors) { + final EnableNotification msg = new EnableNotification(isLeader, persistenceId()); + for (ActorSelection dataChangeListener : leaderOnlyListenerActors) { dataChangeListener.tell(msg, getSelf()); } - if(hasLeader) { - for(D reg : delayedListenerOnAllRegistrations) { - reg.createDelegate(this); + if (hasLeader) { + for (DelayedListenerRegistration reg : delayedListenerOnAllRegistrations) { + reg.doRegistration(this); } delayedListenerOnAllRegistrations.clear(); - delayedListenerOnAllRegistrations.trimToSize(); } - if(isLeader) { - for(D reg : delayedListenerRegistrations) { - reg.createDelegate(this); + if (isLeader) { + for (DelayedListenerRegistration reg : delayedListenerRegistrations) { + reg.doRegistration(this); } delayedListenerRegistrations.clear(); - delayedListenerRegistrations.trimToSize(); } } @Override - void onMessage(R message, boolean isLeader, boolean hasLeader) { - log.debug("{}: {} for {}, leader: {}", persistenceId(), logName(), message.getPath(), isLeader); + void onMessage(M message, boolean isLeader, boolean hasLeader) { + log.debug("{}: {} for {}, isLeader: {}, hasLeader: {}", persistenceId(), logName(), message, + isLeader, hasLeader); - final ListenerRegistration registration; - if((hasLeader && message.isRegisterOnAllInstances()) || isLeader) { - final Entry> res = createDelegate(message); - registration = res.getKey(); + ActorRef registrationActor = createActor(DataTreeNotificationListenerRegistrationActor.props()); + + if (hasLeader && message.isRegisterOnAllInstances() || isLeader) { + doRegistration(message, registrationActor); } else { log.debug("{}: Shard is not the leader - delaying registration", persistenceId()); - D delayedReg = newDelayedListenerRegistration(message); - if(message.isRegisterOnAllInstances()) { - delayedListenerOnAllRegistrations.add(delayedReg); + DelayedListenerRegistration delayedReg = + new DelayedListenerRegistration<>(message, registrationActor); + Collection> delayedRegList; + if (message.isRegisterOnAllInstances()) { + delayedRegList = delayedListenerOnAllRegistrations; } else { - delayedListenerRegistrations.add(delayedReg); + delayedRegList = delayedListenerRegistrations; } - registration = delayedReg; + delayedRegList.add(delayedReg); + registrationActor.tell(new DataTreeNotificationListenerRegistrationActor.SetRegistration( + delayedReg, () -> delayedRegList.remove(delayedReg)), ActorRef.noSender()); } - ActorRef registrationActor = newRegistrationActor(registration); - log.debug("{}: {} sending reply, listenerRegistrationPath = {} ", persistenceId(), logName(), registrationActor.path()); - tellSender(newRegistrationReplyMessage(registrationActor)); + tellSender(new RegisterDataTreeNotificationListenerReply(registrationActor)); + } + + protected ActorSelection processListenerRegistrationMessage(M message) { + final ActorSelection listenerActor = selectActor(message.getListenerActorPath()); + + // We have a leader so enable the listener. + listenerActor.tell(new EnableNotification(true, persistenceId()), getSelf()); + + if (!message.isRegisterOnAllInstances()) { + // This is a leader-only registration so store a reference to the listener actor so it can be notified + // at a later point if notifications should be enabled or disabled. + leaderOnlyListenerActors.add(listenerActor); + } + + allListenerActors.add(listenerActor); + + return listenerActor; } protected Logger log() { return log; } - protected void addListenerActor(ActorSelection actor) { - actors.add(actor); + protected void removeListenerActor(ActorSelection listenerActor) { + allListenerActors.remove(listenerActor); + leaderOnlyListenerActors.remove(listenerActor); } - protected abstract D newDelayedListenerRegistration(R message); - - protected abstract ActorRef newRegistrationActor(ListenerRegistration registration); - - protected abstract Object newRegistrationReplyMessage(ActorRef registrationActor); + abstract void doRegistration(M message, ActorRef registrationActor); protected abstract String logName(); }