]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-3565 do not lock METRICS and CHARACTERISTICS during purges
authorSimon Brandhof <simon.brandhof@gmail.com>
Fri, 8 Jun 2012 10:41:28 +0000 (12:41 +0200)
committerSimon Brandhof <simon.brandhof@gmail.com>
Fri, 8 Jun 2012 10:41:28 +0000 (12:41 +0200)
sonar-core/src/main/java/org/sonar/core/purge/PurgeCommands.java
sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java
sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java
sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml
sonar-core/src/test/java/org/sonar/core/purge/PurgeCommandsTest.java

index d6b26da3cbeec5ddd52165692216b75753ac77b3..1f2e9bb787f73396777752abc5489c9d43ece142 100644 (file)
@@ -24,175 +24,190 @@ import org.apache.ibatis.session.SqlSession;
 
 import java.util.List;
 
-final class PurgeCommands {
-  private PurgeCommands() {
+class PurgeCommands {
+  private final SqlSession session;
+  private final PurgeMapper purgeMapper;
+  private final PurgeVendorMapper purgeVendorMapper;
+
+  PurgeCommands(SqlSession session, PurgeMapper purgeMapper, PurgeVendorMapper purgeVendorMapper) {
+    this.session = session;
+    this.purgeMapper = purgeMapper;
+    this.purgeVendorMapper = purgeVendorMapper;
   }
 
   @VisibleForTesting
-  static void deleteResources(List<Long> resourceIds, SqlSession session, PurgeMapper mapper, PurgeVendorMapper vendorMapper) {
+  PurgeCommands(SqlSession session) {
+    this(session, session.getMapper(PurgeMapper.class), session.getMapper(PurgeVendorMapper.class));
+  }
+
+  List<Long> selectSnapshotIds(PurgeSnapshotQuery query) {
+    return purgeMapper.selectSnapshotIds(query);
+  }
+
+  void deleteResources(List<Long> resourceIds) {
     // Note : do not merge the delete statements into a single loop of resource ids. It's
     // voluntarily grouped by tables in order to benefit from JDBC batch mode.
     // Batch requests can only relate to the same PreparedStatement.
 
     for (Long resourceId : resourceIds) {
-      deleteSnapshots(PurgeSnapshotQuery.create().setResourceId(resourceId), session, mapper);
+      deleteSnapshots(PurgeSnapshotQuery.create().setResourceId(resourceId));
     }
 
     // possible missing optimization: filter requests according to resource scope
 
     for (Long resourceId : resourceIds) {
-      mapper.deleteResourceLinks(resourceId);
+      purgeMapper.deleteResourceLinks(resourceId);
     }
     session.commit();
 
     for (Long resourceId : resourceIds) {
-      mapper.deleteResourceProperties(resourceId);
+      purgeMapper.deleteResourceProperties(resourceId);
     }
     session.commit();
 
     for (Long resourceId : resourceIds) {
-      mapper.deleteResourceIndex(resourceId);
+      purgeMapper.deleteResourceIndex(resourceId);
     }
     session.commit();
 
     for (Long resourceId : resourceIds) {
-      mapper.deleteResourceGroupRoles(resourceId);
+      purgeMapper.deleteResourceGroupRoles(resourceId);
     }
     session.commit();
 
     for (Long resourceId : resourceIds) {
-      mapper.deleteResourceUserRoles(resourceId);
+      purgeMapper.deleteResourceUserRoles(resourceId);
     }
     session.commit();
 
     for (Long resourceId : resourceIds) {
-      mapper.deleteResourceManualMeasures(resourceId);
+      purgeMapper.deleteResourceManualMeasures(resourceId);
     }
     session.commit();
 
     for (Long resourceId : resourceIds) {
-      vendorMapper.deleteResourceReviewComments(resourceId);
+      purgeVendorMapper.deleteResourceReviewComments(resourceId);
     }
     session.commit();
 
     for (Long resourceId : resourceIds) {
-      vendorMapper.deleteResourceActionPlansReviews(resourceId);
+      purgeVendorMapper.deleteResourceActionPlansReviews(resourceId);
     }
     session.commit();
 
     for (Long resourceId : resourceIds) {
-      mapper.deleteResourceReviews(resourceId);
+      purgeMapper.deleteResourceReviews(resourceId);
     }
     session.commit();
 
     for (Long resourceId : resourceIds) {
-      mapper.deleteResourceActionPlans(resourceId);
+      purgeMapper.deleteResourceActionPlans(resourceId);
     }
     session.commit();
 
     for (Long resourceId : resourceIds) {
-      mapper.deleteResourceEvents(resourceId);
+      purgeMapper.deleteResourceEvents(resourceId);
     }
     session.commit();
 
     for (Long resourceId : resourceIds) {
-      mapper.deleteResource(resourceId);
+      purgeMapper.deleteResource(resourceId);
     }
     session.commit();
 
     for (Long resourceId : resourceIds) {
-      mapper.deleteAuthors(resourceId);
+      purgeMapper.deleteAuthors(resourceId);
     }
     session.commit();
   }
 
-  @VisibleForTesting
-  static void deleteSnapshots(final PurgeSnapshotQuery query, final SqlSession session, final PurgeMapper mapper) {
-    deleteSnapshots(mapper.selectSnapshotIds(query), session, mapper);
+  void deleteSnapshots(final PurgeSnapshotQuery query) {
+    deleteSnapshots(purgeMapper.selectSnapshotIds(query));
   }
 
-  private static void deleteSnapshots(final List<Long> snapshotIds, final SqlSession session, final PurgeMapper mapper) {
+  private void deleteSnapshots(final List<Long> snapshotIds) {
     for (Long snapshotId : snapshotIds) {
-      mapper.deleteSnapshotDependencies(snapshotId);
+      purgeMapper.deleteSnapshotDependencies(snapshotId);
     }
     session.commit();
 
     for (Long snapshotId : snapshotIds) {
-      mapper.deleteSnapshotDuplications(snapshotId);
+      purgeMapper.deleteSnapshotDuplications(snapshotId);
     }
     session.commit();
 
     for (Long snapshotId : snapshotIds) {
-      mapper.deleteSnapshotEvents(snapshotId);
+      purgeMapper.deleteSnapshotEvents(snapshotId);
     }
     session.commit();
 
     for (Long snapshotId : snapshotIds) {
-      mapper.deleteSnapshotMeasureData(snapshotId);
+      purgeMapper.deleteSnapshotMeasureData(snapshotId);
     }
     session.commit();
 
     for (Long snapshotId : snapshotIds) {
-      mapper.deleteSnapshotMeasures(snapshotId);
+      purgeMapper.deleteSnapshotMeasures(snapshotId);
     }
     session.commit();
 
     for (Long snapshotId : snapshotIds) {
-      mapper.deleteSnapshotSource(snapshotId);
+      purgeMapper.deleteSnapshotSource(snapshotId);
     }
     session.commit();
 
     for (Long snapshotId : snapshotIds) {
-      mapper.deleteSnapshotViolations(snapshotId);
+      purgeMapper.deleteSnapshotViolations(snapshotId);
     }
     session.commit();
 
     for (Long snapshotId : snapshotIds) {
-      mapper.deleteSnapshot(snapshotId);
+      purgeMapper.deleteSnapshot(snapshotId);
     }
 
     session.commit();
   }
 
-  @VisibleForTesting
-  static void purgeSnapshots(final PurgeSnapshotQuery query, final SqlSession session, final PurgeMapper mapper) {
-    purgeSnapshots(mapper.selectSnapshotIds(query), session, mapper);
+  void purgeSnapshots(final PurgeSnapshotQuery query) {
+    purgeSnapshots(purgeMapper.selectSnapshotIds(query));
   }
 
-  private static void purgeSnapshots(final List<Long> snapshotIds, final SqlSession session, final PurgeMapper mapper) {
+  private void purgeSnapshots(final List<Long> snapshotIds) {
     // note that events are not deleted
     for (Long snapshotId : snapshotIds) {
-      mapper.deleteSnapshotDependencies(snapshotId);
+      purgeMapper.deleteSnapshotDependencies(snapshotId);
     }
     session.commit();
 
     for (Long snapshotId : snapshotIds) {
-      mapper.deleteSnapshotDuplications(snapshotId);
+      purgeMapper.deleteSnapshotDuplications(snapshotId);
     }
     session.commit();
 
     for (Long snapshotId : snapshotIds) {
-      mapper.deleteSnapshotSource(snapshotId);
+      purgeMapper.deleteSnapshotSource(snapshotId);
     }
     session.commit();
 
     for (Long snapshotId : snapshotIds) {
-      mapper.deleteSnapshotViolations(snapshotId);
+      purgeMapper.deleteSnapshotViolations(snapshotId);
     }
     session.commit();
 
+    List<Long> metricIdsWithoutHistoricalData = purgeMapper.selectMetricIdsWithoutHistoricalData();
     for (Long snapshotId : snapshotIds) {
-      mapper.deleteSnapshotWastedMeasures(snapshotId);
+      purgeMapper.deleteSnapshotWastedMeasures(snapshotId, metricIdsWithoutHistoricalData);
     }
     session.commit();
 
+    List<Long> characteristicIds = purgeMapper.selectCharacteristicIdsToPurge();
     for (Long snapshotId : snapshotIds) {
-      mapper.deleteSnapshotMeasuresOnQualityModelRequirements(snapshotId);
+      purgeMapper.deleteSnapshotMeasuresOnCharacteristics(snapshotId, characteristicIds);
     }
     session.commit();
 
     for (Long snapshotId : snapshotIds) {
-      mapper.updatePurgeStatusToOne(snapshotId);
+      purgeMapper.updatePurgeStatusToOne(snapshotId);
     }
     session.commit();
   }
index d4caa191ce30177db9f4ef1f145885d83632415a..73b1487a330130eb8e11917619b8bb783110e4d1 100644 (file)
@@ -50,12 +50,13 @@ public class PurgeDao {
   public PurgeDao purge(long rootResourceId, String[] scopesWithoutHistoricalData) {
     SqlSession session = mybatis.openBatchSession();
     PurgeMapper purgeMapper = session.getMapper(PurgeMapper.class);
+    PurgeCommands commands = new PurgeCommands(session, purgeMapper, session.getMapper(PurgeVendorMapper.class));
     try {
       List<ResourceDto> projects = getProjects(rootResourceId, session);
       for (ResourceDto project : projects) {
         LOG.info("-> Clean " + project.getLongName() + " [id=" + project.getId() + "]");
-        deleteAbortedBuilds(project, session, purgeMapper);
-        purge(project, scopesWithoutHistoricalData, session, purgeMapper);
+        deleteAbortedBuilds(project, commands);
+        purge(project, scopesWithoutHistoricalData, commands);
       }
       for (ResourceDto project : projects) {
         disableOrphanResources(project, session, purgeMapper);
@@ -66,48 +67,44 @@ public class PurgeDao {
     return this;
   }
 
-  private void deleteAbortedBuilds(ResourceDto project, SqlSession session, PurgeMapper purgeMapper) {
-    if (hasAbortedBuilds(project.getId(), purgeMapper)) {
+  private void deleteAbortedBuilds(ResourceDto project, PurgeCommands commands) {
+    if (hasAbortedBuilds(project.getId(), commands)) {
       LOG.info("<- Delete aborted builds");
       PurgeSnapshotQuery query = PurgeSnapshotQuery.create()
-          .setIslast(false)
-          .setStatus(new String[]{"U"})
-          .setRootProjectId(project.getId());
-      PurgeCommands.deleteSnapshots(query, session, purgeMapper);
-      session.commit();
+        .setIslast(false)
+        .setStatus(new String[]{"U"})
+        .setRootProjectId(project.getId());
+      commands.deleteSnapshots(query);
     }
   }
 
-  private boolean hasAbortedBuilds(Long projectId, PurgeMapper purgeMapper) {
+  private boolean hasAbortedBuilds(Long projectId, PurgeCommands commands) {
     PurgeSnapshotQuery query = PurgeSnapshotQuery.create()
-        .setIslast(false)
-        .setStatus(new String[]{"U"})
-        .setResourceId(projectId);
-    return !purgeMapper.selectSnapshotIds(query).isEmpty();
+      .setIslast(false)
+      .setStatus(new String[]{"U"})
+      .setResourceId(projectId);
+    return !commands.selectSnapshotIds(query).isEmpty();
   }
 
-  private void purge(final ResourceDto project, final String[] scopesWithoutHistoricalData, final SqlSession session, final PurgeMapper purgeMapper) {
-    List<Long> projectSnapshotIds = purgeMapper.selectSnapshotIds(
-        PurgeSnapshotQuery.create().setResourceId(project.getId()).setIslast(false).setNotPurged(true)
+  private void purge(ResourceDto project, String[] scopesWithoutHistoricalData, PurgeCommands purgeCommands) {
+    List<Long> projectSnapshotIds = purgeCommands.selectSnapshotIds(
+      PurgeSnapshotQuery.create().setResourceId(project.getId()).setIslast(false).setNotPurged(true)
     );
     for (final Long projectSnapshotId : projectSnapshotIds) {
       LOG.info("<- Clean snapshot " + projectSnapshotId);
       if (!ArrayUtils.isEmpty(scopesWithoutHistoricalData)) {
         PurgeSnapshotQuery query = PurgeSnapshotQuery.create()
-            .setIslast(false)
-            .setScopes(scopesWithoutHistoricalData)
-            .setRootSnapshotId(projectSnapshotId);
-        PurgeCommands.deleteSnapshots(query, session, purgeMapper);
-        session.commit();
+          .setIslast(false)
+          .setScopes(scopesWithoutHistoricalData)
+          .setRootSnapshotId(projectSnapshotId);
+        purgeCommands.deleteSnapshots(query);
       }
 
       PurgeSnapshotQuery query = PurgeSnapshotQuery.create().setRootSnapshotId(projectSnapshotId).setNotPurged(true);
-      PurgeCommands.purgeSnapshots(query, session, purgeMapper);
-      session.commit();
+      purgeCommands.purgeSnapshots(query);
 
       // must be executed at the end for reentrance
-      PurgeCommands.purgeSnapshots(PurgeSnapshotQuery.create().setId(projectSnapshotId).setNotPurged(true), session, purgeMapper);
-      session.commit();
+      purgeCommands.purgeSnapshots(PurgeSnapshotQuery.create().setId(projectSnapshotId).setNotPurged(true));
     }
   }
 
@@ -140,24 +137,22 @@ public class PurgeDao {
   public PurgeDao deleteResourceTree(long rootProjectId) {
     final SqlSession session = mybatis.openBatchSession();
     final PurgeMapper mapper = session.getMapper(PurgeMapper.class);
-    final PurgeVendorMapper vendorMapper = session.getMapper(PurgeVendorMapper.class);
     try {
-      deleteProject(rootProjectId, session, mapper, vendorMapper);
+      deleteProject(rootProjectId, mapper, new PurgeCommands(session));
       return this;
     } finally {
       MyBatis.closeQuietly(session);
     }
   }
 
-  private void deleteProject(long rootProjectId, SqlSession session, PurgeMapper mapper, PurgeVendorMapper vendorMapper) {
+  private void deleteProject(long rootProjectId, PurgeMapper mapper, PurgeCommands commands) {
     List<Long> childrenIds = mapper.selectProjectIdsByRootId(rootProjectId);
     for (Long childId : childrenIds) {
-      deleteProject(childId, session, mapper, vendorMapper);
+      deleteProject(childId, mapper, commands);
     }
 
     List<Long> resourceIds = mapper.selectResourceIdsByRootId(rootProjectId);
-    PurgeCommands.deleteResources(resourceIds, session, mapper, vendorMapper);
-    session.commit();
+    commands.deleteResources(resourceIds);
   }
 
   @VisibleForTesting
@@ -171,9 +166,7 @@ public class PurgeDao {
   public PurgeDao deleteSnapshots(PurgeSnapshotQuery query) {
     final SqlSession session = mybatis.openBatchSession();
     try {
-      final PurgeMapper mapper = session.getMapper(PurgeMapper.class);
-      PurgeCommands.deleteSnapshots(query, session, mapper);
-      session.commit();
+      new PurgeCommands(session).deleteSnapshots(query);
       return this;
 
     } finally {
index 3ec22dde831450cb212c0e47f6c17f03e9c884c0..451b45329f1e64b545e7712937164b159bd76f3a 100644 (file)
@@ -19,6 +19,8 @@
  */
 package org.sonar.core.purge;
 
+import org.apache.ibatis.annotations.Param;
+
 import java.util.List;
 
 public interface PurgeMapper {
@@ -43,9 +45,13 @@ public interface PurgeMapper {
 
   void deleteSnapshotViolations(long snapshotId);
 
-  void deleteSnapshotWastedMeasures(long snapshotId);
+  List<Long> selectMetricIdsWithoutHistoricalData();
+
+  List<Long> selectCharacteristicIdsToPurge();
+
+  void deleteSnapshotWastedMeasures(@Param("sid") long snapshotId, @Param("mids") List<Long> metricIds);
 
-  void deleteSnapshotMeasuresOnQualityModelRequirements(long snapshotId);
+  void deleteSnapshotMeasuresOnCharacteristics(@Param("sid") long snapshotId, @Param("cids") List<Long> characteristicIds);
 
   void updatePurgeStatusToOne(long snapshotId);
 
index 3dd26e2793147670e241e2b2f8818a4a4f4013f1..63c2312565a56c112021aebb4cb009c7e2adc78b 100644 (file)
     and not exists(select s.project_id from snapshots s where s.islast=${_true} and s.project_id=p.id)
   </select>
 
+  <select id="selectMetricIdsWithoutHistoricalData" resultType="long">
+    select id from metrics where delete_historical_data=${_true}
+  </select>
+
+  <select id="selectCharacteristicIdsToPurge" resultType="long">
+    select id from characteristics where rule_id is not null
+  </select>
+
   <select id="selectProjectIdsByRootId" resultType="long" parameterType="long">
     select id from projects where root_id=#{id} and scope='PRJ'
   </select>
     delete from snapshots where id=#{id}
   </delete>
 
-  <delete id="deleteSnapshotWastedMeasures" parameterType="long">
-    delete from project_measures where snapshot_id=#{id} and
-    (rule_id is not null or person_id is not null or metric_id in (select id from metrics where delete_historical_data=${_true}))
-  </delete>
-
-  <delete id="deleteSnapshotMeasuresOnQualityModelRequirements" parameterType="long">
-    delete from project_measures where snapshot_id=#{id} and
-    characteristic_id in (select id from characteristics where rule_id is not null)
+  <delete id="deleteSnapshotWastedMeasures" parameterType="map">
+    delete from project_measures where snapshot_id=#{sid} and
+    (rule_id is not null or person_id is not null or metric_id in
+    <if test="mids.isEmpty()">
+      (-1)
+    </if>
+    <if test="!mids.isEmpty()">
+      <foreach item="mid" index="index" collection="mids" open="(" separator="," close=")">#{mid}</foreach>
+    </if>
+    )
+  </delete>
+
+  <delete id="deleteSnapshotMeasuresOnCharacteristics" parameterType="map">
+    delete from project_measures where snapshot_id=#{sid}
+    <if test="!cids.isEmpty()">
+      and (
+      <foreach item="cid" index="index" collection="cids" open="" separator=" OR " close="">characteristic_id=#{cid}</foreach>
+      )
+    </if>
+    <if test="cids.isEmpty()">
+      and characteristic_id=-1
+    </if>
   </delete>
 
   <update id="updatePurgeStatusToOne" parameterType="long">
index 4ffe7272474b4390df1414117ccd8540cb6ea6c7..cd200b5e8e3ad4a2a8923b45eea4ceb7309ea388 100644 (file)
@@ -36,12 +36,12 @@ public class PurgeCommandsTest extends DaoTestCase {
 
     SqlSession session = getMyBatis().openSession();
     try {
-      PurgeCommands.deleteSnapshots(PurgeSnapshotQuery.create().setId(5L), session, session.getMapper(PurgeMapper.class));
+      new PurgeCommands(session).deleteSnapshots(PurgeSnapshotQuery.create().setId(5L));
     } finally {
       MyBatis.closeQuietly(session);
     }
     checkTables("shouldDeleteSnapshot",
-        "snapshots", "project_measures", "measure_data", "rule_failures", "snapshot_sources", "duplications_index", "events", "dependencies");
+      "snapshots", "project_measures", "measure_data", "rule_failures", "snapshot_sources", "duplications_index", "events", "dependencies");
   }
 
   /**
@@ -53,12 +53,12 @@ public class PurgeCommandsTest extends DaoTestCase {
 
     SqlSession session = getMyBatis().openSession();
     try {
-      PurgeCommands.purgeSnapshots(PurgeSnapshotQuery.create().setId(1L), session, session.getMapper(PurgeMapper.class));
+      new PurgeCommands(session).purgeSnapshots(PurgeSnapshotQuery.create().setId(1L));
     } finally {
       MyBatis.closeQuietly(session);
     }
     checkTables("shouldPurgeSnapshot",
-        "snapshots", "project_measures", "measure_data", "rule_failures", "snapshot_sources", "duplications_index", "events", "dependencies", "reviews");
+      "snapshots", "project_measures", "measure_data", "rule_failures", "snapshot_sources", "duplications_index", "events", "dependencies", "reviews");
   }
 
   @Test
@@ -67,7 +67,7 @@ public class PurgeCommandsTest extends DaoTestCase {
 
     SqlSession session = getMyBatis().openSession();
     try {
-      PurgeCommands.purgeSnapshots(PurgeSnapshotQuery.create().setId(1L), session, session.getMapper(PurgeMapper.class));
+      new PurgeCommands(session).purgeSnapshots(PurgeSnapshotQuery.create().setId(1L));
     } finally {
       MyBatis.closeQuietly(session);
     }
@@ -79,7 +79,7 @@ public class PurgeCommandsTest extends DaoTestCase {
     setupData("shouldDeleteResource");
     SqlSession session = getMyBatis().openSession();
     try {
-      PurgeCommands.deleteResources(Arrays.asList(1L), session, session.getMapper(PurgeMapper.class), session.getMapper(PurgeVendorMapper.class));
+      new PurgeCommands(session).deleteResources(Arrays.asList(1L));
     } finally {
       MyBatis.closeQuietly(session);
     }