001/**002 * Licensed to the Apache Software Foundation (ASF) under one003 * or more contributor license agreements. See the NOTICE file004 * distributed with this work for additional information005 * regarding copyright ownership. The ASF licenses this file006 * to you under the Apache License, Version 2.0 (the007 * "License"); you may not use this file except in compliance008 * with the License. You may obtain a copy of the License at009 *010 * http://www.apache.org/licenses/LICENSE-2.0011 *012 * Unless required by applicable law or agreed to in writing, software013 * distributed under the License is distributed on an "AS IS" BASIS,014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.015 * See the License for the specific language governing permissions and016 * limitations under the License.017 */018019package org.apache.hadoop.net;020021import org.apache.hadoop.classification.InterfaceAudience;022import org.apache.hadoop.classification.InterfaceStability;023import org.apache.hadoop.conf.Configurable;024import org.apache.hadoop.conf.Configuration;025import org.apache.hadoop.fs.CommonConfigurationKeys;026027import java.util.HashSet;028import java.util.Map;029import java.util.Set;030031/**032 * This is a base class for DNS to Switch mappings. <p/> It is not mandatory to033 * derive {@link DNSToSwitchMapping} implementations from it, but it is strongly034 * recommended, as it makes it easy for the Hadoop developers to add new methods035 * to this base class that are automatically picked up by all implementations.036 * <p/>037 *038 * This class does not extend the <code>Configured</code>039 * base class, and should not be changed to do so, as it causes problems040 * for subclasses. The constructor of the <code>Configured</code> calls041 * the {@link #setConf(Configuration)} method, which will call into the042 * subclasses before they have been fully constructed.043 *044 */045@InterfaceAudience.Public046@InterfaceStability.Evolving047public abstract class AbstractDNSToSwitchMapping048 implements DNSToSwitchMapping, Configurable {049050 private Configuration conf;051052 /**053 * Create an unconfigured instance054 */055 protected AbstractDNSToSwitchMapping() {056 }057058 /**059 * Create an instance, caching the configuration file.060 * This constructor does not call {@link #setConf(Configuration)}; if061 * a subclass extracts information in that method, it must call it explicitly.062 * @param conf the configuration063 */064 protected AbstractDNSToSwitchMapping(Configuration conf) {065 this.conf = conf;066 }067068 @Override069 public Configuration getConf() {070 return conf;071 }072073 @Override074 public void setConf(Configuration conf) {075 this.conf = conf;076 }077078 /**079 * Predicate that indicates that the switch mapping is known to be080 * single-switch. The base class returns false: it assumes all mappings are081 * multi-rack. Subclasses may override this with methods that are more aware082 * of their topologies.083 *084 * <p/>085 *086 * This method is used when parts of Hadoop need know whether to apply087 * single rack vs multi-rack policies, such as during block placement.088 * Such algorithms behave differently if they are on multi-switch systems.089 * </p>090 *091 * @return true if the mapping thinks that it is on a single switch092 */093 public boolean isSingleSwitch() {094 return false;095 }096097 /**098 * Get a copy of the map (for diagnostics)099 * @return a clone of the map or null for none known100 */101 public Map<String, String> getSwitchMap() {102 return null;103 }104105 /**106 * Generate a string listing the switch mapping implementation,107 * the mapping for every known node and the number of nodes and108 * unique switches known about -each entry to a separate line.109 * @return a string that can be presented to the ops team or used in110 * debug messages.111 */112 public String dumpTopology() {113 Map<String, String> rack = getSwitchMap();114 StringBuilder builder = new StringBuilder();115 builder.append("Mapping: ").append(toString()).append("\n");116 if (rack != null) {117 builder.append("Map:\n");118 Set<String> switches = new HashSet<String>();119 for (Map.Entry<String, String> entry : rack.entrySet()) {120 builder.append(" ")121 .append(entry.getKey())122 .append(" -> ")123 .append(entry.getValue())124 .append("\n");125 switches.add(entry.getValue());126 }127 builder.append("Nodes: ").append(rack.size()).append("\n");128 builder.append("Switches: ").append(switches.size()).append("\n");129 } else {130 builder.append("No topology information");131 }132 return builder.toString();133 }134135 protected boolean isSingleSwitchByScriptPolicy() {136 return conf != null137 && conf.get(CommonConfigurationKeys.NET_TOPOLOGY_SCRIPT_FILE_NAME_KEY) == null;138 }139140 /**141 * Query for a {@link DNSToSwitchMapping} instance being on a single142 * switch.143 * <p/>144 * This predicate simply assumes that all mappings not derived from145 * this class are multi-switch.146 * @param mapping the mapping to query147 * @return true if the base class says it is single switch, or the mapping148 * is not derived from this class.149 */150 public static boolean isMappingSingleSwitch(DNSToSwitchMapping mapping) {151 return mapping != null && mapping instanceof AbstractDNSToSwitchMapping152 && ((AbstractDNSToSwitchMapping) mapping).isSingleSwitch();153 }154155}