HADOOP-8608. Add Configuration API for parsing time durations.
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1477869 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
7e7d99e905
commit
0728f00282
|
@ -166,6 +166,8 @@ Trunk (Unreleased)
|
||||||
HADOOP-9486. Promoted Windows and Shell related utils from YARN to Hadoop
|
HADOOP-9486. Promoted Windows and Shell related utils from YARN to Hadoop
|
||||||
Common. (Chris Nauroth via vinodkv)
|
Common. (Chris Nauroth via vinodkv)
|
||||||
|
|
||||||
|
HADOOP-8608. Add Configuration API for parsing time durations. (cdouglas)
|
||||||
|
|
||||||
BUG FIXES
|
BUG FIXES
|
||||||
|
|
||||||
HADOOP-9451. Fault single-layer config if node group topology is enabled.
|
HADOOP-9451. Fault single-layer config if node group topology is enabled.
|
||||||
|
|
|
@ -54,6 +54,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.regex.PatternSyntaxException;
|
import java.util.regex.PatternSyntaxException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
@ -1145,6 +1146,93 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
|
||||||
: Enum.valueOf(defaultValue.getDeclaringClass(), val);
|
: Enum.valueOf(defaultValue.getDeclaringClass(), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum ParsedTimeDuration {
|
||||||
|
NS {
|
||||||
|
TimeUnit unit() { return TimeUnit.NANOSECONDS; }
|
||||||
|
String suffix() { return "ns"; }
|
||||||
|
},
|
||||||
|
US {
|
||||||
|
TimeUnit unit() { return TimeUnit.MICROSECONDS; }
|
||||||
|
String suffix() { return "us"; }
|
||||||
|
},
|
||||||
|
MS {
|
||||||
|
TimeUnit unit() { return TimeUnit.MILLISECONDS; }
|
||||||
|
String suffix() { return "ms"; }
|
||||||
|
},
|
||||||
|
S {
|
||||||
|
TimeUnit unit() { return TimeUnit.SECONDS; }
|
||||||
|
String suffix() { return "s"; }
|
||||||
|
},
|
||||||
|
M {
|
||||||
|
TimeUnit unit() { return TimeUnit.MINUTES; }
|
||||||
|
String suffix() { return "m"; }
|
||||||
|
},
|
||||||
|
H {
|
||||||
|
TimeUnit unit() { return TimeUnit.HOURS; }
|
||||||
|
String suffix() { return "h"; }
|
||||||
|
},
|
||||||
|
D {
|
||||||
|
TimeUnit unit() { return TimeUnit.DAYS; }
|
||||||
|
String suffix() { return "d"; }
|
||||||
|
};
|
||||||
|
abstract TimeUnit unit();
|
||||||
|
abstract String suffix();
|
||||||
|
static ParsedTimeDuration unitFor(String s) {
|
||||||
|
for (ParsedTimeDuration ptd : values()) {
|
||||||
|
// iteration order is in decl order, so SECONDS matched last
|
||||||
|
if (s.endsWith(ptd.suffix())) {
|
||||||
|
return ptd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
static ParsedTimeDuration unitFor(TimeUnit unit) {
|
||||||
|
for (ParsedTimeDuration ptd : values()) {
|
||||||
|
if (ptd.unit() == unit) {
|
||||||
|
return ptd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of <code>name</code> to the given time duration. This
|
||||||
|
* is equivalent to <code>set(<name>, value + <time suffix>)</code>.
|
||||||
|
* @param name Property name
|
||||||
|
* @param value Time duration
|
||||||
|
* @param unit Unit of time
|
||||||
|
*/
|
||||||
|
public void setTimeDuration(String name, long value, TimeUnit unit) {
|
||||||
|
set(name, value + ParsedTimeDuration.unitFor(unit).suffix());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return time duration in the given time unit. Valid units are encoded in
|
||||||
|
* properties as suffixes: nanoseconds (ns), microseconds (us), milliseconds
|
||||||
|
* (ms), seconds (s), minutes (m), hours (h), and days (d).
|
||||||
|
* @param name Property name
|
||||||
|
* @param defaultValue Value returned if no mapping exists.
|
||||||
|
* @param unit Unit to convert the stored property, if it exists.
|
||||||
|
* @throws NumberFormatException If the property stripped of its unit is not
|
||||||
|
* a number
|
||||||
|
*/
|
||||||
|
public long getTimeDuration(String name, long defaultValue, TimeUnit unit) {
|
||||||
|
String vStr = get(name);
|
||||||
|
if (null == vStr) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
vStr = vStr.trim();
|
||||||
|
ParsedTimeDuration vUnit = ParsedTimeDuration.unitFor(vStr);
|
||||||
|
if (null == vUnit) {
|
||||||
|
LOG.warn("No unit for " + name + "(" + vStr + ") assuming " + unit);
|
||||||
|
vUnit = ParsedTimeDuration.unitFor(unit);
|
||||||
|
} else {
|
||||||
|
vStr = vStr.substring(0, vStr.lastIndexOf(vUnit.suffix()));
|
||||||
|
}
|
||||||
|
return unit.convert(Long.parseLong(vStr), vUnit.unit());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the value of the <code>name</code> property as a <code>Pattern</code>.
|
* Get the value of the <code>name</code> property as a <code>Pattern</code>.
|
||||||
* If no such property is specified, or if the specified value is not a valid
|
* If no such property is specified, or if the specified value is not a valid
|
||||||
|
|
|
@ -36,6 +36,7 @@ import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
import static java.util.concurrent.TimeUnit.*;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
|
@ -693,6 +694,37 @@ public class TestConfiguration extends TestCase {
|
||||||
assertTrue(fail);
|
assertTrue(fail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testTimeDuration() {
|
||||||
|
Configuration conf = new Configuration(false);
|
||||||
|
conf.setTimeDuration("test.time.a", 7L, SECONDS);
|
||||||
|
assertEquals("7s", conf.get("test.time.a"));
|
||||||
|
assertEquals(0L, conf.getTimeDuration("test.time.a", 30, MINUTES));
|
||||||
|
assertEquals(7L, conf.getTimeDuration("test.time.a", 30, SECONDS));
|
||||||
|
assertEquals(7000L, conf.getTimeDuration("test.time.a", 30, MILLISECONDS));
|
||||||
|
assertEquals(7000000L,
|
||||||
|
conf.getTimeDuration("test.time.a", 30, MICROSECONDS));
|
||||||
|
assertEquals(7000000000L,
|
||||||
|
conf.getTimeDuration("test.time.a", 30, NANOSECONDS));
|
||||||
|
conf.setTimeDuration("test.time.b", 1, DAYS);
|
||||||
|
assertEquals("1d", conf.get("test.time.b"));
|
||||||
|
assertEquals(1, conf.getTimeDuration("test.time.b", 1, DAYS));
|
||||||
|
assertEquals(24, conf.getTimeDuration("test.time.b", 1, HOURS));
|
||||||
|
assertEquals(MINUTES.convert(1, DAYS),
|
||||||
|
conf.getTimeDuration("test.time.b", 1, MINUTES));
|
||||||
|
|
||||||
|
// check default
|
||||||
|
assertEquals(30L, conf.getTimeDuration("test.time.X", 30, SECONDS));
|
||||||
|
conf.set("test.time.X", "30");
|
||||||
|
assertEquals(30L, conf.getTimeDuration("test.time.X", 40, SECONDS));
|
||||||
|
|
||||||
|
for (Configuration.ParsedTimeDuration ptd :
|
||||||
|
Configuration.ParsedTimeDuration.values()) {
|
||||||
|
conf.setTimeDuration("test.time.unit", 1, ptd.unit());
|
||||||
|
assertEquals(1 + ptd.suffix(), conf.get("test.time.unit"));
|
||||||
|
assertEquals(1, conf.getTimeDuration("test.time.unit", 2, ptd.unit()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void testPattern() throws IOException {
|
public void testPattern() throws IOException {
|
||||||
out = new BufferedWriter(new FileWriter(CONFIG));
|
out = new BufferedWriter(new FileWriter(CONFIG));
|
||||||
startConfig();
|
startConfig();
|
||||||
|
|
Loading…
Reference in New Issue