X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=dom%2Fmdsal-dom-broker%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fmdsal%2Fdom%2Fbroker%2FDOMRpcRouter.java;h=76323b059e7dc91f84f26275427d0469417b3c50;hb=11408d627adca7eb71ac956c3ad01f75b6b91596;hp=c6f1acaa5aaca8a494690afe2d2c04d17624c3fe;hpb=63e9fad5de185e4721aa1ad370630c4bade1201f;p=mdsal.git diff --git a/dom/mdsal-dom-broker/src/main/java/org/opendaylight/mdsal/dom/broker/DOMRpcRouter.java b/dom/mdsal-dom-broker/src/main/java/org/opendaylight/mdsal/dom/broker/DOMRpcRouter.java index c6f1acaa5a..76323b059e 100644 --- a/dom/mdsal-dom-broker/src/main/java/org/opendaylight/mdsal/dom/broker/DOMRpcRouter.java +++ b/dom/mdsal-dom-broker/src/main/java/org/opendaylight/mdsal/dom/broker/DOMRpcRouter.java @@ -16,7 +16,6 @@ import com.google.common.collect.ClassToInstanceMap; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableClassToInstanceMap; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableList.Builder; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.MapDifference; @@ -26,10 +25,8 @@ import com.google.common.collect.Sets; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ThreadFactoryBuilder; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -39,6 +36,7 @@ import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; +import javax.annotation.PreDestroy; import javax.inject.Inject; import javax.inject.Singleton; import org.checkerframework.checker.lock.qual.GuardedBy; @@ -50,7 +48,6 @@ import org.opendaylight.mdsal.dom.api.DOMActionImplementation; import org.opendaylight.mdsal.dom.api.DOMActionInstance; import org.opendaylight.mdsal.dom.api.DOMActionNotAvailableException; import org.opendaylight.mdsal.dom.api.DOMActionProviderService; -import org.opendaylight.mdsal.dom.api.DOMActionProviderServiceExtension; import org.opendaylight.mdsal.dom.api.DOMActionResult; import org.opendaylight.mdsal.dom.api.DOMActionService; import org.opendaylight.mdsal.dom.api.DOMActionServiceExtension; @@ -78,12 +75,20 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes; import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; import org.opendaylight.yangtools.yang.model.api.EffectiveModelContextListener; import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Deactivate; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.RequireServiceComponentRuntime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Singleton +@Component(immediate = true, service = DOMRpcRouterServices.class) +@RequireServiceComponentRuntime public final class DOMRpcRouter extends AbstractRegistration implements DOMRpcRouterServices, EffectiveModelContextListener { + private static final Logger LOG = LoggerFactory.getLogger(DOMRpcRouter.class); private static final ThreadFactory THREAD_FACTORY = new ThreadFactoryBuilder().setNameFormat( "DOMRpcRouter-listener-%s").setDaemon(true).build(); @@ -94,10 +99,10 @@ public final class DOMRpcRouter extends AbstractRegistration private final @NonNull DOMRpcService rpcService = new RpcServiceFacade(); @GuardedBy("this") - private Collection> listeners = Collections.emptyList(); + private ImmutableList> listeners = ImmutableList.of(); @GuardedBy("this") - private Collection> actionListeners = Collections.emptyList(); + private ImmutableList> actionListeners = ImmutableList.of(); private volatile DOMRpcRoutingTable routingTable = DOMRpcRoutingTable.EMPTY; @@ -105,11 +110,29 @@ public final class DOMRpcRouter extends AbstractRegistration private ListenerRegistration listenerRegistration; + @Deprecated + @VisibleForTesting + // FIXME: 9.0.0: make this constructor package-private + public DOMRpcRouter() { + + } + @Inject + @Activate + public DOMRpcRouter(@Reference final DOMSchemaService schemaService) { + listenerRegistration = schemaService.registerSchemaContextListener(this); + LOG.info("DOM RPC/Action router started"); + } + + @Deprecated(forRemoval = true) public static DOMRpcRouter newInstance(final DOMSchemaService schemaService) { - final DOMRpcRouter rpcRouter = new DOMRpcRouter(); - rpcRouter.listenerRegistration = schemaService.registerSchemaContextListener(rpcRouter); - return rpcRouter; + return new DOMRpcRouter(schemaService); + } + + @PreDestroy + @Deactivate + public void shutdown() { + close(); } @Override @@ -132,8 +155,6 @@ public final class DOMRpcRouter extends AbstractRegistration return rpcProviderService; } - @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD", - justification = "https://github.com/spotbugs/spotbugs/issues/811") private synchronized void removeRpcImplementation(final DOMRpcImplementation implementation, final Set rpcs) { final DOMRpcRoutingTable oldTable = routingTable; @@ -143,8 +164,6 @@ public final class DOMRpcRouter extends AbstractRegistration listenerNotifier.execute(() -> notifyRemoved(newTable, implementation)); } - @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD", - justification = "https://github.com/spotbugs/spotbugs/issues/811") private synchronized void removeRpcImplementations(final Map map) { final DOMRpcRoutingTable oldTable = routingTable; final DOMRpcRoutingTable newTable = (DOMRpcRoutingTable) oldTable.removeAll(map); @@ -153,8 +172,6 @@ public final class DOMRpcRouter extends AbstractRegistration listenerNotifier.execute(() -> notifyRemoved(newTable, map.values())); } - @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD", - justification = "https://github.com/spotbugs/spotbugs/issues/811") private synchronized void removeActionImplementation(final DOMActionImplementation implementation, final Set actions) { final DOMActionRoutingTable oldTable = actionRoutingTable; @@ -164,28 +181,20 @@ public final class DOMRpcRouter extends AbstractRegistration listenerNotifier.execute(() -> notifyActionChanged(newTable, implementation)); } - @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD", - justification = "https://github.com/spotbugs/spotbugs/issues/811") private synchronized void removeListener(final ListenerRegistration reg) { listeners = ImmutableList.copyOf(Collections2.filter(listeners, input -> !reg.equals(input))); } - @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD", - justification = "https://github.com/spotbugs/spotbugs/issues/811") private synchronized void removeActionListener(final ListenerRegistration reg) { actionListeners = ImmutableList.copyOf(Collections2.filter(actionListeners, input -> !reg.equals(input))); } - @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD", - justification = "https://github.com/spotbugs/spotbugs/issues/811") private synchronized void notifyAdded(final DOMRpcRoutingTable newTable, final DOMRpcImplementation impl) { for (Registration l : listeners) { l.addRpc(newTable, impl); } } - @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD", - justification = "https://github.com/spotbugs/spotbugs/issues/811") private synchronized void notifyAdded(final DOMRpcRoutingTable newTable, final Collection impls) { for (Registration l : listeners) { @@ -195,16 +204,12 @@ public final class DOMRpcRouter extends AbstractRegistration } } - @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD", - justification = "https://github.com/spotbugs/spotbugs/issues/811") private synchronized void notifyRemoved(final DOMRpcRoutingTable newTable, final DOMRpcImplementation impl) { for (Registration l : listeners) { l.removeRpc(newTable, impl); } } - @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD", - justification = "https://github.com/spotbugs/spotbugs/issues/811") private synchronized void notifyRemoved(final DOMRpcRoutingTable newTable, final Collection impls) { for (Registration l : listeners) { @@ -240,13 +245,19 @@ public final class DOMRpcRouter extends AbstractRegistration listenerRegistration = null; } listenerNotifier.shutdown(); + LOG.info("DOM RPC/Action router stopped"); } @VisibleForTesting - synchronized Collection listeners() { + synchronized List listeners() { return listeners; } + @VisibleForTesting + synchronized List actionListeners() { + return actionListeners; + } + @VisibleForTesting DOMRpcRoutingTable routingTable() { return routingTable; @@ -271,7 +282,7 @@ public final class DOMRpcRouter extends AbstractRegistration } void initialTable() { - final Collection added = new ArrayList<>(); + final List added = new ArrayList<>(); for (Entry> e : prevRpcs.entrySet()) { added.addAll(Collections2.transform(e.getValue(), i -> DOMRpcIdentifier.create(e.getKey(), i))); } @@ -289,7 +300,7 @@ public final class DOMRpcRouter extends AbstractRegistration final Map> rpcs = verifyNotNull(newTable.getOperations(l)); final MapDifference> diff = Maps.difference(prevRpcs, rpcs); - final Collection added = new ArrayList<>(); + final List added = new ArrayList<>(); for (Entry> e : diff.entriesOnlyOnRight().entrySet()) { added.addAll(Collections2.transform(e.getValue(), i -> DOMRpcIdentifier.create(e.getKey(), i))); } @@ -314,7 +325,7 @@ public final class DOMRpcRouter extends AbstractRegistration final Map> rpcs = verifyNotNull(newTable.getOperations(l)); final MapDifference> diff = Maps.difference(prevRpcs, rpcs); - final Collection removed = new ArrayList<>(); + final List removed = new ArrayList<>(); for (Entry> e : diff.entriesOnlyOnLeft().entrySet()) { removed.addAll(Collections2.transform(e.getValue(), i -> DOMRpcIdentifier.create(e.getKey(), i))); } @@ -351,7 +362,7 @@ public final class DOMRpcRouter extends AbstractRegistration } void initialTable() { - final Collection added = new ArrayList<>(); + final List added = new ArrayList<>(); for (Entry> e : prevActions.entrySet()) { added.addAll(Collections2.transform(e.getValue(), i -> DOMActionInstance.of(e.getKey(), i))); } @@ -402,12 +413,12 @@ public final class DOMRpcRouter extends AbstractRegistration @Override public ListenerRegistration registerAvailabilityListener(final T listener) { synchronized (DOMRpcRouter.this) { - final ActionRegistration ret = new ActionRegistration<>(DOMRpcRouter.this, - listener, actionRoutingTable.getOperations(listener)); - final Builder> b = ImmutableList.builder(); - b.addAll(actionListeners); - b.add(ret); - actionListeners = b.build(); + final ActionRegistration ret = new ActionRegistration<>(DOMRpcRouter.this, listener, + actionRoutingTable.getOperations(listener)); + actionListeners = ImmutableList.>builder() + .addAll(actionListeners) + .add(ret) + .build(); listenerNotifier.execute(ret::initialTable); return ret; @@ -428,26 +439,21 @@ public final class DOMRpcRouter extends AbstractRegistration @Override public ListenableFuture invokeAction(final Absolute type, final DOMDataTreeIdentifier path, final ContainerNode input) { + final YangInstanceIdentifier pathRoot = path.getRootIdentifier(); + checkArgument(!pathRoot.isEmpty(), "Action path must not be empty"); + final DOMActionRoutingTableEntry entry = (DOMActionRoutingTableEntry) actionRoutingTable.getEntry(type); - if (entry == null) { - return Futures.immediateFailedFuture( + return entry != null ? OperationInvocation.invoke(entry, type, path, requireNonNull(input)) + : Futures.immediateFailedFuture( new DOMActionNotAvailableException("No implementation of Action %s available", type)); - } - - return OperationInvocation.invoke(entry, type, path, requireNonNull(input)); } } @NonNullByDefault private final class ActionProviderServiceFacade implements DOMActionProviderService { - @Override - public ClassToInstanceMap getExtensions() { - return ImmutableClassToInstanceMap.of(); - } - @Override public ObjectRegistration registerActionImplementation( - final T implementation, final Set instances) { + final T implementation, final Set instances) { synchronized (DOMRpcRouter.this) { final DOMActionRoutingTable oldTable = actionRoutingTable; @@ -468,7 +474,7 @@ public final class DOMRpcRouter extends AbstractRegistration private final class RpcServiceFacade implements DOMRpcService { @Override - public ListenableFuture invokeRpc(final QName type, final NormalizedNode input) { + public ListenableFuture invokeRpc(final QName type, final NormalizedNode input) { final AbstractDOMRpcRoutingTableEntry entry = (AbstractDOMRpcRoutingTableEntry) routingTable.getEntry(type); if (entry == null) { return Futures.immediateFailedFuture( @@ -483,10 +489,7 @@ public final class DOMRpcRouter extends AbstractRegistration synchronized (DOMRpcRouter.this) { final Registration ret = new Registration<>(DOMRpcRouter.this, listener, routingTable.getOperations(listener)); - final Builder> b = ImmutableList.builder(); - b.addAll(listeners); - b.add(ret); - listeners = b.build(); + listeners = ImmutableList.>builder().addAll(listeners).add(ret).build(); listenerNotifier.execute(ret::initialTable); return ret; @@ -549,11 +552,21 @@ public final class DOMRpcRouter extends AbstractRegistration static ListenableFuture invoke(final DOMActionRoutingTableEntry entry, final Absolute type, final DOMDataTreeIdentifier path, final ContainerNode input) { - return entry.getImplementations(path).get(0).invokeAction(type, path, input); + List impls = entry.getImplementations(path); + if (impls == null) { + impls = entry.getImplementations( + new DOMDataTreeIdentifier(path.getDatastoreType(), YangInstanceIdentifier.empty())); + if (impls == null) { + return Futures.immediateFailedFuture(new DOMActionNotAvailableException( + "No implementation of Action %s available for %s", type, path)); + } + } + + return impls.get(0).invokeAction(type, path, input); } static ListenableFuture invoke(final AbstractDOMRpcRoutingTableEntry entry, - final NormalizedNode input) { + final NormalizedNode input) { if (entry instanceof UnknownDOMRpcRoutingTableEntry) { return Futures.immediateFailedFuture( new DOMRpcImplementationNotAvailableException("%s is not resolved to an RPC", entry.getType())); @@ -568,14 +581,14 @@ public final class DOMRpcRouter extends AbstractRegistration } private static ListenableFuture invokeRoutedRpc( - final RoutedDOMRpcRoutingTableEntry entry, final NormalizedNode input) { - final Optional> maybeKey = NormalizedNodes.findNode(input, + final RoutedDOMRpcRoutingTableEntry entry, final NormalizedNode input) { + final Optional maybeKey = NormalizedNodes.findNode(input, entry.getRpcId().getContextReference()); // Routing key is present, attempt to deliver as a routed RPC if (maybeKey.isPresent()) { - final NormalizedNode key = maybeKey.get(); - final Object value = key.getValue(); + final NormalizedNode key = maybeKey.get(); + final Object value = key.body(); if (value instanceof YangInstanceIdentifier) { final YangInstanceIdentifier iid = (YangInstanceIdentifier) value; @@ -614,7 +627,7 @@ public final class DOMRpcRouter extends AbstractRegistration } private static ListenableFuture invokeGlobalRpc( - final GlobalDOMRpcRoutingTableEntry entry, final NormalizedNode input) { + final GlobalDOMRpcRoutingTableEntry entry, final NormalizedNode input) { return entry.getImplementations(YangInstanceIdentifier.empty()).get(0).invokeRpc(entry.getRpcId(), input); } }