* 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.plugins.dbcleaner;
import com.google.common.collect.ImmutableList;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.PropertyType;
+import com.google.common.collect.Lists;
import org.sonar.api.SonarPlugin;
import org.sonar.api.config.PropertyDefinition;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.plugins.dbcleaner.api.DbCleanerConstants;
-import org.sonar.plugins.dbcleaner.period.DefaultPeriodCleaner;
+import org.sonar.core.computation.dbcleaner.period.DefaultPeriodCleaner;
-import java.util.Arrays;
import java.util.List;
+@Deprecated
public final class DbCleanerPlugin extends SonarPlugin {
+ static List<PropertyDefinition> propertyDefinitions() {
+ return Lists.newArrayList();
+ }
+
@Override
public List getExtensions() {
- return ImmutableList.builder().add(DefaultPeriodCleaner.class, DefaultPurgeTask.class, ProjectPurgePostJob.class)
+ return ImmutableList.builder().add(DefaultPeriodCleaner.class, DeprecatedDefaultPurgeTask.class)
.addAll(propertyDefinitions()).build();
}
-
- static List<PropertyDefinition> propertyDefinitions() {
- return Arrays.asList(
- PropertyDefinition.builder(DbCleanerConstants.PROPERTY_CLEAN_DIRECTORY)
- .defaultValue("true")
- .name("Clean directory/package history")
- .description("If set to true, no history is kept at directory/package level. Setting this to false can cause database bloat.")
- .type(PropertyType.BOOLEAN)
- .onQualifiers(Qualifiers.PROJECT)
- .category(CoreProperties.CATEGORY_GENERAL)
- .subCategory(CoreProperties.SUBCATEGORY_DATABASE_CLEANER)
- .index(1)
- .build(),
-
- PropertyDefinition.builder(DbCleanerConstants.DAYS_BEFORE_DELETING_CLOSED_ISSUES)
- .defaultValue("30")
- .name("Delete closed issues after")
- .description("Issues that have been closed for more than this number of days will be deleted.")
- .type(PropertyType.INTEGER)
- .onQualifiers(Qualifiers.PROJECT)
- .category(CoreProperties.CATEGORY_GENERAL)
- .subCategory(CoreProperties.SUBCATEGORY_DATABASE_CLEANER)
- .index(2)
- .build(),
-
- PropertyDefinition.builder(DbCleanerConstants.HOURS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_DAY)
- .defaultValue("24")
- .name("Keep only one snapshot a day after")
- .description("After this number of hours, if there are several snapshots during the same day, "
- + "the DbCleaner keeps the most recent one and fully deletes the other ones.")
- .type(PropertyType.INTEGER)
- .onQualifiers(Qualifiers.PROJECT)
- .category(CoreProperties.CATEGORY_GENERAL)
- .subCategory(CoreProperties.SUBCATEGORY_DATABASE_CLEANER)
- .index(3)
- .build(),
-
- PropertyDefinition.builder(DbCleanerConstants.WEEKS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_WEEK)
- .defaultValue("4")
- .name("Keep only one snapshot a week after")
- .description("After this number of weeks, if there are several snapshots during the same week, "
- + "the DbCleaner keeps the most recent one and fully deletes the other ones")
- .type(PropertyType.INTEGER)
- .onQualifiers(Qualifiers.PROJECT)
- .category(CoreProperties.CATEGORY_GENERAL)
- .subCategory(CoreProperties.SUBCATEGORY_DATABASE_CLEANER)
- .index(4)
- .build(),
-
- PropertyDefinition.builder(DbCleanerConstants.WEEKS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_MONTH)
- .defaultValue("52")
- .name("Keep only one snapshot a month after")
- .description("After this number of weeks, if there are several snapshots during the same month, "
- + "the DbCleaner keeps the most recent one and fully deletes the other ones.")
- .type(PropertyType.INTEGER)
- .onQualifiers(Qualifiers.PROJECT)
- .category(CoreProperties.CATEGORY_GENERAL)
- .subCategory(CoreProperties.SUBCATEGORY_DATABASE_CLEANER)
- .index(5)
- .build(),
-
- PropertyDefinition.builder(DbCleanerConstants.WEEKS_BEFORE_DELETING_ALL_SNAPSHOTS)
- .defaultValue("260")
- .name("Delete all snapshots after")
- .description("After this number of weeks, all snapshots are fully deleted.")
- .type(PropertyType.INTEGER)
- .onQualifiers(Qualifiers.PROJECT)
- .category(CoreProperties.CATEGORY_GENERAL)
- .subCategory(CoreProperties.SUBCATEGORY_DATABASE_CLEANER)
- .index(6)
- .build()
- );
- }
}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.dbcleaner;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.config.Settings;
-import org.sonar.api.resources.Scopes;
-import org.sonar.api.utils.TimeUtils;
-import org.sonar.core.purge.PurgeConfiguration;
-import org.sonar.core.purge.PurgeDao;
-import org.sonar.core.purge.PurgeProfiler;
-import org.sonar.plugins.dbcleaner.api.DbCleanerConstants;
-import org.sonar.plugins.dbcleaner.api.PurgeTask;
-import org.sonar.plugins.dbcleaner.period.DefaultPeriodCleaner;
-
-/**
- * @since 2.14
- */
-public class DefaultPurgeTask implements PurgeTask {
- private static final Logger LOG = LoggerFactory.getLogger(DefaultPurgeTask.class);
-
- private PurgeDao purgeDao;
- private Settings settings;
- private DefaultPeriodCleaner periodCleaner;
- private final PurgeProfiler profiler;
-
- public DefaultPurgeTask(PurgeDao purgeDao, Settings settings, DefaultPeriodCleaner periodCleaner, PurgeProfiler profiler) {
- this.purgeDao = purgeDao;
- this.settings = settings;
- this.periodCleaner = periodCleaner;
- this.profiler = profiler;
- }
-
- @Override
- public PurgeTask delete(long resourceId) {
- purgeDao.deleteResourceTree(resourceId);
- return this;
- }
-
- @Override
- public PurgeTask purge(long resourceId) {
- long start = System.currentTimeMillis();
- profiler.reset();
- cleanHistoricalData(resourceId);
- doPurge(resourceId);
- if (settings.getBoolean(CoreProperties.PROFILING_LOG_PROPERTY)) {
- long duration = System.currentTimeMillis() - start;
- LOG.info("\n -------- Profiling for purge: " + TimeUtils.formatDuration(duration) + " --------\n");
- profiler.dump(duration, LOG);
- LOG.info("\n -------- End of profiling for purge --------\n");
- }
- return this;
- }
-
- private void cleanHistoricalData(long resourceId) {
- try {
- periodCleaner.clean(resourceId);
- } catch (Exception e) {
- // purge errors must no fail the batch
- LOG.error("Fail to clean historical data [id=" + resourceId + "]", e);
- }
- }
-
- private void doPurge(long resourceId) {
- try {
- purgeDao.purge(newConf(resourceId));
- } catch (Exception e) {
- // purge errors must no fail the batch
- LOG.error("Fail to purge data [id=" + resourceId + "]", e);
- }
- }
-
- private PurgeConfiguration newConf(long resourceId) {
- String[] scopes = new String[] {Scopes.FILE};
- if (settings.getBoolean(DbCleanerConstants.PROPERTY_CLEAN_DIRECTORY)) {
- scopes = new String[] {Scopes.DIRECTORY, Scopes.FILE};
- }
- return new PurgeConfiguration(resourceId, scopes, settings.getInt(DbCleanerConstants.DAYS_BEFORE_DELETING_CLOSED_ISSUES));
- }
-}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.plugins.dbcleaner;
+
+import org.sonar.api.config.Settings;
+import org.sonar.core.computation.dbcleaner.DefaultPurgeTask;
+import org.sonar.core.computation.dbcleaner.period.DefaultPeriodCleaner;
+import org.sonar.core.purge.PurgeDao;
+import org.sonar.core.purge.PurgeProfiler;
+import org.sonar.plugins.dbcleaner.api.PurgeTask;
+
+/**
+ * @since 2.14
+ */
+@Deprecated
+public class DeprecatedDefaultPurgeTask implements PurgeTask {
+ private final DefaultPurgeTask defaultPurgeTask;
+
+ public DeprecatedDefaultPurgeTask(PurgeDao purgeDao, Settings settings, DefaultPeriodCleaner periodCleaner, PurgeProfiler profiler) {
+ defaultPurgeTask = new DefaultPurgeTask(purgeDao, settings, periodCleaner, profiler);
+ }
+
+ @Override
+ public DeprecatedDefaultPurgeTask delete(long resourceId) {
+ defaultPurgeTask.delete(resourceId);
+ return this;
+ }
+
+ @Override
+ public DeprecatedDefaultPurgeTask purge(long resourceId) {
+ defaultPurgeTask.purge(resourceId);
+ return this;
+ }
+}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.dbcleaner;
-
-import org.sonar.api.batch.PostJob;
-import org.sonar.api.batch.SensorContext;
-import org.sonar.api.resources.Project;
-import org.sonar.core.DryRunIncompatible;
-import org.sonar.plugins.dbcleaner.api.PurgeTask;
-
-@DryRunIncompatible
-public class ProjectPurgePostJob implements PostJob {
-
- private PurgeTask purgeTask;
-
- public ProjectPurgePostJob(PurgeTask purgeTask) {
- this.purgeTask = purgeTask;
- }
-
- @Override
- public void executeOn(final Project project, SensorContext context) {
- purgeTask.purge(project.getId());
- }
-}
*/
package org.sonar.plugins.dbcleaner.api;
-public interface DbCleanerConstants {
-
- String PLUGIN_KEY = "dbcleaner";
- String PLUGIN_NAME = "DbCleaner";
- String PROPERTY_CLEAN_DIRECTORY = "sonar.dbcleaner.cleanDirectory";
-
- String HOURS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_DAY = "sonar.dbcleaner.hoursBeforeKeepingOnlyOneSnapshotByDay";
- String WEEKS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_WEEK = "sonar.dbcleaner.weeksBeforeKeepingOnlyOneSnapshotByWeek";
- String WEEKS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_MONTH = "sonar.dbcleaner.weeksBeforeKeepingOnlyOneSnapshotByMonth";
- String WEEKS_BEFORE_DELETING_ALL_SNAPSHOTS = "sonar.dbcleaner.weeksBeforeDeletingAllSnapshots";
- String DAYS_BEFORE_DELETING_CLOSED_ISSUES = "sonar.dbcleaner.daysBeforeDeletingClosedIssues";
+@Deprecated
+public interface DbCleanerConstants extends org.sonar.core.computation.dbcleaner.DbCleanerConstants {
}
*/
package org.sonar.plugins.dbcleaner.api;
-import org.sonar.api.task.TaskExtension;
-
import com.google.common.annotations.Beta;
+import org.sonar.api.task.TaskExtension;
/**
* @since 2.14
*/
@Beta
+@Deprecated
public interface PurgeTask extends TaskExtension {
/**
* Purges the data related to a tree of resources.
- *
+ * <p/>
* Exceptions are logged and are not thrown again, so this method fails only on {@link Error}s.
*
* @param resourceId the root of the tree
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.dbcleaner.period;
-
-import com.google.common.annotations.VisibleForTesting;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.config.Settings;
-import org.sonar.api.resources.Project;
-import org.sonar.api.task.TaskExtension;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.core.purge.PurgeDao;
-import org.sonar.core.purge.PurgeSnapshotQuery;
-import org.sonar.core.purge.PurgeableSnapshotDto;
-
-import java.util.List;
-
-public class DefaultPeriodCleaner implements TaskExtension {
-
- private static final Logger LOG = LoggerFactory.getLogger(DefaultPeriodCleaner.class);
- private PurgeDao purgeDao;
- private Settings settings;
-
- public DefaultPeriodCleaner(PurgeDao purgeDao, Settings settings) {
- this.purgeDao = purgeDao;
- this.settings = settings;
- }
-
- public void purge(Project project, int projectSnapshotId) {
- clean(project.getId());
- }
-
- public void clean(long projectId) {
- doClean(projectId, new Filters(settings).all());
- }
-
- @VisibleForTesting
- void doClean(long projectId, List<Filter> filters) {
- List<PurgeableSnapshotDto> history = selectProjectSnapshots(projectId);
- for (Filter filter : filters) {
- filter.log();
- delete(filter.filter(history));
- }
- }
-
- private void delete(List<PurgeableSnapshotDto> snapshots) {
- 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()));
- }
- }
-
- private List<PurgeableSnapshotDto> selectProjectSnapshots(long resourceId) {
- return purgeDao.selectPurgeableSnapshots(resourceId);
- }
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.dbcleaner.period;
-
-import com.google.common.collect.Lists;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.core.purge.PurgeableSnapshotDto;
-
-import java.util.Date;
-import java.util.List;
-
-class DeleteAllFilter implements Filter {
- private final Date before;
-
- public DeleteAllFilter(Date before) {
- this.before = before;
- }
-
- @Override
- public List<PurgeableSnapshotDto> filter(List<PurgeableSnapshotDto> history) {
- List<PurgeableSnapshotDto> result = Lists.newArrayList();
- for (PurgeableSnapshotDto snapshot : history) {
- if (snapshot.getDate().before(before)) {
- result.add(snapshot);
- }
- }
- return result;
- }
-
- @Override
- public void log() {
- LoggerFactory.getLogger(getClass()).info("-> Delete data prior to: " + DateUtils.formatDate(before));
- }
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.dbcleaner.period;
-
-import org.sonar.core.purge.PurgeableSnapshotDto;
-
-import java.util.List;
-
-interface Filter {
- List<PurgeableSnapshotDto> filter(List<PurgeableSnapshotDto> snapshots);
-
- void log();
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.dbcleaner.period;
-
-import com.google.common.collect.Lists;
-import org.apache.commons.lang.time.DateUtils;
-import org.sonar.api.config.Settings;
-import org.sonar.plugins.dbcleaner.api.DbCleanerConstants;
-
-import java.util.Calendar;
-import java.util.Date;
-import java.util.List;
-
-class Filters {
- private final List<Filter> all = Lists.newArrayList();
-
- Filters(Settings settings) {
- Date dateToStartKeepingOneSnapshotByDay = getDateFromHours(settings, DbCleanerConstants.HOURS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_DAY);
- Date dateToStartKeepingOneSnapshotByWeek = getDateFromWeeks(settings, DbCleanerConstants.WEEKS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_WEEK);
- Date dateToStartKeepingOneSnapshotByMonth = getDateFromWeeks(settings, DbCleanerConstants.WEEKS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_MONTH);
- Date dateToStartDeletingAllSnapshots = getDateFromWeeks(settings, DbCleanerConstants.WEEKS_BEFORE_DELETING_ALL_SNAPSHOTS);
-
- all.add(new KeepOneFilter(dateToStartKeepingOneSnapshotByWeek, dateToStartKeepingOneSnapshotByDay, Calendar.DAY_OF_YEAR, "day"));
- all.add(new KeepOneFilter(dateToStartKeepingOneSnapshotByMonth, dateToStartKeepingOneSnapshotByWeek, Calendar.WEEK_OF_YEAR, "week"));
- all.add(new KeepOneFilter(dateToStartDeletingAllSnapshots, dateToStartKeepingOneSnapshotByMonth, Calendar.MONTH, "month"));
- all.add(new DeleteAllFilter(dateToStartDeletingAllSnapshots));
- }
-
- List<Filter> all() {
- return all;
- }
-
- static Date getDateFromWeeks(Settings settings, String propertyKey) {
- int weeks = settings.getInt(propertyKey);
- return DateUtils.addWeeks(new Date(), -weeks);
- }
-
- static Date getDateFromHours(Settings settings, String propertyKey) {
- int hours = settings.getInt(propertyKey);
- return DateUtils.addHours(new Date(), -hours);
- }
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.dbcleaner.period;
-
-import com.google.common.collect.Lists;
-import org.apache.commons.lang.time.DateUtils;
-import org.sonar.core.purge.PurgeableSnapshotDto;
-
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.List;
-
-final class Interval {
- List<PurgeableSnapshotDto> snapshots = Lists.newArrayList();
-
- void add(PurgeableSnapshotDto snapshot) {
- snapshots.add(snapshot);
- }
-
- List<PurgeableSnapshotDto> get() {
- return snapshots;
- }
-
- int count() {
- return snapshots.size();
- }
-
- static List<Interval> group(List<PurgeableSnapshotDto> snapshots, Date start, Date end, int calendarField) {
- List<Interval> intervals = Lists.newArrayList();
-
- GregorianCalendar calendar = new GregorianCalendar();
- int lastYear = -1;
- int lastFieldValue = -1;
- Interval currentInterval = null;
-
- for (PurgeableSnapshotDto snapshot : snapshots) {
- if (!DateUtils.isSameDay(start, snapshot.getDate()) && snapshot.getDate().after(start) &&
- (snapshot.getDate().before(end) || DateUtils.isSameDay(end, snapshot.getDate()))) {
- calendar.setTime(snapshot.getDate());
- int currentFieldValue = calendar.get(calendarField);
- int currentYear = calendar.get(Calendar.YEAR);
- if (lastYear!=currentYear || lastFieldValue != currentFieldValue) {
- currentInterval = new Interval();
- intervals.add(currentInterval);
- }
- lastFieldValue = currentFieldValue;
- lastYear = currentYear;
- if (currentInterval != null) {
- currentInterval.add(snapshot);
- }
- }
- }
- return intervals;
- }
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.dbcleaner.period;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Lists;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.core.purge.PurgeableSnapshotDto;
-
-import java.util.Date;
-import java.util.List;
-
-class KeepOneFilter implements Filter {
-
- private final Date start;
- private final Date end;
- private final int dateField;
- private final String label;
-
- KeepOneFilter(Date start, Date end, int calendarField, String label) {
- this.start = start;
- this.end = end;
- this.dateField = calendarField;
- this.label = label;
- }
-
- @Override
- public List<PurgeableSnapshotDto> filter(List<PurgeableSnapshotDto> history) {
- List<Interval> intervals = Interval.group(history, start, end, dateField);
- List<PurgeableSnapshotDto> result = Lists.newArrayList();
- for (Interval interval : intervals) {
- appendSnapshotsToDelete(interval, result);
- }
-
- return result;
- }
-
- @Override
- public void log() {
- LoggerFactory.getLogger(getClass()).info("-> Keep one snapshot per " + label + " between " + DateUtils.formatDate(start) + " and " + DateUtils.formatDate(end));
- }
-
- private void appendSnapshotsToDelete(Interval interval, List<PurgeableSnapshotDto> toDelete) {
- if (interval.count() > 1) {
- List<PurgeableSnapshotDto> deletables = Lists.newArrayList();
- List<PurgeableSnapshotDto> toKeep = Lists.newArrayList();
- for (PurgeableSnapshotDto snapshot : interval.get()) {
- if (isDeletable(snapshot)) {
- deletables.add(snapshot);
- } else {
- toKeep.add(snapshot);
- }
- }
-
- if (!toKeep.isEmpty()) {
- toDelete.addAll(deletables);
-
- } else if (deletables.size() > 1) {
- // keep one snapshot
- toDelete.addAll(deletables.subList(1, deletables.size()));
- }
- }
- }
-
- @VisibleForTesting
- static boolean isDeletable(PurgeableSnapshotDto snapshot) {
- return !snapshot.isLast() && !snapshot.hasEvents();
- }
-
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.
- */
-
-@ParametersAreNonnullByDefault
-package org.sonar.plugins.dbcleaner.period;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.dbcleaner;
-
-import org.junit.Test;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class DbCleanerPluginTest {
-
- @Test
- public void shouldGetExtensions() {
- assertThat(new DbCleanerPlugin().getExtensions()).hasSize(9);
- }
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.dbcleaner;
-
-import org.sonar.api.utils.DateUtils;
-import org.sonar.core.purge.PurgeableSnapshotDto;
-
-public final class DbCleanerTestUtils {
-
- private DbCleanerTestUtils() {
- }
-
- public static PurgeableSnapshotDto createSnapshotWithDate(long snapshotId, String date) {
- PurgeableSnapshotDto snapshot = new PurgeableSnapshotDto();
- snapshot.setSnapshotId(snapshotId);
- snapshot.setDate(DateUtils.parseDate(date));
- return snapshot;
- }
-
- public static PurgeableSnapshotDto createSnapshotWithDateTime(long snapshotId, String datetime) {
- PurgeableSnapshotDto snapshot = new PurgeableSnapshotDto();
- snapshot.setSnapshotId(snapshotId);
- snapshot.setDate(DateUtils.parseDateTime(datetime));
- return snapshot;
- }
-
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.dbcleaner;
-
-import ch.qos.logback.classic.Logger;
-import org.junit.Test;
-import org.mockito.ArgumentMatcher;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.config.PropertyDefinitions;
-import org.sonar.api.config.Settings;
-import org.sonar.api.resources.Scopes;
-import org.sonar.core.purge.PurgeConfiguration;
-import org.sonar.core.purge.PurgeDao;
-import org.sonar.core.purge.PurgeProfiler;
-import org.sonar.plugins.dbcleaner.api.DbCleanerConstants;
-import org.sonar.plugins.dbcleaner.period.DefaultPeriodCleaner;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class DefaultPurgeTaskTest {
- @Test
- public void shouldNotDeleteHistoricalDataOfDirectories() {
- PurgeDao purgeDao = mock(PurgeDao.class);
- Settings settings = new Settings(new PropertyDefinitions(DbCleanerPlugin.propertyDefinitions()));
- settings.setProperty(DbCleanerConstants.PROPERTY_CLEAN_DIRECTORY, "false");
- DefaultPurgeTask task = new DefaultPurgeTask(purgeDao, settings, mock(DefaultPeriodCleaner.class), mock(PurgeProfiler.class));
-
- task.purge(1L);
-
- verify(purgeDao).purge(argThat(new ArgumentMatcher<PurgeConfiguration>() {
- @Override
- public boolean matches(Object o) {
- PurgeConfiguration conf = (PurgeConfiguration) o;
- return conf.rootProjectId() == 1L && conf.scopesWithoutHistoricalData().length == 1 && conf.scopesWithoutHistoricalData()[0].equals(Scopes.FILE);
- }
- }));
- }
-
- @Test
- public void shouldDeleteHistoricalDataOfDirectoriesByDefault() {
- PurgeDao purgeDao = mock(PurgeDao.class);
- Settings settings = new Settings(new PropertyDefinitions(DbCleanerPlugin.propertyDefinitions()));
- DefaultPurgeTask task = new DefaultPurgeTask(purgeDao, settings, mock(DefaultPeriodCleaner.class), mock(PurgeProfiler.class));
-
- task.purge(1L);
-
- verify(purgeDao).purge(argThat(new ArgumentMatcher<PurgeConfiguration>() {
- @Override
- public boolean matches(Object o) {
- PurgeConfiguration conf = (PurgeConfiguration) o;
- return conf.rootProjectId() == 1L &&
- conf.scopesWithoutHistoricalData().length == 2 &&
- conf.scopesWithoutHistoricalData()[0].equals(Scopes.DIRECTORY) &&
- conf.scopesWithoutHistoricalData()[1].equals(Scopes.FILE);
- }
- }));
- }
-
- @Test
- public void shouldNotFailOnErrors() {
- PurgeDao purgeDao = mock(PurgeDao.class);
- when(purgeDao.purge(any(PurgeConfiguration.class))).thenThrow(new RuntimeException());
- DefaultPurgeTask task = new DefaultPurgeTask(purgeDao, new Settings(), mock(DefaultPeriodCleaner.class), mock(PurgeProfiler.class));
-
- task.purge(1L);
-
- verify(purgeDao, times(1)).purge(any(PurgeConfiguration.class));
- }
-
- @Test
- public void shouldDumpProfiling() {
- PurgeConfiguration conf = new PurgeConfiguration(1L, new String[0], 30);
- PurgeDao purgeDao = mock(PurgeDao.class);
- when(purgeDao.purge(conf)).thenThrow(new RuntimeException());
- Settings settings = new Settings(new PropertyDefinitions(DbCleanerPlugin.propertyDefinitions()));
- settings.setProperty(CoreProperties.PROFILING_LOG_PROPERTY, true);
- PurgeProfiler profiler = mock(PurgeProfiler.class);
-
- DefaultPurgeTask task = new DefaultPurgeTask(purgeDao, settings, mock(DefaultPeriodCleaner.class), profiler);
- task.purge(1L);
-
- verify(profiler).dump(anyLong(), any(Logger.class));
- }
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.dbcleaner.period;
-
-import org.apache.commons.lang.ObjectUtils;
-import org.hamcrest.BaseMatcher;
-import org.junit.Test;
-import org.mockito.ArgumentMatcher;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-import org.sonar.api.config.Settings;
-import org.sonar.core.purge.PurgeDao;
-import org.sonar.core.purge.PurgeSnapshotQuery;
-import org.sonar.core.purge.PurgeableSnapshotDto;
-
-import java.util.Arrays;
-import java.util.Date;
-
-import static org.mockito.Matchers.anyListOf;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class DefaultPeriodCleanerTest {
-
-
- @Test
- public void doClean() {
- PurgeDao dao = mock(PurgeDao.class);
- when(dao.selectPurgeableSnapshots(123L)).thenReturn(Arrays.asList(
- new PurgeableSnapshotDto().setSnapshotId(999L).setDate(new Date())));
- Filter filter1 = newLazyFilter();
- Filter filter2 = newLazyFilter();
-
- DefaultPeriodCleaner cleaner = new DefaultPeriodCleaner(dao, mock(Settings.class));
- cleaner.doClean(123L, Arrays.asList(filter1, filter2));
-
- 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 ArgumentMatcher<PurgeSnapshotQuery>() {
- @Override
- public boolean matches(Object o) {
- PurgeSnapshotQuery query = (PurgeSnapshotQuery) o;
- return ObjectUtils.equals(query.getRootSnapshotId(), 999L);
- }
- };
- }
-
- private BaseMatcher<PurgeSnapshotQuery> newSnapshotIdQuery() {
- return new ArgumentMatcher<PurgeSnapshotQuery>() {
- @Override
- public boolean matches(Object o) {
- PurgeSnapshotQuery query = (PurgeSnapshotQuery) o;
- return ObjectUtils.equals(query.getId(), 999L);
- }
- };
- }
-
- private Filter newLazyFilter() {
- Filter filter1 = mock(Filter.class);
- when(filter1.filter(anyListOf(PurgeableSnapshotDto.class))).thenAnswer(new Answer<Object>() {
- public Object answer(InvocationOnMock invocation) throws Throwable {
- return invocation.getArguments()[0];
- }
- });
- return filter1;
- }
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.dbcleaner.period;
-
-import org.junit.Test;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.core.purge.PurgeableSnapshotDto;
-import org.sonar.plugins.dbcleaner.DbCleanerTestUtils;
-
-import java.util.Arrays;
-import java.util.List;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class DeleteAllFilterTest {
-
- @Test
- public void shouldDeleteAllSnapshotsPriorToDate() {
- Filter filter = new DeleteAllFilter(DateUtils.parseDate("2011-12-25"));
-
- List<PurgeableSnapshotDto> toDelete = filter.filter(Arrays.asList(
- DbCleanerTestUtils.createSnapshotWithDate(1L, "2010-01-01"),
- DbCleanerTestUtils.createSnapshotWithDate(2L, "2010-12-25"),
- DbCleanerTestUtils.createSnapshotWithDate(3L, "2012-01-01")
- ));
-
- assertThat(toDelete).onProperty("snapshotId").containsOnly(1L, 2L);
- }
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.dbcleaner.period;
-
-import org.junit.Test;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.core.purge.PurgeableSnapshotDto;
-
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.GregorianCalendar;
-import java.util.List;
-
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertThat;
-import static org.sonar.plugins.dbcleaner.DbCleanerTestUtils.createSnapshotWithDate;
-import static org.sonar.plugins.dbcleaner.DbCleanerTestUtils.createSnapshotWithDateTime;
-
-public class IntervalTest {
- @Test
- public void shouldGroupByIntervals() {
- List<PurgeableSnapshotDto> snapshots = Arrays.asList(
- createSnapshotWithDate(1L, "2011-04-03"),
-
- createSnapshotWithDate(2L, "2011-05-01"),
- createSnapshotWithDate(3L, "2011-05-19"),
-
- createSnapshotWithDate(4L, "2011-06-02"),
- createSnapshotWithDate(5L, "2011-06-20"),
-
- createSnapshotWithDate(6L, "2012-06-29") // out of scope
- );
-
- List<Interval> intervals = Interval.group(snapshots, DateUtils.parseDate("2010-01-01"), DateUtils.parseDate("2011-12-31"), Calendar.MONTH);
- assertThat(intervals.size(), is(3));
-
- assertThat(intervals.get(0).count(), is(1));
- assertThat(calendarField(intervals.get(0), Calendar.MONTH), is(Calendar.APRIL));
-
- assertThat(intervals.get(1).count(), is(2));
- assertThat(calendarField(intervals.get(1), Calendar.MONTH), is(Calendar.MAY));
-
- assertThat(intervals.get(2).count(), is(2));
- assertThat(calendarField(intervals.get(2), Calendar.MONTH), is(Calendar.JUNE));
- }
-
- @Test
- public void shouldNotJoinMonthsOfDifferentYears() {
- List<PurgeableSnapshotDto> snapshots = Arrays.asList(
- createSnapshotWithDate(1L, "2010-04-03"),
- createSnapshotWithDate(2L, "2011-04-13")
- );
-
- List<Interval> intervals = Interval.group(snapshots, DateUtils.parseDate("2010-01-01"), DateUtils.parseDate("2011-12-31"), Calendar.MONTH);
- assertThat(intervals.size(), is(2));
-
- assertThat(intervals.get(0).count(), is(1));
- assertThat(calendarField(intervals.get(0), Calendar.MONTH), is(Calendar.APRIL));
- assertThat(calendarField(intervals.get(0), Calendar.YEAR), is(2010));
-
- assertThat(intervals.get(1).count(), is(1));
- assertThat(calendarField(intervals.get(1), Calendar.MONTH), is(Calendar.APRIL));
- assertThat(calendarField(intervals.get(1), Calendar.YEAR), is(2011));
- }
-
- @Test
- public void shouldIgnoreTimeWhenGroupingByIntervals() {
- List<PurgeableSnapshotDto> snapshots = Arrays.asList(
- createSnapshotWithDateTime(1L, "2011-05-25T16:16:48+0100"),
- createSnapshotWithDateTime(2L, "2012-01-26T16:16:48+0100"),
- createSnapshotWithDateTime(3L, "2012-01-27T16:16:48+0100")
- );
-
- List<Interval> intervals = Interval.group(snapshots, DateUtils.parseDate("2011-05-25"), DateUtils.parseDate("2012-01-26"), Calendar.MONTH);
- assertThat(intervals.size(), is(1));
- assertThat(intervals.get(0).count(), is(1));
- assertThat(intervals.get(0).get().get(0).getSnapshotId(), is(2L));
- }
-
- static int calendarField(Interval interval, int field) {
- if (interval.count() == 0) {
- return -1;
- }
-
- PurgeableSnapshotDto first = interval.get().iterator().next();
- GregorianCalendar cal = new GregorianCalendar();
- cal.setTime(first.getDate());
- return cal.get(field);
- }
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.dbcleaner.period;
-
-import com.google.common.base.Function;
-import com.google.common.collect.Iterables;
-import org.junit.Test;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.core.purge.PurgeableSnapshotDto;
-
-import javax.annotation.Nullable;
-
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.List;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static org.fest.assertions.Assertions.assertThat;
-import static org.sonar.plugins.dbcleaner.DbCleanerTestUtils.createSnapshotWithDate;
-
-public class KeepOneFilterTest {
-
- @Test
- public void shouldOnlyOneSnapshotPerInterval() {
- Filter filter = new KeepOneFilter(DateUtils.parseDate("2011-03-25"), DateUtils.parseDate("2011-08-25"), Calendar.MONTH, "month");
-
- List<PurgeableSnapshotDto> toDelete = filter.filter(Arrays.<PurgeableSnapshotDto>asList(
- createSnapshotWithDate(1L, "2010-01-01"), // out of scope -> keep
- createSnapshotWithDate(2L, "2011-05-01"), // may -> keep
- createSnapshotWithDate(3L, "2011-05-02"), // may -> to be deleted
- createSnapshotWithDate(4L, "2011-05-19"), // may -> to be deleted
- createSnapshotWithDate(5L, "2011-06-01"), // june -> keep
- createSnapshotWithDate(6L, "2012-01-01") // out of scope -> keep
- ));
-
- assertThat(toDelete).hasSize(2);
-
- List<Long> snapshotIds = snapshotIds(toDelete);
- assertThat(snapshotIds).contains(3L);
- assertThat(snapshotIds.contains(4L));
- }
-
- @Test
- public void shouldKeepNonDeletableSnapshots() {
- Filter filter = new KeepOneFilter(DateUtils.parseDate("2011-03-25"), DateUtils.parseDate("2011-08-25"), Calendar.MONTH, "month");
-
- List<PurgeableSnapshotDto> toDelete = filter.filter(Arrays.<PurgeableSnapshotDto>asList(
- createSnapshotWithDate(1L, "2011-05-01"), // to be deleted
- createSnapshotWithDate(2L, "2011-05-02").setLast(true),
- createSnapshotWithDate(3L, "2011-05-19").setHasEvents(true).setLast(false),
- createSnapshotWithDate(4L, "2011-05-23") // to be deleted
- ));
-
- assertThat(toDelete).hasSize(2);
-
- List<Long> snapshotIds = snapshotIds(toDelete);
- assertThat(snapshotIds).contains(1L);
- assertThat(snapshotIds.contains(4L));
- }
-
- @Test
- public void test_isDeletable() {
- assertThat(KeepOneFilter.isDeletable(createSnapshotWithDate(1L, "2011-05-01"))).isTrue();
- assertThat(KeepOneFilter.isDeletable(createSnapshotWithDate(1L, "2011-05-01").setLast(true))).isFalse();
- assertThat(KeepOneFilter.isDeletable(createSnapshotWithDate(1L, "2011-05-01").setHasEvents(true))).isFalse();
- }
-
- private static List<Long> snapshotIds(List<PurgeableSnapshotDto> snapshotDtos){
- return newArrayList(Iterables.transform(snapshotDtos, new Function<PurgeableSnapshotDto, Long>() {
- @Override
- public Long apply(@Nullable PurgeableSnapshotDto input) {
- return input != null ? input.getSnapshotId() : null;
- }
- }));
- }
-
-}
private AnalysisReportDto newPendingAnalysisReport(String projectKey) {
return new AnalysisReportDto()
.setProjectKey(projectKey)
- .setProjectName(projectKey)
.setStatus(PENDING);
}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.server.computation;
-
-import org.sonar.api.ServerComponent;
-import org.sonar.core.computation.db.AnalysisReportDto;
-import org.sonar.core.persistence.DbSession;
-
-public interface AnalysisReportStep extends ServerComponent {
- void execute(DbSession session, AnalysisReportDto analysisReportDto);
-}
public AnalysisReportTaskLauncher(ComputationService service, AnalysisReportQueue queue) {
this.service = service;
this.queue = queue;
-
- // all threads are named "ar-xxx", so they can have a dedicated logging output
- // (see SwitchLogbackAppender)
- ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
- .setNameFormat(ANALYSIS_REPORT_THREAD_NAME_PREFIX + "%d").setPriority(Thread.MIN_PRIORITY).build();
-
- this.executorService = Executors.newSingleThreadScheduledExecutor(namedThreadFactory);
+ this.executorService = Executors.newSingleThreadScheduledExecutor(threadFactoryWithSpecificNameForLogging());
this.delayBetweenTasks = 10;
this.delayForFirstStart = 0;
@VisibleForTesting
AnalysisReportTaskLauncher(ComputationService service, AnalysisReportQueue queue, long delayForFirstStart, long delayBetweenTasks, TimeUnit timeUnit) {
this.queue = queue;
- this.executorService = Executors.newSingleThreadScheduledExecutor();
+ this.executorService = Executors.newSingleThreadScheduledExecutor(threadFactoryWithSpecificNameForLogging());
this.delayBetweenTasks = delayBetweenTasks;
this.delayForFirstStart = delayForFirstStart;
this.service = service;
}
+ /**
+ * @see org.sonar.server.platform.SwitchLogbackAppender
+ */
+ private ThreadFactory threadFactoryWithSpecificNameForLogging() {
+ return new ThreadFactoryBuilder()
+ .setNameFormat(ANALYSIS_REPORT_THREAD_NAME_PREFIX + "%d").setPriority(Thread.MIN_PRIORITY).build();
+ }
+
@Override
public void start() {
// do nothing because we want to wait for the server to finish startup
*/
public class ComputationService implements ServerComponent {
private final DbClient dbClient;
- private final SynchronizeProjectPermissionsStep synchronizeProjectPermissionsStep;
- private final IndexProjectIssuesStep indexProjectIssuesStep;
- private final SwitchSnapshotStep switchSnapshotStep;
+ private final ComputationStepRegistry stepRegistry;
- public ComputationService(DbClient dbClient, SynchronizeProjectPermissionsStep synchronizeProjectPermissionsStep,
- IndexProjectIssuesStep indexProjectIssuesStep, SwitchSnapshotStep switchSnapshotStep) {
+ public ComputationService(DbClient dbClient, ComputationStepRegistry stepRegistry) {
this.dbClient = dbClient;
- this.synchronizeProjectPermissionsStep = synchronizeProjectPermissionsStep;
- this.indexProjectIssuesStep = indexProjectIssuesStep;
- this.switchSnapshotStep = switchSnapshotStep;
+ this.stepRegistry = stepRegistry;
}
public void analyzeReport(AnalysisReportDto report) {
DbSession session = dbClient.openSession(true);
try {
- synchronizeProjectPermissionsStep.execute(session, report);
- indexProjectIssuesStep.execute(session, report);
- switchSnapshotStep.execute(session, report);
+ for (ComputationStep step : stepRegistry.steps()) {
+ step.execute(session, report);
+ }
} finally {
MyBatis.closeQuietly(session);
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.server.computation;
+
+import org.sonar.api.ServerComponent;
+import org.sonar.core.computation.db.AnalysisReportDto;
+import org.sonar.core.persistence.DbSession;
+
+public interface ComputationStep extends ServerComponent {
+ void execute(DbSession session, AnalysisReportDto analysisReportDto);
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.server.computation;
+
+import com.google.common.collect.ImmutableList;
+import org.sonar.api.ServerComponent;
+
+import java.util.List;
+
+public class ComputationStepRegistry implements ServerComponent {
+
+ private final List<ComputationStep> steps;
+
+ public ComputationStepRegistry(
+ GetAndSetProjectStep getAndSetProjectStep,
+ SynchronizeProjectPermissionsStep synchronizeProjectPermissionsStep,
+ IndexProjectIssuesStep indexProjectIssuesStep,
+ SwitchSnapshotStep switchSnapshotStep,
+ DbCleanerStep dbCleanerStep) {
+ steps = ImmutableList.of(getAndSetProjectStep, synchronizeProjectPermissionsStep, indexProjectIssuesStep, switchSnapshotStep, dbCleanerStep);
+ }
+
+ public List<ComputationStep> steps() {
+ return steps;
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.server.computation;
+
+import org.sonar.core.computation.db.AnalysisReportDto;
+import org.sonar.core.computation.dbcleaner.DefaultPurgeTask;
+import org.sonar.core.persistence.DbSession;
+
+public class DbCleanerStep implements ComputationStep {
+ private final DefaultPurgeTask purgeTask;
+
+ public DbCleanerStep(DefaultPurgeTask purgeTask) {
+ this.purgeTask = purgeTask;
+ }
+
+ @Override
+ public void execute(DbSession session, AnalysisReportDto report) {
+ purgeTask.purge(report.getProject().getId());
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.server.computation;
+
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.computation.db.AnalysisReportDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.DbClient;
+
+public class GetAndSetProjectStep implements ComputationStep {
+
+ private final DbClient dbClient;
+
+ public GetAndSetProjectStep(DbClient dbClient) {
+ this.dbClient = dbClient;
+ }
+
+ @Override
+ public void execute(DbSession session, AnalysisReportDto report) {
+ ComponentDto project = dbClient.componentDao().getByKey(session, report.getProjectKey());
+ report.setProject(project);
+ }
+}
import org.sonar.server.issue.index.IssueIndex;
import org.sonar.server.search.IndexClient;
-public class IndexProjectIssuesStep implements AnalysisReportStep {
+public class IndexProjectIssuesStep implements ComputationStep {
private final DbClient dbClient;
private final IndexClient index;
import java.util.List;
-public class SwitchSnapshotStep implements AnalysisReportStep {
+public class SwitchSnapshotStep implements ComputationStep {
private SnapshotDao dao;
package org.sonar.server.computation;
-import org.sonar.core.component.AuthorizedComponentDto;
import org.sonar.core.computation.db.AnalysisReportDto;
import org.sonar.core.persistence.DbSession;
-import org.sonar.server.db.DbClient;
import org.sonar.server.issue.index.IssueAuthorizationIndex;
import org.sonar.server.permission.InternalPermissionService;
import org.sonar.server.search.IndexClient;
-public class SynchronizeProjectPermissionsStep implements AnalysisReportStep {
+public class SynchronizeProjectPermissionsStep implements ComputationStep {
private final IndexClient index;
- private final DbClient dbClient;
private final InternalPermissionService permissionService;
- public SynchronizeProjectPermissionsStep(IndexClient index, DbClient dbClient, InternalPermissionService permissionService) {
+ public SynchronizeProjectPermissionsStep(IndexClient index, InternalPermissionService permissionService) {
this.index = index;
- this.dbClient = dbClient;
this.permissionService = permissionService;
}
@Override
public void execute(DbSession session, AnalysisReportDto report) {
- synchronizeProjectPermissionsIfNotFound(session, report.getProjectKey());
+ synchronizeProjectPermissionsIfNotFound(session, report);
}
- private void synchronizeProjectPermissionsIfNotFound(DbSession session, String projectKey) {
- if (index.get(IssueAuthorizationIndex.class).getNullableByKey(projectKey) == null) {
- // TODO Remove this db call by inserting the project uuid in the report
- AuthorizedComponentDto project = dbClient.componentDao().getAuthorizedComponentByKey(projectKey, session);
- permissionService.synchronizePermissions(session, project.uuid());
+ private void synchronizeProjectPermissionsIfNotFound(DbSession session, AnalysisReportDto report) {
+ if (index.get(IssueAuthorizationIndex.class).getNullableByKey(report.getProjectKey()) == null) {
+ permissionService.synchronizePermissions(session, report.getProject().uuid());
session.commit();
}
}
import org.sonar.api.utils.UriReader;
import org.sonar.api.utils.internal.TempFolderCleaner;
import org.sonar.core.component.SnapshotPerspectives;
+import org.sonar.core.computation.dbcleaner.DefaultPurgeTask;
+import org.sonar.core.computation.dbcleaner.period.DefaultPeriodCleaner;
import org.sonar.core.config.CorePropertyDefinitions;
import org.sonar.core.config.Logback;
import org.sonar.core.i18n.DefaultI18n;
ActivityNormalizer.class,
ActivityIndex.class,
ActivityDao.class
- ));
+ ));
components.addAll(CorePropertyDefinitions.all());
components.addAll(DatabaseMigrations.CLASSES);
components.addAll(DaoUtils.getDaoClasses());
// ws
RestartHandler.class,
SystemWs.class
- );
+ );
}
/**
HttpDownloader.class,
UriReader.class,
ServerIdGenerator.class
- );
+ );
}
void startLevel4Components(ComponentContainer pico) {
// Compute engine
pico.addSingleton(ComputationService.class);
- pico.addSingleton(SwitchSnapshotStep.class);
+ pico.addSingleton(ComputationStepRegistry.class);
+ pico.addSingleton(GetAndSetProjectStep.class);
pico.addSingleton(SynchronizeProjectPermissionsStep.class);
pico.addSingleton(IndexProjectIssuesStep.class);
+ pico.addSingleton(SwitchSnapshotStep.class);
+ pico.addSingleton(DbCleanerStep.class);
pico.add(AnalysisReportQueue.class);
pico.addSingleton(AnalysisReportTaskLauncher.class);
pico.addSingleton(AnalysisReportWebService.class);
pico.addSingleton(ActiveAnalysisReportsAction.class);
pico.addSingleton(IsAnalysisReportQueueEmptyAction.class);
pico.addSingleton(AnalysisReportHistorySearchAction.class);
+ pico.addSingleton(DefaultPurgeTask.class);
+ pico.addSingleton(DefaultPeriodCleaner.class);
for (Object components : level4AddedComponents) {
pico.addSingleton(components);
import org.sonar.core.persistence.DbSession;
import org.sonar.server.activity.ActivityService;
import org.sonar.server.activity.index.ActivityIndex;
+import org.sonar.server.component.ComponentTesting;
import org.sonar.server.db.DbClient;
import org.sonar.server.tester.ServerTester;
public void insert_find_analysis_report_log() {
AnalysisReportDto report = AnalysisReportDto.newForTests(1L)
.setProjectKey("projectKey")
- .setProjectName("projectName")
.setStatus(FAILED)
.setCreatedAt(DateUtils.parseDate("2014-10-15"))
.setUpdatedAt(DateUtils.parseDate("2014-10-16"))
.setStartedAt(DateUtils.parseDate("2014-10-17"))
- .setFinishedAt(DateUtils.parseDate("2014-10-18"));
+ .setFinishedAt(DateUtils.parseDate("2014-10-18"))
+ .setProject(ComponentTesting.newProjectDto());
service.write(dbSession, ANALYSIS_REPORT, new AnalysisReportLog(report));
dbSession.commit();
import org.sonar.core.persistence.MyBatis;
import org.sonar.core.user.UserDto;
import org.sonar.server.activity.index.ActivityIndex;
+import org.sonar.server.component.ComponentTesting;
import org.sonar.server.db.DbClient;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.tester.ServerTester;
insertPermissionsForProject(DEFAULT_PROJECT_KEY);
sut.add(DEFAULT_PROJECT_KEY, 123L);
AnalysisReportDto report = sut.bookNextAvailable();
+ report.setProject(ComponentTesting.newProjectDto());
report.setStatus(SUCCESS);
sut.remove(report);
package org.sonar.server.computation;
+import com.google.common.collect.Lists;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InOrder;
private ComputationService sut;
private DbClient dbClient;
- private IndexProjectIssuesStep indexProjectIssuesStep;
- private SynchronizeProjectPermissionsStep synchronizeProjectPermissionsStep;
- private SwitchSnapshotStep switchSnapshotStep;
+ private ComputationStepRegistry stepRegistry;
@Before
public void before() {
this.dbClient = mock(DbClient.class);
+ this.stepRegistry = mock(ComputationStepRegistry.class);
- this.indexProjectIssuesStep = mock(IndexProjectIssuesStep.class);
- this.synchronizeProjectPermissionsStep = mock(SynchronizeProjectPermissionsStep.class);
- this.switchSnapshotStep = mock(SwitchSnapshotStep.class);
-
- this.sut = new ComputationService(dbClient, synchronizeProjectPermissionsStep, indexProjectIssuesStep, switchSnapshotStep);
+ this.sut = new ComputationService(dbClient, stepRegistry);
}
@Test
- public void all_my_steps_are_called_in_the_right_order() {
- sut.analyzeReport(AnalysisReportDto.newForTests(1L));
+ public void call_execute_method_of_my_registry() {
+ ComputationStep firstStep = mock(ComputationStep.class);
+ ComputationStep secondStep = mock(ComputationStep.class);
+ ComputationStep thirdStep = mock(ComputationStep.class);
- InOrder inOrder = inOrder(indexProjectIssuesStep, synchronizeProjectPermissionsStep, switchSnapshotStep);
+ when(stepRegistry.steps()).thenReturn(Lists.newArrayList(firstStep, secondStep, thirdStep));
- inOrder.verify(synchronizeProjectPermissionsStep).execute(any(DbSession.class), any(AnalysisReportDto.class));
- inOrder.verify(indexProjectIssuesStep).execute(any(DbSession.class), any(AnalysisReportDto.class));
- inOrder.verify(switchSnapshotStep).execute(any(DbSession.class), any(AnalysisReportDto.class));
- }
+ sut.analyzeReport(AnalysisReportDto.newForTests(1L));
- @Test(expected = IllegalStateException.class)
- public void computation_service_rethrows_exceptions() {
- doThrow(IllegalStateException.class).when(switchSnapshotStep).execute(any(DbSession.class), any(AnalysisReportDto.class));
+ InOrder order = inOrder(firstStep, secondStep, thirdStep);
- sut.analyzeReport(AnalysisReportDto.newForTests(1L));
+ order.verify(firstStep).execute(any(DbSession.class), any(AnalysisReportDto.class));
+ order.verify(secondStep).execute(any(DbSession.class), any(AnalysisReportDto.class));
+ order.verify(thirdStep).execute(any(DbSession.class), any(AnalysisReportDto.class));
}
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.server.computation;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+public class ComputationStepRegistryTest {
+
+ private ComputationStepRegistry sut;
+ private GetAndSetProjectStep getAndSetProjectStep;
+ private SynchronizeProjectPermissionsStep synchronizeProjectPermissionsStep;
+ private IndexProjectIssuesStep indexProjectIssuesStep;
+ private SwitchSnapshotStep switchSnapshotStep;
+ private DbCleanerStep dbCleanerStep;
+
+ @Before
+ public void before() {
+ getAndSetProjectStep = mock(GetAndSetProjectStep.class);
+ synchronizeProjectPermissionsStep = mock(SynchronizeProjectPermissionsStep.class);
+ indexProjectIssuesStep = mock(IndexProjectIssuesStep.class);
+ switchSnapshotStep = mock(SwitchSnapshotStep.class);
+ dbCleanerStep = mock(DbCleanerStep.class);
+
+ sut = new ComputationStepRegistry(getAndSetProjectStep, synchronizeProjectPermissionsStep, indexProjectIssuesStep, switchSnapshotStep, dbCleanerStep);
+ }
+
+ @Test
+ public void steps_returned_in_the_right_order() throws Exception {
+ assertThat(sut.steps()).containsExactly(getAndSetProjectStep, synchronizeProjectPermissionsStep, indexProjectIssuesStep, switchSnapshotStep, dbCleanerStep);
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.server.computation;
+
+import org.junit.Before;
+import org.sonar.api.config.Settings;
+import org.sonar.core.computation.dbcleaner.DefaultPurgeTask;
+import org.sonar.core.computation.dbcleaner.period.DefaultPeriodCleaner;
+import org.sonar.core.purge.PurgeDao;
+import org.sonar.core.purge.PurgeProfiler;
+
+import static org.mockito.Mockito.mock;
+
+public class DbCleanStepTest {
+
+ private DbCleanerStep sut;
+
+ @Before
+ public void before() {
+ sut = new DbCleanerStep(new DefaultPurgeTask(mock(PurgeDao.class), mock(Settings.class), mock(DefaultPeriodCleaner.class), mock(PurgeProfiler.class)));
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.server.computation;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.core.component.AuthorizedComponentDto;
+import org.sonar.core.computation.db.AnalysisReportDto;
+import org.sonar.core.computation.dbcleaner.DefaultPurgeTask;
+import org.sonar.core.persistence.DbSession;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class DbCleanerStepTest {
+
+ private DbCleanerStep sut;
+ private DefaultPurgeTask purgeTask;
+
+ @Before
+ public void before() {
+ this.purgeTask = mock(DefaultPurgeTask.class);
+ this.sut = new DbCleanerStep(purgeTask);
+ }
+
+ @Test
+ public void call_purge_method_of_the_purge_task() {
+ AnalysisReportDto report = mock(AnalysisReportDto.class);
+ when(report.getProject()).thenReturn(mock(AuthorizedComponentDto.class));
+
+ sut.execute(mock(DbSession.class), report);
+
+ verify(purgeTask).purge(any(Long.class));
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.server.computation;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.computation.db.AnalysisReportDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.component.ComponentTesting;
+import org.sonar.server.component.db.ComponentDao;
+import org.sonar.server.db.DbClient;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class GetAndSetProjectStepTest {
+
+ private GetAndSetProjectStep sut;
+ private DbClient dbClient;
+ private ComponentDto project;
+ private DbSession session;
+
+ @Before
+ public void before() {
+ this.dbClient = mock(DbClient.class);
+ this.session = mock(DbSession.class);
+ this.project = ComponentTesting.newProjectDto();
+
+ ComponentDao componentDao = mock(ComponentDao.class);
+ when(dbClient.componentDao()).thenReturn(componentDao);
+ when(componentDao.getByKey(any(DbSession.class), anyString())).thenReturn(project);
+
+ this.sut = new GetAndSetProjectStep(dbClient);
+ }
+
+ @Test
+ public void set_project_return_by_dbclient() {
+ AnalysisReportDto report = new AnalysisReportDto().setProjectKey("123-456-789");
+
+ sut.execute(session, report);
+
+ assertThat(report.getProject()).isEqualTo(project);
+ }
+
+}
private SynchronizeProjectPermissionsStep sut;
private AnalysisReportQueue queue;
+ private GetAndSetProjectStep getAndSetProjectStep;
private DbClient db;
private DbSession session;
private MockUserSession userSession;
db = tester.get(DbClient.class);
session = db.openSession(false);
queue = tester.get(AnalysisReportQueue.class);
+ getAndSetProjectStep = tester.get(GetAndSetProjectStep.class);
sut = tester.get(SynchronizeProjectPermissionsStep.class);
queue.add(DEFAULT_PROJECT_KEY, 123L);
List<AnalysisReportDto> reports = queue.findByProjectKey(DEFAULT_PROJECT_KEY);
+ getAndSetProjectStep.execute(session, reports.get(0));
sut.execute(session, reports.get(0));
this.sut = new AnalysisReportDao(system2);
when(system2.now()).thenReturn(DateUtils.parseDate("2014-09-26").getTime());
-
- db.prepareDbUnit(getClass(), "empty.xml");
}
@After
@Test
public void insert_multiple_reports() {
+ db.prepareDbUnit(getClass(), "empty.xml");
+
AnalysisReportDto report = new AnalysisReportDto()
.setProjectKey(DEFAULT_PROJECT_KEY)
- .setProjectName(DEFAULT_PROJECT_NAME)
.setSnapshotId(DEFAULT_SNAPSHOT_ID)
.setData("data-project")
.setStatus(PENDING)
AnalysisReportDto report = sut.getById(session, 1L);
assertThat(report.getProjectKey()).isEqualTo(DEFAULT_PROJECT_KEY);
- assertThat(report.getProjectName()).isEqualTo(DEFAULT_PROJECT_NAME);
assertThat(report.getCreatedAt()).isEqualTo(DateUtils.parseDate("2014-09-24"));
assertThat(report.getUpdatedAt()).isEqualTo(DateUtils.parseDate("2014-09-25"));
assertThat(report.getStartedAt()).isEqualTo(DateUtils.parseDate("2014-09-26"));
public void list_active_reports() throws Exception {
AnalysisReportDto report = AnalysisReportDto
.newForTests(1L)
- .setProjectName("Project Name")
.setProjectKey("project-name")
.setStatus(PENDING)
.setData(null)
<analysis_reports
id="1"
project_key="123456789-987654321"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="WORKING"
<analysis_reports
id="2"
project_key="123456789-987654321"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="WORKING"
<analysis_reports
id="3"
project_key="123456789-987654321"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="PENDING"
<analysis_reports
id="1"
project_key="123456789-987654321"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="PENDING"
<analysis_reports
id="2"
project_key="987654321-123456789"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="WORKING"
<analysis_reports
id="1"
project_key="123456789-987654321"
- project_name="default project name"
+ project_name="[null]"
snapshot_id="123"
report_data="data-project"
report_status="PENDING"
<analysis_reports
id="2"
project_key="123456789-987654321"
- project_name="default project name"
+ project_name="[null]"
snapshot_id="123"
report_data="data-project"
report_status="PENDING"
<analysis_reports
id="1"
project_key="123456789-987654321"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="WORKING"
<analysis_reports
id="1"
project_key="123456789-987654321"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="PENDING"
<analysis_reports
id="2"
project_key="123456789-987654321"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="PENDING"
<analysis_reports
id="1"
project_key="123456789-987654321"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="PENDING"
<analysis_reports
id="2"
project_key="123456789-987654321"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="WORKING"
<analysis_reports
id="1"
project_key="123456789-987654321"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="WORKING"
<analysis_reports
id="1"
project_key="111111111-987654321"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="WORKING"
<analysis_reports
id="2"
project_key="123456789-987654321"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="WORKING"
<analysis_reports
id="3"
project_key="123456789-987654321"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="PENDING"
<analysis_reports
id="1"
project_key="123456789-987654321"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="WORKING"
<analysis_reports
id="2"
project_key="987654321-123456789"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="WORKING"
<analysis_reports
id="3"
project_key="987654321-123456789"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="PENDING"
<analysis_reports
id="1"
project_key="111111111-987654321"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="PENDING"
<analysis_reports
id="2"
project_key="123456789-987654321"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="PENDING"
<analysis_reports
id="3"
project_key="333333333-123456789"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="PENDING"
<analysis_reports
id="1"
project_key="111111111-987654321"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="WORKING"
<analysis_reports
id="2"
project_key="123456789-987654321"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="PENDING"
<analysis_reports
id="3"
project_key="333333333-123456789"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="WORKING"
<analysis_reports
id="1"
project_key="123456789-987654321"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="WORKING"
<analysis_reports
id="2"
project_key="987654321-123456789"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="WORKING"
<analysis_reports
id="3"
project_key="987654321-123456789"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="PENDING"
<analysis_reports
id="1"
project_key="123456789-987654321"
- project_name="default project name"
+ project_name="[null]"
snapshot_id="123"
report_data="data-project"
report_status="PENDING"
<analysis_reports
id="2"
project_key="123456789-987654321"
- project_name="default project name"
+ project_name="[null]"
snapshot_id="123"
report_data="data-project"
report_status="PENDING"
<analysis_reports
id="3"
project_key="123456789-987654321"
- project_name="default project name"
+ project_name="[null]"
snapshot_id="123"
report_data="data-project"
report_status="PENDING"
<analysis_reports
id="1"
project_key="123456789-987654321"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="WORKING"
<analysis_reports
id="2"
project_key="123456789-987654321"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="WORKING"
<analysis_reports
id="3"
project_key="123456789-987654321"
- project_name="default project name"
snapshot_id="123"
report_data="data-project"
report_status="PENDING"
{
"id": 1,
"status": "PENDING",
- "projectName": "Project Name",
+ "projectName": "project-name",
"project": "project-name",
"submittedAt": "2014-10-13T00:00:00+0200",
"startedAt": "2014-10-13T00:00:00+0200",
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Objects;
+import com.google.common.base.Strings;
+import org.sonar.core.component.AuthorizedComponentDto;
+import org.sonar.core.component.ComponentDto;
import org.sonar.core.persistence.Dto;
import javax.annotation.Nullable;
import java.util.Date;
+import static com.google.common.base.Preconditions.checkNotNull;
import static org.sonar.core.computation.db.AnalysisReportDto.Status.FAILED;
import static org.sonar.core.computation.db.AnalysisReportDto.Status.SUCCESS;
private Long id;
private String projectKey;
- private String projectName;
private Status status;
private String data;
private Long snapshotId;
private Date startedAt;
private Date finishedAt;
+ private ComponentDto project;
public AnalysisReportDto() {
super();
return Objects.toStringHelper(this)
.add("id", getId())
.add("projectKey", getProjectKey())
- .add("projectName", getProjectName())
.add("status", getStatus())
.add("createdAt", getCreatedAt())
.add("startedAt", getStartedAt())
}
public String getProjectName() {
- return projectName;
- }
+ if (project == null) {
+ return getProjectKey();
+ }
- public AnalysisReportDto setProjectName(String projectName) {
- this.projectName = projectName;
- return this;
+ return Strings.nullToEmpty(project.name());
}
public Long getSnapshotId() {
return this;
}
+ public AuthorizedComponentDto getProject() {
+ return checkNotNull(project);
+ }
+
+ public AnalysisReportDto setProject(ComponentDto project) {
+ this.project = project;
+ return this;
+ }
+
public enum Status {
PENDING, WORKING, SUCCESS, FAILED;
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.core.computation.dbcleaner;
+
+public interface DbCleanerConstants {
+
+ String PLUGIN_KEY = "dbcleaner";
+ String PLUGIN_NAME = "DbCleaner";
+ String PROPERTY_CLEAN_DIRECTORY = "sonar.dbcleaner.cleanDirectory";
+
+ String HOURS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_DAY = "sonar.dbcleaner.hoursBeforeKeepingOnlyOneSnapshotByDay";
+ String WEEKS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_WEEK = "sonar.dbcleaner.weeksBeforeKeepingOnlyOneSnapshotByWeek";
+ String WEEKS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_MONTH = "sonar.dbcleaner.weeksBeforeKeepingOnlyOneSnapshotByMonth";
+ String WEEKS_BEFORE_DELETING_ALL_SNAPSHOTS = "sonar.dbcleaner.weeksBeforeDeletingAllSnapshots";
+ String DAYS_BEFORE_DELETING_CLOSED_ISSUES = "sonar.dbcleaner.daysBeforeDeletingClosedIssues";
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.core.computation.dbcleaner;
+
+import org.sonar.api.CoreProperties;
+import org.sonar.api.PropertyType;
+import org.sonar.api.config.PropertyDefinition;
+import org.sonar.api.resources.Qualifiers;
+
+import java.util.Arrays;
+import java.util.List;
+
+public final class DbCleanerProperties {
+
+ public static List<PropertyDefinition> all() {
+ return Arrays.asList(
+ PropertyDefinition.builder(DbCleanerConstants.PROPERTY_CLEAN_DIRECTORY)
+ .defaultValue("true")
+ .name("Clean directory/package history")
+ .description("If set to true, no history is kept at directory/package level. Setting this to false can cause database bloat.")
+ .type(PropertyType.BOOLEAN)
+ .onQualifiers(Qualifiers.PROJECT)
+ .category(CoreProperties.CATEGORY_GENERAL)
+ .subCategory(CoreProperties.SUBCATEGORY_DATABASE_CLEANER)
+ .index(1)
+ .build(),
+
+ PropertyDefinition.builder(DbCleanerConstants.DAYS_BEFORE_DELETING_CLOSED_ISSUES)
+ .defaultValue("30")
+ .name("Delete closed issues after")
+ .description("Issues that have been closed for more than this number of days will be deleted.")
+ .type(PropertyType.INTEGER)
+ .onQualifiers(Qualifiers.PROJECT)
+ .category(CoreProperties.CATEGORY_GENERAL)
+ .subCategory(CoreProperties.SUBCATEGORY_DATABASE_CLEANER)
+ .index(2)
+ .build(),
+
+ PropertyDefinition.builder(DbCleanerConstants.HOURS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_DAY)
+ .defaultValue("24")
+ .name("Keep only one snapshot a day after")
+ .description("After this number of hours, if there are several snapshots during the same day, "
+ + "the DbCleaner keeps the most recent one and fully deletes the other ones.")
+ .type(PropertyType.INTEGER)
+ .onQualifiers(Qualifiers.PROJECT)
+ .category(CoreProperties.CATEGORY_GENERAL)
+ .subCategory(CoreProperties.SUBCATEGORY_DATABASE_CLEANER)
+ .index(3)
+ .build(),
+
+ PropertyDefinition.builder(DbCleanerConstants.WEEKS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_WEEK)
+ .defaultValue("4")
+ .name("Keep only one snapshot a week after")
+ .description("After this number of weeks, if there are several snapshots during the same week, "
+ + "the DbCleaner keeps the most recent one and fully deletes the other ones")
+ .type(PropertyType.INTEGER)
+ .onQualifiers(Qualifiers.PROJECT)
+ .category(CoreProperties.CATEGORY_GENERAL)
+ .subCategory(CoreProperties.SUBCATEGORY_DATABASE_CLEANER)
+ .index(4)
+ .build(),
+
+ PropertyDefinition.builder(DbCleanerConstants.WEEKS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_MONTH)
+ .defaultValue("52")
+ .name("Keep only one snapshot a month after")
+ .description("After this number of weeks, if there are several snapshots during the same month, "
+ + "the DbCleaner keeps the most recent one and fully deletes the other ones.")
+ .type(PropertyType.INTEGER)
+ .onQualifiers(Qualifiers.PROJECT)
+ .category(CoreProperties.CATEGORY_GENERAL)
+ .subCategory(CoreProperties.SUBCATEGORY_DATABASE_CLEANER)
+ .index(5)
+ .build(),
+
+ PropertyDefinition.builder(DbCleanerConstants.WEEKS_BEFORE_DELETING_ALL_SNAPSHOTS)
+ .defaultValue("260")
+ .name("Delete all snapshots after")
+ .description("After this number of weeks, all snapshots are fully deleted.")
+ .type(PropertyType.INTEGER)
+ .onQualifiers(Qualifiers.PROJECT)
+ .category(CoreProperties.CATEGORY_GENERAL)
+ .subCategory(CoreProperties.SUBCATEGORY_DATABASE_CLEANER)
+ .index(6)
+ .build()
+ );
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.core.computation.dbcleaner;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
+import org.sonar.api.resources.Scopes;
+import org.sonar.api.utils.TimeUtils;
+import org.sonar.core.computation.dbcleaner.period.DefaultPeriodCleaner;
+import org.sonar.core.purge.PurgeConfiguration;
+import org.sonar.core.purge.PurgeDao;
+import org.sonar.core.purge.PurgeProfiler;
+
+/**
+ * @since 2.14
+ */
+public class DefaultPurgeTask {
+ private static final Logger LOG = LoggerFactory.getLogger(DefaultPurgeTask.class);
+
+ private PurgeDao purgeDao;
+ private Settings settings;
+ private DefaultPeriodCleaner periodCleaner;
+ private final PurgeProfiler profiler;
+
+ public DefaultPurgeTask(PurgeDao purgeDao, Settings settings, DefaultPeriodCleaner periodCleaner, PurgeProfiler profiler) {
+ this.purgeDao = purgeDao;
+ this.settings = settings;
+ this.periodCleaner = periodCleaner;
+ this.profiler = profiler;
+ }
+
+ public DefaultPurgeTask delete(long resourceId) {
+ purgeDao.deleteResourceTree(resourceId);
+ return this;
+ }
+
+ public DefaultPurgeTask purge(long resourceId) {
+ long start = System.currentTimeMillis();
+ profiler.reset();
+ cleanHistoricalData(resourceId);
+ doPurge(resourceId);
+ if (settings.getBoolean(CoreProperties.PROFILING_LOG_PROPERTY)) {
+ long duration = System.currentTimeMillis() - start;
+ LOG.info("\n -------- Profiling for purge: " + TimeUtils.formatDuration(duration) + " --------\n");
+ profiler.dump(duration, LOG);
+ LOG.info("\n -------- End of profiling for purge --------\n");
+ }
+ return this;
+ }
+
+ private void cleanHistoricalData(long resourceId) {
+ try {
+ periodCleaner.clean(resourceId);
+ } catch (Exception e) {
+ // purge errors must no fail the batch
+ LOG.error("Fail to clean historical data [id=" + resourceId + "]", e);
+ }
+ }
+
+ private void doPurge(long resourceId) {
+ try {
+ purgeDao.purge(newConf(resourceId));
+ } catch (Exception e) {
+ // purge errors must no fail the batch
+ LOG.error("Fail to purge data [id=" + resourceId + "]", e);
+ }
+ }
+
+ private PurgeConfiguration newConf(long resourceId) {
+ String[] scopes = new String[] {Scopes.FILE};
+ if (settings.getBoolean(DbCleanerConstants.PROPERTY_CLEAN_DIRECTORY)) {
+ scopes = new String[] {Scopes.DIRECTORY, Scopes.FILE};
+ }
+ return new PurgeConfiguration(resourceId, scopes, settings.getInt(DbCleanerConstants.DAYS_BEFORE_DELETING_CLOSED_ISSUES));
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.core.computation.dbcleaner.period;
+
+import com.google.common.annotations.VisibleForTesting;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.config.Settings;
+import org.sonar.api.resources.Project;
+import org.sonar.api.task.TaskExtension;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.core.purge.PurgeDao;
+import org.sonar.core.purge.PurgeSnapshotQuery;
+import org.sonar.core.purge.PurgeableSnapshotDto;
+
+import java.util.List;
+
+public class DefaultPeriodCleaner implements TaskExtension {
+
+ private static final Logger LOG = LoggerFactory.getLogger(DefaultPeriodCleaner.class);
+ private PurgeDao purgeDao;
+ private Settings settings;
+
+ public DefaultPeriodCleaner(PurgeDao purgeDao, Settings settings) {
+ this.purgeDao = purgeDao;
+ this.settings = settings;
+ }
+
+ public void purge(Project project, int projectSnapshotId) {
+ clean(project.getId());
+ }
+
+ public void clean(long projectId) {
+ doClean(projectId, new Filters(settings).all());
+ }
+
+ @VisibleForTesting
+ void doClean(long projectId, List<Filter> filters) {
+ List<PurgeableSnapshotDto> history = selectProjectSnapshots(projectId);
+ for (Filter filter : filters) {
+ filter.log();
+ delete(filter.filter(history));
+ }
+ }
+
+ private void delete(List<PurgeableSnapshotDto> snapshots) {
+ 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()));
+ }
+ }
+
+ private List<PurgeableSnapshotDto> selectProjectSnapshots(long resourceId) {
+ return purgeDao.selectPurgeableSnapshots(resourceId);
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.core.computation.dbcleaner.period;
+
+import com.google.common.collect.Lists;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.core.purge.PurgeableSnapshotDto;
+
+import java.util.Date;
+import java.util.List;
+
+class DeleteAllFilter implements Filter {
+ private final Date before;
+
+ public DeleteAllFilter(Date before) {
+ this.before = before;
+ }
+
+ @Override
+ public List<PurgeableSnapshotDto> filter(List<PurgeableSnapshotDto> history) {
+ List<PurgeableSnapshotDto> result = Lists.newArrayList();
+ for (PurgeableSnapshotDto snapshot : history) {
+ if (snapshot.getDate().before(before)) {
+ result.add(snapshot);
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public void log() {
+ LoggerFactory.getLogger(getClass()).info("-> Delete data prior to: " + DateUtils.formatDate(before));
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.core.computation.dbcleaner.period;
+
+import org.sonar.core.purge.PurgeableSnapshotDto;
+
+import java.util.List;
+
+interface Filter {
+ List<PurgeableSnapshotDto> filter(List<PurgeableSnapshotDto> snapshots);
+
+ void log();
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.core.computation.dbcleaner.period;
+
+import com.google.common.collect.Lists;
+import org.apache.commons.lang.time.DateUtils;
+import org.sonar.api.config.Settings;
+import org.sonar.core.computation.dbcleaner.DbCleanerConstants;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+class Filters {
+ private final List<Filter> all = Lists.newArrayList();
+
+ Filters(Settings settings) {
+ Date dateToStartKeepingOneSnapshotByDay = getDateFromHours(settings, DbCleanerConstants.HOURS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_DAY);
+ Date dateToStartKeepingOneSnapshotByWeek = getDateFromWeeks(settings, DbCleanerConstants.WEEKS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_WEEK);
+ Date dateToStartKeepingOneSnapshotByMonth = getDateFromWeeks(settings, DbCleanerConstants.WEEKS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_MONTH);
+ Date dateToStartDeletingAllSnapshots = getDateFromWeeks(settings, DbCleanerConstants.WEEKS_BEFORE_DELETING_ALL_SNAPSHOTS);
+
+ all.add(new KeepOneFilter(dateToStartKeepingOneSnapshotByWeek, dateToStartKeepingOneSnapshotByDay, Calendar.DAY_OF_YEAR, "day"));
+ all.add(new KeepOneFilter(dateToStartKeepingOneSnapshotByMonth, dateToStartKeepingOneSnapshotByWeek, Calendar.WEEK_OF_YEAR, "week"));
+ all.add(new KeepOneFilter(dateToStartDeletingAllSnapshots, dateToStartKeepingOneSnapshotByMonth, Calendar.MONTH, "month"));
+ all.add(new DeleteAllFilter(dateToStartDeletingAllSnapshots));
+ }
+
+ static Date getDateFromWeeks(Settings settings, String propertyKey) {
+ int weeks = settings.getInt(propertyKey);
+ return DateUtils.addWeeks(new Date(), -weeks);
+ }
+
+ static Date getDateFromHours(Settings settings, String propertyKey) {
+ int hours = settings.getInt(propertyKey);
+ return DateUtils.addHours(new Date(), -hours);
+ }
+
+ List<Filter> all() {
+ return all;
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.core.computation.dbcleaner.period;
+
+import com.google.common.collect.Lists;
+import org.apache.commons.lang.time.DateUtils;
+import org.sonar.core.purge.PurgeableSnapshotDto;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.List;
+
+final class Interval {
+ List<PurgeableSnapshotDto> snapshots = Lists.newArrayList();
+
+ void add(PurgeableSnapshotDto snapshot) {
+ snapshots.add(snapshot);
+ }
+
+ List<PurgeableSnapshotDto> get() {
+ return snapshots;
+ }
+
+ int count() {
+ return snapshots.size();
+ }
+
+ static List<Interval> group(List<PurgeableSnapshotDto> snapshots, Date start, Date end, int calendarField) {
+ List<Interval> intervals = Lists.newArrayList();
+
+ GregorianCalendar calendar = new GregorianCalendar();
+ int lastYear = -1;
+ int lastFieldValue = -1;
+ Interval currentInterval = null;
+
+ for (PurgeableSnapshotDto snapshot : snapshots) {
+ if (!DateUtils.isSameDay(start, snapshot.getDate()) && snapshot.getDate().after(start) &&
+ (snapshot.getDate().before(end) || DateUtils.isSameDay(end, snapshot.getDate()))) {
+ calendar.setTime(snapshot.getDate());
+ int currentFieldValue = calendar.get(calendarField);
+ int currentYear = calendar.get(Calendar.YEAR);
+ if (lastYear!=currentYear || lastFieldValue != currentFieldValue) {
+ currentInterval = new Interval();
+ intervals.add(currentInterval);
+ }
+ lastFieldValue = currentFieldValue;
+ lastYear = currentYear;
+ if (currentInterval != null) {
+ currentInterval.add(snapshot);
+ }
+ }
+ }
+ return intervals;
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.core.computation.dbcleaner.period;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Lists;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.core.purge.PurgeableSnapshotDto;
+
+import java.util.Date;
+import java.util.List;
+
+class KeepOneFilter implements Filter {
+
+ private final Date start;
+ private final Date end;
+ private final int dateField;
+ private final String label;
+
+ KeepOneFilter(Date start, Date end, int calendarField, String label) {
+ this.start = start;
+ this.end = end;
+ this.dateField = calendarField;
+ this.label = label;
+ }
+
+ @Override
+ public List<PurgeableSnapshotDto> filter(List<PurgeableSnapshotDto> history) {
+ List<Interval> intervals = Interval.group(history, start, end, dateField);
+ List<PurgeableSnapshotDto> result = Lists.newArrayList();
+ for (Interval interval : intervals) {
+ appendSnapshotsToDelete(interval, result);
+ }
+
+ return result;
+ }
+
+ @Override
+ public void log() {
+ LoggerFactory.getLogger(getClass()).info("-> Keep one snapshot per " + label + " between " + DateUtils.formatDate(start) + " and " + DateUtils.formatDate(end));
+ }
+
+ private void appendSnapshotsToDelete(Interval interval, List<PurgeableSnapshotDto> toDelete) {
+ if (interval.count() > 1) {
+ List<PurgeableSnapshotDto> deletables = Lists.newArrayList();
+ List<PurgeableSnapshotDto> toKeep = Lists.newArrayList();
+ for (PurgeableSnapshotDto snapshot : interval.get()) {
+ if (isDeletable(snapshot)) {
+ deletables.add(snapshot);
+ } else {
+ toKeep.add(snapshot);
+ }
+ }
+
+ if (!toKeep.isEmpty()) {
+ toDelete.addAll(deletables);
+
+ } else if (deletables.size() > 1) {
+ // keep one snapshot
+ toDelete.addAll(deletables.subList(1, deletables.size()));
+ }
+ }
+ }
+
+ @VisibleForTesting
+ static boolean isDeletable(PurgeableSnapshotDto snapshot) {
+ return !snapshot.isLast() && !snapshot.hasEvents();
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.
+ */
+
+@ParametersAreNonnullByDefault
+package org.sonar.core.computation.dbcleaner.period;
+
+import javax.annotation.ParametersAreNonnullByDefault;
import org.sonar.api.CoreProperties;
import org.sonar.api.config.PropertyDefinition;
import org.sonar.api.resources.Qualifiers;
+import org.sonar.core.computation.dbcleaner.DbCleanerProperties;
import java.util.List;
defs.addAll(ExclusionProperties.all());
defs.addAll(SecurityProperties.all());
defs.addAll(DebtProperties.all());
+ defs.addAll(DbCleanerProperties.all());
defs.addAll(ImmutableList.of(
// BATCH
.category(CoreProperties.CATEGORY_GENERAL)
.subCategory(CoreProperties.SUBCATEGORY_DIFFERENTIAL_VIEWS)
.build()
- ));
+ ));
return defs;
}
}
<!-- the data report is not brought back by default as it could be too big in memory -->
ar.id,
ar.project_key as projectKey,
- ar.project_name as projectName,
ar.report_status as status,
ar.snapshot_id as snapshotId,
ar.created_at as createdAt,
<insert id="insert" parameterType="AnalysisReport" useGeneratedKeys="true">
insert into analysis_reports
- (project_key, project_name, snapshot_id, report_status, report_data, created_at, updated_at, started_at,
+ (project_key, snapshot_id, report_status, report_data, created_at, updated_at, started_at,
finished_at)
- values (#{projectKey}, #{projectName}, #{snapshotId}, #{status}, #{data}, #{createdAt}, #{updatedAt}, #{startedAt},
+ values (#{projectKey}, #{snapshotId}, #{status}, #{data}, #{createdAt}, #{updatedAt}, #{startedAt},
#{finishedAt})
</insert>
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.core.computation.dbcleaner;
+
+import org.junit.Test;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class DbCleanerPropertiesTest {
+
+ @Test
+ public void shouldGetExtensions() {
+ assertThat(new DbCleanerProperties().all()).hasSize(6);
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.core.computation.dbcleaner;
+
+import org.sonar.api.utils.DateUtils;
+import org.sonar.core.purge.PurgeableSnapshotDto;
+
+public final class DbCleanerTestUtils {
+
+ private DbCleanerTestUtils() {
+ }
+
+ public static PurgeableSnapshotDto createSnapshotWithDate(long snapshotId, String date) {
+ PurgeableSnapshotDto snapshot = new PurgeableSnapshotDto();
+ snapshot.setSnapshotId(snapshotId);
+ snapshot.setDate(DateUtils.parseDate(date));
+ return snapshot;
+ }
+
+ public static PurgeableSnapshotDto createSnapshotWithDateTime(long snapshotId, String datetime) {
+ PurgeableSnapshotDto snapshot = new PurgeableSnapshotDto();
+ snapshot.setSnapshotId(snapshotId);
+ snapshot.setDate(DateUtils.parseDateTime(datetime));
+ return snapshot;
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.core.computation.dbcleaner;
+
+import ch.qos.logback.classic.Logger;
+import org.junit.Test;
+import org.mockito.ArgumentMatcher;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.PropertyDefinitions;
+import org.sonar.api.config.Settings;
+import org.sonar.api.resources.Scopes;
+import org.sonar.core.computation.dbcleaner.period.DefaultPeriodCleaner;
+import org.sonar.core.purge.PurgeConfiguration;
+import org.sonar.core.purge.PurgeDao;
+import org.sonar.core.purge.PurgeProfiler;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.*;
+
+public class DefaultPurgeTaskTest {
+
+ @Test
+ public void shouldNotDeleteHistoricalDataOfDirectories() {
+ PurgeDao purgeDao = mock(PurgeDao.class);
+ Settings settings = new Settings(new PropertyDefinitions(DbCleanerProperties.all()));
+ settings.setProperty(DbCleanerConstants.PROPERTY_CLEAN_DIRECTORY, "false");
+ DefaultPurgeTask task = new DefaultPurgeTask(purgeDao, settings, mock(DefaultPeriodCleaner.class), mock(PurgeProfiler.class));
+
+ task.purge(1L);
+
+ verify(purgeDao).purge(argThat(new ArgumentMatcher<PurgeConfiguration>() {
+ @Override
+ public boolean matches(Object o) {
+ PurgeConfiguration conf = (PurgeConfiguration) o;
+ return conf.rootProjectId() == 1L && conf.scopesWithoutHistoricalData().length == 1 && conf.scopesWithoutHistoricalData()[0].equals(Scopes.FILE);
+ }
+ }));
+ }
+
+ @Test
+ public void shouldDeleteHistoricalDataOfDirectoriesByDefault() {
+ PurgeDao purgeDao = mock(PurgeDao.class);
+ Settings settings = new Settings(new PropertyDefinitions(DbCleanerProperties.all()));
+ DefaultPurgeTask task = new DefaultPurgeTask(purgeDao, settings, mock(DefaultPeriodCleaner.class), mock(PurgeProfiler.class));
+
+ task.purge(1L);
+
+ verify(purgeDao).purge(argThat(new ArgumentMatcher<PurgeConfiguration>() {
+ @Override
+ public boolean matches(Object o) {
+ PurgeConfiguration conf = (PurgeConfiguration) o;
+ return conf.rootProjectId() == 1L &&
+ conf.scopesWithoutHistoricalData().length == 2 &&
+ conf.scopesWithoutHistoricalData()[0].equals(Scopes.DIRECTORY) &&
+ conf.scopesWithoutHistoricalData()[1].equals(Scopes.FILE);
+ }
+ }));
+ }
+
+ @Test
+ public void shouldNotFailOnErrors() {
+ PurgeDao purgeDao = mock(PurgeDao.class);
+ when(purgeDao.purge(any(PurgeConfiguration.class))).thenThrow(new RuntimeException());
+ DefaultPurgeTask task = new DefaultPurgeTask(purgeDao, new Settings(), mock(DefaultPeriodCleaner.class), mock(PurgeProfiler.class));
+
+ task.purge(1L);
+
+ verify(purgeDao, times(1)).purge(any(PurgeConfiguration.class));
+ }
+
+ @Test
+ public void shouldDumpProfiling() {
+ PurgeConfiguration conf = new PurgeConfiguration(1L, new String[0], 30);
+ PurgeDao purgeDao = mock(PurgeDao.class);
+ when(purgeDao.purge(conf)).thenThrow(new RuntimeException());
+ Settings settings = new Settings(new PropertyDefinitions(DbCleanerProperties.all()));
+ settings.setProperty(CoreProperties.PROFILING_LOG_PROPERTY, true);
+ PurgeProfiler profiler = mock(PurgeProfiler.class);
+
+ DefaultPurgeTask task = new DefaultPurgeTask(purgeDao, settings, mock(DefaultPeriodCleaner.class), profiler);
+ task.purge(1L);
+
+ verify(profiler).dump(anyLong(), any(Logger.class));
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.core.computation.dbcleaner.period;
+
+import org.apache.commons.lang.ObjectUtils;
+import org.hamcrest.BaseMatcher;
+import org.junit.Test;
+import org.mockito.ArgumentMatcher;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.sonar.api.config.Settings;
+import org.sonar.core.purge.PurgeDao;
+import org.sonar.core.purge.PurgeSnapshotQuery;
+import org.sonar.core.purge.PurgeableSnapshotDto;
+
+import java.util.Arrays;
+import java.util.Date;
+
+import static org.mockito.Matchers.anyListOf;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.*;
+
+public class DefaultPeriodCleanerTest {
+
+
+ @Test
+ public void doClean() {
+ PurgeDao dao = mock(PurgeDao.class);
+ when(dao.selectPurgeableSnapshots(123L)).thenReturn(Arrays.asList(
+ new PurgeableSnapshotDto().setSnapshotId(999L).setDate(new Date())));
+ Filter filter1 = newLazyFilter();
+ Filter filter2 = newLazyFilter();
+
+ DefaultPeriodCleaner cleaner = new DefaultPeriodCleaner(dao, mock(Settings.class));
+ cleaner.doClean(123L, Arrays.asList(filter1, filter2));
+
+ 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 ArgumentMatcher<PurgeSnapshotQuery>() {
+ @Override
+ public boolean matches(Object o) {
+ PurgeSnapshotQuery query = (PurgeSnapshotQuery) o;
+ return ObjectUtils.equals(query.getRootSnapshotId(), 999L);
+ }
+ };
+ }
+
+ private BaseMatcher<PurgeSnapshotQuery> newSnapshotIdQuery() {
+ return new ArgumentMatcher<PurgeSnapshotQuery>() {
+ @Override
+ public boolean matches(Object o) {
+ PurgeSnapshotQuery query = (PurgeSnapshotQuery) o;
+ return ObjectUtils.equals(query.getId(), 999L);
+ }
+ };
+ }
+
+ private Filter newLazyFilter() {
+ Filter filter1 = mock(Filter.class);
+ when(filter1.filter(anyListOf(PurgeableSnapshotDto.class))).thenAnswer(new Answer<Object>() {
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ return invocation.getArguments()[0];
+ }
+ });
+ return filter1;
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.core.computation.dbcleaner.period;
+
+import org.junit.Test;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.core.computation.dbcleaner.DbCleanerTestUtils;
+import org.sonar.core.purge.PurgeableSnapshotDto;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class DeleteAllFilterTest {
+
+ @Test
+ public void shouldDeleteAllSnapshotsPriorToDate() {
+ Filter filter = new DeleteAllFilter(DateUtils.parseDate("2011-12-25"));
+
+ List<PurgeableSnapshotDto> toDelete = filter.filter(Arrays.asList(
+ DbCleanerTestUtils.createSnapshotWithDate(1L, "2010-01-01"),
+ DbCleanerTestUtils.createSnapshotWithDate(2L, "2010-12-25"),
+ DbCleanerTestUtils.createSnapshotWithDate(3L, "2012-01-01")
+ ));
+
+ assertThat(toDelete).onProperty("snapshotId").containsOnly(1L, 2L);
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.core.computation.dbcleaner.period;
+
+import org.junit.Test;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.core.purge.PurgeableSnapshotDto;
+
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.List;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.sonar.core.computation.dbcleaner.DbCleanerTestUtils.createSnapshotWithDate;
+import static org.sonar.core.computation.dbcleaner.DbCleanerTestUtils.createSnapshotWithDateTime;
+
+public class IntervalTest {
+ static int calendarField(Interval interval, int field) {
+ if (interval.count() == 0) {
+ return -1;
+ }
+
+ PurgeableSnapshotDto first = interval.get().iterator().next();
+ GregorianCalendar cal = new GregorianCalendar();
+ cal.setTime(first.getDate());
+ return cal.get(field);
+ }
+
+ @Test
+ public void shouldGroupByIntervals() {
+ List<PurgeableSnapshotDto> snapshots = Arrays.asList(
+ createSnapshotWithDate(1L, "2011-04-03"),
+
+ createSnapshotWithDate(2L, "2011-05-01"),
+ createSnapshotWithDate(3L, "2011-05-19"),
+
+ createSnapshotWithDate(4L, "2011-06-02"),
+ createSnapshotWithDate(5L, "2011-06-20"),
+
+ createSnapshotWithDate(6L, "2012-06-29") // out of scope
+ );
+
+ List<Interval> intervals = Interval.group(snapshots, DateUtils.parseDate("2010-01-01"), DateUtils.parseDate("2011-12-31"), Calendar.MONTH);
+ assertThat(intervals.size(), is(3));
+
+ assertThat(intervals.get(0).count(), is(1));
+ assertThat(calendarField(intervals.get(0), Calendar.MONTH), is(Calendar.APRIL));
+
+ assertThat(intervals.get(1).count(), is(2));
+ assertThat(calendarField(intervals.get(1), Calendar.MONTH), is(Calendar.MAY));
+
+ assertThat(intervals.get(2).count(), is(2));
+ assertThat(calendarField(intervals.get(2), Calendar.MONTH), is(Calendar.JUNE));
+ }
+
+ @Test
+ public void shouldNotJoinMonthsOfDifferentYears() {
+ List<PurgeableSnapshotDto> snapshots = Arrays.asList(
+ createSnapshotWithDate(1L, "2010-04-03"),
+ createSnapshotWithDate(2L, "2011-04-13")
+ );
+
+ List<Interval> intervals = Interval.group(snapshots, DateUtils.parseDate("2010-01-01"), DateUtils.parseDate("2011-12-31"), Calendar.MONTH);
+ assertThat(intervals.size(), is(2));
+
+ assertThat(intervals.get(0).count(), is(1));
+ assertThat(calendarField(intervals.get(0), Calendar.MONTH), is(Calendar.APRIL));
+ assertThat(calendarField(intervals.get(0), Calendar.YEAR), is(2010));
+
+ assertThat(intervals.get(1).count(), is(1));
+ assertThat(calendarField(intervals.get(1), Calendar.MONTH), is(Calendar.APRIL));
+ assertThat(calendarField(intervals.get(1), Calendar.YEAR), is(2011));
+ }
+
+ @Test
+ public void shouldIgnoreTimeWhenGroupingByIntervals() {
+ List<PurgeableSnapshotDto> snapshots = Arrays.asList(
+ createSnapshotWithDateTime(1L, "2011-05-25T16:16:48+0100"),
+ createSnapshotWithDateTime(2L, "2012-01-26T16:16:48+0100"),
+ createSnapshotWithDateTime(3L, "2012-01-27T16:16:48+0100")
+ );
+
+ List<Interval> intervals = Interval.group(snapshots, DateUtils.parseDate("2011-05-25"), DateUtils.parseDate("2012-01-26"), Calendar.MONTH);
+ assertThat(intervals.size(), is(1));
+ assertThat(intervals.get(0).count(), is(1));
+ assertThat(intervals.get(0).get().get(0).getSnapshotId(), is(2L));
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.core.computation.dbcleaner.period;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
+import org.junit.Test;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.core.purge.PurgeableSnapshotDto;
+
+import javax.annotation.Nullable;
+
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.List;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static org.fest.assertions.Assertions.assertThat;
+import static org.sonar.core.computation.dbcleaner.DbCleanerTestUtils.createSnapshotWithDate;
+
+public class KeepOneFilterTest {
+
+ private static List<Long> snapshotIds(List<PurgeableSnapshotDto> snapshotDtos) {
+ return newArrayList(Iterables.transform(snapshotDtos, new Function<PurgeableSnapshotDto, Long>() {
+ @Override
+ public Long apply(@Nullable PurgeableSnapshotDto input) {
+ return input != null ? input.getSnapshotId() : null;
+ }
+ }));
+ }
+
+ @Test
+ public void shouldOnlyOneSnapshotPerInterval() {
+ Filter filter = new KeepOneFilter(DateUtils.parseDate("2011-03-25"), DateUtils.parseDate("2011-08-25"), Calendar.MONTH, "month");
+
+ List<PurgeableSnapshotDto> toDelete = filter.filter(Arrays.<PurgeableSnapshotDto>asList(
+ createSnapshotWithDate(1L, "2010-01-01"), // out of scope -> keep
+ createSnapshotWithDate(2L, "2011-05-01"), // may -> keep
+ createSnapshotWithDate(3L, "2011-05-02"), // may -> to be deleted
+ createSnapshotWithDate(4L, "2011-05-19"), // may -> to be deleted
+ createSnapshotWithDate(5L, "2011-06-01"), // june -> keep
+ createSnapshotWithDate(6L, "2012-01-01") // out of scope -> keep
+ ));
+
+ assertThat(toDelete).hasSize(2);
+
+ List<Long> snapshotIds = snapshotIds(toDelete);
+ assertThat(snapshotIds).contains(3L);
+ assertThat(snapshotIds.contains(4L));
+ }
+
+ @Test
+ public void shouldKeepNonDeletableSnapshots() {
+ Filter filter = new KeepOneFilter(DateUtils.parseDate("2011-03-25"), DateUtils.parseDate("2011-08-25"), Calendar.MONTH, "month");
+
+ List<PurgeableSnapshotDto> toDelete = filter.filter(Arrays.<PurgeableSnapshotDto>asList(
+ createSnapshotWithDate(1L, "2011-05-01"), // to be deleted
+ createSnapshotWithDate(2L, "2011-05-02").setLast(true),
+ createSnapshotWithDate(3L, "2011-05-19").setHasEvents(true).setLast(false),
+ createSnapshotWithDate(4L, "2011-05-23") // to be deleted
+ ));
+
+ assertThat(toDelete).hasSize(2);
+
+ List<Long> snapshotIds = snapshotIds(toDelete);
+ assertThat(snapshotIds).contains(1L);
+ assertThat(snapshotIds.contains(4L));
+ }
+
+ @Test
+ public void test_isDeletable() {
+ assertThat(KeepOneFilter.isDeletable(createSnapshotWithDate(1L, "2011-05-01"))).isTrue();
+ assertThat(KeepOneFilter.isDeletable(createSnapshotWithDate(1L, "2011-05-01").setLast(true))).isFalse();
+ assertThat(KeepOneFilter.isDeletable(createSnapshotWithDate(1L, "2011-05-01").setHasEvents(true))).isFalse();
+ }
+
+}