Commit 7a6131c4 authored by Dave Syer's avatar Dave Syer

Make InMemoryMetricRepository.increment() thread safe

parent eb246d6b
...@@ -31,18 +31,26 @@ public class InMemoryMetricRepository implements MetricRepository { ...@@ -31,18 +31,26 @@ public class InMemoryMetricRepository implements MetricRepository {
private ConcurrentMap<String, Measurement> metrics = new ConcurrentHashMap<String, Measurement>(); private ConcurrentMap<String, Measurement> metrics = new ConcurrentHashMap<String, Measurement>();
private ConcurrentMap<String, Object> locks = new ConcurrentHashMap<String, Object>();
@Override @Override
public void increment(String metricName, int amount, Date timestamp) { public void increment(String metricName, int amount, Date timestamp) {
Measurement current = this.metrics.get(metricName); Measurement current = this.metrics.get(metricName);
if (current != null) { if (current != null) {
Metric metric = current.getMetric(); Object lock = this.locks.putIfAbsent(metricName, new Object());
this.metrics.replace(metricName, current, if (lock == null) {
new Measurement(timestamp, metric.increment(amount))); lock = this.locks.get(metricName);
} }
else { synchronized (lock) {
this.metrics.putIfAbsent(metricName, new Measurement(timestamp, new Metric( current = this.metrics.get(metricName);
metricName, amount))); Metric metric = current.getMetric();
this.metrics.replace(metricName, current, new Measurement(timestamp,
metric.increment(amount)));
return;
}
} }
this.metrics.putIfAbsent(metricName, new Measurement(timestamp, new Metric(
metricName, amount)));
} }
@Override @Override
......
...@@ -16,24 +16,65 @@ ...@@ -16,24 +16,65 @@
package org.springframework.boot.actuate.metrics; package org.springframework.boot.actuate.metrics;
import org.junit.Ignore; import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.actuate.metrics.InMemoryMetricRepository;
import static org.junit.Assert.fail; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/** /**
* Tests for {@link InMemoryMetricRepository}. * Tests for {@link InMemoryMetricRepository}.
*/ */
@Ignore
public class InMemoryMetricRepositoryTests { public class InMemoryMetricRepositoryTests {
// FIXME write tests private InMemoryMetricRepository repository = new InMemoryMetricRepository();
// FIXME possibly also add Metric/Measurement tests
@Test
public void increment() {
this.repository.increment("foo", 1, new Date());
assertEquals(1.0, this.repository.findOne("foo").getValue(), 0.01);
}
@Test
public void incrementConcurrent() throws Exception {
Collection<Callable<Boolean>> tasks = new ArrayList<Callable<Boolean>>();
for (int i = 0; i < 100; i++) {
tasks.add(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
InMemoryMetricRepositoryTests.this.repository.increment("foo", 1,
new Date());
return true;
}
});
tasks.add(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
InMemoryMetricRepositoryTests.this.repository.increment("foo", -1,
new Date());
return true;
}
});
}
List<Future<Boolean>> all = Executors.newFixedThreadPool(10).invokeAll(tasks);
for (Future<Boolean> future : all) {
assertTrue(future.get(1, TimeUnit.SECONDS));
}
assertEquals(0, this.repository.findOne("foo").getValue(), 0.01);
}
@Test @Test
public void test() { public void set() {
fail("Not yet implemented"); this.repository.set("foo", 1, new Date());
assertEquals(1.0, this.repository.findOne("foo").getValue(), 0.01);
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment