HADOOP-8172. Configuration no longer sets all keys in a deprecated key list. (Anupam Seth via bobby)

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1332821 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Robert Joseph Evans 2012-05-01 21:00:52 +00:00
parent 934f466bab
commit 7d1b804d3a
4 changed files with 164 additions and 34 deletions

View File

@ -447,6 +447,9 @@ Release 2.0.0 - UNRELEASED
HADOOP-8317. Update maven-assembly-plugin to 2.3 - fix build on FreeBSD HADOOP-8317. Update maven-assembly-plugin to 2.3 - fix build on FreeBSD
(Radim Kolar via bobby) (Radim Kolar via bobby)
HADOOP-8172. Configuration no longer sets all keys in a deprecated key
list. (Anupam Seth via bobby)
Release 0.23.3 - UNRELEASED Release 0.23.3 - UNRELEASED
INCOMPATIBLE CHANGES INCOMPATIBLE CHANGES

View File

@ -33,6 +33,7 @@
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Enumeration; import java.util.Enumeration;
@ -269,10 +270,18 @@ private final String getWarningMessage(String key) {
* This is to be used only by the developers in order to add deprecation of * This is to be used only by the developers in order to add deprecation of
* keys, and attempts to call this method after loading resources once, * keys, and attempts to call this method after loading resources once,
* would lead to <tt>UnsupportedOperationException</tt> * would lead to <tt>UnsupportedOperationException</tt>
*
* If a key is deprecated in favor of multiple keys, they are all treated as
* aliases of each other, and setting any one of them resets all the others
* to the new value.
*
* @param key * @param key
* @param newKeys * @param newKeys
* @param customMessage * @param customMessage
* @deprecated use {@link addDeprecation(String key, String newKey,
String customMessage)} instead
*/ */
@Deprecated
public synchronized static void addDeprecation(String key, String[] newKeys, public synchronized static void addDeprecation(String key, String[] newKeys,
String customMessage) { String customMessage) {
if (key == null || key.length() == 0 || if (key == null || key.length() == 0 ||
@ -289,6 +298,43 @@ public synchronized static void addDeprecation(String key, String[] newKeys,
} }
} }
/**
* Adds the deprecated key to the deprecation map.
* It does not override any existing entries in the deprecation map.
* This is to be used only by the developers in order to add deprecation of
* keys, and attempts to call this method after loading resources once,
* would lead to <tt>UnsupportedOperationException</tt>
*
* @param key
* @param newKey
* @param customMessage
*/
public synchronized static void addDeprecation(String key, String newKey,
String customMessage) {
addDeprecation(key, new String[] {newKey}, customMessage);
}
/**
* Adds the deprecated key to the deprecation map when no custom message
* is provided.
* It does not override any existing entries in the deprecation map.
* This is to be used only by the developers in order to add deprecation of
* keys, and attempts to call this method after loading resources once,
* would lead to <tt>UnsupportedOperationException</tt>
*
* If a key is deprecated in favor of multiple keys, they are all treated as
* aliases of each other, and setting any one of them resets all the others
* to the new value.
*
* @param key Key that is to be deprecated
* @param newKeys list of keys that take up the values of deprecated key
* @deprecated use {@link addDeprecation(String key, String newKey)} instead
*/
@Deprecated
public synchronized static void addDeprecation(String key, String[] newKeys) {
addDeprecation(key, newKeys, null);
}
/** /**
* Adds the deprecated key to the deprecation map when no custom message * Adds the deprecated key to the deprecation map when no custom message
* is provided. * is provided.
@ -298,10 +344,10 @@ public synchronized static void addDeprecation(String key, String[] newKeys,
* would lead to <tt>UnsupportedOperationException</tt> * would lead to <tt>UnsupportedOperationException</tt>
* *
* @param key Key that is to be deprecated * @param key Key that is to be deprecated
* @param newKeys list of keys that take up the values of deprecated key * @param newKey key that takes up the value of deprecated key
*/ */
public synchronized static void addDeprecation(String key, String[] newKeys) { public synchronized static void addDeprecation(String key, String newKey) {
addDeprecation(key, newKeys, null); addDeprecation(key, new String[] {newKey}, null);
} }
/** /**
@ -322,16 +368,26 @@ public static boolean isDeprecated(String key) {
* @param name property name. * @param name property name.
* @return alternate name. * @return alternate name.
*/ */
private String getAlternateName(String name) { private String[] getAlternateNames(String name) {
String altName; String oldName, altNames[] = null;
DeprecatedKeyInfo keyInfo = deprecatedKeyMap.get(name); DeprecatedKeyInfo keyInfo = deprecatedKeyMap.get(name);
if (keyInfo != null) { if (keyInfo == null) {
altName = (keyInfo.newKeys.length > 0) ? keyInfo.newKeys[0] : null; altNames = (reverseDeprecatedKeyMap.get(name) != null ) ?
new String [] {reverseDeprecatedKeyMap.get(name)} : null;
if(altNames != null && altNames.length > 0) {
//To help look for other new configs for this deprecated config
keyInfo = deprecatedKeyMap.get(altNames[0]);
} }
else {
altName = reverseDeprecatedKeyMap.get(name);
} }
return altName; if(keyInfo != null && keyInfo.newKeys.length > 0) {
List<String> list = new ArrayList<String>();
if(altNames != null) {
list.addAll(Arrays.asList(altNames));
}
list.addAll(Arrays.asList(keyInfo.newKeys));
altNames = list.toArray(new String[list.size()]);
}
return altNames;
} }
/** /**
@ -346,24 +402,29 @@ private String getAlternateName(String name) {
* @return the first property in the list of properties mapping * @return the first property in the list of properties mapping
* the <code>name</code> or the <code>name</code> itself. * the <code>name</code> or the <code>name</code> itself.
*/ */
private String handleDeprecation(String name) { private String[] handleDeprecation(String name) {
ArrayList<String > names = new ArrayList<String>();
if (isDeprecated(name)) { if (isDeprecated(name)) {
DeprecatedKeyInfo keyInfo = deprecatedKeyMap.get(name); DeprecatedKeyInfo keyInfo = deprecatedKeyMap.get(name);
warnOnceIfDeprecated(name); warnOnceIfDeprecated(name);
for (String newKey : keyInfo.newKeys) { for (String newKey : keyInfo.newKeys) {
if(newKey != null) { if(newKey != null) {
name = newKey; names.add(newKey);
break;
} }
} }
} }
String deprecatedKey = reverseDeprecatedKeyMap.get(name); if(names.size() == 0) {
if (deprecatedKey != null && !getOverlay().containsKey(name) && names.add(name);
}
for(String n : names) {
String deprecatedKey = reverseDeprecatedKeyMap.get(n);
if (deprecatedKey != null && !getOverlay().containsKey(n) &&
getOverlay().containsKey(deprecatedKey)) { getOverlay().containsKey(deprecatedKey)) {
getProps().setProperty(name, getOverlay().getProperty(deprecatedKey)); getProps().setProperty(n, getOverlay().getProperty(deprecatedKey));
getOverlay().setProperty(name, getOverlay().getProperty(deprecatedKey)); getOverlay().setProperty(n, getOverlay().getProperty(deprecatedKey));
} }
return name; }
return names.toArray(new String[names.size()]);
} }
private void handleDeprecation() { private void handleDeprecation() {
@ -595,8 +656,12 @@ private String substituteVars(String expr) {
* or null if no such property exists. * or null if no such property exists.
*/ */
public String get(String name) { public String get(String name) {
name = handleDeprecation(name); String[] names = handleDeprecation(name);
return substituteVars(getProps().getProperty(name)); String result = null;
for(String n : names) {
result = substituteVars(getProps().getProperty(n));
}
return result;
} }
/** /**
@ -633,8 +698,12 @@ public String getTrimmed(String name) {
* its replacing property and null if no such property exists. * its replacing property and null if no such property exists.
*/ */
public String getRaw(String name) { public String getRaw(String name) {
name = handleDeprecation(name); String[] names = handleDeprecation(name);
return getProps().getProperty(name); String result = null;
for(String n : names) {
result = getProps().getProperty(n);
}
return result;
} }
/** /**
@ -652,11 +721,13 @@ public void set(String name, String value) {
getOverlay().setProperty(name, value); getOverlay().setProperty(name, value);
getProps().setProperty(name, value); getProps().setProperty(name, value);
updatingResource.put(name, UNKNOWN_RESOURCE); updatingResource.put(name, UNKNOWN_RESOURCE);
String altName = getAlternateName(name); String[] altNames = getAlternateNames(name);
if (altName != null) { if (altNames != null && altNames.length > 0) {
for(String altName : altNames) {
getOverlay().setProperty(altName, value); getOverlay().setProperty(altName, value);
getProps().setProperty(altName, value); getProps().setProperty(altName, value);
} }
}
warnOnceIfDeprecated(name); warnOnceIfDeprecated(name);
} }
@ -671,14 +742,16 @@ private void warnOnceIfDeprecated(String name) {
* Unset a previously set property. * Unset a previously set property.
*/ */
public synchronized void unset(String name) { public synchronized void unset(String name) {
String altName = getAlternateName(name); String[] altNames = getAlternateNames(name);
getOverlay().remove(name); getOverlay().remove(name);
getProps().remove(name); getProps().remove(name);
if (altName !=null) { if (altNames !=null && altNames.length > 0) {
for(String altName : altNames) {
getOverlay().remove(altName); getOverlay().remove(altName);
getProps().remove(altName); getProps().remove(altName);
} }
} }
}
/** /**
* Sets a property if it is currently unset. * Sets a property if it is currently unset.
@ -711,8 +784,12 @@ private synchronized Properties getOverlay() {
* doesn't exist. * doesn't exist.
*/ */
public String get(String name, String defaultValue) { public String get(String name, String defaultValue) {
name = handleDeprecation(name); String[] names = handleDeprecation(name);
return substituteVars(getProps().getProperty(name, defaultValue)); String result = null;
for(String n : names) {
result = substituteVars(getProps().getProperty(n, defaultValue));
}
return result;
} }
/** /**

View File

@ -164,7 +164,7 @@ public void testDeprecation() throws IOException {
conf.set("Y", "y"); conf.set("Y", "y");
conf.set("Z", "z"); conf.set("Z", "z");
// get old key // get old key
assertEquals("y", conf.get("X")); assertEquals("z", conf.get("X"));
} }
/** /**

View File

@ -18,10 +18,15 @@
package org.apache.hadoop.conf; package org.apache.hadoop.conf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.util.Map;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.CommonConfigurationKeys; import org.apache.hadoop.fs.CommonConfigurationKeys;
import org.junit.Test;
import junit.framework.TestCase; import junit.framework.TestCase;
@ -53,4 +58,49 @@ public void testReadWriteWithDeprecatedKeys() throws Exception {
assertTrue(fileContents.contains("old.config.yet.to.be.deprecated")); assertTrue(fileContents.contains("old.config.yet.to.be.deprecated"));
assertTrue(fileContents.contains("new.conf.to.replace.deprecated.conf")); assertTrue(fileContents.contains("new.conf.to.replace.deprecated.conf"));
} }
@Test
public void testIteratorWithDeprecatedKeysMappedToMultipleNewKeys() {
Configuration conf = new Configuration();
Configuration.addDeprecation("dK", new String[]{"nK1", "nK2"});
conf.set("k", "v");
conf.set("dK", "V");
assertEquals("V", conf.get("dK"));
assertEquals("V", conf.get("nK1"));
assertEquals("V", conf.get("nK2"));
conf.set("nK1", "VV");
assertEquals("VV", conf.get("dK"));
assertEquals("VV", conf.get("nK1"));
assertEquals("VV", conf.get("nK2"));
conf.set("nK2", "VVV");
assertEquals("VVV", conf.get("dK"));
assertEquals("VVV", conf.get("nK2"));
assertEquals("VVV", conf.get("nK1"));
boolean kFound = false;
boolean dKFound = false;
boolean nK1Found = false;
boolean nK2Found = false;
for (Map.Entry<String, String> entry : conf) {
if (entry.getKey().equals("k")) {
assertEquals("v", entry.getValue());
kFound = true;
}
if (entry.getKey().equals("dK")) {
assertEquals("VVV", entry.getValue());
dKFound = true;
}
if (entry.getKey().equals("nK1")) {
assertEquals("VVV", entry.getValue());
nK1Found = true;
}
if (entry.getKey().equals("nK2")) {
assertEquals("VVV", entry.getValue());
nK2Found = true;
}
}
assertTrue("regular Key not found", kFound);
assertTrue("deprecated Key not found", dKFound);
assertTrue("new Key 1 not found", nK1Found);
assertTrue("new Key 2 not found", nK2Found);
}
} }