summaryrefslogtreecommitdiffstats
path: root/sonar-batch
diff options
context:
space:
mode:
authorJulien HENRY <julien.henry@sonarsource.com>2014-06-18 10:10:36 +0200
committerJulien HENRY <julien.henry@sonarsource.com>2014-06-18 16:26:00 +0200
commitf3ce69889f1a33e07d81ba20e052eebe599a03bc (patch)
tree6796efe303ada02c43fc0650a8a06362c4ce81a5 /sonar-batch
parent383f66769521484085f7ffe3aea3a6f3878b213e (diff)
downloadsonarqube-f3ce69889f1a33e07d81ba20e052eebe599a03bc.tar.gz
sonarqube-f3ce69889f1a33e07d81ba20e052eebe599a03bc.zip
Try to improve performance of MeasurePersister
Diffstat (limited to 'sonar-batch')
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/index/Caches.java7
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureCache.java5
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureValueCoder.java86
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/measure/MeasureCacheTest.java69
4 files changed, 160 insertions, 7 deletions
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/Caches.java b/sonar-batch/src/main/java/org/sonar/batch/index/Caches.java
index ab32231dbea..1e8c53d8853 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/index/Caches.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/index/Caches.java
@@ -25,6 +25,8 @@ import com.persistit.Exchange;
import com.persistit.Persistit;
import com.persistit.Value;
import com.persistit.Volume;
+import com.persistit.encoding.CoderManager;
+import com.persistit.encoding.ValueCoder;
import com.persistit.exception.PersistitException;
import com.persistit.logging.Slf4jAdapter;
import org.apache.commons.io.FileUtils;
@@ -78,6 +80,11 @@ public class Caches implements BatchComponent, Startable {
}
}
+ public void registerValueCoder(Class<?> clazz, ValueCoder coder) {
+ CoderManager cm = persistit.getCoderManager();
+ cm.registerValueCoder(clazz, coder);
+ }
+
public <V extends Serializable> Cache<V> createCache(String cacheName) {
Preconditions.checkState(volume != null && volume.isOpened(), "Caches are not initialized");
Preconditions.checkState(!cacheNames.contains(cacheName), "Cache is already created: " + cacheName);
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureCache.java b/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureCache.java
index e3732308cf5..a3d23bf4fde 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureCache.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureCache.java
@@ -22,8 +22,10 @@ package org.sonar.batch.scan.measure;
import com.google.common.base.Preconditions;
import org.sonar.api.BatchComponent;
import org.sonar.api.measures.Measure;
+import org.sonar.api.measures.MetricFinder;
import org.sonar.api.measures.RuleMeasure;
import org.sonar.api.resources.Resource;
+import org.sonar.api.technicaldebt.batch.TechnicalDebtModel;
import org.sonar.batch.index.Cache;
import org.sonar.batch.index.Cache.Entry;
import org.sonar.batch.index.Caches;
@@ -35,7 +37,8 @@ public class MeasureCache implements BatchComponent {
private final Cache<Measure> cache;
- public MeasureCache(Caches caches) {
+ public MeasureCache(Caches caches, MetricFinder metricFinder, TechnicalDebtModel techDebtModel) {
+ caches.registerValueCoder(Measure.class, new MeasureValueCoder(metricFinder, techDebtModel));
cache = caches.createCache("measures");
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureValueCoder.java b/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureValueCoder.java
new file mode 100644
index 00000000000..ccda40c429b
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureValueCoder.java
@@ -0,0 +1,86 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.scan.measure;
+
+import com.persistit.Value;
+import com.persistit.encoding.CoderContext;
+import com.persistit.encoding.ValueCoder;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.measures.MetricFinder;
+import org.sonar.api.measures.PersistenceMode;
+import org.sonar.api.technicaldebt.batch.TechnicalDebtModel;
+
+class MeasureValueCoder implements ValueCoder {
+
+ private final MetricFinder metricFinder;
+ private final TechnicalDebtModel techDebtModel;
+
+ public MeasureValueCoder(MetricFinder metricFinder, TechnicalDebtModel techDebtModel) {
+ this.metricFinder = metricFinder;
+ this.techDebtModel = techDebtModel;
+ }
+
+ public void put(Value value, Object object, CoderContext context) {
+ Measure<?> m = (Measure) object;
+ value.putString(m.getMetricKey());
+ value.put(m.getValue());
+ value.putString(m.getData());
+ value.putString(m.getDescription());
+ value.putString(m.getAlertStatus() != null ? m.getAlertStatus().name() : null);
+ value.putString(m.getAlertText());
+ value.put(m.getTendency());
+ value.putDate(m.getDate());
+ value.put(m.getVariation1());
+ value.put(m.getVariation2());
+ value.put(m.getVariation3());
+ value.put(m.getVariation4());
+ value.put(m.getVariation5());
+ value.putString(m.getUrl());
+ value.put(m.getCharacteristic() != null ? m.getCharacteristic().id() : null);
+ value.put(m.getRequirement() != null ? m.getRequirement().id() : null);
+ value.put(m.getPersonId() != null ? m.getPersonId().intValue() : null);
+ value.putString(m.getPersistenceMode() != null ? m.getPersistenceMode().name() : null);
+ }
+
+ public Object get(Value value, Class clazz, CoderContext context) {
+ Measure<?> m = new Measure();
+ String metricKey = value.getString();
+ m.setMetric(metricFinder.findByKey(metricKey));
+ m.setRawValue(value.isNull(true) ? null : value.getDouble());
+ m.setData(value.getString());
+ m.setDescription(value.getString());
+ m.setAlertStatus(value.isNull(true) ? null : Metric.Level.valueOf(value.getString()));
+ m.setAlertText(value.getString());
+ m.setTendency(value.isNull(true) ? null : value.getInt());
+ m.setDate(value.getDate());
+ m.setVariation1(value.isNull(true) ? null : value.getDouble());
+ m.setVariation2(value.isNull(true) ? null : value.getDouble());
+ m.setVariation3(value.isNull(true) ? null : value.getDouble());
+ m.setVariation4(value.isNull(true) ? null : value.getDouble());
+ m.setVariation5(value.isNull(true) ? null : value.getDouble());
+ m.setUrl(value.getString());
+ m.setCharacteristic(value.isNull(true) ? null : techDebtModel.characteristicById(value.getInt()));
+ m.setRequirement(value.isNull(true) ? null : techDebtModel.requirementsById(value.getInt()));
+ m.setPersonId(value.isNull(true) ? null : value.getInt());
+ m.setPersistenceMode(value.isNull(true) ? null : PersistenceMode.valueOf(value.getString()));
+ return m;
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/measure/MeasureCacheTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/measure/MeasureCacheTest.java
index 2e086f16627..82653d849fc 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/measure/MeasureCacheTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/measure/MeasureCacheTest.java
@@ -19,6 +19,7 @@
*/
package org.sonar.batch.scan.measure;
+import org.apache.commons.lang.builder.EqualsBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
@@ -27,6 +28,8 @@ import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Measure;
+import org.sonar.api.measures.Metric.Level;
+import org.sonar.api.measures.MetricFinder;
import org.sonar.api.measures.RuleMeasure;
import org.sonar.api.resources.Directory;
import org.sonar.api.resources.File;
@@ -34,6 +37,9 @@ import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rules.RulePriority;
+import org.sonar.api.technicaldebt.batch.Characteristic;
+import org.sonar.api.technicaldebt.batch.Requirement;
+import org.sonar.api.technicaldebt.batch.TechnicalDebtModel;
import org.sonar.api.technicaldebt.batch.internal.DefaultCharacteristic;
import org.sonar.batch.index.Cache.Entry;
import org.sonar.batch.index.Caches;
@@ -43,6 +49,8 @@ import java.util.Date;
import java.util.Iterator;
import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class MeasureCacheTest {
@@ -54,10 +62,17 @@ public class MeasureCacheTest {
Caches caches;
+ private MetricFinder metricFinder;
+
+ private TechnicalDebtModel techDebtModel;
+
@Before
public void start() throws Exception {
caches = CachesTest.createCacheOnTemp(temp);
caches.start();
+ metricFinder = mock(MetricFinder.class);
+ when(metricFinder.findByKey(CoreMetrics.NCLOC_KEY)).thenReturn(CoreMetrics.NCLOC);
+ techDebtModel = mock(TechnicalDebtModel.class);
}
@After
@@ -67,7 +82,7 @@ public class MeasureCacheTest {
@Test
public void should_add_measure() throws Exception {
- MeasureCache cache = new MeasureCache(caches);
+ MeasureCache cache = new MeasureCache(caches, metricFinder, techDebtModel);
Project p = new Project("struts");
assertThat(cache.entries()).hasSize(0);
@@ -102,7 +117,7 @@ public class MeasureCacheTest {
*/
@Test
public void should_add_measure_with_big_data() throws Exception {
- MeasureCache cache = new MeasureCache(caches);
+ MeasureCache cache = new MeasureCache(caches, metricFinder, techDebtModel);
Project p = new Project("struts");
assertThat(cache.entries()).hasSize(0);
@@ -142,7 +157,7 @@ public class MeasureCacheTest {
*/
@Test
public void should_add_measure_with_too_big_data_for_persistit_pre_patch() throws Exception {
- MeasureCache cache = new MeasureCache(caches);
+ MeasureCache cache = new MeasureCache(caches, metricFinder, techDebtModel);
Project p = new Project("struts");
assertThat(cache.entries()).hasSize(0);
@@ -178,7 +193,7 @@ public class MeasureCacheTest {
@Test
public void should_add_measure_with_too_big_data_for_persistit() throws Exception {
- MeasureCache cache = new MeasureCache(caches);
+ MeasureCache cache = new MeasureCache(caches, metricFinder, techDebtModel);
Project p = new Project("struts");
assertThat(cache.entries()).hasSize(0);
@@ -201,7 +216,7 @@ public class MeasureCacheTest {
@Test
public void should_add_measure_with_same_metric() throws Exception {
- MeasureCache cache = new MeasureCache(caches);
+ MeasureCache cache = new MeasureCache(caches, metricFinder, techDebtModel);
Project p = new Project("struts");
assertThat(cache.entries()).hasSize(0);
@@ -223,7 +238,7 @@ public class MeasureCacheTest {
@Test
public void should_get_measures() throws Exception {
- MeasureCache cache = new MeasureCache(caches);
+ MeasureCache cache = new MeasureCache(caches, metricFinder, techDebtModel);
Project p = new Project("struts");
Resource dir = new Directory("foo/bar").setEffectiveKey("struts:foo/bar");
Resource file1 = new File("foo/bar/File1.txt").setEffectiveKey("struts:foo/bar/File1.txt");
@@ -260,4 +275,46 @@ public class MeasureCacheTest {
assertThat(cache.byResource(dir)).hasSize(1);
assertThat(cache.byResource(dir).iterator().next()).isEqualTo(mDir);
}
+
+ @Test
+ public void test_measure_coder() throws Exception {
+ MeasureCache cache = new MeasureCache(caches, metricFinder, techDebtModel);
+ Resource file1 = new File("foo/bar/File1.txt").setEffectiveKey("struts:foo/bar/File1.txt");
+
+ Measure measure = new Measure(CoreMetrics.NCLOC, 1.786, 5);
+ cache.put(file1, measure);
+
+ Measure savedMeasure = cache.byResource(file1).iterator().next();
+
+ assertThat(EqualsBuilder.reflectionEquals(measure, savedMeasure)).isTrue();
+
+ measure = new Measure(CoreMetrics.NCLOC);
+ measure.setData("data");
+ measure.setAlertStatus(Level.ERROR);
+ measure.setAlertText("alert");
+ Characteristic c = mock(Characteristic.class);
+ when(c.id()).thenReturn(1);
+ when(techDebtModel.characteristicById(1)).thenReturn(c);
+ measure.setCharacteristic(c);
+ measure.setDate(new Date());
+ measure.setDescription("description");
+ measure.setPersistenceMode(null);
+ measure.setPersonId(3);
+ Requirement r = mock(Requirement.class);
+ when(r.id()).thenReturn(7);
+ when(techDebtModel.requirementsById(7)).thenReturn(r);
+ measure.setRequirement(r);
+ measure.setTendency(4);
+ measure.setUrl("http://foo");
+ measure.setVariation1(11.0);
+ measure.setVariation2(12.0);
+ measure.setVariation3(13.0);
+ measure.setVariation4(14.0);
+ measure.setVariation5(15.0);
+ cache.put(file1, measure);
+
+ savedMeasure = cache.byResource(file1).iterator().next();
+ assertThat(EqualsBuilder.reflectionEquals(measure, savedMeasure)).isTrue();
+
+ }
}