hadoop-common-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cdoug...@apache.org
Subject svn commit: r896966 - in /hadoop/common/trunk: CHANGES.txt src/java/org/apache/hadoop/conf/Configuration.java src/test/core/org/apache/hadoop/conf/TestConfiguration.java
Date Thu, 07 Jan 2010 18:55:46 GMT
Author: cdouglas
Date: Thu Jan  7 18:55:45 2010
New Revision: 896966

URL: http://svn.apache.org/viewvc?rev=896966&view=rev
Log:
HADOOP-6420. Add functionality permitting subsets of Configuration to be
interpreted as Map<String,String>. Contributed by Aaron Kimball

Modified:
    hadoop/common/trunk/CHANGES.txt
    hadoop/common/trunk/src/java/org/apache/hadoop/conf/Configuration.java
    hadoop/common/trunk/src/test/core/org/apache/hadoop/conf/TestConfiguration.java

Modified: hadoop/common/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/CHANGES.txt?rev=896966&r1=896965&r2=896966&view=diff
==============================================================================
--- hadoop/common/trunk/CHANGES.txt (original)
+++ hadoop/common/trunk/CHANGES.txt Thu Jan  7 18:55:45 2010
@@ -94,6 +94,9 @@
     HADOOP-6479. TestUTF8 assertions could fail with better text.
     (Steve Loughran via tomwhite)
 
+    HADOOP-6420. Add functionality permitting subsets of Configuration to be
+    interpreted as Map<String,String>. (Aaron Kimball via cdouglas)
+
   OPTIMIZATIONS
 
   BUG FIXES

Modified: hadoop/common/trunk/src/java/org/apache/hadoop/conf/Configuration.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/src/java/org/apache/hadoop/conf/Configuration.java?rev=896966&r1=896965&r2=896966&view=diff
==============================================================================
--- hadoop/common/trunk/src/java/org/apache/hadoop/conf/Configuration.java (original)
+++ hadoop/common/trunk/src/java/org/apache/hadoop/conf/Configuration.java Thu Jan  7 18:55:45
2010
@@ -31,6 +31,7 @@
 import java.io.Reader;
 import java.io.Writer;
 import java.net.URL;
+import java.util.AbstractMap;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -1067,7 +1068,139 @@
   public void setStrings(String name, String... values) {
     set(name, StringUtils.arrayToString(values));
   }
- 
+
+  /**
+   * Instantiates a map view over a subset of the entries in
+   * the Configuration. This is instantiated by getMap(), which
+   * binds a prefix of the namespace to the ConfigItemMap. This
+   * mapping reflects changes to the underlying Configuration.
+   *
+   * This map does not support iteration.
+   */
+  protected class ConfigItemMap extends AbstractMap<String, String>
+      implements Map<String, String> {
+
+    private final String prefix;
+
+    public ConfigItemMap(String prefix) {
+      this.prefix = prefix;
+    }
+
+    @Override
+    public boolean containsKey(Object key) {
+      return lookup(key.toString()) != null;
+    }
+
+    @Override
+    public Set<Map.Entry<String, String>> entrySet() {
+      throw new UnsupportedOperationException("unsupported");
+    }
+
+    @Override
+    public boolean equals(Object o) {
+      return o != null && o instanceof ConfigItemMap
+          && prefix.equals(((ConfigItemMap) o).prefix)
+          && Configuration.this == ((ConfigItemMap) o).getConfiguration();
+    }
+
+    private Configuration getConfiguration() {
+      return Configuration.this;
+    }
+
+    @Override
+    public String get(Object key) {
+      if (null == key) {
+        return null;
+      }
+
+      return lookup(key.toString());
+    }
+
+    @Override
+    public int hashCode() {
+      return prefix.hashCode();
+    }
+
+    @Override
+    public String put(String key, String val) {
+      if (null == key) {
+        return null;
+      }
+
+      String ret = get(key);
+      Configuration.this.set(prefix + key, val);
+      return ret;
+    }
+
+    @Override
+    public void putAll(Map<? extends String, ? extends String> m) {
+      for (Map.Entry<? extends String, ? extends String> entry : m.entrySet()) {
+        put(entry.getKey(), entry.getValue());
+      }
+    }
+
+    private String lookup(String subKey) {
+      String configKey = prefix + subKey;
+      Properties props = Configuration.this.getProps();
+      Object val = props.get(configKey);
+      String str = null;
+      if (null != val) {
+        str = substituteVars(val.toString());
+      }
+
+      return str;
+    }
+  }
+
+  /**
+   * Given a string -&gt; string map as a value, embed this in the
+   * Configuration by prepending 'name' to all the keys in the valueMap,
+   * and storing it inside the current Configuration.
+   *
+   * e.g., setMap("foo", { "bar" -&gt; "a", "baz" -&gt; "b" }) would
+   * insert "foo.bar" -&gt; "a" and "foo.baz" -&gt; "b" in this
+   * Configuration.
+   *
+   * @param name the prefix to attach to all keys in the valueMap. This
+   * should not have a trailing "." character.
+   * @param valueMap the map to embed in the Configuration.
+   */
+  public void setMap(String name, Map<String, String> valueMap) {
+    // Store all elements of the map proper.
+    for (Map.Entry<String, String> entry : valueMap.entrySet()) {
+      set(name + "." + entry.getKey(), entry.getValue());
+    }
+  }
+
+  /**
+   * Returns a map containing a view of all configuration properties
+   * whose names begin with "name.*", with the "name." prefix  removed.
+   * e.g., if "foo.bar" -&gt; "a" and "foo.baz" -&gt; "b" are in the
+   * Configuration, getMap("foo") would return { "bar" -&gt; "a",
+   * "baz" -&gt; "b" }.
+   *
+   * Map name deprecation is handled via "prefix deprecation"; the individual
+   * keys created in a configuration by inserting a map do not need to be
+   * individually deprecated -- it is sufficient to deprecate the 'name'
+   * associated with the map and bind that to a new name. e.g., if "foo"
+   * is deprecated for "newfoo," and the configuration contains entries for
+   * "newfoo.a" and "newfoo.b", getMap("foo") will return a map containing
+   * the keys "a" and "b".
+   *
+   * The returned map does not support iteration; it is a lazy view over
+   * the slice of the configuration whose keys begin with 'name'. Updates
+   * to the underlying configuration are reflected in the returned map,
+   * and updates to the map will modify the underlying configuration.
+   *
+   * @param name The prefix of the key names to extract into the output map.
+   * @return a String-&gt;String map that contains all (k, v) pairs
+   * where 'k' begins with 'name.'; the 'name.' prefix is removed in the output.
+   */
+  public Map<String, String> getMap(String name) {
+    String prefix = handleDeprecation(name) + ".";
+    return new ConfigItemMap(prefix);
+  }
+
   /**
    * Load a class by name.
    * 

Modified: hadoop/common/trunk/src/test/core/org/apache/hadoop/conf/TestConfiguration.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/src/test/core/org/apache/hadoop/conf/TestConfiguration.java?rev=896966&r1=896965&r2=896966&view=diff
==============================================================================
--- hadoop/common/trunk/src/test/core/org/apache/hadoop/conf/TestConfiguration.java (original)
+++ hadoop/common/trunk/src/test/core/org/apache/hadoop/conf/TestConfiguration.java Thu Jan
 7 18:55:45 2010
@@ -24,6 +24,7 @@
 import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.Map;
 import java.util.Random;
 import java.util.regex.Pattern;
 
@@ -365,6 +366,49 @@
     assertTrue(fail);
   }
 
+  public void testMap() throws IOException {
+    Configuration conf = new Configuration();
+
+    // manually create a map in the config; extract
+    // its values as a map object.
+    conf.set("foo.bar", "A");
+    conf.set("foo.baz", "B");
+    assertEquals("A", conf.get("foo.bar"));
+    assertEquals("B", conf.get("foo.baz"));
+
+    Map<String, String> out = conf.getMap("foo");
+    assertEquals("A", out.get("bar"));
+    assertEquals("B", out.get("baz"));
+
+    Map<String, String> in = new HashMap<String, String>();
+    in.put("yak", "123");
+    in.put("bop", "456");
+    conf.setMap("quux", in);
+
+    // Assert that we can extract individual entries in
+    // the nested map ok.
+    assertEquals("123", conf.get("quux.yak"));
+
+    // Assert that we can get the whole map back out again.
+    out = conf.getMap("quux");
+    assertEquals("123", out.get("yak"));
+    assertEquals("456", out.get("bop"));
+
+    // Test that substitution is handled by getMap().
+    conf.set("subparam", "foo");
+    conf.set("mymap.someprop", "AAA${subparam}BBB");
+    out = conf.getMap("mymap");
+    assertEquals("AAAfooBBB", out.get("someprop"));
+
+    // Test deprecation of maps.
+    Configuration.addDeprecation("oldfoo", new String[]{"newfoo"});
+    conf.set("newfoo.a", "A");
+    conf.set("newfoo.b", "B");
+    out = conf.getMap("oldfoo");
+    assertEquals("A", out.get("a"));
+    assertEquals("B", out.get("b"));
+  }
+
   public void testPattern() throws IOException {
     out = new BufferedWriter(new FileWriter(CONFIG));
     startConfig();



Mime
View raw message