import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
-import javax.annotation.concurrent.NotThreadSafe;
import org.opendaylight.protocol.bgp.mode.api.RouteEntry;
import org.opendaylight.protocol.bgp.mode.impl.BestPathStateImpl;
import org.opendaylight.protocol.bgp.rib.spi.RIBSupport;
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.PathId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.PathId;
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.DataObject;
import org.opendaylight.yangtools.yang.binding.Identifiable;
import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.common.Uint32;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * A single route entry inside a route table. Maintains the attributes of
- * from all contributing peers. The information is stored in arrays with a
- * shared map of offsets for peers to allow lookups. This is needed to
- * maintain low memory overhead in face of large number of routes and peers,
- * where individual object overhead becomes the dominating factor.
+ * A single route entry inside a route table. Maintains the attributes from all contributing peers. The information is
+ * stored in arrays with a shared map of offsets for peers to allow lookups. This is needed to maintain low memory
+ * overhead in face of large number of routes and peers, where individual object overhead becomes the dominating factor.
+ *
+ * <p>
+ * This class is NOT thread-safe.
*/
-@NotThreadSafe
public abstract class AddPathAbstractRouteEntry<C extends Routes & DataObject & ChoiceIn<Tables>,
- S extends ChildOf<? super C>,
- R extends Route & ChildOf<? super S> & Identifiable<I>, I extends Identifier<R>>
+ 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 class Stale<C extends Routes & DataObject & ChoiceIn<Tables>,
+ S extends ChildOf<? super C>, R extends Route & ChildOf<? super S> & Identifiable<I>,
+ I extends Identifier<R>> extends StaleBestPathRoute<C, S, R, I> {
+ private final List<I> addPathRouteKeyIdentifier;
+ private final List<I> staleRouteKeyIdentifier;
+ private final boolean isNonAddPathBestPathNew;
+
+ Stale(final RIBSupport<C, S, R, I> ribSupport, final String routeKey, final List<PathId> staleRoutesPathIds,
+ final List<PathId> withdrawalRoutePathIds, final boolean isNonAddPathBestPathNew) {
+ super(ribSupport.createRouteListKey(routeKey));
+ this.isNonAddPathBestPathNew = isNonAddPathBestPathNew;
+
+ this.staleRouteKeyIdentifier = staleRoutesPathIds.stream()
+ .map(pathId -> ribSupport.createRouteListKey(pathId, routeKey)).collect(Collectors.toList());
+ if (withdrawalRoutePathIds != null) {
+ this.addPathRouteKeyIdentifier = withdrawalRoutePathIds.stream()
+ .map(pathId -> ribSupport.createRouteListKey(pathId, routeKey)).collect(Collectors.toList());
+ } else {
+ this.addPathRouteKeyIdentifier = Collections.emptyList();
+ }
+ }
+
+ @Override
+ public List<I> getStaleRouteKeyIdentifiers() {
+ return this.staleRouteKeyIdentifier;
+ }
+
+ @Override
+ public List<I> getAddPathRouteKeyIdentifiers() {
+ return addPathRouteKeyIdentifier;
+ }
+
+ @Override
+ public boolean isNonAddPathBestPathNew() {
+ return isNonAddPathBestPathNew;
+ }
+ }
private static final Logger LOG = LoggerFactory.getLogger(AddPathAbstractRouteEntry.class);
- private static final Long[] EMPTY_PATHS_ID = new Long[0];
+ private static final Uint32[] EMPTY_PATHS_ID = new Uint32[0];
private static final Route[] EMPTY_VALUES = new Route[0];
private RouteKeyOffsets offsets = RouteKeyOffsets.EMPTY;
private R[] values = (R[]) EMPTY_VALUES;
- private Long[] pathsId = EMPTY_PATHS_ID;
+ private Uint32[] pathsId = EMPTY_PATHS_ID;
private List<AddPathBestPath> bestPath;
private List<AddPathBestPath> bestPathRemoved;
private List<AddPathBestPath> newBestPathToBeAdvertised;
- private List<Long> removedPathsId;
+ private List<Uint32> removedPathsId;
private long pathIdCounter = 0L;
private boolean isNonAddPathBestPathNew;
}
@Override
- public final int addRoute(final RouterId routerId, final Long remotePathId, final R route) {
+ public final int addRoute(final RouterId routerId, final Uint32 remotePathId, final R route) {
final RouteKey key = new RouteKey(routerId, remotePathId);
int offset = this.offsets.offsetOf(key);
if (offset < 0) {
final RouteKeyOffsets newOffsets = this.offsets.with(key);
offset = newOffsets.offsetOf(key);
final R[] newRoute = newOffsets.expand(this.offsets, this.values, offset);
- final Long[] newPathsId = newOffsets.expand(this.offsets, this.pathsId, offset);
+ final Uint32[] newPathsId = newOffsets.expand(this.offsets, this.pathsId, offset);
this.values = newRoute;
this.offsets = newOffsets;
this.pathsId = newPathsId;
- this.offsets.setValue(this.pathsId, offset, ++this.pathIdCounter);
+ this.offsets.setValue(this.pathsId, offset, Uint32.valueOf(++this.pathIdCounter));
}
this.offsets.setValue(this.values, offset, route);
LOG.trace("Added route {} from {}", route, routerId);
}
@Override
- public final boolean removeRoute(final RouterId routerId, final Long remotePathId) {
+ public final boolean removeRoute(final RouterId routerId, final Uint32 remotePathId) {
final RouteKey key = new RouteKey(routerId, remotePathId);
final int offset = this.offsets.offsetOf(key);
- final Long pathId = this.offsets.getValue(this.pathsId, offset);
+ final Uint32 pathId = this.offsets.getValue(this.pathsId, offset);
this.values = this.offsets.removeValue(this.values, offset, (R[]) EMPTY_VALUES);
this.pathsId = this.offsets.removeValue(this.pathsId, offset, EMPTY_PATHS_ID);
this.offsets = this.offsets.without(key);
final String routeKey) {
final List<PathId> stalePaths;
if (bestPathRemoved != null && !bestPathRemoved.isEmpty()) {
- stalePaths = bestPathRemoved.stream().map(AddPathBestPath::getPathId)
+ stalePaths = bestPathRemoved.stream().map(AddPathBestPath::getPathIdLong)
.map(AddPathAbstractRouteEntry::pathIdObj).collect(Collectors.toList());
bestPathRemoved = null;
} else {
}
return stalePaths.isEmpty() && removedPaths.isEmpty() ? Optional.empty()
- : Optional.of(new StaleBestPathRoute<>(ribSupport, routeKey, stalePaths,
- removedPaths, this.isNonAddPathBestPathNew));
+ : Optional.of(new Stale<>(ribSupport, routeKey, stalePaths, removedPaths, isNonAddPathBestPathNew));
}
@Override
protected final void processOffset(final AddPathSelector selector, final int offset) {
final RouteKey key = offsets.getKey(offset);
final R route = offsets.getValue(values, offset);
- final Long pathId = offsets.getValue(pathsId, offset);
+ final Uint32 pathId = offsets.getValue(pathsId, offset);
LOG.trace("Processing router key {} route {}", key, route);
selector.processPath(route.getAttributes(), key, offset, pathId);
}
});
}
- private static PathId pathIdObj(final Long pathId) {
- return pathId == NON_PATH_ID_VALUE ? NON_PATH_ID : new PathId(pathId);
+ private static PathId pathIdObj(final Uint32 pathId) {
+ return NON_PATH_ID_VALUE.equals(pathId) ? NON_PATH_ID : new PathId(pathId);
}
}