You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@accumulo.apache.org by bh...@apache.org on 2014/08/13 16:48:27 UTC

[1/8] git commit: ACCUMULO-3012 Improve DefaultConfiguration

Repository: accumulo
Updated Branches:
  refs/heads/1.5.2-SNAPSHOT c4d46bbae -> 7136996a1
  refs/heads/1.6.1-SNAPSHOT 3ee78d994 -> 37f900b75
  refs/heads/master b8271d495 -> c6ed57ed8


ACCUMULO-3012 Improve DefaultConfiguration

* The map of default properties created during the iterator() method each time is now
  static and immutable.
* A unit test is added.
* Accompanying changes were made to ConfigSanityCheck:
  - The validate method takes in an Iterable of entries instead of a Configuration.
  - Validation failure throws a new SanityCheckException class instead of RuntimeException.
  - A unit test is added.


Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo
Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/7136996a
Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/7136996a
Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/7136996a

Branch: refs/heads/1.5.2-SNAPSHOT
Commit: 7136996a19406a7dfc5c2f2c5861cae95f68badc
Parents: c4d46bb
Author: Bill Havanki <bh...@cloudera.com>
Authored: Thu Jul 24 09:36:04 2014 -0400
Committer: Bill Havanki <bh...@cloudera.com>
Committed: Wed Aug 13 09:30:04 2014 -0400

----------------------------------------------------------------------
 .../accumulo/core/conf/ConfigSanityCheck.java   | 44 +++++++++--
 .../core/conf/DefaultConfiguration.java         | 41 ++++++----
 .../core/conf/ConfigSanityCheckTest.java        | 79 ++++++++++++++++++++
 .../core/conf/DefaultConfigurationTest.java     | 47 ++++++++++++
 4 files changed, 187 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/accumulo/blob/7136996a/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java b/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java
index 6724670..abec58b 100644
--- a/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java
+++ b/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java
@@ -20,13 +20,24 @@ import java.util.Map.Entry;
 
 import org.apache.log4j.Logger;
 
+/**
+ * A utility class for checking over configuration entries.
+ */
 public class ConfigSanityCheck {
   
   private static final Logger log = Logger.getLogger(ConfigSanityCheck.class);
   private static final String PREFIX = "BAD CONFIG ";
   
-  public static void validate(AccumuloConfiguration acuconf) {
-    for (Entry<String,String> entry : acuconf) {
+  /**
+   * Validates the given configuration entries.
+   *
+   * @param entries iterable through configuration keys and values
+   * @throws SanityCheckException if a fatal configuration error is found
+   */
+  public static void validate(Iterable<Entry<String,String>> entries) {
+    String instanceZkTimeoutKey = Property.INSTANCE_ZK_TIMEOUT.getKey();
+    String instanceZkTimeoutValue = null;
+    for (Entry<String,String> entry : entries) {
       String key = entry.getKey();
       String value = entry.getValue();
       Property prop = Property.getPropertyByKey(entry.getKey());
@@ -38,9 +49,16 @@ public class ConfigSanityCheck {
         fatal(PREFIX + "incomplete property key (" + key + ")");
       else if (!prop.getType().isValidFormat(value))
         fatal(PREFIX + "improperly formatted value for key (" + key + ", type=" + prop.getType() + ")");
+
+      if (key.equals(instanceZkTimeoutKey)) {
+        instanceZkTimeoutValue = value;
+      }
+    }
+
+    if (instanceZkTimeoutValue != null) {
+      checkTimeDuration(Property.INSTANCE_ZK_TIMEOUT, instanceZkTimeoutValue,
+                        new CheckTimeDurationBetween(1000, 300000));
     }
-    
-    checkTimeDuration(acuconf, Property.INSTANCE_ZK_TIMEOUT, new CheckTimeDurationBetween(1000, 300000));
   }
   
   private static interface CheckTimeDuration {
@@ -68,9 +86,9 @@ public class ConfigSanityCheck {
     }
   }
   
-  private static void checkTimeDuration(AccumuloConfiguration acuconf, Property prop, CheckTimeDuration chk) {
+  private static void checkTimeDuration(Property prop, String value, CheckTimeDuration chk) {
     verifyPropertyTypes(PropertyType.TIMEDURATION, prop);
-    if (!chk.check(acuconf.getTimeInMillis(prop)))
+    if (!chk.check(AccumuloConfiguration.getTimeInMillis(value)))
       fatal(PREFIX + chk.getDescription(prop));
   }
   
@@ -79,9 +97,19 @@ public class ConfigSanityCheck {
       if (prop.getType() != type)
         fatal("Unexpected property type (" + prop.getType() + " != " + type + ")");
   }
-  
+
+  /**
+   * The exception thrown when {@link ConfigSanityCheck#validate(Iterable)} fails.
+   */
+  public static class SanityCheckException extends RuntimeException {
+    /**
+     * Creates a new exception with the given message.
+     */
+    public SanityCheckException(String msg) { super(msg); }
+  }
+
   private static void fatal(String msg) {
     log.fatal(msg);
-    throw new RuntimeException(msg);
+    throw new SanityCheckException(msg);
   }
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7136996a/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java b/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java
index d653274..c83c754 100644
--- a/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java
+++ b/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java
@@ -23,6 +23,8 @@ import java.io.PrintStream;
 import java.io.UnsupportedEncodingException;
 import java.util.ArrayList;
 import java.util.Iterator;
+import java.util.Collections;
+import java.util.Map;
 import java.util.Map.Entry;
 import java.util.TreeMap;
 
@@ -30,32 +32,40 @@ import org.apache.accumulo.core.Constants;
 import org.apache.log4j.Logger;
 
 public class DefaultConfiguration extends AccumuloConfiguration {
-  private static DefaultConfiguration instance = null;
   private static Logger log = Logger.getLogger(DefaultConfiguration.class);
-  
-  synchronized public static DefaultConfiguration getInstance() {
-    if (instance == null) {
-      instance = new DefaultConfiguration();
-      ConfigSanityCheck.validate(instance);
+
+  private final static Map<String,String> resolvedProps;
+  static {
+    Map<String,String> m = new TreeMap<String,String>();
+    for (Property prop : Property.values()) {
+      if (!prop.isExperimental() && !prop.getType().equals(PropertyType.PREFIX)) {
+        m.put(prop.getKey(), prop.getDefaultValue());
+      }
     }
-    return instance;
+    ConfigSanityCheck.validate(m.entrySet());
+    resolvedProps = Collections.unmodifiableMap(m);
   }
-  
+
+  /**
+   * Gets a default configuration.
+   *
+   * @return default configuration
+   */
+  public static DefaultConfiguration getInstance() {
+    return new DefaultConfiguration();
+  }
+
   @Override
   public String get(Property property) {
     return property.getDefaultValue();
   }
-  
+
   @Override
   public Iterator<Entry<String,String>> iterator() {
-    TreeMap<String,String> entries = new TreeMap<String,String>();
-    for (Property prop : Property.values())
-      if (!prop.isExperimental() && !prop.getType().equals(PropertyType.PREFIX))
-        entries.put(prop.getKey(), prop.getDefaultValue());
-    
-    return entries.entrySet().iterator();
+    return resolvedProps.entrySet().iterator();
   }
   
+
   private static void generateDocumentation(PrintStream doc) {
     // read static content from resources and output
     InputStream data = DefaultConfiguration.class.getResourceAsStream("config.html");
@@ -185,5 +195,4 @@ public class DefaultConfiguration extends AccumuloConfiguration {
       throw new IllegalArgumentException("Usage: " + DefaultConfiguration.class.getName() + " --generate-doc <filename>");
     }
   }
-  
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7136996a/core/src/test/java/org/apache/accumulo/core/conf/ConfigSanityCheckTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/conf/ConfigSanityCheckTest.java b/core/src/test/java/org/apache/accumulo/core/conf/ConfigSanityCheckTest.java
new file mode 100644
index 0000000..88bbe64
--- /dev/null
+++ b/core/src/test/java/org/apache/accumulo/core/conf/ConfigSanityCheckTest.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.accumulo.core.conf;
+
+import java.util.Map;
+import org.apache.accumulo.core.conf.ConfigSanityCheck.SanityCheckException;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ConfigSanityCheckTest {
+  private Map<String,String> m;
+
+  @Before
+  public void setUp() {
+    m = new java.util.HashMap<String,String>();
+  }
+
+  @Test
+  public void testPass() {
+    m.put(Property.MASTER_CLIENTPORT.getKey(), "9999");
+    m.put(Property.MASTER_TABLET_BALANCER.getKey(), "org.apache.accumulo.server.master.balancer.TableLoadBalancer");
+    m.put(Property.MASTER_RECOVERY_MAXAGE.getKey(), "60m");
+    m.put(Property.MASTER_BULK_RETRIES.getKey(), "3");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test
+  public void testPass_Empty() {
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test
+  public void testPass_UnrecognizedValidProperty() {
+    m.put(Property.MASTER_CLIENTPORT.getKey(), "9999");
+    m.put(Property.MASTER_PREFIX.getKey() + "something", "abcdefg");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test
+  public void testPass_UnrecognizedProperty() {
+    m.put(Property.MASTER_CLIENTPORT.getKey(), "9999");
+    m.put("invalid.prefix.value", "abcdefg");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test(expected = SanityCheckException.class)
+  public void testFail_Prefix() {
+    m.put(Property.MASTER_CLIENTPORT.getKey(), "9999");
+    m.put(Property.MASTER_PREFIX.getKey(), "oops");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test(expected = SanityCheckException.class)
+  public void testFail_InvalidFormat() {
+    m.put(Property.MASTER_CLIENTPORT.getKey(), "9999");
+    m.put(Property.MASTER_RECOVERY_MAXAGE.getKey(), "60breem");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test(expected = SanityCheckException.class)
+  public void testFail_InstanceZkTimeoutOutOfRange() {
+    m.put(Property.INSTANCE_ZK_TIMEOUT.getKey(), "10ms");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7136996a/core/src/test/java/org/apache/accumulo/core/conf/DefaultConfigurationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/conf/DefaultConfigurationTest.java b/core/src/test/java/org/apache/accumulo/core/conf/DefaultConfigurationTest.java
new file mode 100644
index 0000000..9355fff
--- /dev/null
+++ b/core/src/test/java/org/apache/accumulo/core/conf/DefaultConfigurationTest.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.accumulo.core.conf;
+
+import java.util.Iterator;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+public class DefaultConfigurationTest {
+  private DefaultConfiguration c;
+
+  @Before
+  public void setUp() {
+    c = new DefaultConfiguration();
+  }
+
+  @Test
+  public void testGet() {
+    assertEquals(Property.MASTER_CLIENTPORT.getDefaultValue(), c.get(Property.MASTER_CLIENTPORT));
+  }
+
+  @Test
+  public void testGetProperties() {
+    Iterator<Map.Entry<String,String>> iter = c.iterator();
+    while (iter.hasNext()) {
+      Map.Entry<String,String> e = iter.next();
+      Property p = Property.getPropertyByKey(e.getKey());
+      assertEquals(p.getDefaultValue(), e.getValue());
+    }
+  }
+}


[6/8] git commit: ACCUMULO-3012 Improve DefaultConfiguration

Posted by bh...@apache.org.
ACCUMULO-3012 Improve DefaultConfiguration

* The internal map of resolved (default) properties is now static and immutable, making
  explicit synchronization unnecessary.
* The main method is moved to ConfigurationDocGen.
* A unit test is added.
* Accompanying changes were made to ConfigSanityCheck:
  - The validate method takes in an Iterable of entries instead of a Configuration.
  - Validation failure throws a new SanityCheckException class instead of RuntimeException.
  - A unit test is added.


Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo
Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/37f900b7
Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/37f900b7
Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/37f900b7

Branch: refs/heads/master
Commit: 37f900b7550d6ffe7b39f2ff5cd766912ab09141
Parents: 8140804
Author: Bill Havanki <bh...@cloudera.com>
Authored: Thu Jul 24 09:36:04 2014 -0400
Committer: Bill Havanki <bh...@cloudera.com>
Committed: Wed Aug 13 10:09:57 2014 -0400

----------------------------------------------------------------------
 .../accumulo/core/conf/ConfigSanityCheck.java   | 44 +++++++++--
 .../accumulo/core/conf/ConfigurationDocGen.java | 19 ++++-
 .../core/conf/DefaultConfiguration.java         | 58 ++++++--------
 .../core/conf/ConfigSanityCheckTest.java        | 79 ++++++++++++++++++++
 .../core/conf/DefaultConfigurationTest.java     | 44 +++++++++++
 docs/pom.xml                                    |  4 +-
 6 files changed, 199 insertions(+), 49 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/accumulo/blob/37f900b7/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java b/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java
index f9781f4..88d32ef 100644
--- a/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java
+++ b/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java
@@ -20,13 +20,24 @@ import java.util.Map.Entry;
 
 import org.apache.log4j.Logger;
 
+/**
+ * A utility class for checking over configuration entries.
+ */
 public class ConfigSanityCheck {
   
   private static final Logger log = Logger.getLogger(ConfigSanityCheck.class);
   private static final String PREFIX = "BAD CONFIG ";
   
-  public static void validate(AccumuloConfiguration acuconf) {
-    for (Entry<String,String> entry : acuconf) {
+  /**
+   * Validates the given configuration entries.
+   *
+   * @param entries iterable through configuration keys and values
+   * @throws SanityCheckException if a fatal configuration error is found
+   */
+  public static void validate(Iterable<Entry<String,String>> entries) {
+    String instanceZkTimeoutKey = Property.INSTANCE_ZK_TIMEOUT.getKey();
+    String instanceZkTimeoutValue = null;
+    for (Entry<String,String> entry : entries) {
       String key = entry.getKey();
       String value = entry.getValue();
       Property prop = Property.getPropertyByKey(entry.getKey());
@@ -38,9 +49,16 @@ public class ConfigSanityCheck {
         fatal(PREFIX + "incomplete property key (" + key + ")");
       else if (!prop.getType().isValidFormat(value))
         fatal(PREFIX + "improperly formatted value for key (" + key + ", type=" + prop.getType() + ")");
+
+      if (key.equals(instanceZkTimeoutKey)) {
+        instanceZkTimeoutValue = value;
+      }
+    }
+
+    if (instanceZkTimeoutValue != null) {
+      checkTimeDuration(Property.INSTANCE_ZK_TIMEOUT, instanceZkTimeoutValue,
+                        new CheckTimeDurationBetween(1000, 300000));
     }
-    
-    checkTimeDuration(acuconf, Property.INSTANCE_ZK_TIMEOUT, new CheckTimeDurationBetween(1000, 300000));
   }
   
   private interface CheckTimeDuration {
@@ -68,9 +86,9 @@ public class ConfigSanityCheck {
     }
   }
   
-  private static void checkTimeDuration(AccumuloConfiguration acuconf, Property prop, CheckTimeDuration chk) {
+  private static void checkTimeDuration(Property prop, String value, CheckTimeDuration chk) {
     verifyPropertyTypes(PropertyType.TIMEDURATION, prop);
-    if (!chk.check(acuconf.getTimeInMillis(prop)))
+    if (!chk.check(AccumuloConfiguration.getTimeInMillis(value)))
       fatal(PREFIX + chk.getDescription(prop));
   }
   
@@ -79,9 +97,19 @@ public class ConfigSanityCheck {
       if (prop.getType() != type)
         fatal("Unexpected property type (" + prop.getType() + " != " + type + ")");
   }
-  
+
+  /**
+   * The exception thrown when {@link ConfigSanityCheck#validate(Iterable)} fails.
+   */
+  public static class SanityCheckException extends RuntimeException {
+    /**
+     * Creates a new exception with the given message.
+     */
+    public SanityCheckException(String msg) { super(msg); }
+  }
+
   private static void fatal(String msg) {
     log.fatal(msg);
-    throw new RuntimeException(msg);
+    throw new SanityCheckException(msg);
   }
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/37f900b7/core/src/main/java/org/apache/accumulo/core/conf/ConfigurationDocGen.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/conf/ConfigurationDocGen.java b/core/src/main/java/org/apache/accumulo/core/conf/ConfigurationDocGen.java
index ca57372..41a1f3b 100644
--- a/core/src/main/java/org/apache/accumulo/core/conf/ConfigurationDocGen.java
+++ b/core/src/main/java/org/apache/accumulo/core/conf/ConfigurationDocGen.java
@@ -16,9 +16,11 @@
  */
 package org.apache.accumulo.core.conf;
 
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
 import java.util.ArrayList;
 import java.util.TreeMap;
 
@@ -277,7 +279,7 @@ class ConfigurationDocGen {
     }
   }
 
-  private static Logger log = Logger.getLogger(DefaultConfiguration.class);
+  private static Logger log = Logger.getLogger(ConfigurationDocGen.class);
 
   private PrintStream doc;
 
@@ -302,7 +304,7 @@ class ConfigurationDocGen {
   }
 
   private void appendResource(String resourceName) {
-    InputStream data = DefaultConfiguration.class.getResourceAsStream(resourceName);
+    InputStream data = ConfigurationDocGen.class.getResourceAsStream(resourceName);
     if (data != null) {
       byte[] buffer = new byte[1024];
       int n;
@@ -338,4 +340,17 @@ class ConfigurationDocGen {
     new LaTeX().generate();
   }
 
+  /*
+   * Generate documentation for conf/accumulo-site.xml file usage
+   */
+  public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
+    if (args.length == 2 && args[0].equals("--generate-html")) {
+      new ConfigurationDocGen(new PrintStream(args[1], Constants.UTF8.name())).generateHtml();
+    } else if (args.length == 2 && args[0].equals("--generate-latex")) {
+      new ConfigurationDocGen(new PrintStream(args[1], Constants.UTF8.name())).generateLaTeX();
+    } else {
+      throw new IllegalArgumentException("Usage: " + ConfigurationDocGen.class.getName() + " --generate-html <filename> | --generate-latex <filename>");
+    }
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/37f900b7/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java b/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java
index 44e198a..6e1b779 100644
--- a/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java
+++ b/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java
@@ -16,9 +16,7 @@
  */
 package org.apache.accumulo.core.conf;
 
-import java.io.FileNotFoundException;
-import java.io.PrintStream;
-import java.io.UnsupportedEncodingException;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -26,51 +24,37 @@ import java.util.Map.Entry;
 import org.apache.accumulo.core.Constants;
 
 public class DefaultConfiguration extends AccumuloConfiguration {
-  private static DefaultConfiguration instance = null;
-  private Map<String,String> resolvedProps = null;
-
-  synchronized public static DefaultConfiguration getInstance() {
-    if (instance == null) {
-      instance = new DefaultConfiguration();
-      ConfigSanityCheck.validate(instance);
+  private final static Map<String,String> resolvedProps;
+  static {
+    Map<String, String> m = new HashMap<String,String>();
+    for (Property prop : Property.values()) {
+      if (!prop.getType().equals(PropertyType.PREFIX)) {
+        m.put(prop.getKey(), prop.getDefaultValue());
+      }
     }
-    return instance;
+    ConfigSanityCheck.validate(m.entrySet());
+    resolvedProps = Collections.unmodifiableMap(m);
   }
 
-  @Override
-  public String get(Property property) {
-    return getResolvedProps().get(property.getKey());
+  /**
+   * Gets a default configuration.
+   *
+   * @return default configuration
+   */
+  public static DefaultConfiguration getInstance() {
+    return new DefaultConfiguration();
   }
 
-  private synchronized Map<String,String> getResolvedProps() {
-    if (resolvedProps == null) {
-      // the following loop is super slow, it takes a few milliseconds, so cache it
-      resolvedProps = new HashMap<String,String>();
-      for (Property prop : Property.values())
-        if (!prop.getType().equals(PropertyType.PREFIX))
-          resolvedProps.put(prop.getKey(), prop.getDefaultValue());
-    }
-    return resolvedProps;
+  @Override
+  public String get(Property property) {
+    return resolvedProps.get(property.getKey());
   }
 
   @Override
   public void getProperties(Map<String,String> props, PropertyFilter filter) {
-    for (Entry<String,String> entry : getResolvedProps().entrySet())
+    for (Entry<String,String> entry : resolvedProps.entrySet())
       if (filter.accept(entry.getKey()))
         props.put(entry.getKey(), entry.getValue());
   }
 
-  /*
-   * Generate documentation for conf/accumulo-site.xml file usage
-   */
-  public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
-    if (args.length == 2 && args[0].equals("--generate-html")) {
-      new ConfigurationDocGen(new PrintStream(args[1], Constants.UTF8.name())).generateHtml();
-    } else if (args.length == 2 && args[0].equals("--generate-latex")) {
-      new ConfigurationDocGen(new PrintStream(args[1], Constants.UTF8.name())).generateLaTeX();
-    } else {
-      throw new IllegalArgumentException("Usage: " + DefaultConfiguration.class.getName() + " --generate-html <filename> | --generate-latex <filename>");
-    }
-  }
-
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/37f900b7/core/src/test/java/org/apache/accumulo/core/conf/ConfigSanityCheckTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/conf/ConfigSanityCheckTest.java b/core/src/test/java/org/apache/accumulo/core/conf/ConfigSanityCheckTest.java
new file mode 100644
index 0000000..88bbe64
--- /dev/null
+++ b/core/src/test/java/org/apache/accumulo/core/conf/ConfigSanityCheckTest.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.accumulo.core.conf;
+
+import java.util.Map;
+import org.apache.accumulo.core.conf.ConfigSanityCheck.SanityCheckException;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ConfigSanityCheckTest {
+  private Map<String,String> m;
+
+  @Before
+  public void setUp() {
+    m = new java.util.HashMap<String,String>();
+  }
+
+  @Test
+  public void testPass() {
+    m.put(Property.MASTER_CLIENTPORT.getKey(), "9999");
+    m.put(Property.MASTER_TABLET_BALANCER.getKey(), "org.apache.accumulo.server.master.balancer.TableLoadBalancer");
+    m.put(Property.MASTER_RECOVERY_MAXAGE.getKey(), "60m");
+    m.put(Property.MASTER_BULK_RETRIES.getKey(), "3");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test
+  public void testPass_Empty() {
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test
+  public void testPass_UnrecognizedValidProperty() {
+    m.put(Property.MASTER_CLIENTPORT.getKey(), "9999");
+    m.put(Property.MASTER_PREFIX.getKey() + "something", "abcdefg");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test
+  public void testPass_UnrecognizedProperty() {
+    m.put(Property.MASTER_CLIENTPORT.getKey(), "9999");
+    m.put("invalid.prefix.value", "abcdefg");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test(expected = SanityCheckException.class)
+  public void testFail_Prefix() {
+    m.put(Property.MASTER_CLIENTPORT.getKey(), "9999");
+    m.put(Property.MASTER_PREFIX.getKey(), "oops");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test(expected = SanityCheckException.class)
+  public void testFail_InvalidFormat() {
+    m.put(Property.MASTER_CLIENTPORT.getKey(), "9999");
+    m.put(Property.MASTER_RECOVERY_MAXAGE.getKey(), "60breem");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test(expected = SanityCheckException.class)
+  public void testFail_InstanceZkTimeoutOutOfRange() {
+    m.put(Property.INSTANCE_ZK_TIMEOUT.getKey(), "10ms");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/37f900b7/core/src/test/java/org/apache/accumulo/core/conf/DefaultConfigurationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/conf/DefaultConfigurationTest.java b/core/src/test/java/org/apache/accumulo/core/conf/DefaultConfigurationTest.java
new file mode 100644
index 0000000..beb63a7
--- /dev/null
+++ b/core/src/test/java/org/apache/accumulo/core/conf/DefaultConfigurationTest.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.accumulo.core.conf;
+
+import org.apache.accumulo.core.conf.AccumuloConfiguration.AllFilter;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+public class DefaultConfigurationTest {
+  private DefaultConfiguration c;
+
+  @Before
+  public void setUp() {
+    c = new DefaultConfiguration();
+  }
+
+  @Test
+  public void testGet() {
+    assertEquals(Property.MASTER_CLIENTPORT.getDefaultValue(), c.get(Property.MASTER_CLIENTPORT));
+  }
+
+  @Test
+  public void testGetProperties() {
+    Map<String,String> p = new java.util.HashMap<String,String>();
+    c.getProperties(p, new AllFilter());
+    assertEquals(Property.MASTER_CLIENTPORT.getDefaultValue(), p.get(Property.MASTER_CLIENTPORT.getKey()));
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/37f900b7/docs/pom.xml
----------------------------------------------------------------------
diff --git a/docs/pom.xml b/docs/pom.xml
index d54b144..a6260c6 100644
--- a/docs/pom.xml
+++ b/docs/pom.xml
@@ -62,7 +62,7 @@
                 </goals>
                 <phase>compile</phase>
                 <configuration>
-                  <mainClass>org.apache.accumulo.core.conf.DefaultConfiguration</mainClass>
+                  <mainClass>org.apache.accumulo.core.conf.ConfigurationDocGen</mainClass>
                   <classpathScope>compile</classpathScope>
                   <arguments>
                     <argument>--generate-html</argument>
@@ -77,7 +77,7 @@
                 </goals>
                 <phase>compile</phase>
                 <configuration>
-                  <mainClass>org.apache.accumulo.core.conf.DefaultConfiguration</mainClass>
+                  <mainClass>org.apache.accumulo.core.conf.ConfigurationDocGen</mainClass>
                   <classpathScope>compile</classpathScope>
                   <arguments>
                     <argument>--generate-latex</argument>


[7/8] git commit: ACCUMULO-3012 Improve DefaultConfiguration

Posted by bh...@apache.org.
ACCUMULO-3012 Improve DefaultConfiguration

* The internal map of resolved (default) properties is now static and immutable, making
  explicit synchronization unnecessary.
* The main method is moved to ConfigurationDocGen.
* A unit test is added.
* Accompanying changes were made to ConfigSanityCheck:
  - The validate method takes in an Iterable of entries instead of a Configuration.
  - Validation failure throws a new SanityCheckException class instead of RuntimeException.
  - A unit test is added.


Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo
Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/37f900b7
Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/37f900b7
Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/37f900b7

Branch: refs/heads/1.6.1-SNAPSHOT
Commit: 37f900b7550d6ffe7b39f2ff5cd766912ab09141
Parents: 8140804
Author: Bill Havanki <bh...@cloudera.com>
Authored: Thu Jul 24 09:36:04 2014 -0400
Committer: Bill Havanki <bh...@cloudera.com>
Committed: Wed Aug 13 10:09:57 2014 -0400

----------------------------------------------------------------------
 .../accumulo/core/conf/ConfigSanityCheck.java   | 44 +++++++++--
 .../accumulo/core/conf/ConfigurationDocGen.java | 19 ++++-
 .../core/conf/DefaultConfiguration.java         | 58 ++++++--------
 .../core/conf/ConfigSanityCheckTest.java        | 79 ++++++++++++++++++++
 .../core/conf/DefaultConfigurationTest.java     | 44 +++++++++++
 docs/pom.xml                                    |  4 +-
 6 files changed, 199 insertions(+), 49 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/accumulo/blob/37f900b7/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java b/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java
index f9781f4..88d32ef 100644
--- a/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java
+++ b/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java
@@ -20,13 +20,24 @@ import java.util.Map.Entry;
 
 import org.apache.log4j.Logger;
 
+/**
+ * A utility class for checking over configuration entries.
+ */
 public class ConfigSanityCheck {
   
   private static final Logger log = Logger.getLogger(ConfigSanityCheck.class);
   private static final String PREFIX = "BAD CONFIG ";
   
-  public static void validate(AccumuloConfiguration acuconf) {
-    for (Entry<String,String> entry : acuconf) {
+  /**
+   * Validates the given configuration entries.
+   *
+   * @param entries iterable through configuration keys and values
+   * @throws SanityCheckException if a fatal configuration error is found
+   */
+  public static void validate(Iterable<Entry<String,String>> entries) {
+    String instanceZkTimeoutKey = Property.INSTANCE_ZK_TIMEOUT.getKey();
+    String instanceZkTimeoutValue = null;
+    for (Entry<String,String> entry : entries) {
       String key = entry.getKey();
       String value = entry.getValue();
       Property prop = Property.getPropertyByKey(entry.getKey());
@@ -38,9 +49,16 @@ public class ConfigSanityCheck {
         fatal(PREFIX + "incomplete property key (" + key + ")");
       else if (!prop.getType().isValidFormat(value))
         fatal(PREFIX + "improperly formatted value for key (" + key + ", type=" + prop.getType() + ")");
+
+      if (key.equals(instanceZkTimeoutKey)) {
+        instanceZkTimeoutValue = value;
+      }
+    }
+
+    if (instanceZkTimeoutValue != null) {
+      checkTimeDuration(Property.INSTANCE_ZK_TIMEOUT, instanceZkTimeoutValue,
+                        new CheckTimeDurationBetween(1000, 300000));
     }
-    
-    checkTimeDuration(acuconf, Property.INSTANCE_ZK_TIMEOUT, new CheckTimeDurationBetween(1000, 300000));
   }
   
   private interface CheckTimeDuration {
@@ -68,9 +86,9 @@ public class ConfigSanityCheck {
     }
   }
   
-  private static void checkTimeDuration(AccumuloConfiguration acuconf, Property prop, CheckTimeDuration chk) {
+  private static void checkTimeDuration(Property prop, String value, CheckTimeDuration chk) {
     verifyPropertyTypes(PropertyType.TIMEDURATION, prop);
-    if (!chk.check(acuconf.getTimeInMillis(prop)))
+    if (!chk.check(AccumuloConfiguration.getTimeInMillis(value)))
       fatal(PREFIX + chk.getDescription(prop));
   }
   
@@ -79,9 +97,19 @@ public class ConfigSanityCheck {
       if (prop.getType() != type)
         fatal("Unexpected property type (" + prop.getType() + " != " + type + ")");
   }
-  
+
+  /**
+   * The exception thrown when {@link ConfigSanityCheck#validate(Iterable)} fails.
+   */
+  public static class SanityCheckException extends RuntimeException {
+    /**
+     * Creates a new exception with the given message.
+     */
+    public SanityCheckException(String msg) { super(msg); }
+  }
+
   private static void fatal(String msg) {
     log.fatal(msg);
-    throw new RuntimeException(msg);
+    throw new SanityCheckException(msg);
   }
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/37f900b7/core/src/main/java/org/apache/accumulo/core/conf/ConfigurationDocGen.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/conf/ConfigurationDocGen.java b/core/src/main/java/org/apache/accumulo/core/conf/ConfigurationDocGen.java
index ca57372..41a1f3b 100644
--- a/core/src/main/java/org/apache/accumulo/core/conf/ConfigurationDocGen.java
+++ b/core/src/main/java/org/apache/accumulo/core/conf/ConfigurationDocGen.java
@@ -16,9 +16,11 @@
  */
 package org.apache.accumulo.core.conf;
 
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
 import java.util.ArrayList;
 import java.util.TreeMap;
 
@@ -277,7 +279,7 @@ class ConfigurationDocGen {
     }
   }
 
-  private static Logger log = Logger.getLogger(DefaultConfiguration.class);
+  private static Logger log = Logger.getLogger(ConfigurationDocGen.class);
 
   private PrintStream doc;
 
@@ -302,7 +304,7 @@ class ConfigurationDocGen {
   }
 
   private void appendResource(String resourceName) {
-    InputStream data = DefaultConfiguration.class.getResourceAsStream(resourceName);
+    InputStream data = ConfigurationDocGen.class.getResourceAsStream(resourceName);
     if (data != null) {
       byte[] buffer = new byte[1024];
       int n;
@@ -338,4 +340,17 @@ class ConfigurationDocGen {
     new LaTeX().generate();
   }
 
+  /*
+   * Generate documentation for conf/accumulo-site.xml file usage
+   */
+  public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
+    if (args.length == 2 && args[0].equals("--generate-html")) {
+      new ConfigurationDocGen(new PrintStream(args[1], Constants.UTF8.name())).generateHtml();
+    } else if (args.length == 2 && args[0].equals("--generate-latex")) {
+      new ConfigurationDocGen(new PrintStream(args[1], Constants.UTF8.name())).generateLaTeX();
+    } else {
+      throw new IllegalArgumentException("Usage: " + ConfigurationDocGen.class.getName() + " --generate-html <filename> | --generate-latex <filename>");
+    }
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/37f900b7/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java b/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java
index 44e198a..6e1b779 100644
--- a/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java
+++ b/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java
@@ -16,9 +16,7 @@
  */
 package org.apache.accumulo.core.conf;
 
-import java.io.FileNotFoundException;
-import java.io.PrintStream;
-import java.io.UnsupportedEncodingException;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -26,51 +24,37 @@ import java.util.Map.Entry;
 import org.apache.accumulo.core.Constants;
 
 public class DefaultConfiguration extends AccumuloConfiguration {
-  private static DefaultConfiguration instance = null;
-  private Map<String,String> resolvedProps = null;
-
-  synchronized public static DefaultConfiguration getInstance() {
-    if (instance == null) {
-      instance = new DefaultConfiguration();
-      ConfigSanityCheck.validate(instance);
+  private final static Map<String,String> resolvedProps;
+  static {
+    Map<String, String> m = new HashMap<String,String>();
+    for (Property prop : Property.values()) {
+      if (!prop.getType().equals(PropertyType.PREFIX)) {
+        m.put(prop.getKey(), prop.getDefaultValue());
+      }
     }
-    return instance;
+    ConfigSanityCheck.validate(m.entrySet());
+    resolvedProps = Collections.unmodifiableMap(m);
   }
 
-  @Override
-  public String get(Property property) {
-    return getResolvedProps().get(property.getKey());
+  /**
+   * Gets a default configuration.
+   *
+   * @return default configuration
+   */
+  public static DefaultConfiguration getInstance() {
+    return new DefaultConfiguration();
   }
 
-  private synchronized Map<String,String> getResolvedProps() {
-    if (resolvedProps == null) {
-      // the following loop is super slow, it takes a few milliseconds, so cache it
-      resolvedProps = new HashMap<String,String>();
-      for (Property prop : Property.values())
-        if (!prop.getType().equals(PropertyType.PREFIX))
-          resolvedProps.put(prop.getKey(), prop.getDefaultValue());
-    }
-    return resolvedProps;
+  @Override
+  public String get(Property property) {
+    return resolvedProps.get(property.getKey());
   }
 
   @Override
   public void getProperties(Map<String,String> props, PropertyFilter filter) {
-    for (Entry<String,String> entry : getResolvedProps().entrySet())
+    for (Entry<String,String> entry : resolvedProps.entrySet())
       if (filter.accept(entry.getKey()))
         props.put(entry.getKey(), entry.getValue());
   }
 
-  /*
-   * Generate documentation for conf/accumulo-site.xml file usage
-   */
-  public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
-    if (args.length == 2 && args[0].equals("--generate-html")) {
-      new ConfigurationDocGen(new PrintStream(args[1], Constants.UTF8.name())).generateHtml();
-    } else if (args.length == 2 && args[0].equals("--generate-latex")) {
-      new ConfigurationDocGen(new PrintStream(args[1], Constants.UTF8.name())).generateLaTeX();
-    } else {
-      throw new IllegalArgumentException("Usage: " + DefaultConfiguration.class.getName() + " --generate-html <filename> | --generate-latex <filename>");
-    }
-  }
-
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/37f900b7/core/src/test/java/org/apache/accumulo/core/conf/ConfigSanityCheckTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/conf/ConfigSanityCheckTest.java b/core/src/test/java/org/apache/accumulo/core/conf/ConfigSanityCheckTest.java
new file mode 100644
index 0000000..88bbe64
--- /dev/null
+++ b/core/src/test/java/org/apache/accumulo/core/conf/ConfigSanityCheckTest.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.accumulo.core.conf;
+
+import java.util.Map;
+import org.apache.accumulo.core.conf.ConfigSanityCheck.SanityCheckException;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ConfigSanityCheckTest {
+  private Map<String,String> m;
+
+  @Before
+  public void setUp() {
+    m = new java.util.HashMap<String,String>();
+  }
+
+  @Test
+  public void testPass() {
+    m.put(Property.MASTER_CLIENTPORT.getKey(), "9999");
+    m.put(Property.MASTER_TABLET_BALANCER.getKey(), "org.apache.accumulo.server.master.balancer.TableLoadBalancer");
+    m.put(Property.MASTER_RECOVERY_MAXAGE.getKey(), "60m");
+    m.put(Property.MASTER_BULK_RETRIES.getKey(), "3");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test
+  public void testPass_Empty() {
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test
+  public void testPass_UnrecognizedValidProperty() {
+    m.put(Property.MASTER_CLIENTPORT.getKey(), "9999");
+    m.put(Property.MASTER_PREFIX.getKey() + "something", "abcdefg");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test
+  public void testPass_UnrecognizedProperty() {
+    m.put(Property.MASTER_CLIENTPORT.getKey(), "9999");
+    m.put("invalid.prefix.value", "abcdefg");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test(expected = SanityCheckException.class)
+  public void testFail_Prefix() {
+    m.put(Property.MASTER_CLIENTPORT.getKey(), "9999");
+    m.put(Property.MASTER_PREFIX.getKey(), "oops");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test(expected = SanityCheckException.class)
+  public void testFail_InvalidFormat() {
+    m.put(Property.MASTER_CLIENTPORT.getKey(), "9999");
+    m.put(Property.MASTER_RECOVERY_MAXAGE.getKey(), "60breem");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test(expected = SanityCheckException.class)
+  public void testFail_InstanceZkTimeoutOutOfRange() {
+    m.put(Property.INSTANCE_ZK_TIMEOUT.getKey(), "10ms");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/37f900b7/core/src/test/java/org/apache/accumulo/core/conf/DefaultConfigurationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/conf/DefaultConfigurationTest.java b/core/src/test/java/org/apache/accumulo/core/conf/DefaultConfigurationTest.java
new file mode 100644
index 0000000..beb63a7
--- /dev/null
+++ b/core/src/test/java/org/apache/accumulo/core/conf/DefaultConfigurationTest.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.accumulo.core.conf;
+
+import org.apache.accumulo.core.conf.AccumuloConfiguration.AllFilter;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+public class DefaultConfigurationTest {
+  private DefaultConfiguration c;
+
+  @Before
+  public void setUp() {
+    c = new DefaultConfiguration();
+  }
+
+  @Test
+  public void testGet() {
+    assertEquals(Property.MASTER_CLIENTPORT.getDefaultValue(), c.get(Property.MASTER_CLIENTPORT));
+  }
+
+  @Test
+  public void testGetProperties() {
+    Map<String,String> p = new java.util.HashMap<String,String>();
+    c.getProperties(p, new AllFilter());
+    assertEquals(Property.MASTER_CLIENTPORT.getDefaultValue(), p.get(Property.MASTER_CLIENTPORT.getKey()));
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/37f900b7/docs/pom.xml
----------------------------------------------------------------------
diff --git a/docs/pom.xml b/docs/pom.xml
index d54b144..a6260c6 100644
--- a/docs/pom.xml
+++ b/docs/pom.xml
@@ -62,7 +62,7 @@
                 </goals>
                 <phase>compile</phase>
                 <configuration>
-                  <mainClass>org.apache.accumulo.core.conf.DefaultConfiguration</mainClass>
+                  <mainClass>org.apache.accumulo.core.conf.ConfigurationDocGen</mainClass>
                   <classpathScope>compile</classpathScope>
                   <arguments>
                     <argument>--generate-html</argument>
@@ -77,7 +77,7 @@
                 </goals>
                 <phase>compile</phase>
                 <configuration>
-                  <mainClass>org.apache.accumulo.core.conf.DefaultConfiguration</mainClass>
+                  <mainClass>org.apache.accumulo.core.conf.ConfigurationDocGen</mainClass>
                   <classpathScope>compile</classpathScope>
                   <arguments>
                     <argument>--generate-latex</argument>


[2/8] git commit: ACCUMULO-3012 Improve DefaultConfiguration

Posted by bh...@apache.org.
ACCUMULO-3012 Improve DefaultConfiguration

* The map of default properties created during the iterator() method each time is now
  static and immutable.
* A unit test is added.
* Accompanying changes were made to ConfigSanityCheck:
  - The validate method takes in an Iterable of entries instead of a Configuration.
  - Validation failure throws a new SanityCheckException class instead of RuntimeException.
  - A unit test is added.


Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo
Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/7136996a
Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/7136996a
Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/7136996a

Branch: refs/heads/1.6.1-SNAPSHOT
Commit: 7136996a19406a7dfc5c2f2c5861cae95f68badc
Parents: c4d46bb
Author: Bill Havanki <bh...@cloudera.com>
Authored: Thu Jul 24 09:36:04 2014 -0400
Committer: Bill Havanki <bh...@cloudera.com>
Committed: Wed Aug 13 09:30:04 2014 -0400

----------------------------------------------------------------------
 .../accumulo/core/conf/ConfigSanityCheck.java   | 44 +++++++++--
 .../core/conf/DefaultConfiguration.java         | 41 ++++++----
 .../core/conf/ConfigSanityCheckTest.java        | 79 ++++++++++++++++++++
 .../core/conf/DefaultConfigurationTest.java     | 47 ++++++++++++
 4 files changed, 187 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/accumulo/blob/7136996a/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java b/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java
index 6724670..abec58b 100644
--- a/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java
+++ b/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java
@@ -20,13 +20,24 @@ import java.util.Map.Entry;
 
 import org.apache.log4j.Logger;
 
+/**
+ * A utility class for checking over configuration entries.
+ */
 public class ConfigSanityCheck {
   
   private static final Logger log = Logger.getLogger(ConfigSanityCheck.class);
   private static final String PREFIX = "BAD CONFIG ";
   
-  public static void validate(AccumuloConfiguration acuconf) {
-    for (Entry<String,String> entry : acuconf) {
+  /**
+   * Validates the given configuration entries.
+   *
+   * @param entries iterable through configuration keys and values
+   * @throws SanityCheckException if a fatal configuration error is found
+   */
+  public static void validate(Iterable<Entry<String,String>> entries) {
+    String instanceZkTimeoutKey = Property.INSTANCE_ZK_TIMEOUT.getKey();
+    String instanceZkTimeoutValue = null;
+    for (Entry<String,String> entry : entries) {
       String key = entry.getKey();
       String value = entry.getValue();
       Property prop = Property.getPropertyByKey(entry.getKey());
@@ -38,9 +49,16 @@ public class ConfigSanityCheck {
         fatal(PREFIX + "incomplete property key (" + key + ")");
       else if (!prop.getType().isValidFormat(value))
         fatal(PREFIX + "improperly formatted value for key (" + key + ", type=" + prop.getType() + ")");
+
+      if (key.equals(instanceZkTimeoutKey)) {
+        instanceZkTimeoutValue = value;
+      }
+    }
+
+    if (instanceZkTimeoutValue != null) {
+      checkTimeDuration(Property.INSTANCE_ZK_TIMEOUT, instanceZkTimeoutValue,
+                        new CheckTimeDurationBetween(1000, 300000));
     }
-    
-    checkTimeDuration(acuconf, Property.INSTANCE_ZK_TIMEOUT, new CheckTimeDurationBetween(1000, 300000));
   }
   
   private static interface CheckTimeDuration {
@@ -68,9 +86,9 @@ public class ConfigSanityCheck {
     }
   }
   
-  private static void checkTimeDuration(AccumuloConfiguration acuconf, Property prop, CheckTimeDuration chk) {
+  private static void checkTimeDuration(Property prop, String value, CheckTimeDuration chk) {
     verifyPropertyTypes(PropertyType.TIMEDURATION, prop);
-    if (!chk.check(acuconf.getTimeInMillis(prop)))
+    if (!chk.check(AccumuloConfiguration.getTimeInMillis(value)))
       fatal(PREFIX + chk.getDescription(prop));
   }
   
@@ -79,9 +97,19 @@ public class ConfigSanityCheck {
       if (prop.getType() != type)
         fatal("Unexpected property type (" + prop.getType() + " != " + type + ")");
   }
-  
+
+  /**
+   * The exception thrown when {@link ConfigSanityCheck#validate(Iterable)} fails.
+   */
+  public static class SanityCheckException extends RuntimeException {
+    /**
+     * Creates a new exception with the given message.
+     */
+    public SanityCheckException(String msg) { super(msg); }
+  }
+
   private static void fatal(String msg) {
     log.fatal(msg);
-    throw new RuntimeException(msg);
+    throw new SanityCheckException(msg);
   }
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7136996a/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java b/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java
index d653274..c83c754 100644
--- a/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java
+++ b/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java
@@ -23,6 +23,8 @@ import java.io.PrintStream;
 import java.io.UnsupportedEncodingException;
 import java.util.ArrayList;
 import java.util.Iterator;
+import java.util.Collections;
+import java.util.Map;
 import java.util.Map.Entry;
 import java.util.TreeMap;
 
@@ -30,32 +32,40 @@ import org.apache.accumulo.core.Constants;
 import org.apache.log4j.Logger;
 
 public class DefaultConfiguration extends AccumuloConfiguration {
-  private static DefaultConfiguration instance = null;
   private static Logger log = Logger.getLogger(DefaultConfiguration.class);
-  
-  synchronized public static DefaultConfiguration getInstance() {
-    if (instance == null) {
-      instance = new DefaultConfiguration();
-      ConfigSanityCheck.validate(instance);
+
+  private final static Map<String,String> resolvedProps;
+  static {
+    Map<String,String> m = new TreeMap<String,String>();
+    for (Property prop : Property.values()) {
+      if (!prop.isExperimental() && !prop.getType().equals(PropertyType.PREFIX)) {
+        m.put(prop.getKey(), prop.getDefaultValue());
+      }
     }
-    return instance;
+    ConfigSanityCheck.validate(m.entrySet());
+    resolvedProps = Collections.unmodifiableMap(m);
   }
-  
+
+  /**
+   * Gets a default configuration.
+   *
+   * @return default configuration
+   */
+  public static DefaultConfiguration getInstance() {
+    return new DefaultConfiguration();
+  }
+
   @Override
   public String get(Property property) {
     return property.getDefaultValue();
   }
-  
+
   @Override
   public Iterator<Entry<String,String>> iterator() {
-    TreeMap<String,String> entries = new TreeMap<String,String>();
-    for (Property prop : Property.values())
-      if (!prop.isExperimental() && !prop.getType().equals(PropertyType.PREFIX))
-        entries.put(prop.getKey(), prop.getDefaultValue());
-    
-    return entries.entrySet().iterator();
+    return resolvedProps.entrySet().iterator();
   }
   
+
   private static void generateDocumentation(PrintStream doc) {
     // read static content from resources and output
     InputStream data = DefaultConfiguration.class.getResourceAsStream("config.html");
@@ -185,5 +195,4 @@ public class DefaultConfiguration extends AccumuloConfiguration {
       throw new IllegalArgumentException("Usage: " + DefaultConfiguration.class.getName() + " --generate-doc <filename>");
     }
   }
-  
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7136996a/core/src/test/java/org/apache/accumulo/core/conf/ConfigSanityCheckTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/conf/ConfigSanityCheckTest.java b/core/src/test/java/org/apache/accumulo/core/conf/ConfigSanityCheckTest.java
new file mode 100644
index 0000000..88bbe64
--- /dev/null
+++ b/core/src/test/java/org/apache/accumulo/core/conf/ConfigSanityCheckTest.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.accumulo.core.conf;
+
+import java.util.Map;
+import org.apache.accumulo.core.conf.ConfigSanityCheck.SanityCheckException;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ConfigSanityCheckTest {
+  private Map<String,String> m;
+
+  @Before
+  public void setUp() {
+    m = new java.util.HashMap<String,String>();
+  }
+
+  @Test
+  public void testPass() {
+    m.put(Property.MASTER_CLIENTPORT.getKey(), "9999");
+    m.put(Property.MASTER_TABLET_BALANCER.getKey(), "org.apache.accumulo.server.master.balancer.TableLoadBalancer");
+    m.put(Property.MASTER_RECOVERY_MAXAGE.getKey(), "60m");
+    m.put(Property.MASTER_BULK_RETRIES.getKey(), "3");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test
+  public void testPass_Empty() {
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test
+  public void testPass_UnrecognizedValidProperty() {
+    m.put(Property.MASTER_CLIENTPORT.getKey(), "9999");
+    m.put(Property.MASTER_PREFIX.getKey() + "something", "abcdefg");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test
+  public void testPass_UnrecognizedProperty() {
+    m.put(Property.MASTER_CLIENTPORT.getKey(), "9999");
+    m.put("invalid.prefix.value", "abcdefg");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test(expected = SanityCheckException.class)
+  public void testFail_Prefix() {
+    m.put(Property.MASTER_CLIENTPORT.getKey(), "9999");
+    m.put(Property.MASTER_PREFIX.getKey(), "oops");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test(expected = SanityCheckException.class)
+  public void testFail_InvalidFormat() {
+    m.put(Property.MASTER_CLIENTPORT.getKey(), "9999");
+    m.put(Property.MASTER_RECOVERY_MAXAGE.getKey(), "60breem");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test(expected = SanityCheckException.class)
+  public void testFail_InstanceZkTimeoutOutOfRange() {
+    m.put(Property.INSTANCE_ZK_TIMEOUT.getKey(), "10ms");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7136996a/core/src/test/java/org/apache/accumulo/core/conf/DefaultConfigurationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/conf/DefaultConfigurationTest.java b/core/src/test/java/org/apache/accumulo/core/conf/DefaultConfigurationTest.java
new file mode 100644
index 0000000..9355fff
--- /dev/null
+++ b/core/src/test/java/org/apache/accumulo/core/conf/DefaultConfigurationTest.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.accumulo.core.conf;
+
+import java.util.Iterator;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+public class DefaultConfigurationTest {
+  private DefaultConfiguration c;
+
+  @Before
+  public void setUp() {
+    c = new DefaultConfiguration();
+  }
+
+  @Test
+  public void testGet() {
+    assertEquals(Property.MASTER_CLIENTPORT.getDefaultValue(), c.get(Property.MASTER_CLIENTPORT));
+  }
+
+  @Test
+  public void testGetProperties() {
+    Iterator<Map.Entry<String,String>> iter = c.iterator();
+    while (iter.hasNext()) {
+      Map.Entry<String,String> e = iter.next();
+      Property p = Property.getPropertyByKey(e.getKey());
+      assertEquals(p.getDefaultValue(), e.getValue());
+    }
+  }
+}


[8/8] git commit: Merge branch '1.6.1-SNAPSHOT'

Posted by bh...@apache.org.
Merge branch '1.6.1-SNAPSHOT'

Conflicts:
	core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java
	core/src/main/java/org/apache/accumulo/core/conf/ConfigurationDocGen.java
	core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java


Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo
Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/c6ed57ed
Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/c6ed57ed
Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/c6ed57ed

Branch: refs/heads/master
Commit: c6ed57ed8f68ba99dfe54bbb7a36f85a4baa59b5
Parents: b8271d4 37f900b
Author: Bill Havanki <bh...@cloudera.com>
Authored: Wed Aug 13 10:48:05 2014 -0400
Committer: Bill Havanki <bh...@cloudera.com>
Committed: Wed Aug 13 10:48:05 2014 -0400

----------------------------------------------------------------------
 .../accumulo/core/conf/ConfigSanityCheck.java   | 41 +++++++---
 .../accumulo/core/conf/ConfigurationDocGen.java | 23 +++++-
 .../core/conf/DefaultConfiguration.java         | 62 +++++----------
 .../core/conf/ConfigSanityCheckTest.java        | 79 ++++++++++++++++++++
 .../core/conf/DefaultConfigurationTest.java     | 44 +++++++++++
 docs/pom.xml                                    |  4 +-
 6 files changed, 193 insertions(+), 60 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/accumulo/blob/c6ed57ed/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java
----------------------------------------------------------------------
diff --cc core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java
index 1fb035c,88d32ef..4bda600
--- a/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java
+++ b/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java
@@@ -29,17 -29,15 +29,19 @@@ public class ConfigSanityCheck 
    private static final String PREFIX = "BAD CONFIG ";
    
    /**
-    * Validates the given configuration. A valid configuration contains only
 -   * Validates the given configuration entries.
++   * Validates the given configuration entries. A valid configuration contains only
 +   * valid properties (i.e., defined or otherwise valid) that are not prefixes
 +   * and whose values are formatted correctly for their property types. A valid
 +   * configuration also contains a value for property
 +   * {@link Property#INSTANCE_ZK_TIMEOUT} within a valid range.
     *
-    * @param acuconf configuration
-    * @throws RuntimeException if the configuration fails validation
+    * @param entries iterable through configuration keys and values
+    * @throws SanityCheckException if a fatal configuration error is found
     */
-   public static void validate(AccumuloConfiguration acuconf) {
-     for (Entry<String,String> entry : acuconf) {
+   public static void validate(Iterable<Entry<String,String>> entries) {
+     String instanceZkTimeoutKey = Property.INSTANCE_ZK_TIMEOUT.getKey();
+     String instanceZkTimeoutValue = null;
+     for (Entry<String,String> entry : entries) {
        String key = entry.getKey();
        String value = entry.getValue();
        Property prop = Property.getPropertyByKey(entry.getKey());

http://git-wip-us.apache.org/repos/asf/accumulo/blob/c6ed57ed/core/src/main/java/org/apache/accumulo/core/conf/ConfigurationDocGen.java
----------------------------------------------------------------------
diff --cc core/src/main/java/org/apache/accumulo/core/conf/ConfigurationDocGen.java
index d90ce98,41a1f3b..d8d788b
--- a/core/src/main/java/org/apache/accumulo/core/conf/ConfigurationDocGen.java
+++ b/core/src/main/java/org/apache/accumulo/core/conf/ConfigurationDocGen.java
@@@ -19,7 -20,7 +20,8 @@@ import java.io.FileNotFoundException
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.PrintStream;
+ import java.io.UnsupportedEncodingException;
 +import java.nio.charset.StandardCharsets;
  import java.util.ArrayList;
  import java.util.TreeMap;
  
@@@ -348,8 -336,21 +350,25 @@@ class ConfigurationDocGen 
      new HTML().generate();
    }
  
 -  void generateLaTeX() {
 -    new LaTeX().generate();
 +  void generateAsciidoc() {
 +    new Asciidoc().generate();
    }
  
+   /*
 -   * Generate documentation for conf/accumulo-site.xml file usage
++   * Generates documentation for conf/accumulo-site.xml file usage. Arguments
++   * are: "--generate-doc", file to write to.
++   *
++   * @param args command-line arguments
++   * @throws IllegalArgumentException if args is invalid
+    */
+   public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
+     if (args.length == 2 && args[0].equals("--generate-html")) {
 -      new ConfigurationDocGen(new PrintStream(args[1], Constants.UTF8.name())).generateHtml();
 -    } else if (args.length == 2 && args[0].equals("--generate-latex")) {
 -      new ConfigurationDocGen(new PrintStream(args[1], Constants.UTF8.name())).generateLaTeX();
++      new ConfigurationDocGen(new PrintStream(args[1], StandardCharsets.UTF_8.name())).generateHtml();
++    } else if (args.length == 2 && args[0].equals("--generate-asciidoc")) {
++      new ConfigurationDocGen(new PrintStream(args[1], StandardCharsets.UTF_8.name())).generateAsciidoc();
+     } else {
 -      throw new IllegalArgumentException("Usage: " + ConfigurationDocGen.class.getName() + " --generate-html <filename> | --generate-latex <filename>");
++      throw new IllegalArgumentException("Usage: " + ConfigurationDocGen.class.getName() + " --generate-html <filename> | --generate-asciidoc <filename>");
+     }
+   }
+ 
  }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/c6ed57ed/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java
----------------------------------------------------------------------
diff --cc core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java
index 635813f,6e1b779..b1d8851
--- a/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java
+++ b/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java
@@@ -24,26 -21,28 +21,30 @@@ import java.util.HashMap
  import java.util.Map;
  import java.util.Map.Entry;
  
 -import org.apache.accumulo.core.Constants;
 -
 +/**
 + * An {@link AccumuloConfiguration} that contains only default values for
 + * properties. This class is a singleton.
 + */
  public class DefaultConfiguration extends AccumuloConfiguration {
-   private static DefaultConfiguration instance = null;
-   private Map<String,String> resolvedProps = null;
+   private final static Map<String,String> resolvedProps;
+   static {
+     Map<String, String> m = new HashMap<String,String>();
+     for (Property prop : Property.values()) {
+       if (!prop.getType().equals(PropertyType.PREFIX)) {
+         m.put(prop.getKey(), prop.getDefaultValue());
+       }
+     }
+     ConfigSanityCheck.validate(m.entrySet());
+     resolvedProps = Collections.unmodifiableMap(m);
+   }
  
    /**
-    * Gets an instance of this class.
+    * Gets a default configuration.
     *
     * @return default configuration
-    * @throws RuntimeException if the default configuration is invalid
     */
-   synchronized public static DefaultConfiguration getInstance() {
-     if (instance == null) {
-       instance = new DefaultConfiguration();
-       ConfigSanityCheck.validate(instance);
-     }
-     return instance;
+   public static DefaultConfiguration getInstance() {
+     return new DefaultConfiguration();
    }
  
    @Override
@@@ -68,22 -56,5 +58,4 @@@
        if (filter.accept(entry.getKey()))
          props.put(entry.getKey(), entry.getValue());
    }
--
-   /*
-    * Generates documentation for conf/accumulo-site.xml file usage. Arguments
-    * are: "--generate-doc", file to write to.
-    *
-    * @param args command-line arguments
-    * @throws IllegalArgumentException if args is invalid
-    */
-   public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
-     if (args.length == 2 && args[0].equals("--generate-html")) {
-       new ConfigurationDocGen(new PrintStream(args[1], StandardCharsets.UTF_8.name())).generateHtml();
-     } else if (args.length == 2 && args[0].equals("--generate-asciidoc")) {
-       new ConfigurationDocGen(new PrintStream(args[1], StandardCharsets.UTF_8.name())).generateAsciidoc();
-     } else {
-       throw new IllegalArgumentException("Usage: " + DefaultConfiguration.class.getName() + " --generate-html <filename> | --generate-latex <filename>");
-     }
-   }
- 
  }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/c6ed57ed/docs/pom.xml
----------------------------------------------------------------------
diff --cc docs/pom.xml
index 4cc75a9,a6260c6..47d98da
--- a/docs/pom.xml
+++ b/docs/pom.xml
@@@ -119,11 -77,11 +119,11 @@@
                  </goals>
                  <phase>compile</phase>
                  <configuration>
-                   <mainClass>org.apache.accumulo.core.conf.DefaultConfiguration</mainClass>
+                   <mainClass>org.apache.accumulo.core.conf.ConfigurationDocGen</mainClass>
                    <classpathScope>compile</classpathScope>
                    <arguments>
 -                    <argument>--generate-latex</argument>
 -                    <argument>${project.build.directory}/latex/accumulo_user_manual/appendices/config.tex</argument>
 +                    <argument>--generate-asciidoc</argument>
 +                    <argument>${project.build.directory}/asciidoc/appendices/config.txt</argument>
                    </arguments>
                  </configuration>
                </execution>


[5/8] git commit: Merge branch '1.5.2-SNAPSHOT' into 1.6.1-SNAPSHOT (-sours)

Posted by bh...@apache.org.
Merge branch '1.5.2-SNAPSHOT' into 1.6.1-SNAPSHOT (-sours)


Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo
Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/8140804b
Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/8140804b
Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/8140804b

Branch: refs/heads/master
Commit: 8140804bb534808ea94d718695ee442009fbeb8f
Parents: 3ee78d9 7136996
Author: Bill Havanki <bh...@cloudera.com>
Authored: Wed Aug 13 10:09:45 2014 -0400
Committer: Bill Havanki <bh...@cloudera.com>
Committed: Wed Aug 13 10:09:45 2014 -0400

----------------------------------------------------------------------

----------------------------------------------------------------------



[3/8] git commit: ACCUMULO-3012 Improve DefaultConfiguration

Posted by bh...@apache.org.
ACCUMULO-3012 Improve DefaultConfiguration

* The map of default properties created during the iterator() method each time is now
  static and immutable.
* A unit test is added.
* Accompanying changes were made to ConfigSanityCheck:
  - The validate method takes in an Iterable of entries instead of a Configuration.
  - Validation failure throws a new SanityCheckException class instead of RuntimeException.
  - A unit test is added.


Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo
Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/7136996a
Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/7136996a
Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/7136996a

Branch: refs/heads/master
Commit: 7136996a19406a7dfc5c2f2c5861cae95f68badc
Parents: c4d46bb
Author: Bill Havanki <bh...@cloudera.com>
Authored: Thu Jul 24 09:36:04 2014 -0400
Committer: Bill Havanki <bh...@cloudera.com>
Committed: Wed Aug 13 09:30:04 2014 -0400

----------------------------------------------------------------------
 .../accumulo/core/conf/ConfigSanityCheck.java   | 44 +++++++++--
 .../core/conf/DefaultConfiguration.java         | 41 ++++++----
 .../core/conf/ConfigSanityCheckTest.java        | 79 ++++++++++++++++++++
 .../core/conf/DefaultConfigurationTest.java     | 47 ++++++++++++
 4 files changed, 187 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/accumulo/blob/7136996a/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java b/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java
index 6724670..abec58b 100644
--- a/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java
+++ b/core/src/main/java/org/apache/accumulo/core/conf/ConfigSanityCheck.java
@@ -20,13 +20,24 @@ import java.util.Map.Entry;
 
 import org.apache.log4j.Logger;
 
+/**
+ * A utility class for checking over configuration entries.
+ */
 public class ConfigSanityCheck {
   
   private static final Logger log = Logger.getLogger(ConfigSanityCheck.class);
   private static final String PREFIX = "BAD CONFIG ";
   
-  public static void validate(AccumuloConfiguration acuconf) {
-    for (Entry<String,String> entry : acuconf) {
+  /**
+   * Validates the given configuration entries.
+   *
+   * @param entries iterable through configuration keys and values
+   * @throws SanityCheckException if a fatal configuration error is found
+   */
+  public static void validate(Iterable<Entry<String,String>> entries) {
+    String instanceZkTimeoutKey = Property.INSTANCE_ZK_TIMEOUT.getKey();
+    String instanceZkTimeoutValue = null;
+    for (Entry<String,String> entry : entries) {
       String key = entry.getKey();
       String value = entry.getValue();
       Property prop = Property.getPropertyByKey(entry.getKey());
@@ -38,9 +49,16 @@ public class ConfigSanityCheck {
         fatal(PREFIX + "incomplete property key (" + key + ")");
       else if (!prop.getType().isValidFormat(value))
         fatal(PREFIX + "improperly formatted value for key (" + key + ", type=" + prop.getType() + ")");
+
+      if (key.equals(instanceZkTimeoutKey)) {
+        instanceZkTimeoutValue = value;
+      }
+    }
+
+    if (instanceZkTimeoutValue != null) {
+      checkTimeDuration(Property.INSTANCE_ZK_TIMEOUT, instanceZkTimeoutValue,
+                        new CheckTimeDurationBetween(1000, 300000));
     }
-    
-    checkTimeDuration(acuconf, Property.INSTANCE_ZK_TIMEOUT, new CheckTimeDurationBetween(1000, 300000));
   }
   
   private static interface CheckTimeDuration {
@@ -68,9 +86,9 @@ public class ConfigSanityCheck {
     }
   }
   
-  private static void checkTimeDuration(AccumuloConfiguration acuconf, Property prop, CheckTimeDuration chk) {
+  private static void checkTimeDuration(Property prop, String value, CheckTimeDuration chk) {
     verifyPropertyTypes(PropertyType.TIMEDURATION, prop);
-    if (!chk.check(acuconf.getTimeInMillis(prop)))
+    if (!chk.check(AccumuloConfiguration.getTimeInMillis(value)))
       fatal(PREFIX + chk.getDescription(prop));
   }
   
@@ -79,9 +97,19 @@ public class ConfigSanityCheck {
       if (prop.getType() != type)
         fatal("Unexpected property type (" + prop.getType() + " != " + type + ")");
   }
-  
+
+  /**
+   * The exception thrown when {@link ConfigSanityCheck#validate(Iterable)} fails.
+   */
+  public static class SanityCheckException extends RuntimeException {
+    /**
+     * Creates a new exception with the given message.
+     */
+    public SanityCheckException(String msg) { super(msg); }
+  }
+
   private static void fatal(String msg) {
     log.fatal(msg);
-    throw new RuntimeException(msg);
+    throw new SanityCheckException(msg);
   }
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7136996a/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java b/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java
index d653274..c83c754 100644
--- a/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java
+++ b/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java
@@ -23,6 +23,8 @@ import java.io.PrintStream;
 import java.io.UnsupportedEncodingException;
 import java.util.ArrayList;
 import java.util.Iterator;
+import java.util.Collections;
+import java.util.Map;
 import java.util.Map.Entry;
 import java.util.TreeMap;
 
@@ -30,32 +32,40 @@ import org.apache.accumulo.core.Constants;
 import org.apache.log4j.Logger;
 
 public class DefaultConfiguration extends AccumuloConfiguration {
-  private static DefaultConfiguration instance = null;
   private static Logger log = Logger.getLogger(DefaultConfiguration.class);
-  
-  synchronized public static DefaultConfiguration getInstance() {
-    if (instance == null) {
-      instance = new DefaultConfiguration();
-      ConfigSanityCheck.validate(instance);
+
+  private final static Map<String,String> resolvedProps;
+  static {
+    Map<String,String> m = new TreeMap<String,String>();
+    for (Property prop : Property.values()) {
+      if (!prop.isExperimental() && !prop.getType().equals(PropertyType.PREFIX)) {
+        m.put(prop.getKey(), prop.getDefaultValue());
+      }
     }
-    return instance;
+    ConfigSanityCheck.validate(m.entrySet());
+    resolvedProps = Collections.unmodifiableMap(m);
   }
-  
+
+  /**
+   * Gets a default configuration.
+   *
+   * @return default configuration
+   */
+  public static DefaultConfiguration getInstance() {
+    return new DefaultConfiguration();
+  }
+
   @Override
   public String get(Property property) {
     return property.getDefaultValue();
   }
-  
+
   @Override
   public Iterator<Entry<String,String>> iterator() {
-    TreeMap<String,String> entries = new TreeMap<String,String>();
-    for (Property prop : Property.values())
-      if (!prop.isExperimental() && !prop.getType().equals(PropertyType.PREFIX))
-        entries.put(prop.getKey(), prop.getDefaultValue());
-    
-    return entries.entrySet().iterator();
+    return resolvedProps.entrySet().iterator();
   }
   
+
   private static void generateDocumentation(PrintStream doc) {
     // read static content from resources and output
     InputStream data = DefaultConfiguration.class.getResourceAsStream("config.html");
@@ -185,5 +195,4 @@ public class DefaultConfiguration extends AccumuloConfiguration {
       throw new IllegalArgumentException("Usage: " + DefaultConfiguration.class.getName() + " --generate-doc <filename>");
     }
   }
-  
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7136996a/core/src/test/java/org/apache/accumulo/core/conf/ConfigSanityCheckTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/conf/ConfigSanityCheckTest.java b/core/src/test/java/org/apache/accumulo/core/conf/ConfigSanityCheckTest.java
new file mode 100644
index 0000000..88bbe64
--- /dev/null
+++ b/core/src/test/java/org/apache/accumulo/core/conf/ConfigSanityCheckTest.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.accumulo.core.conf;
+
+import java.util.Map;
+import org.apache.accumulo.core.conf.ConfigSanityCheck.SanityCheckException;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ConfigSanityCheckTest {
+  private Map<String,String> m;
+
+  @Before
+  public void setUp() {
+    m = new java.util.HashMap<String,String>();
+  }
+
+  @Test
+  public void testPass() {
+    m.put(Property.MASTER_CLIENTPORT.getKey(), "9999");
+    m.put(Property.MASTER_TABLET_BALANCER.getKey(), "org.apache.accumulo.server.master.balancer.TableLoadBalancer");
+    m.put(Property.MASTER_RECOVERY_MAXAGE.getKey(), "60m");
+    m.put(Property.MASTER_BULK_RETRIES.getKey(), "3");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test
+  public void testPass_Empty() {
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test
+  public void testPass_UnrecognizedValidProperty() {
+    m.put(Property.MASTER_CLIENTPORT.getKey(), "9999");
+    m.put(Property.MASTER_PREFIX.getKey() + "something", "abcdefg");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test
+  public void testPass_UnrecognizedProperty() {
+    m.put(Property.MASTER_CLIENTPORT.getKey(), "9999");
+    m.put("invalid.prefix.value", "abcdefg");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test(expected = SanityCheckException.class)
+  public void testFail_Prefix() {
+    m.put(Property.MASTER_CLIENTPORT.getKey(), "9999");
+    m.put(Property.MASTER_PREFIX.getKey(), "oops");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test(expected = SanityCheckException.class)
+  public void testFail_InvalidFormat() {
+    m.put(Property.MASTER_CLIENTPORT.getKey(), "9999");
+    m.put(Property.MASTER_RECOVERY_MAXAGE.getKey(), "60breem");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+
+  @Test(expected = SanityCheckException.class)
+  public void testFail_InstanceZkTimeoutOutOfRange() {
+    m.put(Property.INSTANCE_ZK_TIMEOUT.getKey(), "10ms");
+    ConfigSanityCheck.validate(m.entrySet());
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/7136996a/core/src/test/java/org/apache/accumulo/core/conf/DefaultConfigurationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/conf/DefaultConfigurationTest.java b/core/src/test/java/org/apache/accumulo/core/conf/DefaultConfigurationTest.java
new file mode 100644
index 0000000..9355fff
--- /dev/null
+++ b/core/src/test/java/org/apache/accumulo/core/conf/DefaultConfigurationTest.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.accumulo.core.conf;
+
+import java.util.Iterator;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+public class DefaultConfigurationTest {
+  private DefaultConfiguration c;
+
+  @Before
+  public void setUp() {
+    c = new DefaultConfiguration();
+  }
+
+  @Test
+  public void testGet() {
+    assertEquals(Property.MASTER_CLIENTPORT.getDefaultValue(), c.get(Property.MASTER_CLIENTPORT));
+  }
+
+  @Test
+  public void testGetProperties() {
+    Iterator<Map.Entry<String,String>> iter = c.iterator();
+    while (iter.hasNext()) {
+      Map.Entry<String,String> e = iter.next();
+      Property p = Property.getPropertyByKey(e.getKey());
+      assertEquals(p.getDefaultValue(), e.getValue());
+    }
+  }
+}


[4/8] git commit: Merge branch '1.5.2-SNAPSHOT' into 1.6.1-SNAPSHOT (-sours)

Posted by bh...@apache.org.
Merge branch '1.5.2-SNAPSHOT' into 1.6.1-SNAPSHOT (-sours)


Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo
Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/8140804b
Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/8140804b
Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/8140804b

Branch: refs/heads/1.6.1-SNAPSHOT
Commit: 8140804bb534808ea94d718695ee442009fbeb8f
Parents: 3ee78d9 7136996
Author: Bill Havanki <bh...@cloudera.com>
Authored: Wed Aug 13 10:09:45 2014 -0400
Committer: Bill Havanki <bh...@cloudera.com>
Committed: Wed Aug 13 10:09:45 2014 -0400

----------------------------------------------------------------------

----------------------------------------------------------------------