import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Future;
+import org.opendaylight.controller.clustering.it.provider.impl.FlappingSingletonService;
import org.opendaylight.controller.clustering.it.provider.impl.GetConstantService;
import org.opendaylight.controller.clustering.it.provider.impl.RoutedGetConstantService;
import org.opendaylight.controller.clustering.it.provider.impl.SingletonGetConstantService;
import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.SubscribeYnlInput;
import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnregisterBoundConstantInput;
import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnregisterFlappingSingletonOutput;
+import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnregisterFlappingSingletonOutputBuilder;
import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnsubscribeDdtlOutput;
import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnsubscribeDtclOutput;
import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnsubscribeYnlInput;
private DOMRpcImplementationRegistration<GetConstantService> globalGetConstantRegistration = null;
private ClusterSingletonServiceRegistration getSingletonConstantRegistration;
+ private FlappingSingletonService flappingSingletonService;
public MdsalLowLevelTestProvider(final RpcProviderRegistry rpcRegistry,
final DOMRpcProviderService domRpcService,
@Override
public Future<RpcResult<UnregisterFlappingSingletonOutput>> unregisterFlappingSingleton() {
- return null;
+ LOG.debug("unregister-flapping-singleton received.");
+
+ if (flappingSingletonService == null) {
+ final RpcError rpcError = RpcResultBuilder
+ .newError(ErrorType.APPLICATION, "missing-registration", "No flapping-singleton registration present.");
+ final RpcResult<UnregisterFlappingSingletonOutput> result =
+ RpcResultBuilder.<UnregisterFlappingSingletonOutput>failed().withRpcError(rpcError).build();
+ return Futures.immediateFuture(result);
+ }
+
+ final long flapCount = flappingSingletonService.setInactive();
+ flappingSingletonService = null;
+
+ final UnregisterFlappingSingletonOutput output =
+ new UnregisterFlappingSingletonOutputBuilder().setFlapCount(flapCount).build();
+
+ return Futures.immediateFuture(RpcResultBuilder.success(output).build());
}
@Override
@Override
public Future<RpcResult<Void>> registerFlappingSingleton() {
- return null;
+ LOG.debug("Received register-flapping-singleton.");
+
+ if (flappingSingletonService != null) {
+ final RpcError error = RpcResultBuilder.newError(
+ ErrorType.RPC, "Registration present.", "flappin-singleton already registered");
+ return Futures.immediateFuture(RpcResultBuilder.<Void>failed().withRpcError(error).build());
+ }
+
+ flappingSingletonService = new FlappingSingletonService(singletonService);
+
+ return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
}
@Override
--- /dev/null
+/*
+ * Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.clustering.it.provider.impl;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
+import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
+import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
+import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FlappingSingletonService implements ClusterSingletonService {
+
+ private static final Logger LOG = LoggerFactory.getLogger(FlappingSingletonService.class);
+
+ private static final ServiceGroupIdentifier SERVICE_GROUP_IDENTIFIER =
+ ServiceGroupIdentifier.create("flapping-singleton-service");
+
+ private final ClusterSingletonServiceProvider singletonServiceProvider;
+
+ private volatile long flapCount = 0;
+ private AtomicBoolean active = new AtomicBoolean(true);
+
+ private volatile ClusterSingletonServiceRegistration registration;
+
+ private static ScheduledExecutorService EXECUTOR = Executors.newSingleThreadScheduledExecutor();
+
+ public FlappingSingletonService(final ClusterSingletonServiceProvider singletonServiceProvider) {
+ LOG.debug("Registering flapping-singleton-service.");
+
+ this.singletonServiceProvider = singletonServiceProvider;
+ registration = singletonServiceProvider.registerClusterSingletonService(this);
+ }
+
+ @Override
+ public void instantiateServiceInstance() {
+ LOG.debug("Instantiating flapping-singleton-service.");
+
+ // TODO direct registration/close seem to trigger a bug in singleton state transitions,
+ // remove the whole executor shenanigans after it's fixed.
+ EXECUTOR.submit(() -> {
+ try {
+ registration.close();
+ registration = null;
+ } catch (final Exception e) {
+ LOG.warn("There was a problem closing flapping singleton service.", e);
+ flapCount = -flapCount;
+ }
+ });
+ }
+
+ @Override
+ public ListenableFuture<Void> closeServiceInstance() {
+ LOG.debug("Closing flapping-singleton-service, flapCount: {}", flapCount);
+
+ flapCount++;
+ if (active.get()) {
+ // TODO direct registration/close seem to trigger a bug in singleton state transitions,
+ // remove whole executor shenanigans after it's fixed.
+ // Needs to be delayed slightly otherwise it's triggered as well.
+ EXECUTOR.schedule(() -> {
+ LOG.debug("Running registration");
+ registration =
+ singletonServiceProvider.registerClusterSingletonService(this);
+
+ }, 200, TimeUnit.MILLISECONDS);
+ }
+
+ return Futures.immediateFuture(null);
+ }
+
+ @Override
+ public ServiceGroupIdentifier getIdentifier() {
+ return SERVICE_GROUP_IDENTIFIER;
+ }
+
+ public long setInactive() {
+ LOG.debug("Setting flapping-singleton-service to inactive, flap-count: {}", flapCount);
+
+ active.set(false);
+ return flapCount;
+ }
+}