All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hazelcast.jet.impl.execution.init.DagNodeUtil Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2008-2024, Hazelcast, Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.hazelcast.jet.impl.execution.init;

import com.hazelcast.cluster.Address;
import com.hazelcast.internal.util.collection.Int2ObjectHashMap;
import com.hazelcast.jet.core.Edge;

import java.util.ArrayDeque;
import java.util.BitSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Queue;
import java.util.Set;

/**
 * A utility to deploy DAG on nodes. It helps to find which vertices never
 * receive data on some nodes and avoid creating processors on those nodes and
 * also queues, sender and receiver tasklets to those nodes.
 *
 * 
{@code
 * /--------|--------\
 * | Node 1 | Node 2 |
 * |--------|--------|
 * |   V1       V1   |
 * |   ||       //   |
 * |   ||    //      |
 * |   ||  //        |
 * |   \/|/          |
 * |   V2            |
 * \_________________/
 * }
* * The V2 operator doesn't need to be created on the second node. We also do not * need to create V1 -> V2 edge from the first to the second node. *

* We don't use Java streams here for a better performance. */ class DagNodeUtil { private final Address localAddress; private final BitSet localVertices; private final Map> targets = new HashMap<>(); private final Map> sources = new HashMap<>(); @SuppressWarnings("checkstyle:executablestatementcount") DagNodeUtil(List vertices, Set

allAddresses, Address localAddress) { this.localAddress = localAddress; Int2ObjectHashMap> vertexOnAddress = new Int2ObjectHashMap<>(); Map> edgesToConnections = new HashMap<>(); Queue queue = new ArrayDeque<>(vertices.size()); BitSet visited = new BitSet(vertices.size()); for (VertexDef vertex : vertices) { if (vertex.inboundEdges().isEmpty()) { vertexOnAddress.put(vertex.vertexId(), allAddresses); queue.add(vertex); } else { vertexOnAddress.put(vertex.vertexId(), new HashSet<>()); } } while (!queue.isEmpty()) { VertexDef current = queue.poll(); visited.set(current.vertexId()); Set
currentVertexAddresses = vertexOnAddress.get(current.vertexId()); for (EdgeDef outboundEdge : current.outboundEdges()) { traverse(outboundEdge, currentVertexAddresses, allAddresses, vertexOnAddress, edgesToConnections); if (allSourcesVisited(outboundEdge.destVertex(), visited) && !visited.get(outboundEdge.destVertex().vertexId())) { queue.add(outboundEdge.destVertex()); } } } localVertices = new BitSet(vertices.size()); populateFields(vertexOnAddress, edgesToConnections); } private void populateFields( Int2ObjectHashMap> vertexOnAddress, Map> edgesToConnections ) { for (Entry> entry : vertexOnAddress.entrySet()) { if (entry.getValue().contains(localAddress)) { localVertices.set(entry.getKey()); } } for (String edgeId : edgesToConnections.keySet()) { sources.put(edgeId, new HashSet<>()); targets.put(edgeId, new HashSet<>()); } for (Entry> entry : edgesToConnections.entrySet()) { for (Connection connection : entry.getValue()) { if (connection.isTo(localAddress)) { sources.computeIfAbsent(entry.getKey(), x -> new HashSet<>()).add(connection.from); } if (connection.isFrom(localAddress)) { targets.computeIfAbsent(entry.getKey(), x -> new HashSet<>()).add(connection.to); } } } } private void traverse( EdgeDef outboundEdge, Set
currentVertexAddresses, Set
allAddresses, Int2ObjectHashMap> vertexOnAddress, Map> edgesToConnections ) { Set connections = edgesToConnections.computeIfAbsent(outboundEdge.edgeId(), edgeDef -> new HashSet<>()); if (outboundEdge.isLocal()) { for (Address address : currentVertexAddresses) { connections.add(new Connection(address, address)); Set
addresses = vertexOnAddress.get(outboundEdge.destVertex().vertexId()); if (addresses.size() != allAddresses.size()) { addresses.add(address); } } } else if (outboundEdge.getDistributedTo().equals(Edge.DISTRIBUTE_TO_ALL)) { for (Address sourceAddress : currentVertexAddresses) { for (Address targetAddress : allAddresses) { connections.add(new Connection(sourceAddress, targetAddress)); } } vertexOnAddress.put(outboundEdge.destVertex().vertexId(), allAddresses); } else { for (Address address : currentVertexAddresses) { connections.add(new Connection(address, outboundEdge.getDistributedTo())); } Set
addresses = vertexOnAddress.get(outboundEdge.destVertex().vertexId()); if (addresses.size() != allAddresses.size()) { addresses.add(outboundEdge.getDistributedTo()); } } } private boolean allSourcesVisited(VertexDef current, BitSet visited) { for (EdgeDef inboundEdge : current.inboundEdges()) { if (!visited.get(inboundEdge.sourceVertex().vertexId())) { return false; } } return true; } Set
getEdgeTargets(EdgeDef edge) { return targets.get(edge.edgeId()); } Set
getEdgeSources(EdgeDef edge) { return sources.get(edge.edgeId()); } boolean vertexExists(VertexDef vertex) { return localVertices.get(vertex.vertexId()); } int numRemoteSources(EdgeDef edge) { Set
edgeSources = sources.get(edge.edgeId()); return edgeSources.contains(localAddress) ? edgeSources.size() - 1 : edgeSources.size(); } private static class Connection { final Address from; final Address to; private final int hashCode; Connection(Address from, Address to) { this.from = from; this.to = to; this.hashCode = Objects.hash(from, to); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Connection that = (Connection) o; return hashCode == that.hashCode && Objects.equals(from, that.from) && Objects.equals(to, that.to); } boolean isFrom(Address from) { return from.equals(this.from); } boolean isTo(Address to) { return to.equals(this.to); } @Override public int hashCode() { return hashCode; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy