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=3b6587a80285a68bdfb22af085506872a8a4ce40;hb=5f8a373c07549a901b70595067dd11c161d0c4e4;hp=d997dfa3f5e00b98afb33b88750bbca602448ed4;hpb=01c6b621ff68c728f2e739d1d20cbbea54f2e5ce;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 d997dfa3f5..3b6587a802 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 @@ -12,12 +12,10 @@ import static com.google.common.base.Verify.verifyNotNull; import static java.util.Objects.requireNonNull; import com.google.common.annotations.VisibleForTesting; -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.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableTable; import com.google.common.collect.MapDifference; import com.google.common.collect.MapDifference.ValueDifference; import com.google.common.collect.Maps; @@ -31,7 +29,6 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Optional; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -50,28 +47,20 @@ import org.opendaylight.mdsal.dom.api.DOMActionNotAvailableException; import org.opendaylight.mdsal.dom.api.DOMActionProviderService; import org.opendaylight.mdsal.dom.api.DOMActionResult; import org.opendaylight.mdsal.dom.api.DOMActionService; -import org.opendaylight.mdsal.dom.api.DOMActionServiceExtension; import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier; import org.opendaylight.mdsal.dom.api.DOMRpcAvailabilityListener; import org.opendaylight.mdsal.dom.api.DOMRpcIdentifier; import org.opendaylight.mdsal.dom.api.DOMRpcImplementation; import org.opendaylight.mdsal.dom.api.DOMRpcImplementationNotAvailableException; -import org.opendaylight.mdsal.dom.api.DOMRpcImplementationRegistration; import org.opendaylight.mdsal.dom.api.DOMRpcProviderService; import org.opendaylight.mdsal.dom.api.DOMRpcResult; import org.opendaylight.mdsal.dom.api.DOMRpcService; import org.opendaylight.mdsal.dom.api.DOMSchemaService; -import org.opendaylight.mdsal.dom.spi.AbstractDOMRpcImplementationRegistration; -import org.opendaylight.yangtools.concepts.AbstractListenerRegistration; -import org.opendaylight.yangtools.concepts.AbstractObjectRegistration; import org.opendaylight.yangtools.concepts.AbstractRegistration; -import org.opendaylight.yangtools.concepts.ListenerRegistration; -import org.opendaylight.yangtools.concepts.ObjectRegistration; +import org.opendaylight.yangtools.concepts.Registration; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; -import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; -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; @@ -79,15 +68,12 @@ 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 { +@Component(service = DOMRpcRouter.class) +public final class DOMRpcRouter extends AbstractRegistration implements 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(); @@ -99,16 +85,16 @@ public final class DOMRpcRouter extends AbstractRegistration private final @NonNull DOMRpcService rpcService = new RpcServiceFacade(); @GuardedBy("this") - private ImmutableList> listeners = ImmutableList.of(); + private ImmutableList listeners = ImmutableList.of(); @GuardedBy("this") - private ImmutableList> actionListeners = ImmutableList.of(); + private ImmutableList actionListeners = ImmutableList.of(); private volatile DOMRpcRoutingTable routingTable = DOMRpcRoutingTable.EMPTY; private volatile DOMActionRoutingTable actionRoutingTable = DOMActionRoutingTable.EMPTY; - private ListenerRegistration listenerRegistration; + private Registration listenerRegistration; @Deprecated @VisibleForTesting @@ -135,23 +121,19 @@ public final class DOMRpcRouter extends AbstractRegistration close(); } - @Override - public DOMActionService getActionService() { + public @NonNull DOMActionService actionService() { return actionService; } - @Override - public DOMActionProviderService getActionProviderService() { + public @NonNull DOMActionProviderService actionProviderService() { return actionProviderService; } - @Override - public DOMRpcService getRpcService() { + public @NonNull DOMRpcService rpcService() { return rpcService; } - @Override - public DOMRpcProviderService getRpcProviderService() { + public @NonNull DOMRpcProviderService rpcProviderService() { return rpcProviderService; } @@ -164,12 +146,13 @@ public final class DOMRpcRouter extends AbstractRegistration listenerNotifier.execute(() -> notifyRemoved(newTable, implementation)); } - private synchronized void removeRpcImplementations(final Map map) { + private synchronized void removeRpcImplementations( + final ImmutableTable implTable) { final DOMRpcRoutingTable oldTable = routingTable; - final DOMRpcRoutingTable newTable = (DOMRpcRoutingTable) oldTable.removeAll(map); + final DOMRpcRoutingTable newTable = (DOMRpcRoutingTable) oldTable.removeAll(implTable); routingTable = newTable; - listenerNotifier.execute(() -> notifyRemoved(newTable, map.values())); + listenerNotifier.execute(() -> notifyRemoved(newTable, implTable.values())); } private synchronized void removeActionImplementation(final DOMActionImplementation implementation, @@ -181,38 +164,38 @@ public final class DOMRpcRouter extends AbstractRegistration listenerNotifier.execute(() -> notifyActionChanged(newTable, implementation)); } - private synchronized void removeListener(final ListenerRegistration reg) { + private synchronized void removeListener(final RpcAvailReg reg) { listeners = ImmutableList.copyOf(Collections2.filter(listeners, input -> !reg.equals(input))); } - private synchronized void removeActionListener(final ListenerRegistration reg) { + private synchronized void removeActionListener(final ActionAvailReg reg) { actionListeners = ImmutableList.copyOf(Collections2.filter(actionListeners, input -> !reg.equals(input))); } private synchronized void notifyAdded(final DOMRpcRoutingTable newTable, final DOMRpcImplementation impl) { - for (Registration l : listeners) { + for (var l : listeners) { l.addRpc(newTable, impl); } } private synchronized void notifyAdded(final DOMRpcRoutingTable newTable, final Collection impls) { - for (Registration l : listeners) { - for (DOMRpcImplementation impl : impls) { + for (var l : listeners) { + for (var impl : impls) { l.addRpc(newTable, impl); } } } private synchronized void notifyRemoved(final DOMRpcRoutingTable newTable, final DOMRpcImplementation impl) { - for (Registration l : listeners) { + for (var l : listeners) { l.removeRpc(newTable, impl); } } private synchronized void notifyRemoved(final DOMRpcRoutingTable newTable, final Collection impls) { - for (Registration l : listeners) { + for (var l : listeners) { for (DOMRpcImplementation impl : impls) { l.removeRpc(newTable, impl); } @@ -221,7 +204,7 @@ public final class DOMRpcRouter extends AbstractRegistration private synchronized void notifyActionChanged(final DOMActionRoutingTable newTable, final DOMActionImplementation impl) { - for (ActionRegistration l : actionListeners) { + for (var l : actionListeners) { l.actionChanged(newTable, impl); } } @@ -263,16 +246,17 @@ public final class DOMRpcRouter extends AbstractRegistration return routingTable; } - private static final class Registration - extends AbstractListenerRegistration { + private static final class RpcAvailReg extends AbstractRegistration { + private final DOMRpcAvailabilityListener listener; private Map> prevRpcs; private DOMRpcRouter router; - Registration(final DOMRpcRouter router, final T listener, final Map> rpcs) { - super(listener); + RpcAvailReg(final DOMRpcRouter router, final DOMRpcAvailabilityListener listener, + final Map> rpcs) { + this.listener = requireNonNull(listener); this.router = requireNonNull(router); - this.prevRpcs = requireNonNull(rpcs); + prevRpcs = requireNonNull(rpcs); } @Override @@ -287,17 +271,16 @@ public final class DOMRpcRouter extends AbstractRegistration added.addAll(Collections2.transform(e.getValue(), i -> DOMRpcIdentifier.create(e.getKey(), i))); } if (!added.isEmpty()) { - getInstance().onRpcAvailable(added); + listener.onRpcAvailable(added); } } void addRpc(final DOMRpcRoutingTable newTable, final DOMRpcImplementation impl) { - final T l = getInstance(); - if (!l.acceptsImplementation(impl)) { + if (!listener.acceptsImplementation(impl)) { return; } - final Map> rpcs = verifyNotNull(newTable.getOperations(l)); + final Map> rpcs = verifyNotNull(newTable.getOperations(listener)); final MapDifference> diff = Maps.difference(prevRpcs, rpcs); final List added = new ArrayList<>(); @@ -312,17 +295,16 @@ public final class DOMRpcRouter extends AbstractRegistration prevRpcs = rpcs; if (!added.isEmpty()) { - l.onRpcAvailable(added); + listener.onRpcAvailable(added); } } void removeRpc(final DOMRpcRoutingTable newTable, final DOMRpcImplementation impl) { - final T l = getInstance(); - if (!l.acceptsImplementation(impl)) { + if (!listener.acceptsImplementation(impl)) { return; } - final Map> rpcs = verifyNotNull(newTable.getOperations(l)); + final Map> rpcs = verifyNotNull(newTable.getOperations(listener)); final MapDifference> diff = Maps.difference(prevRpcs, rpcs); final List removed = new ArrayList<>(); @@ -337,22 +319,22 @@ public final class DOMRpcRouter extends AbstractRegistration prevRpcs = rpcs; if (!removed.isEmpty()) { - l.onRpcUnavailable(removed); + listener.onRpcUnavailable(removed); } } } - private static final class ActionRegistration - extends AbstractListenerRegistration { + private static final class ActionAvailReg extends AbstractRegistration { + private final AvailabilityListener listener; private Map> prevActions; private DOMRpcRouter router; - ActionRegistration(final DOMRpcRouter router, final T listener, + ActionAvailReg(final DOMRpcRouter router, final AvailabilityListener listener, final Map> actions) { - super(listener); + this.listener = requireNonNull(listener); this.router = requireNonNull(router); - this.prevActions = requireNonNull(actions); + prevActions = requireNonNull(actions); } @Override @@ -362,22 +344,21 @@ public final class DOMRpcRouter extends AbstractRegistration } void initialTable() { - final List added = new ArrayList<>(); - for (Entry> e : prevActions.entrySet()) { + final var added = new ArrayList(); + for (var e : prevActions.entrySet()) { added.addAll(Collections2.transform(e.getValue(), i -> DOMActionInstance.of(e.getKey(), i))); } if (!added.isEmpty()) { - getInstance().onActionsChanged(ImmutableSet.of(), ImmutableSet.copyOf(added)); + listener.onActionsChanged(ImmutableSet.of(), ImmutableSet.copyOf(added)); } } void actionChanged(final DOMActionRoutingTable newTable, final DOMActionImplementation impl) { - final T l = getInstance(); - if (!l.acceptsImplementation(impl)) { + if (!listener.acceptsImplementation(impl)) { return; } - final Map> actions = verifyNotNull(newTable.getOperations(l)); + final Map> actions = verifyNotNull(newTable.getOperations(listener)); final MapDifference> diff = Maps.difference(prevActions, actions); final Set removed = new HashSet<>(); @@ -403,43 +384,22 @@ public final class DOMRpcRouter extends AbstractRegistration prevActions = actions; if (!removed.isEmpty() || !added.isEmpty()) { - l.onActionsChanged(removed, added); - } - } - } - - @NonNullByDefault - private final class ActionAvailabilityFacade implements DOMActionAvailabilityExtension { - @Override - public ListenerRegistration registerAvailabilityListener(final T listener) { - synchronized (DOMRpcRouter.this) { - 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; + listener.onActionsChanged(removed, added); } } } @NonNullByDefault - private final class ActionServiceFacade implements DOMActionService { - private final ClassToInstanceMap extensions = ImmutableClassToInstanceMap.of( - DOMActionAvailabilityExtension.class, new ActionAvailabilityFacade()); - + private final class ActionServiceFacade implements DOMActionService, DOMActionAvailabilityExtension { @Override - public ClassToInstanceMap getExtensions() { - return extensions; + public List supportedExtensions() { + return List.of(this); } @Override public ListenableFuture invokeAction(final Absolute type, final DOMDataTreeIdentifier path, final ContainerNode input) { - final YangInstanceIdentifier pathRoot = path.getRootIdentifier(); + final YangInstanceIdentifier pathRoot = path.path(); checkArgument(!pathRoot.isEmpty(), "Action path must not be empty"); final DOMActionRoutingTableEntry entry = (DOMActionRoutingTableEntry) actionRoutingTable.getEntry(type); @@ -447,13 +407,29 @@ public final class DOMRpcRouter extends AbstractRegistration : Futures.immediateFailedFuture( new DOMActionNotAvailableException("No implementation of Action %s available", type)); } + + @Override + public Registration registerAvailabilityListener(final AvailabilityListener listener) { + synchronized (DOMRpcRouter.this) { + final var ret = new ActionAvailReg(DOMRpcRouter.this, listener, + actionRoutingTable.getOperations(listener)); + actionListeners = ImmutableList.builder() + .addAll(actionListeners) + .add(ret) + .build(); + + listenerNotifier.execute(ret::initialTable); + return ret; + } + } } @NonNullByDefault private final class ActionProviderServiceFacade implements DOMActionProviderService { @Override - public ObjectRegistration registerActionImplementation( - final T implementation, final Set instances) { + public Registration registerActionImplementation(final DOMActionImplementation implementation, + final Set instances) { + checkArgument(!instances.isEmpty(), "Instances must not be empty"); synchronized (DOMRpcRouter.this) { final DOMActionRoutingTable oldTable = actionRoutingTable; @@ -463,10 +439,10 @@ public final class DOMRpcRouter extends AbstractRegistration listenerNotifier.execute(() -> notifyActionChanged(newTable, implementation)); } - return new AbstractObjectRegistration<>(implementation) { + return new AbstractRegistration() { @Override protected void removeRegistration() { - removeActionImplementation(getInstance(), instances); + removeActionImplementation(implementation, instances); } }; } @@ -474,8 +450,8 @@ public final class DOMRpcRouter extends AbstractRegistration private final class RpcServiceFacade implements DOMRpcService { @Override - public ListenableFuture invokeRpc(final QName type, final NormalizedNode input) { - final AbstractDOMRpcRoutingTableEntry entry = (AbstractDOMRpcRoutingTableEntry) routingTable.getEntry(type); + public ListenableFuture invokeRpc(final QName type, final ContainerNode input) { + final var entry = (AbstractDOMRpcRoutingTableEntry) routingTable.getEntry(type); if (entry == null) { return Futures.immediateFailedFuture( new DOMRpcImplementationNotAvailableException("No implementation of RPC %s available", type)); @@ -485,11 +461,10 @@ public final class DOMRpcRouter extends AbstractRegistration } @Override - public ListenerRegistration registerRpcListener(final T listener) { + public Registration registerRpcListener(final DOMRpcAvailabilityListener listener) { synchronized (DOMRpcRouter.this) { - final Registration ret = new Registration<>(DOMRpcRouter.this, listener, - routingTable.getOperations(listener)); - listeners = ImmutableList.>builder().addAll(listeners).add(ret).build(); + final var ret = new RpcAvailReg(DOMRpcRouter.this, listener, routingTable.getOperations(listener)); + listeners = ImmutableList.builder().addAll(listeners).add(ret).build(); listenerNotifier.execute(ret::initialTable); return ret; @@ -499,14 +474,8 @@ public final class DOMRpcRouter extends AbstractRegistration private final class RpcProviderServiceFacade implements DOMRpcProviderService { @Override - public DOMRpcImplementationRegistration registerRpcImplementation( - final T implementation, final DOMRpcIdentifier... rpcs) { - return registerRpcImplementation(implementation, ImmutableSet.copyOf(rpcs)); - } - - @Override - public DOMRpcImplementationRegistration registerRpcImplementation( - final T implementation, final Set rpcs) { + public Registration registerRpcImplementation(final DOMRpcImplementation implementation, + final Set rpcs) { synchronized (DOMRpcRouter.this) { final DOMRpcRoutingTable oldTable = routingTable; @@ -516,117 +485,39 @@ public final class DOMRpcRouter extends AbstractRegistration listenerNotifier.execute(() -> notifyAdded(newTable, implementation)); } - return new AbstractDOMRpcImplementationRegistration<>(implementation) { + return new AbstractRegistration() { @Override protected void removeRegistration() { - removeRpcImplementation(getInstance(), rpcs); + removeRpcImplementation(implementation, rpcs); } }; } @Override - public org.opendaylight.yangtools.concepts.Registration registerRpcImplementations( - final Map map) { - final ImmutableMap defensive = ImmutableMap.copyOf(map); + public Registration registerRpcImplementations(final Map map) { checkArgument(!map.isEmpty()); + final var builder = ImmutableTable.builder(); + for (var entry : map.entrySet()) { + final var id = entry.getKey(); + builder.put(id.getType(), id.getContextReference(), entry.getValue()); + } + final var implTable = builder.build(); + synchronized (DOMRpcRouter.this) { final DOMRpcRoutingTable oldTable = routingTable; - final DOMRpcRoutingTable newTable = (DOMRpcRoutingTable) oldTable.addAll(defensive); + final DOMRpcRoutingTable newTable = (DOMRpcRoutingTable) oldTable.addAll(implTable); routingTable = newTable; - listenerNotifier.execute(() -> notifyAdded(newTable, defensive.values())); + listenerNotifier.execute(() -> notifyAdded(newTable, implTable.values())); } return new AbstractRegistration() { @Override protected void removeRegistration() { - removeRpcImplementations(defensive); + removeRpcImplementations(implTable); } }; } } - - static final class OperationInvocation { - private static final Logger LOG = LoggerFactory.getLogger(OperationInvocation.class); - - static ListenableFuture invoke(final DOMActionRoutingTableEntry entry, - final Absolute type, final DOMDataTreeIdentifier path, final ContainerNode 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) { - if (entry instanceof UnknownDOMRpcRoutingTableEntry) { - return Futures.immediateFailedFuture( - new DOMRpcImplementationNotAvailableException("%s is not resolved to an RPC", entry.getType())); - } else if (entry instanceof RoutedDOMRpcRoutingTableEntry routed) { - return invokeRoutedRpc(routed, input); - } else if (entry instanceof GlobalDOMRpcRoutingTableEntry global) { - return invokeGlobalRpc(global, input); - } - - return Futures.immediateFailedFuture( - new DOMRpcImplementationNotAvailableException("Unsupported RPC entry.")); - } - - private static ListenableFuture invokeRoutedRpc( - 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.body(); - if (value instanceof YangInstanceIdentifier iid) { - // Find a DOMRpcImplementation for a specific iid - final List specificImpls = entry.getImplementations(iid); - if (specificImpls != null) { - return specificImpls.get(0) - .invokeRpc(DOMRpcIdentifier.create(entry.getType(), iid), input); - } - - LOG.debug("No implementation for context {} found will now look for wildcard id", iid); - - // Find a DOMRpcImplementation for a wild card. Usually remote-rpc-connector would register an - // implementation this way - final List mayBeRemoteImpls = - entry.getImplementations(YangInstanceIdentifier.empty()); - - if (mayBeRemoteImpls != null) { - return mayBeRemoteImpls.get(0) - .invokeRpc(DOMRpcIdentifier.create(entry.getType(), iid), input); - } - - } else { - LOG.warn("Ignoring wrong context value {}", value); - } - } - - final List impls = entry.getImplementations(null); - if (impls != null) { - return impls.get(0).invokeRpc(entry.getRpcId(), input); - } - - return Futures.immediateFailedFuture( - new DOMRpcImplementationNotAvailableException("No implementation of RPC %s available", - entry.getType())); - } - - private static ListenableFuture invokeGlobalRpc( - final GlobalDOMRpcRoutingTableEntry entry, final NormalizedNode input) { - return entry.getImplementations(YangInstanceIdentifier.empty()).get(0).invokeRpc(entry.getRpcId(), input); - } - } }