| /** |
| * 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.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.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 { |
| String name; |
| List<LoggedNetworkTopology> children = new ArrayList<LoggedNetworkTopology>(); |
| |
| static private Set<String> alreadySeenAnySetterAttributes = |
| new TreeSet<String>(); |
| |
| public LoggedNetworkTopology() { |
| super(); |
| } |
| |
| @SuppressWarnings("unused") |
| // 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> { |
| public int compare(LoggedNetworkTopology t1, LoggedNetworkTopology t2) { |
| return t1.name.compareTo(t2.name); |
| } |
| } |
| |
| /** |
| * @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) { |
| |
| this.name = 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, "<root>", 0); |
| } |
| |
| public String getName() { |
| return name; |
| } |
| |
| void setName(String name) { |
| this.name = 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"); |
| } |
| } |