HBASE-8240 CompoundConfiguration should implement Iterable (Ted Yu)
git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1464669 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
f357ac700d
commit
17b1428a11
|
@ -25,10 +25,12 @@ import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.commons.collections.iterators.UnmodifiableIterator;
|
||||||
import org.apache.hadoop.classification.InterfaceAudience;
|
import org.apache.hadoop.classification.InterfaceAudience;
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
|
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
|
||||||
|
@ -42,6 +44,9 @@ import org.apache.hadoop.util.StringUtils;
|
||||||
* functionality, which performs a deep merge and mutates the common data
|
* functionality, which performs a deep merge and mutates the common data
|
||||||
* structure.
|
* structure.
|
||||||
* <p>
|
* <p>
|
||||||
|
* The iterator on CompoundConfiguration is unmodifiable. Obtaining iterator is an expensive
|
||||||
|
* operation.
|
||||||
|
* <p>
|
||||||
* For clarity: the shallow merge allows the user to mutate either of the
|
* For clarity: the shallow merge allows the user to mutate either of the
|
||||||
* configuration objects and have changes reflected everywhere. In contrast to a
|
* configuration objects and have changes reflected everywhere. In contrast to a
|
||||||
* deep merge, that requires you to explicitly know all applicable copies to
|
* deep merge, that requires you to explicitly know all applicable copies to
|
||||||
|
@ -57,7 +62,7 @@ public class CompoundConfiguration extends Configuration {
|
||||||
|
|
||||||
// Devs: these APIs are the same contract as their counterparts in
|
// Devs: these APIs are the same contract as their counterparts in
|
||||||
// Configuration.java
|
// Configuration.java
|
||||||
private static interface ImmutableConfigMap {
|
private static interface ImmutableConfigMap extends Iterable<Map.Entry<String,String>> {
|
||||||
String get(String key);
|
String get(String key);
|
||||||
String getRaw(String key);
|
String getRaw(String key);
|
||||||
Class<?> getClassByName(String name) throws ClassNotFoundException;
|
Class<?> getClassByName(String name) throws ClassNotFoundException;
|
||||||
|
@ -82,6 +87,11 @@ public class CompoundConfiguration extends Configuration {
|
||||||
this.configs.add(0, new ImmutableConfigMap() {
|
this.configs.add(0, new ImmutableConfigMap() {
|
||||||
Configuration c = conf;
|
Configuration c = conf;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Map.Entry<String,String>> iterator() {
|
||||||
|
return c.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String get(String key) {
|
public String get(String key) {
|
||||||
return c.get(key);
|
return c.get(key);
|
||||||
|
@ -127,6 +137,17 @@ public class CompoundConfiguration extends Configuration {
|
||||||
this.configs.add(0, new ImmutableConfigMap() {
|
this.configs.add(0, new ImmutableConfigMap() {
|
||||||
Map<ImmutableBytesWritable, ImmutableBytesWritable> m = map;
|
Map<ImmutableBytesWritable, ImmutableBytesWritable> m = map;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Map.Entry<String,String>> iterator() {
|
||||||
|
Map<String, String> ret = new HashMap<String, String>();
|
||||||
|
for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> entry : map.entrySet()) {
|
||||||
|
String key = Bytes.toString(entry.getKey().get());
|
||||||
|
String val = entry.getValue() == null ? null : Bytes.toString(entry.getValue().get());
|
||||||
|
ret.put(key, val);
|
||||||
|
}
|
||||||
|
return ret.entrySet().iterator();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String get(String key) {
|
public String get(String key) {
|
||||||
ImmutableBytesWritable ibw = new ImmutableBytesWritable(Bytes
|
ImmutableBytesWritable ibw = new ImmutableBytesWritable(Bytes
|
||||||
|
@ -175,6 +196,11 @@ public class CompoundConfiguration extends Configuration {
|
||||||
this.configs.add(0, new ImmutableConfigMap() {
|
this.configs.add(0, new ImmutableConfigMap() {
|
||||||
Map<String, String> m = map;
|
Map<String, String> m = map;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Map.Entry<String,String>> iterator() {
|
||||||
|
return map.entrySet().iterator();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String get(String key) {
|
public String get(String key) {
|
||||||
return m.get(key);
|
return m.get(key);
|
||||||
|
@ -434,7 +460,18 @@ public class CompoundConfiguration extends Configuration {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<Map.Entry<String, String>> iterator() {
|
public Iterator<Map.Entry<String, String>> iterator() {
|
||||||
throw new UnsupportedOperationException("Immutable Configuration");
|
Map<String, String> ret = new HashMap<String, String>();
|
||||||
|
if (!configs.isEmpty()) {
|
||||||
|
for (int i = configs.size() - 1; i >= 0; i--) {
|
||||||
|
ImmutableConfigMap map = configs.get(i);
|
||||||
|
Iterator<Map.Entry<String, String>> iter = map.iterator();
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
Map.Entry<String, String> entry = iter.next();
|
||||||
|
ret.put(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return UnmodifiableIterator.decorate(ret.entrySet().iterator());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
package org.apache.hadoop.hbase;
|
package org.apache.hadoop.hbase;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
|
@ -35,6 +36,7 @@ import junit.framework.TestCase;
|
||||||
@Category(SmallTests.class)
|
@Category(SmallTests.class)
|
||||||
public class TestCompoundConfiguration extends TestCase {
|
public class TestCompoundConfiguration extends TestCase {
|
||||||
private Configuration baseConf;
|
private Configuration baseConf;
|
||||||
|
private int baseConfSize;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
|
@ -42,6 +44,7 @@ public class TestCompoundConfiguration extends TestCase {
|
||||||
baseConf.set("A", "1");
|
baseConf.set("A", "1");
|
||||||
baseConf.setInt("B", 2);
|
baseConf.setInt("B", 2);
|
||||||
baseConf.set("C", "3");
|
baseConf.set("C", "3");
|
||||||
|
baseConfSize = baseConf.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -80,6 +83,15 @@ public class TestCompoundConfiguration extends TestCase {
|
||||||
assertEquals(4, compoundConf.getInt("D", 0));
|
assertEquals(4, compoundConf.getInt("D", 0));
|
||||||
assertNull(compoundConf.get("E"));
|
assertNull(compoundConf.get("E"));
|
||||||
assertEquals(6, compoundConf.getInt("F", 6));
|
assertEquals(6, compoundConf.getInt("F", 6));
|
||||||
|
|
||||||
|
int cnt = 0;
|
||||||
|
for (Map.Entry<String,String> entry : compoundConf) {
|
||||||
|
cnt++;
|
||||||
|
if (entry.getKey().equals("B")) assertEquals("2b", entry.getValue());
|
||||||
|
else if (entry.getKey().equals("G")) assertEquals(null, entry.getValue());
|
||||||
|
}
|
||||||
|
// verify that entries from ImmutableConfigMap's are merged in the iterator's view
|
||||||
|
assertEquals(baseConfSize + 1, cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ImmutableBytesWritable strToIbw(String s) {
|
private ImmutableBytesWritable strToIbw(String s) {
|
||||||
|
@ -107,6 +119,15 @@ public class TestCompoundConfiguration extends TestCase {
|
||||||
assertNull(compoundConf.get("E"));
|
assertNull(compoundConf.get("E"));
|
||||||
assertEquals(6, compoundConf.getInt("F", 6));
|
assertEquals(6, compoundConf.getInt("F", 6));
|
||||||
assertNull(compoundConf.get("G"));
|
assertNull(compoundConf.get("G"));
|
||||||
|
|
||||||
|
int cnt = 0;
|
||||||
|
for (Map.Entry<String,String> entry : compoundConf) {
|
||||||
|
cnt++;
|
||||||
|
if (entry.getKey().equals("B")) assertEquals("2b", entry.getValue());
|
||||||
|
else if (entry.getKey().equals("G")) assertEquals(null, entry.getValue());
|
||||||
|
}
|
||||||
|
// verify that entries from ImmutableConfigMap's are merged in the iterator's view
|
||||||
|
assertEquals(baseConfSize + 2, cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -126,6 +147,15 @@ public class TestCompoundConfiguration extends TestCase {
|
||||||
assertNull(compoundConf.get("E"));
|
assertNull(compoundConf.get("E"));
|
||||||
assertEquals(6, compoundConf.getInt("F", 6));
|
assertEquals(6, compoundConf.getInt("F", 6));
|
||||||
assertNull(compoundConf.get("G"));
|
assertNull(compoundConf.get("G"));
|
||||||
|
|
||||||
|
int cnt = 0;
|
||||||
|
for (Map.Entry<String,String> entry : compoundConf) {
|
||||||
|
cnt++;
|
||||||
|
if (entry.getKey().equals("B")) assertEquals("2b", entry.getValue());
|
||||||
|
else if (entry.getKey().equals("G")) assertEquals(null, entry.getValue());
|
||||||
|
}
|
||||||
|
// verify that entries from ImmutableConfigMap's are merged in the iterator's view
|
||||||
|
assertEquals(4, cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -134,16 +164,26 @@ public class TestCompoundConfiguration extends TestCase {
|
||||||
map1.put("A", "2");
|
map1.put("A", "2");
|
||||||
map1.put("D", "5");
|
map1.put("D", "5");
|
||||||
Map<String, String> map2 = new HashMap<String, String>();
|
Map<String, String> map2 = new HashMap<String, String>();
|
||||||
map2.put("A", "3");
|
String newValueForA = "3", newValueForB = "4";
|
||||||
map2.put("B", "4");
|
map2.put("A", newValueForA);
|
||||||
|
map2.put("B", newValueForB);
|
||||||
|
|
||||||
CompoundConfiguration compoundConf = new CompoundConfiguration()
|
CompoundConfiguration compoundConf = new CompoundConfiguration()
|
||||||
.addStringMap(map1).add(baseConf);
|
.addStringMap(map1).add(baseConf);
|
||||||
assertEquals("1", compoundConf.get("A"));
|
assertEquals("1", compoundConf.get("A"));
|
||||||
assertEquals("5", compoundConf.get("D"));
|
assertEquals("5", compoundConf.get("D"));
|
||||||
compoundConf.addStringMap(map2);
|
compoundConf.addStringMap(map2);
|
||||||
assertEquals("3", compoundConf.get("A"));
|
assertEquals(newValueForA, compoundConf.get("A"));
|
||||||
assertEquals("4", compoundConf.get("B"));
|
assertEquals(newValueForB, compoundConf.get("B"));
|
||||||
assertEquals("5", compoundConf.get("D"));
|
assertEquals("5", compoundConf.get("D"));
|
||||||
|
|
||||||
|
int cnt = 0;
|
||||||
|
for (Map.Entry<String,String> entry : compoundConf) {
|
||||||
|
cnt++;
|
||||||
|
if (entry.getKey().equals("A")) assertEquals(newValueForA, entry.getValue());
|
||||||
|
else if (entry.getKey().equals("B")) assertEquals(newValueForB, entry.getValue());
|
||||||
|
}
|
||||||
|
// verify that entries from ImmutableConfigMap's are merged in the iterator's view
|
||||||
|
assertEquals(baseConfSize + 1, cnt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue