From ac47319b64d6fad519be729699b0064fb52b668c Mon Sep 17 00:00:00 2001 From: Tony Tkacik Date: Tue, 15 Jul 2014 18:17:38 +0200 Subject: [PATCH] Bug 1225: Fixed bug in registration of default RPC implementation. Change-Id: I302bd0c9aa75e844864d0b7dd692c1d331a563ed Signed-off-by: Tony Tkacik --- .../impl/RpcRouterCodegenInstance.java | 37 ++++- .../binding/impl/RpcProviderRegistryImpl.java | 51 +++---- .../sal/binding/impl/util/MapUtils.java | 36 ----- .../impl/test/RpcProviderRegistryTest.java | 137 ++++++++++++++++++ .../yang/opendaylight-test-routed-rpc.yang | 46 ++++++ 5 files changed, 238 insertions(+), 69 deletions(-) delete mode 100644 opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/MapUtils.java create mode 100644 opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/RpcProviderRegistryTest.java create mode 100644 opendaylight/md-sal/sal-test-model/src/main/yang/opendaylight-test-routed-rpc.yang diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RpcRouterCodegenInstance.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RpcRouterCodegenInstance.java index 052fd2169a..709b62fee2 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RpcRouterCodegenInstance.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RpcRouterCodegenInstance.java @@ -37,8 +37,6 @@ RpcRouter, RouteChangeListener, InstanceIdentif private static final Logger LOG = LoggerFactory.getLogger(RpcRouterCodegenInstance.class); - private T defaultService; - private final Class serviceType; private final T invocationProxy; @@ -49,11 +47,8 @@ RpcRouter, RouteChangeListener, InstanceIdentif private final Map, RpcRoutingTableImpl> routingTables; - private final String name; - @SuppressWarnings("unchecked") public RpcRouterCodegenInstance(final String name,final Class type, final T routerImpl, final Iterable> contexts) { - this.name = name; this.listeners = ListenerRegistry.create(); this.serviceType = type; this.invocationProxy = routerImpl; @@ -90,7 +85,7 @@ RpcRouter, RouteChangeListener, InstanceIdentif @Override public T getDefaultService() { - return defaultService; + return RuntimeCodeHelper.getDelegate(invocationProxy); } @Override @@ -125,11 +120,17 @@ RpcRouter, RouteChangeListener, InstanceIdentif return new RoutedRpcRegistrationImpl(service); } + public void removeDefaultImplementation(final T instance) { + RpcService current = RuntimeCodeHelper.getDelegate(invocationProxy); + if(instance == current) { + RuntimeCodeHelper.setDelegate(invocationProxy, null); + } + } + @Override public RpcRegistration registerDefaultService(final T service) { - // TODO Auto-generated method stub RuntimeCodeHelper.setDelegate(invocationProxy, service); - return null; + return new DefaultRpcImplementationRegistration(service); } private class RoutedRpcRegistrationImpl extends AbstractObjectRegistration implements RoutedRpcRegistration { @@ -168,4 +169,24 @@ RpcRouter, RouteChangeListener, InstanceIdentif } } + + private class DefaultRpcImplementationRegistration extends AbstractObjectRegistration implements RpcRegistration { + + + protected DefaultRpcImplementationRegistration(final T instance) { + super(instance); + } + + @Override + protected void removeRegistration() { + removeDefaultImplementation(this.getInstance()); + } + + @Override + public Class getServiceType() { + return serviceType; + } + } + + } diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/RpcProviderRegistryImpl.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/RpcProviderRegistryImpl.java index 542dfa7e7b..952d84d885 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/RpcProviderRegistryImpl.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/RpcProviderRegistryImpl.java @@ -7,6 +7,15 @@ */ package org.opendaylight.controller.sal.binding.impl; +import static com.google.common.base.Preconditions.checkState; + +import java.util.EventListener; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.WeakHashMap; + import org.opendaylight.controller.md.sal.common.api.routing.RouteChange; import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener; import org.opendaylight.controller.md.sal.common.api.routing.RouteChangePublisher; @@ -28,15 +37,6 @@ import org.opendaylight.yangtools.yang.binding.RpcService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.EventListener; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.WeakHashMap; - -import static com.google.common.base.Preconditions.checkState; - public class RpcProviderRegistryImpl implements // RpcProviderRegistry, // RouteChangePublisher> { @@ -60,19 +60,19 @@ public class RpcProviderRegistryImpl implements // return name; } - public RpcProviderRegistryImpl(String name) { + public RpcProviderRegistryImpl(final String name) { super(); this.name = name; } @Override - public final RoutedRpcRegistration addRoutedRpcImplementation(Class type, - T implementation) throws IllegalStateException { + public final RoutedRpcRegistration addRoutedRpcImplementation(final Class type, + final T implementation) throws IllegalStateException { return getRpcRouter(type).addRoutedRpcImplementation(implementation); } @Override - public final RpcRegistration addRpcImplementation(Class type, T implementation) + public final RpcRegistration addRpcImplementation(final Class type, final T implementation) throws IllegalStateException { @SuppressWarnings("unchecked") RpcRouter potentialRouter = (RpcRouter) rpcRouters.get(type); @@ -92,7 +92,7 @@ public class RpcProviderRegistryImpl implements // @SuppressWarnings("unchecked") @Override - public final T getRpcService(Class type) { + public final T getRpcService(final Class type) { T potentialProxy = (T) publicProxies.get(type); if (potentialProxy != null) { @@ -115,8 +115,8 @@ public class RpcProviderRegistryImpl implements // } } - @SuppressWarnings("unchecked") - public RpcRouter getRpcRouter(Class type) { + @SuppressWarnings({ "unchecked", "rawtypes" }) + public RpcRouter getRpcRouter(final Class type) { RpcRouter potentialRouter = rpcRouters.get(type); if (potentialRouter != null) { return (RpcRouter) potentialRouter; @@ -140,7 +140,7 @@ public class RpcProviderRegistryImpl implements // } } - private void notifyGlobalRpcAdded(Class type) { + private void notifyGlobalRpcAdded(final Class type) { for(ListenerRegistration listener : globalRpcListeners) { try { listener.getInstance().onGlobalRpcRegistered(type); @@ -151,7 +151,7 @@ public class RpcProviderRegistryImpl implements // } - private void notifyListenersRoutedCreated(RpcRouter router) { + private void notifyListenersRoutedCreated(final RpcRouter router) { for (ListenerRegistration listener : routerInstantiationListener) { try { @@ -164,7 +164,7 @@ public class RpcProviderRegistryImpl implements // } public ListenerRegistration registerRouterInstantiationListener( - RouterInstantiationListener listener) { + final RouterInstantiationListener listener) { ListenerRegistration reg = routerInstantiationListener.register(listener); try { for (RpcRouter router : rpcRouters.values()) { @@ -176,9 +176,10 @@ public class RpcProviderRegistryImpl implements // return reg; } + @SuppressWarnings("unchecked") @Override public >> ListenerRegistration registerRouteChangeListener( - L listener) { + final L listener) { return (ListenerRegistration) routeChangeListeners.register(listener); } @@ -186,7 +187,7 @@ public class RpcProviderRegistryImpl implements // return rpcFactory; } - public void setRpcFactory(RuntimeCodeGenerator rpcFactory) { + public void setRpcFactory(final RuntimeCodeGenerator rpcFactory) { this.rpcFactory = rpcFactory; } @@ -194,7 +195,7 @@ public class RpcProviderRegistryImpl implements // void onRpcRouterCreated(RpcRouter router); } - public ListenerRegistration registerGlobalRpcRegistrationListener(GlobalRpcRegistrationListener listener) { + public ListenerRegistration registerGlobalRpcRegistrationListener(final GlobalRpcRegistrationListener listener) { return globalRpcListeners.register(listener); } @@ -209,12 +210,12 @@ public class RpcProviderRegistryImpl implements // private final Class type; - public RouteChangeForwarder(Class type) { + public RouteChangeForwarder(final Class type) { this.type = type; } @Override - public void onRouteChange(RouteChange, InstanceIdentifier> change) { + public void onRouteChange(final RouteChange, InstanceIdentifier> change) { Map>> announcements = new HashMap<>(); for (Entry, Set>> entry : change.getAnnouncements() .entrySet()) { @@ -245,7 +246,7 @@ public class RpcProviderRegistryImpl implements // private final Class serviceType; private RpcProviderRegistryImpl registry; - public RpcProxyRegistration(Class type, T service, RpcProviderRegistryImpl registry) { + public RpcProxyRegistration(final Class type, final T service, final RpcProviderRegistryImpl registry) { super(service); this.serviceType = type; this.registry = registry; diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/MapUtils.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/MapUtils.java deleted file mode 100644 index aa6a9a21e5..0000000000 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/MapUtils.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2014 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.sal.binding.impl.util; - -import com.google.common.collect.Multimap; -import java.util.Collection; -import java.util.HashSet; -import java.util.Map.Entry; -import org.opendaylight.yangtools.concepts.Path; - -@SuppressWarnings("all") -public class MapUtils { - public static

, V extends Object> Collection> getAllChildren(final Multimap map, final P path) { - HashSet> _hashSet = new HashSet>(); - final HashSet> ret = _hashSet; - final Collection> entries = map.entries(); - for (final Entry entry : entries) { - { - final P currentPath = entry.getKey(); - if (path.contains(currentPath)) { - ret.add(entry); - } else if (currentPath.contains(path)){ - ret.add(entry); - } - } - } - return ret; - } -} - diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/RpcProviderRegistryTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/RpcProviderRegistryTest.java new file mode 100644 index 0000000000..110e5b4dce --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/RpcProviderRegistryTest.java @@ -0,0 +1,137 @@ +package org.opendaylight.controller.md.sal.binding.impl.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; +import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.TOP_BAR_KEY; +import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.TOP_FOO_KEY; +import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.path; + +import java.util.Set; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.opendaylight.controller.md.sal.binding.test.AssertCollections; +import org.opendaylight.controller.md.sal.common.api.routing.RouteChange; +import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener; +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration; +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration; +import org.opendaylight.controller.sal.binding.api.rpc.RpcContextIdentifier; +import org.opendaylight.controller.sal.binding.api.rpc.RpcRouter; +import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.bi.ba.rpcservice.rev140701.OpendaylightTestRpcServiceService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.rpc.routing.rev140701.OpendaylightTestRoutedRpcService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.rpc.routing.rev140701.TestContext; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +import com.google.common.util.concurrent.SettableFuture; + + +public class RpcProviderRegistryTest { + + private static InstanceIdentifier FOO_PATH = path(TOP_FOO_KEY); + private static InstanceIdentifier BAR_PATH = path(TOP_BAR_KEY); + private static RpcContextIdentifier ROUTING_CONTEXT = RpcContextIdentifier.contextFor(OpendaylightTestRoutedRpcService.class, TestContext.class); + + private RpcProviderRegistryImpl rpcRegistry; + + @Before + public void setup() { + rpcRegistry = new RpcProviderRegistryImpl("test"); + } + + private static class TestListener implements RouteChangeListener> { + + final SettableFuture>> event = SettableFuture.create(); + @Override + public void onRouteChange( + final RouteChange> change) { + event.set(change); + } + } + + @Test + public void testGlobalRpcRegistrations() throws Exception { + OpendaylightTestRpcServiceService one = Mockito.mock(OpendaylightTestRpcServiceService.class); + OpendaylightTestRpcServiceService two = Mockito.mock(OpendaylightTestRpcServiceService.class); + + RpcRegistration regOne = rpcRegistry.addRpcImplementation(OpendaylightTestRpcServiceService.class, one); + assertNotNull(regOne); + + try { + rpcRegistry.addRpcImplementation(OpendaylightTestRpcServiceService.class, two); + fail("Second call for registration of same RPC must throw IllegalStateException"); + } catch (IllegalStateException e) { + assertNotNull(e.getMessage()); + } + + regOne.close(); + + RpcRegistration regTwo = rpcRegistry.addRpcImplementation(OpendaylightTestRpcServiceService.class, two); + assertNotNull(regTwo); + } + + @Test + public void testRpcRouterInstance() throws Exception { + OpendaylightTestRoutedRpcService def = Mockito.mock(OpendaylightTestRoutedRpcService.class); + + RpcRouter router = rpcRegistry.getRpcRouter(OpendaylightTestRoutedRpcService.class); + + assertEquals(OpendaylightTestRoutedRpcService.class, router.getServiceType()); + assertNotNull(router.getInvocationProxy()); + assertNull(router.getDefaultService()); + + AssertCollections.assertContains(router.getContexts(), TestContext.class); + + RpcRegistration regDef = router.registerDefaultService(def); + assertNotNull(regDef); + assertEquals(OpendaylightTestRoutedRpcService.class,regDef.getServiceType()); + assertEquals(def,regDef.getInstance()); + assertEquals(def, router.getDefaultService()); + + regDef.close(); + assertNull("Default instance should be null after closing registration", router.getDefaultService()); + } + + @Test + public void testRoutedRpcPathChangeEvents() throws InterruptedException, TimeoutException, ExecutionException { + OpendaylightTestRoutedRpcService one = Mockito.mock(OpendaylightTestRoutedRpcService.class); + OpendaylightTestRoutedRpcService two = Mockito.mock(OpendaylightTestRoutedRpcService.class); + RoutedRpcRegistration regOne = rpcRegistry.addRoutedRpcImplementation(OpendaylightTestRoutedRpcService.class, one); + RoutedRpcRegistration regTwo = rpcRegistry.addRoutedRpcImplementation(OpendaylightTestRoutedRpcService.class, two); + assertNotNull(regOne); + assertNotNull(regTwo); + + final TestListener addListener = new TestListener(); + rpcRegistry.registerRouteChangeListener(addListener); + regOne.registerPath(TestContext.class, FOO_PATH); + + RouteChange> fooAddEvent = addListener.event.get(500, TimeUnit.MILLISECONDS); + Set> announce = fooAddEvent.getAnnouncements().get(ROUTING_CONTEXT); + assertNotNull(announce); + AssertCollections.assertContains(announce, FOO_PATH); + AssertCollections.assertNotContains(announce, BAR_PATH); + + + + final TestListener removeListener = new TestListener(); + rpcRegistry.registerRouteChangeListener(removeListener); + + regOne.unregisterPath(TestContext.class, FOO_PATH); + + RouteChange> fooRemoveEvent = removeListener.event.get(500, TimeUnit.MILLISECONDS); + Set> removal = fooRemoveEvent.getRemovals().get(ROUTING_CONTEXT); + assertNotNull(removal); + AssertCollections.assertContains(removal, FOO_PATH); + AssertCollections.assertNotContains(removal, BAR_PATH); + + + } + +} diff --git a/opendaylight/md-sal/sal-test-model/src/main/yang/opendaylight-test-routed-rpc.yang b/opendaylight/md-sal/sal-test-model/src/main/yang/opendaylight-test-routed-rpc.yang new file mode 100644 index 0000000000..c3a982473c --- /dev/null +++ b/opendaylight/md-sal/sal-test-model/src/main/yang/opendaylight-test-routed-rpc.yang @@ -0,0 +1,46 @@ +module opendaylight-test-routed-rpc { + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:test:rpc:routing"; + prefix "rpc"; + import yang-ext { prefix ext; } + + description + "Test model for testing of registering rpc service on binding independent mount point + and retrieving rpc service via binding aware mount point."; + + revision "2014-07-01" { + description + "Initial revision"; + } + + identity test-context { + description "Test Context"; + } + + typedef encapsulated-route { + type instance-identifier; + } + + grouping route-in-grouping { + leaf route { + type instance-identifier; + ext:context-reference test-context; + } + } + + grouping encapsulated-route-in-grouping { + leaf route { + type encapsulated-route; + ext:context-reference test-context; + } + } + + rpc routed-simple-route { + input { + leaf route { + type instance-identifier; + ext:context-reference test-context; + } + } + } +} -- 2.36.6