You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by ch...@apache.org on 2016/06/20 08:50:15 UTC
svn commit: r1749275 - in /jackrabbit/oak/trunk/oak-core/src:
main/java/org/apache/jackrabbit/oak/plugins/metric/MetricStatisticsProvider.java
test/java/org/apache/jackrabbit/oak/plugins/metric/MetricStatisticsProviderTest.java
Author: chetanm
Date: Mon Jun 20 08:50:14 2016
New Revision: 1749275
URL: http://svn.apache.org/viewvc?rev=1749275&view=rev
Log:
OAK-4483 - Remove synchronized access requirement from MetricStatisticsProvider#getStats
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricStatisticsProvider.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/metric/MetricStatisticsProviderTest.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricStatisticsProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricStatisticsProvider.java?rev=1749275&r1=1749274&r2=1749275&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricStatisticsProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/metric/MetricStatisticsProvider.java Mon Jun 20 08:50:14 2016
@@ -21,7 +21,7 @@ package org.apache.jackrabbit.oak.plugin
import java.io.Closeable;
import java.util.Hashtable;
-import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
@@ -59,7 +59,7 @@ public class MetricStatisticsProvider im
private static final String JMX_TYPE_METRICS = "Metrics";
- private final Map<String, Stats> statsRegistry = Maps.newHashMap();
+ private final ConcurrentMap<String, Stats> statsRegistry = Maps.newConcurrentMap();
private final MetricRegistry registry;
private final JmxReporter reporter;
private final RepositoryStatisticsImpl repoStats;
@@ -125,17 +125,25 @@ public class MetricStatisticsProvider im
return repoStats;
}
- private synchronized <T extends Stats> T getStats(String name, StatsBuilder<T> builder, StatsOptions options) {
+ private <T extends Stats> T getStats(String name, StatsBuilder<T> builder, StatsOptions options) {
Stats stats = statsRegistry.get(name);
+ //Use double locking pattern. The map should get populated with required set
+ //during startup phase so for later calls should not hit the synchronized block
if (stats == null) {
- if (options.isOnlyMetricEnabled()) {
- stats = builder.newMetric(this, name);
- } else if (options.isOnlyTimeSeriesEnabled()){
- stats = new SimpleStats(getTimerSeriesStats(name, builder), builder.getType());
- } else {
- stats = builder.newComposite(getTimerSeriesStats(name, builder), this, name);
+ synchronized (this){
+ stats = statsRegistry.get(name);
+ //If still null then go ahead and create it within lock
+ if (stats == null){
+ if (options.isOnlyMetricEnabled()) {
+ stats = builder.newMetric(this, name);
+ } else if (options.isOnlyTimeSeriesEnabled()) {
+ stats = new SimpleStats(getTimerSeriesStats(name, builder), builder.getType());
+ } else {
+ stats = builder.newComposite(getTimerSeriesStats(name, builder), this, name);
+ }
+ statsRegistry.put(name, stats);
+ }
}
- statsRegistry.put(name, stats);
}
if (builder.isInstance(stats)) {
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/metric/MetricStatisticsProviderTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/metric/MetricStatisticsProviderTest.java?rev=1749275&r1=1749274&r2=1749275&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/metric/MetricStatisticsProviderTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/metric/MetricStatisticsProviderTest.java Mon Jun 20 08:50:14 2016
@@ -20,7 +20,11 @@
package org.apache.jackrabbit.oak.plugins.metric;
import java.lang.management.ManagementFactory;
+import java.util.List;
+import java.util.Queue;
import java.util.Set;
+import java.util.concurrent.ConcurrentLinkedDeque;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@@ -32,6 +36,9 @@ import javax.management.Query;
import javax.management.QueryExp;
import com.codahale.metrics.JmxReporter;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.common.util.concurrent.Uninterruptibles;
import org.apache.jackrabbit.api.stats.RepositoryStatistics.Type;
import org.apache.jackrabbit.oak.stats.CounterStats;
import org.apache.jackrabbit.oak.stats.HistogramStats;
@@ -142,6 +149,44 @@ public class MetricStatisticsProviderTes
assertInstanceOf(statsProvider.getTimer("fooTimer", StatsOptions.DEFAULT), CompositeStats.class);
}
+ @Test
+ public void concurrentAccess() throws Exception{
+ //Queue is used to collect instances with minimal overhead in concurrent scenario
+ final Queue<MeterStats> statsQueue = new ConcurrentLinkedDeque<MeterStats>();
+ List<Thread> threads = Lists.newArrayList();
+ int numWorker = 5;
+ final CountDownLatch latch = new CountDownLatch(1);
+ for (int i = 0; i < numWorker; i++) {
+ threads.add(new Thread(new Runnable() {
+ @Override
+ public void run() {
+ Uninterruptibles.awaitUninterruptibly(latch);
+ statsQueue.add(statsProvider.getMeter("foo", StatsOptions.DEFAULT));
+ }
+ }));
+ }
+
+ for (Thread t : threads){
+ t.start();
+ }
+
+ latch.countDown();
+
+ for (Thread t : threads){
+ t.join();
+ }
+
+ //Assert that we get same reference for every call
+ Set<MeterStats> statsSet = Sets.newIdentityHashSet();
+
+ for (MeterStats m : statsQueue){
+ statsSet.add(m);
+ }
+
+ assertEquals(1, statsSet.size());
+
+ }
+
@After
public void cleanup() {
statsProvider.close();