Since we no longer use the time stored in internal entries,
we can use a Set instead of a Map. Adjust internal structure
of RoutingTable and tighten its exported methods.
Change-Id: Ifa2ed53ffc9d05c658927167a4e7dd331c3c2006
Signed-off-by: Robert Varga <rovarga@cisco.com>
package org.opendaylight.controller.remote.rpc.registry;
import akka.actor.ActorRef;
package org.opendaylight.controller.remote.rpc.registry;
import akka.actor.ActorRef;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
import java.io.Serializable;
import java.io.Serializable;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.Collection;
+import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import org.opendaylight.controller.remote.rpc.registry.gossip.BucketData;
import java.util.Optional;
import java.util.Set;
import org.opendaylight.controller.remote.rpc.registry.gossip.BucketData;
-import org.opendaylight.controller.sal.connector.api.RpcRouter;
import org.opendaylight.controller.sal.connector.api.RpcRouter.RouteIdentifier;
public class RoutingTable implements BucketData<RoutingTable>, Serializable {
import org.opendaylight.controller.sal.connector.api.RpcRouter.RouteIdentifier;
public class RoutingTable implements BucketData<RoutingTable>, Serializable {
- private static final long serialVersionUID = 5592610415175278760L;
+ private static final long serialVersionUID = 1L;
- private final Map<RouteIdentifier<?, ?, ?>, Long> table;
- private final ActorRef router;
+ private final Set<RouteIdentifier<?, ?, ?>> rpcs;
+ private final ActorRef rpcInvoker;
- private RoutingTable(final ActorRef router, final Map<RouteIdentifier<?, ?, ?>, Long> table) {
- this.router = Preconditions.checkNotNull(router);
- this.table = Preconditions.checkNotNull(table);
+ private RoutingTable(final ActorRef rpcInvoker, final Set<RouteIdentifier<?, ?, ?>> table) {
+ this.rpcInvoker = Preconditions.checkNotNull(rpcInvoker);
+ this.rpcs = ImmutableSet.copyOf(table);
- RoutingTable(final ActorRef router) {
- this(router, new HashMap<>());
- }
-
- RoutingTable copy() {
- return new RoutingTable(router, new HashMap<>(table));
+ RoutingTable(final ActorRef rpcInvoker) {
+ this(rpcInvoker, ImmutableSet.of());
}
@Override
public Optional<ActorRef> getWatchActor() {
}
@Override
public Optional<ActorRef> getWatchActor() {
- return Optional.of(router);
- }
-
- public Set<RpcRouter.RouteIdentifier<?, ?, ?>> getRoutes() {
- return table.keySet();
+ return Optional.of(rpcInvoker);
- public void addRoute(final RpcRouter.RouteIdentifier<?, ?, ?> routeId) {
- table.put(routeId, System.currentTimeMillis());
+ public Set<RouteIdentifier<?, ?, ?>> getRoutes() {
+ return rpcs;
- public void removeRoute(final RpcRouter.RouteIdentifier<?, ?, ?> routeId) {
- table.remove(routeId);
+ ActorRef getRpcInvoker() {
+ return rpcInvoker;
- public boolean contains(final RpcRouter.RouteIdentifier<?, ?, ?> routeId) {
- return table.containsKey(routeId);
+ RoutingTable addRpcs(final Collection<RouteIdentifier<?, ?, ?>> toAdd) {
+ final Set<RouteIdentifier<?, ?, ?>> newRpcs = new HashSet<>(rpcs);
+ newRpcs.addAll(toAdd);
+ return new RoutingTable(rpcInvoker, newRpcs);
- public boolean isEmpty() {
- return table.isEmpty();
+ RoutingTable removeRpcs(final Collection<RouteIdentifier<?, ?, ?>> toRemove) {
+ final Set<RouteIdentifier<?, ?, ?>> newRpcs = new HashSet<>(rpcs);
+ newRpcs.removeAll(toRemove);
+ return new RoutingTable(rpcInvoker, newRpcs);
- public int size() {
- return table.size();
+ @VisibleForTesting
+ boolean contains(final RouteIdentifier<?, ?, ?> routeId) {
+ return rpcs.contains(routeId);
- public ActorRef getRouter() {
- return router;
+ @VisibleForTesting
+ int size() {
+ return rpcs.size();
}
@Override
public String toString() {
}
@Override
public String toString() {
- return "RoutingTable{" + "table=" + table + ", router=" + router + '}';
+ return "RoutingTable{" + "rpcs=" + rpcs + ", rpcInvoker=" + rpcInvoker + '}';
import org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.UpdateRemoteEndpoints;
import org.opendaylight.controller.remote.rpc.registry.gossip.Bucket;
import org.opendaylight.controller.remote.rpc.registry.gossip.BucketStore;
import org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.UpdateRemoteEndpoints;
import org.opendaylight.controller.remote.rpc.registry.gossip.Bucket;
import org.opendaylight.controller.remote.rpc.registry.gossip.BucketStore;
-import org.opendaylight.controller.sal.connector.api.RpcRouter;
import org.opendaylight.controller.sal.connector.api.RpcRouter.RouteIdentifier;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.opendaylight.controller.sal.connector.api.RpcRouter.RouteIdentifier;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
private void receiveAddRoutes(final AddOrUpdateRoutes msg) {
LOG.debug("AddOrUpdateRoutes: {}", msg.getRouteIdentifiers());
private void receiveAddRoutes(final AddOrUpdateRoutes msg) {
LOG.debug("AddOrUpdateRoutes: {}", msg.getRouteIdentifiers());
-
- RoutingTable table = getLocalBucket().getData().copy();
- for (RpcRouter.RouteIdentifier<?, ?, ?> routeId : msg.getRouteIdentifiers()) {
- table.addRoute(routeId);
- }
-
- updateLocalBucket(table);
+ updateLocalBucket(getLocalBucket().getData().addRpcs(msg.getRouteIdentifiers()));
* @param msg contains list of route ids to remove
*/
private void receiveRemoveRoutes(final RemoveRoutes msg) {
* @param msg contains list of route ids to remove
*/
private void receiveRemoveRoutes(final RemoveRoutes msg) {
- RoutingTable table = getLocalBucket().getData().copy();
- for (RpcRouter.RouteIdentifier<?, ?, ?> routeId : msg.getRouteIdentifiers()) {
- table.removeRoute(routeId);
- }
-
- updateLocalBucket(table);
+ LOG.debug("RemoveRoutes: {}", msg.getRouteIdentifiers());
+ updateLocalBucket(getLocalBucket().getData().removeRpcs(msg.getRouteIdentifiers()));
}
endpoints.put(e.getKey(), rpcs.isEmpty() ? Optional.empty()
}
endpoints.put(e.getKey(), rpcs.isEmpty() ? Optional.empty()
- : Optional.of(new RemoteRpcEndpoint(table.getRouter(), rpcs)));
+ : Optional.of(new RemoteRpcEndpoint(table.getRpcInvoker(), rpcs)));
}
if (!endpoints.isEmpty()) {
}
if (!endpoints.isEmpty()) {
*/
public static class Messages {
abstract static class AbstractRouteMessage {
*/
public static class Messages {
abstract static class AbstractRouteMessage {
- final List<RpcRouter.RouteIdentifier<?, ?, ?>> routeIdentifiers;
+ final List<RouteIdentifier<?, ?, ?>> routeIdentifiers;
- AbstractRouteMessage(final List<RpcRouter.RouteIdentifier<?, ?, ?>> routeIdentifiers) {
+ AbstractRouteMessage(final List<RouteIdentifier<?, ?, ?>> routeIdentifiers) {
Preconditions.checkArgument(routeIdentifiers != null && !routeIdentifiers.isEmpty(),
"Route Identifiers must be supplied");
this.routeIdentifiers = routeIdentifiers;
}
Preconditions.checkArgument(routeIdentifiers != null && !routeIdentifiers.isEmpty(),
"Route Identifiers must be supplied");
this.routeIdentifiers = routeIdentifiers;
}
- List<RpcRouter.RouteIdentifier<?, ?, ?>> getRouteIdentifiers() {
+ List<RouteIdentifier<?, ?, ?>> getRouteIdentifiers() {
return this.routeIdentifiers;
}
return this.routeIdentifiers;
}
}
public static final class AddOrUpdateRoutes extends AbstractRouteMessage {
}
public static final class AddOrUpdateRoutes extends AbstractRouteMessage {
- public AddOrUpdateRoutes(final List<RpcRouter.RouteIdentifier<?, ?, ?>> routeIdentifiers) {
+ public AddOrUpdateRoutes(final List<RouteIdentifier<?, ?, ?>> routeIdentifiers) {
super(routeIdentifiers);
}
}
public static final class RemoveRoutes extends AbstractRouteMessage {
super(routeIdentifiers);
}
}
public static final class RemoveRoutes extends AbstractRouteMessage {
- public RemoveRoutes(final List<RpcRouter.RouteIdentifier<?, ?, ?>> routeIdentifiers) {
+ public RemoveRoutes(final List<RouteIdentifier<?, ?, ?>> routeIdentifiers) {
super(routeIdentifiers);
}
}
super(routeIdentifiers);
}
}
import akka.actor.ActorRef;
import java.util.Optional;
import akka.actor.ActorRef;
import java.util.Optional;
+import org.opendaylight.yangtools.concepts.Immutable;
/**
* Marker interface for data which is able to be held in a {@link Bucket}.
/**
* Marker interface for data which is able to be held in a {@link Bucket}.
*
* @param <T> Concrete BucketData type
*/
*
* @param <T> Concrete BucketData type
*/
-public interface BucketData<T extends BucketData<T>> {
+public interface BucketData<T extends BucketData<T>> extends Immutable {
/**
* Return the {@link ActorRef} which should be tracked as the authoritative source of this bucket's data.
* The bucket will be invalidated should the actor be reported as Terminated.
/**
* Return the {@link ActorRef} which should be tracked as the authoritative source of this bucket's data.
* The bucket will be invalidated should the actor be reported as Terminated.