diff options
author | simonbrandhof <simon.brandhof@gmail.com> | 2012-01-26 23:13:09 +0100 |
---|---|---|
committer | simonbrandhof <simon.brandhof@gmail.com> | 2012-01-26 23:13:43 +0100 |
commit | 3a1b309e342a4b61cbc7ff06c6900150beee3573 (patch) | |
tree | bc197e0c36f2b7b7104aa68f4f80c8ba1b035d05 /sonar-core | |
parent | ec1df33232cfe41612c4f402abfa9e3262c65a2d (diff) | |
download | sonarqube-3a1b309e342a4b61cbc7ff06c6900150beee3573.tar.gz sonarqube-3a1b309e342a4b61cbc7ff06c6900150beee3573.zip |
SONAR-2757 improve reentrance of project deletion
Diffstat (limited to 'sonar-core')
8 files changed, 170 insertions, 49 deletions
diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/BatchSession.java b/sonar-core/src/main/java/org/sonar/core/persistence/BatchSession.java index 2a416fd11b3..4413fff3aee 100644 --- a/sonar-core/src/main/java/org/sonar/core/persistence/BatchSession.java +++ b/sonar-core/src/main/java/org/sonar/core/persistence/BatchSession.java @@ -46,21 +46,6 @@ public final class BatchSession implements SqlSession { this.batchSize = batchSize; } - /** - * This method must be called when executing SQL requests. - */ - public BatchSession increment(int nbSqlRequests) { - count += nbSqlRequests; - if (count >= batchSize) { - commit(); - } - return this; - } - - private void reset() { - count=0; - } - public void select(String statement, Object parameter, ResultHandler handler) { reset(); session.select(statement, parameter, handler); @@ -117,32 +102,32 @@ public final class BatchSession implements SqlSession { } public int insert(String statement) { - increment(1); + increment(); return session.insert(statement); } public int insert(String statement, Object parameter) { - increment(1); + increment(); return session.insert(statement, parameter); } public int update(String statement) { - increment(1); + increment(); return session.update(statement); } public int update(String statement, Object parameter) { - increment(1); + increment(); return session.update(statement, parameter); } public int delete(String statement) { - increment(1); + increment(); return session.delete(statement); } public int delete(String statement, Object parameter) { - increment(1); + increment(); return session.delete(statement, parameter); } @@ -192,4 +177,15 @@ public final class BatchSession implements SqlSession { return session.getConnection(); } + private BatchSession increment() { + count += 1; + if (count >= batchSize) { + commit(); + } + return this; + } + + private void reset() { + count = 0; + } } 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 726f59dcb52..e751cc32f20 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 @@ -24,7 +24,6 @@ import com.google.common.collect.Lists; import org.apache.ibatis.session.ResultContext; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.SqlSession; -import org.sonar.core.persistence.BatchSession; import org.sonar.core.persistence.MyBatis; import org.sonar.core.resource.ResourceDao; @@ -100,28 +99,33 @@ public class PurgeDao { } public PurgeDao deleteProject(long rootProjectId) { - final BatchSession session = mybatis.openBatchSession(); + final SqlSession session = mybatis.openBatchSession(); + final PurgeMapper mapper = session.getMapper(PurgeMapper.class); try { - final PurgeMapper mapper = session.getMapper(PurgeMapper.class); - List<Long> projectIds = resourceDao.getDescendantProjectIdsAndSelf(rootProjectId, session); - for (Long projectId : projectIds) { - session.select("org.sonar.core.purge.PurgeMapper.selectResourceIdsByRootId", projectId, new ResultHandler() { - public void handleResult(ResultContext context) { - Long resourceId = (Long) context.getResultObject(); - deleteResource(resourceId, session, mapper); - } - }); - } - session.commit(); + deleteProject(rootProjectId, session, mapper); return this; - } finally { MyBatis.closeQuietly(session); } } - void deleteResource(final long resourceId, final BatchSession session, final PurgeMapper mapper) { - session.select("org.sonar.core.purge.PurgeMapper.selectSnapshotIdsByResource", new ResultHandler() { + private void deleteProject(final long rootProjectId, final SqlSession session, final PurgeMapper mapper) { + List<Long> childrenIds = mapper.selectProjectIdsByRootId(rootProjectId); + for (Long childId : childrenIds) { + deleteProject(childId, session, mapper); + } + + session.select("org.sonar.core.purge.PurgeMapper.selectResourceTreeIdsByRootId", rootProjectId, new ResultHandler() { + public void handleResult(ResultContext context) { + Long resourceId = (Long) context.getResultObject(); + deleteResource(resourceId, session, mapper); + } + }); + session.commit(); + } + + void deleteResource(final long resourceId, final SqlSession session, final PurgeMapper mapper) { + session.select("org.sonar.core.purge.PurgeMapper.selectSnapshotIdsByResource", resourceId, new ResultHandler() { public void handleResult(ResultContext context) { Long snapshotId = (Long) context.getResultObject(); deleteSnapshot(snapshotId, mapper); @@ -149,7 +153,7 @@ public class PurgeDao { public PurgeDao deleteSnapshots(PurgeSnapshotQuery query) { - final BatchSession session = mybatis.openBatchSession(); + final SqlSession session = mybatis.openBatchSession(); try { final PurgeMapper mapper = session.getMapper(PurgeMapper.class); session.select("org.sonar.core.purge.PurgeMapper.selectSnapshotIds", query, new ResultHandler() { 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 31993b1896f..d663cd44c53 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 @@ -25,6 +25,8 @@ public interface PurgeMapper { List<Long> selectSnapshotIds(PurgeSnapshotQuery query); + List<Long> selectProjectIdsByRootId(long rootResourceId); + void deleteSnapshot(long snapshotId); void deleteSnapshotDependencies(long snapshotId); @@ -70,7 +72,7 @@ public interface PurgeMapper { void deleteResourceEvents(long resourceId); void closeResourceReviews(long resourceId); - + List<PurgeableSnapshotDto> selectPurgeableSnapshotsWithVersionEvent(long resourceId); List<PurgeableSnapshotDto> selectPurgeableSnapshotsWithoutVersionEvent(long resourceId); 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 e0a7f656c3d..34c85d4f7e2 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 @@ -34,7 +34,8 @@ </if> <if test="qualifiers != null"> and s.qualifier in - <foreach item="qualifier" index="index" collection="qualifiers" open="(" separator="," close=")">#{qualifier}</foreach> + <foreach item="qualifier" index="index" collection="qualifiers" open="(" separator="," close=")">#{qualifier} + </foreach> </if> <if test="withVersionEvent != null"> <if test="withVersionEvent"> @@ -48,13 +49,17 @@ </select> <select id="selectPurgeableSnapshotsWithVersionEvent" parameterType="long" resultType="PurgeableSnapshot"> - select s.id as "snapshotId", s.created_at as "date", ${_true} as "hasVersionEvent", islast as "isLast" from snapshots s - where s.project_id=#{id} and s.status='P' and s.qualifier <> 'LIB' and exists(select e.id from events e where e.snapshot_id=s.id and e.category='Version') + select s.id as "snapshotId", s.created_at as "date", ${_true} as "hasVersionEvent", islast as "isLast" from + snapshots s + where s.project_id=#{id} and s.status='P' and s.qualifier <> 'LIB' and exists(select e.id from events e where + e.snapshot_id=s.id and e.category='Version') </select> <select id="selectPurgeableSnapshotsWithoutVersionEvent" parameterType="long" resultType="PurgeableSnapshot"> - select s.id as "snapshotId", s.created_at as "date", ${_false} as "hasVersionEvent", islast as "isLast" from snapshots s - where s.project_id=#{id} and s.status='P' and s.qualifier <> 'LIB' and not exists(select e.id from events e where e.snapshot_id=s.id and e.category='Version') + select s.id as "snapshotId", s.created_at as "date", ${_false} as "hasVersionEvent", islast as "isLast" from + snapshots s + where s.project_id=#{id} and s.status='P' and s.qualifier <> 'LIB' and not exists(select e.id from events e + where e.snapshot_id=s.id and e.category='Version') </select> <select id="selectResourceIdsToDisable" resultType="long" parameterType="long"> @@ -63,7 +68,11 @@ and not exists(select s.project_id from snapshots s where s.islast=${_true} and s.project_id=p.id) </select> - <select id="selectResourceIdsByRootId" resultType="long" parameterType="long"> + <select id="selectProjectIdsByRootId" resultType="long" parameterType="long"> + select id from projects where root_id=#{id} and scope='PRJ' + </select> + + <select id="selectResourceTreeIdsByRootId" resultType="long" parameterType="long"> select id from projects where root_id=#{id} or id=#{id} </select> @@ -105,7 +114,8 @@ <delete id="deleteSnapshotWastedMeasures" parameterType="long"> delete from project_measures where snapshot_id=#{id} and - (characteristic_id is not null or rule_id is not null or metric_id in (select id from metrics where delete_historical_data=${_true})) + (characteristic_id is not null or rule_id is not null or metric_id in (select id from metrics where + delete_historical_data=${_true})) </delete> <update id="updatePurgeStatusToOne" parameterType="long"> diff --git a/sonar-core/src/test/java/org/sonar/core/persistence/DaoTestCase.java b/sonar-core/src/test/java/org/sonar/core/persistence/DaoTestCase.java index d7b54126fd4..02f6be17c39 100644 --- a/sonar-core/src/test/java/org/sonar/core/persistence/DaoTestCase.java +++ b/sonar-core/src/test/java/org/sonar/core/persistence/DaoTestCase.java @@ -185,7 +185,7 @@ public abstract class DaoTestCase { protected final void assertEmptyTables(String... emptyTables) { for (String table : emptyTables) { try { - Assert.assertEquals(0, getCurrentDataSet().getTable(table).getRowCount()); + Assert.assertEquals("Table " + table + " not empty.", 0, getCurrentDataSet().getTable(table).getRowCount()); } catch (DataSetException e) { throw translateException("Error while checking results", e); } diff --git a/sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java b/sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java index a165063ee30..c1a3541aeb0 100644 --- a/sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java @@ -29,7 +29,6 @@ import org.sonar.core.persistence.MyBatis; import org.sonar.core.resource.ResourceDao; import java.util.List; -import java.util.SortedSet; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; @@ -156,6 +155,28 @@ public class PurgeDaoTest extends DaoTestCase { assertThat(snapshots.size(), is(3)); } + @Test + public void shouldDeleteResource() { + setupData("shouldDeleteResource"); + SqlSession session = getMyBatis().openSession(); + try { + // this method does not commit and close the session + dao.deleteResource(1L, session, session.getMapper(PurgeMapper.class)); + session.commit(); + + } finally { + MyBatis.closeQuietly(session); + } + assertEmptyTables("projects", "snapshots", "events"); + } + + @Test + public void shouldDeleteProject() { + setupData("shouldDeleteProject"); + dao.deleteProject(1L); + assertEmptyTables("projects", "snapshots"); + } + static final class SnapshotMatcher extends BaseMatcher<PurgeableSnapshotDto> { long snapshotId; boolean isLast; @@ -169,7 +190,7 @@ public class PurgeDaoTest extends DaoTestCase { public boolean matches(Object o) { PurgeableSnapshotDto obj = (PurgeableSnapshotDto) o; - return obj.getSnapshotId() == snapshotId && obj.isLast()==isLast && obj.hasVersionEvent()==hasVersionEvent; + return obj.getSnapshotId() == snapshotId && obj.isLast() == isLast && obj.hasVersionEvent() == hasVersionEvent; } public void describeTo(Description description) { diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDeleteProject.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDeleteProject.xml new file mode 100644 index 00000000000..2a1e333079f --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDeleteProject.xml @@ -0,0 +1,67 @@ +<dataset> + + <!-- root --> + <projects id="1" enabled="true" root_id="[null]" + long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project" + description="[null]" language="java" copy_resource_id="[null]" profile_id="[null]"/> + + <snapshots id="1" project_id="1" parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" + status="P" islast="false" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" + build_date="2008-12-02 13:58:00.00" + version="[null]" path="[null]"/> + + + <!-- modules --> + <projects id="2" enabled="true" root_id="1" + long_name="[null]" scope="PRJ" qualifier="BRC" kee="module1" name="module1" + description="[null]" language="java" copy_resource_id="[null]" profile_id="[null]"/> + + <snapshots id="2" project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1" + status="P" islast="false" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="BRC" created_at="2008-12-02 13:58:00.00" + build_date="2008-12-02 13:58:00.00" + version="[null]" path="[null]"/> + + + <projects id="3" enabled="false" root_id="1" + long_name="[null]" scope="PRJ" qualifier="BRC" kee="module2" name="module2" + description="[null]" language="java" copy_resource_id="[null]" profile_id="[null]"/> + + <snapshots id="3" project_id="3" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1" + status="P" islast="true" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="BRC" created_at="2008-12-02 13:58:00.00" + build_date="2008-12-02 13:58:00.00" + version="[null]" path="[null]"/> + + <!-- file of module 2--> + <projects id="4" enabled="false" root_id="3" + long_name="[null]" scope="FIL" qualifier="FIL" kee="module2:File.java" name="File" + description="[null]" language="java" copy_resource_id="[null]" profile_id="[null]"/> + + <snapshots id="4" project_id="4" parent_snapshot_id="3" root_project_id="1" root_snapshot_id="1" + status="P" islast="true" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="FIL" qualifier="FIL" created_at="2008-12-02 13:58:00.00" + build_date="2008-12-02 13:58:00.00" + version="[null]" path="[null]"/> +</dataset>
\ No newline at end of file diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDeleteResource.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDeleteResource.xml new file mode 100644 index 00000000000..3ed5a6f4d36 --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDeleteResource.xml @@ -0,0 +1,21 @@ +<dataset> + + <projects id="1" enabled="true" root_id="[null]" + long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project" + description="[null]" language="java" copy_resource_id="[null]" profile_id="[null]"/> + + <snapshots id="1" project_id="1" parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" + status="P" islast="false" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" + build_date="2008-12-02 13:58:00.00" + version="[null]" path="[null]"/> + + <events id="1" name="Version 1.0" resource_id="1" snapshot_id="1" category="VERSION" description="[null]" + event_date="2008-12-02 13:58:00.00" created_at="[null]"/> + +</dataset>
\ No newline at end of file |