Author: tedyu
Date: Thu Apr 4 18:38:22 2013
New Revision: 1464669
URL: http://svn.apache.org/r1464669
Log:
HBASE-8240 CompoundConfiguration should implement Iterable (Ted Yu)
Modified:
hbase/trunk/hbase-common/src/main/java/org/apache/hadoop/hbase/CompoundConfiguration.java
hbase/trunk/hbase-common/src/test/java/org/apache/hadoop/hbase/TestCompoundConfiguration.java
Modified:
hbase/trunk/hbase-common/src/main/java/org/apache/hadoop/hbase/CompoundConfiguration.java
URL:
http://svn.apache.org/viewvc/hbase/trunk/hbase-common/src/main/java/org/apache/hadoop/hbase/CompoundConfiguration.java?rev=1464669&r1=1464668&r2=1464669&view=diff
==============================================================================
---
hbase/trunk/hbase-common/src/main/java/org/apache/hadoop/hbase/CompoundConfiguration.java
(original)
+++
hbase/trunk/hbase-common/src/main/java/org/apache/hadoop/hbase/CompoundConfiguration.java
Thu Apr 4 18:38:22 2013
@@ -25,10 +25,12 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import org.apache.commons.collections.iterators.UnmodifiableIterator;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
@@ -42,6 +44,9 @@ import org.apache.hadoop.util.StringUtil
* functionality, which performs a deep merge and mutates the common data
* structure.
* <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
* configuration objects and have changes reflected everywhere. In contrast to
a
* deep merge, that requires you to explicitly know all applicable copies to
@@ -57,7 +62,7 @@ public class CompoundConfiguration exten
// Devs: these APIs are the same contract as their counterparts in
// Configuration.java
- private static interface ImmutableConfigMap {
+ private static interface ImmutableConfigMap extends
Iterable<Map.Entry<String,String>> {
String get(String key);
String getRaw(String key);
Class<?> getClassByName(String name) throws ClassNotFoundException;
@@ -83,6 +88,11 @@ public class CompoundConfiguration exten
Configuration c = conf;
@Override
+ public Iterator<Map.Entry<String,String>> iterator() {
+ return c.iterator();
+ }
+
+ @Override
public String get(String key) {
return c.get(key);
}
@@ -128,6 +138,17 @@ public class CompoundConfiguration exten
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
public String get(String key) {
ImmutableBytesWritable ibw = new ImmutableBytesWritable(Bytes
.toBytes(key));
@@ -176,6 +197,11 @@ public class CompoundConfiguration exten
Map<String, String> m = map;
@Override
+ public Iterator<Map.Entry<String,String>> iterator() {
+ return map.entrySet().iterator();
+ }
+
+ @Override
public String get(String key) {
return m.get(key);
}
@@ -434,7 +460,18 @@ public class CompoundConfiguration exten
@Override
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
Modified:
hbase/trunk/hbase-common/src/test/java/org/apache/hadoop/hbase/TestCompoundConfiguration.java
URL:
http://svn.apache.org/viewvc/hbase/trunk/hbase-common/src/test/java/org/apache/hadoop/hbase/TestCompoundConfiguration.java?rev=1464669&r1=1464668&r2=1464669&view=diff
==============================================================================
---
hbase/trunk/hbase-common/src/test/java/org/apache/hadoop/hbase/TestCompoundConfiguration.java
(original)
+++
hbase/trunk/hbase-common/src/test/java/org/apache/hadoop/hbase/TestCompoundConfiguration.java
Thu Apr 4 18:38:22 2013
@@ -20,6 +20,7 @@
package org.apache.hadoop.hbase;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.Map;
import org.apache.hadoop.conf.Configuration;
@@ -35,6 +36,7 @@ import junit.framework.TestCase;
@Category(SmallTests.class)
public class TestCompoundConfiguration extends TestCase {
private Configuration baseConf;
+ private int baseConfSize;
@Override
protected void setUp() throws Exception {
@@ -42,6 +44,7 @@ public class TestCompoundConfiguration e
baseConf.set("A", "1");
baseConf.setInt("B", 2);
baseConf.set("C", "3");
+ baseConfSize = baseConf.size();
}
@Test
@@ -80,6 +83,15 @@ public class TestCompoundConfiguration e
assertEquals(4, compoundConf.getInt("D", 0));
assertNull(compoundConf.get("E"));
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) {
@@ -107,6 +119,15 @@ public class TestCompoundConfiguration e
assertNull(compoundConf.get("E"));
assertEquals(6, compoundConf.getInt("F", 6));
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
@@ -126,6 +147,15 @@ public class TestCompoundConfiguration e
assertNull(compoundConf.get("E"));
assertEquals(6, compoundConf.getInt("F", 6));
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
@@ -134,16 +164,26 @@ public class TestCompoundConfiguration e
map1.put("A", "2");
map1.put("D", "5");
Map<String, String> map2 = new HashMap<String, String>();
- map2.put("A", "3");
- map2.put("B", "4");
+ String newValueForA = "3", newValueForB = "4";
+ map2.put("A", newValueForA);
+ map2.put("B", newValueForB);
CompoundConfiguration compoundConf = new CompoundConfiguration()
.addStringMap(map1).add(baseConf);
assertEquals("1", compoundConf.get("A"));
assertEquals("5", compoundConf.get("D"));
compoundConf.addStringMap(map2);
- assertEquals("3", compoundConf.get("A"));
- assertEquals("4", compoundConf.get("B"));
+ assertEquals(newValueForA, compoundConf.get("A"));
+ assertEquals(newValueForB, compoundConf.get("B"));
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);
}
}