2 * Copyright (c) 2017 Cisco 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.remote.rpc;
10 import static java.util.Objects.requireNonNull;
12 import akka.actor.Address;
13 import akka.actor.Props;
14 import java.util.HashMap;
16 import java.util.Map.Entry;
17 import java.util.Optional;
18 import org.opendaylight.controller.cluster.common.actor.AbstractUntypedActor;
19 import org.opendaylight.controller.remote.rpc.registry.ActionRegistry;
20 import org.opendaylight.controller.remote.rpc.registry.ActionRegistry.Messages.UpdateRemoteActionEndpoints;
21 import org.opendaylight.controller.remote.rpc.registry.ActionRegistry.RemoteActionEndpoint;
22 import org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.UpdateRemoteEndpoints;
23 import org.opendaylight.controller.remote.rpc.registry.RpcRegistry.RemoteRpcEndpoint;
24 import org.opendaylight.mdsal.dom.api.DOMActionImplementation;
25 import org.opendaylight.mdsal.dom.api.DOMActionProviderService;
26 import org.opendaylight.mdsal.dom.api.DOMRpcImplementation;
27 import org.opendaylight.mdsal.dom.api.DOMRpcProviderService;
28 import org.opendaylight.yangtools.concepts.ObjectRegistration;
31 * Actor handling registration of RPCs and Actions available on remote nodes with the local
32 * {@link DOMRpcProviderService} and {@link DOMActionProviderService}.
34 final class OpsRegistrar extends AbstractUntypedActor {
35 private final Map<Address, ObjectRegistration<DOMRpcImplementation>> rpcRegs = new HashMap<>();
36 private final Map<Address, ObjectRegistration<DOMActionImplementation>> actionRegs = new HashMap<>();
37 private final DOMRpcProviderService rpcProviderService;
38 private final RemoteOpsProviderConfig config;
39 private final DOMActionProviderService actionProviderService;
41 OpsRegistrar(final RemoteOpsProviderConfig config, final DOMRpcProviderService rpcProviderService,
42 final DOMActionProviderService actionProviderService) {
43 this.config = requireNonNull(config);
44 this.rpcProviderService = requireNonNull(rpcProviderService);
45 this.actionProviderService = requireNonNull(actionProviderService);
48 public static Props props(final RemoteOpsProviderConfig config, final DOMRpcProviderService rpcProviderService,
49 final DOMActionProviderService actionProviderService) {
50 return Props.create(OpsRegistrar.class, requireNonNull(config),
51 requireNonNull(rpcProviderService, "DOMRpcProviderService cannot be null"),
52 requireNonNull(actionProviderService, "DOMActionProviderService cannot be null"));
56 public void postStop() throws Exception {
64 protected void handleReceive(final Object message) {
65 if (message instanceof UpdateRemoteEndpoints) {
66 LOG.debug("Handling updateRemoteEndpoints message");
67 updateRemoteRpcEndpoints(((UpdateRemoteEndpoints) message).getRpcEndpoints());
68 } else if (message instanceof UpdateRemoteActionEndpoints) {
69 LOG.debug("Handling updateRemoteActionEndpoints message");
70 updateRemoteActionEndpoints(((UpdateRemoteActionEndpoints) message).getActionEndpoints());
72 unknownMessage(message);
76 private void updateRemoteRpcEndpoints(final Map<Address, Optional<RemoteRpcEndpoint>> rpcEndpoints) {
78 * Updating RPC providers is a two-step process. We first add the newly-discovered RPCs and then close
79 * the old registration. This minimizes churn observed by listeners, as they will not observe RPC
80 * unavailability which would occur if we were to do it the other way around.
82 * Note that when an RPC moves from one remote node to another, we also do not want to expose the gap,
83 * hence we register all new implementations before closing all registrations.
85 for (Entry<Address, Optional<RemoteRpcEndpoint>> e : rpcEndpoints.entrySet()) {
86 LOG.debug("Updating RPC registrations for {}", e.getKey());
88 final Optional<RemoteRpcEndpoint> maybeEndpoint = e.getValue();
89 if (maybeEndpoint.isPresent()) {
90 final RemoteRpcEndpoint endpoint = maybeEndpoint.get();
91 final RemoteRpcImplementation impl = new RemoteRpcImplementation(endpoint.getRouter(), config);
92 rpcRegs.put(e.getKey(), rpcProviderService.registerRpcImplementation(impl,
95 rpcRegs.remove(e.getKey());
101 * Updates the action endpoints, Adding new registrations first before removing previous registrations.
103 private void updateRemoteActionEndpoints(final Map<Address,
104 Optional<ActionRegistry.RemoteActionEndpoint>> actionEndpoints) {
106 * Updating Action providers is a two-step process. We first add the newly-discovered RPCs and then close
107 * the old registration. This minimizes churn observed by listeners, as they will not observe RPC
108 * unavailability which would occur if we were to do it the other way around.
110 * Note that when an Action moves from one remote node to another, we also do not want to expose the gap,
111 * hence we register all new implementations before closing all registrations.
113 for (Entry<Address, Optional<RemoteActionEndpoint>> e : actionEndpoints.entrySet()) {
114 LOG.debug("Updating Action registrations for {}", e.getKey());
116 final Optional<RemoteActionEndpoint> maybeEndpoint = e.getValue();
117 if (maybeEndpoint.isPresent()) {
118 final RemoteActionEndpoint endpoint = maybeEndpoint.get();
119 final RemoteActionImplementation impl = new RemoteActionImplementation(endpoint.getRouter(), config);
120 actionRegs.put(e.getKey(),
121 actionProviderService.registerActionImplementation(impl, endpoint.getActions()));
123 actionRegs.remove(e.getKey());