Bump upstreams
[bgpcep.git] / bgp / path-selection-mode / src / main / java / org / opendaylight / protocol / bgp / mode / impl / base / BaseRouteEntry.java
index a8be574a836d693593d0b6d5964c3ce0fde6ce54..0105f22044c61bf18e970b6e4fbb3cec745e348f 100644 (file)
  */
 package org.opendaylight.protocol.bgp.mode.impl.base;
 
-import com.google.common.primitives.UnsignedInteger;
 import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
-import javax.annotation.concurrent.NotThreadSafe;
 import org.opendaylight.protocol.bgp.mode.api.RouteEntry;
 import org.opendaylight.protocol.bgp.rib.spi.RIBSupport;
+import org.opendaylight.protocol.bgp.rib.spi.RouterId;
 import org.opendaylight.protocol.bgp.rib.spi.entry.ActualBestPathRoutes;
 import org.opendaylight.protocol.bgp.rib.spi.entry.AdvertizedRoute;
 import org.opendaylight.protocol.bgp.rib.spi.entry.RouteEntryInfo;
 import org.opendaylight.protocol.bgp.rib.spi.entry.StaleBestPathRoute;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.Attributes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.Route;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.Tables;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.tables.Routes;
 import org.opendaylight.yangtools.yang.binding.ChildOf;
 import org.opendaylight.yangtools.yang.binding.ChoiceIn;
 import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.Identifiable;
-import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.common.Uint32;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-@NotThreadSafe
-final class BaseRouteEntry<C extends Routes & DataObject & ChoiceIn<Tables>,
-        S extends ChildOf<? super C>,
-        R extends Route & ChildOf<? super S> & Identifiable<I>,
-        I extends Identifier<R>> implements RouteEntry<C,S,R,I> {
-    private static final Logger LOG = LoggerFactory.getLogger(BaseRouteEntry.class);
-    private static final Route[] EMPTY_VALUES = new Route[0];
+final class BaseRouteEntry<C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>>
+        implements RouteEntry<C, S> {
+    private static final class Stale extends StaleBestPathRoute {
+        Stale(final NodeIdentifierWithPredicates nonAddPathRouteKeyIdentifier) {
+            super(nonAddPathRouteKeyIdentifier);
+        }
 
-    private OffsetMap offsets = OffsetMap.EMPTY;
-    private R[] values = (R[]) EMPTY_VALUES;
-    private BaseBestPath bestPath;
-    private BaseBestPath removedBestPath;
+        @Override
+        public List<NodeIdentifierWithPredicates> getStaleRouteKeyIdentifiers() {
+            return Collections.singletonList(getNonAddPathRouteKeyIdentifier());
+        }
+
+        @Override
+        public List<NodeIdentifierWithPredicates> getAddPathRouteKeyIdentifiers() {
+            return Collections.emptyList();
+        }
 
-    BaseRouteEntry() {
+        @Override
+        public boolean isNonAddPathBestPathNew() {
+            return true;
+        }
     }
 
+    private static final Logger LOG = LoggerFactory.getLogger(BaseRouteEntry.class);
+    private static final MapEntryNode[] EMPTY_VALUES = new MapEntryNode[0];
+
+    private RouterIdOffsets offsets = RouterIdOffsets.EMPTY;
+    private MapEntryNode[] values = EMPTY_VALUES;
+    private BaseBestPath bestPath = null;
+    private BaseBestPath removedBestPath;
+
     @Override
-    public boolean removeRoute(final UnsignedInteger routerId, final long remotePathId) {
-        final int offset = this.offsets.offsetOf(routerId);
-        this.values = this.offsets.removeValue(this.values, offset, (R[]) EMPTY_VALUES);
-        this.offsets = this.offsets.without(routerId);
-        return this.offsets.isEmpty();
+    public boolean removeRoute(final RouterId routerId, final Uint32 remotePathId) {
+        final int offset = offsets.offsetOf(routerId);
+        values = offsets.removeValue(values, offset, EMPTY_VALUES);
+        offsets = offsets.without(routerId);
+        return offsets.isEmpty();
     }
 
-    private  R createRoute(final RIBSupport<C, S, R, I> ribSup, final String routeKey, final long pathId,
-            final BaseBestPath path) {
-        final R route = this.offsets.getValue(this.values, this.offsets.offsetOf(path.getRouterId()));
-        return ribSup.createRoute(route, routeKey, pathId, path.getAttributes());
+    private MapEntryNode createRoute(final RIBSupport<C, S> ribSup, final String routeKey) {
+        final MapEntryNode route = offsets.getValue(values, offsets.offsetOf(bestPath.getRouterId()));
+        return ribSup.createRoute(route, ribSup.createRouteListArgument(routeKey), bestPath.getAttributes());
     }
 
     @Override
-    public boolean selectBest(final long localAs) {
+    public boolean selectBest(final RIBSupport<C, S> ribSupport, final long localAs) {
         /*
          * FIXME: optimize flaps by making sure we consider stability of currently-selected route.
          */
         final BasePathSelector selector = new BasePathSelector(localAs);
 
         // Select the best route.
-        for (int i = 0; i < this.offsets.size(); ++i) {
-            final UnsignedInteger routerId = this.offsets.getRouterKey(i);
-            final Attributes attributes = this.offsets.getValue(this.values, i).getAttributes();
+        for (int i = 0; i < offsets.size(); ++i) {
+            final RouterId routerId = offsets.getKey(i);
+            final ContainerNode attributes = ribSupport.extractAttributes(offsets.getValue(values, i));
             LOG.trace("Processing router id {} attributes {}", routerId, attributes);
             selector.processPath(routerId, attributes);
         }
 
         // Get the newly-selected best path.
         final BaseBestPath newBestPath = selector.result();
-        final boolean modified = newBestPath == null || !newBestPath.equals(this.bestPath);
+        final boolean modified = newBestPath == null || !newBestPath.equals(bestPath);
         if (modified) {
-            if (this.offsets.isEmpty()) {
-                this.removedBestPath = this.bestPath;
+            if (offsets.isEmpty()) {
+                removedBestPath = bestPath;
             }
-            LOG.trace("Previous best {}, current best {}", this.bestPath, newBestPath);
-            this.bestPath = newBestPath;
+            LOG.trace("Previous best {}, current best {}", bestPath, newBestPath);
+            bestPath = newBestPath;
         }
         return modified;
     }
 
     @Override
-    public int addRoute(final UnsignedInteger routerId, final long remotePathId, final R route) {
-        int offset = this.offsets.offsetOf(routerId);
+    public int addRoute(final RouterId routerId, final Uint32 remotePathId, final MapEntryNode route) {
+        int offset = offsets.offsetOf(routerId);
         if (offset < 0) {
-            final OffsetMap newOffsets = this.offsets.with(routerId);
+            final RouterIdOffsets newOffsets = offsets.with(routerId);
             offset = newOffsets.offsetOf(routerId);
 
-            this.values = newOffsets.expand(this.offsets, this.values, offset);
-            this.offsets = newOffsets;
+            values = newOffsets.expand(offsets, values, offset);
+            offsets = newOffsets;
         }
 
-        this.offsets.setValue(this.values, offset, route);
+        offsets.setValue(values, offset, route);
         LOG.trace("Added route {} from {}", route, routerId);
         return offset;
     }
 
     @Override
-    public Optional<StaleBestPathRoute<C, S, R, I>> removeStalePaths(final RIBSupport<C, S, R, I> ribSupport,
-            final String routeKey) {
-        if (this.removedBestPath == null) {
+    public Optional<StaleBestPathRoute> removeStalePaths(final RIBSupport<C, S> ribSupport, final String routeKey) {
+        if (removedBestPath == null) {
             return Optional.empty();
         }
-        final StaleBestPathRoute<C, S, R, I> stale = new StaleBestPathRoute<>(ribSupport, routeKey);
-        this.removedBestPath = null;
-        return Optional.of(stale);
+        removedBestPath = null;
+        return Optional.of(new Stale(ribSupport.createRouteListArgument(routeKey)));
     }
 
     @Override
-    public List<AdvertizedRoute<C, S, R, I>> newBestPaths(final RIBSupport<C, S, R, I> ribSupport,
-            final String routeKey) {
-        if (this.bestPath == null) {
+    public List<AdvertizedRoute<C, S>> newBestPaths(final RIBSupport<C, S> ribSupport, final String routeKey) {
+        if (bestPath == null) {
             return Collections.emptyList();
         }
-        final R route = createRoute(ribSupport, routeKey, this.bestPath.getPathId(), this.bestPath);
-        final AdvertizedRoute<C, S, R, I> adv = new AdvertizedRoute<>(ribSupport, route, this.bestPath.getAttributes(),
-                this.bestPath.getPeerId(), this.bestPath.isDepreferenced());
+        final MapEntryNode route = createRoute(ribSupport, routeKey);
+        final AdvertizedRoute<C, S> adv = new AdvertizedRoute<>(ribSupport, route, bestPath.getAttributes(),
+                bestPath.getPeerId(), bestPath.isDepreferenced());
         LOG.trace("Selected best route {}", route);
         return Collections.singletonList(adv);
     }
 
     @Override
-    public List<ActualBestPathRoutes<C, S, R, I>> actualBestPaths(final RIBSupport<C, S, R, I> ribSupport,
+    public List<ActualBestPathRoutes<C, S>> actualBestPaths(final RIBSupport<C, S> ribSupport,
             final RouteEntryInfo entryInfo) {
-        if (this.bestPath == null) {
+        if (bestPath == null) {
             return Collections.emptyList();
         }
-        final R route = createRoute(ribSupport, entryInfo.getRouteKey(), this.bestPath.getPathId(), this.bestPath);
-        return Collections.singletonList(new ActualBestPathRoutes<>(ribSupport, route, this.bestPath.getPeerId(),
-                this.bestPath.getAttributes(), this.bestPath.isDepreferenced()));
+        final MapEntryNode route = createRoute(ribSupport, entryInfo.getRouteKey());
+        return Collections.singletonList(new ActualBestPathRoutes<>(ribSupport, route, bestPath.getPeerId(),
+                bestPath.getAttributes(), bestPath.isDepreferenced()));
     }
 }
\ No newline at end of file