From 1be37880a5ecfb86bd9fb326d42bbb5c5bfeaac6 Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Thu, 26 Jan 2012 17:16:49 +0100 Subject: [PATCH] SONAR-2807 + SONAR-3219 : improve the DBCleaner plugin * Delete all the wasted data. Some snapshots have been ignored * Keep a single snapshot per day --- .../plugins/dbcleaner/DbCleanerPlugin.java | 8 +- .../plugins/dbcleaner/api/PeriodCleaner.java | 1 - .../period/DefaultPeriodCleaner.java | 84 +++------ ...oDatesFilter.java => DeleteAllFilter.java} | 32 ++-- ...eepLastSnapshotFilter.java => Filter.java} | 12 +- .../plugins/dbcleaner/period/Filters.java | 56 ++++++ .../plugins/dbcleaner/period/Interval.java | 69 ++++++++ .../period/KeepLibrarySnapshotFilter.java | 30 ---- .../dbcleaner/period/KeepOneFilter.java | 88 +++++++++ ...SnapshotByPeriodBetweenTwoDatesFilter.java | 54 ------ .../plugins/dbcleaner/period/PeriodPurge.java | 39 ---- .../plugins/dbcleaner/period/Periods.java | 67 ------- .../plugins/dbcleaner/period/SQLRequests.java | 51 ------ .../dbcleaner/period/SnapshotFilter.java | 43 ----- .../runner/DeprecatedPurgePostJob.java | 161 ----------------- .../dbcleaner/runner/ProjectPurgePostJob.java | 10 +- .../dbcleaner/DbCleanerPluginTest.java | 3 +- .../plugins/dbcleaner/DbCleanerTestUtils.java | 64 +++++++ .../org/sonar/plugins/dbcleaner/Utils.java | 57 ------ .../period/DefaultPeriodCleanerTest.java | 68 ------- ...lterTest.java => DeleteAllFilterTest.java} | 33 ++-- .../dbcleaner/period/IntervalTest.java | 88 +++++++++ .../period/KeepLastSnapshotFilterTest.java | 46 ----- .../period/KeepLibrarySnapshotFilterTest.java | 48 ----- .../dbcleaner/period/KeepOneFilterTest.java | 78 ++++++++ ...shotByPeriodBetweenTwoDatesFilterTest.java | 50 ------ .../plugins/dbcleaner/period/PeriodsTest.java | 49 ----- .../runner/DeprecatedPurgePostJobTest.java | 111 ------------ .../dbContent-result.xml | 167 ------------------ .../DefaultPeriodCleanerTest/dbContent.xml | 149 ---------------- .../DeprecatedPurgePostJobTest/shared.xml | 75 -------- .../org/sonar/core/persistence/MyBatis.java | 2 + .../java/org/sonar/core/purge/PurgeDao.java | 18 ++ .../org/sonar/core/purge/PurgeMapper.java | 4 + .../sonar/core/purge/PurgeSnapshotQuery.java | 10 ++ .../core/purge/PurgeableSnapshotDto.java | 93 ++++++++++ .../org/sonar/core/purge/PurgeMapper.xml | 38 ++-- .../org/sonar/core/purge/PurgeDaoTest.java | 70 ++++++-- .../shouldSelectPurgeableSnapshots.xml | 64 +++++++ 39 files changed, 798 insertions(+), 1392 deletions(-) rename plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/{KeepSnapshotsBetweenTwoDatesFilter.java => DeleteAllFilter.java} (57%) rename plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/{KeepLastSnapshotFilter.java => Filter.java} (81%) create mode 100644 plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Filters.java create mode 100644 plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Interval.java delete mode 100644 plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepLibrarySnapshotFilter.java create mode 100644 plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepOneFilter.java delete mode 100644 plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepOneSnapshotByPeriodBetweenTwoDatesFilter.java delete mode 100644 plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/PeriodPurge.java delete mode 100644 plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Periods.java delete mode 100644 plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/SQLRequests.java delete mode 100644 plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/SnapshotFilter.java delete mode 100644 plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/runner/DeprecatedPurgePostJob.java create mode 100644 plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/DbCleanerTestUtils.java delete mode 100644 plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/Utils.java delete mode 100644 plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleanerTest.java rename plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/{KeepSnapshotsBetweenTwoDatesFilterTest.java => DeleteAllFilterTest.java} (53%) create mode 100644 plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/IntervalTest.java delete mode 100644 plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepLastSnapshotFilterTest.java delete mode 100644 plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepLibrarySnapshotFilterTest.java create mode 100644 plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepOneFilterTest.java delete mode 100644 plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepOneSnapshotByPeriodBetweenTwoDatesFilterTest.java delete mode 100644 plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/PeriodsTest.java delete mode 100644 plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/runner/DeprecatedPurgePostJobTest.java delete mode 100644 plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleanerTest/dbContent-result.xml delete mode 100644 plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleanerTest/dbContent.xml delete mode 100644 plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/runner/DeprecatedPurgePostJobTest/shared.xml create mode 100644 sonar-core/src/main/java/org/sonar/core/purge/PurgeableSnapshotDto.java create mode 100644 sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldSelectPurgeableSnapshots.xml diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/DbCleanerPlugin.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/DbCleanerPlugin.java index 0eb4d380281..a14b64b1f30 100644 --- a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/DbCleanerPlugin.java +++ b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/DbCleanerPlugin.java @@ -24,8 +24,6 @@ import org.sonar.api.Property; import org.sonar.api.SonarPlugin; import org.sonar.plugins.dbcleaner.api.DbCleanerConstants; import org.sonar.plugins.dbcleaner.period.DefaultPeriodCleaner; -import org.sonar.plugins.dbcleaner.period.PeriodPurge; -import org.sonar.plugins.dbcleaner.runner.DeprecatedPurgePostJob; import org.sonar.plugins.dbcleaner.runner.ProjectPurgePostJob; import java.util.Arrays; @@ -55,10 +53,6 @@ public final class DbCleanerPlugin extends SonarPlugin { public List getExtensions() { return Arrays.asList( - DefaultPeriodCleaner.class, - PeriodPurge.class, - - // post-jobs - ProjectPurgePostJob.class, DeprecatedPurgePostJob.class); + DefaultPeriodCleaner.class, ProjectPurgePostJob.class); } } diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/api/PeriodCleaner.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/api/PeriodCleaner.java index 25cad3f72d5..fb3cc833f58 100644 --- a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/api/PeriodCleaner.java +++ b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/api/PeriodCleaner.java @@ -23,7 +23,6 @@ import org.sonar.api.BatchExtension; import org.sonar.api.resources.Project; /** - * @since 2.14 * @deprecated in 2.14 */ @Deprecated diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleaner.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleaner.java index c12ae358fc4..ea50bac1d65 100644 --- a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleaner.java +++ b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleaner.java @@ -19,88 +19,52 @@ */ package org.sonar.plugins.dbcleaner.period; -import com.google.common.collect.Lists; +import com.google.common.annotations.VisibleForTesting; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.sonar.api.database.DatabaseSession; -import org.sonar.api.database.model.Snapshot; +import org.sonar.api.config.Settings; import org.sonar.api.resources.Project; +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 org.sonar.plugins.dbcleaner.api.PeriodCleaner; -import org.sonar.plugins.dbcleaner.api.PurgeUtils; -import java.text.DateFormat; -import java.util.Date; -import java.util.GregorianCalendar; import java.util.List; public final class DefaultPeriodCleaner implements PeriodCleaner { private static final Logger LOG = LoggerFactory.getLogger(DefaultPeriodCleaner.class); - private final SQLRequests sql; - private DatabaseSession session; + private PurgeDao purgeDao; + private Settings settings; - public DefaultPeriodCleaner(DatabaseSession session) { - this.session = session; - this.sql = new SQLRequests(session); + public DefaultPeriodCleaner(PurgeDao purgeDao, Settings settings) { + this.purgeDao = purgeDao; + this.settings = settings; } public void purge(Project project, int projectSnapshotId) { - Periods periods = new Periods(project); - periods.log(); - purge(project, projectSnapshotId, periods); + purge((long) project.getId()); } - void purge(Project project, int projectSnapshotId, Periods periods) { - List filters = newFilters(periods); - List snapshotHistory = selectProjectSnapshots(project, projectSnapshotId); - applyFilters(snapshotHistory, filters); - deleteSnapshotsAndAllRelatedData(snapshotHistory); - } - - private List selectProjectSnapshots(Project project, int snapshotId) { - List snapshotHistory = Lists.newLinkedList(sql.getProjectSnapshotsOrderedByCreatedAt(snapshotId)); - LOG.debug("The project '" + project.getName() + "' has " + snapshotHistory.size() + " snapshots."); - return snapshotHistory; - } + public void purge(long projectId) { + List history = selectProjectSnapshots(projectId); - private void deleteSnapshotsAndAllRelatedData(List snapshotHistory) { - if (snapshotHistory.isEmpty()) { - LOG.info("There are no snapshots to purge"); - return; - } - - List ids = Lists.newArrayList(); - for (Snapshot snapshot : snapshotHistory) { - ids.addAll(sql.getChildIds(snapshot)); - } - LOG.info("There are " + snapshotHistory.size() + " snapshots and " + (ids.size() - snapshotHistory.size()) - + " children snapshots which are obsolete and are going to be deleted."); - if (LOG.isDebugEnabled()) { - DateFormat format = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT); - for (Snapshot snapshot : snapshotHistory) { - LOG.debug("Delete snapshot created at " + format.format(snapshot.getCreatedAt())); - } + Filters filters = new Filters(settings); + for (Filter filter : filters.getFilters()) { + filter.log(); + delete(filter.filter(history)); } - PurgeUtils.deleteSnapshotsData(session, ids); } - private void applyFilters(List snapshotHistory, List filters) { - for (SnapshotFilter filter : filters) { - filter.filter(snapshotHistory); + private void delete(List snapshots) { + for (PurgeableSnapshotDto snapshot : snapshots) { + LOG.debug("<- Delete snapshot: " + DateUtils.formatDateTime(snapshot.getDate()) + " [" + snapshot.getSnapshotId() + "]"); + purgeDao.deleteSnapshots(PurgeSnapshotQuery.create().setRootSnapshotId(snapshot.getSnapshotId())); } } - private List newFilters(Periods periods) { - List filters = Lists.newArrayList(); - filters.add(new KeepLibrarySnapshotFilter()); - filters.add(new KeepSnapshotsBetweenTwoDatesFilter(new Date(), periods.dateToStartKeepingOneSnapshotByWeek)); - filters.add(new KeepOneSnapshotByPeriodBetweenTwoDatesFilter(GregorianCalendar.WEEK_OF_YEAR, - periods.dateToStartKeepingOneSnapshotByWeek, - periods.dateToStartKeepingOneSnapshotByMonth)); - filters.add(new KeepOneSnapshotByPeriodBetweenTwoDatesFilter(GregorianCalendar.MONTH, - periods.dateToStartKeepingOneSnapshotByMonth, - periods.dateToStartDeletingAllSnapshots)); - filters.add(new KeepLastSnapshotFilter()); - return filters; + private List selectProjectSnapshots(long resourceId) { + return purgeDao.selectPurgeableSnapshots(resourceId); } } diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepSnapshotsBetweenTwoDatesFilter.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/DeleteAllFilter.java similarity index 57% rename from plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepSnapshotsBetweenTwoDatesFilter.java rename to plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/DeleteAllFilter.java index d2e491f5715..51fdd03ff05 100644 --- a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepSnapshotsBetweenTwoDatesFilter.java +++ b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/DeleteAllFilter.java @@ -19,24 +19,34 @@ */ package org.sonar.plugins.dbcleaner.period; -import java.util.Date; - -import org.sonar.api.database.model.Snapshot; +import com.google.common.collect.Lists; +import org.slf4j.LoggerFactory; +import org.sonar.api.utils.DateUtils; +import org.sonar.core.purge.PurgeableSnapshotDto; -class KeepSnapshotsBetweenTwoDatesFilter extends SnapshotFilter { +import java.util.Date; +import java.util.List; - private Date before; - private Date after; +class DeleteAllFilter extends Filter { + private final Date before; - KeepSnapshotsBetweenTwoDatesFilter(Date before, Date after) { + public DeleteAllFilter(Date before) { this.before = before; - this.after = after; } @Override - boolean filter(Snapshot snapshot) { - Date createdAt = snapshot.getCreatedAt(); - return createdAt.before(before) && createdAt.after(after); + List filter(List history) { + List result = Lists.newArrayList(); + for (PurgeableSnapshotDto snapshot : history) { + if (snapshot.getDate().before(before)) { + result.add(snapshot); + } + } + return result; } + @Override + void log() { + LoggerFactory.getLogger(getClass()).debug("-> Delete data prior to: " + DateUtils.formatDate(before)); + } } diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepLastSnapshotFilter.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Filter.java similarity index 81% rename from plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepLastSnapshotFilter.java rename to plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Filter.java index 24ed1716da4..cb1b33e03e3 100644 --- a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepLastSnapshotFilter.java +++ b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Filter.java @@ -19,12 +19,12 @@ */ package org.sonar.plugins.dbcleaner.period; -import org.sonar.api.database.model.Snapshot; +import org.sonar.core.purge.PurgeableSnapshotDto; -class KeepLastSnapshotFilter extends SnapshotFilter { +import java.util.List; - @Override - boolean filter(Snapshot snapshot) { - return snapshot.getLast(); - } +abstract class Filter { + abstract List filter(List snapshots); + + abstract void log(); } diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Filters.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Filters.java new file mode 100644 index 00000000000..f89db209adf --- /dev/null +++ b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Filters.java @@ -0,0 +1,56 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +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.GregorianCalendar; +import java.util.List; + +class Filters { + private final List filters = Lists.newArrayList(); + + Filters(Settings settings) { + Date dateToStartKeepingOneSnapshotByWeek = getDate(settings, DbCleanerConstants.MONTHS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_WEEK); + Date dateToStartKeepingOneSnapshotByMonth = getDate(settings, DbCleanerConstants.MONTHS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_MONTH); + Date dateToStartDeletingAllSnapshots = getDate(settings, DbCleanerConstants.MONTHS_BEFORE_DELETING_ALL_SNAPSHOTS); + + filters.add(new KeepOneFilter(dateToStartKeepingOneSnapshotByWeek, new Date(), Calendar.DAY_OF_YEAR, "day")); + filters.add(new KeepOneFilter(dateToStartKeepingOneSnapshotByMonth, dateToStartKeepingOneSnapshotByWeek, Calendar.WEEK_OF_YEAR, "week")); + filters.add(new KeepOneFilter(dateToStartDeletingAllSnapshots, dateToStartKeepingOneSnapshotByMonth, Calendar.MONTH, "month")); + filters.add(new DeleteAllFilter(dateToStartDeletingAllSnapshots)); + } + + List getFilters() { + return filters; + } + + static Date getDate(Settings settings, String propertyKey) { + int months = settings.getInt(propertyKey); + GregorianCalendar calendar = new GregorianCalendar(); + calendar.add(GregorianCalendar.MONTH, -months); + return calendar.getTime(); + } +} diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Interval.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Interval.java new file mode 100644 index 00000000000..40e422f9faf --- /dev/null +++ b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Interval.java @@ -0,0 +1,69 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +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.Date; +import java.util.GregorianCalendar; +import java.util.List; + +final class Interval { + List snapshots = Lists.newArrayList(); + + void add(PurgeableSnapshotDto snapshot) { + snapshots.add(snapshot); + } + + List get() { + return snapshots; + } + + int count() { + return snapshots.size(); + } + + static List group(List snapshots, Date start, Date end, int calendarField) { + List intervals = Lists.newArrayList(); + + GregorianCalendar calendar = new GregorianCalendar(); + 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); + if (lastFieldValue != currentFieldValue) { + currentInterval = new Interval(); + intervals.add(currentInterval); + } + lastFieldValue = currentFieldValue; + if (currentInterval != null) { + currentInterval.add(snapshot); + } + } + } + return intervals; + } +} diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepLibrarySnapshotFilter.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepLibrarySnapshotFilter.java deleted file mode 100644 index 906a8d743ef..00000000000 --- a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepLibrarySnapshotFilter.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2012 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar 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. - * - * Sonar 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 Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.dbcleaner.period; - -import org.sonar.api.database.model.Snapshot; - -class KeepLibrarySnapshotFilter extends SnapshotFilter { - - @Override - boolean filter(Snapshot snapshot) { - return "LIB".equals(snapshot.getQualifier()); - } -} diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepOneFilter.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepOneFilter.java new file mode 100644 index 00000000000..fa8c5b3255f --- /dev/null +++ b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepOneFilter.java @@ -0,0 +1,88 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +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 extends 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 + List filter(List history) { + List intervals = Interval.group(history, start, end, dateField); + List result = Lists.newArrayList(); + for (Interval interval : intervals) { + appendSnapshotsToDelete(interval, result); + } + + return result; + } + + @Override + void log() { + LoggerFactory.getLogger(getClass()).debug("-> Keep one snapshot per " + label + " between " + DateUtils.formatDate(start) + " and " + DateUtils.formatDate(end)); + } + + private void appendSnapshotsToDelete(Interval interval, List toDelete) { + if (interval.count() > 1) { + List deletables = Lists.newArrayList(); + List 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.hasVersionEvent(); + } + +} diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepOneSnapshotByPeriodBetweenTwoDatesFilter.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepOneSnapshotByPeriodBetweenTwoDatesFilter.java deleted file mode 100644 index 17e6d9ac65c..00000000000 --- a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepOneSnapshotByPeriodBetweenTwoDatesFilter.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2012 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar 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. - * - * Sonar 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 Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.dbcleaner.period; - -import java.util.Date; -import java.util.GregorianCalendar; - -import org.sonar.api.database.model.Snapshot; - -class KeepOneSnapshotByPeriodBetweenTwoDatesFilter extends SnapshotFilter { - - private final Date before; - private final Date after; - private GregorianCalendar calendar = new GregorianCalendar(); - private int lastFieldValue = -1; - private final int dateField; - - KeepOneSnapshotByPeriodBetweenTwoDatesFilter(int dateField, Date before, Date after) { - this.before = before; - this.after = after; - this.dateField = dateField; - } - - @Override - boolean filter(Snapshot snapshot) { - boolean result = false; - Date createdAt = snapshot.getCreatedAt(); - calendar.setTime(createdAt); - int currentFieldValue = calendar.get(dateField); - if (lastFieldValue != currentFieldValue && snapshot.getCreatedAt().after(after) && snapshot.getCreatedAt().before(before)) { - result = true; - } - lastFieldValue = currentFieldValue; - return result; - } - -} diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/PeriodPurge.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/PeriodPurge.java deleted file mode 100644 index b7efbf9a71c..00000000000 --- a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/PeriodPurge.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2012 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar 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. - * - * Sonar 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 Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.dbcleaner.period; - -import org.sonar.api.database.DatabaseSession; -import org.sonar.plugins.dbcleaner.api.PeriodCleaner; -import org.sonar.plugins.dbcleaner.api.Purge; -import org.sonar.plugins.dbcleaner.api.PurgeContext; - -public final class PeriodPurge extends Purge { - - private PeriodCleaner periodCleaner; - - public PeriodPurge(DatabaseSession session, PeriodCleaner periodCleaner) { - super(session); - this.periodCleaner = periodCleaner; - } - - public void purge(PurgeContext context) { - periodCleaner.purge(context.getProject(), context.getSnapshotId()); - } -} diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Periods.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Periods.java deleted file mode 100644 index ae1766c3593..00000000000 --- a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Periods.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2012 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar 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. - * - * Sonar 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 Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.dbcleaner.period; - -import org.apache.commons.configuration.Configuration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.sonar.api.resources.Project; -import org.sonar.plugins.dbcleaner.api.DbCleanerConstants; - -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.GregorianCalendar; - -public final class Periods { - - Date dateToStartKeepingOneSnapshotByWeek; - Date dateToStartKeepingOneSnapshotByMonth; - Date dateToStartDeletingAllSnapshots; - - public Periods(Date dateToStartKeepingOneSnapshotByWeek, Date dateToStartKeepingOneSnapshotByMonth, Date dateToStartDeletingAllSnapshots) { - this.dateToStartKeepingOneSnapshotByWeek = dateToStartKeepingOneSnapshotByWeek; - this.dateToStartKeepingOneSnapshotByMonth = dateToStartKeepingOneSnapshotByMonth; - this.dateToStartDeletingAllSnapshots = dateToStartDeletingAllSnapshots; - } - - public Periods(Project project) { - dateToStartKeepingOneSnapshotByWeek = getDate(project.getConfiguration(), - DbCleanerConstants.MONTHS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_WEEK, DbCleanerConstants.ONE_MONTH); - dateToStartKeepingOneSnapshotByMonth = getDate(project.getConfiguration(), - DbCleanerConstants.MONTHS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_MONTH, DbCleanerConstants.ONE_YEAR); - dateToStartDeletingAllSnapshots = getDate(project.getConfiguration(), DbCleanerConstants.MONTHS_BEFORE_DELETING_ALL_SNAPSHOTS, - DbCleanerConstants.FIVE_YEARS); - } - - void log() { - Logger logger = LoggerFactory.getLogger(getClass()); - SimpleDateFormat dateFormat = new SimpleDateFormat(); - logger.debug("Keep only one snapshot by week after : " + dateFormat.format(dateToStartKeepingOneSnapshotByWeek)); - logger.debug("Keep only one snapshot by month after : " + dateFormat.format(dateToStartKeepingOneSnapshotByMonth)); - logger.debug("Delete all snapshots after : " + dateFormat.format(dateToStartDeletingAllSnapshots)); - } - - static Date getDate(Configuration conf, String propertyKey, String defaultNumberOfMonths) { - int months = conf.getInt(propertyKey, Integer.parseInt(defaultNumberOfMonths)); - GregorianCalendar calendar = new GregorianCalendar(); - calendar.add(GregorianCalendar.MONTH, -months); - return calendar.getTime(); - } -} diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/SQLRequests.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/SQLRequests.java deleted file mode 100644 index 47f89ff2cef..00000000000 --- a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/SQLRequests.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2012 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar 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. - * - * Sonar 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 Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.dbcleaner.period; - -import org.sonar.api.batch.Event; -import org.sonar.api.database.DatabaseSession; -import org.sonar.api.database.model.Snapshot; - -import javax.persistence.Query; -import java.util.List; - -final class SQLRequests { - - private final DatabaseSession session; - - SQLRequests(DatabaseSession session) { - this.session = session; - } - - List getProjectSnapshotsOrderedByCreatedAt(int oneProjectSnapshotId) { - Query query = session.createQuery("FROM " + Snapshot.class.getSimpleName() - + " sp1 WHERE sp1.resourceId = (select sp2.resourceId FROM " + Snapshot.class.getSimpleName() - + " sp2 WHERE sp2.id = :id) and sp1.rootId= null and not exists (from " + Event.class.getSimpleName() + " e where e.snapshot=sp1) order by sp1.createdAt"); - query.setParameter("id", oneProjectSnapshotId); - return query.getResultList(); - } - - List getChildIds(Snapshot parentSnapshot) { - Query query = session.createQuery("select sp.id FROM " + Snapshot.class.getSimpleName() - + " sp WHERE sp.rootId = :rootId or id = :rootId"); - query.setParameter("rootId", parentSnapshot.getId()); - return query.getResultList(); - } -} diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/SnapshotFilter.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/SnapshotFilter.java deleted file mode 100644 index 1a85cee7960..00000000000 --- a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/SnapshotFilter.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2012 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar 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. - * - * Sonar 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 Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.dbcleaner.period; - -import java.util.List; -import java.util.ListIterator; - -import org.sonar.api.database.model.Snapshot; - -abstract class SnapshotFilter { - - final int filter(List snapshots) { - int before = snapshots.size(); - ListIterator iterator = snapshots.listIterator(); - while (iterator.hasNext()) { - Snapshot snapshot = iterator.next(); - if(filter(snapshot)){ - iterator.remove(); - } - } - int after = snapshots.size(); - return before - after; - } - - abstract boolean filter(Snapshot snapshot); -} diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/runner/DeprecatedPurgePostJob.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/runner/DeprecatedPurgePostJob.java deleted file mode 100644 index 2069b3873cd..00000000000 --- a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/runner/DeprecatedPurgePostJob.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2012 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar 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. - * - * Sonar 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 Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.dbcleaner.runner; - -import org.apache.commons.lang.builder.ToStringBuilder; -import org.hibernate.HibernateException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.sonar.api.batch.PostJob; -import org.sonar.api.batch.SensorContext; -import org.sonar.api.database.DatabaseSession; -import org.sonar.api.database.model.Snapshot; -import org.sonar.api.resources.Project; -import org.sonar.api.utils.TimeProfiler; -import org.sonar.core.NotDryRun; -import org.sonar.plugins.dbcleaner.api.Purge; -import org.sonar.plugins.dbcleaner.api.PurgeContext; - -import javax.persistence.Query; - -@NotDryRun -public final class DeprecatedPurgePostJob implements PostJob { - - private DatabaseSession session; - private Snapshot snapshot; - private Purge[] purges; - private Project project; - private static final Logger LOG = LoggerFactory.getLogger(DeprecatedPurgePostJob.class); - - public DeprecatedPurgePostJob(DatabaseSession session, Project project, Snapshot snapshot, Purge[] purges) { - this.session = session; - this.project = project; - this.snapshot = snapshot; - this.purges = purges.clone(); - } - - public void executeOn(Project project, SensorContext context) { - if (shouldExecuteOn(project)) { - purge(); - } - } - - static boolean shouldExecuteOn(Project project) { - return project.isRoot(); - } - - public void purge() { - TimeProfiler profiler = new TimeProfiler(LOG).start("Database optimization"); - DefaultPurgeContext context = newContext(); - LOG.debug("Snapshots to purge: " + context); - executePurges(context); - profiler.stop(); - } - - - private void executePurges(DefaultPurgeContext context) { - TimeProfiler profiler = new TimeProfiler(); - for (Purge purge : purges) { - try { - profiler.start("Purge " + purge.getClass().getName()); - purge.purge(context); - session.commit(); // force hibernate to commit, so we're sure that the potential raised exception comes from this purge - profiler.stop(); - } catch (javax.persistence.PersistenceException e) { - // Temporary workaround for MySQL deadlocks. The exception must not fail the build - // See https://jira.codehaus.org/browse/SONAR-2961 and https://jira.codehaus.org/browse/SONAR-2190 - LOG.warn("Fail to execute purge: " + purge, e); - - } catch (HibernateException e) { - // Temporary workaround for MySQL deadlocks. The exception must not fail the build - // See https://jira.codehaus.org/browse/SONAR-2961 and https://jira.codehaus.org/browse/SONAR-2190 - LOG.warn("Fail to execute purge: " + purge, e); - } - } - } - - private DefaultPurgeContext newContext() { - DefaultPurgeContext context = new DefaultPurgeContext(project, snapshot); - Snapshot previousLastSnapshot = getPreviousLastSnapshot(); - if (previousLastSnapshot != null && previousLastSnapshot.getCreatedAt().before(snapshot.getCreatedAt())) { - context.setLastSnapshotId(previousLastSnapshot.getId()); - } - return context; - } - - private Snapshot getPreviousLastSnapshot() { - Query query = session.createQuery( - "SELECT s FROM " + Snapshot.class.getSimpleName() + " s " + - "WHERE s.status=:status AND s.resourceId=:resourceId AND s.createdAt<:date AND s.id <> :sid ORDER BY s.createdAt DESC"); - query.setParameter("status", Snapshot.STATUS_PROCESSED); - query.setParameter("resourceId", snapshot.getResourceId()); - query.setParameter("date", snapshot.getCreatedAt()); - query.setParameter("sid", snapshot.getId()); - query.setMaxResults(1); - return session.getSingleResult(query, null); - } - - static final class DefaultPurgeContext implements PurgeContext { - - private Project project; - private Integer currentSid; - private Integer previousSid; - - public DefaultPurgeContext(Project project, Snapshot currentSnapshot) { - this(project, currentSnapshot, null); - } - - public DefaultPurgeContext(Project project, Snapshot currentSnapshot, Snapshot previousSnapshot) { - this.project = project; - if (currentSnapshot != null) { - currentSid = currentSnapshot.getId(); - } - if (previousSnapshot != null) { - previousSid = previousSnapshot.getId(); - } - } - - public DefaultPurgeContext setLastSnapshotId(Integer previousSid) { - this.previousSid = previousSid; - return this; - } - - public Integer getSnapshotId() { - return currentSid; - } - - public Integer getPreviousSnapshotId() { - return previousSid; - } - - public Project getProject() { - return project; - } - - @Override - public String toString() { - return new ToStringBuilder(this) - .append("currentSid", currentSid) - .append("previousSid", previousSid) - .toString(); - } - } - -} diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/runner/ProjectPurgePostJob.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/runner/ProjectPurgePostJob.java index 5a5646e4187..016cf6aee01 100644 --- a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/runner/ProjectPurgePostJob.java +++ b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/runner/ProjectPurgePostJob.java @@ -30,6 +30,7 @@ import org.sonar.core.NotDryRun; import org.sonar.core.purge.PurgeDao; import org.sonar.core.purge.PurgeSnapshotQuery; import org.sonar.plugins.dbcleaner.api.DbCleanerConstants; +import org.sonar.plugins.dbcleaner.period.DefaultPeriodCleaner; @Properties({ @Property( @@ -42,14 +43,17 @@ public class ProjectPurgePostJob implements PostJob { private PurgeDao purgeDao; private Settings settings; + private DefaultPeriodCleaner periodCleaner; - public ProjectPurgePostJob(PurgeDao purgeDao, Settings settings) { + public ProjectPurgePostJob(PurgeDao purgeDao, Settings settings, DefaultPeriodCleaner periodCleaner) { this.purgeDao = purgeDao; this.settings = settings; + this.periodCleaner = periodCleaner; } public void executeOn(final Project project, SensorContext context) { long projectId = (long) project.getId(); + cleanHistory(projectId); deleteAbortedBuilds(projectId); deleteFileHistory(projectId); if (settings.getBoolean(DbCleanerConstants.PROPERTY_CLEAN_DIRECTORY)) { @@ -58,6 +62,10 @@ public class ProjectPurgePostJob implements PostJob { purgeProject(projectId); } + private void cleanHistory(long projectId) { + periodCleaner.purge(projectId); + } + private void purgeProject(long projectId) { purgeDao.purgeProject(projectId); } diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/DbCleanerPluginTest.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/DbCleanerPluginTest.java index f08ebf1f690..e46d3bb44bb 100644 --- a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/DbCleanerPluginTest.java +++ b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/DbCleanerPluginTest.java @@ -22,12 +22,13 @@ package org.sonar.plugins.dbcleaner; import org.junit.Test; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; import static org.hamcrest.number.OrderingComparisons.greaterThan; public class DbCleanerPluginTest { @Test public void shouldGetExtensions() { - assertThat(new DbCleanerPlugin().getExtensions().size(), greaterThan(2)); + assertThat(new DbCleanerPlugin().getExtensions().size(), is(2)); } } diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/DbCleanerTestUtils.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/DbCleanerTestUtils.java new file mode 100644 index 00000000000..9711b383533 --- /dev/null +++ b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/DbCleanerTestUtils.java @@ -0,0 +1,64 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.dbcleaner; + +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.sonar.api.utils.DateUtils; +import org.sonar.core.purge.PurgeableSnapshotDto; + +import java.util.Date; +import java.util.GregorianCalendar; + +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; + } + + public static final class SnapshotMatcher extends BaseMatcher { + long snapshotId; + + public SnapshotMatcher(long snapshotId) { + this.snapshotId = snapshotId; + } + + public boolean matches(Object o) { + return ((PurgeableSnapshotDto) o).getSnapshotId() == snapshotId; + } + + public void describeTo(Description description) { + description.appendText("snapshotId").appendValue(snapshotId); + } + } +} diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/Utils.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/Utils.java deleted file mode 100644 index 59f9f257d9a..00000000000 --- a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/Utils.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2012 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar 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. - * - * Sonar 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 Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.dbcleaner; - -import java.util.Date; -import java.util.GregorianCalendar; - -import org.sonar.api.database.model.Snapshot; - -public class Utils { - - public static Snapshot createSnapshot(int id, String version) { - Snapshot snapshot = new Snapshot(); - snapshot.setId(id); - snapshot.setVersion(version); - snapshot.setCreatedAt(new GregorianCalendar().getTime()); - return snapshot; - } - - public static Snapshot createSnapshot(int id, Date createdAt) { - Snapshot snapshot = new Snapshot(); - snapshot.setId(id); - snapshot.setCreatedAt(createdAt); - return snapshot; - } - - public static Date day(int delta) { - GregorianCalendar calendar = new GregorianCalendar(); - calendar.add(GregorianCalendar.DAY_OF_YEAR, delta); - return calendar.getTime(); - } - - public static Date week(int delta, int dayOfWeek) { - GregorianCalendar calendar = new GregorianCalendar(); - calendar.add(GregorianCalendar.WEEK_OF_YEAR, delta); - calendar.set(GregorianCalendar.DAY_OF_WEEK, dayOfWeek); - return calendar.getTime(); - } - -} diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleanerTest.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleanerTest.java deleted file mode 100644 index 99e035757aa..00000000000 --- a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleanerTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2012 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar 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. - * - * Sonar 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 Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.dbcleaner.period; - -import org.apache.commons.configuration.PropertiesConfiguration; -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.resources.Project; -import org.sonar.jpa.test.AbstractDbUnitTestCase; - -import java.util.Date; -import java.util.GregorianCalendar; - -public class DefaultPeriodCleanerTest extends AbstractDbUnitTestCase { - - DefaultPeriodCleaner cleaner; - - Project project; - Periods periods; - - @Before - public void init() { - cleaner = new DefaultPeriodCleaner(getSession()); - - project = new Project("myproject"); - project.setConfiguration(new PropertiesConfiguration()); - - GregorianCalendar calendar = new GregorianCalendar(2010, 10, 1); - Date dateToStartKeepingOneSnapshotByWeek = calendar.getTime(); - calendar.set(2010, 7, 1); - Date dateToStartKeepingOneSnapshotByMonth = calendar.getTime(); - calendar.set(2010, 2, 1); - Date dateToStartDeletingAllSnapshots = calendar.getTime(); - periods = new Periods(dateToStartKeepingOneSnapshotByWeek, dateToStartKeepingOneSnapshotByMonth, dateToStartDeletingAllSnapshots); - } - - @Test - public void integrationTests() { - setupData("dbContent"); - cleaner.purge(project, 1010, periods); - checkTables("dbContent", "snapshots"); - } - - @Test - public void test() { - // After a first run, no more snapshot should be deleted - setupData("dbContent-result"); - cleaner.purge(project, 1010, periods); - checkTables("dbContent"); - } -} diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepSnapshotsBetweenTwoDatesFilterTest.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/DeleteAllFilterTest.java similarity index 53% rename from plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepSnapshotsBetweenTwoDatesFilterTest.java rename to plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/DeleteAllFilterTest.java index 9afa90b7f47..a4123185a5c 100644 --- a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepSnapshotsBetweenTwoDatesFilterTest.java +++ b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/DeleteAllFilterTest.java @@ -19,33 +19,32 @@ */ package org.sonar.plugins.dbcleaner.period; -import com.google.common.collect.Lists; import org.junit.Test; -import org.sonar.api.database.model.Snapshot; +import org.sonar.api.utils.DateUtils; +import org.sonar.core.purge.PurgeableSnapshotDto; +import org.sonar.plugins.dbcleaner.DbCleanerTestUtils; -import java.util.Date; +import java.util.Arrays; import java.util.List; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; -import static org.sonar.plugins.dbcleaner.Utils.createSnapshot; -import static org.sonar.plugins.dbcleaner.Utils.day; +import static org.junit.internal.matchers.IsCollectionContaining.hasItem; -public class KeepSnapshotsBetweenTwoDatesFilterTest { +public class DeleteAllFilterTest { @Test - public void testFilter() { - List snapshots = Lists.newLinkedList(); - snapshots.add(createSnapshot(1, day(-100))); - snapshots.add(createSnapshot(2, day(-70))); - snapshots.add(createSnapshot(3, day(-40))); - snapshots.add(createSnapshot(4, day(-10))); + public void shouldDeleteAllSnapshotsPriorToDate() { + Filter filter = new DeleteAllFilter(DateUtils.parseDate("2011-12-25")); - assertThat(new KeepSnapshotsBetweenTwoDatesFilter(new Date(), day(-1)).filter(snapshots), is(0)); - assertThat(snapshots.size(), is(4)); + List toDelete = filter.filter(Arrays.asList( + DbCleanerTestUtils.createSnapshotWithDate(1L, "2010-01-01"), + DbCleanerTestUtils.createSnapshotWithDate(2L, "2010-12-25"), + DbCleanerTestUtils.createSnapshotWithDate(3L, "2012-01-01") + )); - assertThat(new KeepSnapshotsBetweenTwoDatesFilter(new Date(), day(-80)).filter(snapshots), is(3)); - assertThat(snapshots.size(), is(1)); - assertThat(snapshots.get(0).getId(), is(1)); + assertThat(toDelete.size(), is(2)); + assertThat(toDelete, hasItem(new DbCleanerTestUtils.SnapshotMatcher(1L))); + assertThat(toDelete, hasItem(new DbCleanerTestUtils.SnapshotMatcher(2L))); } } diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/IntervalTest.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/IntervalTest.java new file mode 100644 index 00000000000..b369383d1e3 --- /dev/null +++ b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/IntervalTest.java @@ -0,0 +1,88 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +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 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 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(month(intervals.get(0)), is(Calendar.APRIL)); + + assertThat(intervals.get(1).count(), is(2)); + assertThat(month(intervals.get(1)), is(Calendar.MAY)); + + assertThat(intervals.get(2).count(), is(2)); + assertThat(month(intervals.get(2)), is(Calendar.JUNE)); + } + + @Test + public void shouldIgnoreTimeWhenGroupingByIntervals() { + List 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 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 month(Interval interval) { + if (interval.count() == 0) { + return -1; + } + + PurgeableSnapshotDto first = interval.get().iterator().next(); + GregorianCalendar cal = new GregorianCalendar(); + cal.setTime(first.getDate()); + return cal.get(Calendar.MONTH); + } +} diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepLastSnapshotFilterTest.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepLastSnapshotFilterTest.java deleted file mode 100644 index 667502a76c2..00000000000 --- a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepLastSnapshotFilterTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2012 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar 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. - * - * Sonar 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 Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.dbcleaner.period; - -import com.google.common.collect.Lists; -import org.junit.Test; -import org.sonar.api.database.model.Snapshot; - -import java.util.List; - -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; -import static org.sonar.plugins.dbcleaner.Utils.createSnapshot; - -public class KeepLastSnapshotFilterTest { - - @Test - public void testFilter() { - List snapshots = Lists.newLinkedList(); - snapshots.add(createSnapshot(1, "0.1")); - Snapshot lastSnapshot = createSnapshot(2, "0.1"); - lastSnapshot.setLast(true); - snapshots.add(lastSnapshot); - - assertThat(new KeepLastSnapshotFilter().filter(snapshots), is(1)); - assertThat(snapshots.size(), is(1)); - assertThat(snapshots.get(0).getId(), is(1)); - } -} diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepLibrarySnapshotFilterTest.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepLibrarySnapshotFilterTest.java deleted file mode 100644 index d8031fd2464..00000000000 --- a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepLibrarySnapshotFilterTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2012 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar 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. - * - * Sonar 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 Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.dbcleaner.period; - -import com.google.common.collect.Lists; -import org.junit.Test; -import org.sonar.api.database.model.Snapshot; - -import java.util.List; - -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; -import static org.sonar.plugins.dbcleaner.Utils.createSnapshot; - -public class KeepLibrarySnapshotFilterTest { - - @Test - public void testFilter() { - List snapshots = Lists.newLinkedList(); - Snapshot snapshot = createSnapshot(2, "0.1"); - snapshots.add(snapshot); - snapshot.setQualifier("TRK"); - snapshot = createSnapshot(2, "0.1"); - snapshot.setQualifier("LIB"); - snapshots.add(snapshot); - - assertThat(new KeepLibrarySnapshotFilter().filter(snapshots), is(1)); - assertThat(snapshots.size(), is(1)); - assertThat(snapshots.get(0).getId(), is(2)); - } -} diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepOneFilterTest.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepOneFilterTest.java new file mode 100644 index 00000000000..9e775a7fc61 --- /dev/null +++ b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepOneFilterTest.java @@ -0,0 +1,78 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.dbcleaner.period; + +import org.junit.Test; +import org.junit.internal.matchers.IsCollectionContaining; +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.Calendar; +import java.util.List; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.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 toDelete = filter.filter(Arrays.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.size(), is(2)); + assertThat(toDelete, IsCollectionContaining.hasItem(new DbCleanerTestUtils.SnapshotMatcher(3L))); + assertThat(toDelete, IsCollectionContaining.hasItem(new DbCleanerTestUtils.SnapshotMatcher(4L))); + } + + @Test + public void shouldKeepNonDeletableSnapshots() { + Filter filter = new KeepOneFilter(DateUtils.parseDate("2011-03-25"), DateUtils.parseDate("2011-08-25"), Calendar.MONTH, "month"); + + List toDelete = filter.filter(Arrays.asList( + createSnapshotWithDate(1L, "2011-05-01"), // to be deleted + createSnapshotWithDate(2L, "2011-05-02").setLast(true), + createSnapshotWithDate(3L, "2011-05-19").setHasVersionEvent(true).setLast(false), + createSnapshotWithDate(4L, "2011-05-23") // to be deleted + )); + + assertThat(toDelete.size(), is(2)); + assertThat(toDelete, IsCollectionContaining.hasItem(new DbCleanerTestUtils.SnapshotMatcher(1L))); + assertThat(toDelete, IsCollectionContaining.hasItem(new DbCleanerTestUtils.SnapshotMatcher(4L))); + } + + @Test + public void test_isDeletable() { + assertThat(KeepOneFilter.isDeletable(createSnapshotWithDate(1L, "2011-05-01")), is(true)); + assertThat(KeepOneFilter.isDeletable(createSnapshotWithDate(1L, "2011-05-01").setLast(true)), is(false)); + assertThat(KeepOneFilter.isDeletable(createSnapshotWithDate(1L, "2011-05-01").setHasVersionEvent(true)), is(false)); + } +} diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepOneSnapshotByPeriodBetweenTwoDatesFilterTest.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepOneSnapshotByPeriodBetweenTwoDatesFilterTest.java deleted file mode 100644 index b2d2e5b4718..00000000000 --- a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepOneSnapshotByPeriodBetweenTwoDatesFilterTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2012 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar 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. - * - * Sonar 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 Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.dbcleaner.period; - -import com.google.common.collect.Lists; -import org.junit.Test; -import org.sonar.api.database.model.Snapshot; -import org.sonar.plugins.dbcleaner.Utils; - -import java.util.GregorianCalendar; -import java.util.List; - -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - -public class KeepOneSnapshotByPeriodBetweenTwoDatesFilterTest { - - @Test - public void testFilter() { - List snapshots = Lists.newLinkedList(); - snapshots.add(Utils.createSnapshot(1, Utils.week(-7, 1))); - snapshots.add(Utils.createSnapshot(2, Utils.week(-7, 2))); - snapshots.add(Utils.createSnapshot(3, Utils.week(-7, 3))); - snapshots.add(Utils.createSnapshot(4, Utils.week(-6, 3))); - snapshots.add(Utils.createSnapshot(5, Utils.week(-6, 4))); - - assertThat(new KeepOneSnapshotByPeriodBetweenTwoDatesFilter(GregorianCalendar.WEEK_OF_YEAR, Utils.week(-3, 1), Utils.week(-9, 1)).filter(snapshots), is(2)); - assertThat(snapshots.size(), is(3)); - assertThat(snapshots.get(0).getId(), is(2)); - assertThat(snapshots.get(1).getId(), is(3)); - assertThat(snapshots.get(2).getId(), is(5)); - } -} diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/PeriodsTest.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/PeriodsTest.java deleted file mode 100644 index f03e050b423..00000000000 --- a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/PeriodsTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2012 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar 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. - * - * Sonar 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 Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.dbcleaner.period; - -import org.apache.commons.configuration.PropertiesConfiguration; -import org.junit.Test; -import org.sonar.api.resources.Project; - -import java.util.Date; -import java.util.GregorianCalendar; - -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - -public class PeriodsTest { - - @Test - public void getDateShouldReturnCurrentTimeMinusDesiredMonths() { - Project project = new Project("myproject"); - PropertiesConfiguration conf = new PropertiesConfiguration(); - conf.setProperty("KEY", "2"); - project.setConfiguration(conf); - - Date date = Periods.getDate(conf, "KEY", "2"); - - GregorianCalendar calendar = new GregorianCalendar(); - calendar.add(GregorianCalendar.MONTH, -2); - Date expectedDate = calendar.getTime(); - - assertThat(date.getMonth(), is(expectedDate.getMonth())); - } -} diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/runner/DeprecatedPurgePostJobTest.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/runner/DeprecatedPurgePostJobTest.java deleted file mode 100644 index 402fdff856a..00000000000 --- a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/runner/DeprecatedPurgePostJobTest.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2012 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar 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. - * - * Sonar 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 Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.dbcleaner.runner; - -import org.hamcrest.BaseMatcher; -import org.hamcrest.Description; -import org.junit.Test; -import org.sonar.api.database.model.Snapshot; -import org.sonar.api.resources.Project; -import org.sonar.jpa.test.AbstractDbUnitTestCase; -import org.sonar.plugins.dbcleaner.api.Purge; -import org.sonar.plugins.dbcleaner.api.PurgeContext; - -import javax.persistence.PersistenceException; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.argThat; -import static org.mockito.Mockito.*; - -public class DeprecatedPurgePostJobTest extends AbstractDbUnitTestCase { - - @Test - public void shouldExecutePurges() { - setupData("shared"); - final int currentSID = 400; - final int previousSID = 300; - Snapshot snapshot = getSession().getSingleResult(Snapshot.class, "id", currentSID); - - Purge purge1 = mock(Purge.class); - Purge purge2 = mock(Purge.class); - Purge[] purges = new Purge[]{purge1, purge2}; - - new DeprecatedPurgePostJob(getSession(), new Project("key"), snapshot, purges).purge(); - - verify(purge1).purge(argThat(new BaseMatcher() { - public boolean matches(Object o) { - PurgeContext context = (PurgeContext) o; - return context.getSnapshotId() == currentSID && context.getPreviousSnapshotId() == previousSID; - } - - public void describeTo(Description description) { - } - })); - } - - @Test - public void shouldExecutePurgesEvenIfSingleAnalysis() { - setupData("shared"); - final int currentSID = 1000; - Snapshot snapshot = getSession().getSingleResult(Snapshot.class, "id", currentSID); - - Purge purge1 = mock(Purge.class); - Purge purge2 = mock(Purge.class); - Purge[] purges = new Purge[]{purge1, purge2}; - - new DeprecatedPurgePostJob(getSession(), new Project("key"), snapshot, purges).purge(); - - verify(purge1).purge(argThat(new BaseMatcher() { - public boolean matches(Object o) { - PurgeContext context = (PurgeContext) o; - return context.getSnapshotId() == currentSID && context.getPreviousSnapshotId() == null; - } - - public void describeTo(Description description) { - } - })); - } - - @Test - public void shouldExecuteOnlyOnRootProjects() { - Project project = mock(Project.class); - when(project.isRoot()).thenReturn(true); - assertTrue(DeprecatedPurgePostJob.shouldExecuteOn(project)); - - when(project.isRoot()).thenReturn(false); - assertFalse(DeprecatedPurgePostJob.shouldExecuteOn(project)); - } - - /** - * See https://jira.codehaus.org/browse/SONAR-2961 - * Temporarily ignore MySQL deadlocks - */ - @Test - public void shouldIgnoreDeadlocks() { - Purge purge = mock(Purge.class); - doThrow(new PersistenceException()).when(purge).purge((PurgeContext) anyObject()); - - DeprecatedPurgePostJob runner = new DeprecatedPurgePostJob(getSession(), new Project(""), new Snapshot(), new Purge[]{purge}); - runner.purge();// must not raise any exceptions - - verify(purge).purge((PurgeContext) anyObject()); - } -} diff --git a/plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleanerTest/dbContent-result.xml b/plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleanerTest/dbContent-result.xml deleted file mode 100644 index 661d9daedd3..00000000000 --- a/plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleanerTest/dbContent-result.xml +++ /dev/null @@ -1,167 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleanerTest/dbContent.xml b/plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleanerTest/dbContent.xml deleted file mode 100644 index b7e8a1cfb0f..00000000000 --- a/plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleanerTest/dbContent.xml +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/runner/DeprecatedPurgePostJobTest/shared.xml b/plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/runner/DeprecatedPurgePostJobTest/shared.xml deleted file mode 100644 index 18860b7ab95..00000000000 --- a/plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/runner/DeprecatedPurgePostJobTest/shared.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java b/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java index 8837db3c6d7..f74d34fed79 100644 --- a/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java +++ b/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java @@ -33,6 +33,7 @@ import org.sonar.core.dashboard.*; import org.sonar.core.duplication.DuplicationMapper; import org.sonar.core.duplication.DuplicationUnitDto; import org.sonar.core.purge.PurgeMapper; +import org.sonar.core.purge.PurgeableSnapshotDto; import org.sonar.core.resource.*; import org.sonar.core.review.ReviewDto; import org.sonar.core.review.ReviewMapper; @@ -66,6 +67,7 @@ public class MyBatis implements BatchComponent, ServerComponent { loadAlias(conf, "Dashboard", DashboardDto.class); loadAlias(conf, "DuplicationUnit", DuplicationUnitDto.class); loadAlias(conf, "LoadedTemplate", LoadedTemplateDto.class); + loadAlias(conf, "PurgeableSnapshot", PurgeableSnapshotDto.class); loadAlias(conf, "Review", ReviewDto.class); loadAlias(conf, "Resource", ResourceDto.class); loadAlias(conf, "ResourceIndex", ResourceIndexDto.class); diff --git a/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java b/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java index 8bbe33b44b8..cd38614b5e7 100644 --- a/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java +++ b/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java @@ -20,6 +20,8 @@ package org.sonar.core.purge; import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.ResultContext; import org.apache.ibatis.session.ResultHandler; @@ -28,7 +30,9 @@ import org.sonar.core.persistence.BatchSession; import org.sonar.core.persistence.MyBatis; import org.sonar.core.resource.ResourceDao; +import java.util.Collections; import java.util.List; +import java.util.SortedSet; public class PurgeDao { private final MyBatis mybatis; @@ -84,6 +88,20 @@ public class PurgeDao { session.commit(); } + public List selectPurgeableSnapshots(long resourceId) { + SqlSession session = mybatis.openSession(ExecutorType.REUSE); + try { + PurgeMapper mapper = session.getMapper(PurgeMapper.class); + List result = Lists.newArrayList(); + result.addAll(mapper.selectPurgeableSnapshotsWithVersionEvent(resourceId)); + result.addAll(mapper.selectPurgeableSnapshotsWithoutVersionEvent(resourceId)); + Collections.sort(result);// sort by date + return result; + } finally { + MyBatis.closeQuietly(session); + } + } + public PurgeDao deleteProject(long rootProjectId) { final BatchSession session = mybatis.openBatchSession(); try { diff --git a/sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java b/sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java index 38cccfe0e60..31993b1896f 100644 --- a/sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java @@ -70,4 +70,8 @@ public interface PurgeMapper { void deleteResourceEvents(long resourceId); void closeResourceReviews(long resourceId); + + List selectPurgeableSnapshotsWithVersionEvent(long resourceId); + + List selectPurgeableSnapshotsWithoutVersionEvent(long resourceId); } diff --git a/sonar-core/src/main/java/org/sonar/core/purge/PurgeSnapshotQuery.java b/sonar-core/src/main/java/org/sonar/core/purge/PurgeSnapshotQuery.java index 95dadd2f03c..5c9c3eccdf0 100644 --- a/sonar-core/src/main/java/org/sonar/core/purge/PurgeSnapshotQuery.java +++ b/sonar-core/src/main/java/org/sonar/core/purge/PurgeSnapshotQuery.java @@ -31,6 +31,7 @@ public final class PurgeSnapshotQuery { private String[] status; private Boolean islast; private Boolean notPurged; + private Boolean withVersionEvent; private PurgeSnapshotQuery() { } @@ -119,4 +120,13 @@ public final class PurgeSnapshotQuery { this.resourceId = l; return this; } + + public Boolean getWithVersionEvent() { + return withVersionEvent; + } + + public PurgeSnapshotQuery setWithVersionEvent(Boolean withVersionEvent) { + this.withVersionEvent = withVersionEvent; + return this; + } } diff --git a/sonar-core/src/main/java/org/sonar/core/purge/PurgeableSnapshotDto.java b/sonar-core/src/main/java/org/sonar/core/purge/PurgeableSnapshotDto.java new file mode 100644 index 00000000000..5579bfa7c06 --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/purge/PurgeableSnapshotDto.java @@ -0,0 +1,93 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.core.purge; + +import org.apache.commons.lang.builder.ReflectionToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; + +import java.util.Date; + +public class PurgeableSnapshotDto implements Comparable { + private Date date; + private long snapshotId; + private boolean hasVersionEvent; + private boolean isLast; + + public Date getDate() { + return date; + } + + public long getSnapshotId() { + return snapshotId; + } + + public boolean hasVersionEvent() { + return hasVersionEvent; + } + + public boolean isLast() { + return isLast; + } + + public void setDate(Date date) { + this.date = date; + } + + public PurgeableSnapshotDto setSnapshotId(long snapshotId) { + this.snapshotId = snapshotId; + return this; + } + + public PurgeableSnapshotDto setHasVersionEvent(boolean hasVersionEvent) { + this.hasVersionEvent = hasVersionEvent; + return this; + } + + public PurgeableSnapshotDto setLast(boolean last) { + isLast = last; + return this; + } + + public int compareTo(PurgeableSnapshotDto other) { + return date.compareTo(other.date); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + PurgeableSnapshotDto that = (PurgeableSnapshotDto) o; + return snapshotId == that.snapshotId; + } + + @Override + public int hashCode() { + return (int)snapshotId; + } + + @Override + public String toString() { + return new ReflectionToStringBuilder(this, ToStringStyle.SIMPLE_STYLE).toString(); + } +} diff --git a/sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml b/sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml index 3f942d66c6b..e0a7f656c3d 100644 --- a/sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml @@ -4,41 +4,59 @@ + + + +