diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/net/AbstractDNSToSwitchMapping.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/net/AbstractDNSToSwitchMapping.java new file mode 100644 index 0000000000..a1b185dd08 --- /dev/null +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/net/AbstractDNSToSwitchMapping.java @@ -0,0 +1,107 @@ +/** + * 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.net; + +import org.apache.hadoop.classification.InterfaceAudience; +import org.apache.hadoop.classification.InterfaceStability; +import org.apache.hadoop.conf.Configurable; +import org.apache.hadoop.conf.Configuration; + +/** + * This is a base class for DNS to Switch mappings.

It is not mandatory to + * derive {@link DNSToSwitchMapping} implementations from it, but it is strongly + * recommended, as it makes it easy for the Hadoop developers to add new methods + * to this base class that are automatically picked up by all implementations. + *

+ * + * This class does not extend the Configured + * base class, and should not be changed to do so, as it causes problems + * for subclasses. The constructor of the Configured calls + * the {@link #setConf(Configuration)} method, which will call into the + * subclasses before they have been fully constructed. + * + */ +@InterfaceAudience.Public +@InterfaceStability.Evolving +public abstract class AbstractDNSToSwitchMapping + implements DNSToSwitchMapping, Configurable { + + private Configuration conf; + + /** + * Create an unconfigured instance + */ + protected AbstractDNSToSwitchMapping() { + } + + /** + * Create an instance, caching the configuration file. + * This constructor does not call {@link #setConf(Configuration)}; if + * a subclass extracts information in that method, it must call it explicitly. + * @param conf the configuration + */ + protected AbstractDNSToSwitchMapping(Configuration conf) { + this.conf = conf; + } + + @Override + public Configuration getConf() { + return conf; + } + + @Override + public void setConf(Configuration conf) { + this.conf = conf; + } + + /** + * Predicate that indicates that the switch mapping is known to be + * single-switch. The base class returns false: it assumes all mappings are + * multi-rack. Subclasses may override this with methods that are more aware + * of their topologies. + * + *

+ * + * This method is used when parts of Hadoop need know whether to apply + * single rack vs multi-rack policies, such as during block placement. + * Such algorithms behave differently if they are on multi-switch systems. + *

+ * + * @return true if the mapping thinks that it is on a single switch + */ + public boolean isSingleSwitch() { + return false; + } + + /** + * Query for a {@link DNSToSwitchMapping} instance being on a single + * switch. + *

+ * This predicate simply assumes that all mappings not derived from + * this class are multi-switch. + * @param mapping the mapping to query + * @return true if the base class says it is single switch, or the mapping + * is not derived from this class. + */ + public static boolean isMappingSingleSwitch(DNSToSwitchMapping mapping) { + return mapping instanceof AbstractDNSToSwitchMapping + && ((AbstractDNSToSwitchMapping) mapping).isSingleSwitch(); + } + +} diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/net/CachedDNSToSwitchMapping.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/net/CachedDNSToSwitchMapping.java index f29e53cfbf..bdfc95cb0e 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/net/CachedDNSToSwitchMapping.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/net/CachedDNSToSwitchMapping.java @@ -34,9 +34,13 @@ */ @InterfaceAudience.Public @InterfaceStability.Evolving -public class CachedDNSToSwitchMapping implements DNSToSwitchMapping { +public class CachedDNSToSwitchMapping extends AbstractDNSToSwitchMapping { private Map cache = new ConcurrentHashMap(); - protected DNSToSwitchMapping rawMapping; + + /** + * The uncached mapping + */ + protected final DNSToSwitchMapping rawMapping; /** * cache a raw DNS mapping @@ -118,4 +122,14 @@ public List resolve(List names) { return getCachedHosts(names); } + + /** + * Delegate the switch topology query to the raw mapping, via + * {@link AbstractDNSToSwitchMapping#isMappingSingleSwitch(DNSToSwitchMapping)} + * @return true iff the raw mapper is considered single-switch. + */ + @Override + public boolean isSingleSwitch() { + return isMappingSingleSwitch(rawMapping); + } } diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/net/DNSToSwitchMapping.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/net/DNSToSwitchMapping.java index 2a832f25f8..8521a9a92b 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/net/DNSToSwitchMapping.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/net/DNSToSwitchMapping.java @@ -40,6 +40,12 @@ public interface DNSToSwitchMapping { * Note the hostname/ip-address is not part of the returned path. * The network topology of the cluster would determine the number of * components in the network path. + *

+ * + * If a name cannot be resolved to a rack, the implementation + * should return {@link NetworkTopology#DEFAULT_RACK}. This + * is what the bundled implementations do, though it is not a formal requirement + * * @param names the list of hosts to resolve (can be empty) * @return list of resolved network paths. * If names is empty, the returned list is also empty diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/net/ScriptBasedMapping.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/net/ScriptBasedMapping.java index bf24a04bee..4e2dcf6d4c 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/net/ScriptBasedMapping.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/net/ScriptBasedMapping.java @@ -32,16 +32,21 @@ /** * This class implements the {@link DNSToSwitchMapping} interface using a - * script configured via the {@link CommonConfigurationKeys#NET_TOPOLOGY_SCRIPT_FILE_NAME_KEY} + * script configured via the + * {@link CommonConfigurationKeys#NET_TOPOLOGY_SCRIPT_FILE_NAME_KEY} option. + *

+ * It contains a static class RawScriptBasedMapping that performs + * the work: reading the configuration parameters, executing any defined + * script, handling errors and such like. The outer + * class extends {@link CachedDNSToSwitchMapping} to cache the delegated + * queries. + *

+ * This DNS mapper's {@link #isSingleSwitch()} predicate returns + * true if and only if a script is defined. */ @InterfaceAudience.Public @InterfaceStability.Evolving -public final class ScriptBasedMapping extends CachedDNSToSwitchMapping -implements Configurable -{ - public ScriptBasedMapping() { - super(new RawScriptBasedMapping()); - } +public final class ScriptBasedMapping extends CachedDNSToSwitchMapping { /** * Minimum number of arguments: {@value} @@ -65,6 +70,18 @@ public ScriptBasedMapping() { static final String SCRIPT_ARG_COUNT_KEY = CommonConfigurationKeys.NET_TOPOLOGY_SCRIPT_NUMBER_ARGS_KEY ; + /** + * Create an instance with the default configuration. + *

+ * Calling {@link #setConf(Configuration)} will trigger a + * re-evaluation of the configuration settings and so be used to + * set up the mapping script. + * + */ + public ScriptBasedMapping() { + super(new RawScriptBasedMapping()); + } + /** * Create an instance from the given configuration * @param conf configuration @@ -74,14 +91,31 @@ public ScriptBasedMapping(Configuration conf) { setConf(conf); } - @Override - public Configuration getConf() { - return ((RawScriptBasedMapping)rawMapping).getConf(); + /** + * Get the cached mapping and convert it to its real type + * @return the inner raw script mapping. + */ + private RawScriptBasedMapping getRawMapping() { + return (RawScriptBasedMapping)rawMapping; } + @Override + public Configuration getConf() { + return getRawMapping().getConf(); + } + + /** + * {@inheritDoc} + *

+ * This will get called in the superclass constructor, so a check is needed + * to ensure that the raw mapping is defined before trying to relaying a null + * configuration. + * @param conf + */ @Override public void setConf(Configuration conf) { - ((RawScriptBasedMapping)rawMapping).setConf(conf); + super.setConf(conf); + getRawMapping().setConf(conf); } /** @@ -89,29 +123,26 @@ public void setConf(Configuration conf) { * by the superclass {@link CachedDNSToSwitchMapping} */ private static final class RawScriptBasedMapping - implements DNSToSwitchMapping { + extends AbstractDNSToSwitchMapping { private String scriptName; - private Configuration conf; private int maxArgs; //max hostnames per call of the script - private static Log LOG = + private static final Log LOG = LogFactory.getLog(ScriptBasedMapping.class); /** - * Set the configuration and - * @param conf extract the configuration parameters of interest + * Set the configuration and extract the configuration parameters of interest + * @param conf the new configuration */ + @Override public void setConf (Configuration conf) { - this.scriptName = conf.get(SCRIPT_FILENAME_KEY); - this.maxArgs = conf.getInt(SCRIPT_ARG_COUNT_KEY, DEFAULT_ARG_COUNT); - this.conf = conf; - } - - /** - * Get the configuration - * @return the configuration - */ - public Configuration getConf () { - return conf; + super.setConf(conf); + if (conf != null) { + scriptName = conf.get(SCRIPT_FILENAME_KEY); + maxArgs = conf.getInt(SCRIPT_ARG_COUNT_KEY, DEFAULT_ARG_COUNT); + } else { + scriptName = null; + maxArgs = 0; + } } /** @@ -122,42 +153,42 @@ public RawScriptBasedMapping() {} @Override public List resolve(List names) { - List m = new ArrayList(names.size()); - - if (names.isEmpty()) { - return m; - } + List m = new ArrayList(names.size()); - if (scriptName == null) { - for (int i = 0; i < names.size(); i++) { - m.add(NetworkTopology.DEFAULT_RACK); + if (names.isEmpty()) { + return m; } - return m; - } - - String output = runResolveCommand(names); - if (output != null) { - StringTokenizer allSwitchInfo = new StringTokenizer(output); - while (allSwitchInfo.hasMoreTokens()) { - String switchInfo = allSwitchInfo.nextToken(); - m.add(switchInfo); + + if (scriptName == null) { + for (String name : names) { + m.add(NetworkTopology.DEFAULT_RACK); + } + return m; } - - if (m.size() != names.size()) { - // invalid number of entries returned by the script - LOG.error("Script " + scriptName + " returned " - + Integer.toString(m.size()) + " values when " - + Integer.toString(names.size()) + " were expected."); + + String output = runResolveCommand(names); + if (output != null) { + StringTokenizer allSwitchInfo = new StringTokenizer(output); + while (allSwitchInfo.hasMoreTokens()) { + String switchInfo = allSwitchInfo.nextToken(); + m.add(switchInfo); + } + + if (m.size() != names.size()) { + // invalid number of entries returned by the script + LOG.error("Script " + scriptName + " returned " + + Integer.toString(m.size()) + " values when " + + Integer.toString(names.size()) + " were expected."); + return null; + } + } else { + // an error occurred. return null to signify this. + // (exn was already logged in runResolveCommand) return null; } - } else { - // an error occurred. return null to signify this. - // (exn was already logged in runResolveCommand) - return null; + + return m; } - - return m; - } /** * Build and execute the resolution command. The command is @@ -195,10 +226,10 @@ private String runResolveCommand(List args) { dir = new File(userDir); } ShellCommandExecutor s = new ShellCommandExecutor( - cmdList.toArray(new String[0]), dir); + cmdList.toArray(new String[cmdList.size()]), dir); try { s.execute(); - allOutput.append(s.getOutput() + " "); + allOutput.append(s.getOutput()).append(" "); } catch (Exception e) { LOG.warn("Exception: ", e); return null; @@ -207,5 +238,15 @@ private String runResolveCommand(List args) { } return allOutput.toString(); } + + /** + * Declare that the mapper is single-switched if a script was not named + * in the configuration. + * @return true iff there is no script + */ + @Override + public boolean isSingleSwitch() { + return scriptName == null; + } } } diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/net/StaticMapping.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/net/StaticMapping.java index c3923ed951..3be8a95862 100644 --- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/net/StaticMapping.java +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/net/StaticMapping.java @@ -17,34 +17,80 @@ */ package org.apache.hadoop.net; -import java.util.*; - import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.conf.Configured; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * Implements the {@link DNSToSwitchMapping} via static mappings. Used - * in testcases that simulate racks. + * in testcases that simulate racks, and in the + * {@link org.apache.hadoop.hdfs.MiniDFSCluster} * + * A shared, static mapping is used; to reset it call {@link #resetMap()}. + * + * When an instance of the class has its {@link #setConf(Configuration)} + * method called, nodes listed in the configuration will be added to the map. + * These do not get removed when the instance is garbage collected. */ -public class StaticMapping extends Configured implements DNSToSwitchMapping { - public void setconf(Configuration conf) { - String[] mappings = conf.getStrings("hadoop.configured.node.mapping"); - if (mappings != null) { - for (int i = 0; i < mappings.length; i++) { - String str = mappings[i]; - String host = str.substring(0, str.indexOf('=')); - String rack = str.substring(str.indexOf('=') + 1); - addNodeToRack(host, rack); +public class StaticMapping extends AbstractDNSToSwitchMapping { + + /** + * key to define the node mapping as a comma-delimited list of host=rack + * mappings, e.g. host1=r1,host2=r1,host3=r2. + *

+ * Important: spaces not trimmed and are considered significant. + */ + public static final String KEY_HADOOP_CONFIGURED_NODE_MAPPING = + "hadoop.configured.node.mapping"; + + /** + * Configure the mapping by extracting any mappings defined in the + * {@link #KEY_HADOOP_CONFIGURED_NODE_MAPPING} field + * @param conf new configuration + */ + @Override + public void setConf(Configuration conf) { + super.setConf(conf); + if (conf != null) { + String[] mappings = conf.getStrings(KEY_HADOOP_CONFIGURED_NODE_MAPPING); + if (mappings != null) { + for (String str : mappings) { + String host = str.substring(0, str.indexOf('=')); + String rack = str.substring(str.indexOf('=') + 1); + addNodeToRack(host, rack); + } } } } - /* Only one instance per JVM */ - private static Map nameToRackMap = new HashMap(); - - static synchronized public void addNodeToRack(String name, String rackId) { - nameToRackMap.put(name, rackId); + + /** + * retained lower case setter for compatibility reasons; relays to + * {@link #setConf(Configuration)} + * @param conf new configuration + */ + public void setconf(Configuration conf) { + setConf(conf); } + + /* Only one instance per JVM */ + private static final Map nameToRackMap = new HashMap(); + + /** + * Add a node to the static map. The moment any entry is added to the map, + * the map goes multi-rack. + * @param name node name + * @param rackId rack ID + */ + public static void addNodeToRack(String name, String rackId) { + synchronized (nameToRackMap) { + nameToRackMap.put(name, rackId); + } + } + + @Override public List resolve(List names) { List m = new ArrayList(); synchronized (nameToRackMap) { @@ -59,4 +105,24 @@ public List resolve(List names) { return m; } } + + /** + * This mapping is only single switch if the map is empty + * @return the current switching status + */ + @Override + public boolean isSingleSwitch() { + synchronized (nameToRackMap) { + return nameToRackMap.isEmpty(); + } + } + + /** + * Clear the map and revert to being a single switch + */ + public static void resetMap() { + synchronized (nameToRackMap) { + nameToRackMap.clear(); + } + } } diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/net/TestScriptBasedMapping.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/net/TestScriptBasedMapping.java index fc4a781cb5..e201787479 100644 --- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/net/TestScriptBasedMapping.java +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/net/TestScriptBasedMapping.java @@ -23,30 +23,59 @@ import org.apache.hadoop.conf.Configuration; import junit.framework.TestCase; +import org.junit.Test; public class TestScriptBasedMapping extends TestCase { - private ScriptBasedMapping mapping; - private Configuration conf; - private List names; + public TestScriptBasedMapping() { - mapping = new ScriptBasedMapping(); - conf = new Configuration(); - conf.setInt(ScriptBasedMapping.SCRIPT_ARG_COUNT_KEY, - ScriptBasedMapping.MIN_ALLOWABLE_ARGS - 1); - conf.set(ScriptBasedMapping.SCRIPT_FILENAME_KEY, "any-filename"); - - mapping.setConf(conf); } + @Test public void testNoArgsMeansNoResult() { - names = new ArrayList(); + Configuration conf = new Configuration(); + conf.setInt(ScriptBasedMapping.SCRIPT_ARG_COUNT_KEY, + ScriptBasedMapping.MIN_ALLOWABLE_ARGS - 1); + conf.set(ScriptBasedMapping.SCRIPT_FILENAME_KEY, "any-filename"); + conf.set(ScriptBasedMapping.SCRIPT_FILENAME_KEY, "any-filename"); + ScriptBasedMapping mapping = createMapping(conf); + List names = new ArrayList(); names.add("some.machine.name"); names.add("other.machine.name"); List result = mapping.resolve(names); - assertNull(result); + assertNull("Expected an empty list", result); } + @Test + public void testNoFilenameMeansSingleSwitch() throws Throwable { + Configuration conf = new Configuration(); + ScriptBasedMapping mapping = createMapping(conf); + assertTrue("Expected to be single switch", mapping.isSingleSwitch()); + assertTrue("Expected to be single switch", + AbstractDNSToSwitchMapping.isMappingSingleSwitch(mapping)); + } + + @Test + public void testFilenameMeansMultiSwitch() throws Throwable { + Configuration conf = new Configuration(); + conf.set(ScriptBasedMapping.SCRIPT_FILENAME_KEY, "any-filename"); + ScriptBasedMapping mapping = createMapping(conf); + assertFalse("Expected to be multi switch", mapping.isSingleSwitch()); + mapping.setConf(new Configuration()); + assertTrue("Expected to be single switch", mapping.isSingleSwitch()); + } + + @Test + public void testNullConfig() throws Throwable { + ScriptBasedMapping mapping = createMapping(null); + assertTrue("Expected to be single switch", mapping.isSingleSwitch()); + + } + private ScriptBasedMapping createMapping(Configuration conf) { + ScriptBasedMapping mapping = new ScriptBasedMapping(); + mapping.setConf(conf); + return mapping; + } } diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/net/TestStaticMapping.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/net/TestStaticMapping.java new file mode 100644 index 0000000000..17753222fc --- /dev/null +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/net/TestStaticMapping.java @@ -0,0 +1,103 @@ +/** + * 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.net; + +import org.apache.hadoop.conf.Configuration; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +/** + * Test the static mapping class. + * Because the map is actually static, this map needs to be reset for every test + */ +public class TestStaticMapping extends Assert { + + /** + * Reset the map then create a new instance of the {@link StaticMapping} + * class + * @return a new instance + */ + private StaticMapping newInstance() { + StaticMapping.resetMap(); + return new StaticMapping(); + } + + @Test + public void testStaticIsSingleSwitch() throws Throwable { + StaticMapping mapping = newInstance(); + assertTrue("Empty maps are not single switch", mapping.isSingleSwitch()); + } + + + @Test + public void testCachingRelaysQueries() throws Throwable { + StaticMapping staticMapping = newInstance(); + CachedDNSToSwitchMapping mapping = + new CachedDNSToSwitchMapping(staticMapping); + assertTrue("Expected single switch", mapping.isSingleSwitch()); + StaticMapping.addNodeToRack("n1", "r1"); + assertFalse("Expected to be multi switch", + mapping.isSingleSwitch()); + } + + @Test + public void testAddResolveNodes() throws Throwable { + StaticMapping mapping = newInstance(); + StaticMapping.addNodeToRack("n1", "r1"); + List l1 = new ArrayList(2); + l1.add("n1"); + l1.add("unknown"); + List mappings = mapping.resolve(l1); + assertEquals(2, mappings.size()); + assertEquals("r1", mappings.get(0)); + assertEquals(NetworkTopology.DEFAULT_RACK, mappings.get(1)); + assertFalse("Mapping is still single switch", mapping.isSingleSwitch()); + } + + @Test + public void testReadNodesFromConfig() throws Throwable { + StaticMapping mapping = newInstance(); + Configuration conf = new Configuration(); + conf.set(StaticMapping.KEY_HADOOP_CONFIGURED_NODE_MAPPING, "n1=r1,n2=r2"); + mapping.setConf(conf); + List l1 = new ArrayList(3); + l1.add("n1"); + l1.add("unknown"); + l1.add("n2"); + List mappings = mapping.resolve(l1); + assertEquals(3, mappings.size()); + assertEquals("r1", mappings.get(0)); + assertEquals(NetworkTopology.DEFAULT_RACK, mappings.get(1)); + assertEquals("r2", mappings.get(2)); + assertFalse("Expected to be multi switch", + AbstractDNSToSwitchMapping.isMappingSingleSwitch(mapping)); + } + + @Test + public void testNullConfiguration() throws Throwable { + StaticMapping mapping = newInstance(); + mapping.setConf(null); + assertTrue("Null maps is not single switch", mapping.isSingleSwitch()); + assertTrue("Expected to be single switch", + AbstractDNSToSwitchMapping.isMappingSingleSwitch(mapping)); + } +} diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/net/TestSwitchMapping.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/net/TestSwitchMapping.java new file mode 100644 index 0000000000..e66a5c0165 --- /dev/null +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/net/TestSwitchMapping.java @@ -0,0 +1,53 @@ +/** + * 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.net; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +/** + * Test some other details of the switch mapping + */ +public class TestSwitchMapping extends Assert { + + @Test + public void testStandaloneClassesAssumedMultiswitch() throws Throwable { + DNSToSwitchMapping mapping = new StandaloneSwitchMapping(); + assertFalse("Expected to be multi switch", + AbstractDNSToSwitchMapping.isMappingSingleSwitch(mapping)); + } + + + @Test + public void testCachingRelays() throws Throwable { + CachedDNSToSwitchMapping mapping = + new CachedDNSToSwitchMapping(new StandaloneSwitchMapping()); + assertFalse("Expected to be multi switch", + mapping.isSingleSwitch()); + } + + private static class StandaloneSwitchMapping implements DNSToSwitchMapping { + @Override + public List resolve(List names) { + return names; + } + } +}