import com.google.common.base.MoreObjects.ToStringHelper;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
import com.google.common.collect.ImmutableList;
import java.util.Collection;
import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
import javax.annotation.concurrent.NotThreadSafe;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.AsPath;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.AListCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.ASetCase;
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
@NotThreadSafe
final class BestPathState {
- private static final Collection<PathArgument> AS_PATH = ImmutableList.<PathArgument>of(new NodeIdentifier(AsPath.QNAME), new NodeIdentifier(Segments.QNAME));
- private static final Collection<PathArgument> LOCAL_PREF = ImmutableList.<PathArgument>of(new NodeIdentifier(LocalPref.QNAME), new NodeIdentifier(QName.create(LocalPref.QNAME, "pref")));
- private static final Collection<PathArgument> MED = ImmutableList.<PathArgument>of(new NodeIdentifier(MultiExitDisc.QNAME), new NodeIdentifier(QName.create(MultiExitDisc.QNAME, "med")));
- private static final Collection<PathArgument> ORIGIN = ImmutableList.<PathArgument>of(new NodeIdentifier(Origin.QNAME), new NodeIdentifier(QName.create(Origin.QNAME, "value")));
+ private static final class AttributesCollection {
+ private final Collection<PathArgument> asPath;
+ private final Collection<PathArgument> locPref;
+ private final Collection<PathArgument> med;
+ private final Collection<PathArgument> orig;
+
+ AttributesCollection(final QName namespace) {
+ NodeIdentifier container = new NodeIdentifier(QName.cachedReference(QName.create(namespace, AsPath.QNAME.getLocalName())));
+ NodeIdentifier leaf = new NodeIdentifier(QName.cachedReference(QName.create(namespace, "segments")));
+ this.asPath = ImmutableList.<PathArgument>of(container, leaf);
+
+ container = new NodeIdentifier(QName.cachedReference(QName.create(namespace, LocalPref.QNAME.getLocalName())));
+ leaf = new NodeIdentifier(QName.cachedReference(QName.create(namespace, "pref")));
+ this.locPref = ImmutableList.<PathArgument>of(container, leaf);
+
+ container = new NodeIdentifier(QName.cachedReference(QName.create(namespace, MultiExitDisc.QNAME.getLocalName())));
+ leaf = new NodeIdentifier(QName.cachedReference(QName.create(namespace, "med")));
+ this.med = ImmutableList.<PathArgument>of(container, leaf);
+
+ container = new NodeIdentifier(QName.cachedReference(QName.create(namespace, Origin.QNAME.getLocalName())));
+ leaf = new NodeIdentifier(QName.cachedReference(QName.create(namespace, "value")));
+ this.orig = ImmutableList.<PathArgument>of(container, leaf);
+ }
+
+ Collection<PathArgument> getAsPath() {
+ return this.asPath;
+ }
+
+ Collection<PathArgument> getLocPref() {
+ return this.locPref;
+ }
+
+ Collection<PathArgument> getMed() {
+ return this.med;
+ }
+
+ Collection<PathArgument> getOrig() {
+ return this.orig;
+ }
+ }
+
+ private static final Logger LOG = LoggerFactory.getLogger(BestPathState.class);
+ private static final Cache<QNameModule, AttributesCollection> PATH_CACHE = CacheBuilder.newBuilder().weakKeys().weakValues().build();
+
+ private static Long peerAs = 0L;
+ private static int asPathLength = 0;
private final ContainerNode attributes;
+ private final AttributesCollection collection;
private Long localPref;
private Long multiExitDisc;
private BgpOrigin origin;
- private static final Long peerAs = 0L;
- private static final int asPathLength = 0;
private boolean resolved;
BestPathState(final ContainerNode attributes) {
+ final AttributesCollection col;
+ try {
+ col = PATH_CACHE.get(attributes.getNodeType().getModule(), new Callable<AttributesCollection>() {
+ @Override
+ public AttributesCollection call() {
+ return new AttributesCollection(attributes.getNodeType());
+ }
+ });
+ } catch (final ExecutionException e) {
+ LOG.error("Error creating namespace-specific attributes collection.", e);
+ throw new IllegalStateException("Error creating namespace-specific attributes collection.", e);
+ }
+
this.attributes = Preconditions.checkNotNull(attributes);
+ this.collection = col;
}
private static BgpOrigin fromString(final String originStr) {
return;
}
- final Optional<NormalizedNode<?, ?>> maybeLocalPref = NormalizedNodes.findNode(this.attributes, LOCAL_PREF);
+ final Optional<NormalizedNode<?, ?>> maybeLocalPref = NormalizedNodes.findNode(this.attributes, this.collection.getLocPref());
if (maybeLocalPref.isPresent()) {
this.localPref = (Long) ((LeafNode<?>)maybeLocalPref.get()).getValue();
} else {
this.localPref = null;
}
- final Optional<NormalizedNode<?, ?>> maybeMultiExitDisc = NormalizedNodes.findNode(this.attributes, MED);
+ final Optional<NormalizedNode<?, ?>> maybeMultiExitDisc = NormalizedNodes.findNode(this.attributes, this.collection.getMed());
if (maybeMultiExitDisc.isPresent()) {
this.multiExitDisc = (Long) ((LeafNode<?>)maybeMultiExitDisc.get()).getValue();
} else {
this.multiExitDisc = null;
}
- final Optional<NormalizedNode<?, ?>> maybeOrigin = NormalizedNodes.findNode(this.attributes, ORIGIN);
+ final Optional<NormalizedNode<?, ?>> maybeOrigin = NormalizedNodes.findNode(this.attributes, this.collection.getOrig());
if (maybeOrigin.isPresent()) {
this.origin = fromString((String) ((LeafNode<?>)maybeOrigin.get()).getValue());
} else {
this.origin = null;
}
- final Optional<NormalizedNode<?, ?>> maybeSegments = NormalizedNodes.findNode(this.attributes, AS_PATH);
+ final Optional<NormalizedNode<?, ?>> maybeSegments = NormalizedNodes.findNode(this.attributes, this.collection.getAsPath());
if (maybeSegments.isPresent()) {
final UnkeyedListNode segments = (UnkeyedListNode) maybeSegments.get();
Long getPeerAs() {
resolveValues();
- return this.peerAs;
+ return peerAs;
}
int getAsPathLength() {
import com.google.common.primitives.UnsignedInteger;
import org.junit.Test;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.AsPath;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.LocalPref;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.MultiExitDisc;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.Origin;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerId;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
public class BestPathSelectorTest {
- private final QName DATA_QNAME = QName.create("data");
+ private final QName extensionQName = QName.create("urn:opendaylight:params:xml:ns:yang:bgp-inet", "2015-03-05", "attributes");
+ private final QName localPrefQName = QName.create(this.extensionQName, "local-pref");
+ private final QName multiExitDiscQName = QName.create(this.extensionQName, "multi-exit-disc");
+ private final QName originQName = QName.create(this.extensionQName, "origin");
+ private final QName asPathQName = QName.create(this.extensionQName, "as-path");
private final UnsignedInteger ROUTER_ID = RouterIds.routerIdForAddress("127.0.0.1");
private final UnsignedInteger ROUTER_ID2 = RouterIds.routerIdForPeerId(new PeerId("bgp://127.0.0.1"));
private final UnsignedInteger ROUTER_ID3 = RouterIds.routerIdForPeerId(new PeerId("bgp://127.0.0.2"));
}
private ContainerNode createStateFromPrefMedOrigin() {
- this.dataContBuilder = createContBuilder(this.DATA_QNAME);
+ this.dataContBuilder = createContBuilder(this.extensionQName);
// local pref
- this.dataContBuilder.addChild(createContBuilder(LocalPref.QNAME).addChild(createValueBuilder(123L, LocalPref.QNAME, "pref").build()).build());
+ this.dataContBuilder.addChild(createContBuilder(this.localPrefQName).addChild(createValueBuilder(123L, this.localPrefQName, "pref").build()).build());
// multi exit disc
- this.dataContBuilder.addChild(createContBuilder(MultiExitDisc.QNAME).addChild(createValueBuilder(1234L, MultiExitDisc.QNAME, "med").build()).build());
+ this.dataContBuilder.addChild(createContBuilder(this.multiExitDiscQName).addChild(createValueBuilder(1234L, this.multiExitDiscQName, "med").build()).build());
// origin
- this.dataContBuilder.addChild(createContBuilder(Origin.QNAME).addChild(createValueBuilder("igp", Origin.QNAME, "value").build()).build());
+ this.dataContBuilder.addChild(createContBuilder(this.originQName).addChild(createValueBuilder("igp", this.originQName, "value").build()).build());
return this.dataContBuilder.build();
}
private ContainerNode createStateFromPrefMedOriginASPath() {
- this.dataContBuilder = createContBuilder(this.DATA_QNAME);
+ this.dataContBuilder = createContBuilder(this.extensionQName);
// local pref
- this.dataContBuilder.addChild(createContBuilder(LocalPref.QNAME).addChild(createValueBuilder(321L, LocalPref.QNAME, "pref").build()).build());
+ this.dataContBuilder.addChild(createContBuilder(this.localPrefQName).addChild(createValueBuilder(321L, this.localPrefQName, "pref").build()).build());
// multi exit disc
- this.dataContBuilder.addChild(createContBuilder(MultiExitDisc.QNAME).addChild(createValueBuilder(4321L, MultiExitDisc.QNAME, "med").build()).build());
+ this.dataContBuilder.addChild(createContBuilder(this.multiExitDiscQName).addChild(createValueBuilder(4321L, this.multiExitDiscQName, "med").build()).build());
// origin
- this.dataContBuilder.addChild(createContBuilder(Origin.QNAME).addChild(createValueBuilder("egp", Origin.QNAME, "value").build()).build());
+ this.dataContBuilder.addChild(createContBuilder(this.originQName).addChild(createValueBuilder("egp", this.originQName, "value").build()).build());
// as path
final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> asPathContBuilder = ImmutableContainerNodeSchemaAwareBuilder.create();
- asPathContBuilder.withNodeIdentifier(new NodeIdentifier(AsPath.QNAME));
+ asPathContBuilder.withNodeIdentifier(new NodeIdentifier(this.asPathQName));
final CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode> segments = ImmutableUnkeyedListNodeBuilder.create();
- segments.withNodeIdentifier(new NodeIdentifier(AsPath.QNAME));
+ segments.withNodeIdentifier(new NodeIdentifier(this.asPathQName));
final DataContainerNodeAttrBuilder<NodeIdentifier, UnkeyedListEntryNode> segmentBuilder = ImmutableUnkeyedListEntryNodeBuilder.create();
- segmentBuilder.withNodeIdentifier(new NodeIdentifier(AsPath.QNAME));
+ segmentBuilder.withNodeIdentifier(new NodeIdentifier(this.asPathQName));
final ImmutableLeafNodeBuilder<Long> segmentLeaf = new ImmutableLeafNodeBuilder<>();
- segmentLeaf.withNodeIdentifier(new NodeIdentifier(QName.create(AsPath.QNAME, "segments"))).withValue(123454L);
+ segmentLeaf.withNodeIdentifier(new NodeIdentifier(QName.create(this.asPathQName, "segments"))).withValue(123454L);
segmentBuilder.addChild(segmentLeaf.build());
segments.addChild(segmentBuilder.build());