}
public PurgeTask purge(long resourceId) {
- LOG.info("Clean historical data [id=" + resourceId + "]");
cleanHistoricalData(resourceId);
doPurge(resourceId);
return this;
for (PurgeableSnapshotDto snapshot : snapshots) {
LOG.info("<- Delete snapshot: " + DateUtils.formatDateTime(snapshot.getDate()) + " [" + snapshot.getSnapshotId() + "]");
purgeDao.deleteSnapshots(PurgeSnapshotQuery.create().setRootSnapshotId(snapshot.getSnapshotId()));
+ purgeDao.deleteSnapshots(PurgeSnapshotQuery.create().setId(snapshot.getSnapshotId()));
}
}
*/
package org.sonar.plugins.dbcleaner.period;
+import org.apache.commons.lang.ObjectUtils;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.junit.Test;
public void doClean() {
PurgeDao dao = mock(PurgeDao.class);
when(dao.selectPurgeableSnapshots(123L)).thenReturn(Arrays.asList(
- new PurgeableSnapshotDto().setSnapshotId(999L).setDate(new Date())));
+ new PurgeableSnapshotDto().setSnapshotId(999L).setDate(new Date())));
Filter filter1 = newLazyFilter();
Filter filter2 = newLazyFilter();
verify(filter1).log();
verify(filter2).log();
verify(dao, times(2)).deleteSnapshots(argThat(newRootSnapshotQuery()));
+ verify(dao, times(2)).deleteSnapshots(argThat(newSnapshotIdQuery()));
}
private BaseMatcher<PurgeSnapshotQuery> newRootSnapshotQuery() {
return new BaseMatcher<PurgeSnapshotQuery>() {
public boolean matches(Object o) {
- return ((PurgeSnapshotQuery) o).getRootSnapshotId() == 999L;
+ PurgeSnapshotQuery query = (PurgeSnapshotQuery) o;
+ return ObjectUtils.equals(query.getRootSnapshotId(), 999L);
+ }
+
+ public void describeTo(Description description) {
+ }
+ };
+ }
+
+ private BaseMatcher<PurgeSnapshotQuery> newSnapshotIdQuery() {
+ return new BaseMatcher<PurgeSnapshotQuery>() {
+ public boolean matches(Object o) {
+ PurgeSnapshotQuery query = (PurgeSnapshotQuery) o;
+ return ObjectUtils.equals(query.getId(), 999L);
}
public void describeTo(Description description) {
import java.util.Collections;
import java.util.List;
+/**
+ * @since 2.14
+ */
public class PurgeDao {
private final MyBatis mybatis;
private final ResourceDao resourceDao;
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);
}
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();
}
}
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) {
final PurgeVendorMapper vendorMapper = session.getMapper(PurgeVendorMapper.class);
try {
deleteProject(rootProjectId, session, mapper, vendorMapper);
+ session.commit();
return this;
} finally {
MyBatis.closeQuietly(session);
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);
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;
}
}
- 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);
+ }
}
/**
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);
- }
}
package org.sonar.core.purge;
public final class PurgeSnapshotQuery {
+ private Long id;
private Long rootProjectId;
private Long rootSnapshotId;
private Long resourceId;
return new PurgeSnapshotQuery();
}
+ public Long getId() {
+ return id;
+ }
+
+ public PurgeSnapshotQuery setId(Long l) {
+ this.id = l;
+ return this;
+ }
+
public Long getRootProjectId() {
return rootProjectId;
}
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}
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>
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");
}
/**
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
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 {
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 {
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 {
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);
}
}
}
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 {
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));
+ }
}
--- /dev/null
+<!--
+
+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
--- /dev/null
+<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
<!-- 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]"