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
9 package org.opendaylight.controller.clustering.it.provider;
11 import com.google.common.base.Optional;
12 import com.google.common.base.Preconditions;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import com.google.common.util.concurrent.SettableFuture;
16 import java.io.PrintWriter;
17 import java.io.StringWriter;
18 import java.util.Collection;
19 import java.util.Collections;
20 import java.util.HashMap;
22 import java.util.concurrent.ExecutionException;
23 import java.util.concurrent.Future;
24 import javax.annotation.Nonnull;
25 import org.opendaylight.controller.cluster.sharding.DistributedShardFactory;
26 import org.opendaylight.controller.clustering.it.provider.impl.FlappingSingletonService;
27 import org.opendaylight.controller.clustering.it.provider.impl.GetConstantService;
28 import org.opendaylight.controller.clustering.it.provider.impl.IdIntsDOMDataTreeLIstener;
29 import org.opendaylight.controller.clustering.it.provider.impl.IdIntsListener;
30 import org.opendaylight.controller.clustering.it.provider.impl.PrefixLeaderHandler;
31 import org.opendaylight.controller.clustering.it.provider.impl.PrefixShardHandler;
32 import org.opendaylight.controller.clustering.it.provider.impl.ProduceTransactionsHandler;
33 import org.opendaylight.controller.clustering.it.provider.impl.PublishNotificationsTask;
34 import org.opendaylight.controller.clustering.it.provider.impl.RoutedGetConstantService;
35 import org.opendaylight.controller.clustering.it.provider.impl.SingletonGetConstantService;
36 import org.opendaylight.controller.clustering.it.provider.impl.WriteTransactionsHandler;
37 import org.opendaylight.controller.clustering.it.provider.impl.YnlListener;
38 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
39 import org.opendaylight.controller.md.sal.binding.api.NotificationService;
40 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
41 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
42 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
43 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeListener;
44 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeService;
45 import org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementationRegistration;
46 import org.opendaylight.controller.md.sal.dom.api.DOMRpcProviderService;
47 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
48 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
49 import org.opendaylight.controller.sal.core.api.model.SchemaService;
50 import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
51 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
52 import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
53 import org.opendaylight.mdsal.dom.api.DOMDataTreeListener;
54 import org.opendaylight.mdsal.dom.api.DOMDataTreeListeningException;
55 import org.opendaylight.mdsal.dom.api.DOMDataTreeLoopException;
56 import org.opendaylight.mdsal.dom.api.DOMDataTreeService;
57 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
58 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
59 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.AddShardReplicaInput;
60 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.BecomePrefixLeaderInput;
61 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.CheckPublishNotificationsInput;
62 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.CheckPublishNotificationsOutput;
63 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.CheckPublishNotificationsOutputBuilder;
64 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.CreatePrefixShardInput;
65 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.IsClientAbortedOutput;
66 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.OdlMdsalLowlevelControlService;
67 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.ProduceTransactionsInput;
68 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.ProduceTransactionsOutput;
69 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.RegisterBoundConstantInput;
70 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.RegisterConstantInput;
71 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.RegisterDefaultConstantInput;
72 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.RegisterSingletonConstantInput;
73 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.RemovePrefixShardInput;
74 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.RemoveShardReplicaInput;
75 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.StartPublishNotificationsInput;
76 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.SubscribeYnlInput;
77 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnregisterBoundConstantInput;
78 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnregisterFlappingSingletonOutput;
79 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnregisterFlappingSingletonOutputBuilder;
80 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnsubscribeDdtlOutput;
81 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnsubscribeDdtlOutputBuilder;
82 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnsubscribeDtclOutput;
83 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnsubscribeDtclOutputBuilder;
84 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnsubscribeYnlInput;
85 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnsubscribeYnlOutput;
86 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.WriteTransactionsInput;
87 import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.WriteTransactionsOutput;
88 import org.opendaylight.yangtools.concepts.ListenerRegistration;
89 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
90 import org.opendaylight.yangtools.yang.common.RpcError;
91 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
92 import org.opendaylight.yangtools.yang.common.RpcResult;
93 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
94 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
95 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
96 import org.slf4j.Logger;
97 import org.slf4j.LoggerFactory;
99 public class MdsalLowLevelTestProvider implements OdlMdsalLowlevelControlService {
101 private static final Logger LOG = LoggerFactory.getLogger(MdsalLowLevelTestProvider.class);
102 private static final org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType CONTROLLER_CONFIG =
103 org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
105 private final RpcProviderRegistry rpcRegistry;
106 private final BindingAwareBroker.RpcRegistration<OdlMdsalLowlevelControlService> registration;
107 private final DistributedShardFactory distributedShardFactory;
108 private final DOMDataTreeService domDataTreeService;
109 private final BindingNormalizedNodeSerializer bindingNormalizedNodeSerializer;
110 private final DOMDataBroker domDataBroker;
111 private final NotificationPublishService notificationPublishService;
112 private final NotificationService notificationService;
113 private final SchemaService schemaService;
114 private final ClusterSingletonServiceProvider singletonService;
115 private final DOMRpcProviderService domRpcService;
116 private final PrefixLeaderHandler prefixLeaderHandler;
117 private final PrefixShardHandler prefixShardHandler;
118 private final DOMDataTreeChangeService domDataTreeChangeService;
120 private Map<InstanceIdentifier<?>, DOMRpcImplementationRegistration<RoutedGetConstantService>> routedRegistrations =
123 private Map<String, ListenerRegistration<YnlListener>> ynlRegistrations = new HashMap<>();
125 private DOMRpcImplementationRegistration<GetConstantService> globalGetConstantRegistration = null;
126 private ClusterSingletonServiceRegistration getSingletonConstantRegistration;
127 private FlappingSingletonService flappingSingletonService;
128 private ListenerRegistration<DOMDataTreeChangeListener> dtclReg;
129 private IdIntsListener idIntsListener;
130 private Map<String, PublishNotificationsTask> publishNotificationsTasks = new HashMap<>();
131 private ListenerRegistration<IdIntsDOMDataTreeLIstener> ddtlReg;
132 private IdIntsDOMDataTreeLIstener idIntsDdtl;
136 public MdsalLowLevelTestProvider(final RpcProviderRegistry rpcRegistry,
137 final DOMRpcProviderService domRpcService,
138 final ClusterSingletonServiceProvider singletonService,
139 final SchemaService schemaService,
140 final BindingNormalizedNodeSerializer bindingNormalizedNodeSerializer,
141 final NotificationPublishService notificationPublishService,
142 final NotificationService notificationService,
143 final DOMDataBroker domDataBroker,
144 final DOMDataTreeService domDataTreeService,
145 final DistributedShardFactory distributedShardFactory) {
146 this.rpcRegistry = rpcRegistry;
147 this.domRpcService = domRpcService;
148 this.singletonService = singletonService;
149 this.schemaService = schemaService;
150 this.bindingNormalizedNodeSerializer = bindingNormalizedNodeSerializer;
151 this.notificationPublishService = notificationPublishService;
152 this.notificationService = notificationService;
153 this.domDataBroker = domDataBroker;
154 this.domDataTreeService = domDataTreeService;
155 this.distributedShardFactory = distributedShardFactory;
156 this.prefixLeaderHandler = new PrefixLeaderHandler(domDataTreeService, bindingNormalizedNodeSerializer);
158 domDataTreeChangeService =
159 (DOMDataTreeChangeService) domDataBroker.getSupportedExtensions().get(DOMDataTreeChangeService.class);
161 registration = rpcRegistry.addRpcImplementation(OdlMdsalLowlevelControlService.class, this);
163 prefixShardHandler = new PrefixShardHandler(distributedShardFactory, domDataTreeService,
164 bindingNormalizedNodeSerializer);
168 public Future<RpcResult<Void>> unregisterSingletonConstant() {
169 LOG.debug("unregister-singleton-constant");
171 if (getSingletonConstantRegistration == null) {
172 LOG.debug("No get-singleton-constant registration present.");
173 final RpcError rpcError = RpcResultBuilder
174 .newError(ErrorType.APPLICATION, "missing-registration", "No get-singleton-constant rpc registration present.");
175 final RpcResult<Void> result = RpcResultBuilder.<Void>failed().withRpcError(rpcError).build();
176 return Futures.immediateFuture(result);
180 getSingletonConstantRegistration.close();
181 getSingletonConstantRegistration = null;
183 return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
184 } catch (final Exception e) {
185 LOG.debug("There was a problem closing the singleton constant service", e);
186 final RpcError rpcError = RpcResultBuilder
187 .newError(ErrorType.APPLICATION, "error-closing", "There was a problem closing get-singleton-constant");
188 final RpcResult<Void> result = RpcResultBuilder.<Void>failed().withRpcError(rpcError).build();
189 return Futures.immediateFuture(result);
194 public Future<RpcResult<Void>> startPublishNotifications(final StartPublishNotificationsInput input) {
195 LOG.debug("publish-notifications, input: {}", input);
197 final PublishNotificationsTask task = new PublishNotificationsTask(notificationPublishService, input.getId(),
198 input.getSeconds(), input.getNotificationsPerSecond());
200 publishNotificationsTasks.put(input.getId(), task);
204 return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
208 public Future<RpcResult<Void>> subscribeDtcl() {
210 if (dtclReg != null) {
211 final RpcError error = RpcResultBuilder.newError(ErrorType.RPC, "Registration present.",
212 "There is already dataTreeChangeListener registered on id-ints list.");
213 return Futures.immediateFuture(RpcResultBuilder.<Void>failed().withRpcError(error).build());
216 idIntsListener = new IdIntsListener();
218 dtclReg = domDataTreeChangeService
219 .registerDataTreeChangeListener(
220 new org.opendaylight.controller.md.sal.dom.api.DOMDataTreeIdentifier(
221 CONTROLLER_CONFIG, WriteTransactionsHandler.ID_INT_YID),
224 return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
228 public Future<RpcResult<WriteTransactionsOutput>> writeTransactions(final WriteTransactionsInput input) {
229 LOG.debug("write-transactions, input: {}", input);
231 final WriteTransactionsHandler writeTransactionsHandler = new WriteTransactionsHandler(domDataBroker, input);
233 final SettableFuture<RpcResult<WriteTransactionsOutput>> settableFuture = SettableFuture.create();
234 writeTransactionsHandler.start(settableFuture);
236 return settableFuture;
240 public Future<RpcResult<IsClientAbortedOutput>> isClientAborted() {
245 public Future<RpcResult<Void>> removeShardReplica(RemoveShardReplicaInput input) {
250 public Future<RpcResult<Void>> subscribeYnl(final SubscribeYnlInput input) {
252 LOG.debug("subscribe-ynl, input: {}", input);
254 if (ynlRegistrations.containsKey(input.getId())) {
255 final RpcError error = RpcResultBuilder.newError(ErrorType.RPC, "Registration present.",
256 "There is already ynl listener registered for this id: " + input.getId());
257 return Futures.immediateFuture(RpcResultBuilder.<Void>failed().withRpcError(error).build());
260 ynlRegistrations.put(input.getId(),
261 notificationService.registerNotificationListener(new YnlListener(input.getId())));
263 return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
267 public Future<RpcResult<Void>> removePrefixShard(final RemovePrefixShardInput input) {
268 LOG.debug("remove-prefix-shard, input: {}", input);
270 return prefixShardHandler.onRemovePrefixShard(input);
274 public Future<RpcResult<Void>> becomePrefixLeader(final BecomePrefixLeaderInput input) {
275 LOG.debug("become-prefix-leader, input: {}", input);
277 return prefixLeaderHandler.makeLeaderLocal(input);
281 public Future<RpcResult<Void>> unregisterBoundConstant(final UnregisterBoundConstantInput input) {
282 LOG.debug("unregister-bound-constant, {}", input);
284 final DOMRpcImplementationRegistration<RoutedGetConstantService> registration =
285 routedRegistrations.remove(input.getContext());
287 if (registration == null) {
288 LOG.debug("No get-contexted-constant registration for context: {}", input.getContext());
289 final RpcError rpcError = RpcResultBuilder
290 .newError(ErrorType.APPLICATION, "missing-registration", "No get-constant rpc registration present.");
291 final RpcResult<Void> result = RpcResultBuilder.<Void>failed().withRpcError(rpcError).build();
292 return Futures.immediateFuture(result);
295 registration.close();
296 return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
300 public Future<RpcResult<Void>> registerSingletonConstant(final RegisterSingletonConstantInput input) {
302 LOG.debug("Received register-singleton-constant rpc, input: {}", input);
304 if (input.getConstant() == null) {
305 final RpcError error = RpcResultBuilder.newError(
306 ErrorType.RPC, "Invalid input.", "Constant value is null");
307 return Futures.immediateFuture(RpcResultBuilder.<Void>failed().withRpcError(error).build());
310 getSingletonConstantRegistration =
311 SingletonGetConstantService.registerNew(singletonService, domRpcService, input.getConstant());
313 return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
317 public Future<RpcResult<Void>> registerDefaultConstant(RegisterDefaultConstantInput input) {
322 public Future<RpcResult<Void>> unregisterConstant() {
324 if (globalGetConstantRegistration == null) {
325 final RpcError rpcError = RpcResultBuilder
326 .newError(ErrorType.APPLICATION, "missing-registration", "No get-constant rpc registration present.");
327 final RpcResult<Void> result = RpcResultBuilder.<Void>failed().withRpcError(rpcError).build();
328 return Futures.immediateFuture(result);
331 globalGetConstantRegistration.close();
332 globalGetConstantRegistration = null;
334 return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
338 public Future<RpcResult<UnregisterFlappingSingletonOutput>> unregisterFlappingSingleton() {
339 LOG.debug("unregister-flapping-singleton received.");
341 if (flappingSingletonService == null) {
342 final RpcError rpcError = RpcResultBuilder
343 .newError(ErrorType.APPLICATION, "missing-registration", "No flapping-singleton registration present.");
344 final RpcResult<UnregisterFlappingSingletonOutput> result =
345 RpcResultBuilder.<UnregisterFlappingSingletonOutput>failed().withRpcError(rpcError).build();
346 return Futures.immediateFuture(result);
349 final long flapCount = flappingSingletonService.setInactive();
350 flappingSingletonService = null;
352 final UnregisterFlappingSingletonOutput output =
353 new UnregisterFlappingSingletonOutputBuilder().setFlapCount(flapCount).build();
355 return Futures.immediateFuture(RpcResultBuilder.success(output).build());
359 public Future<RpcResult<Void>> addShardReplica(AddShardReplicaInput input) {
364 public Future<RpcResult<Void>> subscribeDdtl() {
366 if (ddtlReg != null) {
367 final RpcError error = RpcResultBuilder.newError(ErrorType.RPC, "Registration present.",
368 "There is already dataTreeChangeListener registered on id-ints list.");
369 return Futures.immediateFuture(RpcResultBuilder.<Void>failed().withRpcError(error).build());
372 idIntsDdtl = new IdIntsDOMDataTreeLIstener();
376 domDataTreeService.registerListener(idIntsDdtl,
377 Collections.singleton(new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION,
378 ProduceTransactionsHandler.ID_INT_YID))
379 , true, Collections.emptyList());
380 } catch (DOMDataTreeLoopException e) {
381 LOG.error("Failed to register DOMDataTreeListener.", e);
385 return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
389 public Future<RpcResult<Void>> registerBoundConstant(final RegisterBoundConstantInput input) {
390 LOG.debug("register-bound-constant: {}", input);
392 if (input.getContext() == null) {
393 final RpcError error = RpcResultBuilder.newError(
394 ErrorType.RPC, "Invalid input.", "Context value is null");
395 return Futures.immediateFuture(RpcResultBuilder.<Void>failed().withRpcError(error).build());
398 if (input.getConstant() == null) {
399 final RpcError error = RpcResultBuilder.newError(
400 ErrorType.RPC, "Invalid input.", "Constant value is null");
401 return Futures.immediateFuture(RpcResultBuilder.<Void>failed().withRpcError(error).build());
404 if (routedRegistrations.containsKey(input.getContext())) {
405 final RpcError error = RpcResultBuilder.newError(ErrorType.RPC, "Registration present.",
406 "There is already a rpc registered for context: " + input.getContext());
407 return Futures.immediateFuture(RpcResultBuilder.<Void>failed().withRpcError(error).build());
410 final DOMRpcImplementationRegistration<RoutedGetConstantService> registration =
411 RoutedGetConstantService.registerNew(bindingNormalizedNodeSerializer, domRpcService,
412 input.getConstant(), input.getContext());
414 routedRegistrations.put(input.getContext(), registration);
415 return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
419 public Future<RpcResult<Void>> registerFlappingSingleton() {
420 LOG.debug("Received register-flapping-singleton.");
422 if (flappingSingletonService != null) {
423 final RpcError error = RpcResultBuilder.newError(
424 ErrorType.RPC, "Registration present.", "flappin-singleton already registered");
425 return Futures.immediateFuture(RpcResultBuilder.<Void>failed().withRpcError(error).build());
428 flappingSingletonService = new FlappingSingletonService(singletonService);
430 return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
434 public Future<RpcResult<UnsubscribeDtclOutput>> unsubscribeDtcl() {
435 LOG.debug("Received unsubscribe-dtcl");
437 if (idIntsListener == null || dtclReg == null) {
438 final RpcError error = RpcResultBuilder.newError(
439 ErrorType.RPC, "Dtcl missing.", "No DataTreeChangeListener registered.");
440 return Futures.immediateFuture(RpcResultBuilder.<UnsubscribeDtclOutput>failed().withRpcError(error).build());
443 final DOMDataReadOnlyTransaction rTx = domDataBroker.newReadOnlyTransaction();
445 if (dtclReg != null) {
450 final Optional<NormalizedNode<?, ?>> readResult =
451 rTx.read(CONTROLLER_CONFIG, WriteTransactionsHandler.ID_INT_YID).checkedGet();
453 if (!readResult.isPresent()) {
454 final RpcError error = RpcResultBuilder.newError(
455 ErrorType.APPLICATION, "Final read empty.", "No data read from id-ints list.");
456 return Futures.immediateFuture(RpcResultBuilder.<UnsubscribeDtclOutput>failed()
457 .withRpcError(error).build());
460 return Futures.immediateFuture(
461 RpcResultBuilder.success(new UnsubscribeDtclOutputBuilder()
462 .setCopyMatches(idIntsListener.checkEqual(readResult.get()))).build());
464 } catch (final ReadFailedException e) {
465 final RpcError error = RpcResultBuilder.newError(
466 ErrorType.APPLICATION, "Read failed.", "Final read from id-ints failed.");
467 return Futures.immediateFuture(RpcResultBuilder.<UnsubscribeDtclOutput>failed()
468 .withRpcError(error).build());
474 public Future<RpcResult<Void>> createPrefixShard(final CreatePrefixShardInput input) {
475 LOG.debug("create-prefix-shard, input: {}", input);
477 return prefixShardHandler.onCreatePrefixShard(input);
481 public Future<RpcResult<Void>> deconfigureIdIntsShard() {
486 public Future<RpcResult<UnsubscribeYnlOutput>> unsubscribeYnl(final UnsubscribeYnlInput input) {
487 LOG.debug("Received unsubscribe-ynl, input: {}", input);
489 if (!ynlRegistrations.containsKey(input.getId())) {
490 final RpcError rpcError = RpcResultBuilder
491 .newError(ErrorType.APPLICATION, "missing-registration", "No ynl listener with this id registered.");
492 final RpcResult<UnsubscribeYnlOutput> result =
493 RpcResultBuilder.<UnsubscribeYnlOutput>failed().withRpcError(rpcError).build();
494 return Futures.immediateFuture(result);
497 final ListenerRegistration<YnlListener> registration = ynlRegistrations.remove(input.getId());
498 final UnsubscribeYnlOutput output = registration.getInstance().getOutput();
500 registration.close();
502 return Futures.immediateFuture(RpcResultBuilder.<UnsubscribeYnlOutput>success().withResult(output).build());
506 public Future<RpcResult<CheckPublishNotificationsOutput>> checkPublishNotifications(
507 final CheckPublishNotificationsInput input) {
509 final PublishNotificationsTask task = publishNotificationsTasks.get(input.getId());
512 return Futures.immediateFuture(RpcResultBuilder.success(
513 new CheckPublishNotificationsOutputBuilder().setActive(false)).build());
516 final CheckPublishNotificationsOutputBuilder checkPublishNotificationsOutputBuilder =
517 new CheckPublishNotificationsOutputBuilder().setActive(!task.isFinished());
519 if (task.getLastError() != null) {
520 final StringWriter sw = new StringWriter();
521 final PrintWriter pw = new PrintWriter(sw);
522 task.getLastError().printStackTrace(pw);
523 checkPublishNotificationsOutputBuilder.setLastError(task.getLastError().toString() + sw.toString());
526 final CheckPublishNotificationsOutput output =
527 checkPublishNotificationsOutputBuilder.setPublishCount(task.getCurrentNotif()).build();
529 return Futures.immediateFuture(RpcResultBuilder.success(output).build());
533 public Future<RpcResult<ProduceTransactionsOutput>> produceTransactions(final ProduceTransactionsInput input) {
534 LOG.debug("producer-transactions, input: {}", input);
536 final ProduceTransactionsHandler handler =
537 new ProduceTransactionsHandler(domDataTreeService, input);
539 final SettableFuture<RpcResult<ProduceTransactionsOutput>> settableFuture = SettableFuture.create();
540 handler.start(settableFuture);
542 return settableFuture;
546 public Future<RpcResult<Void>> registerConstant(final RegisterConstantInput input) {
548 LOG.debug("Received register-constant rpc, input: {}", input);
550 if (input.getConstant() == null) {
551 final RpcError error = RpcResultBuilder.newError(
552 ErrorType.RPC, "Invalid input.", "Constant value is null");
553 return Futures.immediateFuture(RpcResultBuilder.<Void>failed().withRpcError(error).build());
556 if (globalGetConstantRegistration != null) {
557 final RpcError error = RpcResultBuilder.newError(ErrorType.RPC, "Registration present.",
558 "There is already a get-constant rpc registered.");
559 return Futures.immediateFuture(RpcResultBuilder.<Void>failed().withRpcError(error).build());
562 globalGetConstantRegistration = GetConstantService.registerNew(domRpcService, input.getConstant());
563 return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
567 public Future<RpcResult<Void>> unregisterDefaultConstant() {
572 public Future<RpcResult<UnsubscribeDdtlOutput>> unsubscribeDdtl() {
573 LOG.debug("Received unsubscribe-ddtl.");
575 if (idIntsDdtl == null || ddtlReg == null) {
576 final RpcError error = RpcResultBuilder.newError(
577 ErrorType.RPC, "Ddtl missing.", "No DOMDataTreeListener registered.");
578 return Futures.immediateFuture(RpcResultBuilder.<UnsubscribeDdtlOutput>failed().withRpcError(error).build());
584 final ReadListener readListener = new ReadListener();
586 final ListenerRegistration<ReadListener> registration = domDataTreeService.registerListener(readListener,
587 Collections.singleton(new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION,
588 ProduceTransactionsHandler.ID_INT_YID))
589 , true, Collections.emptyList());
591 final DataTreeCandidate dataTreeCandidate = readListener.getFirstNotif().get();
592 registration.close();
594 if (!dataTreeCandidate.getRootNode().getDataAfter().isPresent()) {
595 final RpcError error = RpcResultBuilder.newError(
596 ErrorType.APPLICATION, "Final read empty.", "No data read from id-ints list.");
597 return Futures.immediateFuture(RpcResultBuilder.<UnsubscribeDdtlOutput>failed()
598 .withRpcError(error).build());
601 final NormalizedNode<?, ?> lastRead = dataTreeCandidate.getRootNode().getDataAfter().get();
603 return Futures.immediateFuture(
604 RpcResultBuilder.success(new UnsubscribeDdtlOutputBuilder()
605 .setCopyMatches(idIntsDdtl.checkEqual(lastRead))).build());
607 } catch (final DOMDataTreeLoopException | InterruptedException | ExecutionException e) {
608 LOG.error("Unable to read data to verify ddtl data.", e);
609 final RpcError error = RpcResultBuilder.newError(
610 ErrorType.APPLICATION, "Read failed.", "Final read from id-ints failed.");
611 return Futures.immediateFuture(RpcResultBuilder.<UnsubscribeDdtlOutput>failed()
612 .withRpcError(error).build());
616 private static class ReadListener implements DOMDataTreeListener {
618 private Collection<DataTreeCandidate> changes = null;
619 private SettableFuture<DataTreeCandidate> readFuture;
622 public synchronized void onDataTreeChanged(@Nonnull final Collection<DataTreeCandidate> changes,
623 @Nonnull final Map<DOMDataTreeIdentifier, NormalizedNode<?, ?>> subtrees) {
624 Preconditions.checkArgument(changes.size() == 1);
626 if (this.changes == null) {
627 this.changes = changes;
629 readFuture.set(changes.iterator().next());
634 public void onDataTreeFailed(@Nonnull final Collection<DOMDataTreeListeningException> causes) {
635 LOG.error("Read Listener failed. {}", causes);
638 public synchronized ListenableFuture<DataTreeCandidate> getFirstNotif() {
639 if (changes != null) {
640 return Futures.immediateFuture(changes.iterator().next());
643 readFuture = SettableFuture.create();