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 javax.annotation.concurrent.NotThreadSafe;
12 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
13 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
14 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
15 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
16 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
17 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
18 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory;
22 * A single route entry inside a route table. Maintains the attributes of
23 * from all contributing peers. The information is stored in arrays with a
24 * shared map of offsets for peers to allow lookups. This is needed to
25 * maintain low memory overhead in face of large number of routes and peers,
26 * where individual object overhead becomes the dominating factor.
29 abstract class AbstractRouteEntry {
31 private static final Logger LOG = LoggerFactory.getLogger(AbstractRouteEntry.class);
33 private static final ContainerNode[] EMPTY_ATTRIBUTES = new ContainerNode[0];
35 private OffsetMap offsets = OffsetMap.EMPTY;
36 private ContainerNode[] values = EMPTY_ATTRIBUTES;
37 private BestPath bestPath;
39 private int addRoute(final UnsignedInteger routerId, final ContainerNode attributes) {
40 int offset = this.offsets.offsetOf(routerId);
42 final OffsetMap newOffsets = this.offsets.with(routerId);
43 offset = newOffsets.offsetOf(routerId);
45 final ContainerNode[] newAttributes = newOffsets.expand(this.offsets, this.values, offset);
46 this.values = newAttributes;
47 this.offsets = newOffsets;
50 this.offsets.setValue(this.values, offset, attributes);
51 LOG.trace("Added route from {} attributes {}", routerId, attributes);
55 protected int addRoute(final UnsignedInteger routerId, final NodeIdentifier attributesIdentifier, final NormalizedNode<?, ?> data) {
56 LOG.trace("Find {} in {}", attributesIdentifier, data);
57 final ContainerNode advertisedAttrs = (ContainerNode) NormalizedNodes.findNode(data, attributesIdentifier).orNull();
58 return addRoute(routerId, advertisedAttrs);
61 // Indicates whether this was the last route
62 protected final boolean removeRoute(final int offset) {
63 if (this.offsets.size() != 1) {
64 // FIXME: actually shrink the array
65 this.offsets.setValue(this.values, offset, null);
72 // Indicates whether best has changed
73 final boolean selectBest(final long localAs) {
75 * FIXME: optimize flaps by making sure we consider stability of currently-selected route.
77 final BestPathSelector selector = new BestPathSelector(localAs);
79 // Select the best route.
80 for (int i = 0; i < this.offsets.size(); ++i) {
81 final UnsignedInteger routerId = this.offsets.getRouterId(i);
82 final ContainerNode attributes = this.offsets.getValue(this.values, i);
83 LOG.trace("Processing router id {} attributes {}", routerId, attributes);
84 selector.processPath(routerId, attributes);
87 // Get the newly-selected best path.
88 final BestPath newBestPath = selector.result();
89 final boolean ret = !newBestPath.equals(this.bestPath);
90 LOG.trace("Previous best {}, current best {}, result {}", this.bestPath, newBestPath, ret);
91 this.bestPath = newBestPath;
95 final ContainerNode attributes() {
96 return this.bestPath.getState().getAttributes();
99 protected final OffsetMap getOffsets() {
103 protected final UnsignedInteger getBestRouterId() {
104 return this.bestPath.getRouterId();
107 abstract boolean removeRoute(final UnsignedInteger routerId);
108 abstract MapEntryNode createValue(PathArgument routeId);