blob: 23bbb98bb00c22ca98bdf2ac661666091221e066 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.hadoop.tools.rumen;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.ArrayList;
import java.util.Comparator;
import org.apache.hadoop.tools.rumen.datatypes.NodeName;
import org.codehaus.jackson.annotate.JsonAnySetter;
/**
* A {@link LoggedNetworkTopology} represents a tree that in turn represents a
* hierarchy of hosts. The current version requires the tree to have all leaves
* at the same level.
*
* All of the public methods are simply accessors for the instance variables we
* want to write out in the JSON files.
*
*/
public class LoggedNetworkTopology implements DeepCompare {
NodeName name;
List<LoggedNetworkTopology> children = new ArrayList<LoggedNetworkTopology>();
static private Set<String> alreadySeenAnySetterAttributes =
new TreeSet<String>();
public LoggedNetworkTopology() {
super();
}
// for input parameter ignored.
@JsonAnySetter
public void setUnknownAttribute(String attributeName, Object ignored) {
if (!alreadySeenAnySetterAttributes.contains(attributeName)) {
alreadySeenAnySetterAttributes.add(attributeName);
System.err.println("In LoggedJob, we saw the unknown attribute "
+ attributeName + ".");
}
}
/**
* We need this because we have to sort the {@code children} field. That field
* is set-valued, but if we sort these fields we ensure that comparisons won't
* bogusly fail because the hash table happened to enumerate in a different
* order.
*
*/
static class TopoSort implements Comparator<LoggedNetworkTopology>,
Serializable {
public int compare(LoggedNetworkTopology t1, LoggedNetworkTopology t2) {
return t1.name.getValue().compareTo(t2.name.getValue());
}
}
/**
* @param hosts
* a HashSet of the {@link ParsedHost}
* @param name
* the name of this level's host [for recursive descent]
* @param level
* the level number
*/
LoggedNetworkTopology(Set<ParsedHost> hosts, String name, int level) {
if (name == null) {
this.name = NodeName.ROOT;
} else {
this.name = new NodeName(name);
}
this.children = null;
if (level < ParsedHost.numberOfDistances() - 1) {
HashMap<String, HashSet<ParsedHost>> topologies =
new HashMap<String, HashSet<ParsedHost>>();
Iterator<ParsedHost> iter = hosts.iterator();
while (iter.hasNext()) {
ParsedHost host = iter.next();
String thisComponent = host.nameComponent(level);
HashSet<ParsedHost> thisSet = topologies.get(thisComponent);
if (thisSet == null) {
thisSet = new HashSet<ParsedHost>();
topologies.put(thisComponent, thisSet);
}
thisSet.add(host);
}
children = new ArrayList<LoggedNetworkTopology>();
for (Map.Entry<String, HashSet<ParsedHost>> ent : topologies.entrySet()) {
children.add(new LoggedNetworkTopology(ent.getValue(), ent.getKey(),
level + 1));
}
} else {
// nothing to do here
}
}
LoggedNetworkTopology(Set<ParsedHost> hosts) {
this(hosts, null, 0);
}
public NodeName getName() {
return name;
}
void setName(String name) {
this.name = new NodeName(name);
}
public List<LoggedNetworkTopology> getChildren() {
return children;
}
void setChildren(List<LoggedNetworkTopology> children) {
this.children = children;
}
private void compare1(List<LoggedNetworkTopology> c1,
List<LoggedNetworkTopology> c2, TreePath loc, String eltname)
throws DeepInequalityException {
if (c1 == null && c2 == null) {
return;
}
if (c1 == null || c2 == null || c1.size() != c2.size()) {
throw new DeepInequalityException(eltname + " miscompared", new TreePath(
loc, eltname));
}
Collections.sort(c1, new TopoSort());
Collections.sort(c2, new TopoSort());
for (int i = 0; i < c1.size(); ++i) {
c1.get(i).deepCompare(c2.get(i), new TreePath(loc, eltname, i));
}
}
public void deepCompare(DeepCompare comparand, TreePath loc)
throws DeepInequalityException {
if (!(comparand instanceof LoggedNetworkTopology)) {
throw new DeepInequalityException("comparand has wrong type", loc);
}
LoggedNetworkTopology other = (LoggedNetworkTopology) comparand;
compare1(children, other.children, loc, "children");
}
}