aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-core
diff options
context:
space:
mode:
authorsimonbrandhof <simon.brandhof@gmail.com>2012-01-26 23:13:09 +0100
committersimonbrandhof <simon.brandhof@gmail.com>2012-01-26 23:13:43 +0100
commit3a1b309e342a4b61cbc7ff06c6900150beee3573 (patch)
treebc197e0c36f2b7b7104aa68f4f80c8ba1b035d05 /sonar-core
parentec1df33232cfe41612c4f402abfa9e3262c65a2d (diff)
downloadsonarqube-3a1b309e342a4b61cbc7ff06c6900150beee3573.tar.gz
sonarqube-3a1b309e342a4b61cbc7ff06c6900150beee3573.zip
SONAR-2757 improve reentrance of project deletion
Diffstat (limited to 'sonar-core')
-rw-r--r--sonar-core/src/main/java/org/sonar/core/persistence/BatchSession.java38
-rw-r--r--sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java38
-rw-r--r--sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java4
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml24
-rw-r--r--sonar-core/src/test/java/org/sonar/core/persistence/DaoTestCase.java2
-rw-r--r--sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java25
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDeleteProject.xml67
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDeleteResource.xml21
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 &lt;&gt; '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 &lt;&gt; '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 &lt;&gt; '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 &lt;&gt; '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