From: Simon Brandhof Date: Fri, 8 Jun 2012 10:41:28 +0000 (+0200) Subject: SONAR-3565 do not lock METRICS and CHARACTERISTICS during purges X-Git-Tag: 3.1~7 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=9d6977c25ec8f671d94a24b245ddb378eda41c12;p=sonarqube.git SONAR-3565 do not lock METRICS and CHARACTERISTICS during purges --- diff --git a/sonar-core/src/main/java/org/sonar/core/purge/PurgeCommands.java b/sonar-core/src/main/java/org/sonar/core/purge/PurgeCommands.java index d6b26da3cbe..1f2e9bb787f 100644 --- a/sonar-core/src/main/java/org/sonar/core/purge/PurgeCommands.java +++ b/sonar-core/src/main/java/org/sonar/core/purge/PurgeCommands.java @@ -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 resourceIds, SqlSession session, PurgeMapper mapper, PurgeVendorMapper vendorMapper) { + PurgeCommands(SqlSession session) { + this(session, session.getMapper(PurgeMapper.class), session.getMapper(PurgeVendorMapper.class)); + } + + List selectSnapshotIds(PurgeSnapshotQuery query) { + return purgeMapper.selectSnapshotIds(query); + } + + void deleteResources(List 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 snapshotIds, final SqlSession session, final PurgeMapper mapper) { + private void deleteSnapshots(final List 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 snapshotIds, final SqlSession session, final PurgeMapper mapper) { + private void purgeSnapshots(final List 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 metricIdsWithoutHistoricalData = purgeMapper.selectMetricIdsWithoutHistoricalData(); for (Long snapshotId : snapshotIds) { - mapper.deleteSnapshotWastedMeasures(snapshotId); + purgeMapper.deleteSnapshotWastedMeasures(snapshotId, metricIdsWithoutHistoricalData); } session.commit(); + List 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(); } diff --git a/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java b/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java index d4caa191ce3..73b1487a330 100644 --- a/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java +++ b/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java @@ -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 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 projectSnapshotIds = purgeMapper.selectSnapshotIds( - PurgeSnapshotQuery.create().setResourceId(project.getId()).setIslast(false).setNotPurged(true) + private void purge(ResourceDto project, String[] scopesWithoutHistoricalData, PurgeCommands purgeCommands) { + List 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 childrenIds = mapper.selectProjectIdsByRootId(rootProjectId); for (Long childId : childrenIds) { - deleteProject(childId, session, mapper, vendorMapper); + deleteProject(childId, mapper, commands); } List 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 { diff --git a/sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java b/sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java index 3ec22dde831..451b45329f1 100644 --- a/sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java @@ -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 selectMetricIdsWithoutHistoricalData(); + + List selectCharacteristicIdsToPurge(); + + void deleteSnapshotWastedMeasures(@Param("sid") long snapshotId, @Param("mids") List metricIds); - void deleteSnapshotMeasuresOnQualityModelRequirements(long snapshotId); + void deleteSnapshotMeasuresOnCharacteristics(@Param("sid") long snapshotId, @Param("cids") List characteristicIds); void updatePurgeStatusToOne(long snapshotId); diff --git a/sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml b/sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml index 3dd26e27931..63c2312565a 100644 --- a/sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml @@ -68,6 +68,14 @@ and not exists(select s.project_id from snapshots s where s.islast=${_true} and s.project_id=p.id) + + + + @@ -108,14 +116,28 @@ delete from snapshots where id=#{id} - - 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 from project_measures where snapshot_id=#{id} and - characteristic_id in (select id from characteristics where rule_id is not null) + + delete from project_measures where snapshot_id=#{sid} and + (rule_id is not null or person_id is not null or metric_id in + + (-1) + + + #{mid} + + ) + + + + delete from project_measures where snapshot_id=#{sid} + + and ( + characteristic_id=#{cid} + ) + + + and characteristic_id=-1 + diff --git a/sonar-core/src/test/java/org/sonar/core/purge/PurgeCommandsTest.java b/sonar-core/src/test/java/org/sonar/core/purge/PurgeCommandsTest.java index 4ffe7272474..cd200b5e8e3 100644 --- a/sonar-core/src/test/java/org/sonar/core/purge/PurgeCommandsTest.java +++ b/sonar-core/src/test/java/org/sonar/core/purge/PurgeCommandsTest.java @@ -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); }