4ff42c14a1c6c76e1a5446811fca0e7d2fdc1758
[controller.git] / opendaylight / md-sal / samples / clustering-test-app / provider / src / main / java / org / opendaylight / controller / clustering / it / provider / MdsalLowLevelTestProvider.java
1 /*
2  * Copyright (c) 2017 Cisco 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
9 package org.opendaylight.controller.clustering.it.provider;
10
11 import com.google.common.util.concurrent.Futures;
12 import com.google.common.util.concurrent.SettableFuture;
13 import java.util.HashMap;
14 import java.util.Map;
15 import java.util.concurrent.Future;
16 import org.opendaylight.controller.clustering.it.provider.impl.FlappingSingletonService;
17 import org.opendaylight.controller.clustering.it.provider.impl.GetConstantService;
18 import org.opendaylight.controller.clustering.it.provider.impl.PublishNotificationsTask;
19 import org.opendaylight.controller.clustering.it.provider.impl.RoutedGetConstantService;
20 import org.opendaylight.controller.clustering.it.provider.impl.SingletonGetConstantService;
21 import org.opendaylight.controller.clustering.it.provider.impl.WriteTransactionsHandler;
22 import org.opendaylight.controller.clustering.it.provider.impl.YnlListener;
23 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
24 import org.opendaylight.controller.md.sal.binding.api.NotificationService;
25 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
26 import org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementationRegistration;
27 import org.opendaylight.controller.md.sal.dom.api.DOMRpcProviderService;
28 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
29 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
30 import org.opendaylight.controller.sal.core.api.model.SchemaService;
31 import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
32 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
33 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
34 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.AddShardReplicaInput;
35 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.BecomeModuleLeaderInput;
36 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.BecomePrefixLeaderInput;
37 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.IsClientAbortedOutput;
38 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.OdlMdsalLowlevelControlService;
39 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.ProduceTransactionsInput;
40 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.PublishNotificationsInput;
41 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.RegisterBoundConstantInput;
42 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.RegisterConstantInput;
43 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.RegisterDefaultConstantInput;
44 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.RegisterSingletonConstantInput;
45 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.RemoveShardReplicaInput;
46 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.SubscribeYnlInput;
47 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnregisterBoundConstantInput;
48 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnregisterFlappingSingletonOutput;
49 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnregisterFlappingSingletonOutputBuilder;
50 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnsubscribeDdtlOutput;
51 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnsubscribeDtclOutput;
52 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnsubscribeYnlInput;
53 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnsubscribeYnlOutput;
54 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.WriteTransactionsInput;
55 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.WriteTransactionsOutput;
56 import org.opendaylight.yangtools.concepts.ListenerRegistration;
57 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
58 import org.opendaylight.yangtools.yang.common.RpcError;
59 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
60 import org.opendaylight.yangtools.yang.common.RpcResult;
61 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
64
65 public class MdsalLowLevelTestProvider implements OdlMdsalLowlevelControlService {
66
67     private static final Logger LOG = LoggerFactory.getLogger(MdsalLowLevelTestProvider.class);
68
69     private final RpcProviderRegistry rpcRegistry;
70     private final BindingAwareBroker.RpcRegistration<OdlMdsalLowlevelControlService> registration;
71     private final BindingNormalizedNodeSerializer bindingNormalizedNodeSerializer;
72     private final DOMDataBroker domDataBroker;
73     private final NotificationPublishService notificationPublishService;
74     private final NotificationService notificationService;
75     private final SchemaService schemaService;
76     private final ClusterSingletonServiceProvider singletonService;
77     private final DOMRpcProviderService domRpcService;
78
79     private Map<InstanceIdentifier<?>, DOMRpcImplementationRegistration<RoutedGetConstantService>> routedRegistrations =
80             new HashMap<>();
81
82     private Map<String, ListenerRegistration<YnlListener>> ynlRegistrations = new HashMap<>();
83
84     private DOMRpcImplementationRegistration<GetConstantService> globalGetConstantRegistration = null;
85     private ClusterSingletonServiceRegistration getSingletonConstantRegistration;
86     private FlappingSingletonService flappingSingletonService;
87
88     public MdsalLowLevelTestProvider(final RpcProviderRegistry rpcRegistry,
89                                      final DOMRpcProviderService domRpcService,
90                                      final ClusterSingletonServiceProvider singletonService,
91                                      final SchemaService schemaService,
92                                      final BindingNormalizedNodeSerializer bindingNormalizedNodeSerializer,
93                                      final NotificationPublishService notificationPublishService,
94                                      final NotificationService notificationService,
95                                      final DOMDataBroker domDataBroker) {
96         this.rpcRegistry = rpcRegistry;
97         this.domRpcService = domRpcService;
98         this.singletonService = singletonService;
99         this.schemaService = schemaService;
100         this.bindingNormalizedNodeSerializer = bindingNormalizedNodeSerializer;
101         this.notificationPublishService = notificationPublishService;
102         this.notificationService = notificationService;
103         this.domDataBroker = domDataBroker;
104
105         registration = rpcRegistry.addRpcImplementation(OdlMdsalLowlevelControlService.class, this);
106     }
107
108     @Override
109     public Future<RpcResult<Void>> unregisterSingletonConstant() {
110         LOG.debug("unregister-singleton-constant");
111
112         if (getSingletonConstantRegistration == null) {
113             LOG.debug("No get-singleton-constant registration present.");
114             final RpcError rpcError = RpcResultBuilder
115                     .newError(ErrorType.APPLICATION, "missing-registration", "No get-singleton-constant rpc registration present.");
116             final RpcResult<Void> result = RpcResultBuilder.<Void>failed().withRpcError(rpcError).build();
117             return Futures.immediateFuture(result);
118         }
119
120         try {
121             getSingletonConstantRegistration.close();
122             getSingletonConstantRegistration = null;
123
124             return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
125         } catch (final Exception e) {
126             LOG.debug("There was a problem closing the singleton constant service", e);
127             final RpcError rpcError = RpcResultBuilder
128                     .newError(ErrorType.APPLICATION, "error-closing", "There was a problem closing get-singleton-constant");
129             final RpcResult<Void> result = RpcResultBuilder.<Void>failed().withRpcError(rpcError).build();
130             return Futures.immediateFuture(result);
131         }
132     }
133
134     @Override
135     public Future<RpcResult<Void>> publishNotifications(final PublishNotificationsInput input) {
136         LOG.debug("publish-notifications, input: {}", input);
137
138         final PublishNotificationsTask task = new PublishNotificationsTask(notificationPublishService, input.getId(),
139                 input.getSeconds(), input.getNotificationsPerSecond());
140
141         final SettableFuture<RpcResult<Void>> settableFuture = SettableFuture.create();
142         task.start(settableFuture);
143
144         return settableFuture;
145     }
146
147     @Override
148     public Future<RpcResult<Void>> subscribeDtcl() {
149         return null;
150     }
151
152     @Override
153     public Future<RpcResult<WriteTransactionsOutput>> writeTransactions(final WriteTransactionsInput input) {
154         LOG.debug("write-transactions, input: {}", input);
155
156         final WriteTransactionsHandler writeTransactionsHandler = new WriteTransactionsHandler(domDataBroker, input);
157
158         final SettableFuture<RpcResult<WriteTransactionsOutput>> settableFuture = SettableFuture.create();
159         writeTransactionsHandler.start(settableFuture);
160
161         return settableFuture;
162     }
163
164     @Override
165     public Future<RpcResult<IsClientAbortedOutput>> isClientAborted() {
166         return null;
167     }
168
169     @Override
170     public Future<RpcResult<Void>> becomeModuleLeader(BecomeModuleLeaderInput input) {
171         return null;
172     }
173
174     @Override
175     public Future<RpcResult<Void>> removeShardReplica(RemoveShardReplicaInput input) {
176         return null;
177     }
178
179     @Override
180     public Future<RpcResult<Void>> subscribeYnl(final SubscribeYnlInput input) {
181
182         LOG.debug("subscribe-ynl, input: {}", input);
183
184         if (ynlRegistrations.containsKey(input.getId())) {
185             final RpcError error = RpcResultBuilder.newError(ErrorType.RPC, "Registration present.",
186                     "There is already ynl listener registered for this id: " + input.getId());
187             return Futures.immediateFuture(RpcResultBuilder.<Void>failed().withRpcError(error).build());
188         }
189
190         ynlRegistrations.put(input.getId(),
191                 notificationService.registerNotificationListener(new YnlListener(input.getId())));
192
193         return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
194     }
195
196     @Override
197     public Future<RpcResult<Void>> becomePrefixLeader(BecomePrefixLeaderInput input) {
198         return null;
199     }
200
201     @Override
202     public Future<RpcResult<Void>> unregisterBoundConstant(final UnregisterBoundConstantInput input) {
203         LOG.debug("unregister-bound-constant, {}", input);
204
205         final DOMRpcImplementationRegistration<RoutedGetConstantService> registration =
206                 routedRegistrations.remove(input.getContext());
207
208         if (registration == null) {
209             LOG.debug("No get-contexted-constant registration for context: {}", input.getContext());
210             final RpcError rpcError = RpcResultBuilder
211                     .newError(ErrorType.APPLICATION, "missing-registration", "No get-constant rpc registration present.");
212             final RpcResult<Void> result = RpcResultBuilder.<Void>failed().withRpcError(rpcError).build();
213             return Futures.immediateFuture(result);
214         }
215
216         registration.close();
217         return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
218     }
219
220     @Override
221     public Future<RpcResult<Void>> registerSingletonConstant(final RegisterSingletonConstantInput input) {
222
223         LOG.debug("Received register-singleton-constant rpc, input: {}", input);
224
225         if (input.getConstant() == null) {
226             final RpcError error = RpcResultBuilder.newError(
227                     ErrorType.RPC, "Invalid input.", "Constant value is null");
228             return Futures.immediateFuture(RpcResultBuilder.<Void>failed().withRpcError(error).build());
229         }
230
231         getSingletonConstantRegistration =
232                 SingletonGetConstantService.registerNew(singletonService, domRpcService, input.getConstant());
233
234         return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
235     }
236
237     @Override
238     public Future<RpcResult<Void>> registerDefaultConstant(RegisterDefaultConstantInput input) {
239         return null;
240     }
241
242     @Override
243     public Future<RpcResult<Void>> unregisterConstant() {
244
245         if (globalGetConstantRegistration == null) {
246             final RpcError rpcError = RpcResultBuilder
247                     .newError(ErrorType.APPLICATION, "missing-registration", "No get-constant rpc registration present.");
248             final RpcResult<Void> result = RpcResultBuilder.<Void>failed().withRpcError(rpcError).build();
249             return Futures.immediateFuture(result);
250         }
251
252         globalGetConstantRegistration.close();
253         globalGetConstantRegistration = null;
254
255         return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
256     }
257
258     @Override
259     public Future<RpcResult<UnregisterFlappingSingletonOutput>> unregisterFlappingSingleton() {
260         LOG.debug("unregister-flapping-singleton received.");
261
262         if (flappingSingletonService == null) {
263             final RpcError rpcError = RpcResultBuilder
264                     .newError(ErrorType.APPLICATION, "missing-registration", "No flapping-singleton registration present.");
265             final RpcResult<UnregisterFlappingSingletonOutput> result =
266                     RpcResultBuilder.<UnregisterFlappingSingletonOutput>failed().withRpcError(rpcError).build();
267             return Futures.immediateFuture(result);
268         }
269
270         final long flapCount = flappingSingletonService.setInactive();
271         flappingSingletonService = null;
272
273         final UnregisterFlappingSingletonOutput output =
274                 new UnregisterFlappingSingletonOutputBuilder().setFlapCount(flapCount).build();
275
276         return Futures.immediateFuture(RpcResultBuilder.success(output).build());
277     }
278
279     @Override
280     public Future<RpcResult<Void>> addShardReplica(AddShardReplicaInput input) {
281         return null;
282     }
283
284     @Override
285     public Future<RpcResult<Void>> subscribeDdtl() {
286         return null;
287     }
288
289     @Override
290     public Future<RpcResult<Void>> registerBoundConstant(final RegisterBoundConstantInput input) {
291         LOG.debug("register-bound-constant: {}", input);
292
293         if (input.getContext() == null) {
294             final RpcError error = RpcResultBuilder.newError(
295                     ErrorType.RPC, "Invalid input.", "Context value is null");
296             return Futures.immediateFuture(RpcResultBuilder.<Void>failed().withRpcError(error).build());
297         }
298
299         if (input.getConstant() == null) {
300             final RpcError error = RpcResultBuilder.newError(
301                     ErrorType.RPC, "Invalid input.", "Constant value is null");
302             return Futures.immediateFuture(RpcResultBuilder.<Void>failed().withRpcError(error).build());
303         }
304
305         if (routedRegistrations.containsKey(input.getContext())) {
306             final RpcError error = RpcResultBuilder.newError(ErrorType.RPC, "Registration present.",
307                     "There is already a rpc registered for context: " + input.getContext());
308             return Futures.immediateFuture(RpcResultBuilder.<Void>failed().withRpcError(error).build());
309         }
310
311         final DOMRpcImplementationRegistration<RoutedGetConstantService> registration =
312                 RoutedGetConstantService.registerNew(bindingNormalizedNodeSerializer, domRpcService,
313                         input.getConstant(), input.getContext());
314
315         routedRegistrations.put(input.getContext(), registration);
316         return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
317     }
318
319     @Override
320     public Future<RpcResult<Void>> registerFlappingSingleton() {
321         LOG.debug("Received register-flapping-singleton.");
322
323         if (flappingSingletonService != null) {
324             final RpcError error = RpcResultBuilder.newError(
325                     ErrorType.RPC, "Registration present.", "flappin-singleton already registered");
326             return Futures.immediateFuture(RpcResultBuilder.<Void>failed().withRpcError(error).build());
327         }
328
329         flappingSingletonService = new FlappingSingletonService(singletonService);
330
331         return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
332     }
333
334     @Override
335     public Future<RpcResult<UnsubscribeDtclOutput>> unsubscribeDtcl() {
336         return null;
337     }
338
339     @Override
340     public Future<RpcResult<Void>> deconfigureIdIntsShard() {
341         return null;
342     }
343
344     @Override
345     public Future<RpcResult<UnsubscribeYnlOutput>> unsubscribeYnl(final UnsubscribeYnlInput input) {
346         LOG.debug("Received unsubscribe-ynl, input: {}", input);
347
348         if (!ynlRegistrations.containsKey(input.getId())) {
349             final RpcError rpcError = RpcResultBuilder
350                     .newError(ErrorType.APPLICATION, "missing-registration", "No ynl listener with this id registered.");
351             final RpcResult<UnsubscribeYnlOutput> result =
352                     RpcResultBuilder.<UnsubscribeYnlOutput>failed().withRpcError(rpcError).build();
353             return Futures.immediateFuture(result);
354         }
355
356         final ListenerRegistration<YnlListener> registration = ynlRegistrations.remove(input.getId());
357         final UnsubscribeYnlOutput output = registration.getInstance().getOutput();
358
359         registration.close();
360
361         return Futures.immediateFuture(RpcResultBuilder.<UnsubscribeYnlOutput>success().withResult(output).build());
362     }
363
364     @Override
365     public Future<RpcResult<Void>> produceTransactions(ProduceTransactionsInput input) {
366         return null;
367     }
368
369     @Override
370     public Future<RpcResult<Void>> registerConstant(final RegisterConstantInput input) {
371
372         LOG.debug("Received register-constant rpc, input: {}", input);
373
374         if (input.getConstant() == null) {
375             final RpcError error = RpcResultBuilder.newError(
376                     ErrorType.RPC, "Invalid input.", "Constant value is null");
377             return Futures.immediateFuture(RpcResultBuilder.<Void>failed().withRpcError(error).build());
378         }
379
380         if (globalGetConstantRegistration != null) {
381             final RpcError error = RpcResultBuilder.newError(ErrorType.RPC, "Registration present.",
382                     "There is already a get-constant rpc registered.");
383             return Futures.immediateFuture(RpcResultBuilder.<Void>failed().withRpcError(error).build());
384         }
385
386         globalGetConstantRegistration = GetConstantService.registerNew(domRpcService, input.getConstant());
387         return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
388     }
389
390     @Override
391     public Future<RpcResult<Void>> unregisterDefaultConstant() {
392         return null;
393     }
394
395     @Override
396     public Future<RpcResult<UnsubscribeDdtlOutput>> unsubscribeDdtl() {
397         return null;
398     }
399 }