2 * Copyright (c) 2019 Nordix Foundation. 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.remote.rpc.registry;
10 import akka.actor.ActorRef;
11 import akka.actor.Address;
12 import akka.actor.Props;
13 import com.google.common.annotations.VisibleForTesting;
14 import com.google.common.base.Preconditions;
15 import com.google.common.collect.ImmutableList;
16 import com.google.common.collect.ImmutableMap;
17 import com.google.common.collect.ImmutableSet;
18 import java.util.Collection;
19 import java.util.HashMap;
21 import java.util.Optional;
23 import org.opendaylight.controller.remote.rpc.RemoteOpsProviderConfig;
24 import org.opendaylight.controller.remote.rpc.registry.gossip.Bucket;
25 import org.opendaylight.controller.remote.rpc.registry.gossip.BucketStoreAccess;
26 import org.opendaylight.controller.remote.rpc.registry.gossip.BucketStoreActor;
27 import org.opendaylight.controller.remote.rpc.registry.mbeans.RemoteActionRegistryMXBeanImpl;
28 import org.opendaylight.mdsal.dom.api.DOMActionInstance;
31 * Registry to look up cluster nodes that have registered for a given Action.
34 * It uses {@link org.opendaylight.controller.remote.rpc.registry.gossip.BucketStoreActor} to maintain this
35 * cluster wide information.
37 public class ActionRegistry extends BucketStoreActor<ActionRoutingTable> {
38 private final ActorRef rpcRegistrar;
39 private final RemoteActionRegistryMXBeanImpl mxBean;
41 public ActionRegistry(final RemoteOpsProviderConfig config, final ActorRef rpcInvoker,
42 final ActorRef rpcRegistrar) {
43 super(config, config.getRpcRegistryPersistenceId(), new ActionRoutingTable(rpcInvoker, ImmutableSet.of()));
44 this.rpcRegistrar = Preconditions.checkNotNull(rpcRegistrar);
45 this.mxBean = new RemoteActionRegistryMXBeanImpl(new BucketStoreAccess(self(), getContext().dispatcher(),
46 config.getAskDuration()), config.getAskDuration());
50 * Create a new props instance for instantiating an ActionRegistry actor.
52 * @param config Provider configuration
53 * @param opsRegistrar Local RPC provider interface, used to register routers to remote nodes
54 * @param opsInvoker Actor handling RPC invocation requests from remote nodes
55 * @return A new {@link Props} instance
57 public static Props props(final RemoteOpsProviderConfig config, final ActorRef opsInvoker,
58 final ActorRef opsRegistrar) {
59 return Props.create(ActionRegistry.class, config, opsInvoker, opsRegistrar);
63 public void postStop() {
65 this.mxBean.unregister();
69 protected void handleCommand(final Object message) throws Exception {
70 if (message instanceof ActionRegistry.Messages.UpdateActions) {
71 LOG.debug("handling updatesActionRoutes message");
72 updatesActionRoutes((Messages.UpdateActions) message);
74 super.handleCommand(message);
78 private void updatesActionRoutes(final Messages.UpdateActions msg) {
79 LOG.debug("addedActions: {}", msg.getAddedActions());
80 LOG.debug("removedActions: {}", msg.getRemovedActions());
81 updateLocalBucket(getLocalData().updateActions(msg.getAddedActions(), msg.getRemovedActions()));
85 protected void onBucketRemoved(final Address address, final Bucket<ActionRoutingTable> bucket) {
86 rpcRegistrar.tell(new Messages.UpdateRemoteActionEndpoints(ImmutableMap.of(address, Optional.empty())),
91 protected void onBucketsUpdated(final Map<Address, Bucket<ActionRoutingTable>> buckets) {
92 LOG.debug("Updating buckets for action registry");
93 final Map<Address, Optional<RemoteActionEndpoint>> endpoints = new HashMap<>(buckets.size());
95 for (Map.Entry<Address, Bucket<ActionRoutingTable>> e : buckets.entrySet()) {
96 final ActionRoutingTable table = e.getValue().getData();
98 final Collection<DOMActionInstance> actions = table.getItems();
99 endpoints.put(e.getKey(), actions.isEmpty() ? Optional.empty()
100 : Optional.of(new RemoteActionEndpoint(table.getInvoker(), actions)));
103 if (!endpoints.isEmpty()) {
104 rpcRegistrar.tell(new Messages.UpdateRemoteActionEndpoints(endpoints), ActorRef.noSender());
108 public static final class RemoteActionEndpoint {
109 private final Set<DOMActionInstance> actions;
110 private final ActorRef router;
113 public RemoteActionEndpoint(final ActorRef router, final Collection<DOMActionInstance> actions) {
114 this.router = Preconditions.checkNotNull(router);
115 this.actions = ImmutableSet.copyOf(actions);
118 public ActorRef getRouter() {
122 public Set<DOMActionInstance> getActions() {
128 * All messages used by the ActionRegistry.
130 public static class Messages {
131 abstract static class AbstractActionRouteMessage {
132 final Collection<DOMActionInstance> addedActions;
133 final Collection<DOMActionInstance> removedActions;
135 AbstractActionRouteMessage(final Collection<DOMActionInstance> addedActions,
136 final Collection<DOMActionInstance> removedActions) {
137 this.addedActions = ImmutableList.copyOf(addedActions);
138 this.removedActions = ImmutableList.copyOf(removedActions);
141 Collection<DOMActionInstance> getAddedActions() {
142 return this.addedActions;
145 Collection<DOMActionInstance> getRemovedActions() {
146 return this.removedActions;
151 public String toString() {
152 return "ContainsRoute{" + "addedActions=" + addedActions + " removedActions=" + removedActions + '}';
157 public static final class UpdateActions extends AbstractActionRouteMessage {
158 public UpdateActions(final Collection<DOMActionInstance> addedActions,
159 final Collection<DOMActionInstance> removedActions) {
160 super(addedActions, removedActions);
165 public static final class UpdateRemoteActionEndpoints {
166 private final Map<Address, Optional<RemoteActionEndpoint>> actionEndpoints;
169 public UpdateRemoteActionEndpoints(final Map<Address, Optional<RemoteActionEndpoint>>
171 this.actionEndpoints = ImmutableMap.copyOf(actionEndpoints);
174 public Map<Address, Optional<RemoteActionEndpoint>> getActionEndpoints() {
175 return actionEndpoints;