aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-core
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@gmail.com>2012-03-05 16:04:44 +0100
committerSimon Brandhof <simon.brandhof@gmail.com>2012-03-05 16:04:44 +0100
commit5209fac8c90c46ba4dd6d9ce73eae7f2dc428a9b (patch)
treeb12cea78009c77471fea3c873afa92ad093ce167 /sonar-core
parent15efef19303c240d12ec345e774987ba8a075d8d (diff)
downloadsonarqube-5209fac8c90c46ba4dd6d9ce73eae7f2dc428a9b.tar.gz
sonarqube-5209fac8c90c46ba4dd6d9ce73eae7f2dc428a9b.zip
Improve batch execution of DELETE statements in PurgeDao
Diffstat (limited to 'sonar-core')
-rw-r--r--sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java139
-rw-r--r--sonar-core/src/main/java/org/sonar/core/purge/PurgeSnapshotQuery.java10
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml9
-rw-r--r--sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java37
-rw-r--r--sonar-core/src/test/java/org/sonar/core/resource/ResourceDaoTest.java21
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDeleteAbortedBuilds-result.xml46
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDeleteAbortedBuilds.xml41
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/resource/ResourceDaoTest/fixture.xml2
8 files changed, 224 insertions, 81 deletions
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 72322a2e180..3a262e92f19 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
@@ -34,6 +34,9 @@ import org.sonar.core.resource.ResourceDto;
import java.util.Collections;
import java.util.List;
+/**
+ * @since 2.14
+ */
public class PurgeDao {
private final MyBatis mybatis;
private final ResourceDao resourceDao;
@@ -50,10 +53,10 @@ public class PurgeDao {
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);
}
-
for (ResourceDto project : projects) {
disableOrphanResources(project, session, purgeMapper);
}
@@ -65,12 +68,13 @@ public class PurgeDao {
private void deleteAbortedBuilds(ResourceDto project, SqlSession session, PurgeMapper purgeMapper) {
if (hasAbortedBuilds(project.getId(), purgeMapper)) {
- LOG.info("<- Deleting aborted builds of " + project.getLongName());
+ LOG.info("<- Delete aborted builds");
PurgeSnapshotQuery query = PurgeSnapshotQuery.create()
.setIslast(false)
.setStatus(new String[]{"U"})
.setRootProjectId(project.getId());
- deleteSnapshots(query, session, purgeMapper);
+ deleteSnapshots(query, purgeMapper);
+ session.commit();
}
}
@@ -87,29 +91,24 @@ public class PurgeDao {
PurgeSnapshotQuery.create().setResourceId(project.getId()).setIslast(false).setNotPurged(true)
);
for (final Long projectSnapshotId : projectSnapshotIds) {
- // TODO log date
+ LOG.info("<- Clean snapshot " + projectSnapshotId);
if (!ArrayUtils.isEmpty(scopesWithoutHistoricalData)) {
PurgeSnapshotQuery query = PurgeSnapshotQuery.create()
.setIslast(false)
.setScopes(scopesWithoutHistoricalData)
.setRootSnapshotId(projectSnapshotId);
- deleteSnapshots(query, session, purgeMapper);
+ deleteSnapshots(query, purgeMapper);
+ session.commit();
}
PurgeSnapshotQuery query = PurgeSnapshotQuery.create().setRootSnapshotId(projectSnapshotId).setNotPurged(true);
- session.select("org.sonar.core.purge.PurgeMapper.selectSnapshotIds", query, new ResultHandler() {
- public void handleResult(ResultContext resultContext) {
- Long snapshotId = (Long) resultContext.getResultObject();
- if (snapshotId != null) {
- purgeSnapshot(snapshotId, purgeMapper);
- }
- }
- });
+ purgeSnapshots(query, purgeMapper);
+ session.commit();
// must be executed at the end for reentrance
- purgeSnapshot(projectSnapshotId, purgeMapper);
+ purgeSnapshots(PurgeSnapshotQuery.create().setId(projectSnapshotId).setNotPurged(true), purgeMapper);
+ session.commit();
}
- session.commit();
}
private void disableOrphanResources(final ResourceDto project, final SqlSession session, final PurgeMapper purgeMapper) {
@@ -144,6 +143,7 @@ public class PurgeDao {
final PurgeVendorMapper vendorMapper = session.getMapper(PurgeVendorMapper.class);
try {
deleteProject(rootProjectId, session, mapper, vendorMapper);
+ session.commit();
return this;
} finally {
MyBatis.closeQuietly(session);
@@ -160,22 +160,15 @@ public class PurgeDao {
public void handleResult(ResultContext context) {
Long resourceId = (Long) context.getResultObject();
if (resourceId != null) {
- deleteResource(resourceId, session, mapper, vendorMapper);
+ deleteResource(resourceId, mapper, vendorMapper);
}
}
});
- session.commit();
}
- void deleteResource(final long resourceId, final SqlSession session, final PurgeMapper mapper, final PurgeVendorMapper vendorMapper) {
- session.select("org.sonar.core.purge.PurgeMapper.selectSnapshotIdsByResource", resourceId, new ResultHandler() {
- public void handleResult(ResultContext context) {
- Long snapshotId = (Long) context.getResultObject();
- if (snapshotId != null) {
- deleteSnapshot(snapshotId, mapper);
- }
- }
- });
+ void deleteResource(final long resourceId, final PurgeMapper mapper, final PurgeVendorMapper vendorMapper) {
+ deleteSnapshots(PurgeSnapshotQuery.create().setResourceId(resourceId), mapper);
+
// possible optimization: filter requests according to resource scope
mapper.deleteResourceLinks(resourceId);
mapper.deleteResourceProperties(resourceId);
@@ -203,7 +196,7 @@ public class PurgeDao {
final SqlSession session = mybatis.openBatchSession();
try {
final PurgeMapper mapper = session.getMapper(PurgeMapper.class);
- deleteSnapshots(query, session, mapper);
+ deleteSnapshots(mapper.selectSnapshotIds(query), mapper);
session.commit();
return this;
@@ -212,15 +205,66 @@ public class PurgeDao {
}
}
- private void deleteSnapshots(PurgeSnapshotQuery query, SqlSession session, final PurgeMapper mapper) {
- session.select("org.sonar.core.purge.PurgeMapper.selectSnapshotIds", query, new ResultHandler() {
- public void handleResult(ResultContext context) {
- Long snapshotId = (Long) context.getResultObject();
- if (snapshotId != null) {
- deleteSnapshot(snapshotId, mapper);
- }
- }
- });
+ @VisibleForTesting
+ void deleteSnapshots(final PurgeSnapshotQuery query, final PurgeMapper mapper) {
+ deleteSnapshots(mapper.selectSnapshotIds(query), mapper);
+ }
+
+ private void deleteSnapshots(final List<Long> snapshotIds, final PurgeMapper mapper) {
+ for (Long snapshotId : snapshotIds) {
+ mapper.deleteSnapshotDependencies(snapshotId);
+ }
+ for (Long snapshotId : snapshotIds) {
+ mapper.deleteSnapshotDuplications(snapshotId);
+ }
+ for (Long snapshotId : snapshotIds) {
+ mapper.deleteSnapshotEvents(snapshotId);
+ }
+ for (Long snapshotId : snapshotIds) {
+ mapper.deleteSnapshotMeasureData(snapshotId);
+ }
+ for (Long snapshotId : snapshotIds) {
+ mapper.deleteSnapshotMeasures(snapshotId);
+ }
+ for (Long snapshotId : snapshotIds) {
+ mapper.deleteSnapshotSource(snapshotId);
+ }
+ for (Long snapshotId : snapshotIds) {
+ mapper.deleteSnapshotViolations(snapshotId);
+ }
+ for (Long snapshotId : snapshotIds) {
+ mapper.deleteSnapshot(snapshotId);
+ }
+ }
+
+ @VisibleForTesting
+ void purgeSnapshots(final PurgeSnapshotQuery query, final PurgeMapper mapper) {
+ purgeSnapshots(mapper.selectSnapshotIds(query), mapper);
+ }
+
+ private void purgeSnapshots(final List<Long> snapshotIds, final PurgeMapper mapper) {
+ // note that events are not deleted
+ for (Long snapshotId : snapshotIds) {
+ mapper.deleteSnapshotDependencies(snapshotId);
+ }
+ for (Long snapshotId : snapshotIds) {
+ mapper.deleteSnapshotDuplications(snapshotId);
+ }
+ for (Long snapshotId : snapshotIds) {
+ mapper.deleteSnapshotSource(snapshotId);
+ }
+ for (Long snapshotId : snapshotIds) {
+ mapper.deleteSnapshotViolations(snapshotId);
+ }
+ for (Long snapshotId : snapshotIds) {
+ mapper.deleteSnapshotWastedMeasures(snapshotId);
+ }
+ for (Long snapshotId : snapshotIds) {
+ mapper.deleteSnapshotMeasuresOnQualityModelRequirements(snapshotId);
+ }
+ for (Long snapshotId : snapshotIds) {
+ mapper.updatePurgeStatusToOne(snapshotId);
+ }
}
/**
@@ -233,27 +277,4 @@ public class PurgeDao {
return projects;
}
- @VisibleForTesting
- void purgeSnapshot(long snapshotId, PurgeMapper mapper) {
- // note that events are not deleted
- mapper.deleteSnapshotDependencies(snapshotId);
- mapper.deleteSnapshotDuplications(snapshotId);
- mapper.deleteSnapshotSource(snapshotId);
- mapper.deleteSnapshotViolations(snapshotId);
- mapper.deleteSnapshotWastedMeasures(snapshotId);
- mapper.deleteSnapshotMeasuresOnQualityModelRequirements(snapshotId);
- mapper.updatePurgeStatusToOne(snapshotId);
- }
-
- @VisibleForTesting
- void deleteSnapshot(long snapshotId, PurgeMapper mapper) {
- mapper.deleteSnapshotDependencies(snapshotId);
- mapper.deleteSnapshotDuplications(snapshotId);
- mapper.deleteSnapshotEvents(snapshotId);
- mapper.deleteSnapshotMeasureData(snapshotId);
- mapper.deleteSnapshotMeasures(snapshotId);
- mapper.deleteSnapshotSource(snapshotId);
- mapper.deleteSnapshotViolations(snapshotId);
- mapper.deleteSnapshot(snapshotId);
- }
}
diff --git a/sonar-core/src/main/java/org/sonar/core/purge/PurgeSnapshotQuery.java b/sonar-core/src/main/java/org/sonar/core/purge/PurgeSnapshotQuery.java
index 7fca0f6773a..c3905abcd67 100644
--- a/sonar-core/src/main/java/org/sonar/core/purge/PurgeSnapshotQuery.java
+++ b/sonar-core/src/main/java/org/sonar/core/purge/PurgeSnapshotQuery.java
@@ -20,6 +20,7 @@
package org.sonar.core.purge;
public final class PurgeSnapshotQuery {
+ private Long id;
private Long rootProjectId;
private Long rootSnapshotId;
private Long resourceId;
@@ -37,6 +38,15 @@ public final class PurgeSnapshotQuery {
return new PurgeSnapshotQuery();
}
+ public Long getId() {
+ return id;
+ }
+
+ public PurgeSnapshotQuery setId(Long l) {
+ this.id = l;
+ return this;
+ }
+
public Long getRootProjectId() {
return rootProjectId;
}
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 aad082e3516..931b6e953f0 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
@@ -13,7 +13,10 @@
and (s.purge_status is null or s.purge_status=0)
</if>
<if test="rootSnapshotId != null">
- and (s.root_snapshot_id=#{rootSnapshotId} or s.id=#{rootSnapshotId})
+ and s.root_snapshot_id=#{rootSnapshotId}
+ </if>
+ <if test="id != null">
+ and s.id=#{id}
</if>
<if test="rootProjectId != null">
and s.root_project_id=#{rootProjectId}
@@ -73,10 +76,6 @@
select id from projects where root_id=#{id} or id=#{id}
</select>
- <select id="selectSnapshotIdsByResource" parameterType="long" resultType="long">
- select id from snapshots where project_id=#{id}
- </select>
-
<delete id="deleteSnapshotMeasures" parameterType="long">
delete from project_measures where snapshot_id=#{id}
</delete>
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 0c6ea4e6d9a..7cd74d9f511 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
@@ -54,14 +54,21 @@ public class PurgeDaoTest extends DaoTestCase {
SqlSession session = getMyBatis().openSession();
try {
// this method does not commit and close the session
- dao.deleteSnapshot(5L, session.getMapper(PurgeMapper.class));
+ dao.deleteSnapshots(PurgeSnapshotQuery.create().setId(5L), session.getMapper(PurgeMapper.class));
session.commit();
} 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");
+ }
+
+ @Test
+ public void shouldDeleteAbortedBuilds() {
+ setupData("shouldDeleteAbortedBuilds");
+ dao.purge(1L, new String[0]);
+ checkTables("shouldDeleteAbortedBuilds", "snapshots");
}
/**
@@ -73,15 +80,16 @@ public class PurgeDaoTest extends DaoTestCase {
SqlSession session = getMyBatis().openSession();
try {
- // this method does not commit and close the session
- dao.purgeSnapshot(1L, session.getMapper(PurgeMapper.class));
+ dao.purgeSnapshots(PurgeSnapshotQuery.create().setId(1L), session.getMapper(PurgeMapper.class));
+
+ // the above method does not commit and close the session
session.commit();
} 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
@@ -90,8 +98,9 @@ public class PurgeDaoTest extends DaoTestCase {
SqlSession session = getMyBatis().openSession();
try {
- // this method does not commit and close the session
- dao.purgeSnapshot(1L, session.getMapper(PurgeMapper.class));
+ dao.purgeSnapshots(PurgeSnapshotQuery.create().setId(1L), session.getMapper(PurgeMapper.class));
+
+// the above method does not commit and close the session
session.commit();
} finally {
@@ -106,8 +115,9 @@ public class PurgeDaoTest extends DaoTestCase {
SqlSession session = getMyBatis().openSession();
try {
- // this method does not commit and close the session
dao.disableResource(1L, session.getMapper(PurgeMapper.class));
+
+ // the above method does not commit and close the session
session.commit();
} finally {
@@ -161,8 +171,9 @@ public class PurgeDaoTest extends DaoTestCase {
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.getMapper(PurgeVendorMapper.class));
+ dao.deleteResource(1L, session.getMapper(PurgeMapper.class), session.getMapper(PurgeVendorMapper.class));
+
+ // the above method does not commit and close the session
session.commit();
} finally {
@@ -196,9 +207,9 @@ public class PurgeDaoTest extends DaoTestCase {
public void describeTo(Description description) {
description
- .appendText("snapshotId").appendValue(snapshotId)
- .appendText("isLast").appendValue(isLast)
- .appendText("hasEvents").appendValue(hasEvents);
+ .appendText("snapshotId").appendValue(snapshotId)
+ .appendText("isLast").appendValue(isLast)
+ .appendText("hasEvents").appendValue(hasEvents);
}
}
}
diff --git a/sonar-core/src/test/java/org/sonar/core/resource/ResourceDaoTest.java b/sonar-core/src/test/java/org/sonar/core/resource/ResourceDaoTest.java
index bdda1f21aeb..cb9d765a95b 100644
--- a/sonar-core/src/test/java/org/sonar/core/resource/ResourceDaoTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/resource/ResourceDaoTest.java
@@ -27,10 +27,8 @@ import org.sonar.core.persistence.DaoTestCase;
import java.util.List;
import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.core.IsNot.not;
-import static org.hamcrest.core.IsNull.nullValue;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
-import static org.junit.matchers.JUnitMatchers.hasItems;
public class ResourceDaoTest extends DaoTestCase {
@@ -57,5 +55,22 @@ public class ResourceDaoTest extends DaoTestCase {
assertThat(dao.getDescendantProjects(33333L).size(), Is.is(0));
}
+
+ @Test
+ public void getResource() {
+ setupData("fixture");
+
+ ResourceDto resource = dao.getResource(1L);
+ assertThat(resource.getName(), Is.is("Struts"));
+ assertThat(resource.getLongName(), Is.is("Apache Struts"));
+ assertThat(resource.getScope(), Is.is("PRJ"));
+ }
+
+ @Test
+ public void getResource_not_found() {
+ setupData("fixture");
+
+ assertNull(dao.getResource(987654321L));
+ }
}
diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDeleteAbortedBuilds-result.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDeleteAbortedBuilds-result.xml
new file mode 100644
index 00000000000..7f21ab01f6e
--- /dev/null
+++ b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDeleteAbortedBuilds-result.xml
@@ -0,0 +1,46 @@
+<!--
+
+Snapshot 2 has been deleted
+
+-->
+<dataset>
+
+ <!-- the project -->
+ <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]" person_id="[null]" profile_id="[null]"/>
+
+ <!-- past snapshot with status "processed" and already purged -->
+ <snapshots id="1"
+ project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ status="P" islast="[false]" purge_status="1"
+ 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]"/>
+
+ <!-- snapshot with status "unprocessed" -> to be deleted -->
+ <!--<snapshots id="2"-->
+ <!--project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"-->
+ <!--status="U" islast="[false]" purge_status="0"-->
+ <!--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]"/>-->
+
+ <!-- snapshot with status "processed" and flagged as "last" -> do not purge and do not delete -->
+ <snapshots id="3"
+ project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ status="P" islast="[true]" purge_status="0"
+ 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]"/>
+
+</dataset> \ No newline at end of file
diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDeleteAbortedBuilds.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDeleteAbortedBuilds.xml
new file mode 100644
index 00000000000..da6f52837c7
--- /dev/null
+++ b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDeleteAbortedBuilds.xml
@@ -0,0 +1,41 @@
+<dataset>
+
+ <!-- the project -->
+ <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]" person_id="[null]" profile_id="[null]"/>
+
+ <!-- past snapshot with status "processed" and already purged -->
+ <snapshots id="1"
+ project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ status="P" islast="[false]" purge_status="1"
+ 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]"/>
+
+ <!-- snapshot with status "unprocessed" -> to be deleted -->
+ <snapshots id="2"
+ project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ status="U" islast="[false]" purge_status="0"
+ 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]"/>
+
+ <!-- snapshot with status "processed" and flagged as "last" -> do not purge and do not delete -->
+ <snapshots id="3"
+ project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ status="P" islast="[true]" purge_status="0"
+ 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]"/>
+
+</dataset> \ No newline at end of file
diff --git a/sonar-core/src/test/resources/org/sonar/core/resource/ResourceDaoTest/fixture.xml b/sonar-core/src/test/resources/org/sonar/core/resource/ResourceDaoTest/fixture.xml
index a993fe82a6f..e92a256f553 100644
--- a/sonar-core/src/test/resources/org/sonar/core/resource/ResourceDaoTest/fixture.xml
+++ b/sonar-core/src/test/resources/org/sonar/core/resource/ResourceDaoTest/fixture.xml
@@ -2,7 +2,7 @@
<!-- root project -->
<projects id="1" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts"
- description="[null]" long_name="Struts"
+ description="[null]" long_name="Apache Struts"
enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/>
<snapshots id="1" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
status="P" islast="[false]" purge_status="[null]"