Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HDDS-9343. Shift sortDatanodes logic to OM #5391

Merged
merged 29 commits into from
Mar 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
df4c96d
HDDS-9389. Introduce new API and cache refresh for serving network to…
Dec 18, 2023
1d006b2
Fix findbugs
Dec 18, 2023
1780d45
Fix LOG.info typos
Dec 18, 2023
36127da
Modify clusterMap object based on the refetched clusterTree from SCM
Dec 21, 2023
c213528
Incorporate dfs.datanode.use.datanode.hostname while filtering matchi…
Dec 21, 2023
d63ca30
Merge remote-tracking branch 'origin' into HDDS-9343
Jan 9, 2024
eff32f1
Merge remote-tracking branch 'origin' into HDDS-9343
Jan 11, 2024
98f8560
Merge branch 'master' into HDDS-9389
Jan 17, 2024
8b33b7b
Merge remote-tracking branch 'origin' into HDDS-9389
Jan 23, 2024
b9741bc
import assertEquals
Jan 29, 2024
9dd266a
Fix TestOmContainerLocationCache
Jan 29, 2024
f623f9d
Fix TestBlockOutputStreamWithFailures
Jan 29, 2024
3d9c241
Address review comments
Feb 5, 2024
a1c6ff8
Include level, parent information, handle case of read from non-datan…
Feb 12, 2024
91e12c5
Refactor proto objects, address reviews
Feb 12, 2024
113d045
NetworkTopologyImpl#getDistanceCost: account for null objects, fix fa…
Feb 13, 2024
f4594a3
Change NodeType to NetworkNode
Feb 13, 2024
80d5a6e
Change NodeImpl to NodeTopology
Feb 13, 2024
fff4abe
Modify proto objects to optional and corresponding usages
Feb 13, 2024
140e3f9
Fix typo
Feb 13, 2024
5b9c577
Merge remote-tracking branch 'origin' into HDDS-9389
Feb 22, 2024
6bda4a7
Resolve node location for reads from non-datanodes hosts within OM
Feb 22, 2024
b62695f
Remove force refetching of clusterTree information
Feb 22, 2024
85e5c60
Merge remote-tracking branch 'origin' into HDDS-9389
Feb 26, 2024
c528224
Remove tests in TestKeyManagerUnit that reference ScmBlockLocationPro…
Feb 27, 2024
db5beab
Fix checkstyle
Feb 27, 2024
c3e04fd
Add tests for KeyManagerImpl#sortDatanodes
Feb 27, 2024
1d1d5d1
Fix findbugs
Feb 27, 2024
8fba5c9
Fix integration (ozone) test failure
Feb 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,9 @@ public static DatanodeDetails.Builder newBuilder(
if (datanodeDetailsProto.hasNetworkLocation()) {
builder.setNetworkLocation(datanodeDetailsProto.getNetworkLocation());
}
if (datanodeDetailsProto.hasLevel()) {
builder.setLevel(datanodeDetailsProto.getLevel());
}
if (datanodeDetailsProto.hasPersistedOpState()) {
builder.setPersistedOpState(datanodeDetailsProto.getPersistedOpState());
}
Expand Down Expand Up @@ -456,6 +459,9 @@ public HddsProtos.DatanodeDetailsProto.Builder toProtoBuilder(
if (!Strings.isNullOrEmpty(getNetworkLocation())) {
builder.setNetworkLocation(getNetworkLocation());
}
if (getLevel() > 0) {
builder.setLevel(getLevel());
}
if (persistedOpState != null) {
builder.setPersistedOpState(persistedOpState);
}
Expand Down Expand Up @@ -585,6 +591,7 @@ public static final class Builder {
private String hostName;
private String networkName;
private String networkLocation;
private int level;
private List<Port> ports;
private String certSerialId;
private String version;
Expand Down Expand Up @@ -616,6 +623,7 @@ public Builder setDatanodeDetails(DatanodeDetails details) {
this.hostName = details.getHostName();
this.networkName = details.getNetworkName();
this.networkLocation = details.getNetworkLocation();
this.level = details.getLevel();
this.ports = details.getPorts();
this.certSerialId = details.getCertSerialId();
this.version = details.getVersion();
Expand Down Expand Up @@ -683,6 +691,11 @@ public Builder setNetworkLocation(String loc) {
return this;
}

public Builder setLevel(int level) {
this.level = level;
return this;
}

/**
* Adds a DataNode Port.
*
Expand Down Expand Up @@ -807,6 +820,9 @@ public DatanodeDetails build() {
if (networkName != null) {
dn.setNetworkName(networkName);
}
if (level > 0) {
dn.setLevel(level);
}
return dn;
}
}
Expand Down Expand Up @@ -1011,4 +1027,13 @@ public String getBuildDate() {
public void setBuildDate(String date) {
this.buildDate = date;
}

@Override
public HddsProtos.NetworkNode toProtobuf(
int clientVersion) {
HddsProtos.NetworkNode networkNode =
HddsProtos.NetworkNode.newBuilder()
.setDatanodeDetails(toProtoBuilder(clientVersion).build()).build();
return networkNode;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import java.util.Collection;
import java.util.List;

import org.apache.hadoop.hdds.protocol.proto.HddsProtos;

/**
* The interface defines an inner node in a network topology.
* An inner node represents network topology entities, such as data center,
Expand Down Expand Up @@ -89,4 +91,16 @@ N newInnerNode(String name, String location, InnerNode parent, int level,
*/
Node getLeaf(int leafIndex, List<String> excludedScopes,
Collection<Node> excludedNodes, int ancestorGen);

@Override
HddsProtos.NetworkNode toProtobuf(int clientVersion);

boolean equals(Object o);

int hashCode();

static InnerNode fromProtobuf(
HddsProtos.InnerNode innerNode) {
return InnerNodeImpl.fromProtobuf(innerNode);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.util.Map;

import com.google.common.base.Preconditions;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -47,10 +48,10 @@ public InnerNodeImpl newInnerNode(String name, String location,
}
}

static final Factory FACTORY = new Factory();
public static final Factory FACTORY = new Factory();
// a map of node's network name to Node for quick search and keep
// the insert order
private final HashMap<String, Node> childrenMap =
private HashMap<String, Node> childrenMap =
new LinkedHashMap<String, Node>();
// number of descendant leaves under this node
private int numOfLeaves;
Expand All @@ -66,6 +67,76 @@ protected InnerNodeImpl(String name, String location, InnerNode parent,
super(name, location, parent, level, cost);
}

/**
* Construct an InnerNode from its name, network location, level, cost,
* childrenMap and number of leaves. This constructor is used as part of
* protobuf deserialization.
*/
protected InnerNodeImpl(String name, String location, int level, int cost,
HashMap<String, Node> childrenMap, int numOfLeaves) {
super(name, location, null, level, cost);
this.childrenMap = childrenMap;
this.numOfLeaves = numOfLeaves;
}

/**
* InnerNodeImpl Builder to help construct an InnerNodeImpl object from
* protobuf objects.
*/
public static class Builder {
private String name;
private String location;
private int cost;
private int level;
private HashMap<String, Node> childrenMap = new LinkedHashMap<>();
private int numOfLeaves;

public Builder setName(String name) {
this.name = name;
return this;
}

public Builder setLocation(String location) {
this.location = location;
return this;
}

public Builder setCost(int cost) {
this.cost = cost;
return this;
}

public Builder setLevel(int level) {
this.level = level;
return this;
}

public Builder setChildrenMap(
List<HddsProtos.ChildrenMap> childrenMapList) {
HashMap<String, Node> newChildrenMap = new LinkedHashMap<>();
for (HddsProtos.ChildrenMap childrenMapProto :
childrenMapList) {
String networkName = childrenMapProto.hasNetworkName() ?
childrenMapProto.getNetworkName() : null;
Node node = childrenMapProto.hasNetworkNode() ?
Node.fromProtobuf(childrenMapProto.getNetworkNode()) : null;
newChildrenMap.put(networkName, node);
}
this.childrenMap = newChildrenMap;
return this;
}

public Builder setNumOfLeaves(int numOfLeaves) {
this.numOfLeaves = numOfLeaves;
return this;
}

public InnerNodeImpl build() {
return new InnerNodeImpl(name, location, level, cost, childrenMap,
numOfLeaves);
}
}

/** @return the number of children this node has */
private int getNumOfChildren() {
return childrenMap.size();
Expand All @@ -77,6 +148,11 @@ public int getNumOfLeaves() {
return numOfLeaves;
}

/** @return a map of node's network name to Node. */
public HashMap<String, Node> getChildrenMap() {
return childrenMap;
}

/**
* @return number of its all nodes at level <i>level</i>. Here level is a
* relative level. If level is 1, means node itself. If level is 2, means its
Expand Down Expand Up @@ -390,14 +466,83 @@ public Node getLeaf(int leafIndex, List<String> excludedScopes,
}

@Override
public boolean equals(Object to) {
if (to == null) {
return false;
public HddsProtos.NetworkNode toProtobuf(
int clientVersion) {

HddsProtos.InnerNode.Builder innerNode =
HddsProtos.InnerNode.newBuilder()
.setNumOfLeaves(numOfLeaves)
.setNodeTopology(
NodeImpl.toProtobuf(getNetworkName(), getNetworkLocation(),
getLevel(), getCost()));

if (childrenMap != null && !childrenMap.isEmpty()) {
for (Map.Entry<String, Node> entry : childrenMap.entrySet()) {
if (entry.getValue() != null) {
HddsProtos.ChildrenMap childrenMapProto =
HddsProtos.ChildrenMap.newBuilder()
.setNetworkName(entry.getKey())
.setNetworkNode(entry.getValue().toProtobuf(clientVersion))
.build();
innerNode.addChildrenMap(childrenMapProto);
}
}
}
innerNode.build();

HddsProtos.NetworkNode networkNode =
HddsProtos.NetworkNode.newBuilder()
.setInnerNode(innerNode).build();

return networkNode;
}

public static InnerNode fromProtobuf(HddsProtos.InnerNode innerNode) {
InnerNodeImpl.Builder builder = new InnerNodeImpl.Builder();

if (innerNode.hasNodeTopology()) {
HddsProtos.NodeTopology nodeTopology = innerNode.getNodeTopology();

if (nodeTopology.hasName()) {
builder.setName(nodeTopology.getName());
}
if (nodeTopology.hasLocation()) {
builder.setLocation(nodeTopology.getLocation());
}
if (nodeTopology.hasLevel()) {
builder.setLevel(nodeTopology.getLevel());
}
if (nodeTopology.hasCost()) {
builder.setCost(nodeTopology.getCost());
}
}

if (!innerNode.getChildrenMapList().isEmpty()) {
builder.setChildrenMap(innerNode.getChildrenMapList());
}
if (innerNode.hasNumOfLeaves()) {
builder.setNumOfLeaves(innerNode.getNumOfLeaves());
}
if (this == to) {

return builder.build();
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
return this.toString().equals(to.toString());
if (o == null || getClass() != o.getClass()) {
return false;
}
InnerNodeImpl innerNode = (InnerNodeImpl) o;
return this.getNetworkName().equals(innerNode.getNetworkName()) &&
this.getNetworkLocation().equals(innerNode.getNetworkLocation()) &&
this.getLevel() == innerNode.getLevel() &&
this.getCost() == innerNode.getCost() &&
this.numOfLeaves == innerNode.numOfLeaves &&
this.childrenMap.size() == innerNode.childrenMap.size() &&
this.childrenMap.equals(innerNode.childrenMap);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,15 @@ public NetworkTopologyImpl(ConfigurationSource conf) {
schemaManager.getCost(NetConstants.ROOT_LEVEL));
}

public NetworkTopologyImpl(String schemaFile, InnerNode clusterTree) {
schemaManager = NodeSchemaManager.getInstance();
schemaManager.init(schemaFile);
maxLevel = schemaManager.getMaxLevel();
shuffleOperation = Collections::shuffle;
factory = InnerNodeImpl.FACTORY;
this.clusterTree = clusterTree;
}

@VisibleForTesting
public NetworkTopologyImpl(NodeSchemaManager manager,
Consumer<List<? extends Node>> shuffleOperation) {
Expand Down Expand Up @@ -726,8 +735,13 @@ public int getDistanceCost(Node node1, Node node2) {
int cost = 0;
netlock.readLock().lock();
try {
if ((node1.getAncestor(level1 - 1) != clusterTree) ||
(node2.getAncestor(level2 - 1) != clusterTree)) {
Node ancestor1 = node1.getAncestor(level1 - 1);
boolean node1Topology = (ancestor1 != null && clusterTree != null &&
!ancestor1.equals(clusterTree)) || (ancestor1 != clusterTree);
Node ancestor2 = node2.getAncestor(level2 - 1);
boolean node2Topology = (ancestor2 != null && clusterTree != null &&
!ancestor2.equals(clusterTree)) || (ancestor2 != clusterTree);
if (node1Topology || node2Topology) {
LOG.debug("One of the nodes is outside of network topology");
return Integer.MAX_VALUE;
}
Expand All @@ -741,7 +755,7 @@ public int getDistanceCost(Node node1, Node node2) {
level2--;
cost += node2 == null ? 0 : node2.getCost();
}
while (node1 != null && node2 != null && node1 != node2) {
while (node1 != null && node2 != null && !node1.equals(node2)) {
node1 = node1.getParent();
node2 = node2.getParent();
cost += node1 == null ? 0 : node1.getCost();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
*/
package org.apache.hadoop.hdds.scm.net;

import org.apache.hadoop.hdds.protocol.DatanodeDetails;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;

/**
* The interface defines a node in a network topology.
* A node may be a leave representing a data node or an inner
Expand Down Expand Up @@ -126,4 +129,21 @@ public interface Node {
* @return true if this node is under a specific scope
*/
boolean isDescendant(String nodePath);

default HddsProtos.NetworkNode toProtobuf(
int clientVersion) {
return null;
}

static Node fromProtobuf(
HddsProtos.NetworkNode networkNode) {
if (networkNode.hasDatanodeDetails()) {
return DatanodeDetails.getFromProtoBuf(
networkNode.getDatanodeDetails());
} else if (networkNode.hasInnerNode()) {
return InnerNode.fromProtobuf(networkNode.getInnerNode());
} else {
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package org.apache.hadoop.hdds.scm.net;

import com.google.common.base.Preconditions;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;

import static org.apache.hadoop.hdds.scm.net.NetConstants.ROOT;
import static org.apache.hadoop.hdds.scm.net.NetConstants.PATH_SEPARATOR_STR;
Expand Down Expand Up @@ -229,6 +230,20 @@ public boolean isDescendant(String nodePath) {
NetUtils.addSuffix(nodePath));
}

public static HddsProtos.NodeTopology toProtobuf(String name, String location,
int level, int cost) {

HddsProtos.NodeTopology.Builder nodeTopologyBuilder =
HddsProtos.NodeTopology.newBuilder()
.setName(name)
.setLocation(location)
.setLevel(level)
.setCost(cost);

HddsProtos.NodeTopology nodeTopology = nodeTopologyBuilder.build();
return nodeTopology;
}

@Override
public boolean equals(Object to) {
if (to == null) {
Expand Down