package org.opendaylight.controller.sal.binding.codegen.impl;
import static org.opendaylight.controller.sal.binding.codegen.RuntimeCodeHelper.setRoutingTable;
-
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
-
+import javax.annotation.concurrent.GuardedBy;
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.codegen.RuntimeCodeHelper;
import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.util.ListenerRegistry;
import org.opendaylight.yangtools.yang.binding.BaseIdentity;
-import org.opendaylight.yangtools.yang.binding.DataContainer;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.RpcService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-
public class RpcRouterCodegenInstance<T extends RpcService> implements //
- RpcRouter<T>, RouteChangeListener<Class<? extends BaseIdentity>, InstanceIdentifier<?>> {
+RpcRouter<T>, RouteChangeListener<Class<? extends BaseIdentity>, InstanceIdentifier<?>> {
private static final Logger LOG = LoggerFactory.getLogger(RpcRouterCodegenInstance.class);
- private T defaultService;
-
private final Class<T> serviceType;
private final T invocationProxy;
private final Map<Class<? extends BaseIdentity>, RpcRoutingTableImpl<? extends BaseIdentity, T>> routingTables;
- private final String name;
-
@SuppressWarnings("unchecked")
- public RpcRouterCodegenInstance(String name,Class<T> type, T routerImpl, Set<Class<? extends BaseIdentity>> contexts,
- Set<Class<? extends DataContainer>> inputs) {
- this.name = name;
+ public RpcRouterCodegenInstance(final String name,final Class<T> type, final T routerImpl, final Iterable<Class<? extends BaseIdentity>> contexts) {
this.listeners = ListenerRegistry.create();
this.serviceType = type;
this.invocationProxy = routerImpl;
@Override
@SuppressWarnings("unchecked")
- public <C extends BaseIdentity> RpcRoutingTable<C, T> getRoutingTable(Class<C> routeContext) {
+ public <C extends BaseIdentity> RpcRoutingTable<C, T> getRoutingTable(final Class<C> routeContext) {
return (RpcRoutingTable<C, T>) routingTables.get(routeContext);
}
@Override
public T getDefaultService() {
- return defaultService;
+ return RuntimeCodeHelper.getDelegate(invocationProxy);
}
@Override
@Override
public <L extends RouteChangeListener<Class<? extends BaseIdentity>, InstanceIdentifier<?>>> ListenerRegistration<L> registerRouteChangeListener(
- L listener) {
+ final L listener) {
return listeners.registerWithType(listener);
}
@Override
- public void onRouteChange(RouteChange<Class<? extends BaseIdentity>, InstanceIdentifier<?>> change) {
+ public void onRouteChange(final RouteChange<Class<? extends BaseIdentity>, InstanceIdentifier<?>> change) {
for (ListenerRegistration<RouteChangeListener<Class<? extends BaseIdentity>, InstanceIdentifier<?>>> listener : listeners) {
try {
listener.getInstance().onRouteChange(change);
}
@Override
- public T getService(Class<? extends BaseIdentity> context, InstanceIdentifier<?> path) {
+ public T getService(final Class<? extends BaseIdentity> context, final InstanceIdentifier<?> path) {
return routingTables.get(context).getRoute(path);
}
@Override
- public RoutedRpcRegistration<T> addRoutedRpcImplementation(T service) {
+ public RoutedRpcRegistration<T> addRoutedRpcImplementation(final T service) {
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<T> registerDefaultService(T service) {
- // TODO Auto-generated method stub
+ public RpcRegistration<T> registerDefaultService(final T service) {
RuntimeCodeHelper.setDelegate(invocationProxy, service);
- return null;
+ return new DefaultRpcImplementationRegistration(service);
}
- private class RoutedRpcRegistrationImpl extends AbstractObjectRegistration<T> implements RoutedRpcRegistration<T> {
+ private final class RoutedRpcRegistrationImpl extends AbstractObjectRegistration<T> implements RoutedRpcRegistration<T> {
+ /*
+ * FIXME: retaining this collection is not completely efficient. We really should be storing
+ * a reference to this registration, as a particular listener may be registered multiple
+ * times -- and then this goes kaboom in various aspects.
+ */
+ @GuardedBy("this")
+ private final Collection<Class<? extends BaseIdentity>> contexts = new ArrayList<>(1);
- public RoutedRpcRegistrationImpl(T instance) {
+ public RoutedRpcRegistrationImpl(final T instance) {
super(instance);
}
}
@Override
- public void registerPath(Class<? extends BaseIdentity> context, InstanceIdentifier<?> path) {
+ public synchronized void registerPath(final Class<? extends BaseIdentity> context, final InstanceIdentifier<?> path) {
+ if (isClosed()) {
+ LOG.debug("Closed registration of {} ignoring new path {}", getInstance(), path);
+ return;
+ }
+
routingTables.get(context).updateRoute(path, getInstance());
+ contexts.add(context);
}
@Override
- public void unregisterPath(Class<? extends BaseIdentity> context, InstanceIdentifier<?> path) {
+ public synchronized void unregisterPath(final Class<? extends BaseIdentity> context, final InstanceIdentifier<?> path) {
+ if (isClosed()) {
+ LOG.debug("Closed unregistration of {} ignoring new path {}", getInstance(), path);
+ return;
+ }
+
routingTables.get(context).removeRoute(path, getInstance());
+ contexts.remove(context);
}
+ @Deprecated
@Override
- public void registerInstance(Class<? extends BaseIdentity> context, InstanceIdentifier<?> instance) {
+ public void registerInstance(final Class<? extends BaseIdentity> context, final InstanceIdentifier<?> instance) {
registerPath(context, instance);
}
+ @Deprecated
@Override
- public void unregisterInstance(Class<? extends BaseIdentity> context, InstanceIdentifier<?> instance) {
+ public void unregisterInstance(final Class<? extends BaseIdentity> context, final InstanceIdentifier<?> instance) {
unregisterPath(context, instance);
}
+ @Override
+ protected synchronized void removeRegistration() {
+ for (Class<? extends BaseIdentity> ctx : contexts) {
+ routingTables.get(ctx).removeAllReferences(getInstance());
+ }
+ contexts.clear();
+ }
+ }
+
+ private final class DefaultRpcImplementationRegistration extends AbstractObjectRegistration<T> implements RpcRegistration<T> {
+
+
+ protected DefaultRpcImplementationRegistration(final T instance) {
+ super(instance);
+ }
+
@Override
protected void removeRegistration() {
+ removeDefaultImplementation(this.getInstance());
+ }
+ @Override
+ public Class<T> getServiceType() {
+ return serviceType;
}
}
+
+
}