2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.protocol.bgp.rib.impl;
10 import com.google.common.primitives.UnsignedInteger;
11 import java.util.Objects;
12 import javax.annotation.concurrent.NotThreadSafe;
13 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
14 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
15 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
16 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
17 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
18 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
23 * A single route entry inside a route table. Maintains the attributes of
24 * from all contributing peers. The information is stored in arrays with a
25 * shared map of offsets for peers to allow lookups. This is needed to
26 * maintain low memory overhead in face of large number of routes and peers,
27 * where individual object overhead becomes the dominating factor.
30 abstract class AbstractRouteEntry {
32 private static final Logger LOG = LoggerFactory.getLogger(AbstractRouteEntry.class);
34 private static final ContainerNode[] EMPTY_ATTRIBUTES = new ContainerNode[0];
36 private OffsetMap offsets = OffsetMap.EMPTY;
37 private ContainerNode[] values = EMPTY_ATTRIBUTES;
38 private BestPath bestPath;
40 private int addRoute(final UnsignedInteger routerId, final ContainerNode attributes) {
41 int offset = this.offsets.offsetOf(routerId);
43 final OffsetMap newOffsets = this.offsets.with(routerId);
44 offset = newOffsets.offsetOf(routerId);
46 final ContainerNode[] newAttributes = newOffsets.expand(this.offsets, this.values, offset);
47 this.values = newAttributes;
48 this.offsets = newOffsets;
51 this.offsets.setValue(this.values, offset, attributes);
52 LOG.trace("Added route from {} attributes {}", routerId, attributes);
56 protected int addRoute(final UnsignedInteger routerId, final NodeIdentifier attributesIdentifier, final NormalizedNode<?, ?> data) {
57 LOG.trace("Find {} in {}", attributesIdentifier, data);
58 final ContainerNode advertisedAttrs = (ContainerNode) NormalizedNodes.findNode(data, attributesIdentifier).orNull();
59 return addRoute(routerId, advertisedAttrs);
62 // Indicates whether this was the last route
63 protected final boolean removeRoute(final int offset) {
64 if (this.offsets.size() != 1) {
65 // FIXME: actually shrink the array
66 this.offsets.setValue(this.values, offset, null);
73 // Indicates whether best has changed
74 final boolean selectBest(final long localAs) {
76 * FIXME: optimize flaps by making sure we consider stability of currently-selected route.
78 final BestPathSelector selector = new BestPathSelector(localAs);
80 // Select the best route.
81 for (int i = 0; i < this.offsets.size(); ++i) {
82 final UnsignedInteger routerId = this.offsets.getRouterId(i);
83 final ContainerNode attributes = this.offsets.getValue(this.values, i);
84 LOG.trace("Processing router id {} attributes {}", routerId, attributes);
85 selector.processPath(routerId, attributes);
88 // Get the newly-selected best path.
89 final BestPath newBestPath = selector.result();
90 // FIXME: run deeper comparison
91 final boolean ret = !Objects.equals(this.bestPath, newBestPath);
92 LOG.trace("Previous best {}, current best {}, result {}", this.bestPath, newBestPath, ret);
93 this.bestPath = newBestPath;
97 final ContainerNode attributes() {
98 return this.bestPath.getState().getAttributes();
101 protected final OffsetMap getOffsets() {
105 protected final UnsignedInteger getBestRouterId() {
106 return this.bestPath.getRouterId();
109 abstract boolean removeRoute(final UnsignedInteger routerId);
110 abstract MapEntryNode createValue(PathArgument routeId);