Skip to content

Commit

Permalink
optimize array parser
Browse files Browse the repository at this point in the history
  • Loading branch information
nobodyiam committed Jan 24, 2017
1 parent 95cf37c commit 97d98f1
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

import com.ctrip.framework.apollo.Config;
Expand All @@ -28,6 +29,7 @@
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ExecutorService;
Expand All @@ -53,6 +55,7 @@ public abstract class AbstractConfig implements Config {
private volatile Cache<String, Boolean> m_booleanCache;
private volatile Cache<String, Date> m_dateCache;
private volatile Cache<String, Long> m_durationCache;
private Map<String, Cache<String, String[]>> m_arrayCache;
private List<Cache> allCaches;
private AtomicLong m_configVersion; //indicate config version

Expand All @@ -65,6 +68,7 @@ public AbstractConfig() {
try {
m_configUtil = ContainerLoader.getDefaultContainer().lookup(ConfigUtil.class);
m_configVersion = new AtomicLong();
m_arrayCache = Maps.newConcurrentMap();
allCaches = Lists.newArrayList();
} catch (ComponentLookupException ex) {
Tracer.logError(ex);
Expand Down Expand Up @@ -220,13 +224,29 @@ public Boolean getBooleanProperty(String key, Boolean defaultValue) {
}

@Override
public String[] getArrayProperty(String key, String delimiter, String[] defaultValue) {
public String[] getArrayProperty(String key, final String delimiter, String[] defaultValue) {
try {
String value = getProperty(key, null);
if (!m_arrayCache.containsKey(delimiter)) {
synchronized (this) {
if (!m_arrayCache.containsKey(delimiter)) {
m_arrayCache.put(delimiter, this.<String[]>newCache());
}
}
}

if (value != null) {
return value.split(delimiter);
Cache<String, String[]> cache = m_arrayCache.get(delimiter);
String[] result = cache.getIfPresent(key);

if (result != null) {
return result;
}

return getValueAndStoreToCache(key, new Function<String, String[]>() {
@Override
public String[] apply(String input) {
return input.split(delimiter);
}
}, cache, defaultValue);
} catch (Throwable ex) {
Tracer.logError(new ApolloConfigException(
String.format("getArrayProperty for %s failed, return default value", key), ex));
Expand Down Expand Up @@ -334,11 +354,15 @@ private <T> T getValueFromCache(String key, Function<String, T> parser, Cache<St
return result;
}

return getValueAndStoreToCache(key, parser, cache, defaultValue);
}

private <T> T getValueAndStoreToCache(String key, Function<String, T> parser, Cache<String, T> cache, T defaultValue) {
long currentConfigVersion = m_configVersion.get();
String value = getProperty(key, null);

if (value != null) {
result = parser.apply(value);
T result = parser.apply(value);

if (result != null) {
synchronized (this) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,68 @@ public void testGetArrayProperty() throws Exception {
someDefaultValue));
}

@Test
public void testGetArrayPropertyMultipleTimesWithCache() throws Exception {
String someKey = "someKey";
String someDelimiter = ",";
String someInvalidDelimiter = "{";

String[] values = new String[]{"a", "b", "c"};
String someValue = Joiner.on(someDelimiter).join(values);

String[] someDefaultValue = new String[]{"1", "2"};

//set up config repo
someProperties = mock(Properties.class);
when(someProperties.getProperty(someKey)).thenReturn(someValue);
when(configRepository.getConfig()).thenReturn(someProperties);

DefaultConfig defaultConfig =
new DefaultConfig(someNamespace, configRepository);

assertArrayEquals(values, defaultConfig.getArrayProperty(someKey, someDelimiter, someDefaultValue));
assertArrayEquals(values, defaultConfig.getArrayProperty(someKey, someDelimiter, someDefaultValue));

verify(someProperties, times(1)).getProperty(someKey);

assertArrayEquals(someDefaultValue, defaultConfig.getArrayProperty(someKey, someInvalidDelimiter,
someDefaultValue));
assertArrayEquals(someDefaultValue, defaultConfig.getArrayProperty(someKey, someInvalidDelimiter,
someDefaultValue));

verify(someProperties, times(3)).getProperty(someKey);
}

@Test
public void testGetArrayPropertyMultipleTimesWithCacheAndValueChanges() throws Exception {
String someKey = "someKey";
String someDelimiter = ",";

String[] values = new String[]{"a", "b", "c"};
String[] anotherValues = new String[]{"b", "c", "d"};
String someValue = Joiner.on(someDelimiter).join(values);
String anotherValue = Joiner.on(someDelimiter).join(anotherValues);

String[] someDefaultValue = new String[]{"1", "2"};

//set up config repo
someProperties = new Properties();
someProperties.setProperty(someKey, someValue);
when(configRepository.getConfig()).thenReturn(someProperties);

Properties anotherProperties = new Properties();
anotherProperties.setProperty(someKey, anotherValue);

DefaultConfig defaultConfig =
new DefaultConfig(someNamespace, configRepository);

assertArrayEquals(values, defaultConfig.getArrayProperty(someKey, someDelimiter, someDefaultValue));

defaultConfig.onRepositoryChange(someNamespace, anotherProperties);

assertArrayEquals(anotherValues, defaultConfig.getArrayProperty(someKey, someDelimiter, someDefaultValue));
}

@Test
public void testGetDatePropertyWithFormat() throws Exception {
Date someDefaultValue = new Date();
Expand Down

0 comments on commit 97d98f1

Please sign in to comment.