org.sonar.db.purge.PurgeDao Maven / Gradle / Ivy
/*
* SonarQube
* Copyright (C) 2009-2016 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.db.purge;
import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.apache.commons.lang.ArrayUtils;
import org.apache.ibatis.session.ResultContext;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.SqlSession;
import org.sonar.api.resources.Scopes;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.db.Dao;
import org.sonar.db.DbSession;
import org.sonar.db.MyBatis;
import org.sonar.db.component.ResourceDao;
import org.sonar.db.component.ResourceDto;
import static org.sonar.api.utils.DateUtils.dateToLong;
/**
* @since 2.14
*/
public class PurgeDao implements Dao {
private static final Logger LOG = Loggers.get(PurgeDao.class);
private static final String[] UNPROCESSED_STATUS = new String[] {"U"};
private final MyBatis mybatis;
private final ResourceDao resourceDao;
private final System2 system2;
public PurgeDao(MyBatis mybatis, ResourceDao resourceDao, System2 system2) {
this.mybatis = mybatis;
this.resourceDao = resourceDao;
this.system2 = system2;
}
public PurgeDao purge(PurgeConfiguration conf, PurgeListener listener, PurgeProfiler profiler) {
DbSession session = mybatis.openSession(true);
try {
purge(session, conf, listener, profiler);
session.commit();
} finally {
MyBatis.closeQuietly(session);
}
return this;
}
public void purge(DbSession session, PurgeConfiguration conf, PurgeListener listener, PurgeProfiler profiler) {
PurgeMapper mapper = session.getMapper(PurgeMapper.class);
PurgeCommands commands = new PurgeCommands(session, mapper, profiler);
List projects = getProjects(conf.rootProjectIdUuid().getId(), session);
for (ResourceDto project : projects) {
LOG.debug("-> Clean " + project.getLongName() + " [id=" + project.getId() + "]");
deleteAbortedBuilds(project, commands);
purge(project, conf.scopesWithoutHistoricalData(), commands);
}
for (ResourceDto project : projects) {
disableOrphanResources(project, session, mapper, listener);
}
deleteOldClosedIssues(conf, mapper);
}
private static void deleteOldClosedIssues(PurgeConfiguration conf, PurgeMapper mapper) {
Date toDate = conf.maxLiveDateOfClosedIssues();
mapper.deleteOldClosedIssueChanges(conf.rootProjectIdUuid().getUuid(), dateToLong(toDate));
mapper.deleteOldClosedIssues(conf.rootProjectIdUuid().getUuid(), dateToLong(toDate));
}
private static void deleteAbortedBuilds(ResourceDto project, PurgeCommands commands) {
LOG.debug("<- Delete aborted builds");
PurgeSnapshotQuery query = PurgeSnapshotQuery.create()
.setIslast(false)
.setStatus(UNPROCESSED_STATUS)
.setRootProjectId(project.getId());
commands.deleteSnapshots(query);
}
private static 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.debug("<- Clean snapshot " + projectSnapshotId);
if (!ArrayUtils.isEmpty(scopesWithoutHistoricalData)) {
PurgeSnapshotQuery query = PurgeSnapshotQuery.create()
.setIslast(false)
.setScopes(scopesWithoutHistoricalData)
.setRootSnapshotId(projectSnapshotId);
purgeCommands.deleteSnapshots(query);
}
// must be executed at the end for reentrance
purgeCommands.purgeSnapshots(
PurgeSnapshotQuery.create().setRootSnapshotId(projectSnapshotId).setNotPurged(true),
PurgeSnapshotQuery.create().setId(projectSnapshotId).setNotPurged(true));
}
}
private void disableOrphanResources(final ResourceDto project, final SqlSession session, final PurgeMapper purgeMapper, final PurgeListener purgeListener) {
final List componentIdUuids = new ArrayList<>();
session.select("org.sonar.db.purge.PurgeMapper.selectComponentIdUuidsToDisable", project.getId(), new ResultHandler() {
@Override
public void handleResult(ResultContext resultContext) {
IdUuidPair componentIdUuid = (IdUuidPair) resultContext.getResultObject();
if (componentIdUuid.getId() != null) {
componentIdUuids.add(componentIdUuid);
}
}
});
for (IdUuidPair componentIdUuid : componentIdUuids) {
disableResource(componentIdUuid, purgeMapper);
purgeListener.onComponentDisabling(componentIdUuid.getUuid());
}
session.commit();
}
public List selectPurgeableSnapshots(long resourceId) {
DbSession session = mybatis.openSession(true);
try {
return selectPurgeableSnapshots(resourceId, session);
} finally {
MyBatis.closeQuietly(session);
}
}
public List selectPurgeableSnapshots(long resourceId, DbSession session) {
List result = Lists.newArrayList();
result.addAll(mapper(session).selectPurgeableSnapshotsWithEvents(resourceId));
result.addAll(mapper(session).selectPurgeableSnapshotsWithoutEvents(resourceId));
// sort by date
Collections.sort(result);
return result;
}
public PurgeDao deleteProject(DbSession session, String uuid) {
PurgeProfiler profiler = new PurgeProfiler();
PurgeCommands purgeCommands = new PurgeCommands(session, profiler);
deleteProject(uuid, mapper(session), purgeCommands);
return this;
}
private static void deleteProject(String rootUuid, PurgeMapper mapper, PurgeCommands commands) {
List childrenIds = mapper.selectComponentsByProjectUuid(rootUuid);
commands.deleteComponents(childrenIds);
commands.deleteFileSources(rootUuid);
commands.deleteCeActivity(rootUuid);
}
private void disableResource(IdUuidPair componentIdUuid, PurgeMapper mapper) {
long componentId = componentIdUuid.getId();
mapper.deleteResourceIndex(Arrays.asList(componentId));
mapper.setSnapshotIsLastToFalse(componentId);
mapper.deleteFileSourcesByUuid(componentIdUuid.getUuid());
mapper.disableResource(componentId);
mapper.resolveResourceIssuesNotAlreadyResolved(componentIdUuid.getUuid(), system2.now());
}
public PurgeDao deleteSnapshots(PurgeSnapshotQuery query, PurgeProfiler profiler) {
final DbSession session = mybatis.openSession(true);
try {
return deleteSnapshots(session, profiler, query);
} finally {
MyBatis.closeQuietly(session);
}
}
public PurgeDao deleteSnapshots(DbSession session, PurgeProfiler profiler, PurgeSnapshotQuery... queries) {
new PurgeCommands(session, profiler).deleteSnapshots(queries);
return this;
}
/**
* Load the whole tree of projects, including the project given in parameter.
*/
private List getProjects(long rootId, SqlSession session) {
return resourceDao.selectWholeTreeForRootId(session, rootId, Scopes.PROJECT);
}
private static PurgeMapper mapper(DbSession session) {
return session.getMapper(PurgeMapper.class);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy