From d2d8e123aa7ee34c47f12b959592631c0538482b Mon Sep 17 00:00:00 2001 From: Tomas Cere Date: Thu, 23 Feb 2017 16:15:23 +0100 Subject: [PATCH] BUG 7799: Implement agent RPCs for singleton rapid un-registration testing Change-Id: I080a8af30c2a47e2046b0235ea75055e4c4a51cf Signed-off-by: Tomas Cere --- .../provider/MdsalLowLevelTestProvider.java | 33 ++++++- .../impl/FlappingSingletonService.java | 95 +++++++++++++++++++ 2 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 opendaylight/md-sal/samples/clustering-test-app/provider/src/main/java/org/opendaylight/controller/clustering/it/provider/impl/FlappingSingletonService.java diff --git a/opendaylight/md-sal/samples/clustering-test-app/provider/src/main/java/org/opendaylight/controller/clustering/it/provider/MdsalLowLevelTestProvider.java b/opendaylight/md-sal/samples/clustering-test-app/provider/src/main/java/org/opendaylight/controller/clustering/it/provider/MdsalLowLevelTestProvider.java index 9b3446c93b..bdc2d2f224 100644 --- a/opendaylight/md-sal/samples/clustering-test-app/provider/src/main/java/org/opendaylight/controller/clustering/it/provider/MdsalLowLevelTestProvider.java +++ b/opendaylight/md-sal/samples/clustering-test-app/provider/src/main/java/org/opendaylight/controller/clustering/it/provider/MdsalLowLevelTestProvider.java @@ -12,6 +12,7 @@ import com.google.common.util.concurrent.Futures; 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; @@ -41,6 +42,7 @@ import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.l 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; @@ -72,6 +74,7 @@ public class MdsalLowLevelTestProvider implements OdlMdsalLowlevelControlService private DOMRpcImplementationRegistration globalGetConstantRegistration = null; private ClusterSingletonServiceRegistration getSingletonConstantRegistration; + private FlappingSingletonService flappingSingletonService; public MdsalLowLevelTestProvider(final RpcProviderRegistry rpcRegistry, final DOMRpcProviderService domRpcService, @@ -212,7 +215,23 @@ public class MdsalLowLevelTestProvider implements OdlMdsalLowlevelControlService @Override public Future> 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 result = + RpcResultBuilder.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 @@ -257,7 +276,17 @@ public class MdsalLowLevelTestProvider implements OdlMdsalLowlevelControlService @Override public Future> 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.failed().withRpcError(error).build()); + } + + flappingSingletonService = new FlappingSingletonService(singletonService); + + return Futures.immediateFuture(RpcResultBuilder.success().build()); } @Override diff --git a/opendaylight/md-sal/samples/clustering-test-app/provider/src/main/java/org/opendaylight/controller/clustering/it/provider/impl/FlappingSingletonService.java b/opendaylight/md-sal/samples/clustering-test-app/provider/src/main/java/org/opendaylight/controller/clustering/it/provider/impl/FlappingSingletonService.java new file mode 100644 index 0000000000..21e6acf1c7 --- /dev/null +++ b/opendaylight/md-sal/samples/clustering-test-app/provider/src/main/java/org/opendaylight/controller/clustering/it/provider/impl/FlappingSingletonService.java @@ -0,0 +1,95 @@ +/* + * 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 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; + } +} -- 2.36.6