HADOOP-10178. Configuration deprecation always emit "deprecated" warnings when a new key is used. Contributed by Shanyu Zhao.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1557236 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Chris Nauroth 2014-01-10 19:57:51 +00:00
parent a0ecb98a77
commit 8e0ba42df4
3 changed files with 112 additions and 54 deletions

View File

@ -596,6 +596,9 @@ Release 2.3.0 - UNRELEASED
HADOOP-10193. hadoop-auth's PseudoAuthenticationHandler can consume getInputStream.
(gchanan via tucu)
HADOOP-10178. Configuration deprecation always emit "deprecated" warnings
when a new key is used. (Shanyu Zhao via cnauroth)
Release 2.2.0 - 2013-10-13
INCOMPATIBLE CHANGES

View File

@ -552,36 +552,6 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
return deprecationContext.get().getDeprecatedKeyMap().containsKey(key);
}
/**
* Returns the alternate name for a key if the property name is deprecated
* or if deprecates a property name.
*
* @param name property name.
* @return alternate name.
*/
private String[] getAlternateNames(String name) {
String altNames[] = null;
DeprecationContext cur = deprecationContext.get();
DeprecatedKeyInfo keyInfo = cur.getDeprecatedKeyMap().get(name);
if (keyInfo == null) {
altNames = (cur.getReverseDeprecatedKeyMap().get(name) != null ) ?
new String [] {cur.getReverseDeprecatedKeyMap().get(name)} : null;
if(altNames != null && altNames.length > 0) {
//To help look for other new configs for this deprecated config
keyInfo = cur.getDeprecatedKeyMap().get(altNames[0]);
}
}
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;
}
/**
* Checks for the presence of the property <code>name</code> in the
* deprecation map. Returns the first of the list of new keys if present
@ -933,6 +903,37 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
return result;
}
/**
* Returns alternative names (non-deprecated keys or previously-set deprecated keys)
* for a given non-deprecated key.
* If the given key is deprecated, return null.
*
* @param name property name.
* @return alternative names.
*/
private String[] getAlternativeNames(String name) {
String altNames[] = null;
DeprecatedKeyInfo keyInfo = null;
DeprecationContext cur = deprecationContext.get();
String depKey = cur.getReverseDeprecatedKeyMap().get(name);
if(depKey != null) {
keyInfo = cur.getDeprecatedKeyMap().get(depKey);
if(keyInfo.newKeys.length > 0) {
if(getProps().containsKey(depKey)) {
//if deprecated key is previously set explicitly
List<String> list = new ArrayList<String>();
list.addAll(Arrays.asList(keyInfo.newKeys));
list.add(depKey);
altNames = list.toArray(new String[list.size()]);
}
else {
altNames = keyInfo.newKeys;
}
}
}
return altNames;
}
/**
* Set the <code>value</code> of the <code>name</code> property. If
* <code>name</code> is deprecated or there is a deprecated name associated to it,
@ -947,9 +948,9 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
/**
* Set the <code>value</code> of the <code>name</code> property. If
* <code>name</code> is deprecated or there is a deprecated name associated to it,
* it sets the value to both names.
*
* <code>name</code> is deprecated, it also sets the <code>value</code> to
* the keys that replace the deprecated key.
*
* @param name property name.
* @param value property value.
* @param source the place that this configuration value came from
@ -969,23 +970,30 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
}
getOverlay().setProperty(name, value);
getProps().setProperty(name, value);
if(source == null) {
updatingResource.put(name, new String[] {"programatically"});
} else {
updatingResource.put(name, new String[] {source});
}
String[] altNames = getAlternateNames(name);
if (altNames != null && altNames.length > 0) {
String altSource = "because " + name + " is deprecated";
for(String altName : altNames) {
if(!altName.equals(name)) {
getOverlay().setProperty(altName, value);
getProps().setProperty(altName, value);
updatingResource.put(altName, new String[] {altSource});
String newSource = (source == null ? "programatically" : source);
if (!isDeprecated(name)) {
updatingResource.put(name, new String[] {newSource});
String[] altNames = getAlternativeNames(name);
if(altNames != null) {
for(String n: altNames) {
if(!n.equals(name)) {
getOverlay().setProperty(n, value);
getProps().setProperty(n, value);
updatingResource.put(n, new String[] {newSource});
}
}
}
}
warnOnceIfDeprecated(deprecations, name);
else {
String[] names = handleDeprecation(deprecationContext.get(), name);
String altSource = "because " + name + " is deprecated";
for(String n : names) {
getOverlay().setProperty(n, value);
getProps().setProperty(n, value);
updatingResource.put(n, new String[] {altSource});
}
}
}
private void warnOnceIfDeprecated(DeprecationContext deprecations, String name) {
@ -999,15 +1007,21 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
* Unset a previously set property.
*/
public synchronized void unset(String name) {
String[] altNames = getAlternateNames(name);
getOverlay().remove(name);
getProps().remove(name);
if (altNames !=null && altNames.length > 0) {
for(String altName : altNames) {
getOverlay().remove(altName);
getProps().remove(altName);
String[] names = null;
if (!isDeprecated(name)) {
names = getAlternativeNames(name);
if(names == null) {
names = new String[]{name};
}
}
else {
names = handleDeprecation(deprecationContext.get(), name);
}
for(String n: names) {
getOverlay().remove(n);
getProps().remove(n);
}
}
/**
@ -2600,4 +2614,18 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
System.out.println(entry.getKey() + "\t" + newKeys.toString());
}
}
/**
* Returns whether or not a deprecated name has been warned. If the name is not
* deprecated then always return false
*/
public static boolean hasWarnedDeprecation(String name) {
DeprecationContext deprecations = deprecationContext.get();
if(deprecations.getDeprecatedKeyMap().containsKey(name)) {
if(deprecations.getDeprecatedKeyMap().get(name).accessed.get()) {
return true;
}
}
return false;
}
}

View File

@ -26,6 +26,7 @@ import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@ -399,4 +400,30 @@ public class TestConfigurationDeprecation {
Uninterruptibles.getUninterruptibly(future);
}
}
@Test
public void testNoFalseDeprecationWarning() throws IOException {
Configuration conf = new Configuration();
Configuration.addDeprecation("AA", "BB");
conf.set("BB", "bb");
conf.get("BB");
conf.writeXml(new ByteArrayOutputStream());
assertEquals(false, Configuration.hasWarnedDeprecation("AA"));
conf.set("AA", "aa");
assertEquals(true, Configuration.hasWarnedDeprecation("AA"));
}
@Test
public void testDeprecationSetUnset() throws IOException {
addDeprecationToConfiguration();
Configuration conf = new Configuration();
//"X" is deprecated by "Y" and "Z"
conf.set("Y", "y");
assertEquals("y", conf.get("Z"));
conf.set("X", "x");
assertEquals("x", conf.get("Z"));
conf.unset("Y");
assertEquals(null, conf.get("Z"));
assertEquals(null, conf.get("X"));
}
}