Merge "Support proper route redistribution"
[bgpcep.git] / bgp / rib-impl / src / main / java / org / opendaylight / protocol / bgp / rib / impl / RouteEntry.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.protocol.bgp.rib.impl;
9
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.PathArgument;
14 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
15 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
16
17 /**
18  * A single route entry inside a route table. Maintains the attributes of
19  * from all contributing peers. The information is stored in arrays with a
20  * shared map of offsets for peers to allow lookups. This is needed to
21  * maintain low memory overhead in face of large number of routes and peers,
22  * where individual object overhead becomes the dominating factor.
23  */
24 @NotThreadSafe
25 final class RouteEntry {
26     private static final ContainerNode[] EMPTY_ATTRIBUTES = new ContainerNode[0];
27
28     private OffsetMap offsets = OffsetMap.EMPTY;
29     private ContainerNode[] values = EMPTY_ATTRIBUTES;
30     private BestPath bestPath;
31
32     void addRoute(final UnsignedInteger routerId, final ContainerNode attributes) {
33         int offset = offsets.offsetOf(routerId);
34         if (offset < 0) {
35             final OffsetMap newOffsets = offsets.with(routerId);
36             offset = newOffsets.offsetOf(routerId);
37
38             final ContainerNode[] newAttributes = newOffsets.expand(offsets, this.values, offset);
39             this.values = newAttributes;
40             this.offsets = newOffsets;
41         }
42
43         offsets.setValue(this.values, offset, attributes);
44     }
45
46     // Indicates whether this was the last route
47     boolean removeRoute(final UnsignedInteger routerId) {
48         if (offsets.size() != 1) {
49             // FIXME: actually shrink the array
50             int offset = offsets.offsetOf(routerId);
51             offsets.setValue(values, offset, null);
52             return false;
53         } else {
54             return true;
55         }
56     }
57
58     // Indicates whether best has changed
59     boolean selectBest(final long localAs) {
60         /*
61          * FIXME: optimize flaps by making sure we consider stability of currently-selected route.
62          */
63         final BestPathSelector selector = new BestPathSelector(localAs);
64
65         // Select the best route.
66         for (int i = 0; i < this.offsets.size(); ++i) {
67             final UnsignedInteger routerId = this.offsets.getRouterId(i);
68             final ContainerNode attributes = this.offsets.getValue(this.values, i);
69
70             selector.processPath(routerId, attributes);
71         }
72
73         // Get the newly-selected best path.
74         final BestPath newBestPath = selector.result();
75         // FIXME: run deeper comparison
76         final boolean ret = !Objects.equals(bestPath, newBestPath);
77
78         bestPath = newBestPath;
79         return ret;
80     }
81
82     NormalizedNode<?, ?> bestValue(final PathArgument key) {
83         // TODO Auto-generated method stub
84         return null;
85     }
86 }