/** Creates a mutable copy of {@code graph} with the same nodes, edges, and edge values. */ public static <N, V> MutableValueGraph<N, V> copyOf(ValueGraph<N, V> graph) { MutableValueGraph<N, V> copy = ValueGraphBuilder.from(graph).expectedNodeCount(graph.nodes().size()).build(); for (N node : graph.nodes()) { copy.addNode(node); } for (EndpointPair<N> edge : graph.edges()) { copy.putEdgeValue( edge.nodeU(), edge.nodeV(), graph.edgeValueOrDefault(edge.nodeU(), edge.nodeV(), null)); } return copy; }
private static <N, V> GraphConnections<N, V> connectionsOf( final ValueGraph<N, V> graph, final N node) { Function<N, V> successorNodeToValueFn = new Function<N, V>() { @Override public V apply(N successorNode) { return graph.edgeValueOrDefault(node, successorNode, null); } }; return graph.isDirected() ? DirectedGraphConnections.ofImmutable( graph.predecessors(node), Maps.asMap(graph.successors(node), successorNodeToValueFn)) : UndirectedGraphConnections.ofImmutable( Maps.asMap(graph.adjacentNodes(node), successorNodeToValueFn)); } }
@Override public Optional<V> edgeValue(EndpointPair<N> endpoints) { return delegate().edgeValue(endpoints); }
/** * Returns a {@link ValueGraphBuilder} initialized with all properties queryable from {@code * graph}. * * <p>The "queryable" properties are those that are exposed through the {@link ValueGraph} * interface, such as {@link ValueGraph#isDirected()}. Other properties, such as {@link * #expectedNodeCount(int)}, are not set in the new builder. */ public static <N, V> ValueGraphBuilder<N, V> from(ValueGraph<N, V> graph) { return new ValueGraphBuilder<N, V>(graph.isDirected()) .allowsSelfLoops(graph.allowsSelfLoops()) .nodeOrder(graph.nodeOrder()); }
@Override public final boolean equals(@Nullable Object obj) { if (obj == this) { return true; } if (!(obj instanceof ValueGraph)) { return false; } ValueGraph<?, ?> other = (ValueGraph<?, ?>) obj; return isDirected() == other.isDirected() && nodes().equals(other.nodes()) && edgeValueMap(this).equals(edgeValueMap(other)); }
/** * Defer to {@link AbstractValueGraph#edges()} (based on {@link #successors(Object)}) for full * edges() implementation. */ @Override protected long edgeCount() { return delegate().edges().size(); }
@Test public void transpose_directedValueGraph() { MutableValueGraph<Integer, String> directedGraph = ValueGraphBuilder.directed().allowsSelfLoops(true).build(); directedGraph.putEdgeValue(N1, N3, E13); directedGraph.putEdgeValue(N3, N1, E31); directedGraph.putEdgeValue(N1, N2, E12); directedGraph.putEdgeValue(N1, N1, E11); directedGraph.putEdgeValue(N3, N4, E34); MutableValueGraph<Integer, String> expectedTranspose = ValueGraphBuilder.directed().allowsSelfLoops(true).build(); expectedTranspose.putEdgeValue(N3, N1, E13); expectedTranspose.putEdgeValue(N1, N3, E31); expectedTranspose.putEdgeValue(N2, N1, E12); expectedTranspose.putEdgeValue(N1, N1, E11); expectedTranspose.putEdgeValue(N4, N3, E34); ValueGraph<Integer, String> transpose = transpose(directedGraph); assertThat(transpose).isEqualTo(expectedTranspose); assertThat(transpose(transpose)).isSameAs(directedGraph); AbstractGraphTest.validateGraph(transpose.asGraph()); assertThat(transpose.edgeValueOrDefault(N1, N2, null)).isNull(); for (Integer node : directedGraph.nodes()) { assertThat(directedGraph.inDegree(node)).isSameAs(transpose.outDegree(node)); assertThat(directedGraph.outDegree(node)).isSameAs(transpose.inDegree(node)); } directedGraph.putEdgeValue(N2, N1, E21); // View should be updated. assertThat(transpose.edgeValueOrDefault(N1, N2, null)).isEqualTo(E21); AbstractGraphTest.validateGraph(transpose.asGraph()); }
for (BgpPeerConfigId bgpPeerConfigId : bgpTopology.nodes()) { BgpPeerConfig bgpPeerConfig = nc.getBgpPeerConfig(bgpPeerConfigId); String hostname = bgpPeerConfigId.getHostname(); continue; if (bgpTopology.adjacentNodes(bgpPeerConfigId).isEmpty()) { bgpSessionInfo._status = SessionStatus.HALF_OPEN; } else if (bgpTopology.degree(bgpPeerConfigId) > 2) { bgpSessionInfo._status = SessionStatus.MULTIPLE_REMOTES; } else { BgpPeerConfigId remoteNeighborId = bgpTopology.adjacentNodes(bgpPeerConfigId).iterator().next(); bgpSessionInfo._remoteNode = remoteNeighborId.getHostname(); bgpSessionInfo._status = SessionStatus.UNIQUE_MATCH;
@Override public int inDegree(N node) { return delegate().outDegree(node); // transpose }
private static <N, V> ImmutableMap<N, GraphConnections<N, V>> getNodeConnections( ValueGraph<N, V> graph) { // ImmutableMap.Builder maintains the order of the elements as inserted, so the map will have // whatever ordering the graph's nodes do, so ImmutableSortedMap is unnecessary even if the // input nodes are sorted. ImmutableMap.Builder<N, GraphConnections<N, V>> nodeConnections = ImmutableMap.builder(); for (N node : graph.nodes()) { nodeConnections.put(node, connectionsOf(graph, node)); } return nodeConnections.build(); }
@Override public int inDegree(N node) { return delegate().inDegree(node); }
@Override public V apply(N successorNode) { return graph.edgeValueOrDefault(node, successorNode, null); } };
/** Creates a mutable copy of {@code graph} with the same nodes, edges, and edge values. */ public static <N, V> MutableValueGraph<N, V> copyOf(ValueGraph<N, V> graph) { MutableValueGraph<N, V> copy = ValueGraphBuilder.from(graph).expectedNodeCount(graph.nodes().size()).build(); for (N node : graph.nodes()) { copy.addNode(node); } for (EndpointPair<N> edge : graph.edges()) { copy.putEdgeValue( edge.nodeU(), edge.nodeV(), graph.edgeValueOrDefault(edge.nodeU(), edge.nodeV(), null)); } return copy; }
@Override public Set<N> adjacentNodes(N node) { return delegate().adjacentNodes(node); }
static void assertStronglyEquivalent(ValueGraph<?, ?> graphA, ValueGraph<?, ?> graphB) { // Properties not covered by equals() assertThat(graphA.allowsSelfLoops()).isEqualTo(graphB.allowsSelfLoops()); assertThat(graphA.nodeOrder()).isEqualTo(graphB.nodeOrder()); assertThat(graphA).isEqualTo(graphB); }
/** * Initialize incoming BGP message queues. * * @param bgpTopology source of truth for which sessions get established. */ void initBgpQueues(ValueGraph<BgpPeerConfigId, BgpSessionProperties> bgpTopology) { if (_vrf.getBgpProcess() == null) { _bgpIncomingRoutes = ImmutableSortedMap.of(); } else { _bgpIncomingRoutes = Stream.concat( _vrf.getBgpProcess().getActiveNeighbors().entrySet().stream() .map( e -> new BgpPeerConfigId( getHostname(), _vrf.getName(), e.getKey(), false)), _vrf.getBgpProcess().getPassiveNeighbors().entrySet().stream() .map( e -> new BgpPeerConfigId(getHostname(), _vrf.getName(), e.getKey(), true))) .filter(bgpTopology.nodes()::contains) .flatMap( dst -> bgpTopology.adjacentNodes(dst).stream().map(src -> new BgpEdgeId(src, dst))) .collect( toImmutableSortedMap(Function.identity(), e -> new ConcurrentLinkedQueue<>())); } }
/** * Returns the subgraph of {@code graph} induced by {@code nodes}. This subgraph is a new graph * that contains all of the nodes in {@code nodes}, and all of the {@link Graph#edges() edges} * (and associated edge values) from {@code graph} for which both nodes are contained by {@code * nodes}. * * @throws IllegalArgumentException if any element in {@code nodes} is not a node in the graph */ public static <N, V> MutableValueGraph<N, V> inducedSubgraph( ValueGraph<N, V> graph, Iterable<? extends N> nodes) { MutableValueGraph<N, V> subgraph = (nodes instanceof Collection) ? ValueGraphBuilder.from(graph).expectedNodeCount(((Collection) nodes).size()).build() : ValueGraphBuilder.from(graph).build(); for (N node : nodes) { subgraph.addNode(node); } for (N node : subgraph.nodes()) { for (N successorNode : graph.successors(node)) { if (subgraph.nodes().contains(successorNode)) { subgraph.putEdgeValue( node, successorNode, graph.edgeValueOrDefault(node, successorNode, null)); } } } return subgraph; }
@Override public int degree(N node) { return delegate().degree(node); }
static @Nonnull ConfiguredSessionStatus getConfiguredStatus( BgpPeerConfigId bgpPeerConfigId, BgpActivePeerConfig activePeerConfig, SessionType sessionType, Set<Ip> allInterfaceIps, ValueGraph<BgpPeerConfigId, BgpSessionProperties> configuredBgpTopology) { ConfiguredSessionStatus brokenStatus = getLocallyBrokenStatus(activePeerConfig, sessionType); if (brokenStatus != null) { return brokenStatus; } // Nothing blatantly broken so far on the local side, keep checking. Ip localIp = activePeerConfig.getLocalIp(); Ip remoteIp = activePeerConfig.getPeerAddress(); if (!allInterfaceIps.contains(localIp)) { return ConfiguredSessionStatus.INVALID_LOCAL_IP; } else if (!allInterfaceIps.contains(remoteIp)) { return ConfiguredSessionStatus.UNKNOWN_REMOTE; } else if (configuredBgpTopology.adjacentNodes(bgpPeerConfigId).isEmpty()) { return ConfiguredSessionStatus.HALF_OPEN; } else if (configuredBgpTopology.outDegree(bgpPeerConfigId) > 1) { return ConfiguredSessionStatus.MULTIPLE_REMOTES; } return ConfiguredSessionStatus.UNIQUE_MATCH; }
@Override public boolean allowsSelfLoops() { return delegate().allowsSelfLoops(); }