|
@@ -18,22 +18,27 @@
|
|
|
|
|
|
package org.apache.hadoop.net;
|
|
|
|
|
|
+import org.apache.commons.logging.Log;
|
|
|
+import org.apache.commons.logging.LogFactory;
|
|
|
import org.apache.hadoop.conf.Configuration;
|
|
|
+import org.apache.hadoop.fs.CommonConfigurationKeys;
|
|
|
import org.junit.Assert;
|
|
|
import org.junit.Test;
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
|
|
|
/**
|
|
|
* 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 {
|
|
|
+ private static final Log LOG = LogFactory.getLog(TestStaticMapping.class);
|
|
|
|
|
|
/**
|
|
|
* Reset the map then create a new instance of the {@link StaticMapping}
|
|
|
- * class
|
|
|
+ * class with a null configuration
|
|
|
* @return a new instance
|
|
|
*/
|
|
|
private StaticMapping newInstance() {
|
|
@@ -41,63 +46,195 @@ public class TestStaticMapping extends Assert {
|
|
|
return new StaticMapping();
|
|
|
}
|
|
|
|
|
|
- @Test
|
|
|
- public void testStaticIsSingleSwitch() throws Throwable {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Reset the map then create a new instance of the {@link StaticMapping}
|
|
|
+ * class with the topology script in the configuration set to
|
|
|
+ * the parameter
|
|
|
+ * @param script a (never executed) script, can be null
|
|
|
+ * @return a new instance
|
|
|
+ */
|
|
|
+ private StaticMapping newInstance(String script) {
|
|
|
StaticMapping mapping = newInstance();
|
|
|
- assertFalse("Empty maps should not be not single switch",
|
|
|
- mapping.isSingleSwitch());
|
|
|
+ mapping.setConf(createConf(script));
|
|
|
+ return mapping;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Create a configuration with a specific topology script
|
|
|
+ * @param script a (never executed) script, can be null
|
|
|
+ * @return a configuration
|
|
|
+ */
|
|
|
+ private Configuration createConf(String script) {
|
|
|
+ Configuration conf = new Configuration();
|
|
|
+ if (script != null) {
|
|
|
+ conf.set(CommonConfigurationKeys.NET_TOPOLOGY_SCRIPT_FILE_NAME_KEY,
|
|
|
+ script);
|
|
|
+ } else {
|
|
|
+ conf.unset(CommonConfigurationKeys.NET_TOPOLOGY_SCRIPT_FILE_NAME_KEY);
|
|
|
+ }
|
|
|
+ return conf;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void assertSingleSwitch(DNSToSwitchMapping mapping) {
|
|
|
+ assertEquals("Expected a single switch mapping "
|
|
|
+ + mapping,
|
|
|
+ true,
|
|
|
+ AbstractDNSToSwitchMapping.isMappingSingleSwitch(mapping));
|
|
|
+ }
|
|
|
+
|
|
|
+ private void assertMultiSwitch(DNSToSwitchMapping mapping) {
|
|
|
+ assertEquals("Expected a multi switch mapping "
|
|
|
+ + mapping,
|
|
|
+ false,
|
|
|
+ AbstractDNSToSwitchMapping.isMappingSingleSwitch(mapping));
|
|
|
+ }
|
|
|
+
|
|
|
+ protected void assertMapSize(AbstractDNSToSwitchMapping switchMapping, int expectedSize) {
|
|
|
+ assertEquals(
|
|
|
+ "Expected two entries in the map " + switchMapping.dumpTopology(),
|
|
|
+ expectedSize, switchMapping.getSwitchMap().size());
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<String> createQueryList() {
|
|
|
+ List<String> l1 = new ArrayList<String>(2);
|
|
|
+ l1.add("n1");
|
|
|
+ l1.add("unknown");
|
|
|
+ return l1;
|
|
|
+ }
|
|
|
|
|
|
@Test
|
|
|
- public void testCachingRelaysQueries() throws Throwable {
|
|
|
- StaticMapping staticMapping = newInstance();
|
|
|
- CachedDNSToSwitchMapping mapping =
|
|
|
- new CachedDNSToSwitchMapping(staticMapping);
|
|
|
- StaticMapping.addNodeToRack("n1", "r1");
|
|
|
- assertFalse("Expected multi switch", mapping.isSingleSwitch());
|
|
|
+ public void testStaticIsSingleSwitchOnNullScript() throws Throwable {
|
|
|
+ StaticMapping mapping = newInstance(null);
|
|
|
+ mapping.setConf(createConf(null));
|
|
|
+ assertSingleSwitch(mapping);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testStaticIsMultiSwitchOnScript() throws Throwable {
|
|
|
+ StaticMapping mapping = newInstance("ls");
|
|
|
+ assertMultiSwitch(mapping);
|
|
|
}
|
|
|
|
|
|
@Test
|
|
|
public void testAddResolveNodes() throws Throwable {
|
|
|
StaticMapping mapping = newInstance();
|
|
|
- StaticMapping.addNodeToRack("n1", "r1");
|
|
|
- List<String> l1 = new ArrayList<String>(2);
|
|
|
- l1.add("n1");
|
|
|
- l1.add("unknown");
|
|
|
- List<String> 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());
|
|
|
+ StaticMapping.addNodeToRack("n1", "/r1");
|
|
|
+ List<String> queryList = createQueryList();
|
|
|
+ List<String> resolved = mapping.resolve(queryList);
|
|
|
+ assertEquals(2, resolved.size());
|
|
|
+ assertEquals("/r1", resolved.get(0));
|
|
|
+ assertEquals(NetworkTopology.DEFAULT_RACK, resolved.get(1));
|
|
|
+ // get the switch map and examine it
|
|
|
+ Map<String, String> switchMap = mapping.getSwitchMap();
|
|
|
+ String topology = mapping.dumpTopology();
|
|
|
+ LOG.info(topology);
|
|
|
+ assertEquals(topology, 1, switchMap.size());
|
|
|
+ assertEquals(topology, "/r1", switchMap.get("n1"));
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Verify that a configuration string builds a topology
|
|
|
+ */
|
|
|
@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");
|
|
|
+ conf.set(StaticMapping.KEY_HADOOP_CONFIGURED_NODE_MAPPING, "n1=/r1,n2=/r2");
|
|
|
mapping.setConf(conf);
|
|
|
+ //even though we have inserted elements into the list, because
|
|
|
+ //it is driven by the script key in the configuration, it still
|
|
|
+ //thinks that it is single rack
|
|
|
+ assertSingleSwitch(mapping);
|
|
|
List<String> l1 = new ArrayList<String>(3);
|
|
|
l1.add("n1");
|
|
|
l1.add("unknown");
|
|
|
l1.add("n2");
|
|
|
- List<String> 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));
|
|
|
+ List<String> resolved = mapping.resolve(l1);
|
|
|
+ assertEquals(3, resolved.size());
|
|
|
+ assertEquals("/r1", resolved.get(0));
|
|
|
+ assertEquals(NetworkTopology.DEFAULT_RACK, resolved.get(1));
|
|
|
+ assertEquals("/r2", resolved.get(2));
|
|
|
+
|
|
|
+ Map<String, String> switchMap = mapping.getSwitchMap();
|
|
|
+ String topology = mapping.dumpTopology();
|
|
|
+ LOG.info(topology);
|
|
|
+ assertEquals(topology, 2, switchMap.size());
|
|
|
+ assertEquals(topology, "/r1", switchMap.get("n1"));
|
|
|
+ assertNull(topology, switchMap.get("unknown"));
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Verify that if the inner mapping is single-switch, so is the cached one
|
|
|
+ * @throws Throwable on any problem
|
|
|
+ */
|
|
|
@Test
|
|
|
- public void testNullConfiguration() throws Throwable {
|
|
|
+ public void testCachingRelaysSingleSwitchQueries() throws Throwable {
|
|
|
+ //create a single switch map
|
|
|
+ StaticMapping staticMapping = newInstance(null);
|
|
|
+ assertSingleSwitch(staticMapping);
|
|
|
+ CachedDNSToSwitchMapping cachedMap =
|
|
|
+ new CachedDNSToSwitchMapping(staticMapping);
|
|
|
+ LOG.info("Mapping: " + cachedMap + "\n" + cachedMap.dumpTopology());
|
|
|
+ assertSingleSwitch(cachedMap);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Verify that if the inner mapping is multi-switch, so is the cached one
|
|
|
+ * @throws Throwable on any problem
|
|
|
+ */
|
|
|
+ @Test
|
|
|
+ public void testCachingRelaysMultiSwitchQueries() throws Throwable {
|
|
|
+ StaticMapping staticMapping = newInstance("top");
|
|
|
+ assertMultiSwitch(staticMapping);
|
|
|
+ CachedDNSToSwitchMapping cachedMap =
|
|
|
+ new CachedDNSToSwitchMapping(staticMapping);
|
|
|
+ LOG.info("Mapping: " + cachedMap + "\n" + cachedMap.dumpTopology());
|
|
|
+ assertMultiSwitch(cachedMap);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * This test verifies that resultion queries get relayed to the inner rack
|
|
|
+ * @throws Throwable on any problem
|
|
|
+ */
|
|
|
+ @Test
|
|
|
+ public void testCachingRelaysResolveQueries() throws Throwable {
|
|
|
StaticMapping mapping = newInstance();
|
|
|
- mapping.setConf(null);
|
|
|
- assertFalse("Null maps are expected to be multi switch",
|
|
|
- mapping.isSingleSwitch());
|
|
|
- assertFalse("Expected to be multi switch",
|
|
|
- AbstractDNSToSwitchMapping.isMappingSingleSwitch(mapping));
|
|
|
+ mapping.setConf(createConf("top"));
|
|
|
+ StaticMapping staticMapping = mapping;
|
|
|
+ CachedDNSToSwitchMapping cachedMap =
|
|
|
+ new CachedDNSToSwitchMapping(staticMapping);
|
|
|
+ assertMapSize(cachedMap, 0);
|
|
|
+ //add a node to the static map
|
|
|
+ StaticMapping.addNodeToRack("n1", "/r1");
|
|
|
+ //verify it is there
|
|
|
+ assertMapSize(staticMapping, 1);
|
|
|
+ //verify that the cache hasn't picked it up yet
|
|
|
+ assertMapSize(cachedMap, 0);
|
|
|
+ //now relay the query
|
|
|
+ cachedMap.resolve(createQueryList());
|
|
|
+ //and verify the cache is no longer empty
|
|
|
+ assertMapSize(cachedMap, 2);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * This test verifies that resultion queries get relayed to the inner rack
|
|
|
+ * @throws Throwable on any problem
|
|
|
+ */
|
|
|
+ @Test
|
|
|
+ public void testCachingCachesNegativeEntries() throws Throwable {
|
|
|
+ StaticMapping staticMapping = newInstance();
|
|
|
+ CachedDNSToSwitchMapping cachedMap =
|
|
|
+ new CachedDNSToSwitchMapping(staticMapping);
|
|
|
+ assertMapSize(cachedMap, 0);
|
|
|
+ assertMapSize(staticMapping, 0);
|
|
|
+ List<String> resolved = cachedMap.resolve(createQueryList());
|
|
|
+ //and verify the cache is no longer empty while the static map is
|
|
|
+ assertMapSize(staticMapping, 0);
|
|
|
+ assertMapSize(cachedMap, 2);
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
}
|