You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@accumulo.apache.org by kt...@apache.org on 2018/02/05 22:53:34 UTC

[accumulo] branch master updated (4ef2671 -> 4879f52)

This is an automated email from the ASF dual-hosted git repository.

kturner pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/accumulo.git.


    from 4ef2671  Merge branch '1.8'
     add 3ca3d65  ACCUMULO-4779 Improved performance of get by prefix in config (#372)
     add 3c55eed  ACCUMULO-4797 improved namespace config performance (#375)
     new 4879f52  Merge branch '1.8'

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../accumulo/core/client/impl/ClientContext.java   |   5 -
 .../apache/accumulo/core/client/impl/Tables.java   |  10 +-
 .../core/client/mock/MockConfiguration.java        |   5 -
 .../accumulo/core/conf/AccumuloConfiguration.java  |  83 +++++++----
 .../accumulo/core/conf/ConfigurationCopy.java      |  22 ++-
 .../accumulo/core/conf/DefaultConfiguration.java   |   5 -
 .../accumulo/core/conf/SiteConfiguration.java      |   9 --
 .../core/security/crypto/CryptoModuleFactory.java  |   2 +-
 .../core/conf/AccumuloConfigurationTest.java       | 152 +++++++++++++++++++++
 .../apache/accumulo/fate/zookeeper/ZooCache.java   |  33 +++--
 .../server/conf/NamespaceConfiguration.java        |   9 +-
 .../server/conf/ServerConfigurationFactory.java    |  10 +-
 .../accumulo/server/conf/TableConfiguration.java   |   5 +
 .../accumulo/server/conf/ZooConfiguration.java     |  14 +-
 .../server/conf/ZooConfigurationFactory.java       |  13 +-
 .../server/conf/NamespaceConfigurationTest.java    |   8 +-
 .../server/conf/ZooConfigurationFactoryTest.java   |   5 +-
 .../BaseHostRegexTableLoadBalancerTest.java        |   5 +
 .../balancer/HostRegexTableLoadBalancerTest.java   |  10 ++
 .../TCredentialsUpdatingInvocationHandlerTest.java |   5 +
 .../java/org/apache/accumulo/master/Master.java    |   4 +-
 .../org/apache/accumulo/tserver/TabletServer.java  |   4 +-
 .../main/java/org/apache/accumulo/shell/Shell.java |  11 +-
 .../start/classloader/vfs/ContextManager.java      |  12 +-
 24 files changed, 337 insertions(+), 104 deletions(-)

-- 
To stop receiving notification emails like this one, please contact
kturner@apache.org.

[accumulo] 01/01: Merge branch '1.8'

Posted by kt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

kturner pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/accumulo.git

commit 4879f52f0334ca1c52b613d297cd3c7fd4c19afa
Merge: 4ef2671 3c55eed
Author: Keith Turner <kt...@apache.org>
AuthorDate: Mon Feb 5 17:51:54 2018 -0500

    Merge branch '1.8'

 .../accumulo/core/client/impl/ClientContext.java   |   5 -
 .../apache/accumulo/core/client/impl/Tables.java   |  10 +-
 .../core/client/mock/MockConfiguration.java        |   5 -
 .../accumulo/core/conf/AccumuloConfiguration.java  |  83 +++++++----
 .../accumulo/core/conf/ConfigurationCopy.java      |  22 ++-
 .../accumulo/core/conf/DefaultConfiguration.java   |   5 -
 .../accumulo/core/conf/SiteConfiguration.java      |   9 --
 .../core/security/crypto/CryptoModuleFactory.java  |   2 +-
 .../core/conf/AccumuloConfigurationTest.java       | 152 +++++++++++++++++++++
 .../apache/accumulo/fate/zookeeper/ZooCache.java   |  33 +++--
 .../server/conf/NamespaceConfiguration.java        |   9 +-
 .../server/conf/ServerConfigurationFactory.java    |  10 +-
 .../accumulo/server/conf/TableConfiguration.java   |   5 +
 .../accumulo/server/conf/ZooConfiguration.java     |  14 +-
 .../server/conf/ZooConfigurationFactory.java       |  13 +-
 .../server/conf/NamespaceConfigurationTest.java    |   8 +-
 .../server/conf/ZooConfigurationFactoryTest.java   |   5 +-
 .../BaseHostRegexTableLoadBalancerTest.java        |   5 +
 .../balancer/HostRegexTableLoadBalancerTest.java   |  10 ++
 .../TCredentialsUpdatingInvocationHandlerTest.java |   5 +
 .../java/org/apache/accumulo/master/Master.java    |   4 +-
 .../org/apache/accumulo/tserver/TabletServer.java  |   4 +-
 .../main/java/org/apache/accumulo/shell/Shell.java |  11 +-
 .../start/classloader/vfs/ContextManager.java      |  12 +-
 24 files changed, 337 insertions(+), 104 deletions(-)

diff --cc core/src/main/java/org/apache/accumulo/core/client/impl/Tables.java
index 94bd193,423d81f..a33d159
--- a/core/src/main/java/org/apache/accumulo/core/client/impl/Tables.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/impl/Tables.java
@@@ -74,8 -64,19 +73,11 @@@ public class Tables 
      final String uuid = instance.getInstanceID();
  
      try {
-       return instanceToZooCache.get(uuid, () -> new ZooCacheFactory().getZooCache(zks, timeOut,
-               watchedEvent -> instanceToMapCache.invalidate(uuid)));
 -      return instanceToZooCache.get(uuid, new Callable<ZooCache>() {
 -        @Override
 -        public ZooCache call() {
 -          final String zks = instance.getZooKeepers();
 -          final int timeOut = instance.getZooKeepersSessionTimeOut();
 -          return new ZooCacheFactory().getZooCache(zks, timeOut, new Watcher() {
 -            @Override
 -            public void process(WatchedEvent watchedEvent) {
 -              instanceToMapCache.invalidate(uuid);
 -            }
 -          });
 -        }
++      return instanceToZooCache.get(uuid, () -> {
++        final String zks = instance.getZooKeepers();
++        final int timeOut = instance.getZooKeepersSessionTimeOut();
++        return new ZooCacheFactory().getZooCache(zks, timeOut, watchedEvent -> instanceToMapCache.invalidate(uuid));
+       });
      } catch (ExecutionException e) {
        throw new RuntimeException(e);
      }
diff --cc core/src/main/java/org/apache/accumulo/core/conf/AccumuloConfiguration.java
index 4de7252,3bf54be..4c1582f
--- a/core/src/main/java/org/apache/accumulo/core/conf/AccumuloConfiguration.java
+++ b/core/src/main/java/org/apache/accumulo/core/conf/AccumuloConfiguration.java
@@@ -22,48 -23,107 +23,37 @@@ import java.util.Map
  import java.util.Map.Entry;
  import java.util.Objects;
  import java.util.TreeMap;
 -import java.util.concurrent.TimeUnit;
+ import java.util.concurrent.locks.Lock;
+ import java.util.concurrent.locks.ReentrantLock;
 +import java.util.function.Predicate;
  
  import org.apache.accumulo.core.Constants;
 -import org.apache.accumulo.core.client.AccumuloException;
 -import org.apache.accumulo.core.client.Connector;
 -import org.apache.accumulo.core.client.TableNotFoundException;
 -import org.apache.accumulo.core.client.impl.Tables;
  import org.apache.accumulo.core.conf.PropertyType.PortRange;
  import org.apache.accumulo.core.util.Pair;
 -import org.apache.accumulo.start.classloader.vfs.AccumuloVFSClassLoader;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
- import com.google.common.base.Preconditions;
 -import com.google.common.base.Predicate;
 -import com.google.common.base.Predicates;
+ import com.google.common.collect.ImmutableMap;
  
  /**
   * A configuration object.
   */
  public abstract class AccumuloConfiguration implements Iterable<Entry<String,String>> {
  
-   private static final Logger log = LoggerFactory.getLogger(AccumuloConfiguration.class);
- 
-   protected String getArbitrarySystemPropertyImpl(AccumuloConfiguration parent, String property) {
-     return parent.getArbitrarySystemPropertyImpl(property);
-   }
+   private static class PrefixProps {
+     final long updateCount;
+     final Map<String,String> props;
  
-   /**
-    * This method is not called with sensitive or per table properties.
-    */
-   protected String getArbitrarySystemPropertyImpl(String property) {
-     throw new UnsupportedOperationException();
+     PrefixProps(Map<String,String> props, long updateCount) {
+       this.updateCount = updateCount;
+       this.props = props;
+     }
    }
  
-   /**
-    * This method was created because {@link #get(String)} is very slow. However this method does not properly handle everything that {@link #get(String)} does.
-    * For example it does not properly handle table or sensitive properties.
-    *
-    * <p>
-    * This method has a whitelist of prefixes it handles. To see the whitelist, check the implementation. When adding to the whitelist, ensure that all
-    * configurations can properly handle.
-    */
-   public String getArbitrarySystemProperty(Property prefix, String property) {
-     Preconditions.checkArgument(prefix == Property.VFS_CONTEXT_CLASSPATH_PROPERTY);
+   private volatile EnumMap<Property,PrefixProps> cachedPrefixProps = new EnumMap<>(Property.class);
+   private Lock prefixCacheUpdateLock = new ReentrantLock();
  
-     String key = prefix.getKey() + property;
-     return getArbitrarySystemPropertyImpl(key);
 -  /**
 -   * A filter for properties, based on key.
 -   *
 -   * @deprecated since 1.7.0; use {@link Predicate} instead.
 -   */
 -  @Deprecated
 -  public interface PropertyFilter {
 -    /**
 -     * Determines whether to accept a property based on its key.
 -     *
 -     * @param key
 -     *          property key
 -     * @return true to accept property (pass filter)
 -     */
 -    boolean accept(String key);
 -  }
 -
 -  /**
 -   * A filter that accepts properties whose keys are an exact match.
 -   */
 -  public static class MatchFilter implements Predicate<String> {
 -
 -    private String match;
 -
 -    /**
 -     * Creates a new filter.
 -     *
 -     * @param match
 -     *          prefix of property keys to accept
 -     */
 -    public MatchFilter(String match) {
 -      this.match = match;
 -    }
 -
 -    @Override
 -    public boolean apply(String key) {
 -      return Objects.equals(match, key);
 -    }
 -  }
 -
 -  /**
 -   * A filter that accepts properties whose keys begin with a prefix.
 -   */
 -  public static class PrefixFilter implements Predicate<String> {
 -
 -    private String prefix;
 -
 -    /**
 -     * Creates a new filter.
 -     *
 -     * @param prefix
 -     *          prefix of property keys to accept
 -     */
 -    public PrefixFilter(String prefix) {
 -      this.prefix = prefix;
 -    }
 -
 -    @Override
 -    public boolean apply(String key) {
 -      return key.startsWith(prefix);
 -    }
--  }
 -
+   private static final Logger log = LoggerFactory.getLogger(AccumuloConfiguration.class);
  
    /**
     * Gets a property value from this configuration.
@@@ -135,9 -202,41 +132,41 @@@
    public Map<String,String> getAllPropertiesWithPrefix(Property property) {
      checkType(property, PropertyType.PREFIX);
  
-     Map<String,String> propMap = new HashMap<>();
-     getProperties(propMap, key -> key.startsWith(property.getKey()));
-     return propMap;
+     PrefixProps prefixProps = cachedPrefixProps.get(property);
+ 
+     if (prefixProps == null || prefixProps.updateCount != getUpdateCount()) {
+       prefixCacheUpdateLock.lock();
+       try {
+         // Very important that update count is read before getting properties. Also only read it once.
+         long updateCount = getUpdateCount();
+         prefixProps = cachedPrefixProps.get(property);
+ 
+         if (prefixProps == null || prefixProps.updateCount != updateCount) {
+           Map<String,String> propMap = new HashMap<>();
+           // The reason this caching exists is to avoid repeatedly making this expensive call.
 -          getProperties(propMap, new PrefixFilter(property.getKey()));
++          getProperties(propMap, key -> key.startsWith(property.getKey()));
+           propMap = ImmutableMap.copyOf(propMap);
+ 
+           // So that locking is not needed when reading from enum map, always create a new one. Construct and populate map using a local var so its not visible
+           // until ready.
+           EnumMap<Property,PrefixProps> localPrefixes = new EnumMap<>(Property.class);
+ 
+           // carry forward any other cached prefixes
+           localPrefixes.putAll(cachedPrefixProps);
+ 
+           // put the updates
+           prefixProps = new PrefixProps(propMap, updateCount);
+           localPrefixes.put(property, prefixProps);
+ 
+           // make the newly constructed map available
+           cachedPrefixProps = localPrefixes;
+         }
+       } finally {
+         prefixCacheUpdateLock.unlock();
+       }
+     }
+ 
+     return prefixProps.props;
    }
  
    /**
diff --cc core/src/main/java/org/apache/accumulo/core/conf/ConfigurationCopy.java
index d315809,a84765a..0f617bb
--- a/core/src/main/java/org/apache/accumulo/core/conf/ConfigurationCopy.java
+++ b/core/src/main/java/org/apache/accumulo/core/conf/ConfigurationCopy.java
@@@ -63,14 -65,9 +64,9 @@@ public class ConfigurationCopy extends 
    }
  
    @Override
-   protected String getArbitrarySystemPropertyImpl(String property) {
-     return copy.get(property);
-   }
- 
-   @Override
    public void getProperties(Map<String,String> props, Predicate<String> filter) {
      for (Entry<String,String> entry : copy.entrySet()) {
 -      if (filter.apply(entry.getKey())) {
 +      if (filter.test(entry.getKey())) {
          props.put(entry.getKey(), entry.getValue());
        }
      }
diff --cc core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java
index 370283f,e1ff7e1..756e241
--- a/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java
+++ b/core/src/main/java/org/apache/accumulo/core/conf/DefaultConfiguration.java
@@@ -47,11 -54,8 +47,6 @@@ public class DefaultConfiguration exten
  
    @Override
    public void getProperties(Map<String,String> props, Predicate<String> filter) {
 -    for (Entry<String,String> entry : resolvedProps.entrySet())
 -      if (filter.apply(entry.getKey()))
 -        props.put(entry.getKey(), entry.getValue());
 +    resolvedProps.entrySet().stream().filter(p -> filter.test(p.getKey())).forEach(e -> props.put(e.getKey(), e.getValue()));
    }
- 
-   @Override
-   protected String getArbitrarySystemPropertyImpl(String property) {
-     return null;
-   }
  }
diff --cc core/src/main/java/org/apache/accumulo/core/conf/SiteConfiguration.java
index 682edec,9f047e2..4135de0
--- a/core/src/main/java/org/apache/accumulo/core/conf/SiteConfiguration.java
+++ b/core/src/main/java/org/apache/accumulo/core/conf/SiteConfiguration.java
@@@ -153,26 -129,11 +153,17 @@@ public class SiteConfiguration extends 
    }
  
    @Override
-   protected String getArbitrarySystemPropertyImpl(String property) {
-     String val = staticConfigs.get(property);
-     if (val == null) {
-       val = parent.getArbitrarySystemPropertyImpl(property);
-     }
-     return val;
-   }
- 
-   @Override
    public void getProperties(Map<String,String> props, Predicate<String> filter) {
 -    parent.getProperties(props, filter);
 +    getProperties(props, filter, true);
 +  }
 +
 +  public void getProperties(Map<String,String> props, Predicate<String> filter, boolean useDefaults) {
 +    if (useDefaults) {
 +      parent.getProperties(props, filter);
 +    }
  
      for (Entry<String,String> entry : getXmlConfig())
 -      if (filter.apply(entry.getKey()))
 +      if (filter.test(entry.getKey()))
          props.put(entry.getKey(), entry.getValue());
  
      // CredentialProvider should take precedence over site
diff --cc core/src/main/java/org/apache/accumulo/core/security/crypto/CryptoModuleFactory.java
index 251a605,f724b7b..dd9cc4c
--- a/core/src/main/java/org/apache/accumulo/core/security/crypto/CryptoModuleFactory.java
+++ b/core/src/main/java/org/apache/accumulo/core/security/crypto/CryptoModuleFactory.java
@@@ -247,10 -257,10 +247,10 @@@ public class CryptoModuleFactory 
  
    public static CryptoModuleParameters fillParamsObjectFromConfiguration(CryptoModuleParameters params, AccumuloConfiguration conf) {
      // Get all the options from the configuration
-     Map<String,String> cryptoOpts = conf.getAllPropertiesWithPrefix(Property.CRYPTO_PREFIX);
+     Map<String,String> cryptoOpts = new HashMap<>(conf.getAllPropertiesWithPrefix(Property.CRYPTO_PREFIX));
      cryptoOpts.putAll(conf.getAllPropertiesWithPrefix(Property.INSTANCE_PREFIX));
      cryptoOpts.remove(Property.INSTANCE_SECRET.getKey());
 -    cryptoOpts.put(Property.CRYPTO_BLOCK_STREAM_SIZE.getKey(), Integer.toString((int) conf.getMemoryInBytes(Property.CRYPTO_BLOCK_STREAM_SIZE)));
 +    cryptoOpts.put(Property.CRYPTO_BLOCK_STREAM_SIZE.getKey(), Integer.toString((int) conf.getAsBytes(Property.CRYPTO_BLOCK_STREAM_SIZE)));
  
      return fillParamsObjectFromStringMap(params, cryptoOpts);
    }
diff --cc core/src/test/java/org/apache/accumulo/core/conf/AccumuloConfigurationTest.java
index 81b5791,ba373ab..68c2d9a
--- a/core/src/test/java/org/apache/accumulo/core/conf/AccumuloConfigurationTest.java
+++ b/core/src/test/java/org/apache/accumulo/core/conf/AccumuloConfigurationTest.java
@@@ -17,15 -17,63 +17,29 @@@
  package org.apache.accumulo.core.conf;
  
  import static org.junit.Assert.assertEquals;
+ import static org.junit.Assert.assertNotSame;
+ import static org.junit.Assert.assertSame;
  import static org.junit.Assert.assertTrue;
  
+ import java.util.HashMap;
+ import java.util.Map;
+ import java.util.Map.Entry;
++import java.util.function.Predicate;
+ 
+ import org.junit.Rule;
  import org.junit.Test;
+ import org.junit.rules.ExpectedException;
+ 
 -import com.google.common.base.Predicate;
+ import com.google.common.collect.ImmutableMap;
  
  public class AccumuloConfigurationTest {
  
+   @Rule
+   public ExpectedException thrown = ExpectedException.none();
+ 
    @Test
 -  public void testGetMemoryInBytes() throws Exception {
 -    assertEquals(42l, AccumuloConfiguration.getMemoryInBytes("42"));
 -    assertEquals(42l, AccumuloConfiguration.getMemoryInBytes("42b"));
 -    assertEquals(42l, AccumuloConfiguration.getMemoryInBytes("42B"));
 -    assertEquals(42l * 1024l, AccumuloConfiguration.getMemoryInBytes("42K"));
 -    assertEquals(42l * 1024l, AccumuloConfiguration.getMemoryInBytes("42k"));
 -    assertEquals(42l * 1024l * 1024l, AccumuloConfiguration.getMemoryInBytes("42M"));
 -    assertEquals(42l * 1024l * 1024l, AccumuloConfiguration.getMemoryInBytes("42m"));
 -    assertEquals(42l * 1024l * 1024l * 1024l, AccumuloConfiguration.getMemoryInBytes("42G"));
 -    assertEquals(42l * 1024l * 1024l * 1024l, AccumuloConfiguration.getMemoryInBytes("42g"));
 -
 -  }
 -
 -  @Test
 -  public void testGetTimeInMillis() {
 -    assertEquals(42L * 24 * 60 * 60 * 1000, AccumuloConfiguration.getTimeInMillis("42d"));
 -    assertEquals(42L * 60 * 60 * 1000, AccumuloConfiguration.getTimeInMillis("42h"));
 -    assertEquals(42L * 60 * 1000, AccumuloConfiguration.getTimeInMillis("42m"));
 -    assertEquals(42L * 1000, AccumuloConfiguration.getTimeInMillis("42s"));
 -    assertEquals(42L * 1000, AccumuloConfiguration.getTimeInMillis("42"));
 -    assertEquals(42L, AccumuloConfiguration.getTimeInMillis("42ms"));
 -  }
 -
 -  @Test(expected = IllegalArgumentException.class)
 -  public void testGetMemoryInBytesFailureCases1() throws Exception {
 -    AccumuloConfiguration.getMemoryInBytes("42x");
 -  }
 -
 -  @Test(expected = IllegalArgumentException.class)
 -  public void testGetMemoryInBytesFailureCases2() throws Exception {
 -    AccumuloConfiguration.getMemoryInBytes("FooBar");
 -  }
 -
 -  @Test
    public void testGetPropertyByString() {
 -    AccumuloConfiguration c = AccumuloConfiguration.getDefaultConfiguration();
 +    AccumuloConfiguration c = DefaultConfiguration.getInstance();
      boolean found = false;
      for (Property p : Property.values()) {
        if (p.getType() != PropertyType.PREFIX) {
@@@ -113,4 -161,142 +127,142 @@@
      cc.getPort(Property.TSERV_CLIENTPORT);
    }
  
+   private static class TestConfiguration extends AccumuloConfiguration {
+ 
+     private HashMap<String,String> props = new HashMap<>();
+     private int upCount = 0;
+ 
+     public void set(String p, String v) {
+       props.put(p, v);
+       upCount++;
+     }
+ 
+     @Override
+     public long getUpdateCount() {
+       return upCount;
+     }
+ 
+     @Override
+     public String get(Property property) {
+       return props.get(property.getKey());
+     }
+ 
+     @Override
+     public void getProperties(Map<String,String> output, Predicate<String> filter) {
+       for (Entry<String,String> entry : props.entrySet()) {
 -        if (filter.apply(entry.getKey())) {
++        if (filter.test(entry.getKey())) {
+           output.put(entry.getKey(), entry.getValue());
+         }
+       }
+     }
+ 
+   }
+ 
+   @Test
+   public void testMutatePrefixMap() {
+     TestConfiguration tc = new TestConfiguration();
+     tc.set(Property.TABLE_ARBITRARY_PROP_PREFIX.getKey() + "a1", "325");
+     tc.set(Property.TABLE_ARBITRARY_PROP_PREFIX.getKey() + "a2", "asg34");
+ 
+     Map<String,String> pm1 = tc.getAllPropertiesWithPrefix(Property.TABLE_ARBITRARY_PROP_PREFIX);
+ 
+     Map<String,String> expected1 = new HashMap<>();
+     expected1.put(Property.TABLE_ARBITRARY_PROP_PREFIX.getKey() + "a1", "325");
+     expected1.put(Property.TABLE_ARBITRARY_PROP_PREFIX.getKey() + "a2", "asg34");
+     assertEquals(expected1, pm1);
+ 
+     thrown.expect(UnsupportedOperationException.class);
+     pm1.put("k9", "v3");
+   }
+ 
+   @Test
+   public void testGetByPrefix() {
+     // This test checks that when anything changes that all prefix maps are regenerated. However when there are not changes the test expects all the exact same
+     // map to always be returned.
+ 
+     TestConfiguration tc = new TestConfiguration();
+ 
+     tc.set(Property.TABLE_ARBITRARY_PROP_PREFIX.getKey() + "a1", "325");
+     tc.set(Property.TABLE_ARBITRARY_PROP_PREFIX.getKey() + "a2", "asg34");
+ 
+     tc.set(Property.TABLE_ITERATOR_SCAN_PREFIX.getKey() + "i1", "class34");
+     tc.set(Property.TABLE_ITERATOR_SCAN_PREFIX.getKey() + "i1.opt", "o99");
+ 
+     Map<String,String> pm1 = tc.getAllPropertiesWithPrefix(Property.TABLE_ARBITRARY_PROP_PREFIX);
+     Map<String,String> pm2 = tc.getAllPropertiesWithPrefix(Property.TABLE_ARBITRARY_PROP_PREFIX);
+ 
+     assertSame(pm1, pm2);
+     Map<String,String> expected1 = new HashMap<>();
+     expected1.put(Property.TABLE_ARBITRARY_PROP_PREFIX.getKey() + "a1", "325");
+     expected1.put(Property.TABLE_ARBITRARY_PROP_PREFIX.getKey() + "a2", "asg34");
+     assertEquals(expected1, pm1);
+ 
+     Map<String,String> pm3 = tc.getAllPropertiesWithPrefix(Property.TABLE_ITERATOR_SCAN_PREFIX);
+     Map<String,String> pm4 = tc.getAllPropertiesWithPrefix(Property.TABLE_ITERATOR_SCAN_PREFIX);
+ 
+     assertSame(pm3, pm4);
+     Map<String,String> expected2 = new HashMap<>();
+     expected2.put(Property.TABLE_ITERATOR_SCAN_PREFIX.getKey() + "i1", "class34");
+     expected2.put(Property.TABLE_ITERATOR_SCAN_PREFIX.getKey() + "i1.opt", "o99");
+     assertEquals(expected2, pm3);
+ 
+     Map<String,String> pm5 = tc.getAllPropertiesWithPrefix(Property.VFS_CONTEXT_CLASSPATH_PROPERTY);
+     Map<String,String> pm6 = tc.getAllPropertiesWithPrefix(Property.VFS_CONTEXT_CLASSPATH_PROPERTY);
+     assertSame(pm5, pm6);
+     assertEquals(0, pm5.size());
+ 
+     // ensure getting one prefix does not cause others to unnecessarily regenerate
+     Map<String,String> pm7 = tc.getAllPropertiesWithPrefix(Property.TABLE_ARBITRARY_PROP_PREFIX);
+     assertSame(pm1, pm7);
+ 
+     Map<String,String> pm8 = tc.getAllPropertiesWithPrefix(Property.TABLE_ITERATOR_SCAN_PREFIX);
+     assertSame(pm3, pm8);
+ 
+     Map<String,String> pm9 = tc.getAllPropertiesWithPrefix(Property.VFS_CONTEXT_CLASSPATH_PROPERTY);
+     assertSame(pm5, pm9);
+ 
+     tc.set(Property.TABLE_ITERATOR_SCAN_PREFIX.getKey() + "i2", "class42");
+     tc.set(Property.TABLE_ITERATOR_SCAN_PREFIX.getKey() + "i2.opt", "o78234");
+ 
+     expected2.put(Property.TABLE_ITERATOR_SCAN_PREFIX.getKey() + "i2", "class42");
+     expected2.put(Property.TABLE_ITERATOR_SCAN_PREFIX.getKey() + "i2.opt", "o78234");
+ 
+     Map<String,String> pmA = tc.getAllPropertiesWithPrefix(Property.TABLE_ITERATOR_SCAN_PREFIX);
+     Map<String,String> pmB = tc.getAllPropertiesWithPrefix(Property.TABLE_ITERATOR_SCAN_PREFIX);
+     assertNotSame(pm3, pmA);
+     assertSame(pmA, pmB);
+     assertEquals(expected2, pmA);
+ 
+     Map<String,String> pmC = tc.getAllPropertiesWithPrefix(Property.TABLE_ARBITRARY_PROP_PREFIX);
+     Map<String,String> pmD = tc.getAllPropertiesWithPrefix(Property.TABLE_ARBITRARY_PROP_PREFIX);
+     assertNotSame(pm1, pmC);
+     assertSame(pmC, pmD);
+     assertEquals(expected1, pmC);
+ 
+     tc.set(Property.VFS_CONTEXT_CLASSPATH_PROPERTY.getKey() + "ctx123", "hdfs://ib/p1");
+ 
+     Map<String,String> pmE = tc.getAllPropertiesWithPrefix(Property.VFS_CONTEXT_CLASSPATH_PROPERTY);
+     Map<String,String> pmF = tc.getAllPropertiesWithPrefix(Property.VFS_CONTEXT_CLASSPATH_PROPERTY);
+     assertSame(pmE, pmF);
+     assertNotSame(pm5, pmE);
+     assertEquals(ImmutableMap.of(Property.VFS_CONTEXT_CLASSPATH_PROPERTY.getKey() + "ctx123", "hdfs://ib/p1"), pmE);
+ 
+     Map<String,String> pmG = tc.getAllPropertiesWithPrefix(Property.TABLE_ITERATOR_SCAN_PREFIX);
+     Map<String,String> pmH = tc.getAllPropertiesWithPrefix(Property.TABLE_ITERATOR_SCAN_PREFIX);
+     assertNotSame(pmA, pmG);
+     assertSame(pmG, pmH);
+     assertEquals(expected2, pmG);
+ 
+     Map<String,String> pmI = tc.getAllPropertiesWithPrefix(Property.TABLE_ARBITRARY_PROP_PREFIX);
+     Map<String,String> pmJ = tc.getAllPropertiesWithPrefix(Property.TABLE_ARBITRARY_PROP_PREFIX);
+     assertNotSame(pmC, pmI);
+     assertSame(pmI, pmJ);
+     assertEquals(expected1, pmI);
+ 
+     Map<String,String> pmK = tc.getAllPropertiesWithPrefix(Property.VFS_CONTEXT_CLASSPATH_PROPERTY);
+     assertSame(pmE, pmK);
+ 
+     Map<String,String> pmL = tc.getAllPropertiesWithPrefix(Property.TABLE_ITERATOR_SCAN_PREFIX);
+     assertSame(pmG, pmL);
+   }
  }
diff --cc server/base/src/main/java/org/apache/accumulo/server/conf/NamespaceConfiguration.java
index ed48d1f,3898f8c..79e09a1
--- a/server/base/src/main/java/org/apache/accumulo/server/conf/NamespaceConfiguration.java
+++ b/server/base/src/main/java/org/apache/accumulo/server/conf/NamespaceConfiguration.java
@@@ -40,11 -42,16 +40,12 @@@ public class NamespaceConfiguration ext
  
    private final AccumuloConfiguration parent;
    private ZooCachePropertyAccessor propCacheAccessor = null;
 -  protected String namespaceId = null;
 +  protected Namespace.ID namespaceId = null;
    protected Instance inst = null;
    private ZooCacheFactory zcf = new ZooCacheFactory();
+   private final String path;
  
 -  public NamespaceConfiguration(String namespaceId, AccumuloConfiguration parent) {
 -    this(namespaceId, HdfsZooInstance.getInstance(), parent);
 -  }
 -
 -  public NamespaceConfiguration(String namespaceId, Instance inst, AccumuloConfiguration parent) {
 +  public NamespaceConfiguration(Namespace.ID namespaceId, Instance inst, AccumuloConfiguration parent) {
      this.inst = inst;
      this.parent = parent;
      this.namespaceId = namespaceId;
diff --cc server/base/src/main/java/org/apache/accumulo/server/conf/ServerConfigurationFactory.java
index 3cdde40,666c5eb..1169450
--- a/server/base/src/main/java/org/apache/accumulo/server/conf/ServerConfigurationFactory.java
+++ b/server/base/src/main/java/org/apache/accumulo/server/conf/ServerConfigurationFactory.java
@@@ -20,8 -21,7 +20,9 @@@ import java.util.HashMap
  import java.util.Map;
  
  import org.apache.accumulo.core.client.Instance;
+ import org.apache.accumulo.core.client.TableNotFoundException;
 +import org.apache.accumulo.core.client.impl.Namespace;
 +import org.apache.accumulo.core.client.impl.Table;
  import org.apache.accumulo.core.client.impl.Tables;
  import org.apache.accumulo.core.conf.AccumuloConfiguration;
  import org.apache.accumulo.core.conf.ConfigSanityCheck;
@@@ -164,8 -190,13 +165,13 @@@ public class ServerConfigurationFactor
      // can't hold the lock during the construction and validation of the config,
      // which may result in creating multiple objects for the same id, but that's ok.
      if (conf == null) {
-       // changed - include instance in constructor call
-       conf = new TableParentConfiguration(tableId, instance, getSystemConfiguration());
 -      String namespaceId;
++      Namespace.ID namespaceId;
+       try {
+         namespaceId = Tables.getNamespaceId(instance, tableId);
+       } catch (TableNotFoundException e) {
+         throw new RuntimeException(e);
+       }
 -      conf = new NamespaceConfiguration(namespaceId, instance, getConfiguration());
++      conf = new NamespaceConfiguration(namespaceId, instance, getSystemConfiguration());
        ConfigSanityCheck.validate(conf);
        synchronized (tableParentConfigs) {
          tableParentConfigs.get(instanceID).put(tableId, conf);
diff --cc server/base/src/test/java/org/apache/accumulo/server/master/balancer/HostRegexTableLoadBalancerTest.java
index e19d05b,10880a6..b0991b5
--- a/server/base/src/test/java/org/apache/accumulo/server/master/balancer/HostRegexTableLoadBalancerTest.java
+++ b/server/base/src/test/java/org/apache/accumulo/server/master/balancer/HostRegexTableLoadBalancerTest.java
@@@ -187,9 -185,14 +187,14 @@@ public class HostRegexTableLoadBalancer
                }
              }
            }
+ 
+           @Override
+           public long getUpdateCount() {
+             return 0;
+           }
          };
        }
 -    });
 +    }));
      Map<String,SortedMap<TServerInstance,TabletServerStatus>> groups = this.splitCurrentByRegex(createCurrent(15));
      Assert.assertEquals(2, groups.size());
      Assert.assertTrue(groups.containsKey(FOO.getTableName()));
@@@ -259,9 -261,14 +264,14 @@@
                }
              }
            }
+ 
+           @Override
+           public long getUpdateCount() {
+             return 0;
+           }
          };
        }
 -    });
 +    }));
      Assert.assertTrue(isIpBasedRegex());
      Map<String,SortedMap<TServerInstance,TabletServerStatus>> groups = this.splitCurrentByRegex(createCurrent(15));
      Assert.assertEquals(3, groups.size());

-- 
To stop receiving notification emails like this one, please contact
kturner@apache.org.